opencode-swarm 7.109.2 → 7.109.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/.opencode/skills/ci-failure-batching/SKILL.md +39 -0
  2. package/.opencode/skills/gate-attribution/SKILL.md +31 -0
  3. package/.opencode/skills/merge-queue-readiness/SKILL.md +37 -0
  4. package/.opencode/skills/skill-edit-validation/SKILL.md +29 -0
  5. package/.opencode/skills/worktree-retry-cleanup/SKILL.md +24 -0
  6. package/dist/cli/{config-doctor-q354tb2w.js → config-doctor-9vjyj9m3.js} +2 -2
  7. package/dist/cli/{curator-llm-factory-wqbm9mwr.js → curator-llm-factory-3hf9xpnd.js} +9 -9
  8. package/dist/cli/{curator-6p9tpprq.js → curator-zn1kmwmz.js} +9 -9
  9. package/dist/cli/{guardrail-explain-ynge4ww3.js → guardrail-explain-hjz1k6w0.js} +10 -10
  10. package/dist/cli/{guardrail-log-8mqqsssq.js → guardrail-log-5240bawg.js} +3 -3
  11. package/dist/cli/{hive-promoter-qh2rh8x2.js → hive-promoter-j81yj97d.js} +9 -9
  12. package/dist/cli/{index-h4c4rrwx.js → index-18690p15.js} +23 -2
  13. package/dist/cli/{index-fz1jgbvw.js → index-41fgssqr.js} +22 -2
  14. package/dist/cli/{index-wg0665ft.js → index-8f10r7ay.js} +2 -2
  15. package/dist/cli/{index-9qxntjtx.js → index-b15qbvph.js} +190 -41
  16. package/dist/cli/{index-wj4jeavn.js → index-d3txrx5q.js} +1 -1
  17. package/dist/cli/{index-5gnp8fyw.js → index-mtzjbaaa.js} +3 -3
  18. package/dist/cli/{index-3qwaydq1.js → index-nvmy7xmj.js} +11 -11
  19. package/dist/cli/{index-vx76tcxe.js → index-p5vm9gy9.js} +1 -1
  20. package/dist/cli/{index-cqbqynzp.js → index-y3nx3ss0.js} +710 -557
  21. package/dist/cli/{index-mmny81g1.js → index-y5z2qdvk.js} +1 -1
  22. package/dist/cli/{index-8a8b5wjf.js → index-zh3qh6m7.js} +2 -2
  23. package/dist/cli/{index-fm7xz1ne.js → index-zjh648z4.js} +81 -1
  24. package/dist/cli/index.js +9 -9
  25. package/dist/cli/{knowledge-escalator-6v7sjprx.js → knowledge-escalator-9ksrgq7h.js} +3 -3
  26. package/dist/cli/{knowledge-events-6n3x3he2.js → knowledge-events-ymysgtrr.js} +1 -1
  27. package/dist/cli/{knowledge-store-exkw6yb1.js → knowledge-store-562fefjy.js} +1 -1
  28. package/dist/cli/{knowledge-validator-exymfcb9.js → knowledge-validator-b9nvmzjc.js} +4 -2
  29. package/dist/cli/{schema-x17zmd03.js → schema-5vmb5dh8.js} +3 -1
  30. package/dist/cli/{skill-generator-mx9br4ty.js → skill-generator-mjfqvnn0.js} +15 -5
  31. package/dist/config/bundled-skills.d.ts +1 -1
  32. package/dist/config/schema.d.ts +12 -4
  33. package/dist/hooks/knowledge-types.d.ts +6 -0
  34. package/dist/hooks/knowledge-validator.d.ts +5 -0
  35. package/dist/hooks/skill-invalidator.d.ts +48 -0
  36. package/dist/index.js +217 -216
  37. package/dist/services/skill-generator.d.ts +47 -2
  38. package/dist/tools/knowledge-remove.d.ts +3 -8
  39. package/package.json +6 -1
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  readRecentEscalations
4
- } from "./index-5gnp8fyw.js";
4
+ } from "./index-mtzjbaaa.js";
5
5
  import {
6
6
  getGlobalEventBus
7
7
  } from "./index-c8s9a3zh.js";
