opencode-swarm 7.74.0 → 7.74.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -52,7 +52,7 @@ var package_default;
52
52
  var init_package = __esm(() => {
53
53
  package_default = {
54
54
  name: "opencode-swarm",
55
- version: "7.74.0",
55
+ version: "7.74.2",
56
56
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
57
57
  main: "dist/index.js",
58
58
  types: "dist/index.d.ts",
@@ -17572,7 +17572,7 @@ var init_tool_metadata = __esm(() => {
17572
17572
  agents: ["architect", "coder"]
17573
17573
  },
17574
17574
  knowledge_archive: {
17575
- description: "archive (default), quarantine, or purge a swarm knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
17575
+ description: "archive (default), quarantine, or purge a swarm or hive knowledge entry by ID with an immutable audit tombstone; purge requires an admin flag",
17576
17576
  agents: ["architect"]
17577
17577
  },
17578
17578
  swarm_memory_recall: {
@@ -18588,7 +18588,11 @@ var init_schema = __esm(() => {
18588
18588
  cold_start_max_age_phases: exports_external.number().int().min(0).max(100).default(3),
18589
18589
  synonym_min_cooccurrence: exports_external.number().int().min(1).max(100).default(3),
18590
18590
  synonym_map_max_pairs: exports_external.number().int().min(1).max(1e4).default(500)
18591
- }).optional()
18591
+ }).optional(),
18592
+ enrichment: exports_external.object({
18593
+ max_calls_per_day: exports_external.number().int().min(0).max(1000).default(30),
18594
+ quota_window: exports_external.enum(["utc", "local"]).default("utc")
18595
+ }).default({ max_calls_per_day: 30, quota_window: "utc" })
18592
18596
  });
18593
18597
  MemoryConfigSchema = exports_external.object({
18594
18598
  enabled: exports_external.boolean().default(false),
@@ -18655,7 +18659,7 @@ var init_schema = __esm(() => {
18655
18659
  llm_timeout_ms: exports_external.number().int().min(5000).max(600000).default(300000),
18656
18660
  skill_generation_enabled: exports_external.boolean().default(true),
18657
18661
  skill_generation_mode: exports_external.enum(["draft", "active"]).default("draft"),
18658
- min_skill_confidence: exports_external.number().min(0).max(1).default(0.85),
18662
+ min_skill_confidence: exports_external.number().min(0).max(1).default(0.7),
18659
18663
  min_skill_confirmations: exports_external.number().int().min(1).max(50).default(2)
18660
18664
  });
18661
18665
  ArchitecturalSupervisionConfigSchema = exports_external.object({
@@ -37561,34 +37565,56 @@ var init_event_bus = __esm(() => {
37561
37565
  init_utils();
37562
37566
  });
37563
37567
 
37568
+ // src/evidence/task-file.ts
37569
+ import { renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
37570
+ import * as path12 from "path";
37571
+ function taskEvidenceRelPath(taskId) {
37572
+ return path12.join("evidence", `${taskId}.json`);
37573
+ }
37574
+ function taskEvidencePath(directory, taskId) {
37575
+ return path12.join(directory, ".swarm", taskEvidenceRelPath(taskId));
37576
+ }
37577
+ async function atomicWriteFile(targetPath, content) {
37578
+ const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
37579
+ try {
37580
+ await bunWrite(tempPath, content);
37581
+ _internals14.renameSync(tempPath, targetPath);
37582
+ } finally {
37583
+ try {
37584
+ _internals14.unlinkSync(tempPath);
37585
+ } catch {}
37586
+ }
37587
+ }
37588
+ var _internals14;
37589
+ var init_task_file = __esm(() => {
37590
+ init_bun_compat();
37591
+ init_lock();
37592
+ _internals14 = {
37593
+ renameSync: renameSync6,
37594
+ unlinkSync: unlinkSync4
37595
+ };
37596
+ });
37597
+
37564
37598
  // src/hooks/knowledge-events.ts
37565
37599
  import { existsSync as existsSync9 } from "fs";
37566
- import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile3 } from "fs/promises";
37567
- import * as path12 from "path";
37600
+ import { appendFile as appendFile2, mkdir as mkdir2, readFile as readFile2, stat as stat2 } from "fs/promises";
37601
+ import * as path13 from "path";
37568
37602
  function resolveKnowledgeEventsPath(directory) {
37569
- return path12.join(directory, ".swarm", "knowledge-events.jsonl");
37603
+ return path13.join(directory, ".swarm", "knowledge-events.jsonl");
37604
+ }
37605
+ function resolveKnowledgeCounterBaselinePath(directory) {
37606
+ return path13.join(directory, ".swarm", "knowledge-counter-baseline.json");
37570
37607
  }
37571
37608
  function resolveLegacyApplicationLogPath(directory) {
37572
- return path12.join(directory, ".swarm", "knowledge-application.jsonl");
37609
+ return path13.join(directory, ".swarm", "knowledge-application.jsonl");
37573
37610
  }
37574
37611
  async function readKnowledgeEvents(directory) {
37575
37612
  const filePath = resolveKnowledgeEventsPath(directory);
37576
37613
  if (!existsSync9(filePath))
37577
37614
  return [];
37578
37615
  const content = await readFile2(filePath, "utf-8");
37579
- const out = [];
37580
- for (const line of content.split(`
37581
- `)) {
37582
- const trimmed = line.trim();
37583
- if (!trimmed)
37584
- continue;
37585
- try {
37586
- out.push(JSON.parse(trimmed));
37587
- } catch {
37588
- warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
37589
- }
37590
- }
37591
- return out;
37616
+ return parseEventLines(content.split(`
37617
+ `), filePath);
37592
37618
  }
37593
37619
  async function readLegacyApplicationRecords(directory) {
37594
37620
  const filePath = resolveLegacyApplicationLogPath(directory);
@@ -37624,6 +37650,29 @@ function emptyRollup() {
37624
37650
  violation_timestamps: []
37625
37651
  };
37626
37652
  }
37653
+ function cloneRollup(input) {
37654
+ return {
37655
+ ...emptyRollup(),
37656
+ ...input,
37657
+ violation_timestamps: [...input.violation_timestamps ?? []]
37658
+ };
37659
+ }
37660
+ function cloneRollupMap(input) {
37661
+ const out = new Map;
37662
+ for (const [id, rollup] of input) {
37663
+ out.set(id, cloneRollup(rollup));
37664
+ }
37665
+ return out;
37666
+ }
37667
+ function normalizeRollupTimestamps(rollup) {
37668
+ if (rollup.violation_timestamps.length > 1) {
37669
+ rollup.violation_timestamps.sort((a, b) => a < b ? 1 : a > b ? -1 : 0);
37670
+ }
37671
+ if (rollup.violation_timestamps.length > MAX_VIOLATION_TIMESTAMPS) {
37672
+ rollup.violation_timestamps = rollup.violation_timestamps.slice(0, MAX_VIOLATION_TIMESTAMPS);
37673
+ }
37674
+ return rollup;
37675
+ }
37627
37676
  function get(map3, id) {
37628
37677
  let r = map3.get(id);
37629
37678
  if (!r) {
@@ -37637,9 +37686,72 @@ function maxIso(current, candidate) {
37637
37686
  return candidate;
37638
37687
  return candidate > current ? candidate : current;
37639
37688
  }
37640
- function recomputeCounters(events, legacyRecords = []) {
37689
+ async function readCounterBaseline(directory) {
37690
+ const filePath = resolveKnowledgeCounterBaselinePath(directory);
37691
+ if (!existsSync9(filePath))
37692
+ return new Map;
37693
+ const raw = JSON.parse(await readFile2(filePath, "utf-8"));
37694
+ const map3 = new Map;
37695
+ for (const [id, rollup] of Object.entries(raw)) {
37696
+ map3.set(id, normalizeRollupTimestamps(cloneRollup(rollup)));
37697
+ }
37698
+ return map3;
37699
+ }
37700
+ async function statCacheKey(filePath) {
37701
+ try {
37702
+ const fileStat = await stat2(filePath);
37703
+ return `${fileStat.mtimeMs}:${fileStat.ctimeMs}:${fileStat.size}`;
37704
+ } catch (err) {
37705
+ if (err?.code === "ENOENT")
37706
+ return "missing";
37707
+ throw err;
37708
+ }
37709
+ }
37710
+ async function buildCounterRollupCacheKey(directory) {
37711
+ const [eventsKey, legacyKey, baselineKey] = await Promise.all([
37712
+ statCacheKey(resolveKnowledgeEventsPath(directory)),
37713
+ statCacheKey(resolveLegacyApplicationLogPath(directory)),
37714
+ statCacheKey(resolveKnowledgeCounterBaselinePath(directory))
37715
+ ]);
37716
+ return `${eventsKey}|${legacyKey}|${baselineKey}`;
37717
+ }
37718
+ function setCounterRollupCache(directory, key, rollups) {
37719
+ if (counterRollupCache.has(directory)) {
37720
+ counterRollupCache.delete(directory);
37721
+ }
37722
+ counterRollupCache.set(directory, {
37723
+ key,
37724
+ rollups: cloneRollupMap(rollups)
37725
+ });
37726
+ while (counterRollupCache.size > MAX_COUNTER_ROLLUP_CACHE_DIRS) {
37727
+ const oldestKey = counterRollupCache.keys().next().value;
37728
+ if (oldestKey === undefined)
37729
+ break;
37730
+ counterRollupCache.delete(oldestKey);
37731
+ }
37732
+ }
37733
+ function parseEventLines(lines, filePath) {
37734
+ const out = [];
37735
+ for (const line of lines) {
37736
+ const trimmed = line.trim();
37737
+ if (!trimmed)
37738
+ continue;
37739
+ try {
37740
+ out.push(JSON.parse(trimmed));
37741
+ } catch {
37742
+ warn(`[knowledge-events] Skipping corrupted JSONL line in ${filePath}: ${trimmed.slice(0, 80)}`);
37743
+ }
37744
+ }
37745
+ return out;
37746
+ }
37747
+ function recomputeCounters(events, legacyRecords = [], baseline = new Map) {
37641
37748
  const map3 = new Map;
37642
37749
  const retrievedIds = new Set;
37750
+ for (const [id, rollup] of baseline) {
37751
+ map3.set(id, cloneRollup(rollup));
37752
+ if ((rollup.shown_count ?? 0) > 0)
37753
+ retrievedIds.add(id);
37754
+ }
37643
37755
  for (const e of events) {
37644
37756
  switch (e.type) {
37645
37757
  case "retrieved": {
@@ -37715,22 +37827,27 @@ function recomputeCounters(events, legacyRecords = []) {
37715
37827
  }
37716
37828
  }
37717
37829
  for (const r of map3.values()) {
37718
- if (r.violation_timestamps.length > 1) {
37719
- r.violation_timestamps.sort((a, b) => a < b ? 1 : a > b ? -1 : 0);
37720
- }
37721
- if (r.violation_timestamps.length > MAX_VIOLATION_TIMESTAMPS) {
37722
- r.violation_timestamps = r.violation_timestamps.slice(0, MAX_VIOLATION_TIMESTAMPS);
37723
- }
37830
+ normalizeRollupTimestamps(r);
37724
37831
  }
37725
37832
  return map3;
37726
37833
  }
37727
37834
  async function readKnowledgeCounterRollups(directory) {
37728
37835
  try {
37729
- const [events, legacyRecords] = await Promise.all([
37836
+ const cacheKey = await buildCounterRollupCacheKey(directory);
37837
+ const cached3 = counterRollupCache.get(directory);
37838
+ if (cached3?.key === cacheKey) {
37839
+ counterRollupCache.delete(directory);
37840
+ counterRollupCache.set(directory, cached3);
37841
+ return cloneRollupMap(cached3.rollups);
37842
+ }
37843
+ const [events, legacyRecords, baseline] = await Promise.all([
37730
37844
  readKnowledgeEvents(directory),
37731
- readLegacyApplicationRecords(directory)
37845
+ readLegacyApplicationRecords(directory),
37846
+ readCounterBaseline(directory)
37732
37847
  ]);
37733
- return recomputeCounters(events, legacyRecords);
37848
+ const rollups = recomputeCounters(events, legacyRecords, baseline);
37849
+ setCounterRollupCache(directory, cacheKey, rollups);
37850
+ return cloneRollupMap(rollups);
37734
37851
  } catch (err) {
37735
37852
  warn(`[knowledge-events] readKnowledgeCounterRollups failed: ${err instanceof Error ? err.message : String(err)}`);
37736
37853
  return new Map;
@@ -37749,10 +37866,12 @@ function effectiveRetrievalOutcomes(stored, rollup) {
37749
37866
  ...rollup
37750
37867
  };
37751
37868
  }
37752
- var import_proper_lockfile3, RECEIPT_EVENT_TYPES, MAX_VIOLATION_TIMESTAMPS = 10;
37869
+ var import_proper_lockfile3, counterRollupCache, MAX_COUNTER_ROLLUP_CACHE_DIRS = 32, RECEIPT_EVENT_TYPES, MAX_VIOLATION_TIMESTAMPS = 10;
37753
37870
  var init_knowledge_events = __esm(() => {
37871
+ init_task_file();
37754
37872
  init_logger();
37755
37873
  import_proper_lockfile3 = __toESM(require_proper_lockfile(), 1);
37874
+ counterRollupCache = new Map;
37756
37875
  RECEIPT_EVENT_TYPES = new Set([
37757
37876
  "acknowledged",
37758
37877
  "applied",
@@ -37764,36 +37883,6 @@ var init_knowledge_events = __esm(() => {
37764
37883
  ]);
37765
37884
  });
37766
37885
 
37767
- // src/evidence/task-file.ts
37768
- import { renameSync as renameSync6, unlinkSync as unlinkSync4 } from "fs";
37769
- import * as path13 from "path";
37770
- function taskEvidenceRelPath(taskId) {
37771
- return path13.join("evidence", `${taskId}.json`);
37772
- }
37773
- function taskEvidencePath(directory, taskId) {
37774
- return path13.join(directory, ".swarm", taskEvidenceRelPath(taskId));
37775
- }
37776
- async function atomicWriteFile(targetPath, content) {
37777
- const tempPath = `${targetPath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
37778
- try {
37779
- await bunWrite(tempPath, content);
37780
- _internals14.renameSync(tempPath, targetPath);
37781
- } finally {
37782
- try {
37783
- _internals14.unlinkSync(tempPath);
37784
- } catch {}
37785
- }
37786
- }
37787
- var _internals14;
37788
- var init_task_file = __esm(() => {
37789
- init_bun_compat();
37790
- init_lock();
37791
- _internals14 = {
37792
- renameSync: renameSync6,
37793
- unlinkSync: unlinkSync4
37794
- };
37795
- });
37796
-
37797
37886
  // src/hooks/knowledge-store.ts
37798
37887
  import { existsSync as existsSync10 } from "fs";
37799
37888
  import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile3 } from "fs/promises";
@@ -37998,9 +38087,46 @@ async function enforceKnowledgeCap(filePath, maxEntries) {
37998
38087
  await transactKnowledge(filePath, (entries) => {
37999
38088
  if (entries.length <= maxEntries)
38000
38089
  return null;
38001
- return entries.slice(entries.length - maxEntries);
38090
+ return selectKnowledgeCapSurvivors(entries, maxEntries);
38002
38091
  });
38003
38092
  }
38093
+ function selectKnowledgeCapSurvivors(entries, maxEntries) {
38094
+ if (entries.length <= maxEntries)
38095
+ return entries;
38096
+ if (maxEntries <= 0)
38097
+ return [];
38098
+ const candidates = entries.map((entry, index) => {
38099
+ const maybeKnowledge = entry;
38100
+ return {
38101
+ entry,
38102
+ index,
38103
+ status: maybeKnowledge.status,
38104
+ outcomeSignal: computeOutcomeSignal(maybeKnowledge.retrieval_outcomes)
38105
+ };
38106
+ });
38107
+ const allPromoted = candidates.every((c) => c.status === "promoted");
38108
+ const evictable = allPromoted ? candidates : candidates.filter((c) => c.status !== "promoted");
38109
+ const targetDropCount = entries.length - maxEntries;
38110
+ const dropCount = Math.min(targetDropCount, evictable.length);
38111
+ if (dropCount <= 0)
38112
+ return entries;
38113
+ const drop = new Set([...evictable].sort((a, b) => {
38114
+ const inactiveDelta = getKnowledgeCapStatusPriority(a.status) - getKnowledgeCapStatusPriority(b.status);
38115
+ if (inactiveDelta !== 0)
38116
+ return inactiveDelta;
38117
+ const signalDelta = a.outcomeSignal - b.outcomeSignal;
38118
+ if (signalDelta !== 0)
38119
+ return signalDelta;
38120
+ return a.index - b.index;
38121
+ }).slice(0, dropCount).map((c) => c.index));
38122
+ return candidates.filter((c) => !drop.has(c.index)).map((c) => c.entry);
38123
+ }
38124
+ function getKnowledgeCapStatusPriority(status) {
38125
+ if (status === "archived" || status === "quarantined" || status === "quarantined_unactionable") {
38126
+ return 0;
38127
+ }
38128
+ return 1;
38129
+ }
38004
38130
  async function appendRejectedLesson(directory, lesson, maxEntries = 20) {
38005
38131
  const filePath = resolveSwarmRejectedPath(directory);
38006
38132
  await transactKnowledge(filePath, (existing) => {
@@ -38661,7 +38787,7 @@ function validateLesson(candidate, existingLessons, meta3) {
38661
38787
  };
38662
38788
  }
38663
38789
  const normalizedCandidate = candidate.normalize("NFKC").replace(INVISIBLE_FORMAT_CHARS, " ").replace(/\s+/g, " ").toLowerCase();
38664
- for (const pattern of DANGEROUS_COMMAND_PATTERNS) {
38790
+ for (const pattern of DANGEROUS_COMMAND_ERROR_PATTERNS) {
38665
38791
  if (pattern.test(normalizedCandidate)) {
38666
38792
  return {
38667
38793
  valid: false,
@@ -38671,6 +38797,16 @@ function validateLesson(candidate, existingLessons, meta3) {
38671
38797
  };
38672
38798
  }
38673
38799
  }
38800
+ for (const pattern of DANGEROUS_COMMAND_WARNING_PATTERNS) {
38801
+ if (pattern.test(normalizedCandidate)) {
38802
+ return {
38803
+ valid: true,
38804
+ layer: 2,
38805
+ reason: "potentially dangerous command pattern queued for review",
38806
+ severity: "warning"
38807
+ };
38808
+ }
38809
+ }
38674
38810
  for (const pattern of SECURITY_DEGRADING_PATTERNS) {
38675
38811
  if (pattern.test(normalizedCandidate)) {
38676
38812
  return {
@@ -38693,10 +38829,10 @@ function validateLesson(candidate, existingLessons, meta3) {
38693
38829
  }
38694
38830
  if (detectContradiction(candidate, existingLessons)) {
38695
38831
  return {
38696
- valid: false,
38832
+ valid: true,
38697
38833
  layer: 3,
38698
- reason: "lesson contradicts an existing lesson with shared tags",
38699
- severity: "error"
38834
+ reason: "possible contradiction with an existing lesson with shared tags",
38835
+ severity: "warning"
38700
38836
  };
38701
38837
  }
38702
38838
  if (isVagueLesson(candidate)) {
@@ -38836,31 +38972,22 @@ async function appendUnactionable(directory, entry, reason) {
38836
38972
  const filePath = resolveUnactionablePath(directory);
38837
38973
  const dirPath = path15.dirname(filePath);
38838
38974
  await mkdir4(dirPath, { recursive: true });
38839
- let release = null;
38840
- try {
38841
- release = await import_proper_lockfile5.default.lock(dirPath, {
38842
- retries: { retries: 50, minTimeout: 10, maxTimeout: 100 },
38843
- stale: 5000
38844
- });
38975
+ await transactKnowledge(filePath, (existing) => {
38845
38976
  const record3 = {
38846
38977
  ...entry,
38847
38978
  status: "quarantined_unactionable",
38848
38979
  unactionable_reason: reason,
38849
38980
  quarantined_at: new Date().toISOString()
38850
38981
  };
38851
- await appendFile4(filePath, `${JSON.stringify(record3)}
38852
- `, "utf-8");
38853
- const existing = await readKnowledge(filePath);
38854
- if (existing.length > 200) {
38855
- const trimmed = existing.slice(-200);
38856
- await atomicWriteFile(filePath, `${trimmed.map((e) => JSON.stringify(e)).join(`
38857
- `)}
38858
- `);
38982
+ const duplicate = findNearDuplicate(record3.lesson, existing, 0.6);
38983
+ if (duplicate?.unactionable_reason === reason) {
38984
+ duplicate.quarantined_at = record3.quarantined_at;
38985
+ duplicate.updated_at = record3.updated_at;
38986
+ return existing;
38859
38987
  }
38860
- } finally {
38861
- if (release)
38862
- await release().catch(() => {});
38863
- }
38988
+ const next = [...existing, record3];
38989
+ return next.length > 200 ? next.slice(-200) : next;
38990
+ });
38864
38991
  }
38865
38992
  async function quarantineEntry(directory, entryId, reason, reportedBy) {
38866
38993
  if (!directory || directory.includes("..")) {
@@ -38994,28 +39121,34 @@ async function restoreEntry(directory, entryId) {
38994
39121
  }
38995
39122
  }
38996
39123
  }
38997
- var import_proper_lockfile5, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, ACTIONABLE_STRING_MAX = 200, ACTIONABLE_LIST_MAX = 20, NAME_PATTERN, SOURCE_REF_FORBIDDEN, ALLOWED_SKILL_PATH_PREFIXES, VALID_DIRECTIVE_PRIORITIES;
39124
+ var import_proper_lockfile5, DANGEROUS_COMMAND_ERROR_PATTERNS, DANGEROUS_COMMAND_WARNING_PATTERNS, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, ACTIONABLE_STRING_MAX = 200, ACTIONABLE_LIST_MAX = 20, NAME_PATTERN, SOURCE_REF_FORBIDDEN, ALLOWED_SKILL_PATH_PREFIXES, VALID_DIRECTIVE_PRIORITIES;
38998
39125
  var init_knowledge_validator = __esm(() => {
38999
39126
  init_task_file();
39000
39127
  init_logger();
39001
39128
  init_knowledge_store();
39002
39129
  import_proper_lockfile5 = __toESM(require_proper_lockfile(), 1);
39003
- DANGEROUS_COMMAND_PATTERNS = [
39130
+ DANGEROUS_COMMAND_ERROR_PATTERNS = [
39004
39131
  /\brm\s+-rf\b/,
39005
39132
  /\bsudo\s+rm\b/,
39006
- /\bformat\b/,
39007
39133
  /\bmkfs\b/,
39008
39134
  /\bdd\s+if=/,
39009
39135
  /:\(\)\s*\{/,
39010
39136
  /\bchmod\s+-R\s+777\b/i,
39011
39137
  /\bdeltree\b/,
39012
- /\brmdir\s+\/s\b/,
39138
+ /\brmdir\s+\/s\b/
39139
+ ];
39140
+ DANGEROUS_COMMAND_WARNING_PATTERNS = [
39141
+ /\bformat\b/,
39013
39142
  /\bkill\s+-9\b/,
39014
39143
  /\bpkill\b/,
39015
39144
  /\bkillall\b/,
39016
39145
  /`[^`]*`/,
39017
39146
  /\$\([^)]*\)/
39018
39147
  ];
39148
+ DANGEROUS_COMMAND_PATTERNS = [
39149
+ ...DANGEROUS_COMMAND_ERROR_PATTERNS,
39150
+ ...DANGEROUS_COMMAND_WARNING_PATTERNS
39151
+ ];
39019
39152
  SECURITY_DEGRADING_PATTERNS = [
39020
39153
  /disable\s+.{0,50}firewall/i,
39021
39154
  /turn\s+off\s+.{0,50}security/i,
@@ -39117,7 +39250,7 @@ var init_knowledge_validator = __esm(() => {
39117
39250
  });
39118
39251
 
39119
39252
  // src/services/skill-changelog.ts
39120
- import { appendFile as appendFile5, mkdir as mkdir5, readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
39253
+ import { appendFile as appendFile5, mkdir as mkdir5, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
39121
39254
  import * as path16 from "path";
39122
39255
  function resolveSkillChangelogPath(directory, slug) {
39123
39256
  if (slug.includes("..") || slug.includes("/") || slug.includes("\\")) {
@@ -39137,7 +39270,7 @@ async function appendSkillChangelog(directory, slug, entry) {
39137
39270
  `).filter((line) => line.trim().length > 0);
39138
39271
  if (lines.length > MAX_CHANGELOG_ENTRIES_PER_SKILL) {
39139
39272
  const trimmed = lines.slice(lines.length - MAX_CHANGELOG_ENTRIES_PER_SKILL);
39140
- await writeFile4(filePath, `${trimmed.join(`
39273
+ await writeFile3(filePath, `${trimmed.join(`
39141
39274
  `)}
39142
39275
  `, "utf-8");
39143
39276
  }
@@ -39152,7 +39285,7 @@ var init_skill_changelog = __esm(() => {
39152
39285
 
39153
39286
  // src/services/skill-generator.ts
39154
39287
  import { existsSync as existsSync11, unlinkSync as unlinkSync5 } from "fs";
39155
- import { mkdir as mkdir6, readFile as readFile5, rename as rename3, writeFile as writeFile5 } from "fs/promises";
39288
+ import { mkdir as mkdir6, readFile as readFile5, rename as rename3, writeFile as writeFile4 } from "fs/promises";
39156
39289
  import * as path17 from "path";
39157
39290
  function sanitizeSlug(input) {
39158
39291
  const lc = input.toLowerCase().trim();
@@ -39177,18 +39310,35 @@ async function selectCandidateEntries(directory, opts) {
39177
39310
  const hivePath = resolveHiveKnowledgePath();
39178
39311
  const hive = existsSync11(hivePath) ? await readKnowledge(hivePath) : [];
39179
39312
  const all = [...swarm, ...hive];
39180
- return all.filter((e) => {
39313
+ const counterRollups = await readKnowledgeCounterRollups(directory);
39314
+ const selected = [];
39315
+ for (const e of all) {
39181
39316
  if (e.status === "archived")
39182
- return false;
39183
- if (e.confidence < opts.minConfidence)
39184
- return false;
39185
- const confirmations = (e.confirmed_by ?? []).length;
39186
- if (confirmations < opts.minConfirmations)
39187
- return false;
39317
+ continue;
39188
39318
  if (e.generated_skill_slug)
39189
- return false;
39190
- return true;
39191
- });
39319
+ continue;
39320
+ const outcomes = effectiveRetrievalOutcomes(e.retrieval_outcomes, counterRollups.get(e.id));
39321
+ if (!isSkillMaturityEligible(e, opts, outcomes))
39322
+ continue;
39323
+ selected.push({ ...e, retrieval_outcomes: outcomes });
39324
+ }
39325
+ return selected;
39326
+ }
39327
+ function hasStrongSkillOutcomeRecord(outcomes) {
39328
+ return (outcomes?.applied_explicit_count ?? 0) >= STRONG_SKILL_OUTCOME_COUNT || (outcomes?.succeeded_after_shown_count ?? 0) >= STRONG_SKILL_OUTCOME_COUNT;
39329
+ }
39330
+ function isHighPriorityDirective(entry) {
39331
+ return entry.directive_priority === "critical" || entry.directive_priority === "high";
39332
+ }
39333
+ function isSkillMaturityEligible(entry, opts, outcomes = entry.retrieval_outcomes) {
39334
+ const outcomeSignal = computeOutcomeSignal(outcomes);
39335
+ if (outcomeSignal < 0)
39336
+ return false;
39337
+ const strongOutcomes = hasStrongSkillOutcomeRecord(outcomes);
39338
+ if (entry.confidence < opts.minConfidence && !strongOutcomes)
39339
+ return false;
39340
+ const confirmations = (entry.confirmed_by ?? []).length;
39341
+ return confirmations >= opts.minConfirmations || strongOutcomes;
39192
39342
  }
39193
39343
  function jaccardSimilarity(setA, setB) {
39194
39344
  const normA = setA.map((s) => s.toLowerCase());
@@ -39228,8 +39378,9 @@ function clusterEntries(entries) {
39228
39378
  }
39229
39379
  const result = [];
39230
39380
  for (const c of clusters) {
39231
- if (c.members.length < MIN_CLUSTER_SIZE)
39381
+ if (c.members.length < MIN_CLUSTER_SIZE && !isSkillSingletonEligible(c.members[0])) {
39232
39382
  continue;
39383
+ }
39233
39384
  const arr = c.members;
39234
39385
  const triggers = uniqueStrings(arr.flatMap((e) => e.triggers ?? []));
39235
39386
  const required3 = uniqueStrings(arr.flatMap((e) => e.required_actions ?? []));
@@ -39255,6 +39406,11 @@ function clusterEntries(entries) {
39255
39406
  result.sort((a, b) => b.entries.length - a.entries.length || b.avgConfidence - a.avgConfidence || a.slug.localeCompare(b.slug));
39256
39407
  return result;
39257
39408
  }
39409
+ function isSkillSingletonEligible(entry) {
39410
+ if (!entry)
39411
+ return false;
39412
+ return isHighPriorityDirective(entry) || hasStrongSkillOutcomeRecord(entry.retrieval_outcomes);
39413
+ }
39258
39414
  function uniqueStrings(arr) {
39259
39415
  return [...new Set(arr.filter((s) => typeof s === "string" && s.length > 0))];
39260
39416
  }
@@ -39355,12 +39511,12 @@ function escapeMarkdown(s) {
39355
39511
  async function atomicWrite(p, content) {
39356
39512
  await mkdir6(path17.dirname(p), { recursive: true });
39357
39513
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
39358
- await writeFile5(tmp, content, "utf-8");
39514
+ await writeFile4(tmp, content, "utf-8");
39359
39515
  await rename3(tmp, p);
39360
39516
  }
39361
39517
  async function generateSkills(req) {
39362
- const minConfidence = req.minConfidence ?? 0.85;
39363
- const minConfirmations = req.minConfirmations ?? 2;
39518
+ const minConfidence = req.minConfidence ?? DEFAULT_SKILL_MIN_CONFIDENCE;
39519
+ const minConfirmations = req.minConfirmations ?? DEFAULT_SKILL_MIN_CONFIRMATIONS;
39364
39520
  const candidates = await selectCandidateEntries(req.directory, {
39365
39521
  minConfidence,
39366
39522
  minConfirmations
@@ -39755,7 +39911,7 @@ async function retireSkill(directory, slug, reason) {
39755
39911
  reason: reason ?? "manual_retire"
39756
39912
  });
39757
39913
  await mkdir6(markerDir, { recursive: true });
39758
- await writeFile5(markerPath, markerContent, "utf-8");
39914
+ await writeFile4(markerPath, markerContent, "utf-8");
39759
39915
  return {
39760
39916
  retired: true,
39761
39917
  path: skillPath,
@@ -39918,8 +40074,9 @@ async function regenerateSkill(directory, slug) {
39918
40074
  entryCount: matchedEntries.length
39919
40075
  };
39920
40076
  }
39921
- var SLUG_PATTERN, MIN_CLUSTER_SIZE = 2, JACCARD_THRESHOLD = 0.5, AUTO_APPLY_BATCH_LIMIT = 5, _internals15;
40077
+ var SLUG_PATTERN, DEFAULT_SKILL_MIN_CONFIDENCE = 0.7, DEFAULT_SKILL_MIN_CONFIRMATIONS = 2, STRONG_SKILL_OUTCOME_COUNT = 3, MIN_CLUSTER_SIZE = 2, JACCARD_THRESHOLD = 0.5, AUTO_APPLY_BATCH_LIMIT = 5, _internals15;
39922
40078
  var init_skill_generator = __esm(() => {
40079
+ init_knowledge_events();
39923
40080
  init_knowledge_store();
39924
40081
  init_knowledge_validator();
39925
40082
  init_logger();
@@ -39929,6 +40086,7 @@ var init_skill_generator = __esm(() => {
39929
40086
  sanitizeSlug,
39930
40087
  isValidSlug,
39931
40088
  selectCandidateEntries,
40089
+ isSkillMaturityEligible,
39932
40090
  clusterEntries,
39933
40091
  jaccardSimilarity,
39934
40092
  renderSkillMarkdown,
@@ -39947,7 +40105,7 @@ var init_skill_generator = __esm(() => {
39947
40105
 
39948
40106
  // src/services/skill-improver-quota.ts
39949
40107
  import { existsSync as existsSync12 } from "fs";
39950
- import { mkdir as mkdir7, readFile as readFile6, rename as rename4, writeFile as writeFile6 } from "fs/promises";
40108
+ import { mkdir as mkdir7, readFile as readFile6, rename as rename4, writeFile as writeFile5 } from "fs/promises";
39951
40109
  import * as path18 from "path";
39952
40110
  async function acquireLock(dir) {
39953
40111
  const acquire = import_proper_lockfile6.default.lock(dir, LOCK_RETRY_OPTS);
@@ -39965,8 +40123,9 @@ async function acquireLock(dir) {
39965
40123
  clearTimeout(timer);
39966
40124
  }
39967
40125
  }
39968
- function resolveQuotaPath(directory) {
39969
- return path18.join(directory, ".swarm", "skill-improver-quota.json");
40126
+ function resolveQuotaPath(directory, scope = "skill-improver") {
40127
+ const fileName = scope === "knowledge-enrichment" ? "knowledge-enrichment-quota.json" : "skill-improver-quota.json";
40128
+ return path18.join(directory, ".swarm", fileName);
39970
40129
  }
39971
40130
  function todayKey(window, now = new Date) {
39972
40131
  if (window === "utc") {
@@ -39994,11 +40153,11 @@ async function readState(filePath) {
39994
40153
  async function writeState(filePath, state) {
39995
40154
  await mkdir7(path18.dirname(filePath), { recursive: true });
39996
40155
  const tmp = `${filePath}.tmp-${process.pid}`;
39997
- await writeFile6(tmp, JSON.stringify(state, null, 2), "utf-8");
40156
+ await writeFile5(tmp, JSON.stringify(state, null, 2), "utf-8");
39998
40157
  await rename4(tmp, filePath);
39999
40158
  }
40000
40159
  async function getQuotaState(directory, opts) {
40001
- const filePath = resolveQuotaPath(directory);
40160
+ const filePath = resolveQuotaPath(directory, opts.scope);
40002
40161
  const today = todayKey(opts.window, opts.now);
40003
40162
  const existing = await readState(filePath);
40004
40163
  if (!existing || existing.date !== today || existing.window !== opts.window) {
@@ -40014,7 +40173,7 @@ async function getQuotaState(directory, opts) {
40014
40173
  return { ...existing, max_calls: opts.maxCalls };
40015
40174
  }
40016
40175
  async function reserveQuota(directory, opts) {
40017
- const filePath = resolveQuotaPath(directory);
40176
+ const filePath = resolveQuotaPath(directory, opts.scope);
40018
40177
  await mkdir7(path18.dirname(filePath), { recursive: true });
40019
40178
  let release = null;
40020
40179
  try {
@@ -40044,7 +40203,7 @@ async function reserveQuota(directory, opts) {
40044
40203
  }
40045
40204
  }
40046
40205
  async function releaseQuota(directory, opts) {
40047
- const filePath = resolveQuotaPath(directory);
40206
+ const filePath = resolveQuotaPath(directory, opts.scope);
40048
40207
  await mkdir7(path18.dirname(filePath), { recursive: true });
40049
40208
  let release = null;
40050
40209
  try {
@@ -40096,6 +40255,89 @@ function resolveLogPath(directory) {
40096
40255
  function normalizeComplianceVerdict(verdict) {
40097
40256
  return verdict === "violation" ? "violated" : verdict;
40098
40257
  }
40258
+ function normalizeSkillUsageEntry(raw) {
40259
+ const entry = raw;
40260
+ return {
40261
+ ...entry,
40262
+ complianceVerdict: normalizeComplianceVerdict(entry.complianceVerdict)
40263
+ };
40264
+ }
40265
+ function legacySkillUsageId(entry) {
40266
+ const stable = JSON.stringify({
40267
+ skillPath: entry.skillPath,
40268
+ agentName: entry.agentName,
40269
+ taskID: entry.taskID,
40270
+ timestamp: entry.timestamp,
40271
+ complianceVerdict: entry.complianceVerdict,
40272
+ sessionID: entry.sessionID,
40273
+ skillVersion: entry.skillVersion
40274
+ });
40275
+ return `legacy:${crypto3.createHash("sha256").update(stable).digest("hex")}`;
40276
+ }
40277
+ function parseSkillUsageEntry(raw) {
40278
+ const entry = raw;
40279
+ if (entry.type === "feedback_applied")
40280
+ return null;
40281
+ if (typeof entry.skillPath !== "string" || typeof entry.agentName !== "string" || typeof entry.taskID !== "string" || typeof entry.timestamp !== "string" || typeof entry.complianceVerdict !== "string" || typeof entry.sessionID !== "string") {
40282
+ return null;
40283
+ }
40284
+ return normalizeSkillUsageEntry({
40285
+ ...entry,
40286
+ id: typeof entry.id === "string" ? entry.id : legacySkillUsageId(entry)
40287
+ });
40288
+ }
40289
+ function parseFeedbackMarker(raw) {
40290
+ const marker = raw;
40291
+ if (marker.type !== "feedback_applied")
40292
+ return null;
40293
+ if (typeof marker.timestamp !== "string")
40294
+ return null;
40295
+ if (!Array.isArray(marker.processedEntryIds))
40296
+ return null;
40297
+ const processedEntryIds = marker.processedEntryIds.filter((id) => typeof id === "string" && id.length > 0);
40298
+ return {
40299
+ type: "feedback_applied",
40300
+ timestamp: marker.timestamp,
40301
+ processedEntryIds
40302
+ };
40303
+ }
40304
+ function readFeedbackAppliedEntryIds(directory) {
40305
+ const resolved = resolveLogPath(directory);
40306
+ const processed = new Set;
40307
+ if (!_internals16.existsSync(resolved))
40308
+ return processed;
40309
+ const raw = _internals16.readFileSync(resolved, "utf-8");
40310
+ for (const line of raw.split(`
40311
+ `)) {
40312
+ const trimmed = line.trim();
40313
+ if (!trimmed)
40314
+ continue;
40315
+ try {
40316
+ const marker = parseFeedbackMarker(JSON.parse(trimmed));
40317
+ if (!marker)
40318
+ continue;
40319
+ for (const id of marker.processedEntryIds)
40320
+ processed.add(id);
40321
+ } catch {}
40322
+ }
40323
+ return processed;
40324
+ }
40325
+ function appendFeedbackAppliedMarker(directory, processedEntryIds) {
40326
+ if (processedEntryIds.length === 0)
40327
+ return;
40328
+ const resolved = resolveLogPath(directory);
40329
+ const dir = path19.dirname(resolved);
40330
+ if (!_internals16.existsSync(dir)) {
40331
+ _internals16.mkdirSync(dir, { recursive: true });
40332
+ }
40333
+ const marker = {
40334
+ type: "feedback_applied",
40335
+ timestamp: new Date().toISOString(),
40336
+ processedEntryIds: [...new Set(processedEntryIds)]
40337
+ };
40338
+ _internals16.appendFileSync(resolved, `${JSON.stringify(marker)}
40339
+ `, "utf-8");
40340
+ }
40099
40341
  function appendSkillUsageEntry(directory, entry) {
40100
40342
  const {
40101
40343
  skillPath,
@@ -40139,7 +40381,7 @@ function appendSkillUsageEntry(directory, entry) {
40139
40381
  agentName,
40140
40382
  taskID,
40141
40383
  timestamp,
40142
- complianceVerdict,
40384
+ complianceVerdict: normalizeComplianceVerdict(complianceVerdict),
40143
40385
  sessionID,
40144
40386
  ...reviewerNotes !== undefined && { reviewerNotes },
40145
40387
  ...skillVersion !== undefined && { skillVersion }
@@ -40147,8 +40389,8 @@ function appendSkillUsageEntry(directory, entry) {
40147
40389
  _internals16.appendFileSync(resolved, `${JSON.stringify(fullEntry)}
40148
40390
  `, "utf-8");
40149
40391
  try {
40150
- const stat2 = _internals16.statSync(resolved);
40151
- if (stat2.size > SKILL_USAGE_LOG_ROTATE_BYTES) {
40392
+ const stat3 = _internals16.statSync(resolved);
40393
+ if (stat3.size > SKILL_USAGE_LOG_ROTATE_BYTES) {
40152
40394
  _internals16.pruneSkillUsageLog(directory, SKILL_USAGE_LOG_MAX_ENTRIES_PER_SKILL);
40153
40395
  }
40154
40396
  } catch {}
@@ -40166,9 +40408,9 @@ function readSkillUsageEntries(directory, options) {
40166
40408
  if (!trimmed)
40167
40409
  continue;
40168
40410
  try {
40169
- const entry = JSON.parse(trimmed);
40170
- entry.complianceVerdict = normalizeComplianceVerdict(entry.complianceVerdict);
40171
- entries.push(entry);
40411
+ const entry = parseSkillUsageEntry(JSON.parse(trimmed));
40412
+ if (entry)
40413
+ entries.push(entry);
40172
40414
  } catch {}
40173
40415
  }
40174
40416
  if (!options)
@@ -40202,11 +40444,11 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
40202
40444
  try {
40203
40445
  const normalizedMaxBytes = Number.isFinite(maxBytes) ? maxBytes : TAIL_BYTES_DEFAULT;
40204
40446
  const boundedMaxBytes = Math.min(Math.max(1, normalizedMaxBytes), MAX_TAIL_BYTES);
40205
- const stat2 = _internals16.statSync(logPath);
40206
- const start = Math.max(0, stat2.size - boundedMaxBytes);
40447
+ const stat3 = _internals16.statSync(logPath);
40448
+ const start = Math.max(0, stat3.size - boundedMaxBytes);
40207
40449
  const fd = _internals16.openSync(logPath, "r");
40208
40450
  try {
40209
- const readLen = stat2.size - start;
40451
+ const readLen = stat3.size - start;
40210
40452
  if (readLen === 0)
40211
40453
  return [];
40212
40454
  const buf = Buffer.alloc(readLen);
@@ -40226,8 +40468,9 @@ function readSkillUsageEntriesTail(directory, filters, maxBytes = TAIL_BYTES_DEF
40226
40468
  if (!line.trim())
40227
40469
  continue;
40228
40470
  try {
40229
- const entry = JSON.parse(line);
40230
- entry.complianceVerdict = normalizeComplianceVerdict(entry.complianceVerdict);
40471
+ const entry = parseSkillUsageEntry(JSON.parse(line));
40472
+ if (!entry)
40473
+ continue;
40231
40474
  if (filters.sessionID !== undefined && entry.sessionID !== filters.sessionID) {
40232
40475
  continue;
40233
40476
  }
@@ -40262,8 +40505,9 @@ function computeComplianceByVersion(entries, skillPath) {
40262
40505
  stats.total += 1;
40263
40506
  if (e.complianceVerdict === "compliant")
40264
40507
  stats.compliant += 1;
40265
- if (e.complianceVerdict === "violated")
40508
+ if (normalizeComplianceVerdict(e.complianceVerdict) === "violated") {
40266
40509
  stats.violation += 1;
40510
+ }
40267
40511
  }
40268
40512
  for (const stats of map3.values()) {
40269
40513
  stats.rate = stats.total === 0 ? 0 : stats.compliant / stats.total;
@@ -40374,6 +40618,7 @@ async function applySkillUsageFeedback(directory, options) {
40374
40618
  let bumps = 0;
40375
40619
  try {
40376
40620
  const allEntries = readSkillUsageEntries(directory);
40621
+ const alreadyProcessed = readFeedbackAppliedEntryIds(directory);
40377
40622
  const actionable = allEntries.filter((e) => {
40378
40623
  if (e.complianceVerdict !== "compliant" && e.complianceVerdict !== "violated") {
40379
40624
  return false;
@@ -40381,6 +40626,9 @@ async function applySkillUsageFeedback(directory, options) {
40381
40626
  if (options?.sinceTimestamp && e.timestamp <= options.sinceTimestamp) {
40382
40627
  return false;
40383
40628
  }
40629
+ if (alreadyProcessed.has(e.id)) {
40630
+ return false;
40631
+ }
40384
40632
  return true;
40385
40633
  });
40386
40634
  if (actionable.length === 0) {
@@ -40395,6 +40643,7 @@ async function applySkillUsageFeedback(directory, options) {
40395
40643
  groups.set(entry.skillPath, [entry]);
40396
40644
  }
40397
40645
  const allDeltas = [];
40646
+ const processedEntryIds = [];
40398
40647
  for (const [skillPath, entries] of Array.from(groups)) {
40399
40648
  let compliantCount = 0;
40400
40649
  let violationCount = 0;
@@ -40413,6 +40662,7 @@ async function applySkillUsageFeedback(directory, options) {
40413
40662
  for (const id of sourceIds) {
40414
40663
  allDeltas.push({ id, delta });
40415
40664
  }
40665
+ processedEntryIds.push(...entries.map((entry) => entry.id));
40416
40666
  processed++;
40417
40667
  bumps += sourceIds.length;
40418
40668
  }
@@ -40426,6 +40676,7 @@ async function applySkillUsageFeedback(directory, options) {
40426
40676
  }));
40427
40677
  if (clampedDeltas.length > 0) {
40428
40678
  await bumpKnowledgeConfidenceBatch(directory, clampedDeltas);
40679
+ appendFeedbackAppliedMarker(directory, processedEntryIds);
40429
40680
  }
40430
40681
  } catch (err) {
40431
40682
  console.warn("[skill-usage-log] applySkillUsageFeedback failed (fail-open):", err instanceof Error ? err.message : String(err));
@@ -40452,7 +40703,10 @@ var init_skill_usage_log = __esm(() => {
40452
40703
  resolveSourceKnowledgeIds,
40453
40704
  applySkillUsageFeedback,
40454
40705
  parseGeneratedFromKnowledge,
40455
- computeComplianceByVersion
40706
+ computeComplianceByVersion,
40707
+ normalizeComplianceVerdict,
40708
+ readFeedbackAppliedEntryIds,
40709
+ appendFeedbackAppliedMarker
40456
40710
  };
40457
40711
  TAIL_BYTES_DEFAULT = 64 * 1024;
40458
40712
  MAX_TAIL_BYTES = TAIL_BYTES_DEFAULT;
@@ -40502,6 +40756,9 @@ function isAlreadyInHive(entry, hiveEntries, threshold) {
40502
40756
  return findNearDuplicate(entry.lesson, hiveEntries, threshold) !== undefined;
40503
40757
  }
40504
40758
  function isHiveEligible(entry, autoPromoteDays) {
40759
+ if (!isActiveForHivePromotion(entry)) {
40760
+ return false;
40761
+ }
40505
40762
  const phaseNumbers = new Set;
40506
40763
  for (const record3 of entry.confirmed_by ?? []) {
40507
40764
  if (record3 && typeof record3.phase_number === "number") {
@@ -40522,6 +40779,9 @@ function isHiveEligible(entry, autoPromoteDays) {
40522
40779
  }
40523
40780
  return false;
40524
40781
  }
40782
+ function isActiveForHivePromotion(entry) {
40783
+ return !["archived", "quarantined", "quarantined_unactionable"].includes(entry.status);
40784
+ }
40525
40785
  function countDistinctProjects(confirmedBy) {
40526
40786
  const projectNames = new Set;
40527
40787
  for (const record3 of confirmedBy) {
@@ -40604,7 +40864,7 @@ async function checkHivePromotions(swarmEntries, config3) {
40604
40864
  }
40605
40865
  let hiveModified = false;
40606
40866
  for (const hiveEntry of hiveEntries) {
40607
- const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries, config3.dedup_threshold);
40867
+ const nearDuplicate = findNearDuplicate(hiveEntry.lesson, swarmEntries.filter(isActiveForHivePromotion), config3.dedup_threshold);
40608
40868
  if (!nearDuplicate) {
40609
40869
  continue;
40610
40870
  }
@@ -40734,9 +40994,9 @@ import {
40734
40994
  mkdir as mkdir8,
40735
40995
  readFile as readFile7,
40736
40996
  rename as rename5,
40737
- stat as stat2,
40997
+ stat as stat3,
40738
40998
  unlink as unlink2,
40739
- writeFile as writeFile7
40999
+ writeFile as writeFile6
40740
41000
  } from "fs/promises";
40741
41001
  import * as path21 from "path";
40742
41002
  function emptySynonymMap() {
@@ -40877,7 +41137,7 @@ async function readSynonymMap(directory, maxPairs = DEFAULT_MAX_PAIRS) {
40877
41137
  }
40878
41138
  try {
40879
41139
  const ceiling = Math.max(MIN_READ_CEILING_BYTES, Math.floor(maxPairs) * APPROX_BYTES_PER_PAIR);
40880
- const st = await stat2(filePath);
41140
+ const st = await stat3(filePath);
40881
41141
  if (st.size > ceiling)
40882
41142
  return emptySynonymMap();
40883
41143
  const raw = await readFile7(filePath, "utf-8");
@@ -40890,7 +41150,7 @@ async function writeSynonymMapAtomic(filePath, map3) {
40890
41150
  await mkdir8(path21.dirname(filePath), { recursive: true });
40891
41151
  const tmp = `${filePath}.tmp.${Date.now()}.${Math.floor(Math.random() * 1e9)}`;
40892
41152
  try {
40893
- await writeFile7(tmp, JSON.stringify(map3, null, 2), "utf-8");
41153
+ await writeFile6(tmp, JSON.stringify(map3, null, 2), "utf-8");
40894
41154
  await rename5(tmp, filePath);
40895
41155
  } finally {
40896
41156
  try {
@@ -41099,12 +41359,12 @@ function extractKeywords(text) {
41099
41359
  const words = text.toLowerCase().split(/[^a-z0-9]+/).filter((w) => w.length >= MIN_KEYWORD_LENGTH);
41100
41360
  return new Set(words);
41101
41361
  }
41102
- function computeContextMatchScore(taskDescription, skillPath) {
41362
+ function computeContextMatchScore(taskDescription, skillPath, metadata) {
41103
41363
  const taskKeywords = extractKeywords(taskDescription);
41104
41364
  if (taskKeywords.size === 0)
41105
41365
  return 0;
41106
41366
  const skillName = extractSkillName(skillPath);
41107
- const skillText = `${skillPath} ${skillName}`;
41367
+ const skillText = `${skillPath} ${skillName} ${metadata?.name ?? ""} ${metadata?.description ?? ""}`;
41108
41368
  const skillKeywords = extractKeywords(skillText);
41109
41369
  let matchCount = 0;
41110
41370
  for (const kw of taskKeywords) {
@@ -41115,7 +41375,7 @@ function computeContextMatchScore(taskDescription, skillPath) {
41115
41375
  return matchCount / taskKeywords.size;
41116
41376
  }
41117
41377
  function computeSkillRelevanceScore(skillPath, taskDescription, usageHistory, metadata) {
41118
- const contextScore = computeContextMatchScore(taskDescription, skillPath) * CONTEXT_WEIGHT;
41378
+ const contextScore = computeContextMatchScore(taskDescription, skillPath, metadata) * CONTEXT_WEIGHT;
41119
41379
  if (usageHistory.length === 0)
41120
41380
  return Math.min(1, contextScore);
41121
41381
  const usageCount = usageHistory.length;
@@ -41190,8 +41450,8 @@ function formatSkillIndexWithContext(skills, directory) {
41190
41450
  const usageLogPath = path22.join(directory, ".swarm", "skill-usage.jsonl");
41191
41451
  let hasHistory = false;
41192
41452
  try {
41193
- const stat3 = fs10.statSync(usageLogPath);
41194
- hasHistory = stat3.size > 0;
41453
+ const stat4 = fs10.statSync(usageLogPath);
41454
+ hasHistory = stat4.size > 0;
41195
41455
  } catch {}
41196
41456
  if (!hasHistory) {
41197
41457
  return skills.map((sp) => {
@@ -41712,24 +41972,32 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
41712
41972
  if (!text)
41713
41973
  continue;
41714
41974
  const skillPaths = [];
41975
+ let explicitReviewerTaskID;
41715
41976
  for (const line of text.split(`
41716
41977
  `)) {
41717
- const coderMatch = line.trim().match(CODER_SKILLS_PATTERN);
41978
+ const trimmed = line.trim();
41979
+ const taskMatch = trimmed.match(REVIEWER_TASK_PATTERN);
41980
+ if (taskMatch) {
41981
+ explicitReviewerTaskID = taskMatch[1];
41982
+ }
41983
+ const coderMatch = trimmed.match(CODER_SKILLS_PATTERN);
41718
41984
  if (coderMatch) {
41719
41985
  const parsed = _internals18.parseSkillPaths(coderMatch[1]);
41720
41986
  skillPaths.push(...parsed);
41721
41987
  }
41722
41988
  }
41723
- let resolvedTaskID = "unknown";
41989
+ let resolvedTaskID = explicitReviewerTaskID ?? "unknown";
41724
41990
  if (existingEntries.length > 0) {
41725
- const latestDelegation = [...existingEntries].reverse().find((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__");
41726
- if (latestDelegation) {
41727
- resolvedTaskID = latestDelegation.taskID;
41728
- if (skillPaths.length === 0) {
41729
- const delegatedPaths = existingEntries.filter((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__" && e.taskID === resolvedTaskID).map((e) => e.skillPath);
41730
- if (delegatedPaths.length > 0) {
41731
- skillPaths.push(...new Set(delegatedPaths));
41732
- }
41991
+ if (!explicitReviewerTaskID) {
41992
+ const latestDelegation = [...existingEntries].reverse().find((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__");
41993
+ if (latestDelegation) {
41994
+ resolvedTaskID = latestDelegation.taskID;
41995
+ }
41996
+ }
41997
+ if (skillPaths.length === 0 && resolvedTaskID !== "unknown") {
41998
+ const delegatedPaths = existingEntries.filter((e) => e.agentName !== "reviewer" && e.skillPath !== "__overall__" && e.taskID === resolvedTaskID).map((e) => e.skillPath);
41999
+ if (delegatedPaths.length > 0) {
42000
+ skillPaths.push(...new Set(delegatedPaths));
41733
42001
  }
41734
42002
  }
41735
42003
  }
@@ -41819,7 +42087,7 @@ async function skillPropagationTransformScan(directory, output, sessionID) {
41819
42087
  break;
41820
42088
  }
41821
42089
  }
41822
- var SKILL_CAPABLE_AGENTS, SKILL_SEARCH_ROOTS, MAX_SCORING_SESSION_ENTRIES = 500, _internals18, COMPLIANCE_PATTERN, CODER_SKILLS_PATTERN;
42090
+ var SKILL_CAPABLE_AGENTS, SKILL_SEARCH_ROOTS, MAX_SCORING_SESSION_ENTRIES = 500, _internals18, COMPLIANCE_PATTERN, CODER_SKILLS_PATTERN, REVIEWER_TASK_PATTERN;
41823
42091
  var init_skill_propagation_gate = __esm(() => {
41824
42092
  init_schema();
41825
42093
  init_logger();
@@ -41865,6 +42133,7 @@ var init_skill_propagation_gate = __esm(() => {
41865
42133
  };
41866
42134
  COMPLIANCE_PATTERN = /SKILL_COMPLIANCE\s*:\s*(COMPLIANT|PARTIAL|VIOLATED)(?:\s*(?:\u2014|-)\s*(.*))?\s*$/i;
41867
42135
  CODER_SKILLS_PATTERN = /SKILLS_USED_BY_CODER\s*:\s*(.+)/i;
42136
+ REVIEWER_TASK_PATTERN = /TASK\s*:\s*(\S+)/i;
41868
42137
  _internals18.skillPropagationGateBefore = skillPropagationGateBefore;
41869
42138
  _internals18.skillPropagationTransformScan = skillPropagationTransformScan;
41870
42139
  _internals18.writeWarnEvent = writeWarnEvent;
@@ -41879,7 +42148,7 @@ var init_skill_propagation_gate = __esm(() => {
41879
42148
 
41880
42149
  // src/hooks/micro-reflector.ts
41881
42150
  import { existsSync as existsSync15 } from "fs";
41882
- import { readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
42151
+ import { readFile as readFile8, writeFile as writeFile7 } from "fs/promises";
41883
42152
  import * as path24 from "path";
41884
42153
  function resolveInsightCandidatesPath(directory) {
41885
42154
  return validateSwarmPath(directory, "insight-candidates.jsonl");
@@ -41926,7 +42195,7 @@ var init_micro_reflector = __esm(() => {
41926
42195
 
41927
42196
  // src/hooks/knowledge-curator.ts
41928
42197
  import { existsSync as existsSync16 } from "fs";
41929
- import { appendFile as appendFile6, mkdir as mkdir9, readFile as readFile9, writeFile as writeFile9 } from "fs/promises";
42198
+ import { appendFile as appendFile6, mkdir as mkdir9, readFile as readFile9, writeFile as writeFile8 } from "fs/promises";
41930
42199
  import * as path25 from "path";
41931
42200
  function pruneSeenRetroSections() {
41932
42201
  const cutoff = Date.now() - 86400000;
@@ -42167,7 +42436,8 @@ async function enrichLessonToV3(params) {
42167
42436
  const reservation = await reserveQuota(params.directory, {
42168
42437
  nCalls: 1,
42169
42438
  maxCalls: quota.maxCalls,
42170
- window: quota.window
42439
+ window: quota.window,
42440
+ scope: "knowledge-enrichment"
42171
42441
  });
42172
42442
  if (!reservation.allowed)
42173
42443
  return null;
@@ -42221,7 +42491,7 @@ async function consumeInsightCandidates(directory, batchLimit = MESO_INSIGHT_BAT
42221
42491
  const body = data.length === 0 ? "" : `${data.map((c) => JSON.stringify(c)).join(`
42222
42492
  `)}
42223
42493
  `;
42224
- await writeFile9(p, body, "utf-8");
42494
+ await writeFile8(p, body, "utf-8");
42225
42495
  }, (all) => {
42226
42496
  if (all.length === 0)
42227
42497
  return null;
@@ -42512,7 +42782,7 @@ async function runAutoPromotion(directory, config3) {
42512
42782
  await rewriteKnowledge(knowledgePath, entries);
42513
42783
  }
42514
42784
  }
42515
- function createKnowledgeCuratorHook(directory, config3) {
42785
+ function createKnowledgeCuratorHook(directory, config3, options = {}) {
42516
42786
  const handler = async (input, _output) => {
42517
42787
  pruneSeenRetroSections();
42518
42788
  if (!config3.enabled)
@@ -42557,7 +42827,10 @@ function createKnowledgeCuratorHook(directory, config3) {
42557
42827
  recordSeenRetroSection(evidenceKey, evidenceHash, Date.now());
42558
42828
  const projectName2 = evidenceData.project_name ?? "unknown";
42559
42829
  const phaseNumber2 = typeof evidenceData.phase_number === "number" ? evidenceData.phase_number : 1;
42560
- await _internals19.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3);
42830
+ await _internals19.curateAndStoreSwarm(lessons, projectName2, { phase_number: phaseNumber2 }, directory, config3, {
42831
+ llmDelegate: options.llmDelegateFactory?.(sessionID),
42832
+ enrichmentQuota: options.enrichmentQuota
42833
+ });
42561
42834
  return;
42562
42835
  }
42563
42836
  const planContent = await readSwarmFileAsync(directory, "plan.md");
@@ -42579,7 +42852,10 @@ function createKnowledgeCuratorHook(directory, config3) {
42579
42852
  const projectName = projectNameMatch ? projectNameMatch[1].trim() : "unknown";
42580
42853
  const phaseMatch = /^Phase:\s*(\d+)/m.exec(planContent);
42581
42854
  const phaseNumber = phaseMatch ? parseInt(phaseMatch[1], 10) : 1;
42582
- await _internals19.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3);
42855
+ await _internals19.curateAndStoreSwarm(normalLessons, projectName, { phase_number: phaseNumber }, directory, config3, {
42856
+ llmDelegate: options.llmDelegateFactory?.(sessionID),
42857
+ enrichmentQuota: options.enrichmentQuota
42858
+ });
42583
42859
  };
42584
42860
  return safeHook(handler);
42585
42861
  }
@@ -42738,7 +43014,7 @@ var init_skill_improver_llm_factory = __esm(() => {
42738
43014
  });
42739
43015
 
42740
43016
  // src/services/trajectory-cluster.ts
42741
- import { mkdir as mkdir10, writeFile as writeFile10 } from "fs/promises";
43017
+ import { mkdir as mkdir10, writeFile as writeFile9 } from "fs/promises";
42742
43018
  import * as path26 from "path";
42743
43019
  function failureKind(e) {
42744
43020
  const tool3 = (e.tool ?? "").toLowerCase();
@@ -42873,7 +43149,7 @@ async function writeMotifProposals(directory, opts = {}) {
42873
43149
  for (const motif of motifs.slice(0, max)) {
42874
43150
  const slug = `motif-${slugify2(motif.signature)}`;
42875
43151
  const filePath = path26.join(proposalsDir, `${slug}.md`);
42876
- await writeFile10(filePath, buildMotifProposal(motif), "utf-8");
43152
+ await writeFile9(filePath, buildMotifProposal(motif), "utf-8");
42877
43153
  result.proposalsWritten.push(filePath);
42878
43154
  }
42879
43155
  return result;
@@ -43017,7 +43293,7 @@ async function writeSuccessMotifProposals(directory, opts = {}) {
43017
43293
  for (const motif of motifs.slice(0, max)) {
43018
43294
  const slug = workflowSlug(motif.signature);
43019
43295
  const filePath = path26.join(proposalsDir, `${slug}.md`);
43020
- await writeFile10(filePath, buildWorkflowProposal(motif), "utf-8");
43296
+ await writeFile9(filePath, buildWorkflowProposal(motif), "utf-8");
43021
43297
  result.proposalsWritten.push(filePath);
43022
43298
  }
43023
43299
  return result;
@@ -43148,7 +43424,7 @@ var init_unactionable_hardening = __esm(() => {
43148
43424
 
43149
43425
  // src/services/skill-improver.ts
43150
43426
  import { existsSync as existsSync18 } from "fs";
43151
- import { mkdir as mkdir11, readFile as readFile10, rename as rename6, writeFile as writeFile11 } from "fs/promises";
43427
+ import { mkdir as mkdir11, readFile as readFile10, rename as rename6, writeFile as writeFile10 } from "fs/promises";
43152
43428
  import * as path27 from "path";
43153
43429
  function timestampSlug(d) {
43154
43430
  return d.toISOString().replace(/[:.]/g, "-");
@@ -43156,7 +43432,7 @@ function timestampSlug(d) {
43156
43432
  async function atomicWrite2(p, content) {
43157
43433
  await mkdir11(path27.dirname(p), { recursive: true });
43158
43434
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
43159
- await writeFile11(tmp, content, "utf-8");
43435
+ await writeFile10(tmp, content, "utf-8");
43160
43436
  await rename6(tmp, p);
43161
43437
  }
43162
43438
  async function gatherInventory(directory) {
@@ -43210,7 +43486,10 @@ async function gatherInventory(directory) {
43210
43486
  });
43211
43487
  }
43212
43488
  }
43213
- const matureCandidates = swarm.concat(hive).filter((e) => e.status !== "archived" && e.confidence >= 0.85 && !e.generated_skill_slug && (e.confirmed_by ?? []).length >= 2);
43489
+ const matureCandidates = await selectCandidateEntries(directory, {
43490
+ minConfidence: DEFAULT_SKILL_MIN_CONFIDENCE,
43491
+ minConfirmations: DEFAULT_SKILL_MIN_CONFIRMATIONS
43492
+ });
43214
43493
  return {
43215
43494
  knowledge: { swarm: swarm.length, hive: hive.length, archived },
43216
43495
  skills: {
@@ -43476,8 +43755,8 @@ async function runSkillImprover(req) {
43476
43755
  const gen = await generateSkills({
43477
43756
  directory: req.directory,
43478
43757
  mode: "draft",
43479
- minConfidence: 0.85,
43480
- minConfirmations: 2
43758
+ minConfidence: DEFAULT_SKILL_MIN_CONFIDENCE,
43759
+ minConfirmations: DEFAULT_SKILL_MIN_CONFIRMATIONS
43481
43760
  });
43482
43761
  draftSkillsWritten = gen.written.map((w) => ({
43483
43762
  slug: w.slug,
@@ -43513,7 +43792,7 @@ async function runSkillImprover(req) {
43513
43792
  unactionableHardening = await hardenUnactionableEntries({
43514
43793
  directory: req.directory,
43515
43794
  llmDelegate: delegate,
43516
- quota: { maxCalls: cfg.max_calls_per_day, window: cfg.quota_window }
43795
+ quota: req.enrichmentQuota
43517
43796
  });
43518
43797
  }
43519
43798
  const motifResult = await writeMotifProposals(req.directory);
@@ -44339,8 +44618,8 @@ async function copyDirRecursive(src, dest) {
44339
44618
  const srcEntry = path29.join(src, entry);
44340
44619
  const destEntry = path29.join(dest, entry);
44341
44620
  try {
44342
- const stat3 = await fs12.stat(srcEntry);
44343
- if (stat3.isDirectory()) {
44621
+ const stat4 = await fs12.stat(srcEntry);
44622
+ if (stat4.isDirectory()) {
44344
44623
  const subCount = await copyDirRecursive(srcEntry, destEntry).catch(() => 0);
44345
44624
  count += subCount;
44346
44625
  } else {
@@ -44376,8 +44655,8 @@ function guaranteeAllPlansComplete(planData) {
44376
44655
  async function handleCloseCommand(directory, args, options = {}) {
44377
44656
  const swarmDir = path29.join(directory, ".swarm");
44378
44657
  try {
44379
- const stat3 = fsSync2.lstatSync(swarmDir);
44380
- if (stat3.isSymbolicLink()) {
44658
+ const stat4 = fsSync2.lstatSync(swarmDir);
44659
+ if (stat4.isSymbolicLink()) {
44381
44660
  return `\u274C Refused: .swarm/ is a symlink or junction. Refusing to operate on a redirected directory for safety.`;
44382
44661
  }
44383
44662
  } catch (err) {
@@ -44531,12 +44810,11 @@ async function handleCloseCommand(directory, args, options = {}) {
44531
44810
  let curationSucceeded = false;
44532
44811
  let curationResult;
44533
44812
  try {
44534
- const skillImproverCfg = SkillImproverConfigSchema.parse(loadedConfig.skill_improver ?? {});
44535
44813
  curationResult = await curateAndStoreSwarm(allLessons, projectName, { phase_number: 0 }, directory, config3, {
44536
44814
  llmDelegate: createCuratorLLMDelegate(directory, "phase", options.sessionID),
44537
44815
  enrichmentQuota: {
44538
- maxCalls: skillImproverCfg.max_calls_per_day,
44539
- window: skillImproverCfg.quota_window
44816
+ maxCalls: config3.enrichment.max_calls_per_day,
44817
+ window: config3.enrichment.quota_window
44540
44818
  }
44541
44819
  });
44542
44820
  curationSucceeded = true;
@@ -44601,7 +44879,11 @@ async function handleCloseCommand(directory, args, options = {}) {
44601
44879
  config: skillImproverConfig,
44602
44880
  targets: ["skills", "knowledge"],
44603
44881
  mode: "proposal",
44604
- sessionId: options.sessionID
44882
+ sessionId: options.sessionID,
44883
+ enrichmentQuota: {
44884
+ maxCalls: config3.enrichment.max_calls_per_day,
44885
+ window: config3.enrichment.quota_window
44886
+ }
44605
44887
  }, options.skillReviewTimeoutMs ?? CLOSE_SKILL_REVIEW_TIMEOUT_MS);
44606
44888
  if (skillReviewResult.ran) {
44607
44889
  const proposal = skillReviewResult.proposalPath ? ` Proposal: ${skillReviewResult.proposalPath}.` : "";
@@ -45359,7 +45641,7 @@ var init_curate = __esm(() => {
45359
45641
  // src/tools/co-change-analyzer.ts
45360
45642
  import * as child_process3 from "child_process";
45361
45643
  import { randomUUID as randomUUID2 } from "crypto";
45362
- import { readdir, readFile as readFile11, stat as stat3 } from "fs/promises";
45644
+ import { readdir, readFile as readFile11, stat as stat4 } from "fs/promises";
45363
45645
  import * as path31 from "path";
45364
45646
  import { promisify } from "util";
45365
45647
  function getExecFileAsync() {
@@ -45510,7 +45792,7 @@ async function getStaticEdges(directory) {
45510
45792
  for (const ext of extensions) {
45511
45793
  const testPath = resolvedPath + ext;
45512
45794
  try {
45513
- const testStat = await stat3(testPath);
45795
+ const testStat = await stat4(testPath);
45514
45796
  if (testStat.isFile()) {
45515
45797
  targetFile = testPath;
45516
45798
  break;
@@ -51774,7 +52056,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
51774
52056
  // src/hooks/knowledge-migrator.ts
51775
52057
  import { randomUUID as randomUUID3 } from "crypto";
51776
52058
  import { existsSync as existsSync26, readFileSync as readFileSync16 } from "fs";
51777
- import { mkdir as mkdir12, readFile as readFile13, writeFile as writeFile12 } from "fs/promises";
52059
+ import { mkdir as mkdir12, readFile as readFile13, writeFile as writeFile11 } from "fs/promises";
51778
52060
  import * as os8 from "os";
51779
52061
  import * as path39 from "path";
51780
52062
  async function migrateKnowledgeToExternal(_directory, _config) {
@@ -52123,7 +52405,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
52123
52405
  migration_tool: "knowledge-migrator.ts"
52124
52406
  };
52125
52407
  await mkdir12(path39.dirname(sentinelPath), { recursive: true });
52126
- await writeFile12(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
52408
+ await writeFile11(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
52127
52409
  }
52128
52410
  function resolveLegacyHiveKnowledgePath() {
52129
52411
  const platform = process.platform;
@@ -52540,7 +52822,7 @@ var init_redaction = __esm(() => {
52540
52822
  });
52541
52823
 
52542
52824
  // src/memory/schema.ts
52543
- import { createHash as createHash6 } from "crypto";
52825
+ import { createHash as createHash7 } from "crypto";
52544
52826
  function normalizeMemoryText(text) {
52545
52827
  return text.replace(/\s+/g, " ").trim();
52546
52828
  }
@@ -52564,7 +52846,7 @@ function stableScopeKey(scope) {
52564
52846
  }
52565
52847
  function computeMemoryContentHash(recordLike) {
52566
52848
  const normalized = normalizeMemoryText(recordLike.text).toLowerCase();
52567
- return createHash6("sha256").update(`${stableScopeKey(recordLike.scope)}
52849
+ return createHash7("sha256").update(`${stableScopeKey(recordLike.scope)}
52568
52850
  ${recordLike.kind}
52569
52851
  ${normalized}`).digest("hex");
52570
52852
  }
@@ -53316,7 +53598,7 @@ import {
53316
53598
  mkdir as mkdir13,
53317
53599
  readFile as readFile14,
53318
53600
  rename as rename7,
53319
- writeFile as writeFile13
53601
+ writeFile as writeFile12
53320
53602
  } from "fs/promises";
53321
53603
  import * as path40 from "path";
53322
53604
 
@@ -53727,7 +54009,7 @@ async function writeJsonlAtomic(filePath, values) {
53727
54009
  const content = values.map((value) => JSON.stringify(value)).join(`
53728
54010
  `) + (values.length > 0 ? `
53729
54011
  ` : "");
53730
- await writeFile13(tmp, content, "utf-8");
54012
+ await writeFile12(tmp, content, "utf-8");
53731
54013
  await rename7(tmp, filePath);
53732
54014
  }
53733
54015
  var init_local_jsonl_provider = __esm(() => {
@@ -53748,7 +54030,7 @@ var init_prompt_block = __esm(() => {
53748
54030
 
53749
54031
  // src/memory/jsonl-migration.ts
53750
54032
  import { existsSync as existsSync28 } from "fs";
53751
- import { copyFile, mkdir as mkdir14, readFile as readFile15, stat as stat4, writeFile as writeFile14 } from "fs/promises";
54033
+ import { copyFile, mkdir as mkdir14, readFile as readFile15, stat as stat5, writeFile as writeFile13 } from "fs/promises";
53752
54034
  import * as path41 from "path";
53753
54035
  function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
53754
54036
  const resolved = resolveConfig(config3);
@@ -53796,14 +54078,14 @@ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
53796
54078
  await mkdir14(exportDir, { recursive: true });
53797
54079
  const memoriesPath = path41.join(exportDir, "memories.jsonl");
53798
54080
  const proposalsPath = path41.join(exportDir, "proposals.jsonl");
53799
- await writeFile14(memoriesPath, toJsonl(memories), "utf-8");
53800
- await writeFile14(proposalsPath, toJsonl(proposals), "utf-8");
54081
+ await writeFile13(memoriesPath, toJsonl(memories), "utf-8");
54082
+ await writeFile13(proposalsPath, toJsonl(proposals), "utf-8");
53801
54083
  return { directory: exportDir, memoriesPath, proposalsPath };
53802
54084
  }
53803
54085
  async function writeMigrationReport(rootDirectory, report, config3 = {}) {
53804
54086
  const reportPath = path41.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
53805
54087
  await mkdir14(path41.dirname(reportPath), { recursive: true });
53806
- await writeFile14(reportPath, `${JSON.stringify(report, null, 2)}
54088
+ await writeFile13(reportPath, `${JSON.stringify(report, null, 2)}
53807
54089
  `, "utf-8");
53808
54090
  return reportPath;
53809
54091
  }
@@ -53824,7 +54106,7 @@ async function getLegacyJsonlFileStatus(rootDirectory, config3 = {}) {
53824
54106
  const filePath = path41.join(storageDir, file3);
53825
54107
  let sizeBytes = 0;
53826
54108
  if (existsSync28(filePath)) {
53827
- sizeBytes = (await stat4(filePath)).size;
54109
+ sizeBytes = (await stat5(filePath)).size;
53828
54110
  }
53829
54111
  statuses.push({
53830
54112
  file: file3,
@@ -57559,8 +57841,8 @@ var init_secretscan = __esm(() => {
57559
57841
  break;
57560
57842
  const fileFindings = scanFileForSecrets(filePath);
57561
57843
  try {
57562
- const stat5 = fs19.statSync(filePath);
57563
- if (stat5.size > MAX_FILE_SIZE_BYTES) {
57844
+ const stat6 = fs19.statSync(filePath);
57845
+ if (stat6.size > MAX_FILE_SIZE_BYTES) {
57564
57846
  skippedFiles++;
57565
57847
  continue;
57566
57848
  }
@@ -58370,8 +58652,8 @@ function sharedTrailingSegments(a, b) {
58370
58652
  function isCacheStale(impactMap, generatedAtMs) {
58371
58653
  for (const sourcePath of Object.keys(impactMap)) {
58372
58654
  try {
58373
- const stat5 = fs23.statSync(sourcePath);
58374
- if (stat5.mtimeMs > generatedAtMs) {
58655
+ const stat6 = fs23.statSync(sourcePath);
58656
+ if (stat6.mtimeMs > generatedAtMs) {
58375
58657
  return true;
58376
58658
  }
58377
58659
  } catch {
@@ -59672,8 +59954,8 @@ function manifestHash(dir) {
59672
59954
  if (!entries.has(name))
59673
59955
  continue;
59674
59956
  try {
59675
- const stat5 = fs28.statSync(path56.join(dir, name));
59676
- parts.push(`${name}:${stat5.size}:${stat5.mtimeMs}:${stat5.ino}`);
59957
+ const stat6 = fs28.statSync(path56.join(dir, name));
59958
+ parts.push(`${name}:${stat6.size}:${stat6.mtimeMs}:${stat6.ino}`);
59677
59959
  } catch {}
59678
59960
  }
59679
59961
  return parts.join("|");