@@ -10,7 +10,7 @@ import {
10
10
  readDoctorArtifact,
11
11
  removeStraySwarmDir,
12
12
  runConfigDoctor
13
- } from "./index-fm7xz1ne.js";
13
+ } from "./index-zjh648z4.js";
14
14
  import {
15
15
  MAX_TRANSIENT_RETRIES,
16
16
  PlanSchema,
@@ -85,6 +85,8 @@ import {
85
85
  AGENT_TOOL_MAP,
86
86
  ALL_SUBAGENT_NAMES,
87
87
  ExternalSkillsConfigSchema,
88
+ GATE_CONFIG_KNOWN_SECTION_KEYS,
89
+ GateConfigSchema,
88
90
  KnowledgeConfigSchema,
89
91
  ORCHESTRATOR_NAME,
90
92
  PluginConfigSchema,
@@ -94,7 +96,7 @@ import {
94
96
  getCanonicalAgentRole,
95
97
  resolveExternalSkillsConfig,
96
98
  stripKnownSwarmPrefix
97
- } from "./index-h4c4rrwx.js";
99
+ } from "./index-18690p15.js";
98
100
  import {
99
101
  DEFAULT_SKILL_MIN_CONFIDENCE,
100
102
  DEFAULT_SKILL_MIN_CONFIRMATIONS,
@@ -102,6 +104,8 @@ import {
102
104
  appendSkillChangelog,
103
105
  autoApplyProposals,
104
106
  evaluateSkillChange,
107
+ findSkillsBySourceKnowledgeId,
108
+ findStaleSkillsBySourceKnowledgeId,
105
109
  generateSkills,
106
110
  listSkills,
107
111
  parseDraftFrontmatter,
@@ -109,14 +113,15 @@ import {
109
113
  retireOrMarkStale,
110
114
  retireSkill,
111
115
  selectCandidateEntries
112
- } from "./index-9qxntjtx.js";
116
+ } from "./index-b15qbvph.js";
113
117
  import {
114
118
  effectiveRetrievalOutcomes,
115
119
  readKnowledgeCounterRollups,
116
120
  readKnowledgeEvents,
121
+ recordHiveKnowledgeEvent,
117
122
  recordKnowledgeEvent,
118
123
  resolveKnowledgeEventsPath
119
- } from "./index-mmny81g1.js";
124
+ } from "./index-y5z2qdvk.js";
120
125
  import {
121
126
  appendUnactionable,
122
127
  quarantineEntry,
@@ -126,7 +131,7 @@ import {
126
131
  validateActionability,
127
132
  validateActionableFields,
128
133
  validateLesson
129
- } from "./index-fz1jgbvw.js";
134
+ } from "./index-41fgssqr.js";
130
135
  import {
131
136
  appendKnowledge,
132
137
  appendRejectedLesson,
@@ -148,7 +153,7 @@ import {
148
153
  rewriteKnowledge,
149
154
  transactFile,
150
155
  transactKnowledge
151
- } from "./index-wg0665ft.js";
156
+ } from "./index-8f10r7ay.js";
152
157
  import {
153
158
  isLinked,
154
159
  readLinkPointer,
@@ -211,7 +216,7 @@ import {
211
216
 
212
217
  // src/state.ts
213
218
  import * as fs30 from "fs/promises";
214
- import * as path65 from "path";
219
+ import * as path66 from "path";
215
220
 
216
221
  // src/db/qa-gate-profile.ts
217
222
  import { createHash } from "crypto";
@@ -4856,6 +4861,62 @@ function sanitizeExternalSkillsConfig(raw) {
4856
4861
  delete cleaned.external_skills;
4857
4862
  return cleaned;
4858
4863
  }
4864
+ function sanitizeGatesConfig(raw) {
4865
+ if (!("gates" in raw) || raw.gates === undefined) {
4866
+ return raw;
4867
+ }
4868
+ if (typeof raw.gates !== "object" || raw.gates === null || Array.isArray(raw.gates)) {
4869
+ console.warn("[opencode-swarm] gates config validation failed: expected an object. Quality gates will use defaults; other config sections remain active.");
4870
+ const cleaned2 = { ...raw };
4871
+ delete cleaned2.gates;
4872
+ return cleaned2;
4873
+ }
4874
+ const gateSchemas = GateConfigSchema.shape;
4875
+ const cleanedGates = { ...raw.gates };
4876
+ for (const [key, value] of Object.entries(cleanedGates)) {
4877
+ const schema = gateSchemas[key];
4878
+ if (!schema) {
4879
+ console.warn(`[opencode-swarm] Unknown gates config section "gates.${key}" ignored. Other config sections remain active.`);
4880
+ delete cleanedGates[key];
4881
+ continue;
4882
+ }
4883
+ const knownFields = GATE_CONFIG_KNOWN_SECTION_KEYS[key];
4884
+ let sectionValue = value;
4885
+ if (knownFields && typeof value === "object" && value !== null && !Array.isArray(value)) {
4886
+ const cleanedSection = { ...value };
4887
+ const knownFieldSet = new Set(knownFields);
4888
+ for (const fieldName of Object.keys(cleanedSection)) {
4889
+ if (!knownFieldSet.has(fieldName)) {
4890
+ console.warn(`[opencode-swarm] Unknown gates config key "gates.${key}.${fieldName}" ignored. Other config sections remain active.`);
4891
+ delete cleanedSection[fieldName];
4892
+ }
4893
+ }
4894
+ sectionValue = cleanedSection;
4895
+ cleanedGates[key] = cleanedSection;
4896
+ }
4897
+ const sectionResult = schema.safeParse(sectionValue);
4898
+ if (!sectionResult.success) {
4899
+ console.warn(`[opencode-swarm] gates.${key} config validation failed; that gate section will use defaults and other config sections remain active:`);
4900
+ console.warn(sectionResult.error.format());
4901
+ delete cleanedGates[key];
4902
+ }
4903
+ }
4904
+ const gatesResult = GateConfigSchema.safeParse(cleanedGates);
4905
+ if (gatesResult.success) {
4906
+ return {
4907
+ ...raw,
4908
+ gates: gatesResult.data
4909
+ };
4910
+ }
4911
+ console.warn("[opencode-swarm] gates config validation failed after section cleanup; quality gates will use defaults and other config sections remain active:");
4912
+ console.warn(gatesResult.error.format());
4913
+ const cleaned = { ...raw };
4914
+ delete cleaned.gates;
4915
+ return cleaned;
4916
+ }
4917
+ function sanitizeSectionConfigs(raw) {
4918
+ return sanitizeGatesConfig(sanitizeExternalSkillsConfig(raw));
4919
+ }
4859
4920
  function rawFullAutoLocked(raw) {
4860
4921
  if (!raw || typeof raw !== "object")
4861
4922
  return false;
@@ -4886,11 +4947,11 @@ function loadPluginConfig(directory) {
4886
4947
  };
4887
4948
  }
4888
4949
  mergedRaw = migratePresetsConfig(mergedRaw);
4889
- mergedRaw = sanitizeExternalSkillsConfig(mergedRaw);
4950
+ mergedRaw = sanitizeSectionConfigs(mergedRaw);
4890
4951
  const result = PluginConfigSchema.safeParse(mergedRaw);
4891
4952
  if (!result.success) {
4892
4953
  if (rawUserConfig) {
4893
- const userParseResult = PluginConfigSchema.safeParse(sanitizeExternalSkillsConfig(rawUserConfig ?? {}));
4954
+ const userParseResult = PluginConfigSchema.safeParse(sanitizeSectionConfigs(rawUserConfig ?? {}));
4894
4955
  if (userParseResult.success) {
4895
4956
  console.warn("[opencode-swarm] Project config ignored due to validation errors. Using user config.");
4896
4957
  return userParseResult.data;
@@ -4958,7 +5019,12 @@ var BUNDLED_PROJECT_SKILLS = [
4958
5019
  "writing-tests",
4959
5020
  "running-tests",
4960
5021
  "engineering-conventions",
4961
- "commit-pr"
5022
+ "commit-pr",
5023
+ "worktree-retry-cleanup",
5024
+ "skill-edit-validation",
5025
+ "merge-queue-readiness",
5026
+ "gate-attribution",
5027
+ "ci-failure-batching"
4962
5028
  ];
4963
5029
  var MAX_SKILL_FILES = 64;
4964
5030
  var MAX_SKILL_BYTES = 512000;
@@ -6484,7 +6550,7 @@ async function handleClarifyCommand(_directory, args) {
6484
6550
  import * as child_process2 from "child_process";
6485
6551
  import * as fsSync from "fs";
6486
6552
  import { promises as fs9 } from "fs";
6487
- import path27 from "path";
6553
+ import path28 from "path";
6488
6554
 
6489
6555
  // src/hooks/curator-postmortem.ts
6490
6556
  import { existsSync as existsSync7, readdirSync, readFileSync as readFileSync4 } from "fs";
@@ -7199,15 +7265,15 @@ var _internals7 = {
7199
7265
  executePostMortemActions,
7200
7266
  repairPostMortemActions,
7201
7267
  loadDefaultKnowledgeConfig: async () => {
7202
- const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-x17zmd03.js");
7268
+ const { KnowledgeConfigSchema: KnowledgeConfigSchema2 } = await import("./schema-5vmb5dh8.js");
7203
7269
  return KnowledgeConfigSchema2.parse({});
7204
7270
  },
7205
7271
  applyCuratorKnowledgeUpdates: async (directory, recommendations, knowledgeConfig) => {
7206
- const { applyCuratorKnowledgeUpdates } = await import("./curator-6p9tpprq.js");
7272
+ const { applyCuratorKnowledgeUpdates } = await import("./curator-zn1kmwmz.js");
7207
7273
  return applyCuratorKnowledgeUpdates(directory, recommendations, knowledgeConfig);
7208
7274
  },
7209
7275
  checkHivePromotions: async (entries, knowledgeConfig) => {
7210
- const { checkHivePromotions } = await import("./hive-promoter-qh2rh8x2.js");
7276
+ const { checkHivePromotions } = await import("./hive-promoter-j81yj97d.js");
7211
7277
  return checkHivePromotions(entries, knowledgeConfig);
7212
7278
  },
7213
7279
  applyProposalTriage: async (directory, triage) => {
@@ -7216,7 +7282,7 @@ var _internals7 = {
7216
7282
  activateProposal,
7217
7283
  listSkills: listSkills2,
7218
7284
  sanitizeSlug
7219
- } = await import("./skill-generator-mx9br4ty.js");
7285
+ } = await import("./skill-generator-mjfqvnn0.js");
7220
7286
  const result = {
7221
7287
  approved: [],
7222
7288
  rejected: [],
@@ -7233,7 +7299,8 @@ var _internals7 = {
7233
7299
  if (item.action === "apply") {
7234
7300
  const activation = await activateProposal(directory, slug, false, {
7235
7301
  evaluate: true,
7236
- operation: "post_mortem_queue_triage"
7302
+ operation: "post_mortem_queue_triage",
7303
+ confirmUnevaluated: true
7237
7304
  });
7238
7305
  if (activation.activated) {
7239
7306
  result.approved.push(slug);
@@ -7264,12 +7331,12 @@ var _internals7 = {
7264
7331
  };
7265
7332
 
7266
7333
  // src/hooks/hive-promoter.ts
7267
- import path16 from "path";
7334
+ import path17 from "path";
7268
7335
 
7269
7336
  // src/hooks/curator.ts
7270
7337
  import { randomUUID as randomUUID5 } from "crypto";
7271
7338
  import * as fs5 from "fs";
7272
- import * as path15 from "path";
7339
+ import * as path16 from "path";
7273
7340
 
7274
7341
  // src/services/learning-metrics.ts
7275
7342
  var SEVEN_DAYS_MS = 7 * 24 * 60 * 60 * 1000;
@@ -8087,10 +8154,69 @@ var _internals8 = {
8087
8154
  // src/hooks/curator.ts
8088
8155
  init_logger();
8089
8156
 
8157
+ // src/hooks/skill-invalidator.ts
8158
+ import * as path14 from "path";
8159
+ init_logger();
8160
+ async function writeArchiveTombstoneAndInvalidateSkills(ctx) {
8161
+ const label = ctx.sourceLabel ?? "skill-invalidator";
8162
+ if (!ctx.skipTombstone) {
8163
+ const tombstone = {
8164
+ type: "archived",
8165
+ entry_id: ctx.entryId,
8166
+ tier: ctx.tier,
8167
+ actor: ctx.actor,
8168
+ reason: ctx.reason,
8169
+ mode: ctx.mode,
8170
+ evidence: ctx.evidence,
8171
+ previous_status: ctx.previousStatus
8172
+ };
8173
+ if (ctx.tier === "hive") {
8174
+ await recordHiveKnowledgeEvent(tombstone);
8175
+ } else {
8176
+ await recordKnowledgeEvent(ctx.directory, tombstone);
8177
+ }
8178
+ }
8179
+ const allArchivedIds = ctx.precomputedArchivedIds ? new Set(ctx.precomputedArchivedIds) : await getArchivedKnowledgeIds(ctx.directory);
8180
+ allArchivedIds.add(ctx.entryId);
8181
+ queueMicrotask(async () => {
8182
+ try {
8183
+ const affectedSkillDirs = await findSkillsBySourceKnowledgeId(ctx.directory, ctx.entryId);
8184
+ const staleSkillDirs = await findStaleSkillsBySourceKnowledgeId(ctx.directory, allArchivedIds);
8185
+ const allSkillDirs = new Set([...affectedSkillDirs, ...staleSkillDirs]);
8186
+ if (allSkillDirs.size === 0)
8187
+ return;
8188
+ const slugSet = new Set;
8189
+ let retiredCount = 0;
8190
+ let staleCount = 0;
8191
+ for (const skillDir of allSkillDirs) {
8192
+ const slug = path14.basename(skillDir);
8193
+ if (slugSet.has(slug))
8194
+ continue;
8195
+ slugSet.add(slug);
8196
+ const result = await retireOrMarkStale(ctx.directory, skillDir, allArchivedIds);
8197
+ if (result.action === "retire")
8198
+ retiredCount++;
8199
+ else
8200
+ staleCount++;
8201
+ }
8202
+ const batchEvent = {
8203
+ type: "skill-stale-batch",
8204
+ skillIds: Array.from(slugSet),
8205
+ archivedIds: Array.from(allArchivedIds),
8206
+ retiredCount,
8207
+ staleCount
8208
+ };
8209
+ await recordKnowledgeEvent(ctx.directory, batchEvent);
8210
+ } catch (err) {
8211
+ warn(`[${label}] post-archive skill invalidation failed for entry '${ctx.entryId}': ${err instanceof Error ? err.message : String(err)}`);
8212
+ }
8213
+ });
8214
+ }
8215
+
8090
8216
  // src/hooks/skill-usage-log.ts
8091
8217
  import * as crypto2 from "crypto";
8092
8218
  import * as fs4 from "fs";
8093
- import * as path14 from "path";
8219
+ import * as path15 from "path";
8094
8220
  function resolveLogPath(directory) {
8095
8221
  return validateSwarmPath(directory, "skill-usage.jsonl");
8096
8222
  }
@@ -8189,7 +8315,7 @@ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
8189
8315
  if (processedEntryIds.length === 0)
8190
8316
  return;
8191
8317
  const resolved = resolveLogPath(directory);
8192
- const dir = path14.dirname(resolved);
8318
+ const dir = path15.dirname(resolved);
8193
8319
  if (!_internals9.existsSync(dir)) {
8194
8320
  _internals9.mkdirSync(dir, { recursive: true });
8195
8321
  }
@@ -8234,7 +8360,7 @@ function appendSkillUsageEntry(directory, entry) {
8234
8360
  throw new Error("sessionID is required and must be a non-empty string");
8235
8361
  }
8236
8362
  const resolved = validateSwarmPath(directory, "skill-usage.jsonl");
8237
- const dir = path14.dirname(resolved);
8363
+ const dir = path15.dirname(resolved);
8238
8364
  if (!_internals9.existsSync(dir)) {
8239
8365
  _internals9.mkdirSync(dir, { recursive: true });
8240
8366
  }
@@ -8410,8 +8536,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
8410
8536
  }
8411
8537
  if (entries.length === 0) {
8412
8538
  if (preservedMarkers.length > 0) {
8413
- const dir2 = path14.dirname(resolved);
8414
- const tmpPath2 = path14.join(dir2, `skill-usage-${Date.now()}.tmp`);
8539
+ const dir2 = path15.dirname(resolved);
8540
+ const tmpPath2 = path15.join(dir2, `skill-usage-${Date.now()}.tmp`);
8415
8541
  const content2 = preservedMarkers.join(`
8416
8542
  `).concat(preservedMarkers.length > 0 ? `
8417
8543
  ` : "");
@@ -8453,8 +8579,8 @@ function pruneSkillUsageLog(directory, maxEntriesPerSkill = 500) {
8453
8579
  if (pruned === 0) {
8454
8580
  return { pruned: 0, remaining: entries.length };
8455
8581
  }
8456
- const dir = path14.dirname(resolved);
8457
- const tmpPath = path14.join(dir, `skill-usage-${Date.now()}.tmp`);
8582
+ const dir = path15.dirname(resolved);
8583
+ const tmpPath = path15.join(dir, `skill-usage-${Date.now()}.tmp`);
8458
8584
  const entryLines = surviving.map((e) => JSON.stringify(e));
8459
8585
  const allLines = [...entryLines, ...preservedMarkers];
8460
8586
  const content = allLines.join(`
@@ -8483,9 +8609,9 @@ async function resolveSourceKnowledgeIds(directory, skillPath) {
8483
8609
  if (/\.\.[/\\]/.test(cleanPath)) {
8484
8610
  return [];
8485
8611
  }
8486
- const absolute = path14.normalize(path14.isAbsolute(cleanPath) ? cleanPath : path14.resolve(directory, cleanPath));
8487
- const baseDir = path14.normalize(path14.resolve(directory));
8488
- const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir + path14.sep).toLowerCase()) : absolute.startsWith(baseDir + path14.sep);
8612
+ const absolute = path15.normalize(path15.isAbsolute(cleanPath) ? cleanPath : path15.resolve(directory, cleanPath));
8613
+ const baseDir = path15.normalize(path15.resolve(directory));
8614
+ const isContained = process.platform === "win32" ? absolute.toLowerCase().startsWith((baseDir + path15.sep).toLowerCase()) : absolute.startsWith(baseDir + path15.sep);
8489
8615
  if (!isContained) {
8490
8616
  return [];
8491
8617
  }
@@ -8679,7 +8805,7 @@ async function autoRetireSkills(directory, _curatorKnowledgePath, excludeSlugs)
8679
8805
  }
8680
8806
  }
8681
8807
  if (archivedSourceMatched) {
8682
- const result = await _internals10.retireOrMarkStale(directory, path15.dirname(active.path), allArchivedIds);
8808
+ const result = await _internals10.retireOrMarkStale(directory, path16.dirname(active.path), allArchivedIds);
8683
8809
  if (result.action === "retire") {
8684
8810
  observations.push(`Skill '${active.slug}' auto-retired: all source knowledge entries archived`);
8685
8811
  warn(`[curator] ${observations[observations.length - 1]}`);
@@ -8876,11 +9002,11 @@ function arrayOfStrings(v) {
8876
9002
  }
8877
9003
  function readLatestPostMortemDigest(directory) {
8878
9004
  try {
8879
- const swarmDir = path15.join(directory, ".swarm");
9005
+ const swarmDir = path16.join(directory, ".swarm");
8880
9006
  if (!fs5.existsSync(swarmDir))
8881
9007
  return null;
8882
9008
  const candidates = fs5.readdirSync(swarmDir).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name)).map((name) => {
8883
- const filePath = path15.join(swarmDir, name);
9009
+ const filePath = path16.join(swarmDir, name);
8884
9010
  return { name, filePath, mtimeMs: fs5.statSync(filePath).mtimeMs };
8885
9011
  }).sort((a, b) => b.mtimeMs - a.mtimeMs);
8886
9012
  const latest = candidates[0];
@@ -8923,7 +9049,7 @@ async function readCuratorSummary(directory) {
8923
9049
  }
8924
9050
  async function writeCuratorSummary(directory, summary) {
8925
9051
  const resolvedPath = validateSwarmPath(directory, "curator-summary.json");
8926
- fs5.mkdirSync(path15.dirname(resolvedPath), { recursive: true });
9052
+ fs5.mkdirSync(path16.dirname(resolvedPath), { recursive: true });
8927
9053
  await bunWrite(resolvedPath, JSON.stringify(summary, null, 2));
8928
9054
  }
8929
9055
  function normalizeAgentName(name) {
@@ -9363,15 +9489,15 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
9363
9489
  await _internals10.writeCuratorSummary(directory, updatedSummary);
9364
9490
  if (knowledgeApplicationFindings.length > 0) {
9365
9491
  try {
9366
- const evidenceDir = path15.join(directory, ".swarm", "evidence", String(phase));
9492
+ const evidenceDir = path16.join(directory, ".swarm", "evidence", String(phase));
9367
9493
  fs5.mkdirSync(evidenceDir, { recursive: true });
9368
- const findingsPath = path15.join(evidenceDir, "curator-findings.json");
9494
+ const findingsPath = path16.join(evidenceDir, "curator-findings.json");
9369
9495
  await bunWrite(findingsPath, JSON.stringify({ findings: knowledgeApplicationFindings }, null, 2));
9370
9496
  } catch (err) {
9371
9497
  warn(`[curator] failed to persist application findings: ${err instanceof Error ? err.message : String(err)}`);
9372
9498
  }
9373
9499
  }
9374
- const eventsPath = path15.join(directory, ".swarm", "events.jsonl");
9500
+ const eventsPath = path16.join(directory, ".swarm", "events.jsonl");
9375
9501
  for (const obs of complianceObservations) {
9376
9502
  await appendKnowledge(eventsPath, {
9377
9503
  type: "curator_compliance",
@@ -9384,7 +9510,7 @@ async function runCuratorPhase(directory, phase, agentsDispatched, config, knowl
9384
9510
  }
9385
9511
  if (config.skill_generation_enabled === true && skillCandidates.length > 0) {
9386
9512
  try {
9387
- const skillModule = await import("./skill-generator-mx9br4ty.js");
9513
+ const skillModule = await import("./skill-generator-mjfqvnn0.js");
9388
9514
  for (const cand of skillCandidates) {
9389
9515
  if (cand.confidence < (config.min_skill_confidence ?? DEFAULT_SKILL_MIN_CONFIDENCE)) {
9390
9516
  continue;
@@ -9552,10 +9678,12 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9552
9678
  const knowledgePath = resolveSwarmKnowledgePath(directory);
9553
9679
  const appliedIds = new Set;
9554
9680
  const foundIds = new Set;
9681
+ const archivedPrevStatus = new Map;
9555
9682
  const contradictedEntries = [];
9556
9683
  await transactKnowledge(knowledgePath, (entries) => {
9557
9684
  appliedIds.clear();
9558
9685
  foundIds.clear();
9686
+ archivedPrevStatus.clear();
9559
9687
  contradictedEntries.length = 0;
9560
9688
  let txApplied = 0;
9561
9689
  let modified = false;
@@ -9581,6 +9709,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9581
9709
  return entry;
9582
9710
  }
9583
9711
  appliedIds.add(entry.id);
9712
+ archivedPrevStatus.set(entry.id, entry.status);
9584
9713
  txApplied++;
9585
9714
  modified = true;
9586
9715
  return {
@@ -9654,7 +9783,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9654
9783
  } catch {}
9655
9784
  }
9656
9785
  if (contradictedEntries.length > 0 && knowledgeConfig.contradiction_threshold_action === "quarantine") {
9657
- const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-6v7sjprx.js");
9786
+ const { maybeQuarantineOnContradiction } = await import("./knowledge-escalator-9ksrgq7h.js");
9658
9787
  for (const { id } of contradictedEntries) {
9659
9788
  try {
9660
9789
  await maybeQuarantineOnContradiction(directory, id, knowledgeConfig.contradiction_quarantine_threshold, knowledgeConfig.contradiction_quarantine_window_days);
@@ -9669,6 +9798,25 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9669
9798
  skipped++;
9670
9799
  }
9671
9800
  }
9801
+ const archivedRecs = validRecommendations.filter((r) => r.action === "archive" && r.entry_id && appliedIds.has(r.entry_id));
9802
+ const precomputedArchivedIds = archivedRecs.length > 0 ? await getArchivedKnowledgeIds(directory) : undefined;
9803
+ for (const rec of archivedRecs) {
9804
+ try {
9805
+ await writeArchiveTombstoneAndInvalidateSkills({
9806
+ directory,
9807
+ entryId: rec.entry_id,
9808
+ tier: "swarm",
9809
+ actor: "curator",
9810
+ reason: rec.reason ?? "curator archive recommendation",
9811
+ mode: "archive",
9812
+ previousStatus: archivedPrevStatus.get(rec.entry_id),
9813
+ sourceLabel: "curator",
9814
+ precomputedArchivedIds
9815
+ });
9816
+ } catch (err) {
9817
+ warn(`[curator] archive invalidation for entry '${rec.entry_id}' failed: ${err instanceof Error ? err.message : String(err)}`);
9818
+ }
9819
+ }
9672
9820
  const currentEntries = await readKnowledge(knowledgePath);
9673
9821
  const currentLessons = currentEntries.map((e) => e.lesson);
9674
9822
  for (const rec of validRecommendations) {
@@ -9718,7 +9866,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
9718
9866
  created_at: now,
9719
9867
  updated_at: now,
9720
9868
  auto_generated: true,
9721
- project_name: path15.basename(directory)
9869
+ project_name: path16.basename(directory)
9722
9870
  };
9723
9871
  if (!validateActionability(newEntry).actionable) {
9724
9872
  try {
@@ -9964,7 +10112,7 @@ async function promoteToHive(directory, lesson, category) {
9964
10112
  schema_version: 1,
9965
10113
  created_at: new Date().toISOString(),
9966
10114
  updated_at: new Date().toISOString(),
9967
- source_project: path16.basename(directory) || "unknown",
10115
+ source_project: path17.basename(directory) || "unknown",
9968
10116
  encounter_score: 1
9969
10117
  };
9970
10118
  await appendKnowledge(resolveHiveKnowledgePath(), newHiveEntry);
@@ -10018,7 +10166,7 @@ async function promoteFromSwarm(directory, lessonId) {
10018
10166
  import { createHash as createHash4 } from "crypto";
10019
10167
  import { existsSync as existsSync13 } from "fs";
10020
10168
  import { appendFile as appendFile2, mkdir as mkdir6, readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
10021
- import * as path21 from "path";
10169
+ import * as path22 from "path";
10022
10170
 
10023
10171
  // src/services/synonym-map.ts
10024
10172
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
@@ -10030,7 +10178,7 @@ import {
10030
10178
  unlink,
10031
10179
  writeFile as writeFile6
10032
10180
  } from "fs/promises";
10033
- import * as path17 from "path";
10181
+ import * as path18 from "path";
10034
10182
  var SYNONYM_MAP_FILENAME = "synonym-map.json";
10035
10183
  var MAX_TOKEN_LENGTH = 64;
10036
10184
  var DEFAULT_MAX_PAIRS = 500;
@@ -10185,7 +10333,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
10185
10333
  }
10186
10334
  }
10187
10335
  async function writeSynonymMapAtomic(filePath, map) {
10188
- await mkdir5(path17.dirname(filePath), { recursive: true });
10336
+ await mkdir5(path18.dirname(filePath), { recursive: true });
10189
10337
  const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
10190
10338
  try {
10191
10339
  await writeFile6(tmp, JSON.stringify(map, null, 2), "utf-8");
@@ -10198,7 +10346,7 @@ async function writeSynonymMapAtomic(filePath, map) {
10198
10346
  }
10199
10347
  async function rebuildSynonymMap(directory, entries, maxPairs = DEFAULT_MAX_PAIRS) {
10200
10348
  const filePath = resolveSynonymMapPath(directory);
10201
- const dir = path17.dirname(filePath);
10349
+ const dir = path18.dirname(filePath);
10202
10350
  await mkdir5(dir, { recursive: true });
10203
10351
  let release = null;
10204
10352
  try {
@@ -10258,17 +10406,17 @@ function reinforceSwarmKnowledgeEntry(entry, confirmation) {
10258
10406
  // src/hooks/micro-reflector.ts
10259
10407
  import { existsSync as existsSync12 } from "fs";
10260
10408
  import { readFile as readFile7, writeFile as writeFile7 } from "fs/promises";
10261
- import * as path20 from "path";
10409
+ import * as path21 from "path";
10262
10410
  init_logger();
10263
10411
 
10264
10412
  // src/hooks/skill-propagation-gate.ts
10265
10413
  import * as fs7 from "fs";
10266
- import * as path19 from "path";
10414
+ import * as path20 from "path";
10267
10415
  init_logger();
10268
10416
 
10269
10417
  // src/hooks/skill-scoring.ts
10270
10418
  import * as fs6 from "fs";
10271
- import * as path18 from "path";
10419
+ import * as path19 from "path";
10272
10420
  var FREQUENCY_CAP = 10;
10273
10421
  var FREQUENCY_WEIGHT = 0.3;
10274
10422
  var COMPLIANCE_WEIGHT = 0.3;
@@ -10296,10 +10444,10 @@ var _internals11 = {
10296
10444
  computeTriggerMatchBoost: null
10297
10445
  };
10298
10446
  function extractSkillName(skillPath) {
10299
- const base = path18.basename(skillPath, path18.extname(skillPath));
10447
+ const base = path19.basename(skillPath, path19.extname(skillPath));
10300
10448
  if (base !== "SKILL")
10301
10449
  return base;
10302
- const parent = path18.basename(path18.dirname(skillPath));
10450
+ const parent = path19.basename(path19.dirname(skillPath));
10303
10451
  return parent;
10304
10452
  }
10305
10453
  function stripQuotes(value) {
@@ -10457,12 +10605,12 @@ function readSkillMetadata(skillPath, directory) {
10457
10605
  const normalizedPath = skillPath.replace(/^file:/, "").replace(/\\/g, "/");
10458
10606
  const fallback = parseSkillFrontmatter("", normalizedPath);
10459
10607
  try {
10460
- if (path18.isAbsolute(normalizedPath) || normalizedPath.split("/").includes("..")) {
10608
+ if (path19.isAbsolute(normalizedPath) || normalizedPath.split("/").includes("..")) {
10461
10609
  return fallback;
10462
10610
  }
10463
- const root = path18.resolve(directory);
10464
- const absolutePath = path18.resolve(directory, normalizedPath);
10465
- if (absolutePath !== root && !absolutePath.startsWith(root + path18.sep)) {
10611
+ const root = path19.resolve(directory);
10612
+ const absolutePath = path19.resolve(directory, normalizedPath);
10613
+ if (absolutePath !== root && !absolutePath.startsWith(root + path19.sep)) {
10466
10614
  return fallback;
10467
10615
  }
10468
10616
  const content = readFilePrefix(absolutePath);
@@ -10600,7 +10748,7 @@ function getSkillStats(skillPath, directory) {
10600
10748
  };
10601
10749
  }
10602
10750
  function formatSkillIndexWithContext(skills, directory) {
10603
- const usageLogPath = path18.join(directory, ".swarm", "skill-usage.jsonl");
10751
+ const usageLogPath = path19.join(directory, ".swarm", "skill-usage.jsonl");
10604
10752
  let hasHistory = false;
10605
10753
  try {
10606
10754
  const stat4 = fs6.statSync(usageLogPath);
@@ -10734,7 +10882,7 @@ function parseYamlValue(value) {
10734
10882
  return trimmed;
10735
10883
  }
10736
10884
  function loadRoutingSkills(directory, targetAgent) {
10737
- const routingPath = path19.join(directory, ".opencode", "skill-routing.yaml");
10885
+ const routingPath = path20.join(directory, ".opencode", "skill-routing.yaml");
10738
10886
  if (!_internals12.existsSync(routingPath))
10739
10887
  return [];
10740
10888
  try {
@@ -10794,7 +10942,7 @@ var _internals12 = {
10794
10942
  function discoverAvailableSkills(directory) {
10795
10943
  const results = [];
10796
10944
  for (const root of SKILL_SEARCH_ROOTS) {
10797
- const rootPath = path19.join(directory, root);
10945
+ const rootPath = path20.join(directory, root);
10798
10946
  if (!_internals12.existsSync(rootPath))
10799
10947
  continue;
10800
10948
  let entries;
@@ -10806,13 +10954,13 @@ function discoverAvailableSkills(directory) {
10806
10954
  for (const entry of entries) {
10807
10955
  if (entry.startsWith("."))
10808
10956
  continue;
10809
- const skillDir = path19.join(rootPath, entry);
10810
- if (_internals12.existsSync(path19.join(skillDir, "retired.marker")) || _internals12.existsSync(path19.join(skillDir, "stale.marker")))
10957
+ const skillDir = path20.join(rootPath, entry);
10958
+ if (_internals12.existsSync(path20.join(skillDir, "retired.marker")) || _internals12.existsSync(path20.join(skillDir, "stale.marker")))
10811
10959
  continue;
10812
- const skillFile = path19.join(skillDir, "SKILL.md");
10960
+ const skillFile = path20.join(skillDir, "SKILL.md");
10813
10961
  try {
10814
10962
  if (_internals12.statSync(skillDir).isDirectory() && _internals12.existsSync(skillFile)) {
10815
- results.push(path19.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
10963
+ results.push(path20.join(root, entry, "SKILL.md").replace(/\\/g, "/"));
10816
10964
  }
10817
10965
  } catch (err) {
10818
10966
  warn(`[skill-propagation-gate] failed to stat skill directory ${entry}: ${err instanceof Error ? err.message : String(err)}`);
@@ -10881,9 +11029,9 @@ function extractSkillsFieldFromPrompt(prompt) {
10881
11029
  return "";
10882
11030
  }
10883
11031
  function writeWarnEvent(directory, record) {
10884
- const filePath = path19.join(directory, ".swarm", "events.jsonl");
11032
+ const filePath = path20.join(directory, ".swarm", "events.jsonl");
10885
11033
  try {
10886
- const dir = path19.dirname(filePath);
11034
+ const dir = path20.dirname(filePath);
10887
11035
  if (!_internals12.existsSync(dir)) {
10888
11036
  _internals12.mkdirSync(dir, { recursive: true });
10889
11037
  }
@@ -11012,8 +11160,8 @@ async function skillPropagationGateBefore(directory, input, config) {
11012
11160
  if (routingPaths.length > 0) {
11013
11161
  const existingPaths = new Set(scored.map((s) => s.skillPath));
11014
11162
  for (const routingPath of routingPaths) {
11015
- const routedSkillDir = path19.dirname(path19.join(directory, routingPath));
11016
- if (_internals12.existsSync(path19.join(routedSkillDir, "retired.marker")) || _internals12.existsSync(path19.join(routedSkillDir, "stale.marker")))
11163
+ const routedSkillDir = path20.dirname(path20.join(directory, routingPath));
11164
+ if (_internals12.existsSync(path20.join(routedSkillDir, "retired.marker")) || _internals12.existsSync(path20.join(routedSkillDir, "stale.marker")))
11017
11165
  continue;
11018
11166
  if (!existingPaths.has(routingPath)) {
11019
11167
  scored.push({
@@ -11032,8 +11180,8 @@ async function skillPropagationGateBefore(directory, input, config) {
11032
11180
  let skillsForIndex = availableSkills;
11033
11181
  if (scoringSkipped) {
11034
11182
  skillsForIndex = [...availableSkills].sort((a, b) => {
11035
- const nameA = path19.basename(path19.dirname(a));
11036
- const nameB = path19.basename(path19.dirname(b));
11183
+ const nameA = path20.basename(path20.dirname(a));
11184
+ const nameB = path20.basename(path20.dirname(b));
11037
11185
  return nameA.localeCompare(nameB);
11038
11186
  });
11039
11187
  } else if (typeof scored !== "undefined" && scored.length > 0) {
@@ -11041,7 +11189,7 @@ async function skillPropagationGateBefore(directory, input, config) {
11041
11189
  }
11042
11190
  const formattedIndex = _internals12.formatSkillIndexWithContext(skillsForIndex, directory);
11043
11191
  if (formattedIndex.length > 0) {
11044
- const contextPath = path19.join(directory, ".swarm", "context.md");
11192
+ const contextPath = path20.join(directory, ".swarm", "context.md");
11045
11193
  let existingContent = "";
11046
11194
  if (_internals12.existsSync(contextPath)) {
11047
11195
  existingContent = _internals12.readFileSync(contextPath, "utf-8");
@@ -11063,7 +11211,7 @@ ${newSection}`;
11063
11211
  updatedContent = existingContent + newSection;
11064
11212
  }
11065
11213
  }
11066
- const swarmDir = path19.dirname(contextPath);
11214
+ const swarmDir = path20.dirname(contextPath);
11067
11215
  if (!_internals12.existsSync(swarmDir)) {
11068
11216
  _internals12.mkdirSync(swarmDir, { recursive: true });
11069
11217
  }
@@ -11289,7 +11437,7 @@ function resolveInsightCandidatesPath(directory) {
11289
11437
  }
11290
11438
  async function readTaskTrajectory(directory, taskId) {
11291
11439
  try {
11292
- const rel = path20.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
11440
+ const rel = path21.join("evidence", sanitizeTaskId(taskId), "trajectory.jsonl");
11293
11441
  const filePath = validateSwarmPath(directory, rel);
11294
11442
  if (!existsSync12(filePath))
11295
11443
  return [];
@@ -11719,8 +11867,8 @@ RETRY: your last output was missing ${result.missing.join("; ")}; produce valid
11719
11867
  }
11720
11868
  async function appendCuratorSkippedEvent(directory, record) {
11721
11869
  try {
11722
- const filePath = path21.join(directory, ".swarm", "events.jsonl");
11723
- await mkdir6(path21.dirname(filePath), { recursive: true });
11870
+ const filePath = path22.join(directory, ".swarm", "events.jsonl");
11871
+ await mkdir6(path22.dirname(filePath), { recursive: true });
11724
11872
  await appendFile2(filePath, `${JSON.stringify({
11725
11873
  timestamp: new Date().toISOString(),
11726
11874
  event: "curator_skipped",
@@ -12287,7 +12435,7 @@ var _internals14 = {
12287
12435
 
12288
12436
  // src/services/session-reflection.ts
12289
12437
  import { promises as fs8 } from "fs";
12290
- import * as path22 from "path";
12438
+ import * as path23 from "path";
12291
12439
 
12292
12440
  // src/hooks/abort-utils.ts
12293
12441
  function isAbortError(err) {
@@ -12448,11 +12596,11 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
12448
12596
  const lessons = [];
12449
12597
  const taxonomy = {};
12450
12598
  try {
12451
- const evidenceDir = path22.join(directory, ".swarm", "evidence");
12599
+ const evidenceDir = path23.join(directory, ".swarm", "evidence");
12452
12600
  const entries = await fs8.readdir(evidenceDir);
12453
12601
  const retroDirs = entries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
12454
12602
  for (const retroDir of retroDirs) {
12455
- const evidencePath = path22.join(evidenceDir, retroDir, "evidence.json");
12603
+ const evidencePath = path23.join(evidenceDir, retroDir, "evidence.json");
12456
12604
  try {
12457
12605
  const content = await fs8.readFile(evidencePath, "utf-8");
12458
12606
  const parsed = JSON.parse(content);
@@ -12481,12 +12629,12 @@ async function gatherRetroLessonsAndTaxonomy(directory) {
12481
12629
  async function gatherGateFailures(directory) {
12482
12630
  const failures = new Map;
12483
12631
  try {
12484
- const evidenceDir = path22.join(directory, ".swarm", "evidence");
12632
+ const evidenceDir = path23.join(directory, ".swarm", "evidence");
12485
12633
  const entries = await fs8.readdir(evidenceDir);
12486
12634
  for (const entry of entries) {
12487
12635
  if (entry.startsWith("retro-"))
12488
12636
  continue;
12489
- const evidencePath = path22.join(evidenceDir, entry, "evidence.json");
12637
+ const evidencePath = path23.join(evidenceDir, entry, "evidence.json");
12490
12638
  try {
12491
12639
  const content = await fs8.readFile(evidencePath, "utf-8");
12492
12640
  const parsed = JSON.parse(content);
@@ -12687,12 +12835,12 @@ async function writeSessionReflection(directory, result) {
12687
12835
  // src/services/skill-improver.ts
12688
12836
  import { existsSync as existsSync15 } from "fs";
12689
12837
  import { mkdir as mkdir8, readFile as readFile9, rename as rename6, writeFile as writeFile10 } from "fs/promises";
12690
- import * as path24 from "path";
12838
+ import * as path25 from "path";
12691
12839
  init_logger();
12692
12840
 
12693
12841
  // src/services/trajectory-cluster.ts
12694
12842
  import { mkdir as mkdir7, writeFile as writeFile9 } from "fs/promises";
12695
- import * as path23 from "path";
12843
+ import * as path24 from "path";
12696
12844
  init_logger();
12697
12845
  var MACRO_TRAJECTORY_WINDOW = 200;
12698
12846
  var MOTIF_MIN_TASKS = 2;
@@ -12824,11 +12972,11 @@ async function writeMotifProposals(directory, opts = {}) {
12824
12972
  if (motifs.length === 0)
12825
12973
  return result;
12826
12974
  const max = opts.maxProposals ?? 10;
12827
- const proposalsDir = validateSwarmPath(directory, path23.join("skills", "proposals"));
12975
+ const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
12828
12976
  await mkdir7(proposalsDir, { recursive: true });
12829
12977
  for (const motif of motifs.slice(0, max)) {
12830
12978
  const slug = `motif-${slugify(motif.signature)}`;
12831
- const filePath = path23.join(proposalsDir, `${slug}.md`);
12979
+ const filePath = path24.join(proposalsDir, `${slug}.md`);
12832
12980
  await writeFile9(filePath, buildMotifProposal(motif), "utf-8");
12833
12981
  result.proposalsWritten.push(filePath);
12834
12982
  }
@@ -12969,11 +13117,11 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
12969
13117
  if (motifs.length === 0)
12970
13118
  return result;
12971
13119
  const max = opts.maxProposals ?? 10;
12972
- const proposalsDir = validateSwarmPath(directory, path23.join("skills", "proposals"));
13120
+ const proposalsDir = validateSwarmPath(directory, path24.join("skills", "proposals"));
12973
13121
  await mkdir7(proposalsDir, { recursive: true });
12974
13122
  for (const motif of motifs.slice(0, max)) {
12975
13123
  const slug = workflowSlug(motif.signature);
12976
- const filePath = path23.join(proposalsDir, `${slug}.md`);
13124
+ const filePath = path24.join(proposalsDir, `${slug}.md`);
12977
13125
  await writeFile9(filePath, buildWorkflowProposal(motif), "utf-8");
12978
13126
  result.proposalsWritten.push(filePath);
12979
13127
  }
@@ -13096,7 +13244,7 @@ function timestampSlug(d) {
13096
13244
  return d.toISOString().replace(/[:.]/g, "-");
13097
13245
  }
13098
13246
  async function atomicWrite(p, content) {
13099
- await mkdir8(path24.dirname(p), { recursive: true });
13247
+ await mkdir8(path25.dirname(p), { recursive: true });
13100
13248
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
13101
13249
  await writeFile10(tmp, content, "utf-8");
13102
13250
  await rename6(tmp, p);
@@ -13499,8 +13647,8 @@ async function runSkillImprover(req) {
13499
13647
  }
13500
13648
  throw err;
13501
13649
  }
13502
- const proposalDir = path24.join(req.directory, ".swarm", "skill-improver", "proposals");
13503
- const proposalFile = path24.join(proposalDir, `${timestampSlug(now)}.md`);
13650
+ const proposalDir = path25.join(req.directory, ".swarm", "skill-improver", "proposals");
13651
+ const proposalFile = path25.join(proposalDir, `${timestampSlug(now)}.md`);
13504
13652
  const finalBody = source === "llm" ? buildLLMProposalFrame({
13505
13653
  body,
13506
13654
  targets,
@@ -13570,13 +13718,13 @@ var _internals15 = {
13570
13718
 
13571
13719
  // src/session/session-start-store.ts
13572
13720
  import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync8, writeFileSync as writeFileSync4 } from "fs";
13573
- import * as path25 from "path";
13721
+ import * as path26 from "path";
13574
13722
  var SESSION_START_FILE = "session-start.jsonl";
13575
13723
  function recordSessionStart(directory, startMs) {
13576
13724
  try {
13577
- const swarmDir = path25.join(directory, ".swarm");
13578
- const sessionDir = path25.join(swarmDir, "session");
13579
- const filePath = path25.join(sessionDir, SESSION_START_FILE);
13725
+ const swarmDir = path26.join(directory, ".swarm");
13726
+ const sessionDir = path26.join(swarmDir, "session");
13727
+ const filePath = path26.join(sessionDir, SESSION_START_FILE);
13580
13728
  const line = JSON.stringify({ startMs, ts: Date.now() });
13581
13729
  mkdirSync9(sessionDir, { recursive: true });
13582
13730
  writeFileSync4(filePath, `${line}
@@ -13585,7 +13733,7 @@ function recordSessionStart(directory, startMs) {
13585
13733
  }
13586
13734
  function readEarliestSessionStart(directory) {
13587
13735
  try {
13588
- const filePath = path25.join(directory, ".swarm", "session", SESSION_START_FILE);
13736
+ const filePath = path26.join(directory, ".swarm", "session", SESSION_START_FILE);
13589
13737
  if (!existsSync16(filePath))
13590
13738
  return null;
13591
13739
  const content = readFileSync8(filePath, "utf-8");
@@ -13612,7 +13760,7 @@ function readEarliestSessionStart(directory) {
13612
13760
 
13613
13761
  // src/tools/write-retro.ts
13614
13762
  import { existsSync as existsSync17 } from "fs";
13615
- import path26 from "path";
13763
+ import path27 from "path";
13616
13764
  async function executeWriteRetro(args, directory) {
13617
13765
  if (/^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(:|$)/i.test(directory)) {
13618
13766
  return JSON.stringify({
@@ -13620,7 +13768,7 @@ async function executeWriteRetro(args, directory) {
13620
13768
  message: "Invalid directory: reserved device name"
13621
13769
  }, null, 2);
13622
13770
  }
13623
- if (!existsSync17(path26.join(directory, ".swarm"))) {
13771
+ if (!existsSync17(path27.join(directory, ".swarm"))) {
13624
13772
  return JSON.stringify({
13625
13773
  success: false,
13626
13774
  message: `Cannot write evidence in "${directory}" \u2014 no .swarm/ folder was found. Run write_retro from an initialized project root.`
@@ -14036,8 +14184,8 @@ async function copyDirRecursiveWithFailures(src, dest) {
14036
14184
  const entries = await fs9.readdir(src);
14037
14185
  await fs9.mkdir(dest, { recursive: true });
14038
14186
  for (const entry of entries) {
14039
- const srcEntry = path27.join(src, entry);
14040
- const destEntry = path27.join(dest, entry);
14187
+ const srcEntry = path28.join(src, entry);
14188
+ const destEntry = path28.join(dest, entry);
14041
14189
  try {
14042
14190
  const stat4 = await fs9.stat(srcEntry);
14043
14191
  if (stat4.isDirectory()) {
@@ -14222,18 +14370,18 @@ async function runFinalizeStage(ctx) {
14222
14370
  ctx.warnings.push(`Session retrospective write threw: ${retroError instanceof Error ? retroError.message : String(retroError)}`);
14223
14371
  }
14224
14372
  }
14225
- const lessonsFilePath = path27.join(ctx.swarmDir, "close-lessons.md");
14373
+ const lessonsFilePath = path28.join(ctx.swarmDir, "close-lessons.md");
14226
14374
  try {
14227
14375
  const lessonsText = await fs9.readFile(lessonsFilePath, "utf-8");
14228
14376
  ctx.explicitLessons = lessonsText.split(`
14229
14377
  `).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#"));
14230
14378
  } catch {}
14231
14379
  try {
14232
- const evidenceDir = path27.join(ctx.swarmDir, "evidence");
14380
+ const evidenceDir = path28.join(ctx.swarmDir, "evidence");
14233
14381
  const evidenceEntries = await fs9.readdir(evidenceDir);
14234
14382
  const retroDirs = evidenceEntries.filter((e) => e.startsWith("retro-")).sort((a, b) => a.localeCompare(b, undefined, { numeric: true }));
14235
14383
  for (const retroDir of retroDirs) {
14236
- const evidencePath = path27.join(evidenceDir, retroDir, "evidence.json");
14384
+ const evidencePath = path28.join(evidenceDir, retroDir, "evidence.json");
14237
14385
  try {
14238
14386
  const content = await fs9.readFile(evidencePath, "utf-8");
14239
14387
  const parsed = JSON.parse(content);
@@ -14385,7 +14533,7 @@ async function runFinalizeStage(ctx) {
14385
14533
  }
14386
14534
  }
14387
14535
  try {
14388
- const { CuratorConfigSchema: CCS } = await import("./schema-x17zmd03.js");
14536
+ const { CuratorConfigSchema: CCS } = await import("./schema-5vmb5dh8.js");
14389
14537
  const { config: pmLoadedConfig } = _internals17.loadPluginConfigWithMeta(ctx.directory);
14390
14538
  const curatorCfg = CCS.parse(pmLoadedConfig.curator ?? {});
14391
14539
  if (curatorCfg.enabled && curatorCfg.postmortem_enabled) {
@@ -14417,7 +14565,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
14417
14565
  let checkpointVerified = false;
14418
14566
  try {
14419
14567
  const result = _internals17.spawnSync("sqlite3", [srcPath, "PRAGMA wal_checkpoint(TRUNCATE);"], {
14420
- cwd: path27.dirname(srcPath),
14568
+ cwd: path28.dirname(srcPath),
14421
14569
  encoding: "utf-8",
14422
14570
  stdio: ["ignore", "pipe", "pipe"],
14423
14571
  timeout: 1e4,
@@ -14486,7 +14634,7 @@ async function copySqliteSafe(srcPath, destPath, laneEnv) {
14486
14634
  async function runArchiveStage(ctx) {
14487
14635
  ctx.timestamp = new Date().toISOString().replace(/[:.]/g, "-");
14488
14636
  ctx.archiveSuffix = Math.random().toString(36).slice(2, 8);
14489
- ctx.archiveDir = path27.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
14637
+ ctx.archiveDir = path28.join(ctx.swarmDir, "archive", `swarm-${ctx.timestamp}-${ctx.archiveSuffix}`);
14490
14638
  try {
14491
14639
  await fs9.mkdir(ctx.archiveDir, { recursive: true });
14492
14640
  const WAL_SIDECAR_FILES = new Set(["swarm.db-shm", "swarm.db-wal"]);
@@ -14501,8 +14649,8 @@ async function runArchiveStage(ctx) {
14501
14649
  if (linkedKnowledgeShared && KNOWLEDGE_FAMILY_ARTIFACTS.has(artifact)) {
14502
14650
  continue;
14503
14651
  }
14504
- const srcPath = path27.join(ctx.swarmDir, artifact);
14505
- const destPath = path27.join(ctx.archiveDir, artifact);
14652
+ const srcPath = path28.join(ctx.swarmDir, artifact);
14653
+ const destPath = path28.join(ctx.archiveDir, artifact);
14506
14654
  if (artifact === "swarm.db") {
14507
14655
  const result = await copySqliteSafe(srcPath, destPath, undefined);
14508
14656
  if (result.skipped) {} else if (result.success) {
@@ -14535,8 +14683,8 @@ async function runArchiveStage(ctx) {
14535
14683
  }
14536
14684
  const dynamicArchiveArtifacts = (await fs9.readdir(ctx.swarmDir).catch(() => [])).filter((name) => /^post-mortem-[^/\\]+\.md$/.test(name) || /^drift-report-phase-\d+\.json$/.test(name));
14537
14685
  for (const artifact of dynamicArchiveArtifacts) {
14538
- const srcPath = path27.join(ctx.swarmDir, artifact);
14539
- const destPath = path27.join(ctx.archiveDir, artifact);
14686
+ const srcPath = path28.join(ctx.swarmDir, artifact);
14687
+ const destPath = path28.join(ctx.archiveDir, artifact);
14540
14688
  try {
14541
14689
  await fs9.copyFile(srcPath, destPath);
14542
14690
  ctx.archivedFileCount++;
@@ -14551,8 +14699,8 @@ async function runArchiveStage(ctx) {
14551
14699
  }
14552
14700
  }
14553
14701
  for (const dirName of ACTIVE_STATE_DIRS_TO_CLEAN) {
14554
- const srcDir = path27.join(ctx.swarmDir, dirName);
14555
- const destDir = path27.join(ctx.archiveDir, dirName);
14702
+ const srcDir = path28.join(ctx.swarmDir, dirName);
14703
+ const destDir = path28.join(ctx.archiveDir, dirName);
14556
14704
  try {
14557
14705
  const result = await copyDirRecursiveWithFailures(srcDir, destDir);
14558
14706
  ctx.archivedFileCount += result.copied;
@@ -14629,7 +14777,7 @@ async function runCleanStage(ctx) {
14629
14777
  ctx.warnings.push(reason ? `Preserved ${artifact} because it was not successfully archived: ${reason}.` : `Preserved ${artifact} because it was not successfully archived.`);
14630
14778
  continue;
14631
14779
  }
14632
- const filePath = path27.join(ctx.swarmDir, artifact);
14780
+ const filePath = path28.join(ctx.swarmDir, artifact);
14633
14781
  try {
14634
14782
  await fs9.unlink(filePath);
14635
14783
  cleanedFiles.push(artifact);
@@ -14649,7 +14797,7 @@ async function runCleanStage(ctx) {
14649
14797
  continue;
14650
14798
  }
14651
14799
  try {
14652
- await fs9.unlink(path27.join(ctx.swarmDir, artifact));
14800
+ await fs9.unlink(path28.join(ctx.swarmDir, artifact));
14653
14801
  cleanedFiles.push(artifact);
14654
14802
  } catch (err) {
14655
14803
  const errno = err?.code;
@@ -14663,7 +14811,7 @@ async function runCleanStage(ctx) {
14663
14811
  if (!ctx.archivedActiveStateDirs.has(dirName)) {
14664
14812
  continue;
14665
14813
  }
14666
- const dirPath = path27.join(ctx.swarmDir, dirName);
14814
+ const dirPath = path28.join(ctx.swarmDir, dirName);
14667
14815
  try {
14668
14816
  await fs9.rm(dirPath, { recursive: true, force: true });
14669
14817
  cleanedFiles.push(`${dirName}/`);
@@ -14674,7 +14822,7 @@ async function runCleanStage(ctx) {
14674
14822
  const configBackups = swarmFiles.filter((f) => f.startsWith("config-backup-") && f.endsWith(".json"));
14675
14823
  for (const backup of configBackups) {
14676
14824
  try {
14677
- await fs9.unlink(path27.join(ctx.swarmDir, backup));
14825
+ await fs9.unlink(path28.join(ctx.swarmDir, backup));
14678
14826
  configBackupsRemoved++;
14679
14827
  } catch (err) {
14680
14828
  const errno = err?.code;
@@ -14687,7 +14835,7 @@ async function runCleanStage(ctx) {
14687
14835
  const ledgerSiblings = swarmFiles.filter((f) => (f.startsWith("plan-ledger.archived-") || f.startsWith("plan-ledger.backup-")) && f.endsWith(".jsonl"));
14688
14836
  for (const sibling of ledgerSiblings) {
14689
14837
  try {
14690
- await fs9.unlink(path27.join(ctx.swarmDir, sibling));
14838
+ await fs9.unlink(path28.join(ctx.swarmDir, sibling));
14691
14839
  } catch (err) {
14692
14840
  const errno = err?.code;
14693
14841
  if (errno === "ENOENT") {} else {
@@ -14705,12 +14853,12 @@ async function runCleanStage(ctx) {
14705
14853
  }
14706
14854
  let swarmPlanFilesRemoved = 0;
14707
14855
  const candidates = [
14708
- path27.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
14709
- path27.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
14710
- path27.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
14711
- path27.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
14712
- path27.join(ctx.directory, "SWARM_PLAN.json"),
14713
- path27.join(ctx.directory, "SWARM_PLAN.md")
14856
+ path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.json"),
14857
+ path28.join(ctx.directory, ".swarm", "plan-export", "SWARM_PLAN.md"),
14858
+ path28.join(ctx.directory, ".swarm", "SWARM_PLAN.json"),
14859
+ path28.join(ctx.directory, ".swarm", "SWARM_PLAN.md"),
14860
+ path28.join(ctx.directory, "SWARM_PLAN.json"),
14861
+ path28.join(ctx.directory, "SWARM_PLAN.md")
14714
14862
  ];
14715
14863
  for (const candidate of candidates) {
14716
14864
  try {
@@ -14728,7 +14876,7 @@ async function runCleanStage(ctx) {
14728
14876
  const tmpFiles = swarmFiles.filter((f) => f.startsWith(".tmp."));
14729
14877
  for (const tmp of tmpFiles) {
14730
14878
  try {
14731
- await fs9.unlink(path27.join(ctx.swarmDir, tmp));
14879
+ await fs9.unlink(path28.join(ctx.swarmDir, tmp));
14732
14880
  tmpFilesRemoved++;
14733
14881
  } catch (err) {
14734
14882
  const errno = err?.code;
@@ -14750,7 +14898,7 @@ async function runCleanStage(ctx) {
14750
14898
  }
14751
14899
  for (const terminalFile of TERMINAL_STATE_FILES) {
14752
14900
  try {
14753
- await fs9.unlink(path27.join(ctx.swarmDir, terminalFile));
14901
+ await fs9.unlink(path28.join(ctx.swarmDir, terminalFile));
14754
14902
  if (!cleanedFiles.includes(terminalFile)) {
14755
14903
  cleanedFiles.push(terminalFile);
14756
14904
  }
@@ -14763,7 +14911,7 @@ async function runCleanStage(ctx) {
14763
14911
  }
14764
14912
  }
14765
14913
  clearAllScopes(ctx.directory);
14766
- const contextPath = path27.join(ctx.swarmDir, "context.md");
14914
+ const contextPath = path28.join(ctx.swarmDir, "context.md");
14767
14915
  const contextContent = [
14768
14916
  "# Context",
14769
14917
  "",
@@ -14775,7 +14923,7 @@ async function runCleanStage(ctx) {
14775
14923
  ""
14776
14924
  ].join(`
14777
14925
  `);
14778
- const contextTempPath = path27.join(path27.dirname(contextPath), `${path27.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
14926
+ const contextTempPath = path28.join(path28.dirname(contextPath), `${path28.basename(contextPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
14779
14927
  try {
14780
14928
  await fs9.writeFile(contextTempPath, contextContent, "utf-8");
14781
14929
  fsSync.renameSync(contextTempPath, contextPath);
@@ -14839,7 +14987,7 @@ async function runAlignStage(ctx) {
14839
14987
  return { gitAlignResult, prunedBranches };
14840
14988
  }
14841
14989
  async function handleCloseCommand(directory, args, options = {}) {
14842
- const swarmDir = path27.join(directory, ".swarm");
14990
+ const swarmDir = path28.join(directory, ".swarm");
14843
14991
  try {
14844
14992
  const stat4 = fsSync.lstatSync(swarmDir);
14845
14993
  if (stat4.isSymbolicLink()) {
@@ -14853,7 +15001,7 @@ async function handleCloseCommand(directory, args, options = {}) {
14853
15001
  const planPath = validateSwarmPath(directory, "plan.json");
14854
15002
  let planExists = false;
14855
15003
  let planData = {
14856
- title: path27.basename(directory) || "Ad-hoc session",
15004
+ title: path28.basename(directory) || "Ad-hoc session",
14857
15005
  phases: []
14858
15006
  };
14859
15007
  try {
@@ -14878,7 +15026,7 @@ async function handleCloseCommand(directory, args, options = {}) {
14878
15026
  }
14879
15027
  try {
14880
15028
  if (!planExists) {
14881
- const archiveDir = path27.join(swarmDir, "archive");
15029
+ const archiveDir = path28.join(swarmDir, "archive");
14882
15030
  try {
14883
15031
  const archiveEntries = await fs9.readdir(archiveDir);
14884
15032
  const hasArchiveBundle = archiveEntries.some((entry) => entry.startsWith("swarm-"));
@@ -14886,7 +15034,7 @@ async function handleCloseCommand(directory, args, options = {}) {
14886
15034
  const hasActiveState = [
14887
15035
  ...ACTIVE_STATE_TO_CLEAN,
14888
15036
  ...ACTIVE_STATE_DIRS_TO_CLEAN
14889
- ].some((entry) => fsSync.existsSync(path27.join(swarmDir, entry)));
15037
+ ].some((entry) => fsSync.existsSync(path28.join(swarmDir, entry)));
14890
15038
  if (!hasActiveState) {
14891
15039
  return `\u2705 Already finalized \u2014 nothing to do.
14892
15040
 
@@ -15014,7 +15162,7 @@ This project was already finalized in a previous /swarm close run. The plan has
15014
15162
  ...ctx.warnings.length > 0 ? ["## Warnings", ...ctx.warnings.map((w) => `- ${w}`), ""] : []
15015
15163
  ].join(`
15016
15164
  `);
15017
- const closeSummaryTempPath = path27.join(path27.dirname(closeSummaryPath), `${path27.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
15165
+ const closeSummaryTempPath = path28.join(path28.dirname(closeSummaryPath), `${path28.basename(closeSummaryPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
15018
15166
  try {
15019
15167
  await fs9.writeFile(closeSummaryTempPath, summaryContent, "utf-8");
15020
15168
  fsSync.renameSync(closeSummaryTempPath, closeSummaryPath);
@@ -15365,14 +15513,14 @@ function buildStatusMessage(session, plan) {
15365
15513
 
15366
15514
  // src/commands/config.ts
15367
15515
  import * as os5 from "os";
15368
- import * as path28 from "path";
15516
+ import * as path29 from "path";
15369
15517
  function getUserConfigDir2() {
15370
- return process.env.XDG_CONFIG_HOME || path28.join(os5.homedir(), ".config");
15518
+ return process.env.XDG_CONFIG_HOME || path29.join(os5.homedir(), ".config");
15371
15519
  }
15372
15520
  async function handleConfigCommand(directory, _args) {
15373
15521
  const config = loadPluginConfig(directory);
15374
- const userConfigPath = path28.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
15375
- const projectConfigPath = path28.join(directory, ".opencode", "opencode-swarm.json");
15522
+ const userConfigPath = path29.join(getUserConfigDir2(), "opencode", "opencode-swarm.json");
15523
+ const projectConfigPath = path29.join(directory, ".opencode", "opencode-swarm.json");
15376
15524
  const lines = [
15377
15525
  "## Swarm Configuration",
15378
15526
  "",
@@ -15392,7 +15540,7 @@ async function handleConfigCommand(directory, _args) {
15392
15540
  // src/services/skill-consolidation.ts
15393
15541
  import { existsSync as existsSync19 } from "fs";
15394
15542
  import { mkdir as mkdir9, readFile as readFile10, rename as rename7, writeFile as writeFile11 } from "fs/promises";
15395
- import * as path29 from "path";
15543
+ import * as path30 from "path";
15396
15544
 
15397
15545
  // src/utils/timeout.ts
15398
15546
  async function withTimeout(promise, ms, timeoutError) {
@@ -15417,7 +15565,7 @@ var DEFAULT_CONSOLIDATION_MAX_CALLS_PER_RUN = 1;
15417
15565
  var CONSOLIDATION_RUN_TIMEOUT_MS = 5 * 60 * 1000;
15418
15566
  var runningByDirectory = new Map;
15419
15567
  function consolidationStatePath(directory) {
15420
- return path29.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
15568
+ return path30.join(directory, ".swarm", "skill-improver", "consolidation-state.json");
15421
15569
  }
15422
15570
  async function readState2(directory) {
15423
15571
  const filePath = consolidationStatePath(directory);
@@ -15433,7 +15581,7 @@ async function readState2(directory) {
15433
15581
  }
15434
15582
  }
15435
15583
  async function atomicWrite2(filePath, content) {
15436
- await mkdir9(path29.dirname(filePath), { recursive: true });
15584
+ await mkdir9(path30.dirname(filePath), { recursive: true });
15437
15585
  const tmp = `${filePath}.tmp-${process.pid}-${Date.now()}`;
15438
15586
  await writeFile11(tmp, content, "utf-8");
15439
15587
  await rename7(tmp, filePath);
@@ -15513,7 +15661,7 @@ async function runSkillConsolidationInner(req) {
15513
15661
  };
15514
15662
  }
15515
15663
  async function runSkillConsolidation(req) {
15516
- const key = path29.resolve(req.directory);
15664
+ const key = path30.resolve(req.directory);
15517
15665
  const existing = runningByDirectory.get(key);
15518
15666
  if (existing) {
15519
15667
  return {
@@ -15715,7 +15863,7 @@ async function handleCouncilCommand(_directory, args) {
15715
15863
  // src/commands/coupling.ts
15716
15864
  import { randomBytes } from "crypto";
15717
15865
  import * as fs10 from "fs";
15718
- import * as path31 from "path";
15866
+ import * as path32 from "path";
15719
15867
 
15720
15868
  // src/turbo/epic/cochange-source.ts
15721
15869
  import * as child_process4 from "child_process";
@@ -15725,7 +15873,7 @@ import { promisify as promisify2 } from "util";
15725
15873
  import * as child_process3 from "child_process";
15726
15874
  import { randomUUID as randomUUID6 } from "crypto";
15727
15875
  import { readdir as readdir2, readFile as readFile11, stat as stat4 } from "fs/promises";
15728
- import * as path30 from "path";
15876
+ import * as path31 from "path";
15729
15877
  import { promisify } from "util";
15730
15878
  function getExecFileAsync() {
15731
15879
  return promisify(child_process3.execFile);
@@ -15829,7 +15977,7 @@ async function scanSourceFiles(dir) {
15829
15977
  try {
15830
15978
  const entries = await readdir2(dir, { withFileTypes: true });
15831
15979
  for (const entry of entries) {
15832
- const fullPath = path30.join(dir, entry.name);
15980
+ const fullPath = path31.join(dir, entry.name);
15833
15981
  if (entry.isDirectory()) {
15834
15982
  if (skipDirs.has(entry.name)) {
15835
15983
  continue;
@@ -15837,7 +15985,7 @@ async function scanSourceFiles(dir) {
15837
15985
  const subFiles = await scanSourceFiles(fullPath);
15838
15986
  results.push(...subFiles);
15839
15987
  } else if (entry.isFile()) {
15840
- const ext = path30.extname(entry.name);
15988
+ const ext = path31.extname(entry.name);
15841
15989
  if ([".ts", ".tsx", ".js", ".jsx", ".mjs"].includes(ext)) {
15842
15990
  results.push(fullPath);
15843
15991
  }
@@ -15859,8 +16007,8 @@ async function getStaticEdges(directory) {
15859
16007
  continue;
15860
16008
  }
15861
16009
  try {
15862
- const sourceDir = path30.dirname(sourceFile);
15863
- const resolvedPath = path30.resolve(sourceDir, importPath);
16010
+ const sourceDir = path31.dirname(sourceFile);
16011
+ const resolvedPath = path31.resolve(sourceDir, importPath);
15864
16012
  const extensions = [
15865
16013
  "",
15866
16014
  ".ts",
@@ -15885,8 +16033,8 @@ async function getStaticEdges(directory) {
15885
16033
  if (!targetFile) {
15886
16034
  continue;
15887
16035
  }
15888
- const relSource = path30.relative(directory, sourceFile).replace(/\\/g, "/");
15889
- const relTarget = path30.relative(directory, targetFile).replace(/\\/g, "/");
16036
+ const relSource = path31.relative(directory, sourceFile).replace(/\\/g, "/");
16037
+ const relTarget = path31.relative(directory, targetFile).replace(/\\/g, "/");
15890
16038
  const [key] = relSource < relTarget ? [`${relSource}::${relTarget}`, relSource, relTarget] : [`${relTarget}::${relSource}`, relTarget, relSource];
15891
16039
  edges.add(key);
15892
16040
  } catch {}
@@ -15898,7 +16046,7 @@ async function getStaticEdges(directory) {
15898
16046
  function isTestImplementationPair(fileA, fileB) {
15899
16047
  const testPatterns = [".test.ts", ".test.js", ".spec.ts", ".spec.js"];
15900
16048
  const getBaseName = (filePath) => {
15901
- const base = path30.basename(filePath);
16049
+ const base = path31.basename(filePath);
15902
16050
  for (const pattern of testPatterns) {
15903
16051
  if (base.endsWith(pattern)) {
15904
16052
  return base.slice(0, -pattern.length);
@@ -15908,16 +16056,16 @@ function isTestImplementationPair(fileA, fileB) {
15908
16056
  };
15909
16057
  const baseA = getBaseName(fileA);
15910
16058
  const baseB = getBaseName(fileB);
15911
- return baseA === baseB && baseA !== path30.basename(fileA) && baseA !== path30.basename(fileB);
16059
+ return baseA === baseB && baseA !== path31.basename(fileA) && baseA !== path31.basename(fileB);
15912
16060
  }
15913
16061
  function hasSharedPrefix(fileA, fileB) {
15914
- const dirA = path30.dirname(fileA);
15915
- const dirB = path30.dirname(fileB);
16062
+ const dirA = path31.dirname(fileA);
16063
+ const dirB = path31.dirname(fileB);
15916
16064
  if (dirA !== dirB) {
15917
16065
  return false;
15918
16066
  }
15919
- const baseA = path30.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
15920
- const baseB = path30.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
16067
+ const baseA = path31.basename(fileA).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
16068
+ const baseB = path31.basename(fileB).replace(/\.(ts|js|tsx|jsx|mjs)$/, "");
15921
16069
  if (baseA.startsWith(baseB) || baseB.startsWith(baseA)) {
15922
16070
  return true;
15923
16071
  }
@@ -15972,8 +16120,8 @@ function darkMatterToKnowledgeEntries(pairs, projectName) {
15972
16120
  const entries = [];
15973
16121
  const now = new Date().toISOString();
15974
16122
  for (const pair of pairs.slice(0, 10)) {
15975
- const baseA = path30.basename(pair.fileA);
15976
- const baseB = path30.basename(pair.fileB);
16123
+ const baseA = path31.basename(pair.fileA);
16124
+ const baseB = path31.basename(pair.fileB);
15977
16125
  let lesson = `Files ${pair.fileA} and ${pair.fileB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
15978
16126
  if (lesson.length > 280) {
15979
16127
  lesson = `Files ${baseA} and ${baseB} co-change with NPMI=${pair.npmi.toFixed(3)} but have no import relationship. This hidden coupling suggests a shared architectural concern \u2014 changes to one likely require changes to the other.`;
@@ -16399,9 +16547,9 @@ function parseArgs3(args) {
16399
16547
  return parsed;
16400
16548
  }
16401
16549
  function persistReportJson(directory, report) {
16402
- const epicDir = path31.join(directory, ".swarm", "epic");
16550
+ const epicDir = path32.join(directory, ".swarm", "epic");
16403
16551
  fs10.mkdirSync(epicDir, { recursive: true });
16404
- const filePath = path31.join(epicDir, "coupling-report.json");
16552
+ const filePath = path32.join(epicDir, "coupling-report.json");
16405
16553
  const tmpPath = `${filePath}.tmp.${randomBytes(8).toString("hex")}`;
16406
16554
  fs10.writeFileSync(tmpPath, `${JSON.stringify(report, null, 2)}
16407
16555
  `, "utf-8");
@@ -16460,7 +16608,7 @@ Usage: /swarm coupling [--phase <n>] [--threshold <-1..1>] [--min-co-changes <n>
16460
16608
  persistStatus = {
16461
16609
  requested: true,
16462
16610
  written: true,
16463
- path: path31.relative(directory, writtenAt).replace(/\\/g, "/")
16611
+ path: path32.relative(directory, writtenAt).replace(/\\/g, "/")
16464
16612
  };
16465
16613
  } catch (err) {
16466
16614
  persistStatus = {
@@ -16498,9 +16646,9 @@ var _internals21 = {
16498
16646
  readSwarmFileAsync,
16499
16647
  loadCuratorDeps: async () => {
16500
16648
  const [{ CuratorConfigSchema }, curator, { createCuratorLLMDelegate: createCuratorLLMDelegate2 }] = await Promise.all([
16501
- import("./schema-x17zmd03.js"),
16502
- import("./curator-6p9tpprq.js"),
16503
- import("./curator-llm-factory-wqbm9mwr.js")
16649
+ import("./schema-5vmb5dh8.js"),
16650
+ import("./curator-zn1kmwmz.js"),
16651
+ import("./curator-llm-factory-3hf9xpnd.js")
16504
16652
  ]);
16505
16653
  return { CuratorConfigSchema, curator, createCuratorLLMDelegate: createCuratorLLMDelegate2 };
16506
16654
  }
@@ -16592,7 +16740,7 @@ function formatCurationSummary(summary) {
16592
16740
  }
16593
16741
 
16594
16742
  // src/commands/dark-matter.ts
16595
- import path32 from "path";
16743
+ import path33 from "path";
16596
16744
  async function handleDarkMatterCommand(directory, args) {
16597
16745
  const options = {};
16598
16746
  for (let i = 0;i < args.length; i++) {
@@ -16624,7 +16772,7 @@ Ensure this is a git repository with commit history.`;
16624
16772
  const output = formatDarkMatterOutput(pairs);
16625
16773
  if (pairs.length > 0) {
16626
16774
  try {
16627
- const projectName = path32.basename(path32.resolve(directory));
16775
+ const projectName = path33.basename(path33.resolve(directory));
16628
16776
  const entries = darkMatterToKnowledgeEntries(pairs, projectName);
16629
16777
  if (entries.length > 0) {
16630
16778
  const knowledgePath = resolveSwarmKnowledgePath(directory);
@@ -16991,12 +17139,12 @@ ${USAGE5}`;
16991
17139
  // src/services/diagnose-service.ts
16992
17140
  import * as child_process5 from "child_process";
16993
17141
  import { existsSync as existsSync22, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
16994
- import * as path34 from "path";
17142
+ import * as path35 from "path";
16995
17143
  import { fileURLToPath } from "url";
16996
17144
  // package.json
16997
17145
  var package_default = {
16998
17146
  name: "opencode-swarm",
16999
- version: "7.109.2",
17147
+ version: "7.109.4",
17000
17148
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
17001
17149
  main: "dist/index.js",
17002
17150
  types: "dist/index.d.ts",
@@ -17063,6 +17211,11 @@ var package_default = {
17063
17211
  ".opencode/skills/running-tests",
17064
17212
  ".opencode/skills/engineering-conventions",
17065
17213
  ".opencode/skills/commit-pr",
17214
+ ".opencode/skills/worktree-retry-cleanup",
17215
+ ".opencode/skills/skill-edit-validation",
17216
+ ".opencode/skills/merge-queue-readiness",
17217
+ ".opencode/skills/gate-attribution",
17218
+ ".opencode/skills/ci-failure-batching",
17066
17219
  "tests/fixtures/memory-recall",
17067
17220
  "README.md",
17068
17221
  "LICENSE"
@@ -17105,44 +17258,44 @@ var package_default = {
17105
17258
 
17106
17259
  // src/config/cache-paths.ts
17107
17260
  import * as os6 from "os";
17108
- import * as path33 from "path";
17261
+ import * as path34 from "path";
17109
17262
  function getPluginConfigDir() {
17110
- return path33.join(process.env.XDG_CONFIG_HOME || path33.join(os6.homedir(), ".config"), "opencode");
17263
+ return path34.join(process.env.XDG_CONFIG_HOME || path34.join(os6.homedir(), ".config"), "opencode");
17111
17264
  }
17112
17265
  function getPluginCachePaths() {
17113
- const cacheBase = process.env.XDG_CACHE_HOME || path33.join(os6.homedir(), ".cache");
17266
+ const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os6.homedir(), ".cache");
17114
17267
  const configDir = getPluginConfigDir();
17115
17268
  const paths = [
17116
- path33.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
17117
- path33.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
17118
- path33.join(configDir, "node_modules", "opencode-swarm")
17269
+ path34.join(cacheBase, "opencode", "node_modules", "opencode-swarm"),
17270
+ path34.join(cacheBase, "opencode", "packages", "opencode-swarm@latest"),
17271
+ path34.join(configDir, "node_modules", "opencode-swarm")
17119
17272
  ];
17120
17273
  if (process.platform === "darwin") {
17121
- const libCaches = path33.join(os6.homedir(), "Library", "Caches");
17122
- paths.push(path33.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path33.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
17274
+ const libCaches = path34.join(os6.homedir(), "Library", "Caches");
17275
+ paths.push(path34.join(libCaches, "opencode", "node_modules", "opencode-swarm"), path34.join(libCaches, "opencode", "packages", "opencode-swarm@latest"));
17123
17276
  }
17124
17277
  if (process.platform === "win32") {
17125
- const localAppData = process.env.LOCALAPPDATA || path33.join(os6.homedir(), "AppData", "Local");
17126
- const appData = process.env.APPDATA || path33.join(os6.homedir(), "AppData", "Roaming");
17127
- paths.push(path33.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path33.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path33.join(appData, "opencode", "node_modules", "opencode-swarm"));
17278
+ const localAppData = process.env.LOCALAPPDATA || path34.join(os6.homedir(), "AppData", "Local");
17279
+ const appData = process.env.APPDATA || path34.join(os6.homedir(), "AppData", "Roaming");
17280
+ paths.push(path34.join(localAppData, "opencode", "node_modules", "opencode-swarm"), path34.join(localAppData, "opencode", "packages", "opencode-swarm@latest"), path34.join(appData, "opencode", "node_modules", "opencode-swarm"));
17128
17281
  }
17129
17282
  return paths;
17130
17283
  }
17131
17284
  function getPluginLockFilePaths() {
17132
- const cacheBase = process.env.XDG_CACHE_HOME || path33.join(os6.homedir(), ".cache");
17285
+ const cacheBase = process.env.XDG_CACHE_HOME || path34.join(os6.homedir(), ".cache");
17133
17286
  const configDir = getPluginConfigDir();
17134
17287
  const paths = [
17135
- path33.join(cacheBase, "opencode", "bun.lock"),
17136
- path33.join(cacheBase, "opencode", "bun.lockb"),
17137
- path33.join(configDir, "package-lock.json")
17288
+ path34.join(cacheBase, "opencode", "bun.lock"),
17289
+ path34.join(cacheBase, "opencode", "bun.lockb"),
17290
+ path34.join(configDir, "package-lock.json")
17138
17291
  ];
17139
17292
  if (process.platform === "darwin") {
17140
- const libCaches = path33.join(os6.homedir(), "Library", "Caches");
17141
- paths.push(path33.join(libCaches, "opencode", "bun.lock"), path33.join(libCaches, "opencode", "bun.lockb"));
17293
+ const libCaches = path34.join(os6.homedir(), "Library", "Caches");
17294
+ paths.push(path34.join(libCaches, "opencode", "bun.lock"), path34.join(libCaches, "opencode", "bun.lockb"));
17142
17295
  }
17143
17296
  if (process.platform === "win32") {
17144
- const localAppData = process.env.LOCALAPPDATA || path33.join(os6.homedir(), "AppData", "Local");
17145
- paths.push(path33.join(localAppData, "opencode", "bun.lock"), path33.join(localAppData, "opencode", "bun.lockb"));
17297
+ const localAppData = process.env.LOCALAPPDATA || path34.join(os6.homedir(), "AppData", "Local");
17298
+ paths.push(path34.join(localAppData, "opencode", "bun.lock"), path34.join(localAppData, "opencode", "bun.lockb"));
17146
17299
  }
17147
17300
  return paths;
17148
17301
  }
@@ -17172,10 +17325,10 @@ function cacheFile() {
17172
17325
  }
17173
17326
  function readVersionCache() {
17174
17327
  try {
17175
- const path34 = cacheFile();
17176
- if (!existsSync20(path34))
17328
+ const path35 = cacheFile();
17329
+ if (!existsSync20(path35))
17177
17330
  return null;
17178
- const raw = readFileSync9(path34, "utf-8");
17331
+ const raw = readFileSync9(path35, "utf-8");
17179
17332
  const parsed = JSON.parse(raw);
17180
17333
  if (typeof parsed?.checkedAt !== "number")
17181
17334
  return null;
@@ -17430,7 +17583,7 @@ var REQUIRED_CACHE_GRAMMAR_ASSETS = [
17430
17583
  "tree-sitter-typescript.wasm"
17431
17584
  ];
17432
17585
  function resolveCachePackageRoot(cachePath) {
17433
- const nestedPackageRoot = path34.join(cachePath, "node_modules", "opencode-swarm");
17586
+ const nestedPackageRoot = path35.join(cachePath, "node_modules", "opencode-swarm");
17434
17587
  return existsSync22(nestedPackageRoot) ? nestedPackageRoot : cachePath;
17435
17588
  }
17436
17589
  var _internals22 = {
@@ -17746,7 +17899,7 @@ async function checkSpecStaleness(directory, plan) {
17746
17899
  };
17747
17900
  }
17748
17901
  async function checkConfigParseability(directory) {
17749
- const configPath = path34.join(directory, ".opencode/opencode-swarm.json");
17902
+ const configPath = path35.join(directory, ".opencode/opencode-swarm.json");
17750
17903
  if (!existsSync22(configPath)) {
17751
17904
  return {
17752
17905
  name: "Config Parseability",
@@ -17775,7 +17928,7 @@ function resolveGrammarDir(thisDir) {
17775
17928
  const normalized = thisDir.replace(/\\/g, "/");
17776
17929
  const isSource = normalized.endsWith("/src/services");
17777
17930
  const isCliBundle = normalized.endsWith("/cli");
17778
- return isSource || isCliBundle ? path34.join(thisDir, "..", "lang", "grammars") : path34.join(thisDir, "lang", "grammars");
17931
+ return isSource || isCliBundle ? path35.join(thisDir, "..", "lang", "grammars") : path35.join(thisDir, "lang", "grammars");
17779
17932
  }
17780
17933
  async function checkGrammarWasmFiles() {
17781
17934
  const grammarFiles = [
@@ -17799,14 +17952,14 @@ async function checkGrammarWasmFiles() {
17799
17952
  "tree-sitter-ini.wasm",
17800
17953
  "tree-sitter-regex.wasm"
17801
17954
  ];
17802
- const thisDir = path34.dirname(fileURLToPath(import.meta.url));
17955
+ const thisDir = path35.dirname(fileURLToPath(import.meta.url));
17803
17956
  const grammarDir = resolveGrammarDir(thisDir);
17804
17957
  const missing = [];
17805
- if (!existsSync22(path34.join(grammarDir, "tree-sitter.wasm"))) {
17958
+ if (!existsSync22(path35.join(grammarDir, "tree-sitter.wasm"))) {
17806
17959
  missing.push("tree-sitter.wasm (core runtime)");
17807
17960
  }
17808
17961
  for (const file of grammarFiles) {
17809
- if (!existsSync22(path34.join(grammarDir, file))) {
17962
+ if (!existsSync22(path35.join(grammarDir, file))) {
17810
17963
  missing.push(file);
17811
17964
  }
17812
17965
  }
@@ -17824,7 +17977,7 @@ async function checkGrammarWasmFiles() {
17824
17977
  };
17825
17978
  }
17826
17979
  async function checkCheckpointManifest(directory) {
17827
- const manifestPath = path34.join(directory, ".swarm/checkpoints.json");
17980
+ const manifestPath = path35.join(directory, ".swarm/checkpoints.json");
17828
17981
  if (!existsSync22(manifestPath)) {
17829
17982
  return {
17830
17983
  name: "Checkpoint Manifest",
@@ -17876,7 +18029,7 @@ async function checkCheckpointManifest(directory) {
17876
18029
  }
17877
18030
  }
17878
18031
  async function checkEventStreamIntegrity(directory) {
17879
- const eventsPath = path34.join(directory, ".swarm/events.jsonl");
18032
+ const eventsPath = path35.join(directory, ".swarm/events.jsonl");
17880
18033
  if (!existsSync22(eventsPath)) {
17881
18034
  return {
17882
18035
  name: "Event Stream",
@@ -17917,7 +18070,7 @@ async function checkEventStreamIntegrity(directory) {
17917
18070
  }
17918
18071
  }
17919
18072
  async function checkSteeringDirectives(directory) {
17920
- const eventsPath = path34.join(directory, ".swarm/events.jsonl");
18073
+ const eventsPath = path35.join(directory, ".swarm/events.jsonl");
17921
18074
  if (!existsSync22(eventsPath)) {
17922
18075
  return {
17923
18076
  name: "Steering Directives",
@@ -17973,7 +18126,7 @@ async function checkCurator(directory) {
17973
18126
  detail: "Disabled (enable via curator.enabled)"
17974
18127
  };
17975
18128
  }
17976
- const summaryPath = path34.join(directory, ".swarm/curator-summary.json");
18129
+ const summaryPath = path35.join(directory, ".swarm/curator-summary.json");
17977
18130
  if (!existsSync22(summaryPath)) {
17978
18131
  return {
17979
18132
  name: "Curator",
@@ -18175,7 +18328,7 @@ async function getDiagnoseData(directory) {
18175
18328
  checks.push(await checkCurator(directory));
18176
18329
  checks.push(await checkKnowledgeHealth(directory));
18177
18330
  try {
18178
- const evidenceDir = path34.join(directory, ".swarm", "evidence");
18331
+ const evidenceDir = path35.join(directory, ".swarm", "evidence");
18179
18332
  const snapshotFiles = existsSync22(evidenceDir) ? readdirSync4(evidenceDir).filter((f) => f.startsWith("agent-tools-") && f.endsWith(".json")) : [];
18180
18333
  if (snapshotFiles.length > 0) {
18181
18334
  const latest = snapshotFiles.sort().pop();
@@ -18215,8 +18368,8 @@ async function getDiagnoseData(directory) {
18215
18368
  }
18216
18369
  const packageRoot = resolveCachePackageRoot(cachePath);
18217
18370
  const cacheLabel = packageRoot === cachePath ? cachePath : `${cachePath} -> ${packageRoot}`;
18218
- const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path34.join(packageRoot, "dist", "lang", "grammars", file)));
18219
- const pkgJsonPath = path34.join(packageRoot, "package.json");
18371
+ const missingGrammarAssets = REQUIRED_CACHE_GRAMMAR_ASSETS.filter((file) => !existsSync22(path35.join(packageRoot, "dist", "lang", "grammars", file)));
18372
+ const pkgJsonPath = path35.join(packageRoot, "package.json");
18220
18373
  try {
18221
18374
  const raw = readFileSync10(pkgJsonPath, "utf-8");
18222
18375
  const parsed = JSON.parse(raw);
@@ -18441,7 +18594,7 @@ async function handleDoctorCommand(directory, args) {
18441
18594
  const result = runConfigDoctor(config, directory);
18442
18595
  let output;
18443
18596
  if (enableAutoFix && result.hasAutoFixableIssues) {
18444
- const { runConfigDoctorWithFixes } = await import("./config-doctor-q354tb2w.js");
18597
+ const { runConfigDoctorWithFixes } = await import("./config-doctor-9vjyj9m3.js");
18445
18598
  const fixResult = await runConfigDoctorWithFixes(directory, config, true);
18446
18599
  output = formatDoctorMarkdown(fixResult.result);
18447
18600
  } else {
@@ -18592,9 +18745,9 @@ function decideEpicActivation(tasks, cochangePairs, commitsObserved, options) {
18592
18745
  // src/turbo/epic/calibration.ts
18593
18746
  init_logger();
18594
18747
  import * as fs11 from "fs";
18595
- import * as path35 from "path";
18748
+ import * as path36 from "path";
18596
18749
  var STATE_FILE = "calibration.json";
18597
- var STATE_REL_DIR = path35.join(".swarm", "epic");
18750
+ var STATE_REL_DIR = path36.join(".swarm", "epic");
18598
18751
  function nowISO() {
18599
18752
  return new Date().toISOString();
18600
18753
  }
@@ -18616,7 +18769,7 @@ function markUnreadable(directory, reason) {
18616
18769
  error(`[epic/calibration] state file unreadable for ${directory}: ${reason} \u2014 failing closed`);
18617
18770
  }
18618
18771
  function repairCalibrationUnreadable(directory) {
18619
- const filePath = path35.join(directory, STATE_REL_DIR, STATE_FILE);
18772
+ const filePath = path36.join(directory, STATE_REL_DIR, STATE_FILE);
18620
18773
  if (!fs11.existsSync(filePath)) {
18621
18774
  stateUnreadableMap.delete(directory);
18622
18775
  return;
@@ -18648,7 +18801,7 @@ function isValidCalibrationShape(candidate) {
18648
18801
  return true;
18649
18802
  }
18650
18803
  function ensureSwarmEpicDir(directory) {
18651
- const dir = path35.resolve(directory, STATE_REL_DIR);
18804
+ const dir = path36.resolve(directory, STATE_REL_DIR);
18652
18805
  if (!fs11.existsSync(dir)) {
18653
18806
  fs11.mkdirSync(dir, { recursive: true });
18654
18807
  }
@@ -18660,7 +18813,7 @@ function loadCalibrationState(directory) {
18660
18813
  if (stateUnreadableMap.get(directory))
18661
18814
  return null;
18662
18815
  }
18663
- const filePath = path35.join(directory, STATE_REL_DIR, STATE_FILE);
18816
+ const filePath = path36.join(directory, STATE_REL_DIR, STATE_FILE);
18664
18817
  try {
18665
18818
  if (!fs11.existsSync(filePath)) {
18666
18819
  const seed = emptyCalibrationState();
@@ -18687,12 +18840,12 @@ function loadCalibrationState(directory) {
18687
18840
  // src/turbo/epic/divergence-recorder.ts
18688
18841
  init_logger();
18689
18842
  import * as fs12 from "fs";
18690
- import * as path36 from "path";
18691
- var EVIDENCE_REL_DIR = path36.join(".swarm", "epic");
18843
+ import * as path37 from "path";
18844
+ var EVIDENCE_REL_DIR = path37.join(".swarm", "epic");
18692
18845
  var EVIDENCE_FILE = "divergence.jsonl";
18693
18846
  var MAX_TAIL_BYTES2 = 16 * 1024 * 1024;
18694
18847
  function readDivergenceHistory(directory, options) {
18695
- const filePath = path36.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
18848
+ const filePath = path37.join(directory, EVIDENCE_REL_DIR, EVIDENCE_FILE);
18696
18849
  if (!fs12.existsSync(filePath)) {
18697
18850
  return [];
18698
18851
  }
@@ -18741,11 +18894,11 @@ function readDivergenceHistory(directory, options) {
18741
18894
 
18742
18895
  // src/turbo/epic/promotion-evidence.ts
18743
18896
  import * as fs13 from "fs";
18744
- import * as path37 from "path";
18745
- var EVIDENCE_REL_DIR2 = path37.join(".swarm", "evidence");
18897
+ import * as path38 from "path";
18898
+ var EVIDENCE_REL_DIR2 = path38.join(".swarm", "evidence");
18746
18899
  var EVIDENCE_FILE2 = "epic-promotions.jsonl";
18747
18900
  function readPromotionEvidence(directory) {
18748
- const filePath = path37.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
18901
+ const filePath = path38.join(directory, EVIDENCE_REL_DIR2, EVIDENCE_FILE2);
18749
18902
  if (!fs13.existsSync(filePath)) {
18750
18903
  return [];
18751
18904
  }
@@ -19319,7 +19472,7 @@ async function handleExportCommand(directory, _args) {
19319
19472
  // src/full-auto/state.ts
19320
19473
  var import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
19321
19474
  import * as fs14 from "fs";
19322
- import * as path38 from "path";
19475
+ import * as path39 from "path";
19323
19476
  init_logger();
19324
19477
  var lockfile3 = import_proper_lockfile3.default;
19325
19478
  var STATE_FILE2 = "full-auto-state.json";
@@ -19327,7 +19480,7 @@ function nowISO2() {
19327
19480
  return new Date().toISOString();
19328
19481
  }
19329
19482
  function ensureSwarmDir(directory) {
19330
- const swarmDir = path38.resolve(directory, ".swarm");
19483
+ const swarmDir = path39.resolve(directory, ".swarm");
19331
19484
  if (!fs14.existsSync(swarmDir)) {
19332
19485
  fs14.mkdirSync(swarmDir, { recursive: true });
19333
19486
  }
@@ -20139,7 +20292,7 @@ var _internals25 = {
20139
20292
 
20140
20293
  // src/session/snapshot-writer.ts
20141
20294
  import { closeSync as closeSync5, fsyncSync as fsyncSync2, mkdirSync as mkdirSync16, openSync as openSync5, renameSync as renameSync8 } from "fs";
20142
- import * as path39 from "path";
20295
+ import * as path40 from "path";
20143
20296
  var _writeInFlight = Promise.resolve();
20144
20297
  function serializeAgentSession(s) {
20145
20298
  const gateLog = {};
@@ -20252,7 +20405,7 @@ async function writeSnapshot(directory, state) {
20252
20405
  }
20253
20406
  const content = JSON.stringify(snapshot, null, 2);
20254
20407
  const resolvedPath = validateSwarmPath(directory, "session/state.json");
20255
- const dir = path39.dirname(resolvedPath);
20408
+ const dir = path40.dirname(resolvedPath);
20256
20409
  mkdirSync16(dir, { recursive: true });
20257
20410
  const tempPath = `${resolvedPath}.tmp.${Date.now()}.${Math.random().toString(36).slice(2)}`;
20258
20411
  await bunWrite(tempPath, content);
@@ -20780,10 +20933,10 @@ import { randomUUID as randomUUID7 } from "crypto";
20780
20933
  import { existsSync as existsSync27, readFileSync as readFileSync15 } from "fs";
20781
20934
  import { mkdir as mkdir10, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
20782
20935
  import * as os7 from "os";
20783
- import * as path40 from "path";
20936
+ import * as path41 from "path";
20784
20937
  async function migrateKnowledgeToExternal(_directory, _config) {
20785
- const externalSentinelPath = path40.join(_directory, ".swarm", ".knowledge-external-migrated");
20786
- const contextPath = path40.join(_directory, ".swarm", "context.md");
20938
+ const externalSentinelPath = path41.join(_directory, ".swarm", ".knowledge-external-migrated");
20939
+ const contextPath = path41.join(_directory, ".swarm", "context.md");
20787
20940
  if (_internals28.existsSync(externalSentinelPath)) {
20788
20941
  return {
20789
20942
  migrated: false,
@@ -20848,8 +21001,8 @@ var _internals28 = {
20848
21001
  writeFile: writeFile12
20849
21002
  };
20850
21003
  async function migrateContextToKnowledge(directory, config) {
20851
- const sentinelPath = path40.join(directory, ".swarm", ".knowledge-migrated");
20852
- const contextPath = path40.join(directory, ".swarm", "context.md");
21004
+ const sentinelPath = path41.join(directory, ".swarm", ".knowledge-migrated");
21005
+ const contextPath = path41.join(directory, ".swarm", "context.md");
20853
21006
  const knowledgePath = resolveSwarmKnowledgePath(directory);
20854
21007
  if (existsSync27(sentinelPath)) {
20855
21008
  return {
@@ -20951,7 +21104,7 @@ async function migrateContextToKnowledge(directory, config) {
20951
21104
  async function migrateHiveKnowledgeLegacy(config) {
20952
21105
  const legacyHivePath = _internals28.resolveLegacyHiveKnowledgePath();
20953
21106
  const canonicalHivePath = resolveHiveKnowledgePath();
20954
- const sentinelPath = path40.join(path40.dirname(canonicalHivePath), ".hive-knowledge-migrated");
21107
+ const sentinelPath = path41.join(path41.dirname(canonicalHivePath), ".hive-knowledge-migrated");
20955
21108
  if (existsSync27(sentinelPath)) {
20956
21109
  return {
20957
21110
  migrated: false,
@@ -21162,7 +21315,7 @@ function truncateLesson2(text) {
21162
21315
  return `${text.slice(0, 277)}...`;
21163
21316
  }
21164
21317
  function inferProjectName(directory) {
21165
- const packageJsonPath = path40.join(directory, "package.json");
21318
+ const packageJsonPath = path41.join(directory, "package.json");
21166
21319
  if (existsSync27(packageJsonPath)) {
21167
21320
  try {
21168
21321
  const pkg = JSON.parse(readFileSync15(packageJsonPath, "utf-8"));
@@ -21171,7 +21324,7 @@ function inferProjectName(directory) {
21171
21324
  }
21172
21325
  } catch {}
21173
21326
  }
21174
- return path40.basename(directory);
21327
+ return path41.basename(directory);
21175
21328
  }
21176
21329
  async function writeSentinel(sentinelPath, migrated, dropped) {
21177
21330
  const sentinel = {
@@ -21183,7 +21336,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
21183
21336
  schema_version: 1,
21184
21337
  migration_tool: "knowledge-migrator.ts"
21185
21338
  };
21186
- await _internals28.mkdir(path40.dirname(sentinelPath), { recursive: true });
21339
+ await _internals28.mkdir(path41.dirname(sentinelPath), { recursive: true });
21187
21340
  await _internals28.writeFile(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
21188
21341
  }
21189
21342
  function resolveLegacyHiveKnowledgePath() {
@@ -21191,13 +21344,13 @@ function resolveLegacyHiveKnowledgePath() {
21191
21344
  const home = process.env.HOME || os7.homedir();
21192
21345
  let dataDir;
21193
21346
  if (platform === "win32") {
21194
- dataDir = path40.join(process.env.LOCALAPPDATA || path40.join(home, "AppData", "Local"), "opencode-swarm", "Data");
21347
+ dataDir = path41.join(process.env.LOCALAPPDATA || path41.join(home, "AppData", "Local"), "opencode-swarm", "Data");
21195
21348
  } else if (platform === "darwin") {
21196
- dataDir = path40.join(home, "Library", "Application Support", "opencode-swarm");
21349
+ dataDir = path41.join(home, "Library", "Application Support", "opencode-swarm");
21197
21350
  } else {
21198
- dataDir = path40.join(process.env.XDG_DATA_HOME || path40.join(home, ".local", "share"), "opencode-swarm");
21351
+ dataDir = path41.join(process.env.XDG_DATA_HOME || path41.join(home, ".local", "share"), "opencode-swarm");
21199
21352
  }
21200
- return path40.join(dataDir, "hive-knowledge.jsonl");
21353
+ return path41.join(dataDir, "hive-knowledge.jsonl");
21201
21354
  }
21202
21355
 
21203
21356
  // src/commands/knowledge.ts
@@ -21628,14 +21781,14 @@ var _internals29 = {
21628
21781
 
21629
21782
  // src/commands/link.ts
21630
21783
  import { existsSync as existsSync28 } from "fs";
21631
- import * as path42 from "path";
21784
+ import * as path43 from "path";
21632
21785
 
21633
21786
  // src/knowledge/identity.ts
21634
21787
  import * as child_process7 from "child_process";
21635
21788
  import { createHash as createHash5 } from "crypto";
21636
- import * as path41 from "path";
21789
+ import * as path42 from "path";
21637
21790
  function deriveProjectHash(directory) {
21638
- const absolutePath = path41.resolve(directory);
21791
+ const absolutePath = path42.resolve(directory);
21639
21792
  let hashInput;
21640
21793
  try {
21641
21794
  const remoteUrl = child_process7.execSync("git remote get-url origin", {
@@ -21655,8 +21808,8 @@ function deriveProjectHash(directory) {
21655
21808
  // src/commands/link.ts
21656
21809
  var DEDUP_THRESHOLD = 0.6;
21657
21810
  async function mergeLocalKnowledgeIntoLink(localSwarmDir, linkDir) {
21658
- const localPath = path42.join(localSwarmDir, "knowledge.jsonl");
21659
- const sharedPath = path42.join(linkDir, "knowledge.jsonl");
21811
+ const localPath = path43.join(localSwarmDir, "knowledge.jsonl");
21812
+ const sharedPath = path43.join(linkDir, "knowledge.jsonl");
21660
21813
  if (!existsSync28(localPath))
21661
21814
  return { merged: 0, skipped: 0 };
21662
21815
  let merged = 0;
@@ -21754,7 +21907,7 @@ ${formatStatus(directory)}`;
21754
21907
  const linkDir = resolveLinkDir(linkId);
21755
21908
  let merge;
21756
21909
  try {
21757
- merge = await mergeLocalKnowledgeIntoLink(path42.join(directory, ".swarm"), linkDir);
21910
+ merge = await mergeLocalKnowledgeIntoLink(path43.join(directory, ".swarm"), linkDir);
21758
21911
  } catch (error2) {
21759
21912
  return `\u274C Failed to merge local knowledge into the link store: ${error2 instanceof Error ? error2.message : String(error2)}`;
21760
21913
  }
@@ -21951,12 +22104,12 @@ ${USAGE7}`;
21951
22104
 
21952
22105
  // src/commands/memory.ts
21953
22106
  import { existsSync as existsSync29 } from "fs";
21954
- import * as path45 from "path";
22107
+ import * as path46 from "path";
21955
22108
  import { fileURLToPath as fileURLToPath2 } from "url";
21956
22109
  // src/memory/evaluation.ts
21957
22110
  import * as fs15 from "fs/promises";
21958
22111
  import * as os8 from "os";
21959
- import * as path43 from "path";
22112
+ import * as path44 from "path";
21960
22113
  var DEFAULT_PROVIDERS = [
21961
22114
  "local-jsonl",
21962
22115
  "sqlite"
@@ -21968,7 +22121,7 @@ var DEFAULT_MODES = [
21968
22121
  ];
21969
22122
  var DEFAULT_TIMESTAMP = "2026-05-26T12:00:00.000Z";
21970
22123
  async function evaluateMemoryRecallFixtures(options) {
21971
- const fixtureDirectory = path43.resolve(options.fixtureDirectory);
22124
+ const fixtureDirectory = path44.resolve(options.fixtureDirectory);
21972
22125
  const providers = options.providers ?? DEFAULT_PROVIDERS;
21973
22126
  const modes = options.modes ?? DEFAULT_MODES;
21974
22127
  const generatedAt = new Date().toISOString();
@@ -21977,7 +22130,7 @@ async function evaluateMemoryRecallFixtures(options) {
21977
22130
  for (const fixture of fixtures) {
21978
22131
  const materialized = materializeFixture(fixture);
21979
22132
  for (const providerName of providers) {
21980
- const tempRoot = await fs15.realpath(await fs15.mkdtemp(path43.join(os8.tmpdir(), "swarm-memory-eval-")));
22133
+ const tempRoot = await fs15.realpath(await fs15.mkdtemp(path44.join(os8.tmpdir(), "swarm-memory-eval-")));
21981
22134
  const provider = createEvaluationProvider(providerName, tempRoot);
21982
22135
  try {
21983
22136
  await provider.initialize?.();
@@ -22034,7 +22187,7 @@ async function loadRecallEvaluationFixtures(fixtureDirectory) {
22034
22187
  const files = entries.filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort((a, b) => a.localeCompare(b));
22035
22188
  const fixtures = [];
22036
22189
  for (const file of files) {
22037
- const raw = await fs15.readFile(path43.join(fixtureDirectory, file), "utf-8");
22190
+ const raw = await fs15.readFile(path44.join(fixtureDirectory, file), "utf-8");
22038
22191
  fixtures.push(validateFixture(JSON.parse(raw), file));
22039
22192
  }
22040
22193
  return fixtures;
@@ -22311,8 +22464,8 @@ var CuratorOutputMemoryDecisionSchema = exports_external.object({
22311
22464
  }).passthrough();
22312
22465
  // src/memory/consolidation-log.ts
22313
22466
  import { appendFile as appendFile3, mkdir as mkdir11, readFile as readFile15 } from "fs/promises";
22314
- import * as path44 from "path";
22315
- var LOG_RELATIVE_PATH = path44.join("memory", "consolidation-log.jsonl");
22467
+ import * as path45 from "path";
22468
+ var LOG_RELATIVE_PATH = path45.join("memory", "consolidation-log.jsonl");
22316
22469
  async function readConsolidationLog(directory) {
22317
22470
  const filePath = validateSwarmPath(directory, LOG_RELATIVE_PATH);
22318
22471
  let raw;
@@ -22335,7 +22488,7 @@ async function readConsolidationLog(directory) {
22335
22488
  }
22336
22489
 
22337
22490
  // src/commands/memory.ts
22338
- var PACKAGE_ROOT = path45.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
22491
+ var PACKAGE_ROOT = path46.resolve(resolvePackageRootFromModule(fileURLToPath2(import.meta.url)));
22339
22492
  async function handleMemoryCommand(_directory, _args) {
22340
22493
  return [
22341
22494
  "## Swarm Memory",
@@ -22692,7 +22845,7 @@ function resolveCommandMemoryConfig(directory) {
22692
22845
  }
22693
22846
  function parseEvaluateArgs(directory, args) {
22694
22847
  let json = false;
22695
- let fixtureDirectory = path45.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
22848
+ let fixtureDirectory = path46.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall");
22696
22849
  for (let i = 0;i < args.length; i++) {
22697
22850
  const arg = args[i];
22698
22851
  if (arg === "--json") {
@@ -22706,10 +22859,10 @@ function parseEvaluateArgs(directory, args) {
22706
22859
  error: "Usage: /swarm memory evaluate [--json] [--fixtures <directory>]"
22707
22860
  };
22708
22861
  }
22709
- const resolvedFixtures = path45.resolve(directory, next);
22710
- const canonical = path45.normalize(resolvedFixtures) + path45.sep;
22711
- const allowedRootA = path45.normalize(directory) + path45.sep;
22712
- const allowedRootB = path45.normalize(path45.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path45.sep;
22862
+ const resolvedFixtures = path46.resolve(directory, next);
22863
+ const canonical = path46.normalize(resolvedFixtures) + path46.sep;
22864
+ const allowedRootA = path46.normalize(directory) + path46.sep;
22865
+ const allowedRootB = path46.normalize(path46.join(PACKAGE_ROOT, "tests", "fixtures", "memory-recall")) + path46.sep;
22713
22866
  if (!canonical.startsWith(allowedRootA) && !canonical.startsWith(allowedRootB)) {
22714
22867
  return {
22715
22868
  error: "--fixtures <directory> must resolve under the project directory or the bundled tests/fixtures/memory-recall directory"
@@ -22748,15 +22901,15 @@ function parseMaintenanceArgs(args, options) {
22748
22901
  return { limit, confirm };
22749
22902
  }
22750
22903
  function resolvePackageRootFromModule(modulePath) {
22751
- const moduleDir = path45.dirname(modulePath);
22752
- const leaf = path45.basename(moduleDir);
22904
+ const moduleDir = path46.dirname(modulePath);
22905
+ const leaf = path46.basename(moduleDir);
22753
22906
  if (leaf === "commands" || leaf === "cli") {
22754
- return path45.resolve(moduleDir, "..", "..");
22907
+ return path46.resolve(moduleDir, "..", "..");
22755
22908
  }
22756
22909
  if (leaf === "dist") {
22757
- return path45.resolve(moduleDir, "..");
22910
+ return path46.resolve(moduleDir, "..");
22758
22911
  }
22759
- return path45.resolve(moduleDir, "..");
22912
+ return path46.resolve(moduleDir, "..");
22760
22913
  }
22761
22914
  function formatMigrationResult(label, report) {
22762
22915
  if (!report) {
@@ -23491,11 +23644,11 @@ var _internals35 = {
23491
23644
 
23492
23645
  // src/services/preflight-service.ts
23493
23646
  import * as fs22 from "fs";
23494
- import * as path52 from "path";
23647
+ import * as path53 from "path";
23495
23648
 
23496
23649
  // src/tools/lint.ts
23497
23650
  import * as fs16 from "fs";
23498
- import * as path46 from "path";
23651
+ import * as path47 from "path";
23499
23652
 
23500
23653
  // src/utils/path-security.ts
23501
23654
  function containsPathTraversal(str) {
@@ -23551,9 +23704,9 @@ function validateArgs(args) {
23551
23704
  }
23552
23705
  function getLinterCommand(linter, mode, projectDir) {
23553
23706
  const isWindows = process.platform === "win32";
23554
- const binDir = path46.join(projectDir, "node_modules", ".bin");
23555
- const biomeBin = isWindows ? path46.join(binDir, "biome.EXE") : path46.join(binDir, "biome");
23556
- const eslintBin = isWindows ? path46.join(binDir, "eslint.cmd") : path46.join(binDir, "eslint");
23707
+ const binDir = path47.join(projectDir, "node_modules", ".bin");
23708
+ const biomeBin = isWindows ? path47.join(binDir, "biome.EXE") : path47.join(binDir, "biome");
23709
+ const eslintBin = isWindows ? path47.join(binDir, "eslint.cmd") : path47.join(binDir, "eslint");
23557
23710
  switch (linter) {
23558
23711
  case "biome":
23559
23712
  if (mode === "fix") {
@@ -23569,7 +23722,7 @@ function getLinterCommand(linter, mode, projectDir) {
23569
23722
  }
23570
23723
  function getAdditionalLinterCommand(linter, mode, cwd) {
23571
23724
  const gradlewName = process.platform === "win32" ? "gradlew.bat" : "gradlew";
23572
- const gradlew = fs16.existsSync(path46.join(cwd, gradlewName)) ? path46.join(cwd, gradlewName) : null;
23725
+ const gradlew = fs16.existsSync(path47.join(cwd, gradlewName)) ? path47.join(cwd, gradlewName) : null;
23573
23726
  switch (linter) {
23574
23727
  case "ruff":
23575
23728
  return mode === "fix" ? ["ruff", "check", "--fix", "."] : ["ruff", "check", "."];
@@ -23611,10 +23764,10 @@ function getAdditionalLinterCommand(linter, mode, cwd) {
23611
23764
  }
23612
23765
  }
23613
23766
  function detectRuff(cwd) {
23614
- if (fs16.existsSync(path46.join(cwd, "ruff.toml")))
23767
+ if (fs16.existsSync(path47.join(cwd, "ruff.toml")))
23615
23768
  return isCommandAvailable("ruff");
23616
23769
  try {
23617
- const pyproject = path46.join(cwd, "pyproject.toml");
23770
+ const pyproject = path47.join(cwd, "pyproject.toml");
23618
23771
  if (fs16.existsSync(pyproject)) {
23619
23772
  const content = fs16.readFileSync(pyproject, "utf-8");
23620
23773
  if (content.includes("[tool.ruff]"))
@@ -23624,10 +23777,10 @@ function detectRuff(cwd) {
23624
23777
  return false;
23625
23778
  }
23626
23779
  function detectClippy(cwd) {
23627
- return fs16.existsSync(path46.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
23780
+ return fs16.existsSync(path47.join(cwd, "Cargo.toml")) && isCommandAvailable("cargo");
23628
23781
  }
23629
23782
  function detectGolangciLint(cwd) {
23630
- return fs16.existsSync(path46.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
23783
+ return fs16.existsSync(path47.join(cwd, "go.mod")) && isCommandAvailable("golangci-lint");
23631
23784
  }
23632
23785
  function readTextFileSafe(filePath) {
23633
23786
  try {
@@ -23638,18 +23791,18 @@ function readTextFileSafe(filePath) {
23638
23791
  }
23639
23792
  function phpVendorBin(_cwd, name) {
23640
23793
  const fileName = process.platform === "win32" ? `${name}.bat` : name;
23641
- return path46.join("vendor", "bin", fileName);
23794
+ return path47.join("vendor", "bin", fileName);
23642
23795
  }
23643
23796
  function phpVendorBinExists(cwd, name) {
23644
- const local = path46.join(cwd, "vendor", "bin", name);
23645
- const localWin = path46.join(cwd, "vendor", "bin", `${name}.bat`);
23797
+ const local = path47.join(cwd, "vendor", "bin", name);
23798
+ const localWin = path47.join(cwd, "vendor", "bin", `${name}.bat`);
23646
23799
  return fs16.existsSync(local) || fs16.existsSync(localWin);
23647
23800
  }
23648
23801
  function detectCheckstyle(cwd) {
23649
- const hasMaven = fs16.existsSync(path46.join(cwd, "pom.xml"));
23650
- const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path46.join(cwd, file)).filter((file) => fs16.existsSync(file));
23651
- const hasGradleCheckstyleSignal = fs16.existsSync(path46.join(cwd, "checkstyle.xml")) || fs16.existsSync(path46.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
23652
- const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs16.existsSync(path46.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
23802
+ const hasMaven = fs16.existsSync(path47.join(cwd, "pom.xml"));
23803
+ const gradleFiles = ["build.gradle", "build.gradle.kts"].map((file) => path47.join(cwd, file)).filter((file) => fs16.existsSync(file));
23804
+ const hasGradleCheckstyleSignal = fs16.existsSync(path47.join(cwd, "checkstyle.xml")) || fs16.existsSync(path47.join(cwd, "config", "checkstyle", "checkstyle.xml")) || gradleFiles.some((file) => /\bcheckstyle\b/i.test(readTextFileSafe(file)));
23805
+ const hasBinary = hasMaven && isCommandAvailable("mvn") || hasGradleCheckstyleSignal && (fs16.existsSync(path47.join(cwd, "gradlew")) || isCommandAvailable("gradle"));
23653
23806
  return (hasMaven || hasGradleCheckstyleSignal) && hasBinary;
23654
23807
  }
23655
23808
  function hasRootKotlinFile(cwd) {
@@ -23660,24 +23813,24 @@ function hasRootKotlinFile(cwd) {
23660
23813
  }
23661
23814
  }
23662
23815
  function buildGradleHasKotlinSignal(cwd) {
23663
- const content = readTextFileSafe(path46.join(cwd, "build.gradle"));
23816
+ const content = readTextFileSafe(path47.join(cwd, "build.gradle"));
23664
23817
  return /\b(kotlin|org\.jetbrains\.kotlin|ktlint)\b/i.test(content);
23665
23818
  }
23666
23819
  function detectKtlint(cwd) {
23667
- const hasKotlin = fs16.existsSync(path46.join(cwd, "build.gradle.kts")) || fs16.existsSync(path46.join(cwd, "build.gradle")) && buildGradleHasKotlinSignal(cwd) || hasRootKotlinFile(cwd);
23820
+ const hasKotlin = fs16.existsSync(path47.join(cwd, "build.gradle.kts")) || fs16.existsSync(path47.join(cwd, "build.gradle")) && buildGradleHasKotlinSignal(cwd) || hasRootKotlinFile(cwd);
23668
23821
  return hasKotlin && isCommandAvailable("ktlint");
23669
23822
  }
23670
23823
  function detectPhpLinter(cwd) {
23671
- if ((fs16.existsSync(path46.join(cwd, "phpstan.neon")) || fs16.existsSync(path46.join(cwd, "phpstan.neon.dist"))) && phpVendorBinExists(cwd, "phpstan")) {
23824
+ if ((fs16.existsSync(path47.join(cwd, "phpstan.neon")) || fs16.existsSync(path47.join(cwd, "phpstan.neon.dist"))) && phpVendorBinExists(cwd, "phpstan")) {
23672
23825
  return "phpstan";
23673
23826
  }
23674
- if (fs16.existsSync(path46.join(cwd, "pint.json")) && phpVendorBinExists(cwd, "pint")) {
23827
+ if (fs16.existsSync(path47.join(cwd, "pint.json")) && phpVendorBinExists(cwd, "pint")) {
23675
23828
  return "pint";
23676
23829
  }
23677
- if (fs16.existsSync(path46.join(cwd, ".php-cs-fixer.php")) && phpVendorBinExists(cwd, "php-cs-fixer")) {
23830
+ if (fs16.existsSync(path47.join(cwd, ".php-cs-fixer.php")) && phpVendorBinExists(cwd, "php-cs-fixer")) {
23678
23831
  return "php-cs-fixer";
23679
23832
  }
23680
- if (fs16.existsSync(path46.join(cwd, "phpcs.xml")) && phpVendorBinExists(cwd, "phpcs")) {
23833
+ if (fs16.existsSync(path47.join(cwd, "phpcs.xml")) && phpVendorBinExists(cwd, "phpcs")) {
23681
23834
  return "phpcs";
23682
23835
  }
23683
23836
  return null;
@@ -23692,11 +23845,11 @@ function detectDotnetFormat(cwd) {
23692
23845
  }
23693
23846
  }
23694
23847
  function detectCppcheck(cwd) {
23695
- if (fs16.existsSync(path46.join(cwd, "CMakeLists.txt"))) {
23848
+ if (fs16.existsSync(path47.join(cwd, "CMakeLists.txt"))) {
23696
23849
  return isCommandAvailable("cppcheck");
23697
23850
  }
23698
23851
  try {
23699
- const dirsToCheck = [cwd, path46.join(cwd, "src")];
23852
+ const dirsToCheck = [cwd, path47.join(cwd, "src")];
23700
23853
  const hasCpp = dirsToCheck.some((dir) => {
23701
23854
  try {
23702
23855
  return fs16.readdirSync(dir).some((f) => /\.(c|cpp|cc|cxx|h|hpp)$/.test(f));
@@ -23710,13 +23863,13 @@ function detectCppcheck(cwd) {
23710
23863
  }
23711
23864
  }
23712
23865
  function detectSwiftlint(cwd) {
23713
- return fs16.existsSync(path46.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
23866
+ return fs16.existsSync(path47.join(cwd, "Package.swift")) && isCommandAvailable("swiftlint");
23714
23867
  }
23715
23868
  function detectDartAnalyze(cwd) {
23716
- return fs16.existsSync(path46.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
23869
+ return fs16.existsSync(path47.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
23717
23870
  }
23718
23871
  function detectRubocop(cwd) {
23719
- return (fs16.existsSync(path46.join(cwd, "Gemfile")) || fs16.existsSync(path46.join(cwd, "gems.rb")) || fs16.existsSync(path46.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
23872
+ return (fs16.existsSync(path47.join(cwd, "Gemfile")) || fs16.existsSync(path47.join(cwd, "gems.rb")) || fs16.existsSync(path47.join(cwd, ".rubocop.yml"))) && (isCommandAvailable("rubocop") || isCommandAvailable("bundle"));
23720
23873
  }
23721
23874
  function detectAdditionalLinter(cwd) {
23722
23875
  if (detectRuff(cwd))
@@ -23747,10 +23900,10 @@ function detectAdditionalLinter(cwd) {
23747
23900
  function findBinInAncestors(startDir, binName) {
23748
23901
  let dir = startDir;
23749
23902
  while (true) {
23750
- const candidate = path46.join(dir, "node_modules", ".bin", binName);
23903
+ const candidate = path47.join(dir, "node_modules", ".bin", binName);
23751
23904
  if (fs16.existsSync(candidate))
23752
23905
  return candidate;
23753
- const parent = path46.dirname(dir);
23906
+ const parent = path47.dirname(dir);
23754
23907
  if (parent === dir)
23755
23908
  break;
23756
23909
  dir = parent;
@@ -23759,10 +23912,10 @@ function findBinInAncestors(startDir, binName) {
23759
23912
  }
23760
23913
  function findBinInEnvPath(binName) {
23761
23914
  const searchPath = process.env.PATH ?? "";
23762
- for (const dir of searchPath.split(path46.delimiter)) {
23915
+ for (const dir of searchPath.split(path47.delimiter)) {
23763
23916
  if (!dir)
23764
23917
  continue;
23765
- const candidate = path46.join(dir, binName);
23918
+ const candidate = path47.join(dir, binName);
23766
23919
  if (fs16.existsSync(candidate))
23767
23920
  return candidate;
23768
23921
  }
@@ -23775,13 +23928,13 @@ async function detectAvailableLinter(directory) {
23775
23928
  return null;
23776
23929
  const projectDir = directory;
23777
23930
  const isWindows = process.platform === "win32";
23778
- const biomeBin = isWindows ? path46.join(projectDir, "node_modules", ".bin", "biome.EXE") : path46.join(projectDir, "node_modules", ".bin", "biome");
23779
- const eslintBin = isWindows ? path46.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path46.join(projectDir, "node_modules", ".bin", "eslint");
23931
+ const biomeBin = isWindows ? path47.join(projectDir, "node_modules", ".bin", "biome.EXE") : path47.join(projectDir, "node_modules", ".bin", "biome");
23932
+ const eslintBin = isWindows ? path47.join(projectDir, "node_modules", ".bin", "eslint.cmd") : path47.join(projectDir, "node_modules", ".bin", "eslint");
23780
23933
  const localResult = await _detectAvailableLinter(projectDir, biomeBin, eslintBin);
23781
23934
  if (localResult)
23782
23935
  return localResult;
23783
- const biomeAncestor = findBinInAncestors(path46.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
23784
- const eslintAncestor = findBinInAncestors(path46.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
23936
+ const biomeAncestor = findBinInAncestors(path47.dirname(projectDir), isWindows ? "biome.EXE" : "biome");
23937
+ const eslintAncestor = findBinInAncestors(path47.dirname(projectDir), isWindows ? "eslint.cmd" : "eslint");
23785
23938
  if (biomeAncestor || eslintAncestor) {
23786
23939
  return _detectAvailableLinter(projectDir, biomeAncestor ?? biomeBin, eslintAncestor ?? eslintBin);
23787
23940
  }
@@ -23995,7 +24148,7 @@ var _internals36 = {
23995
24148
 
23996
24149
  // src/tools/secretscan.ts
23997
24150
  import * as fs17 from "fs";
23998
- import * as path47 from "path";
24151
+ import * as path48 from "path";
23999
24152
  var MAX_FILE_PATH_LENGTH = 500;
24000
24153
  var MAX_FILE_SIZE_BYTES = 512 * 1024;
24001
24154
  var MAX_FILES_SCANNED = 1000;
@@ -24222,7 +24375,7 @@ function isGlobOrPathPattern(pattern) {
24222
24375
  return pattern.includes("/") || pattern.includes("\\") || /[*?[\]{}]/.test(pattern);
24223
24376
  }
24224
24377
  function loadSecretScanIgnore(scanDir) {
24225
- const ignorePath = path47.join(scanDir, ".secretscanignore");
24378
+ const ignorePath = path48.join(scanDir, ".secretscanignore");
24226
24379
  try {
24227
24380
  if (!fs17.existsSync(ignorePath))
24228
24381
  return [];
@@ -24245,7 +24398,7 @@ function isExcluded(entry, relPath, exactNames, globPatterns) {
24245
24398
  if (exactNames.has(entry))
24246
24399
  return true;
24247
24400
  for (const pattern of globPatterns) {
24248
- if (path47.matchesGlob(relPath, pattern))
24401
+ if (path48.matchesGlob(relPath, pattern))
24249
24402
  return true;
24250
24403
  }
24251
24404
  return false;
@@ -24266,7 +24419,7 @@ function validateDirectoryInput(dir) {
24266
24419
  return null;
24267
24420
  }
24268
24421
  function isBinaryFile(filePath, buffer) {
24269
- const ext = path47.extname(filePath).toLowerCase();
24422
+ const ext = path48.extname(filePath).toLowerCase();
24270
24423
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
24271
24424
  return true;
24272
24425
  }
@@ -24403,9 +24556,9 @@ function isSymlinkLoop(realPath, visited) {
24403
24556
  return false;
24404
24557
  }
24405
24558
  function isPathWithinScope(realPath, scanDir) {
24406
- const resolvedScanDir = path47.resolve(scanDir);
24407
- const resolvedRealPath = path47.resolve(realPath);
24408
- return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path47.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
24559
+ const resolvedScanDir = path48.resolve(scanDir);
24560
+ const resolvedRealPath = path48.resolve(realPath);
24561
+ return resolvedRealPath === resolvedScanDir || resolvedRealPath.startsWith(resolvedScanDir + path48.sep) || resolvedRealPath.startsWith(`${resolvedScanDir}/`) || resolvedRealPath.startsWith(`${resolvedScanDir}\\`);
24409
24562
  }
24410
24563
  function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, stats = {
24411
24564
  skippedDirs: 0,
@@ -24431,8 +24584,8 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
24431
24584
  return a.localeCompare(b);
24432
24585
  });
24433
24586
  for (const entry of entries) {
24434
- const fullPath = path47.join(dir, entry);
24435
- const relPath = path47.relative(scanDir, fullPath).replace(/\\/g, "/");
24587
+ const fullPath = path48.join(dir, entry);
24588
+ const relPath = path48.relative(scanDir, fullPath).replace(/\\/g, "/");
24436
24589
  if (isExcluded(entry, relPath, excludeExact, excludeGlobs)) {
24437
24590
  stats.skippedDirs++;
24438
24591
  continue;
@@ -24467,7 +24620,7 @@ function findScannableFiles(dir, excludeExact, excludeGlobs, scanDir, visited, s
24467
24620
  const subFiles = findScannableFiles(fullPath, excludeExact, excludeGlobs, scanDir, visited, stats);
24468
24621
  files.push(...subFiles);
24469
24622
  } else if (lstat2.isFile()) {
24470
- const ext = path47.extname(fullPath).toLowerCase();
24623
+ const ext = path48.extname(fullPath).toLowerCase();
24471
24624
  if (!DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
24472
24625
  files.push(fullPath);
24473
24626
  } else {
@@ -24533,7 +24686,7 @@ var secretscan = createSwarmTool({
24533
24686
  }
24534
24687
  }
24535
24688
  try {
24536
- const _scanDirRaw = path47.resolve(directory);
24689
+ const _scanDirRaw = path48.resolve(directory);
24537
24690
  const scanDir = (() => {
24538
24691
  try {
24539
24692
  return fs17.realpathSync(_scanDirRaw);
@@ -24699,12 +24852,12 @@ async function runSecretscanOnFiles(files, directory) {
24699
24852
  skippedFiles++;
24700
24853
  continue;
24701
24854
  }
24702
- const resolvedPath = path47.isAbsolute(file) ? path47.resolve(file) : path47.resolve(directory, file);
24855
+ const resolvedPath = path48.isAbsolute(file) ? path48.resolve(file) : path48.resolve(directory, file);
24703
24856
  if (!isPathWithinScope(resolvedPath, directory)) {
24704
24857
  skippedFiles++;
24705
24858
  continue;
24706
24859
  }
24707
- const ext = path47.extname(resolvedPath).toLowerCase();
24860
+ const ext = path48.extname(resolvedPath).toLowerCase();
24708
24861
  if (DEFAULT_EXCLUDE_EXTENSIONS.has(ext)) {
24709
24862
  skippedFiles++;
24710
24863
  continue;
@@ -24755,11 +24908,11 @@ var _internals37 = {
24755
24908
 
24756
24909
  // src/tools/test-runner.ts
24757
24910
  import * as fs21 from "fs";
24758
- import * as path51 from "path";
24911
+ import * as path52 from "path";
24759
24912
 
24760
24913
  // src/test-impact/analyzer.ts
24761
24914
  import fs18 from "fs";
24762
- import path48 from "path";
24915
+ import path49 from "path";
24763
24916
  var IMPORT_REGEX_ES = /import\s+[\s\S]*?\s+from\s+['"]([^'"]+)['"]/g;
24764
24917
  var IMPORT_REGEX_REQUIRE = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
24765
24918
  var IMPORT_REGEX_REEXPORT = /export\s+(?:\{[^}]*\}|\*)\s+from\s+['"]([^'"]+)['"]/g;
@@ -24800,8 +24953,8 @@ function resolveRelativeImport(fromDir, importPath) {
24800
24953
  if (!importPath.startsWith(".")) {
24801
24954
  return null;
24802
24955
  }
24803
- const resolved = path48.resolve(fromDir, importPath);
24804
- if (path48.extname(resolved)) {
24956
+ const resolved = path49.resolve(fromDir, importPath);
24957
+ if (path49.extname(resolved)) {
24805
24958
  if (fs18.existsSync(resolved) && fs18.statSync(resolved).isFile()) {
24806
24959
  return normalizePath2(resolved);
24807
24960
  }
@@ -24821,20 +24974,20 @@ function resolvePythonImport(fromDir, module) {
24821
24974
  const leadingDots = module.match(/^\.+/)?.[0].length ?? 0;
24822
24975
  let baseDir = fromDir;
24823
24976
  for (let i = 1;i < leadingDots; i++) {
24824
- baseDir = path48.dirname(baseDir);
24977
+ baseDir = path49.dirname(baseDir);
24825
24978
  }
24826
24979
  const rest = module.slice(leadingDots);
24827
24980
  if (rest.length === 0) {
24828
- const initPath = path48.join(baseDir, "__init__.py");
24981
+ const initPath = path49.join(baseDir, "__init__.py");
24829
24982
  if (fs18.existsSync(initPath) && fs18.statSync(initPath).isFile()) {
24830
24983
  return normalizePath2(initPath);
24831
24984
  }
24832
24985
  return null;
24833
24986
  }
24834
- const subpath = rest.replace(/\./g, path48.sep);
24987
+ const subpath = rest.replace(/\./g, path49.sep);
24835
24988
  const candidates = [
24836
- `${path48.join(baseDir, subpath)}.py`,
24837
- path48.join(baseDir, subpath, "__init__.py")
24989
+ `${path49.join(baseDir, subpath)}.py`,
24990
+ path49.join(baseDir, subpath, "__init__.py")
24838
24991
  ];
24839
24992
  for (const c of candidates) {
24840
24993
  if (fs18.existsSync(c) && fs18.statSync(c).isFile())
@@ -24844,7 +24997,7 @@ function resolvePythonImport(fromDir, module) {
24844
24997
  }
24845
24998
  var goModuleCache = new Map;
24846
24999
  function findGoModule(fromDir) {
24847
- const resolved = path48.resolve(fromDir);
25000
+ const resolved = path49.resolve(fromDir);
24848
25001
  let cur = resolved;
24849
25002
  const walked = [];
24850
25003
  for (let i = 0;i < 16; i++) {
@@ -24856,7 +25009,7 @@ function findGoModule(fromDir) {
24856
25009
  }
24857
25010
  walked.push(cur);
24858
25011
  try {
24859
- const goMod = path48.join(cur, "go.mod");
25012
+ const goMod = path49.join(cur, "go.mod");
24860
25013
  const content = fs18.readFileSync(goMod, "utf-8");
24861
25014
  const moduleMatch = content.match(/^\s*module\s+"?([^"\s/]+(?:\/[^"\s]+)*)"?/m);
24862
25015
  if (moduleMatch) {
@@ -24867,10 +25020,10 @@ function findGoModule(fromDir) {
24867
25020
  }
24868
25021
  } catch {}
24869
25022
  try {
24870
- fs18.accessSync(path48.join(cur, ".git"));
25023
+ fs18.accessSync(path49.join(cur, ".git"));
24871
25024
  break;
24872
25025
  } catch {}
24873
- const parent = path48.dirname(cur);
25026
+ const parent = path49.dirname(cur);
24874
25027
  if (parent === cur)
24875
25028
  break;
24876
25029
  cur = parent;
@@ -24882,12 +25035,12 @@ function findGoModule(fromDir) {
24882
25035
  function resolveGoImport(fromDir, importPath) {
24883
25036
  let dir = null;
24884
25037
  if (importPath.startsWith(".")) {
24885
- dir = path48.resolve(fromDir, importPath);
25038
+ dir = path49.resolve(fromDir, importPath);
24886
25039
  } else {
24887
25040
  const mod = findGoModule(fromDir);
24888
25041
  if (mod && (importPath === mod.modulePath || importPath.startsWith(`${mod.modulePath}/`))) {
24889
25042
  const subpath = importPath.slice(mod.modulePath.length);
24890
- dir = path48.join(mod.moduleRoot, subpath);
25043
+ dir = path49.join(mod.moduleRoot, subpath);
24891
25044
  }
24892
25045
  }
24893
25046
  if (dir === null)
@@ -24895,7 +25048,7 @@ function resolveGoImport(fromDir, importPath) {
24895
25048
  if (!fs18.existsSync(dir) || !fs18.statSync(dir).isDirectory())
24896
25049
  return [];
24897
25050
  try {
24898
- return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path48.join(dir, f)));
25051
+ return fs18.readdirSync(dir).filter((f) => f.endsWith(".go") && !f.endsWith("_test.go")).map((f) => normalizePath2(path49.join(dir, f)));
24899
25052
  } catch {
24900
25053
  return [];
24901
25054
  }
@@ -24934,15 +25087,15 @@ function findTestFilesSync(cwd) {
24934
25087
  for (const entry of entries) {
24935
25088
  if (entry.isDirectory()) {
24936
25089
  if (!skipDirs.has(entry.name)) {
24937
- walk(path48.join(dir, entry.name), visitedInodes);
25090
+ walk(path49.join(dir, entry.name), visitedInodes);
24938
25091
  }
24939
25092
  } else if (entry.isFile()) {
24940
25093
  const name = entry.name;
24941
25094
  const isTsTest = /\.(test|spec)\.(ts|tsx|js|jsx)$/.test(name) || dir.includes("__tests__") && /\.(ts|tsx|js|jsx)$/.test(name);
24942
- const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path48.sep}tests${path48.sep}`) && name.endsWith(".py");
25095
+ const isPyTest = /^test_.+\.py$/.test(name) || /.+_test\.py$/.test(name) || dir.includes(`${path49.sep}tests${path49.sep}`) && name.endsWith(".py");
24943
25096
  const isGoTest = /.+_test\.go$/.test(name);
24944
25097
  if (isTsTest || isPyTest || isGoTest) {
24945
- testFiles.push(normalizePath2(path48.join(dir, entry.name)));
25098
+ testFiles.push(normalizePath2(path49.join(dir, entry.name)));
24946
25099
  }
24947
25100
  }
24948
25101
  }
@@ -24967,8 +25120,8 @@ function extractImports(content) {
24967
25120
  ];
24968
25121
  }
24969
25122
  function addImpactEdgesForTestFile(testFile, content, impactMap) {
24970
- const ext = path48.extname(testFile).toLowerCase();
24971
- const testDir = path48.dirname(testFile);
25123
+ const ext = path49.extname(testFile).toLowerCase();
25124
+ const testDir = path49.dirname(testFile);
24972
25125
  function addEdge(source) {
24973
25126
  if (!impactMap[source])
24974
25127
  impactMap[source] = [];
@@ -25042,7 +25195,7 @@ async function buildImpactMap(cwd) {
25042
25195
  return impactMap;
25043
25196
  }
25044
25197
  async function loadImpactMap(cwd, options) {
25045
- const cachePath = path48.join(cwd, ".swarm", "cache", "impact-map.json");
25198
+ const cachePath = path49.join(cwd, ".swarm", "cache", "impact-map.json");
25046
25199
  if (fs18.existsSync(cachePath)) {
25047
25200
  try {
25048
25201
  const content = fs18.readFileSync(cachePath, "utf-8");
@@ -25075,12 +25228,12 @@ async function loadImpactMap(cwd, options) {
25075
25228
  return _internals38.buildImpactMap(cwd);
25076
25229
  }
25077
25230
  async function saveImpactMap(cwd, impactMap) {
25078
- if (!path48.isAbsolute(cwd)) {
25231
+ if (!path49.isAbsolute(cwd)) {
25079
25232
  throw new Error(`saveImpactMap requires an absolute project root path, got: "${cwd}"`);
25080
25233
  }
25081
25234
  _internals38.validateProjectRoot(cwd);
25082
- const cacheDir2 = path48.join(cwd, ".swarm", "cache");
25083
- const cachePath = path48.join(cacheDir2, "impact-map.json");
25235
+ const cacheDir2 = path49.join(cwd, ".swarm", "cache");
25236
+ const cachePath = path49.join(cacheDir2, "impact-map.json");
25084
25237
  if (!fs18.existsSync(cacheDir2)) {
25085
25238
  fs18.mkdirSync(cacheDir2, { recursive: true });
25086
25239
  }
@@ -25112,7 +25265,7 @@ async function analyzeImpact(changedFiles, cwd, budget) {
25112
25265
  budgetExceeded = true;
25113
25266
  break;
25114
25267
  }
25115
- const normalizedChanged = normalizePath2(path48.resolve(changedFile));
25268
+ const normalizedChanged = normalizePath2(path49.resolve(changedFile));
25116
25269
  const tests = impactMap[normalizedChanged];
25117
25270
  if (tests && tests.length > 0) {
25118
25271
  for (const test of tests) {
@@ -25126,13 +25279,13 @@ async function analyzeImpact(changedFiles, cwd, budget) {
25126
25279
  if (budgetExceeded)
25127
25280
  break;
25128
25281
  } else {
25129
- const changedDir = normalizePath2(path48.dirname(normalizedChanged));
25130
- const changedInputDir = normalizePath2(path48.dirname(changedFile));
25282
+ const changedDir = normalizePath2(path49.dirname(normalizedChanged));
25283
+ const changedInputDir = normalizePath2(path49.dirname(changedFile));
25131
25284
  const suffixMatches = Object.entries(impactMap).filter(([sourcePath]) => {
25132
25285
  return sourcePath.endsWith(changedFile) || changedFile.endsWith(sourcePath) || sourcePath.endsWith(normalizedChanged) || normalizedChanged.endsWith(sourcePath);
25133
25286
  }).sort(([sourceA], [sourceB]) => {
25134
- const sourceDirA = normalizePath2(path48.dirname(sourceA));
25135
- const sourceDirB = normalizePath2(path48.dirname(sourceB));
25287
+ const sourceDirA = normalizePath2(path49.dirname(sourceA));
25288
+ const sourceDirB = normalizePath2(path49.dirname(sourceB));
25136
25289
  const exactA = sourceDirA === changedDir || changedInputDir !== "." && (sourceDirA === changedInputDir || sourceDirA.endsWith(`/${changedInputDir}`));
25137
25290
  const exactB = sourceDirB === changedDir || changedInputDir !== "." && (sourceDirB === changedInputDir || sourceDirB.endsWith(`/${changedInputDir}`));
25138
25291
  if (exactA !== exactB)
@@ -25464,7 +25617,7 @@ function detectFlakyTests(allHistory) {
25464
25617
 
25465
25618
  // src/test-impact/history-store.ts
25466
25619
  import fs19 from "fs";
25467
- import path49 from "path";
25620
+ import path50 from "path";
25468
25621
  var MAX_HISTORY_PER_TEST = 20;
25469
25622
  var MAX_ERROR_LENGTH = 500;
25470
25623
  var MAX_STACK_LENGTH = 200;
@@ -25476,10 +25629,10 @@ function getHistoryPath(workingDir) {
25476
25629
  if (!workingDir) {
25477
25630
  throw new Error("getHistoryPath requires a working directory \u2014 project root must be provided by the caller");
25478
25631
  }
25479
- if (!path49.isAbsolute(workingDir)) {
25632
+ if (!path50.isAbsolute(workingDir)) {
25480
25633
  throw new Error(`getHistoryPath requires an absolute project root path, got: "${workingDir}"`);
25481
25634
  }
25482
- return path49.join(workingDir, ".swarm", "cache", "test-history.jsonl");
25635
+ return path50.join(workingDir, ".swarm", "cache", "test-history.jsonl");
25483
25636
  }
25484
25637
  function sanitizeErrorMessage(errorMessage) {
25485
25638
  if (errorMessage === undefined) {
@@ -25571,7 +25724,7 @@ function batchAppendTestRuns(records, workingDir) {
25571
25724
  }
25572
25725
  }
25573
25726
  const historyPath = getHistoryPath(workingDir);
25574
- const historyDir = path49.dirname(historyPath);
25727
+ const historyDir = path50.dirname(historyPath);
25575
25728
  _internals39.validateProjectRoot(workingDir);
25576
25729
  if (!fs19.existsSync(historyDir)) {
25577
25730
  fs19.mkdirSync(historyDir, { recursive: true });
@@ -25701,7 +25854,7 @@ var _internals39 = {
25701
25854
 
25702
25855
  // src/tools/resolve-working-directory.ts
25703
25856
  import * as fs20 from "fs";
25704
- import * as path50 from "path";
25857
+ import * as path51 from "path";
25705
25858
  function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
25706
25859
  if (workingDirectory == null || workingDirectory === "") {
25707
25860
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
@@ -25738,8 +25891,8 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
25738
25891
  message: "Invalid working_directory: path traversal sequences (..) are not allowed"
25739
25892
  };
25740
25893
  }
25741
- const normalizedDir = path50.normalize(workingDirectory);
25742
- const resolvedDir = path50.resolve(normalizedDir);
25894
+ const normalizedDir = path51.normalize(workingDirectory);
25895
+ const resolvedDir = path51.resolve(normalizedDir);
25743
25896
  let statResult;
25744
25897
  try {
25745
25898
  statResult = fs20.statSync(resolvedDir);
@@ -25758,7 +25911,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
25758
25911
  if (typeof fallbackDirectory !== "string" || fallbackDirectory === "") {
25759
25912
  return { success: true, directory: resolvedDir };
25760
25913
  }
25761
- const resolvedFallback = path50.resolve(fallbackDirectory);
25914
+ const resolvedFallback = path51.resolve(fallbackDirectory);
25762
25915
  let fallbackExists = false;
25763
25916
  try {
25764
25917
  fs20.statSync(resolvedFallback);
@@ -25767,7 +25920,7 @@ function resolveWorkingDirectory(workingDirectory, fallbackDirectory) {
25767
25920
  fallbackExists = false;
25768
25921
  }
25769
25922
  if (fallbackExists) {
25770
- const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path50.sep);
25923
+ const isSubdirectory = resolvedDir.startsWith(resolvedFallback + path51.sep);
25771
25924
  if (isSubdirectory) {
25772
25925
  return {
25773
25926
  success: false,
@@ -25790,7 +25943,7 @@ async function estimateFanOut(sourceFiles, cwd) {
25790
25943
  const impactMap = await loadImpactMap(cwd, { skipRebuild: true });
25791
25944
  const uniqueTestFiles = new Set;
25792
25945
  for (const sourceFile of sourceFiles) {
25793
- const resolvedPath = path51.resolve(cwd, sourceFile);
25946
+ const resolvedPath = path52.resolve(cwd, sourceFile);
25794
25947
  const normalizedPath = resolvedPath.replace(/\\/g, "/");
25795
25948
  const testFiles = impactMap[normalizedPath];
25796
25949
  if (testFiles) {
@@ -25875,14 +26028,14 @@ function hasDevDependency(devDeps, ...patterns) {
25875
26028
  return hasPackageJsonDependency(devDeps, ...patterns);
25876
26029
  }
25877
26030
  function detectGoTest(cwd) {
25878
- return fs21.existsSync(path51.join(cwd, "go.mod")) && isCommandAvailable("go");
26031
+ return fs21.existsSync(path52.join(cwd, "go.mod")) && isCommandAvailable("go");
25879
26032
  }
25880
26033
  function detectJavaMaven(cwd) {
25881
- return fs21.existsSync(path51.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
26034
+ return fs21.existsSync(path52.join(cwd, "pom.xml")) && isCommandAvailable("mvn");
25882
26035
  }
25883
26036
  function detectGradle(cwd) {
25884
- const hasBuildFile = fs21.existsSync(path51.join(cwd, "build.gradle")) || fs21.existsSync(path51.join(cwd, "build.gradle.kts"));
25885
- const hasGradlew = fs21.existsSync(path51.join(cwd, "gradlew")) || fs21.existsSync(path51.join(cwd, "gradlew.bat"));
26037
+ const hasBuildFile = fs21.existsSync(path52.join(cwd, "build.gradle")) || fs21.existsSync(path52.join(cwd, "build.gradle.kts"));
26038
+ const hasGradlew = fs21.existsSync(path52.join(cwd, "gradlew")) || fs21.existsSync(path52.join(cwd, "gradlew.bat"));
25886
26039
  return hasBuildFile && (hasGradlew || isCommandAvailable("gradle"));
25887
26040
  }
25888
26041
  function detectDotnetTest(cwd) {
@@ -25895,25 +26048,25 @@ function detectDotnetTest(cwd) {
25895
26048
  }
25896
26049
  }
25897
26050
  function detectCTest(cwd) {
25898
- const hasSource = fs21.existsSync(path51.join(cwd, "CMakeLists.txt"));
25899
- const hasBuildCache = fs21.existsSync(path51.join(cwd, "CMakeCache.txt")) || fs21.existsSync(path51.join(cwd, "build", "CMakeCache.txt"));
26051
+ const hasSource = fs21.existsSync(path52.join(cwd, "CMakeLists.txt"));
26052
+ const hasBuildCache = fs21.existsSync(path52.join(cwd, "CMakeCache.txt")) || fs21.existsSync(path52.join(cwd, "build", "CMakeCache.txt"));
25900
26053
  return (hasSource || hasBuildCache) && isCommandAvailable("ctest");
25901
26054
  }
25902
26055
  function detectSwiftTest(cwd) {
25903
- return fs21.existsSync(path51.join(cwd, "Package.swift")) && isCommandAvailable("swift");
26056
+ return fs21.existsSync(path52.join(cwd, "Package.swift")) && isCommandAvailable("swift");
25904
26057
  }
25905
26058
  function detectDartTest(cwd) {
25906
- return fs21.existsSync(path51.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
26059
+ return fs21.existsSync(path52.join(cwd, "pubspec.yaml")) && (isCommandAvailable("dart") || isCommandAvailable("flutter"));
25907
26060
  }
25908
26061
  function detectRSpec(cwd) {
25909
- const hasRSpecFile = fs21.existsSync(path51.join(cwd, ".rspec"));
25910
- const hasGemfile = fs21.existsSync(path51.join(cwd, "Gemfile"));
25911
- const hasSpecDir = fs21.existsSync(path51.join(cwd, "spec"));
26062
+ const hasRSpecFile = fs21.existsSync(path52.join(cwd, ".rspec"));
26063
+ const hasGemfile = fs21.existsSync(path52.join(cwd, "Gemfile"));
26064
+ const hasSpecDir = fs21.existsSync(path52.join(cwd, "spec"));
25912
26065
  const hasRSpec = hasRSpecFile || hasGemfile && hasSpecDir;
25913
26066
  return hasRSpec && (isCommandAvailable("bundle") || isCommandAvailable("rspec"));
25914
26067
  }
25915
26068
  function detectMinitest(cwd) {
25916
- return fs21.existsSync(path51.join(cwd, "test")) && (fs21.existsSync(path51.join(cwd, "Gemfile")) || fs21.existsSync(path51.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
26069
+ return fs21.existsSync(path52.join(cwd, "test")) && (fs21.existsSync(path52.join(cwd, "Gemfile")) || fs21.existsSync(path52.join(cwd, "Rakefile"))) && isCommandAvailable("ruby");
25917
26070
  }
25918
26071
  var DISPATCH_FRAMEWORK_MAP = {
25919
26072
  bun: "bun",
@@ -26003,7 +26156,7 @@ async function parseTestOutputViaDispatch(framework, output, baseDir) {
26003
26156
  async function detectTestFramework(cwd) {
26004
26157
  const baseDir = cwd;
26005
26158
  try {
26006
- const packageJsonPath = path51.join(baseDir, "package.json");
26159
+ const packageJsonPath = path52.join(baseDir, "package.json");
26007
26160
  if (fs21.existsSync(packageJsonPath)) {
26008
26161
  const content = fs21.readFileSync(packageJsonPath, "utf-8");
26009
26162
  const pkg = JSON.parse(content);
@@ -26024,16 +26177,16 @@ async function detectTestFramework(cwd) {
26024
26177
  return "jest";
26025
26178
  if (hasDevDependency(devDeps, "mocha", "@types/mocha"))
26026
26179
  return "mocha";
26027
- if (fs21.existsSync(path51.join(baseDir, "bun.lockb")) || fs21.existsSync(path51.join(baseDir, "bun.lock"))) {
26180
+ if (fs21.existsSync(path52.join(baseDir, "bun.lockb")) || fs21.existsSync(path52.join(baseDir, "bun.lock"))) {
26028
26181
  if (scripts.test?.includes("bun"))
26029
26182
  return "bun";
26030
26183
  }
26031
26184
  }
26032
26185
  } catch {}
26033
26186
  try {
26034
- const pyprojectTomlPath = path51.join(baseDir, "pyproject.toml");
26035
- const setupCfgPath = path51.join(baseDir, "setup.cfg");
26036
- const requirementsTxtPath = path51.join(baseDir, "requirements.txt");
26187
+ const pyprojectTomlPath = path52.join(baseDir, "pyproject.toml");
26188
+ const setupCfgPath = path52.join(baseDir, "setup.cfg");
26189
+ const requirementsTxtPath = path52.join(baseDir, "requirements.txt");
26037
26190
  if (fs21.existsSync(pyprojectTomlPath)) {
26038
26191
  const content = fs21.readFileSync(pyprojectTomlPath, "utf-8");
26039
26192
  if (content.includes("[tool.pytest"))
@@ -26053,7 +26206,7 @@ async function detectTestFramework(cwd) {
26053
26206
  }
26054
26207
  } catch {}
26055
26208
  try {
26056
- const cargoTomlPath = path51.join(baseDir, "Cargo.toml");
26209
+ const cargoTomlPath = path52.join(baseDir, "Cargo.toml");
26057
26210
  if (fs21.existsSync(cargoTomlPath)) {
26058
26211
  const content = fs21.readFileSync(cargoTomlPath, "utf-8");
26059
26212
  if (content.includes("[dev-dependencies]")) {
@@ -26064,9 +26217,9 @@ async function detectTestFramework(cwd) {
26064
26217
  }
26065
26218
  } catch {}
26066
26219
  try {
26067
- const pesterConfigPath = path51.join(baseDir, "pester.config.ps1");
26068
- const pesterConfigJsonPath = path51.join(baseDir, "pester.config.ps1.json");
26069
- const pesterPs1Path = path51.join(baseDir, "tests.ps1");
26220
+ const pesterConfigPath = path52.join(baseDir, "pester.config.ps1");
26221
+ const pesterConfigJsonPath = path52.join(baseDir, "pester.config.ps1.json");
26222
+ const pesterPs1Path = path52.join(baseDir, "tests.ps1");
26070
26223
  if (fs21.existsSync(pesterConfigPath) || fs21.existsSync(pesterConfigJsonPath) || fs21.existsSync(pesterPs1Path)) {
26071
26224
  return "pester";
26072
26225
  }
@@ -26095,12 +26248,12 @@ async function detectTestFramework(cwd) {
26095
26248
  return "none";
26096
26249
  }
26097
26250
  function detectPhpTest(cwd) {
26098
- if (fs21.existsSync(path51.join(cwd, "artisan")) && fs21.existsSync(path51.join(cwd, "composer.json"))) {
26251
+ if (fs21.existsSync(path52.join(cwd, "artisan")) && fs21.existsSync(path52.join(cwd, "composer.json"))) {
26099
26252
  return "php-artisan";
26100
26253
  }
26101
- if (fs21.existsSync(path51.join(cwd, "Pest.php")))
26254
+ if (fs21.existsSync(path52.join(cwd, "Pest.php")))
26102
26255
  return "pest";
26103
- if (fs21.existsSync(path51.join(cwd, "phpunit.xml")) || fs21.existsSync(path51.join(cwd, "phpunit.xml.dist"))) {
26256
+ if (fs21.existsSync(path52.join(cwd, "phpunit.xml")) || fs21.existsSync(path52.join(cwd, "phpunit.xml.dist"))) {
26104
26257
  return "phpunit";
26105
26258
  }
26106
26259
  return null;
@@ -26123,12 +26276,12 @@ function isTestDirectoryPath(normalizedPath) {
26123
26276
  return normalizedPath.split("/").some((segment) => TEST_DIRECTORY_NAMES.includes(segment));
26124
26277
  }
26125
26278
  function resolveWorkspacePath(file, workingDir) {
26126
- return path51.isAbsolute(file) ? path51.resolve(file) : path51.resolve(workingDir, file);
26279
+ return path52.isAbsolute(file) ? path52.resolve(file) : path52.resolve(workingDir, file);
26127
26280
  }
26128
26281
  function toWorkspaceOutputPath(absolutePath, workingDir, preferRelative) {
26129
26282
  if (!preferRelative)
26130
26283
  return absolutePath;
26131
- return path51.relative(workingDir, absolutePath);
26284
+ return path52.relative(workingDir, absolutePath);
26132
26285
  }
26133
26286
  function dedupePush(target, value) {
26134
26287
  if (!target.includes(value)) {
@@ -26171,18 +26324,18 @@ function buildLanguageSpecificTestNames(nameWithoutExt, ext) {
26171
26324
  }
26172
26325
  }
26173
26326
  function getRepoLevelCandidateDirectories(workingDir, relativePath, ext) {
26174
- const relativeDir = path51.dirname(relativePath);
26327
+ const relativeDir = path52.dirname(relativePath);
26175
26328
  const nestedRelativeDir = relativeDir === "." ? "" : relativeDir;
26176
26329
  const directories = TEST_DIRECTORY_NAMES.flatMap((dirName) => {
26177
- const rootDir = path51.join(workingDir, dirName);
26178
- return nestedRelativeDir ? [rootDir, path51.join(rootDir, nestedRelativeDir)] : [rootDir];
26330
+ const rootDir = path52.join(workingDir, dirName);
26331
+ return nestedRelativeDir ? [rootDir, path52.join(rootDir, nestedRelativeDir)] : [rootDir];
26179
26332
  });
26180
26333
  const normalizedRelativePath = relativePath.replace(/\\/g, "/");
26181
26334
  if (ext === ".java" && normalizedRelativePath.startsWith("src/main/java/")) {
26182
- directories.push(path51.join(workingDir, "src/test/java", path51.dirname(normalizedRelativePath.slice("src/main/java/".length))));
26335
+ directories.push(path52.join(workingDir, "src/test/java", path52.dirname(normalizedRelativePath.slice("src/main/java/".length))));
26183
26336
  }
26184
26337
  if ((ext === ".kt" || ext === ".java") && normalizedRelativePath.startsWith("src/main/kotlin/")) {
26185
- directories.push(path51.join(workingDir, "src/test/kotlin", path51.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
26338
+ directories.push(path52.join(workingDir, "src/test/kotlin", path52.dirname(normalizedRelativePath.slice("src/main/kotlin/".length))));
26186
26339
  }
26187
26340
  return [...new Set(directories)];
26188
26341
  }
@@ -26190,21 +26343,21 @@ function hasCompoundTestExtension(filename) {
26190
26343
  const lower = filename.toLowerCase();
26191
26344
  return COMPOUND_TEST_EXTENSIONS.some((ext) => lower.endsWith(ext));
26192
26345
  }
26193
- function isLanguageSpecificTestFile(basename11) {
26194
- const lower = basename11.toLowerCase();
26346
+ function isLanguageSpecificTestFile(basename12) {
26347
+ const lower = basename12.toLowerCase();
26195
26348
  if (lower.endsWith("_test.go"))
26196
26349
  return true;
26197
26350
  if (lower.endsWith(".py") && (lower.startsWith("test_") || lower.endsWith("_test.py")))
26198
26351
  return true;
26199
26352
  if (lower.endsWith("_spec.rb"))
26200
26353
  return true;
26201
- if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename11) || basename11.endsWith("Test.java") || basename11.endsWith("Tests.java") || lower.endsWith("it.java")))
26354
+ if (lower.endsWith(".java") && (/^Test[A-Z]/.test(basename12) || basename12.endsWith("Test.java") || basename12.endsWith("Tests.java") || lower.endsWith("it.java")))
26202
26355
  return true;
26203
26356
  if (lower.endsWith(".cs") && (lower.endsWith("test.cs") || lower.endsWith("tests.cs")))
26204
26357
  return true;
26205
- if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename11) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
26358
+ if (lower.endsWith(".kt") && (/^Test[A-Z]/.test(basename12) || lower.endsWith("test.kt") || lower.endsWith("tests.kt")))
26206
26359
  return true;
26207
- if (lower.endsWith(".php") && (/^Test[A-Z]/.test(basename11) || basename11.endsWith("Test.php") || basename11.endsWith("Tests.php")))
26360
+ if (lower.endsWith(".php") && (/^Test[A-Z]/.test(basename12) || basename12.endsWith("Test.php") || basename12.endsWith("Tests.php")))
26208
26361
  return true;
26209
26362
  if (lower.endsWith(".tests.ps1"))
26210
26363
  return true;
@@ -26212,23 +26365,23 @@ function isLanguageSpecificTestFile(basename11) {
26212
26365
  }
26213
26366
  function isConventionTestFilePath(filePath) {
26214
26367
  const normalizedPath = filePath.replace(/\\/g, "/");
26215
- const basename11 = path51.basename(filePath);
26216
- return hasCompoundTestExtension(basename11) || basename11.includes(".spec.") || basename11.includes(".test.") || isLanguageSpecificTestFile(basename11) || isTestDirectoryPath(normalizedPath);
26368
+ const basename12 = path52.basename(filePath);
26369
+ return hasCompoundTestExtension(basename12) || basename12.includes(".spec.") || basename12.includes(".test.") || isLanguageSpecificTestFile(basename12) || isTestDirectoryPath(normalizedPath);
26217
26370
  }
26218
26371
  function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
26219
26372
  const testFiles = [];
26220
26373
  for (const file of sourceFiles) {
26221
26374
  const absoluteFile = resolveWorkspacePath(file, workingDir);
26222
- const relativeFile = path51.relative(workingDir, absoluteFile);
26223
- const basename11 = path51.basename(absoluteFile);
26224
- const dirname25 = path51.dirname(absoluteFile);
26225
- const preferRelativeOutput = !path51.isAbsolute(file);
26375
+ const relativeFile = path52.relative(workingDir, absoluteFile);
26376
+ const basename12 = path52.basename(absoluteFile);
26377
+ const dirname25 = path52.dirname(absoluteFile);
26378
+ const preferRelativeOutput = !path52.isAbsolute(file);
26226
26379
  if (isConventionTestFilePath(relativeFile) || isConventionTestFilePath(file)) {
26227
26380
  dedupePush(testFiles, toWorkspaceOutputPath(absoluteFile, workingDir, preferRelativeOutput));
26228
26381
  continue;
26229
26382
  }
26230
- const nameWithoutExt = basename11.replace(/\.[^.]+$/, "");
26231
- const ext = path51.extname(basename11);
26383
+ const nameWithoutExt = basename12.replace(/\.[^.]+$/, "");
26384
+ const ext = path52.extname(basename12);
26232
26385
  const genericTestNames = [
26233
26386
  `${nameWithoutExt}.spec${ext}`,
26234
26387
  `${nameWithoutExt}.test${ext}`
@@ -26237,17 +26390,17 @@ function getTestFilesFromConvention(sourceFiles, workingDir = process.cwd()) {
26237
26390
  const colocatedCandidates = [
26238
26391
  ...genericTestNames,
26239
26392
  ...languageSpecificTestNames
26240
- ].map((candidateName) => path51.join(dirname25, candidateName));
26393
+ ].map((candidateName) => path52.join(dirname25, candidateName));
26241
26394
  const testDirectoryNames = [
26242
- basename11,
26395
+ basename12,
26243
26396
  ...genericTestNames,
26244
26397
  ...languageSpecificTestNames
26245
26398
  ];
26246
26399
  const repoLevelDirectories = getRepoLevelCandidateDirectories(workingDir, relativeFile, ext);
26247
26400
  const possibleTestFiles = [
26248
26401
  ...colocatedCandidates,
26249
- ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path51.join(dirname25, dirName, candidateName))),
26250
- ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path51.join(candidateDir, candidateName)))
26402
+ ...TEST_DIRECTORY_NAMES.flatMap((dirName) => testDirectoryNames.map((candidateName) => path52.join(dirname25, dirName, candidateName))),
26403
+ ...repoLevelDirectories.flatMap((candidateDir) => testDirectoryNames.map((candidateName) => path52.join(candidateDir, candidateName)))
26251
26404
  ];
26252
26405
  for (const testFile of possibleTestFiles) {
26253
26406
  if (fs21.existsSync(testFile)) {
@@ -26268,7 +26421,7 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
26268
26421
  try {
26269
26422
  const absoluteTestFile = resolveWorkspacePath(testFile, workingDir);
26270
26423
  const content = fs21.readFileSync(absoluteTestFile, "utf-8");
26271
- const testDir = path51.dirname(absoluteTestFile);
26424
+ const testDir = path52.dirname(absoluteTestFile);
26272
26425
  const importRegex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
26273
26426
  let match;
26274
26427
  match = importRegex.exec(content);
@@ -26276,8 +26429,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
26276
26429
  const importPath = match[1];
26277
26430
  let resolvedImport;
26278
26431
  if (importPath.startsWith(".")) {
26279
- resolvedImport = path51.resolve(testDir, importPath);
26280
- const existingExt = path51.extname(resolvedImport);
26432
+ resolvedImport = path52.resolve(testDir, importPath);
26433
+ const existingExt = path52.extname(resolvedImport);
26281
26434
  if (!existingExt) {
26282
26435
  for (const extToTry of [
26283
26436
  ".ts",
@@ -26297,12 +26450,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
26297
26450
  } else {
26298
26451
  continue;
26299
26452
  }
26300
- const importBasename = path51.basename(resolvedImport, path51.extname(resolvedImport));
26301
- const importDir = path51.dirname(resolvedImport);
26453
+ const importBasename = path52.basename(resolvedImport, path52.extname(resolvedImport));
26454
+ const importDir = path52.dirname(resolvedImport);
26302
26455
  for (const sourceFile of absoluteSourceFiles) {
26303
- const sourceDir = path51.dirname(sourceFile);
26304
- const sourceBasename = path51.basename(sourceFile, path51.extname(sourceFile));
26305
- const isRelatedDir = importDir === sourceDir || importDir === path51.join(sourceDir, "__tests__") || importDir === path51.join(sourceDir, "tests") || importDir === path51.join(sourceDir, "test") || importDir === path51.join(sourceDir, "spec");
26456
+ const sourceDir = path52.dirname(sourceFile);
26457
+ const sourceBasename = path52.basename(sourceFile, path52.extname(sourceFile));
26458
+ const isRelatedDir = importDir === sourceDir || importDir === path52.join(sourceDir, "__tests__") || importDir === path52.join(sourceDir, "tests") || importDir === path52.join(sourceDir, "test") || importDir === path52.join(sourceDir, "spec");
26306
26459
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
26307
26460
  dedupePush(testFiles, testFile);
26308
26461
  break;
@@ -26315,8 +26468,8 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
26315
26468
  while (match !== null) {
26316
26469
  const importPath = match[1];
26317
26470
  if (importPath.startsWith(".")) {
26318
- let resolvedImport = path51.resolve(testDir, importPath);
26319
- const existingExt = path51.extname(resolvedImport);
26471
+ let resolvedImport = path52.resolve(testDir, importPath);
26472
+ const existingExt = path52.extname(resolvedImport);
26320
26473
  if (!existingExt) {
26321
26474
  for (const extToTry of [
26322
26475
  ".ts",
@@ -26333,12 +26486,12 @@ async function getTestFilesFromGraph(sourceFiles, workingDir) {
26333
26486
  }
26334
26487
  }
26335
26488
  }
26336
- const importDir = path51.dirname(resolvedImport);
26337
- const importBasename = path51.basename(resolvedImport, path51.extname(resolvedImport));
26489
+ const importDir = path52.dirname(resolvedImport);
26490
+ const importBasename = path52.basename(resolvedImport, path52.extname(resolvedImport));
26338
26491
  for (const sourceFile of absoluteSourceFiles) {
26339
- const sourceDir = path51.dirname(sourceFile);
26340
- const sourceBasename = path51.basename(sourceFile, path51.extname(sourceFile));
26341
- const isRelatedDir = importDir === sourceDir || importDir === path51.join(sourceDir, "__tests__") || importDir === path51.join(sourceDir, "tests") || importDir === path51.join(sourceDir, "test") || importDir === path51.join(sourceDir, "spec");
26492
+ const sourceDir = path52.dirname(sourceFile);
26493
+ const sourceBasename = path52.basename(sourceFile, path52.extname(sourceFile));
26494
+ const isRelatedDir = importDir === sourceDir || importDir === path52.join(sourceDir, "__tests__") || importDir === path52.join(sourceDir, "tests") || importDir === path52.join(sourceDir, "test") || importDir === path52.join(sourceDir, "spec");
26342
26495
  if (resolvedImport === sourceFile || importBasename === sourceBasename && isRelatedDir) {
26343
26496
  dedupePush(testFiles, testFile);
26344
26497
  break;
@@ -26458,8 +26611,8 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
26458
26611
  return ["mvn", "test"];
26459
26612
  case "gradle": {
26460
26613
  const isWindows = process.platform === "win32";
26461
- const hasGradlewBat = fs21.existsSync(path51.join(baseDir, "gradlew.bat"));
26462
- const hasGradlew = fs21.existsSync(path51.join(baseDir, "gradlew"));
26614
+ const hasGradlewBat = fs21.existsSync(path52.join(baseDir, "gradlew.bat"));
26615
+ const hasGradlew = fs21.existsSync(path52.join(baseDir, "gradlew"));
26463
26616
  if (hasGradlewBat && isWindows)
26464
26617
  return ["gradlew.bat", "test"];
26465
26618
  if (hasGradlew)
@@ -26476,7 +26629,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
26476
26629
  "cmake-build-release",
26477
26630
  "out"
26478
26631
  ];
26479
- const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(path51.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
26632
+ const actualBuildDir = buildDirCandidates.find((d) => fs21.existsSync(path52.join(baseDir, d, "CMakeCache.txt"))) ?? "build";
26480
26633
  return ["ctest", "--test-dir", actualBuildDir];
26481
26634
  }
26482
26635
  case "swift-test":
@@ -26526,7 +26679,7 @@ function buildTestCommand(framework, scope, files, coverage, baseDir, bail) {
26526
26679
  }
26527
26680
  }
26528
26681
  function phpVendorBin2(name) {
26529
- return path51.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
26682
+ return path52.join("vendor", "bin", process.platform === "win32" ? `${name}.bat` : name);
26530
26683
  }
26531
26684
  function mapFrameworkStatusToResult(status) {
26532
26685
  if (typeof status !== "string")
@@ -26949,11 +27102,11 @@ async function runTests(framework, scope, files, coverage, timeout_ms, cwd, bail
26949
27102
  };
26950
27103
  }
26951
27104
  const startTime = Date.now();
26952
- const vitestJsonOutputPath = framework === "vitest" ? path51.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
27105
+ const vitestJsonOutputPath = framework === "vitest" ? path52.join(cwd, ".swarm", "cache", "test-runner-vitest.json") : undefined;
26953
27106
  try {
26954
27107
  if (vitestJsonOutputPath) {
26955
27108
  try {
26956
- fs21.mkdirSync(path51.dirname(vitestJsonOutputPath), { recursive: true });
27109
+ fs21.mkdirSync(path52.dirname(vitestJsonOutputPath), { recursive: true });
26957
27110
  if (fs21.existsSync(vitestJsonOutputPath)) {
26958
27111
  fs21.unlinkSync(vitestJsonOutputPath);
26959
27112
  }
@@ -27122,10 +27275,10 @@ var SKIP_DIRECTORIES = new Set([
27122
27275
  ]);
27123
27276
  function normalizeHistoryTestFile(testFile, workingDir) {
27124
27277
  const normalized = testFile.replace(/\\/g, "/");
27125
- if (!path51.isAbsolute(testFile))
27278
+ if (!path52.isAbsolute(testFile))
27126
27279
  return normalized;
27127
- const relative6 = path51.relative(workingDir, testFile);
27128
- if (relative6.startsWith("..") || path51.isAbsolute(relative6)) {
27280
+ const relative6 = path52.relative(workingDir, testFile);
27281
+ if (relative6.startsWith("..") || path52.isAbsolute(relative6)) {
27129
27282
  return normalized;
27130
27283
  }
27131
27284
  return relative6.replace(/\\/g, "/");
@@ -27364,7 +27517,7 @@ var test_runner = createSwarmTool({
27364
27517
  const sourceFiles = args.files.filter((file) => {
27365
27518
  if (directTestFiles.includes(file))
27366
27519
  return false;
27367
- const ext = path51.extname(file).toLowerCase();
27520
+ const ext = path52.extname(file).toLowerCase();
27368
27521
  return SOURCE_EXTENSIONS.has(ext);
27369
27522
  });
27370
27523
  const invalidFiles = args.files.filter((file) => !directTestFiles.includes(file) && !sourceFiles.includes(file));
@@ -27410,7 +27563,7 @@ var test_runner = createSwarmTool({
27410
27563
  if (isConventionTestFilePath(f)) {
27411
27564
  return false;
27412
27565
  }
27413
- const ext = path51.extname(f).toLowerCase();
27566
+ const ext = path52.extname(f).toLowerCase();
27414
27567
  return SOURCE_EXTENSIONS.has(ext);
27415
27568
  });
27416
27569
  if (sourceFiles.length === 0) {
@@ -27460,7 +27613,7 @@ var test_runner = createSwarmTool({
27460
27613
  if (isConventionTestFilePath(f)) {
27461
27614
  return false;
27462
27615
  }
27463
- const ext = path51.extname(f).toLowerCase();
27616
+ const ext = path52.extname(f).toLowerCase();
27464
27617
  return SOURCE_EXTENSIONS.has(ext);
27465
27618
  });
27466
27619
  if (sourceFiles.length === 0) {
@@ -27512,8 +27665,8 @@ var test_runner = createSwarmTool({
27512
27665
  }
27513
27666
  if (impactResult.impactedTests.length > 0) {
27514
27667
  testFiles = impactResult.impactedTests.map((absPath) => {
27515
- const relativePath = path51.relative(workingDir, absPath);
27516
- return path51.isAbsolute(relativePath) ? absPath : relativePath;
27668
+ const relativePath = path52.relative(workingDir, absPath);
27669
+ return path52.isAbsolute(relativePath) ? absPath : relativePath;
27517
27670
  });
27518
27671
  } else {
27519
27672
  graphFallbackReason = "no impacted tests found via impact analysis, falling back to graph";
@@ -27608,8 +27761,8 @@ function validateDirectoryPath(dir) {
27608
27761
  if (dir.includes("..")) {
27609
27762
  throw new Error("Directory path must not contain path traversal sequences");
27610
27763
  }
27611
- const normalized = path52.normalize(dir);
27612
- const absolutePath = path52.isAbsolute(normalized) ? normalized : path52.resolve(normalized);
27764
+ const normalized = path53.normalize(dir);
27765
+ const absolutePath = path53.isAbsolute(normalized) ? normalized : path53.resolve(normalized);
27613
27766
  return absolutePath;
27614
27767
  }
27615
27768
  function validateTimeout(timeoutMs, defaultValue) {
@@ -27632,7 +27785,7 @@ function validateTimeout(timeoutMs, defaultValue) {
27632
27785
  }
27633
27786
  function getPackageVersion(dir) {
27634
27787
  try {
27635
- const packagePath = path52.join(dir, "package.json");
27788
+ const packagePath = path53.join(dir, "package.json");
27636
27789
  if (fs22.existsSync(packagePath)) {
27637
27790
  const content = fs22.readFileSync(packagePath, "utf-8");
27638
27791
  const pkg = JSON.parse(content);
@@ -27643,7 +27796,7 @@ function getPackageVersion(dir) {
27643
27796
  }
27644
27797
  function getChangelogVersion(dir) {
27645
27798
  try {
27646
- const changelogPath = path52.join(dir, "CHANGELOG.md");
27799
+ const changelogPath = path53.join(dir, "CHANGELOG.md");
27647
27800
  if (fs22.existsSync(changelogPath)) {
27648
27801
  const content = fs22.readFileSync(changelogPath, "utf-8");
27649
27802
  const match = content.match(/^##\s*\[?(\d+\.\d+\.\d+)\]?/m);
@@ -27657,7 +27810,7 @@ function getChangelogVersion(dir) {
27657
27810
  function getVersionFileVersion(dir) {
27658
27811
  const possibleFiles = ["VERSION.txt", "version.txt", "VERSION", "version"];
27659
27812
  for (const file of possibleFiles) {
27660
- const filePath = path52.join(dir, file);
27813
+ const filePath = path53.join(dir, file);
27661
27814
  if (fs22.existsSync(filePath)) {
27662
27815
  try {
27663
27816
  const content = fs22.readFileSync(filePath, "utf-8").trim();
@@ -28395,7 +28548,7 @@ async function handleQaGatesCommand(directory, args, sessionID) {
28395
28548
 
28396
28549
  // src/commands/reset.ts
28397
28550
  import * as fs23 from "fs";
28398
- import * as path53 from "path";
28551
+ import * as path54 from "path";
28399
28552
 
28400
28553
  // src/background/circuit-breaker.ts
28401
28554
  class CircuitBreaker {
@@ -29114,7 +29267,7 @@ async function handleResetCommand(directory, args) {
29114
29267
  }
29115
29268
  for (const filename of ["SWARM_PLAN.md", "SWARM_PLAN.json"]) {
29116
29269
  try {
29117
- const rootPath = path53.join(directory, filename);
29270
+ const rootPath = path54.join(directory, filename);
29118
29271
  if (fs23.existsSync(rootPath)) {
29119
29272
  fs23.unlinkSync(rootPath);
29120
29273
  results.push(`- \u2705 Deleted ${filename} (root)`);
@@ -29152,14 +29305,14 @@ async function handleResetCommand(directory, args) {
29152
29305
 
29153
29306
  // src/commands/reset-session.ts
29154
29307
  import * as fs26 from "fs";
29155
- import * as path56 from "path";
29308
+ import * as path57 from "path";
29156
29309
 
29157
29310
  // src/prm/trajectory-store.ts
29158
29311
  import * as fs24 from "fs/promises";
29159
- import * as path54 from "path";
29312
+ import * as path55 from "path";
29160
29313
  var MAX_TRACKED_TRAJECTORY_SESSIONS = 500;
29161
29314
  function getTrajectoryPath(sessionId, directory) {
29162
- const relativePath = path54.join("trajectories", `${sessionId}.jsonl`);
29315
+ const relativePath = path55.join("trajectories", `${sessionId}.jsonl`);
29163
29316
  return validateSwarmPath(directory, relativePath);
29164
29317
  }
29165
29318
  var _inMemoryTrajectoryCache = new Map;
@@ -29218,7 +29371,7 @@ async function cleanupOldTrajectoryFiles(directory, maxAgeDays = 7) {
29218
29371
  for (const entry of entries) {
29219
29372
  if (!entry.isFile())
29220
29373
  continue;
29221
- const filePath = path54.join(dirPath, entry.name);
29374
+ const filePath = path55.join(dirPath, entry.name);
29222
29375
  try {
29223
29376
  const stat6 = await fs24.stat(filePath);
29224
29377
  if (now - stat6.mtimeMs > cutoffMs) {
@@ -29645,16 +29798,16 @@ function detectPatterns(trajectory, config, lastProcessedStep = 0) {
29645
29798
  }
29646
29799
  // src/prm/replay.ts
29647
29800
  import { promises as fs25 } from "fs";
29648
- import path55 from "path";
29801
+ import path56 from "path";
29649
29802
  function isPathSafe(targetPath, basePath) {
29650
- const resolvedTarget = path55.resolve(targetPath);
29651
- const resolvedBase = path55.resolve(basePath);
29652
- const rel = path55.relative(resolvedBase, resolvedTarget);
29653
- return !rel.startsWith("..") && !path55.isAbsolute(rel);
29803
+ const resolvedTarget = path56.resolve(targetPath);
29804
+ const resolvedBase = path56.resolve(basePath);
29805
+ const rel = path56.relative(resolvedBase, resolvedTarget);
29806
+ return !rel.startsWith("..") && !path56.isAbsolute(rel);
29654
29807
  }
29655
29808
  function isWithinReplaysDir(targetPath) {
29656
- const resolved = path55.resolve(targetPath);
29657
- const parts = resolved.split(path55.sep);
29809
+ const resolved = path56.resolve(targetPath);
29810
+ const parts = resolved.split(path56.sep);
29658
29811
  for (let i = 0;i < parts.length - 1; i++) {
29659
29812
  if (parts[i] === ".swarm" && parts[i + 1] === "replays") {
29660
29813
  return true;
@@ -29667,10 +29820,10 @@ function sanitizeFilename(input) {
29667
29820
  }
29668
29821
  async function startReplayRecording(sessionID, directory) {
29669
29822
  try {
29670
- const replayDir = path55.join(directory, ".swarm", "replays");
29823
+ const replayDir = path56.join(directory, ".swarm", "replays");
29671
29824
  const safeSessionID = sanitizeFilename(sessionID);
29672
29825
  const filename = `${safeSessionID}-${Date.now()}.jsonl`;
29673
- const filepath = path55.join(replayDir, filename);
29826
+ const filepath = path56.join(replayDir, filename);
29674
29827
  if (!isPathSafe(filepath, replayDir)) {
29675
29828
  console.warn(`[replay] Invalid path detected - path traversal attempt blocked for session ${sessionID}`);
29676
29829
  return null;
@@ -29752,7 +29905,7 @@ async function handleResetSessionCommand(directory, _args) {
29752
29905
  } catch {
29753
29906
  results.push("\u274C Failed to delete state.json");
29754
29907
  }
29755
- const sessionDir = statePath ? path56.dirname(statePath) : undefined;
29908
+ const sessionDir = statePath ? path57.dirname(statePath) : undefined;
29756
29909
  let sessionFiles = [];
29757
29910
  if (sessionDir && fs26.existsSync(sessionDir)) {
29758
29911
  try {
@@ -29764,7 +29917,7 @@ async function handleResetSessionCommand(directory, _args) {
29764
29917
  for (const file of sessionFiles) {
29765
29918
  if (file === "state.json")
29766
29919
  continue;
29767
- const filePath = path56.join(sessionDir, file);
29920
+ const filePath = path57.join(sessionDir, file);
29768
29921
  try {
29769
29922
  if (!fs26.existsSync(filePath))
29770
29923
  continue;
@@ -29786,7 +29939,7 @@ async function handleResetSessionCommand(directory, _args) {
29786
29939
  const chainCount = swarmState.delegationChains.size;
29787
29940
  swarmState.delegationChains.clear();
29788
29941
  results.push(`\u2705 Cleared ${chainCount} delegation chain(s)`);
29789
- const worktreesDir = path56.resolve(path56.dirname(directory), ".swarm-worktrees");
29942
+ const worktreesDir = path57.resolve(path57.dirname(directory), ".swarm-worktrees");
29790
29943
  try {
29791
29944
  if (fs26.existsSync(worktreesDir)) {
29792
29945
  fs26.rmSync(worktreesDir, { recursive: true, force: true });
@@ -29819,7 +29972,7 @@ async function handleResetSessionCommand(directory, _args) {
29819
29972
  }
29820
29973
 
29821
29974
  // src/summaries/manager.ts
29822
- import * as path57 from "path";
29975
+ import * as path58 from "path";
29823
29976
  var SUMMARY_ID_REGEX = /^S\d+$/;
29824
29977
  function sanitizeSummaryId(id) {
29825
29978
  if (!id || id.length === 0) {
@@ -29843,7 +29996,7 @@ function sanitizeSummaryId(id) {
29843
29996
  }
29844
29997
  async function loadFullOutput(directory, id) {
29845
29998
  const sanitizedId = sanitizeSummaryId(id);
29846
- const relativePath = path57.join("summaries", `${sanitizedId}.json`);
29999
+ const relativePath = path58.join("summaries", `${sanitizedId}.json`);
29847
30000
  validateSwarmPath(directory, relativePath);
29848
30001
  const content = await readSwarmFileAsync(directory, relativePath);
29849
30002
  if (content === null) {
@@ -29896,7 +30049,7 @@ ${error2 instanceof Error ? error2.message : String(error2)}`;
29896
30049
 
29897
30050
  // src/commands/rollback.ts
29898
30051
  import * as fs27 from "fs";
29899
- import * as path58 from "path";
30052
+ import * as path59 from "path";
29900
30053
  function safeParseToolJson(result) {
29901
30054
  try {
29902
30055
  const jsonStr = typeof result === "string" ? result : result.output;
@@ -30051,8 +30204,8 @@ async function handleRollbackCommand(directory, args) {
30051
30204
  if (EXCLUDE_FILES.has(file) || file.startsWith("plan-ledger.archived-")) {
30052
30205
  continue;
30053
30206
  }
30054
- const src = path58.join(checkpointDir, file);
30055
- const dest = path58.join(swarmDir, file);
30207
+ const src = path59.join(checkpointDir, file);
30208
+ const dest = path59.join(swarmDir, file);
30056
30209
  try {
30057
30210
  fs27.cpSync(src, dest, { recursive: true, force: true });
30058
30211
  successes.push(file);
@@ -30071,7 +30224,7 @@ async function handleRollbackCommand(directory, args) {
30071
30224
  ].join(`
30072
30225
  `);
30073
30226
  }
30074
- const existingLedgerPath = path58.join(swarmDir, "plan-ledger.jsonl");
30227
+ const existingLedgerPath = path59.join(swarmDir, "plan-ledger.jsonl");
30075
30228
  let ledgerDeletionFailed = false;
30076
30229
  if (fs27.existsSync(existingLedgerPath)) {
30077
30230
  try {
@@ -30084,7 +30237,7 @@ async function handleRollbackCommand(directory, args) {
30084
30237
  }
30085
30238
  if (!ledgerDeletionFailed) {
30086
30239
  try {
30087
- const planJsonPath = path58.join(swarmDir, "plan.json");
30240
+ const planJsonPath = path59.join(swarmDir, "plan.json");
30088
30241
  if (fs27.existsSync(planJsonPath)) {
30089
30242
  const planRaw = fs27.readFileSync(planJsonPath, "utf-8");
30090
30243
  const plan = PlanSchema.parse(JSON.parse(planRaw));
@@ -30132,11 +30285,11 @@ async function handleRollbackCommand(directory, args) {
30132
30285
 
30133
30286
  // src/commands/sdd.ts
30134
30287
  import * as fs28 from "fs";
30135
- import * as path59 from "path";
30288
+ import * as path60 from "path";
30136
30289
  var _internals43 = {
30137
30290
  writeProjectedSpecSync
30138
30291
  };
30139
- var SWARM_SPEC_REL = path59.join(".swarm", "spec.md");
30292
+ var SWARM_SPEC_REL = path60.join(".swarm", "spec.md");
30140
30293
  var USAGE9 = `Usage:
30141
30294
  /swarm sdd status [--json] [--source <provider>]
30142
30295
  /swarm sdd validate [--json] [--change <id>] [--source <provider>] [--feature <id>]
@@ -30258,7 +30411,7 @@ ${USAGE9}`;
30258
30411
  }
30259
30412
  const speckitDetection = detectSpeckit(directory);
30260
30413
  const speckitPresent = speckitDetection.features.length > 0;
30261
- const nativeSpecExists = fs28.existsSync(path59.join(directory, SWARM_SPEC_REL));
30414
+ const nativeSpecExists = fs28.existsSync(path60.join(directory, SWARM_SPEC_REL));
30262
30415
  if (speckitPresent && !parsed.source && !nativeSpecExists) {
30263
30416
  const openspecProjection = buildOpenSpecProjectionSync(directory);
30264
30417
  if (openspecProjection !== null) {
@@ -30328,7 +30481,7 @@ ${USAGE9}`;
30328
30481
  ${USAGE9}`;
30329
30482
  }
30330
30483
  let useSpeckit = false;
30331
- const nativeSpecExists = fs28.existsSync(path59.join(directory, SWARM_SPEC_REL));
30484
+ const nativeSpecExists = fs28.existsSync(path60.join(directory, SWARM_SPEC_REL));
30332
30485
  if (parsed.source === "speckit") {
30333
30486
  useSpeckit = true;
30334
30487
  } else if (!parsed.source && !nativeSpecExists) {
@@ -30482,7 +30635,7 @@ ${USAGE9}`;
30482
30635
  ${USAGE9}`;
30483
30636
  }
30484
30637
  if (!parsed.dryRun) {
30485
- const nativeSpecPath = path59.join(directory, SWARM_SPEC_REL);
30638
+ const nativeSpecPath = path60.join(directory, SWARM_SPEC_REL);
30486
30639
  if (fs28.existsSync(nativeSpecPath)) {
30487
30640
  if (!parsed.overwrite) {
30488
30641
  return [
@@ -30698,10 +30851,10 @@ Ensure this is a git repository with commit history.`;
30698
30851
  `);
30699
30852
  try {
30700
30853
  const fs29 = await import("fs/promises");
30701
- const path60 = await import("path");
30702
- const reportPath = path60.join(directory, ".swarm", "simulate-report.md");
30703
- await fs29.mkdir(path60.dirname(reportPath), { recursive: true });
30704
- const reportTempPath = path60.join(path60.dirname(reportPath), `${path60.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
30854
+ const path61 = await import("path");
30855
+ const reportPath = path61.join(directory, ".swarm", "simulate-report.md");
30856
+ await fs29.mkdir(path61.dirname(reportPath), { recursive: true });
30857
+ const reportTempPath = path61.join(path61.dirname(reportPath), `${path61.basename(reportPath)}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`);
30705
30858
  try {
30706
30859
  await fs29.writeFile(reportTempPath, report, "utf-8");
30707
30860
  renameSync10(reportTempPath, reportPath);
@@ -30730,7 +30883,7 @@ async function handleSpecifyCommand(_directory, args) {
30730
30883
  // src/services/status-service.ts
30731
30884
  import * as fsSync2 from "fs";
30732
30885
  import { readFile as readFile17 } from "fs/promises";
30733
- import * as path61 from "path";
30886
+ import * as path62 from "path";
30734
30887
 
30735
30888
  // src/hooks/extractors.ts
30736
30889
  function extractCurrentPhase(planContent) {
@@ -30775,13 +30928,13 @@ function extractCurrentPhaseFromPlan2(plan) {
30775
30928
  // src/turbo/lean/state.ts
30776
30929
  init_logger();
30777
30930
  import * as fs29 from "fs";
30778
- import * as path60 from "path";
30931
+ import * as path61 from "path";
30779
30932
  var STATE_FILE3 = "turbo-state.json";
30780
30933
  function nowISO3() {
30781
30934
  return new Date().toISOString();
30782
30935
  }
30783
30936
  function ensureSwarmDir2(directory) {
30784
- const swarmDir = path60.resolve(directory, ".swarm");
30937
+ const swarmDir = path61.resolve(directory, ".swarm");
30785
30938
  if (!fs29.existsSync(swarmDir)) {
30786
30939
  fs29.mkdirSync(swarmDir, { recursive: true });
30787
30940
  }
@@ -30826,7 +30979,7 @@ function markStateUnreadable2(directory, reason) {
30826
30979
  }
30827
30980
  function readPersisted2(directory) {
30828
30981
  try {
30829
- const filePath = path60.join(directory, ".swarm", STATE_FILE3);
30982
+ const filePath = path61.join(directory, ".swarm", STATE_FILE3);
30830
30983
  if (!fs29.existsSync(filePath)) {
30831
30984
  const seed = emptyPersisted2();
30832
30985
  try {
@@ -30862,7 +31015,7 @@ function writePersisted2(directory, persisted) {
30862
31015
  let payload;
30863
31016
  try {
30864
31017
  ensureSwarmDir2(directory);
30865
- filePath = path60.join(directory, ".swarm", STATE_FILE3);
31018
+ filePath = path61.join(directory, ".swarm", STATE_FILE3);
30866
31019
  tmpPath = `${filePath}.tmp.${Date.now()}`;
30867
31020
  persisted.updatedAt = nowISO3();
30868
31021
  payload = `${JSON.stringify(persisted, null, 2)}
@@ -30980,7 +31133,7 @@ var _internals44 = {
30980
31133
  };
30981
31134
  function readSpecStalenessSnapshot(directory) {
30982
31135
  try {
30983
- const p = path61.join(directory, ".swarm", "spec-staleness.json");
31136
+ const p = path62.join(directory, ".swarm", "spec-staleness.json");
30984
31137
  if (!fsSync2.existsSync(p))
30985
31138
  return { stale: false };
30986
31139
  const raw = fsSync2.readFileSync(p, "utf-8");
@@ -31513,11 +31666,11 @@ function buildStatusMessage2(session, directory, sessionID) {
31513
31666
 
31514
31667
  // src/commands/unlink.ts
31515
31668
  import { existsSync as existsSync40 } from "fs";
31516
- import * as path62 from "path";
31669
+ import * as path63 from "path";
31517
31670
  var DEDUP_THRESHOLD2 = 0.6;
31518
31671
  async function copySharedKnowledgeToLocal(linkDir, localSwarmDir) {
31519
- const sharedPath = path62.join(linkDir, "knowledge.jsonl");
31520
- const localPath = path62.join(localSwarmDir, "knowledge.jsonl");
31672
+ const sharedPath = path63.join(linkDir, "knowledge.jsonl");
31673
+ const localPath = path63.join(localSwarmDir, "knowledge.jsonl");
31521
31674
  if (!existsSync40(sharedPath))
31522
31675
  return 0;
31523
31676
  const sharedEntries = await readKnowledge(sharedPath);
@@ -31552,7 +31705,7 @@ async function handleUnlinkCommand(directory, args) {
31552
31705
  let copied = 0;
31553
31706
  if (copyBack) {
31554
31707
  try {
31555
- copied = await copySharedKnowledgeToLocal(linkDir, path62.join(directory, ".swarm"));
31708
+ copied = await copySharedKnowledgeToLocal(linkDir, path63.join(directory, ".swarm"));
31556
31709
  } catch (error2) {
31557
31710
  return `\u274C Failed to copy shared knowledge back to local: ${error2 instanceof Error ? error2.message : String(error2)}`;
31558
31711
  }
@@ -31714,7 +31867,7 @@ function buildDetailedHelp(commandName, entry) {
31714
31867
  async function handleHelpCommand(ctx) {
31715
31868
  const targetCommand = ctx.args.join(" ");
31716
31869
  if (!targetCommand) {
31717
- const { buildHelpText } = await import("./index-3qwaydq1.js");
31870
+ const { buildHelpText } = await import("./index-nvmy7xmj.js");
31718
31871
  return buildHelpText();
31719
31872
  }
31720
31873
  const tokens = targetCommand.split(/\s+/);
@@ -31723,7 +31876,7 @@ async function handleHelpCommand(ctx) {
31723
31876
  return _internals46.buildDetailedHelp(resolved.key, resolved.entry);
31724
31877
  }
31725
31878
  const similar = _internals46.findSimilarCommands(targetCommand);
31726
- const { buildHelpText: fullHelp } = await import("./index-3qwaydq1.js");
31879
+ const { buildHelpText: fullHelp } = await import("./index-nvmy7xmj.js");
31727
31880
  if (similar.length > 0) {
31728
31881
  return `Command '/swarm ${targetCommand}' not found.
31729
31882
 
@@ -31856,7 +32009,7 @@ var COMMAND_REGISTRY = {
31856
32009
  },
31857
32010
  "guardrail explain": {
31858
32011
  handler: async (ctx) => {
31859
- const { handleGuardrailExplain } = await import("./guardrail-explain-ynge4ww3.js");
32012
+ const { handleGuardrailExplain } = await import("./guardrail-explain-hjz1k6w0.js");
31860
32013
  return handleGuardrailExplain(ctx.directory, ctx.args);
31861
32014
  },
31862
32015
  description: "Dry-run: show what the guardrails would do to a command or write target (executes nothing)",
@@ -31866,7 +32019,7 @@ var COMMAND_REGISTRY = {
31866
32019
  },
31867
32020
  "guardrail-log": {
31868
32021
  handler: async (ctx) => {
31869
- const { handleGuardrailLog } = await import("./guardrail-log-8mqqsssq.js");
32022
+ const { handleGuardrailLog } = await import("./guardrail-log-5240bawg.js");
31870
32023
  return handleGuardrailLog(ctx.directory, ctx.args);
31871
32024
  },
31872
32025
  description: "Read the guardrail decision log (use --blocks-only for blocks)",
@@ -32646,24 +32799,24 @@ function validateAliases() {
32646
32799
  continue;
32647
32800
  }
32648
32801
  const visited = new Set;
32649
- const path63 = [];
32802
+ const path64 = [];
32650
32803
  let current = target;
32651
32804
  while (current) {
32652
32805
  const currentEntry = COMMAND_REGISTRY[current];
32653
32806
  if (!currentEntry)
32654
32807
  break;
32655
32808
  if (visited.has(current)) {
32656
- const cycleStart = path63.indexOf(current);
32809
+ const cycleStart = path64.indexOf(current);
32657
32810
  const fullChain = [
32658
32811
  name,
32659
- ...path63.slice(0, cycleStart > 0 ? cycleStart : path63.length),
32812
+ ...path64.slice(0, cycleStart > 0 ? cycleStart : path64.length),
32660
32813
  current
32661
32814
  ].join(" \u2192 ");
32662
32815
  errors.push(`Circular alias detected: ${fullChain}`);
32663
32816
  break;
32664
32817
  }
32665
32818
  visited.add(current);
32666
- path63.push(current);
32819
+ path64.push(current);
32667
32820
  current = currentEntry.aliasOf || "";
32668
32821
  }
32669
32822
  }
@@ -34002,7 +34155,7 @@ init_logger();
34002
34155
 
34003
34156
  // src/hooks/guardrails/destructive-command.ts
34004
34157
  import * as fsSync3 from "fs";
34005
- import * as path63 from "path";
34158
+ import * as path64 from "path";
34006
34159
  var DC_MAX_UNWRAP_DEPTH = 5;
34007
34160
  var DC_SAFE_TARGETS = new Set([
34008
34161
  "node_modules",
@@ -34166,16 +34319,16 @@ function dcIsRemotePath(p) {
34166
34319
  return DC_REMOTE_PREFIXES.some((pfx) => p.startsWith(pfx));
34167
34320
  }
34168
34321
  function dcLstatAncestorWalk(targetPath, cwd) {
34169
- const normalizedTarget = path63.resolve(cwd, targetPath);
34170
- const normalizedCwd = path63.resolve(cwd);
34322
+ const normalizedTarget = path64.resolve(cwd, targetPath);
34323
+ const normalizedCwd = path64.resolve(cwd);
34171
34324
  const ancestors = [];
34172
34325
  let current = normalizedTarget;
34173
34326
  while (true) {
34174
34327
  ancestors.push(current);
34175
- const parent = path63.dirname(current);
34328
+ const parent = path64.dirname(current);
34176
34329
  if (parent === current)
34177
34330
  break;
34178
- const rel = path63.relative(normalizedCwd, current);
34331
+ const rel = path64.relative(normalizedCwd, current);
34179
34332
  if (rel === "" || rel.startsWith(".."))
34180
34333
  break;
34181
34334
  current = parent;
@@ -34214,14 +34367,14 @@ function dcValidateTargets(targets, cwd) {
34214
34367
  const lstatBlock = dcLstatAncestorWalk(t, cwd);
34215
34368
  if (lstatBlock)
34216
34369
  return lstatBlock;
34217
- const basename12 = path63.basename(t);
34218
- if (t === basename12 && DC_SAFE_TARGETS.has(t)) {
34370
+ const basename13 = path64.basename(t);
34371
+ if (t === basename13 && DC_SAFE_TARGETS.has(t)) {
34219
34372
  continue;
34220
34373
  }
34221
34374
  if (DC_FS_ROOTS.has(t) || DC_FS_ROOTS.has(t.replace(/\//g, "\\"))) {
34222
34375
  return `BLOCKED: Destructive command targets filesystem root "${t}"`;
34223
34376
  }
34224
- if (path63.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
34377
+ if (path64.isAbsolute(t) || /^[A-Za-z]:/.test(t)) {
34225
34378
  for (const blocked of DC_BLOCKED_ABSOLUTE_PREFIXES) {
34226
34379
  if (t.startsWith(blocked)) {
34227
34380
  return `BLOCKED: Destructive command targets system path "${t}" which is under protected prefix "${blocked}"`;
@@ -34236,9 +34389,9 @@ function dcCheckJunctionCreation(segment, cwd) {
34236
34389
  if (mklinkMatch) {
34237
34390
  const target = mklinkMatch[2].trim();
34238
34391
  if (!dcHasUnresolvableVars(target)) {
34239
- const resolved = path63.resolve(cwd, target);
34240
- const rel = path63.relative(cwd, resolved);
34241
- if (rel.startsWith("..") || path63.isAbsolute(rel)) {
34392
+ const resolved = path64.resolve(cwd, target);
34393
+ const rel = path64.relative(cwd, resolved);
34394
+ if (rel.startsWith("..") || path64.isAbsolute(rel)) {
34242
34395
  return `BLOCKED: Junction/symlink creation targeting path outside working directory: mklink target "${target}" resolves to "${resolved}" which is outside "${cwd}". Creating junctions to external paths and then deleting them recursively can destroy data.`;
34243
34396
  }
34244
34397
  }
@@ -34250,9 +34403,9 @@ function dcCheckJunctionCreation(segment, cwd) {
34250
34403
  if (newItemMatch) {
34251
34404
  const target = newItemMatch[1].trim();
34252
34405
  if (!dcHasUnresolvableVars(target)) {
34253
- const resolved = path63.resolve(cwd, target);
34254
- const rel = path63.relative(cwd, resolved);
34255
- if (rel.startsWith("..") || path63.isAbsolute(rel)) {
34406
+ const resolved = path64.resolve(cwd, target);
34407
+ const rel = path64.relative(cwd, resolved);
34408
+ if (rel.startsWith("..") || path64.isAbsolute(rel)) {
34256
34409
  return `BLOCKED: Junction/symlink creation targeting path outside working directory: New-Item target "${target}" resolves to "${resolved}" which is outside "${cwd}". This pattern caused the K2.6 data-loss incident.`;
34257
34410
  }
34258
34411
  }
@@ -34262,9 +34415,9 @@ function dcCheckJunctionCreation(segment, cwd) {
34262
34415
  if (lnMatch) {
34263
34416
  const target = lnMatch[1].trim();
34264
34417
  if (!dcHasUnresolvableVars(target)) {
34265
- const resolved = path63.resolve(cwd, target);
34266
- const rel = path63.relative(cwd, resolved);
34267
- if (rel.startsWith("..") || path63.isAbsolute(rel)) {
34418
+ const resolved = path64.resolve(cwd, target);
34419
+ const rel = path64.relative(cwd, resolved);
34420
+ if (rel.startsWith("..") || path64.isAbsolute(rel)) {
34268
34421
  return `BLOCKED: Symlink creation targeting path outside working directory: ln -s target "${target}" resolves to "${resolved}" which is outside "${cwd}". Symlinks to external paths combined with recursive deletion can destroy data.`;
34269
34422
  }
34270
34423
  }
@@ -34635,10 +34788,10 @@ function classifySwarmCommandChatFallbackUse(resolved) {
34635
34788
  init_executor();
34636
34789
 
34637
34790
  // src/hooks/shell-write-detect.ts
34638
- import * as path64 from "path";
34791
+ import * as path65 from "path";
34639
34792
  import parse from "bash-parser";
34640
- function buildDedupeKey(category, operator, path65) {
34641
- return `${category}|${operator}|${path65 ?? "null"}`;
34793
+ function buildDedupeKey(category, operator, path66) {
34794
+ return `${category}|${operator}|${path66 ?? "null"}`;
34642
34795
  }
34643
34796
  var REDIRECT_WRITE_TOKENS = new Set([
34644
34797
  "GREAT",
@@ -34698,16 +34851,16 @@ function detectProcessSubstitutionWrites(command) {
34698
34851
  results.push(builtinResult);
34699
34852
  const appendMatch = stage.match(/^\s*(.*?)\s*>>(\s*)(\S+)\s*$/);
34700
34853
  if (appendMatch) {
34701
- const path65 = appendMatch[3];
34702
- if (path65 && !isNullDevice(path65)) {
34703
- results.push({ category: "redirect", operator: ">>", path: path65 });
34854
+ const path66 = appendMatch[3];
34855
+ if (path66 && !isNullDevice(path66)) {
34856
+ results.push({ category: "redirect", operator: ">>", path: path66 });
34704
34857
  }
34705
34858
  } else {
34706
34859
  const writeMatch = stage.match(/^\s*(.*?)\s*>(?!>)(\s*)(\S+)\s*$/);
34707
34860
  if (writeMatch) {
34708
- const path65 = writeMatch[3];
34709
- if (path65 && !isNullDevice(path65)) {
34710
- results.push({ category: "redirect", operator: ">", path: path65 });
34861
+ const path66 = writeMatch[3];
34862
+ if (path66 && !isNullDevice(path66)) {
34863
+ results.push({ category: "redirect", operator: ">", path: path66 });
34711
34864
  }
34712
34865
  }
34713
34866
  }
@@ -34881,8 +35034,8 @@ function extractRedirectPath(fileNode) {
34881
35034
  return null;
34882
35035
  return text;
34883
35036
  }
34884
- function isNullDevice(path65) {
34885
- return path65 === "/dev/null" || path65 === "/dev/zero" || path65 === "/dev/urandom";
35037
+ function isNullDevice(path66) {
35038
+ return path66 === "/dev/null" || path66 === "/dev/zero" || path66 === "/dev/urandom";
34886
35039
  }
34887
35040
  function isNumeric(s) {
34888
35041
  return /^\d+$/.test(s);
@@ -34902,12 +35055,12 @@ function detectRedirects(cmd) {
34902
35055
  if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
34903
35056
  continue;
34904
35057
  const fileNode = r.file;
34905
- const path65 = extractRedirectPath(fileNode);
35058
+ const path66 = extractRedirectPath(fileNode);
34906
35059
  const opLabel = operatorLabel(opNode);
34907
35060
  if (REDIRECT_WRITE_TOKENS.has(opType)) {
34908
- results.push({ category: "redirect", operator: opLabel, path: path65 });
35061
+ results.push({ category: "redirect", operator: opLabel, path: path66 });
34909
35062
  } else if (REDIRECT_HERE_TOKENS.has(opType)) {
34910
- results.push({ category: "here_doc", operator: opLabel, path: path65 });
35063
+ results.push({ category: "here_doc", operator: opLabel, path: path66 });
34911
35064
  }
34912
35065
  }
34913
35066
  return results;
@@ -34950,9 +35103,9 @@ function detectBuiltinWrites(cmd) {
34950
35103
  const suffixWords2 = getSuffixWords(cmd);
34951
35104
  for (const word of suffixWords2) {
34952
35105
  if (word.startsWith("of=")) {
34953
- const path65 = word.slice(3);
34954
- if (path65 && !isNullDevice(path65)) {
34955
- results.push({ category: "builtin_write", operator: "dd of=", path: path65 });
35106
+ const path66 = word.slice(3);
35107
+ if (path66 && !isNullDevice(path66)) {
35108
+ results.push({ category: "builtin_write", operator: "dd of=", path: path66 });
34956
35109
  }
34957
35110
  }
34958
35111
  }
@@ -35071,12 +35224,12 @@ function detectNetworkDownloaders(cmd) {
35071
35224
  for (let i = 0;i < suffixWords.length; i++) {
35072
35225
  const word = suffixWords[i];
35073
35226
  if (word === "-o" && i + 1 < suffixWords.length) {
35074
- const path65 = suffixWords[i + 1];
35075
- if (!path65.startsWith("-")) {
35227
+ const path66 = suffixWords[i + 1];
35228
+ if (!path66.startsWith("-")) {
35076
35229
  results.push({
35077
35230
  category: "network_download",
35078
35231
  operator: "curl -o",
35079
- path: path65
35232
+ path: path66
35080
35233
  });
35081
35234
  }
35082
35235
  } else if (word.startsWith("-o") && word.length > 2) {
@@ -35091,12 +35244,12 @@ function detectNetworkDownloaders(cmd) {
35091
35244
  for (let i = 0;i < suffixWords.length; i++) {
35092
35245
  const word = suffixWords[i];
35093
35246
  if (word === "-O" && i + 1 < suffixWords.length) {
35094
- const path65 = suffixWords[i + 1];
35095
- if (!path65.startsWith("-")) {
35247
+ const path66 = suffixWords[i + 1];
35248
+ if (!path66.startsWith("-")) {
35096
35249
  results.push({
35097
35250
  category: "network_download",
35098
35251
  operator: "wget -O",
35099
- path: path65
35252
+ path: path66
35100
35253
  });
35101
35254
  }
35102
35255
  } else if (word.startsWith("-O") && word.length > 2) {
@@ -35205,9 +35358,9 @@ function detectGitDestructive(cmd) {
35205
35358
  if (first === "checkout") {
35206
35359
  const dashDashIdx = suffixWords.indexOf("--");
35207
35360
  if (dashDashIdx !== -1 && dashDashIdx + 1 < suffixWords.length) {
35208
- const path65 = suffixWords[dashDashIdx + 1];
35209
- const op = path65 === "." ? "git checkout -- ." : "git checkout --";
35210
- results.push({ category: "git_destructive", operator: op, path: path65 });
35361
+ const path66 = suffixWords[dashDashIdx + 1];
35362
+ const op = path66 === "." ? "git checkout -- ." : "git checkout --";
35363
+ results.push({ category: "git_destructive", operator: op, path: path66 });
35211
35364
  }
35212
35365
  } else if (first === "restore") {
35213
35366
  const hasHard = suffixWords.some((w) => w === "--hard" || w === "-H" || w.startsWith("-") && w.includes("H"));
@@ -35327,10 +35480,10 @@ function detectPowerShellWrites(command) {
35327
35480
  if (redirectMatch) {
35328
35481
  const beforeRedirect = redirectMatch[1];
35329
35482
  const op = redirectMatch[2];
35330
- const path65 = redirectMatch[3];
35483
+ const path66 = redirectMatch[3];
35331
35484
  const fdRedirectPattern = /\d>\s*$|\s\d>&$/;
35332
35485
  if (!fdRedirectPattern.test(`${beforeRedirect} ${op}`)) {
35333
- results.push({ category: "redirect", operator: op, path: path65 });
35486
+ results.push({ category: "redirect", operator: op, path: path66 });
35334
35487
  }
35335
35488
  }
35336
35489
  const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
@@ -35343,12 +35496,12 @@ function detectPowerShellWrites(command) {
35343
35496
  }
35344
35497
  const iwrMatch = trimmed.match(/^(?:Invoke-WebRequest|curl)\s.*?(?:-OutFile\s+(\S+)|-o\s+(\S+))/i);
35345
35498
  if (iwrMatch) {
35346
- const path65 = iwrMatch[1] || iwrMatch[2];
35347
- if (path65) {
35499
+ const path66 = iwrMatch[1] || iwrMatch[2];
35500
+ if (path66) {
35348
35501
  results.push({
35349
35502
  category: "network_download",
35350
35503
  operator: "Invoke-WebRequest -OutFile",
35351
- path: path65
35504
+ path: path66
35352
35505
  });
35353
35506
  }
35354
35507
  }
@@ -35360,15 +35513,15 @@ function detectPowerShellWrites(command) {
35360
35513
  const rest = cmd.slice(cmdletMatch[0].length).trim();
35361
35514
  const pathFlagMatch = rest.match(/(?:-Path|-FilePath|-LiteralPath)\s+("([^"]+)"|'([^']+)'|(\S+))/i);
35362
35515
  if (pathFlagMatch) {
35363
- const path65 = pathFlagMatch[2] ?? pathFlagMatch[3] ?? pathFlagMatch[4] ?? "";
35364
- return { category: "redirect", operator: cmdletName, path: path65 };
35516
+ const path66 = pathFlagMatch[2] ?? pathFlagMatch[3] ?? pathFlagMatch[4] ?? "";
35517
+ return { category: "redirect", operator: cmdletName, path: path66 };
35365
35518
  }
35366
35519
  const tokens = rest.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
35367
35520
  for (const token of tokens) {
35368
35521
  if (token.startsWith("-"))
35369
35522
  continue;
35370
- const path65 = token.replace(/^["']|["']$/g, "");
35371
- return { category: "redirect", operator: cmdletName, path: path65 };
35523
+ const path66 = token.replace(/^["']|["']$/g, "");
35524
+ return { category: "redirect", operator: cmdletName, path: path66 };
35372
35525
  }
35373
35526
  return null;
35374
35527
  }
@@ -35384,9 +35537,9 @@ function detectPowerShellWrites(command) {
35384
35537
  for (const token of tokens) {
35385
35538
  if (token.startsWith("-"))
35386
35539
  continue;
35387
- const path65 = token.replace(/^["']|["']$/g, "");
35388
- if (path65) {
35389
- results.push({ category: "redirect", operator: cmdletName, path: path65 });
35540
+ const path66 = token.replace(/^["']|["']$/g, "");
35541
+ if (path66) {
35542
+ results.push({ category: "redirect", operator: cmdletName, path: path66 });
35390
35543
  break;
35391
35544
  }
35392
35545
  }
@@ -35399,8 +35552,8 @@ function detectPowerShellWrites(command) {
35399
35552
  const rest = cmd.slice(opMatch[0].length).trim();
35400
35553
  const destFlagMatch = rest.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
35401
35554
  if (destFlagMatch) {
35402
- const path65 = destFlagMatch[1].replace(/^["']|["']$/g, "");
35403
- return { category: "builtin_write", operator: cmdletName, path: path65 };
35555
+ const path66 = destFlagMatch[1].replace(/^["']|["']$/g, "");
35556
+ return { category: "builtin_write", operator: cmdletName, path: path66 };
35404
35557
  }
35405
35558
  const tokens = [];
35406
35559
  const flagTakingValue = new Set([
@@ -35439,11 +35592,11 @@ function detectPowerShellWrites(command) {
35439
35592
  }
35440
35593
  }
35441
35594
  if (tokens.length >= 2) {
35442
- const path65 = tokens[tokens.length - 1].replace(/^["']|["']$/g, "");
35443
- return { category: "builtin_write", operator: cmdletName, path: path65 };
35595
+ const path66 = tokens[tokens.length - 1].replace(/^["']|["']$/g, "");
35596
+ return { category: "builtin_write", operator: cmdletName, path: path66 };
35444
35597
  } else if (tokens.length === 1) {
35445
- const path65 = tokens[0].replace(/^["']|["']$/g, "");
35446
- return { category: "builtin_write", operator: cmdletName, path: path65 };
35598
+ const path66 = tokens[0].replace(/^["']|["']$/g, "");
35599
+ return { category: "builtin_write", operator: cmdletName, path: path66 };
35447
35600
  }
35448
35601
  return null;
35449
35602
  }
@@ -35457,14 +35610,14 @@ function detectPowerShellWrites(command) {
35457
35610
  const afterCmdlet = pipeFileOpMatch[2].trim();
35458
35611
  const destFlagMatch = afterCmdlet.match(/-Destination\s+(\S+|"[^"]+"|'[^']+')/i);
35459
35612
  if (destFlagMatch) {
35460
- const path65 = destFlagMatch[1].replace(/^["']|["']$/g, "");
35461
- results.push({ category: "builtin_write", operator: cmdletName, path: path65 });
35613
+ const path66 = destFlagMatch[1].replace(/^["']|["']$/g, "");
35614
+ results.push({ category: "builtin_write", operator: cmdletName, path: path66 });
35462
35615
  } else {
35463
35616
  const tokens = afterCmdlet.match(/(?:[^\s"-]+|"[^"]*"|'[^']*'|-[^\s]+)/g) ?? [];
35464
35617
  const nonFlagTokens = tokens.filter((t) => !t.startsWith("-") && t.length > 0);
35465
35618
  if (nonFlagTokens.length > 0) {
35466
- const path65 = nonFlagTokens[nonFlagTokens.length - 1].replace(/^["']|["']$/g, "");
35467
- results.push({ category: "builtin_write", operator: cmdletName, path: path65 });
35619
+ const path66 = nonFlagTokens[nonFlagTokens.length - 1].replace(/^["']|["']$/g, "");
35620
+ results.push({ category: "builtin_write", operator: cmdletName, path: path66 });
35468
35621
  }
35469
35622
  }
35470
35623
  }
@@ -35517,10 +35670,10 @@ function detectCmdWrites(command) {
35517
35670
  if (redirectMatch) {
35518
35671
  const beforeRedirect = redirectMatch[1];
35519
35672
  const op = redirectMatch[2];
35520
- const path65 = redirectMatch[3];
35673
+ const path66 = redirectMatch[3];
35521
35674
  const fdRedirectPattern = /\d>&?$/;
35522
35675
  if (!fdRedirectPattern.test(beforeRedirect)) {
35523
- results.push({ category: "redirect", operator: op, path: path65 });
35676
+ results.push({ category: "redirect", operator: op, path: path66 });
35524
35677
  }
35525
35678
  }
35526
35679
  const leadingRedirect = innerCommand.match(/^((?:>){1,2})\s+(\S+)$/);
@@ -35578,8 +35731,8 @@ function detectCmdWrites(command) {
35578
35731
  const rawTokens = rest.match(/(\/?[^\s]+|"[^"]*"|'[^']*')/g) ?? [];
35579
35732
  const tokens = rawTokens.filter((t) => !t.startsWith("/"));
35580
35733
  if (tokens.length > 0) {
35581
- const path65 = tokens[0].replace(/^["']|["']$/g, "");
35582
- return { category: "builtin_write", operator: "del", path: path65 };
35734
+ const path66 = tokens[0].replace(/^["']|["']$/g, "");
35735
+ return { category: "builtin_write", operator: "del", path: path66 };
35583
35736
  }
35584
35737
  return null;
35585
35738
  }
@@ -35589,16 +35742,16 @@ function detectCmdWrites(command) {
35589
35742
  }
35590
35743
  const rdMatch = innerCommand.match(/^rd\s+(?:\/s\s+|\/q\s+)*(\S+)/i);
35591
35744
  if (rdMatch) {
35592
- const path65 = rdMatch[1].replace(/^["']|["']$/g, "");
35593
- if (!path65.startsWith("/")) {
35594
- results.push({ category: "builtin_write", operator: "rd", path: path65 });
35745
+ const path66 = rdMatch[1].replace(/^["']|["']$/g, "");
35746
+ if (!path66.startsWith("/")) {
35747
+ results.push({ category: "builtin_write", operator: "rd", path: path66 });
35595
35748
  }
35596
35749
  }
35597
35750
  const mdMatch = trimmed.match(/^md\s+(\S+)/i);
35598
35751
  if (mdMatch) {
35599
- const path65 = mdMatch[1].replace(/^["']|["']$/g, "");
35600
- if (!path65.startsWith("/")) {
35601
- results.push({ category: "builtin_write", operator: "md", path: path65 });
35752
+ const path66 = mdMatch[1].replace(/^["']|["']$/g, "");
35753
+ if (!path66.startsWith("/")) {
35754
+ results.push({ category: "builtin_write", operator: "md", path: path66 });
35602
35755
  }
35603
35756
  }
35604
35757
  const echoMatch = trimmed.match(/^echo\s+(\S+.*?)\s+((?:>){1,2})\s*(\S+)$/i);
@@ -35714,10 +35867,10 @@ function resolvePath(pathText, cwd) {
35714
35867
  return null;
35715
35868
  const isWindowsPath = /^[a-zA-Z]:[\\\\/]/.test(cwd) || cwd.includes("\\");
35716
35869
  if (isWindowsPath) {
35717
- return path64.win32.resolve(cwd, pathText);
35870
+ return path65.win32.resolve(cwd, pathText);
35718
35871
  }
35719
- const normalizedRelativeWindowsPath = !path64.posix.isAbsolute(pathText) && !/^[a-zA-Z]:[\\/]/.test(pathText) ? pathText.replace(/\\/g, "/") : pathText;
35720
- return path64.posix.resolve(cwd, normalizedRelativeWindowsPath);
35872
+ const normalizedRelativeWindowsPath = !path65.posix.isAbsolute(pathText) && !/^[a-zA-Z]:[\\/]/.test(pathText) ? pathText.replace(/\\/g, "/") : pathText;
35873
+ return path65.posix.resolve(cwd, normalizedRelativeWindowsPath);
35721
35874
  }
35722
35875
  function getCdTarget(cmd) {
35723
35876
  if (!cmd || typeof cmd !== "object")
@@ -35784,7 +35937,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
35784
35937
  for (const cmd of node.commands) {
35785
35938
  const cdTarget = getCdTarget(cmd);
35786
35939
  if (cdTarget) {
35787
- currentStack[0] = path64.posix.resolve(currentStack[0] ?? "/", cdTarget);
35940
+ currentStack[0] = path65.posix.resolve(currentStack[0] ?? "/", cdTarget);
35788
35941
  collectWritesWithNodes(cmd, out, currentStack);
35789
35942
  } else {
35790
35943
  collectWritesWithNodes(cmd, out, currentStack);
@@ -35830,7 +35983,7 @@ function collectWritesWithNodes(node, out, cwdStack) {
35830
35983
  const effectiveCwd = cwdStack[0] ?? "/";
35831
35984
  const cdTarget = getCdTarget(node);
35832
35985
  if (cdTarget) {
35833
- cwdStack[0] = path64.posix.resolve(cwdStack[0] ?? "/", cdTarget);
35986
+ cwdStack[0] = path65.posix.resolve(cwdStack[0] ?? "/", cdTarget);
35834
35987
  return;
35835
35988
  }
35836
35989
  const writesFromRedirs = getWritesFromCommandRedirs(node, effectiveCwd);
@@ -35876,12 +36029,12 @@ function getWritesFromRedirectNode(redirect, _context) {
35876
36029
  if (!opType || !REDIRECT_ALL_WRITE_TOKENS.has(opType))
35877
36030
  return [];
35878
36031
  const fileNode = r.file;
35879
- const path65 = extractRedirectPath(fileNode);
36032
+ const path66 = extractRedirectPath(fileNode);
35880
36033
  const opLabel = operatorLabel(opNode);
35881
36034
  if (REDIRECT_WRITE_TOKENS.has(opType)) {
35882
- return [{ category: "redirect", operator: opLabel, path: path65 }];
36035
+ return [{ category: "redirect", operator: opLabel, path: path66 }];
35883
36036
  } else if (REDIRECT_HERE_TOKENS.has(opType)) {
35884
- return [{ category: "here_doc", operator: opLabel, path: path65 }];
36037
+ return [{ category: "here_doc", operator: opLabel, path: path66 }];
35885
36038
  }
35886
36039
  return [];
35887
36040
  }
@@ -36635,7 +36788,7 @@ function evidenceToWorkflowState(evidence) {
36635
36788
  }
36636
36789
  async function readPlanFromDisk(directory) {
36637
36790
  try {
36638
- const planPath = path65.join(directory, ".swarm", "plan.json");
36791
+ const planPath = path66.join(directory, ".swarm", "plan.json");
36639
36792
  const content = await fs30.readFile(planPath, "utf-8");
36640
36793
  const parsed = JSON.parse(content);
36641
36794
  return PlanSchema.parse(parsed);
@@ -36646,7 +36799,7 @@ async function readPlanFromDisk(directory) {
36646
36799
  async function readGateEvidenceFromDisk(directory) {
36647
36800
  const evidenceMap = new Map;
36648
36801
  try {
36649
- const evidenceDir = path65.join(directory, ".swarm", "evidence");
36802
+ const evidenceDir = path66.join(directory, ".swarm", "evidence");
36650
36803
  const entries = await fs30.readdir(evidenceDir, { withFileTypes: true });
36651
36804
  for (const entry of entries) {
36652
36805
  if (!entry.isFile() || !entry.name.endsWith(".json")) {
@@ -36657,7 +36810,7 @@ async function readGateEvidenceFromDisk(directory) {
36657
36810
  continue;
36658
36811
  }
36659
36812
  try {
36660
- const filePath = path65.join(evidenceDir, entry.name);
36813
+ const filePath = path66.join(evidenceDir, entry.name);
36661
36814
  const content = await fs30.readFile(filePath, "utf-8");
36662
36815
  const parsed = JSON.parse(content);
36663
36816
  if (parsed && typeof parsed.taskId === "string" && Array.isArray(parsed.required_gates)) {