opencode-swarm 7.51.1 → 7.51.3

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/index.js CHANGED
@@ -69,7 +69,7 @@ var package_default;
69
69
  var init_package = __esm(() => {
70
70
  package_default = {
71
71
  name: "opencode-swarm",
72
- version: "7.51.1",
72
+ version: "7.51.3",
73
73
  description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
74
74
  main: "dist/index.js",
75
75
  types: "dist/index.d.ts",
@@ -116,7 +116,7 @@ var init_package = __esm(() => {
116
116
  check: "biome check --write .",
117
117
  dev: "bun run build && opencode",
118
118
  "package:smoke": "node scripts/package-smoke.mjs",
119
- prepublishOnly: "bun run build",
119
+ prepare: "bun run build",
120
120
  "repro:704": "node scripts/repro-704.mjs"
121
121
  },
122
122
  dependencies: {
@@ -56604,7 +56604,7 @@ var init_event_bus = __esm(() => {
56604
56604
 
56605
56605
  // src/hooks/knowledge-store.ts
56606
56606
  import { existsSync as existsSync12 } from "node:fs";
56607
- import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile5, writeFile as writeFile3 } from "node:fs/promises";
56607
+ import { appendFile as appendFile3, mkdir as mkdir3, readFile as readFile5 } from "node:fs/promises";
56608
56608
  import * as os8 from "node:os";
56609
56609
  import * as path22 from "node:path";
56610
56610
  function resolveSwarmKnowledgePath(directory) {
@@ -56767,23 +56767,25 @@ async function rewriteKnowledge(filePath, entries) {
56767
56767
  }
56768
56768
  }
56769
56769
  }
56770
- async function enforceKnowledgeCap(filePath, maxEntries) {
56771
- let release = null;
56770
+ async function transactFile(filePath, read, write, mutate) {
56771
+ const dir = path22.dirname(filePath);
56772
56772
  try {
56773
- const dir = path22.dirname(filePath);
56774
56773
  await mkdir3(dir, { recursive: true });
56774
+ } catch {
56775
+ return false;
56776
+ }
56777
+ let release = null;
56778
+ try {
56775
56779
  release = await import_proper_lockfile3.default.lock(dir, {
56776
56780
  retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
56777
56781
  stale: 5000
56778
56782
  });
56779
- const entries = await readKnowledge(filePath);
56780
- if (entries.length > maxEntries) {
56781
- const trimmed = entries.slice(entries.length - maxEntries);
56782
- const content = trimmed.map((e) => JSON.stringify(e)).join(`
56783
- `) + (trimmed.length > 0 ? `
56784
- ` : "");
56785
- await writeFile3(filePath, content, "utf-8");
56786
- }
56783
+ const data = await read(filePath);
56784
+ const result = mutate(data);
56785
+ if (result === null)
56786
+ return false;
56787
+ await write(filePath, result);
56788
+ return true;
56787
56789
  } finally {
56788
56790
  if (release) {
56789
56791
  try {
@@ -56792,25 +56794,33 @@ async function enforceKnowledgeCap(filePath, maxEntries) {
56792
56794
  }
56793
56795
  }
56794
56796
  }
56797
+ async function transactKnowledge(filePath, mutate) {
56798
+ return transactFile(filePath, readKnowledge, async (fp, entries) => {
56799
+ const content = entries.map((e) => JSON.stringify(e)).join(`
56800
+ `) + (entries.length > 0 ? `
56801
+ ` : "");
56802
+ await atomicWriteFile(fp, content);
56803
+ }, mutate);
56804
+ }
56805
+ async function enforceKnowledgeCap(filePath, maxEntries) {
56806
+ await transactKnowledge(filePath, (entries) => {
56807
+ if (entries.length <= maxEntries)
56808
+ return null;
56809
+ return entries.slice(entries.length - maxEntries);
56810
+ });
56811
+ }
56795
56812
  async function sweepAgedEntries(filePath, defaultMaxPhases) {
56796
- let release = null;
56797
- try {
56798
- const dir = path22.dirname(filePath);
56799
- await mkdir3(dir, { recursive: true });
56800
- release = await import_proper_lockfile3.default.lock(dir, {
56801
- retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
56802
- stale: 5000
56803
- });
56804
- const entries = await readKnowledge(filePath);
56805
- const result = {
56806
- scanned: entries.length,
56807
- aged: 0,
56808
- archived: 0,
56809
- removed: 0,
56810
- skipped_promoted: 0
56811
- };
56813
+ const result = {
56814
+ scanned: 0,
56815
+ aged: 0,
56816
+ archived: 0,
56817
+ removed: 0,
56818
+ skipped_promoted: 0
56819
+ };
56820
+ await transactKnowledge(filePath, (entries) => {
56821
+ result.scanned = entries.length;
56812
56822
  if (entries.length === 0)
56813
- return result;
56823
+ return null;
56814
56824
  const now = new Date().toISOString();
56815
56825
  let mutated = false;
56816
56826
  for (const entry of entries) {
@@ -56830,40 +56840,22 @@ async function sweepAgedEntries(filePath, defaultMaxPhases) {
56830
56840
  result.archived++;
56831
56841
  }
56832
56842
  }
56833
- if (mutated) {
56834
- const content = entries.map((e) => JSON.stringify(e)).join(`
56835
- `) + (entries.length > 0 ? `
56836
- ` : "");
56837
- await writeFile3(filePath, content, "utf-8");
56838
- }
56839
- return result;
56840
- } finally {
56841
- if (release) {
56842
- try {
56843
- await release();
56844
- } catch {}
56845
- }
56846
- }
56843
+ return mutated ? entries : null;
56844
+ });
56845
+ return result;
56847
56846
  }
56848
56847
  async function sweepStaleTodos(filePath, todoMaxPhases) {
56849
- let release = null;
56850
- try {
56851
- const dir = path22.dirname(filePath);
56852
- await mkdir3(dir, { recursive: true });
56853
- release = await import_proper_lockfile3.default.lock(dir, {
56854
- retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
56855
- stale: 5000
56856
- });
56857
- const entries = await readKnowledge(filePath);
56858
- const result = {
56859
- scanned: entries.length,
56860
- aged: 0,
56861
- archived: 0,
56862
- removed: 0,
56863
- skipped_promoted: 0
56864
- };
56848
+ const result = {
56849
+ scanned: 0,
56850
+ aged: 0,
56851
+ archived: 0,
56852
+ removed: 0,
56853
+ skipped_promoted: 0
56854
+ };
56855
+ await transactKnowledge(filePath, (entries) => {
56856
+ result.scanned = entries.length;
56865
56857
  if (entries.length === 0)
56866
- return result;
56858
+ return null;
56867
56859
  const kept = entries.filter((e) => {
56868
56860
  if (e.category !== "todo" || e.status === "promoted")
56869
56861
  return true;
@@ -56874,32 +56866,20 @@ async function sweepStaleTodos(filePath, todoMaxPhases) {
56874
56866
  }
56875
56867
  return true;
56876
56868
  });
56877
- if (result.removed > 0) {
56878
- const content = kept.map((e) => JSON.stringify(e)).join(`
56879
- `) + (kept.length > 0 ? `
56880
- ` : "");
56881
- await writeFile3(filePath, content, "utf-8");
56882
- }
56883
- return result;
56884
- } finally {
56885
- if (release) {
56886
- try {
56887
- await release();
56888
- } catch {}
56889
- }
56890
- }
56869
+ return result.removed > 0 ? kept : null;
56870
+ });
56871
+ return result;
56891
56872
  }
56892
56873
  async function appendRejectedLesson(directory, lesson) {
56893
56874
  const filePath = resolveSwarmRejectedPath(directory);
56894
- const existing = await readRejectedLessons(directory);
56895
56875
  const MAX = 20;
56896
- const updated = [...existing, lesson];
56897
- if (updated.length > MAX) {
56898
- const trimmed = updated.slice(updated.length - MAX);
56899
- await rewriteKnowledge(filePath, trimmed);
56900
- } else {
56901
- await appendKnowledge(filePath, lesson);
56902
- }
56876
+ await transactKnowledge(filePath, (existing) => {
56877
+ const updated = [...existing, lesson];
56878
+ if (updated.length > MAX) {
56879
+ return updated.slice(updated.length - MAX);
56880
+ }
56881
+ return updated;
56882
+ });
56903
56883
  }
56904
56884
  function normalize4(text) {
56905
56885
  const s = typeof text === "string" ? text : String(text ?? "");
@@ -57028,7 +57008,7 @@ async function applyConfidenceDeltas(filePath, deltas) {
57028
57008
  const content = entries.map((e) => JSON.stringify(e)).join(`
57029
57009
  `) + (entries.length > 0 ? `
57030
57010
  ` : "");
57031
- await writeFile3(filePath, content, "utf-8");
57011
+ await atomicWriteFile(filePath, content);
57032
57012
  }
57033
57013
  } catch (err2) {
57034
57014
  console.warn(`[knowledge-store] applyConfidenceDeltas failed on ${filePath} (fail-open):`, err2 instanceof Error ? err2.message : String(err2));
@@ -57047,7 +57027,7 @@ var init_knowledge_store = __esm(() => {
57047
57027
  });
57048
57028
 
57049
57029
  // src/hooks/knowledge-validator.ts
57050
- import { appendFile as appendFile4, mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
57030
+ import { appendFile as appendFile4, mkdir as mkdir4 } from "node:fs/promises";
57051
57031
  import * as path23 from "node:path";
57052
57032
  function normalizeText(text) {
57053
57033
  return text.normalize("NFKC").toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
@@ -57224,7 +57204,8 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
57224
57204
  let release;
57225
57205
  try {
57226
57206
  release = await import_proper_lockfile4.default.lock(swarmDir, {
57227
- retries: { retries: 3, minTimeout: 100 }
57207
+ retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
57208
+ stale: 5000
57228
57209
  });
57229
57210
  const entries = await readKnowledge(knowledgePath);
57230
57211
  const entry = entries.find((e) => e.id === entryId);
@@ -57243,7 +57224,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
57243
57224
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
57244
57225
  `)}
57245
57226
  ` : "";
57246
- await writeFile4(knowledgePath, jsonlContent, "utf-8");
57227
+ await atomicWriteFile(knowledgePath, jsonlContent);
57247
57228
  await appendFile4(quarantinePath, `${JSON.stringify(quarantined)}
57248
57229
  `, "utf-8");
57249
57230
  const quarantinedEntries = await readKnowledge(quarantinePath);
@@ -57252,7 +57233,7 @@ async function quarantineEntry(directory, entryId, reason, reportedBy) {
57252
57233
  const capContent = trimmed.length > 0 ? `${trimmed.map((e) => JSON.stringify(e)).join(`
57253
57234
  `)}
57254
57235
  ` : "";
57255
- await writeFile4(quarantinePath, capContent, "utf-8");
57236
+ await atomicWriteFile(quarantinePath, capContent);
57256
57237
  }
57257
57238
  const rejectedRecord = {
57258
57239
  id: entryId,
@@ -57287,7 +57268,8 @@ async function restoreEntry(directory, entryId) {
57287
57268
  let release;
57288
57269
  try {
57289
57270
  release = await import_proper_lockfile4.default.lock(swarmDir, {
57290
- retries: { retries: 3, minTimeout: 100 }
57271
+ retries: { retries: 5, minTimeout: 100, maxTimeout: 500 },
57272
+ stale: 5000
57291
57273
  });
57292
57274
  const quarantinedEntries = await readKnowledge(quarantinePath);
57293
57275
  const entryToRestore = quarantinedEntries.find((e) => e.id === entryId);
@@ -57316,7 +57298,7 @@ async function restoreEntry(directory, entryId) {
57316
57298
  const jsonlContent = remaining.length > 0 ? `${remaining.map((e) => JSON.stringify(e)).join(`
57317
57299
  `)}
57318
57300
  ` : "";
57319
- await writeFile4(quarantinePath, jsonlContent, "utf-8");
57301
+ await atomicWriteFile(quarantinePath, jsonlContent);
57320
57302
  await appendFile4(knowledgePath, `${JSON.stringify(original)}
57321
57303
  `, "utf-8");
57322
57304
  const rejectedEntries = await readKnowledge(rejectedPath);
@@ -57324,7 +57306,7 @@ async function restoreEntry(directory, entryId) {
57324
57306
  const rejectedContent = filtered.length > 0 ? `${filtered.map((e) => JSON.stringify(e)).join(`
57325
57307
  `)}
57326
57308
  ` : "";
57327
- await writeFile4(rejectedPath, rejectedContent, "utf-8");
57309
+ await atomicWriteFile(rejectedPath, rejectedContent);
57328
57310
  } finally {
57329
57311
  if (release) {
57330
57312
  await release();
@@ -57333,6 +57315,7 @@ async function restoreEntry(directory, entryId) {
57333
57315
  }
57334
57316
  var import_proper_lockfile4, DANGEROUS_COMMAND_PATTERNS, SECURITY_DEGRADING_PATTERNS, INVISIBLE_FORMAT_CHARS, INJECTION_PATTERNS, VALID_CATEGORIES, TECH_REFERENCE_WORDS, ACTION_VERB_WORDS, NEGATION_PAIRS, ALLOWED_SKILL_PATH_PREFIXES, VALID_DIRECTIVE_PRIORITIES;
57335
57317
  var init_knowledge_validator = __esm(() => {
57318
+ init_task_file();
57336
57319
  init_logger();
57337
57320
  init_knowledge_store();
57338
57321
  import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
@@ -57470,7 +57453,7 @@ __export(exports_skill_generator, {
57470
57453
  _internals: () => _internals18
57471
57454
  });
57472
57455
  import { existsSync as existsSync13, unlinkSync as unlinkSync5 } from "node:fs";
57473
- import { mkdir as mkdir5, readFile as readFile6, rename as rename3, writeFile as writeFile5 } from "node:fs/promises";
57456
+ import { mkdir as mkdir5, readFile as readFile6, rename as rename3, writeFile as writeFile3 } from "node:fs/promises";
57474
57457
  import * as path24 from "node:path";
57475
57458
  function sanitizeSlug(input) {
57476
57459
  const lc = input.toLowerCase().trim();
@@ -57662,7 +57645,7 @@ function escapeMarkdown(s) {
57662
57645
  async function atomicWrite2(p, content) {
57663
57646
  await mkdir5(path24.dirname(p), { recursive: true });
57664
57647
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
57665
- await writeFile5(tmp, content, "utf-8");
57648
+ await writeFile3(tmp, content, "utf-8");
57666
57649
  await rename3(tmp, p);
57667
57650
  }
57668
57651
  async function generateSkills(req) {
@@ -57976,7 +57959,7 @@ async function retireSkill(directory, slug, reason) {
57976
57959
  reason: reason ?? "manual_retire"
57977
57960
  });
57978
57961
  await mkdir5(markerDir, { recursive: true });
57979
- await writeFile5(markerPath, markerContent, "utf-8");
57962
+ await writeFile3(markerPath, markerContent, "utf-8");
57980
57963
  return {
57981
57964
  retired: true,
57982
57965
  path: skillPath,
@@ -59195,77 +59178,83 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
59195
59178
  }
59196
59179
  const validRecommendations = recommendations.filter((rec) => rec != null);
59197
59180
  const knowledgePath = resolveSwarmKnowledgePath(directory);
59198
- const entries = await readKnowledge(knowledgePath);
59199
- let modified = false;
59200
59181
  const appliedIds = new Set;
59201
- const updatedEntries = entries.map((entry) => {
59202
- const rec = validRecommendations.find((r) => r.entry_id === entry.id);
59203
- if (!rec)
59204
- return entry;
59205
- switch (rec.action) {
59206
- case "promote":
59207
- appliedIds.add(entry.id);
59208
- applied++;
59209
- modified = true;
59210
- return {
59211
- ...entry,
59212
- hive_eligible: true,
59213
- confidence: Math.min(1, (entry.confidence ?? 0) + 0.1),
59214
- updated_at: new Date().toISOString()
59215
- };
59216
- case "archive":
59217
- appliedIds.add(entry.id);
59218
- applied++;
59219
- modified = true;
59220
- return {
59221
- ...entry,
59222
- status: "archived",
59223
- updated_at: new Date().toISOString()
59224
- };
59225
- case "flag_contradiction":
59226
- appliedIds.add(entry.id);
59227
- applied++;
59228
- modified = true;
59229
- return {
59230
- ...entry,
59231
- tags: [
59232
- ...entry.tags ?? [],
59233
- `contradiction:${(rec.reason ?? "").slice(0, 50)}`
59234
- ],
59235
- updated_at: new Date().toISOString()
59236
- };
59237
- case "rewrite": {
59238
- const newLesson = (rec.lesson ?? "").trim();
59239
- if (newLesson.length < 15 || newLesson.length > 280) {
59240
- return entry;
59182
+ const foundIds = new Set;
59183
+ await transactKnowledge(knowledgePath, (entries) => {
59184
+ appliedIds.clear();
59185
+ foundIds.clear();
59186
+ let txApplied = 0;
59187
+ let modified = false;
59188
+ for (const e of entries)
59189
+ foundIds.add(e.id);
59190
+ const updatedEntries = entries.map((entry) => {
59191
+ const rec = validRecommendations.find((r) => r.entry_id === entry.id);
59192
+ if (!rec)
59193
+ return entry;
59194
+ switch (rec.action) {
59195
+ case "promote":
59196
+ appliedIds.add(entry.id);
59197
+ txApplied++;
59198
+ modified = true;
59199
+ return {
59200
+ ...entry,
59201
+ hive_eligible: true,
59202
+ confidence: Math.min(1, (entry.confidence ?? 0) + 0.1),
59203
+ updated_at: new Date().toISOString()
59204
+ };
59205
+ case "archive":
59206
+ appliedIds.add(entry.id);
59207
+ txApplied++;
59208
+ modified = true;
59209
+ return {
59210
+ ...entry,
59211
+ status: "archived",
59212
+ updated_at: new Date().toISOString()
59213
+ };
59214
+ case "flag_contradiction":
59215
+ appliedIds.add(entry.id);
59216
+ txApplied++;
59217
+ modified = true;
59218
+ return {
59219
+ ...entry,
59220
+ tags: [
59221
+ ...entry.tags ?? [],
59222
+ `contradiction:${(rec.reason ?? "").slice(0, 50)}`
59223
+ ],
59224
+ updated_at: new Date().toISOString()
59225
+ };
59226
+ case "rewrite": {
59227
+ const newLesson = (rec.lesson ?? "").trim();
59228
+ if (newLesson.length < 15 || newLesson.length > 280) {
59229
+ return entry;
59230
+ }
59231
+ appliedIds.add(entry.id);
59232
+ txApplied++;
59233
+ modified = true;
59234
+ return {
59235
+ ...entry,
59236
+ lesson: newLesson,
59237
+ updated_at: new Date().toISOString(),
59238
+ confidence: Math.max(0.1, (entry.confidence ?? 0.5) - 0.05)
59239
+ };
59241
59240
  }
59242
- appliedIds.add(entry.id);
59243
- applied++;
59244
- modified = true;
59245
- return {
59246
- ...entry,
59247
- lesson: newLesson,
59248
- updated_at: new Date().toISOString(),
59249
- confidence: Math.max(0.1, (entry.confidence ?? 0.5) - 0.05)
59250
- };
59241
+ default:
59242
+ return entry;
59251
59243
  }
59252
- default:
59253
- return entry;
59254
- }
59244
+ });
59245
+ applied += txApplied;
59246
+ return modified ? updatedEntries : null;
59255
59247
  });
59256
59248
  for (const rec of validRecommendations) {
59257
59249
  if (rec.entry_id !== undefined && !appliedIds.has(rec.entry_id)) {
59258
- const found = entries.some((e) => e.id === rec.entry_id);
59259
- if (!found) {
59250
+ if (!foundIds.has(rec.entry_id)) {
59260
59251
  warn(`[curator] applyCuratorKnowledgeUpdates: entry_id '${rec.entry_id}' not found — skipping`);
59261
59252
  }
59262
59253
  skipped++;
59263
59254
  }
59264
59255
  }
59265
- if (modified) {
59266
- await rewriteKnowledge(knowledgePath, updatedEntries);
59267
- }
59268
- const existingLessons = entries.map((e) => e.lesson);
59256
+ const currentEntries = await readKnowledge(knowledgePath);
59257
+ const currentLessons = currentEntries.map((e) => e.lesson);
59269
59258
  for (const rec of validRecommendations) {
59270
59259
  if (rec.entry_id !== undefined)
59271
59260
  continue;
@@ -59278,12 +59267,12 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
59278
59267
  skipped++;
59279
59268
  continue;
59280
59269
  }
59281
- if (existingLessons.some((el) => el.toLowerCase() === lesson.toLowerCase())) {
59270
+ if (currentLessons.some((el) => el.toLowerCase() === lesson.toLowerCase())) {
59282
59271
  skipped++;
59283
59272
  continue;
59284
59273
  }
59285
59274
  if (knowledgeConfig.validation_enabled !== false) {
59286
- const validation = validateLesson(lesson, existingLessons, {
59275
+ const validation = validateLesson(lesson, currentLessons, {
59287
59276
  category: rec.category ?? "other",
59288
59277
  scope: "global",
59289
59278
  confidence: rec.confidence ?? 0.5
@@ -59317,7 +59306,7 @@ async function applyCuratorKnowledgeUpdates(directory, recommendations, knowledg
59317
59306
  };
59318
59307
  await appendKnowledge(knowledgePath, newEntry);
59319
59308
  applied++;
59320
- existingLessons.push(lesson);
59309
+ currentLessons.push(lesson);
59321
59310
  }
59322
59311
  return { applied, skipped };
59323
59312
  }
@@ -59613,7 +59602,7 @@ var init_hive_promoter = __esm(() => {
59613
59602
  // src/hooks/knowledge-events.ts
59614
59603
  import { randomUUID as randomUUID4 } from "node:crypto";
59615
59604
  import { existsSync as existsSync16 } from "node:fs";
59616
- import { appendFile as appendFile5, mkdir as mkdir6, readFile as readFile7, writeFile as writeFile6 } from "node:fs/promises";
59605
+ import { appendFile as appendFile5, mkdir as mkdir6, readFile as readFile7, writeFile as writeFile4 } from "node:fs/promises";
59617
59606
  import * as path28 from "node:path";
59618
59607
  function resolveKnowledgeEventsPath(directory) {
59619
59608
  return path28.join(directory, ".swarm", "knowledge-events.jsonl");
@@ -59653,7 +59642,7 @@ async function appendKnowledgeEvent(directory, event) {
59653
59642
  `).filter((line) => line.trim().length > 0);
59654
59643
  if (lines.length > MAX_EVENT_LOG_ENTRIES) {
59655
59644
  const trimmed = lines.slice(lines.length - MAX_EVENT_LOG_ENTRIES);
59656
- await writeFile6(filePath, `${trimmed.join(`
59645
+ await writeFile4(filePath, `${trimmed.join(`
59657
59646
  `)}
59658
59647
  `, "utf-8");
59659
59648
  }
@@ -60001,8 +59990,7 @@ async function processRetractions(retractions, directory) {
60001
59990
  }
60002
59991
  async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, config3, options) {
60003
59992
  const knowledgePath = resolveSwarmKnowledgePath(directory);
60004
- const existingEntries = await readKnowledge(knowledgePath) ?? [];
60005
- let stored = 0;
59993
+ const snapshot = await readKnowledge(knowledgePath) ?? [];
60006
59994
  let skipped = 0;
60007
59995
  let rejected = 0;
60008
59996
  const categoryByTag = new Map([
@@ -60017,6 +60005,8 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
60017
60005
  ["other", "other"],
60018
60006
  ["todo", "todo"]
60019
60007
  ]);
60008
+ const snapshotPlusNew = [...snapshot];
60009
+ const toAdd = [];
60020
60010
  for (const lesson of lessons) {
60021
60011
  const tags = inferTags(lesson);
60022
60012
  let category = "process";
@@ -60031,7 +60021,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
60031
60021
  scope: "global",
60032
60022
  confidence: computeConfidence(0, true)
60033
60023
  };
60034
- const result = validateLesson(lesson, existingEntries.map((e) => e.lesson), meta3);
60024
+ const result = validateLesson(lesson, snapshotPlusNew.map((e) => e.lesson), meta3);
60035
60025
  if (result.valid === false || result.severity === "error") {
60036
60026
  const rejectedLesson = {
60037
60027
  id: crypto.randomUUID(),
@@ -60044,7 +60034,7 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
60044
60034
  rejected++;
60045
60035
  continue;
60046
60036
  }
60047
- const duplicate = findNearDuplicate(lesson, existingEntries, config3.dedup_threshold);
60037
+ const duplicate = findNearDuplicate(lesson, snapshotPlusNew, config3.dedup_threshold);
60048
60038
  if (duplicate) {
60049
60039
  skipped++;
60050
60040
  continue;
@@ -60076,9 +60066,20 @@ async function curateAndStoreSwarm(lessons, projectName, phaseInfo, directory, c
60076
60066
  project_name: projectName,
60077
60067
  auto_generated: true
60078
60068
  };
60079
- await appendKnowledge(knowledgePath, entry);
60080
- stored++;
60081
- existingEntries.push(entry);
60069
+ toAdd.push(entry);
60070
+ snapshotPlusNew.push(entry);
60071
+ }
60072
+ let stored = 0;
60073
+ if (toAdd.length > 0) {
60074
+ await transactKnowledge(knowledgePath, (current) => {
60075
+ const trulyNew = toAdd.filter((e) => !findNearDuplicate(e.lesson, current, config3.dedup_threshold));
60076
+ const extraDups = toAdd.length - trulyNew.length;
60077
+ skipped += extraDups;
60078
+ if (trulyNew.length === 0)
60079
+ return null;
60080
+ stored = trulyNew.length;
60081
+ return [...current, ...trulyNew];
60082
+ });
60082
60083
  }
60083
60084
  await enforceKnowledgeCap(knowledgePath, config3.swarm_max_entries);
60084
60085
  if (!options?.skipAutoPromotion) {
@@ -60320,7 +60321,7 @@ var init_skill_improver_llm_factory = __esm(() => {
60320
60321
 
60321
60322
  // src/services/skill-improver-quota.ts
60322
60323
  import { existsSync as existsSync17 } from "node:fs";
60323
- import { mkdir as mkdir7, readFile as readFile8, rename as rename4, writeFile as writeFile7 } from "node:fs/promises";
60324
+ import { mkdir as mkdir7, readFile as readFile8, rename as rename4, writeFile as writeFile5 } from "node:fs/promises";
60324
60325
  import * as path29 from "node:path";
60325
60326
  async function acquireLock(dir) {
60326
60327
  const acquire = import_proper_lockfile6.default.lock(dir, LOCK_RETRY_OPTS);
@@ -60367,7 +60368,7 @@ async function readState(filePath) {
60367
60368
  async function writeState(filePath, state) {
60368
60369
  await mkdir7(path29.dirname(filePath), { recursive: true });
60369
60370
  const tmp = `${filePath}.tmp-${process.pid}`;
60370
- await writeFile7(tmp, JSON.stringify(state, null, 2), "utf-8");
60371
+ await writeFile5(tmp, JSON.stringify(state, null, 2), "utf-8");
60371
60372
  await rename4(tmp, filePath);
60372
60373
  }
60373
60374
  async function getQuotaState(directory, opts) {
@@ -60454,7 +60455,7 @@ var init_skill_improver_quota = __esm(() => {
60454
60455
 
60455
60456
  // src/services/skill-improver.ts
60456
60457
  import { existsSync as existsSync18 } from "node:fs";
60457
- import { mkdir as mkdir8, rename as rename5, writeFile as writeFile8 } from "node:fs/promises";
60458
+ import { mkdir as mkdir8, rename as rename5, writeFile as writeFile6 } from "node:fs/promises";
60458
60459
  import * as path30 from "node:path";
60459
60460
  function timestampSlug(d) {
60460
60461
  return d.toISOString().replace(/[:.]/g, "-");
@@ -60462,7 +60463,7 @@ function timestampSlug(d) {
60462
60463
  async function atomicWrite3(p, content) {
60463
60464
  await mkdir8(path30.dirname(p), { recursive: true });
60464
60465
  const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
60465
- await writeFile8(tmp, content, "utf-8");
60466
+ await writeFile6(tmp, content, "utf-8");
60466
60467
  await rename5(tmp, p);
60467
60468
  }
60468
60469
  async function gatherInventory(directory) {
@@ -68292,7 +68293,7 @@ var KNOWLEDGE_SCHEMA_VERSION = 2;
68292
68293
  // src/hooks/knowledge-migrator.ts
68293
68294
  import { randomUUID as randomUUID6 } from "node:crypto";
68294
68295
  import { existsSync as existsSync25, readFileSync as readFileSync13 } from "node:fs";
68295
- import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile9 } from "node:fs/promises";
68296
+ import { mkdir as mkdir9, readFile as readFile11, writeFile as writeFile7 } from "node:fs/promises";
68296
68297
  import * as path41 from "node:path";
68297
68298
  async function migrateKnowledgeToExternal(_directory, _config) {
68298
68299
  return {
@@ -68523,7 +68524,7 @@ async function writeSentinel(sentinelPath, migrated, dropped) {
68523
68524
  migration_tool: "knowledge-migrator.ts"
68524
68525
  };
68525
68526
  await mkdir9(path41.dirname(sentinelPath), { recursive: true });
68526
- await writeFile9(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
68527
+ await writeFile7(sentinelPath, JSON.stringify(sentinel, null, 2), "utf-8");
68527
68528
  }
68528
68529
  var _internals29;
68529
68530
  var init_knowledge_migrator = __esm(() => {
@@ -69605,7 +69606,7 @@ import {
69605
69606
  mkdir as mkdir10,
69606
69607
  readFile as readFile12,
69607
69608
  rename as rename6,
69608
- writeFile as writeFile10
69609
+ writeFile as writeFile8
69609
69610
  } from "node:fs/promises";
69610
69611
  import * as path42 from "node:path";
69611
69612
 
@@ -70016,7 +70017,7 @@ async function writeJsonlAtomic(filePath, values) {
70016
70017
  const content = values.map((value) => JSON.stringify(value)).join(`
70017
70018
  `) + (values.length > 0 ? `
70018
70019
  ` : "");
70019
- await writeFile10(tmp, content, "utf-8");
70020
+ await writeFile8(tmp, content, "utf-8");
70020
70021
  await rename6(tmp, filePath);
70021
70022
  }
70022
70023
  var init_local_jsonl_provider = __esm(() => {
@@ -70111,7 +70112,7 @@ var init_prompt_block = __esm(() => {
70111
70112
 
70112
70113
  // src/memory/jsonl-migration.ts
70113
70114
  import { existsSync as existsSync27 } from "node:fs";
70114
- import { copyFile, mkdir as mkdir11, readFile as readFile13, stat as stat4, writeFile as writeFile11 } from "node:fs/promises";
70115
+ import { copyFile, mkdir as mkdir11, readFile as readFile13, stat as stat4, writeFile as writeFile9 } from "node:fs/promises";
70115
70116
  import * as path43 from "node:path";
70116
70117
  function resolveMemoryStorageDir(rootDirectory, config3 = {}) {
70117
70118
  const resolved = resolveConfig(config3);
@@ -70159,14 +70160,14 @@ async function writeJsonlExport(rootDirectory, config3, memories, proposals) {
70159
70160
  await mkdir11(exportDir, { recursive: true });
70160
70161
  const memoriesPath = path43.join(exportDir, "memories.jsonl");
70161
70162
  const proposalsPath = path43.join(exportDir, "proposals.jsonl");
70162
- await writeFile11(memoriesPath, toJsonl(memories), "utf-8");
70163
- await writeFile11(proposalsPath, toJsonl(proposals), "utf-8");
70163
+ await writeFile9(memoriesPath, toJsonl(memories), "utf-8");
70164
+ await writeFile9(proposalsPath, toJsonl(proposals), "utf-8");
70164
70165
  return { directory: exportDir, memoriesPath, proposalsPath };
70165
70166
  }
70166
70167
  async function writeMigrationReport(rootDirectory, report, config3 = {}) {
70167
70168
  const reportPath = path43.join(resolveMemoryStorageDir(rootDirectory, config3), "migration-report.json");
70168
70169
  await mkdir11(path43.dirname(reportPath), { recursive: true });
70169
- await writeFile11(reportPath, `${JSON.stringify(report, null, 2)}
70170
+ await writeFile9(reportPath, `${JSON.stringify(report, null, 2)}
70170
70171
  `, "utf-8");
70171
70172
  return reportPath;
70172
70173
  }
@@ -86306,7 +86307,7 @@ COVERAGE REPORTING:
86306
86307
  `;
86307
86308
 
86308
86309
  // src/agents/index.ts
86309
- import { mkdir as mkdir13, writeFile as writeFile12 } from "node:fs/promises";
86310
+ import { mkdir as mkdir13, writeFile as writeFile10 } from "node:fs/promises";
86310
86311
  import * as path70 from "node:path";
86311
86312
  function stripSwarmPrefix(agentName, swarmPrefix) {
86312
86313
  if (!swarmPrefix || !agentName)
@@ -86728,7 +86729,7 @@ function getAgentConfigs(config3, directory, sessionId, projectContext) {
86728
86729
  generatedAt: new Date().toISOString(),
86729
86730
  agents: agentToolSnapshot
86730
86731
  }, null, 2);
86731
- mkdir13(evidenceDir, { recursive: true }).then(() => writeFile12(path70.join(evidenceDir, filename), snapshotData)).catch(() => {});
86732
+ mkdir13(evidenceDir, { recursive: true }).then(() => writeFile10(path70.join(evidenceDir, filename), snapshotData)).catch(() => {});
86732
86733
  }
86733
86734
  return result;
86734
86735
  }
@@ -91269,7 +91270,7 @@ import {
91269
91270
  readFile as readFile16,
91270
91271
  realpath as realpath3,
91271
91272
  stat as stat7,
91272
- writeFile as writeFile14
91273
+ writeFile as writeFile12
91273
91274
  } from "node:fs/promises";
91274
91275
  import * as path94 from "node:path";
91275
91276
  function normalizeSeparators(filePath) {
@@ -91467,7 +91468,7 @@ async function scanDocIndex(directory) {
91467
91468
  };
91468
91469
  try {
91469
91470
  await mkdir16(path94.dirname(manifestPath), { recursive: true });
91470
- await writeFile14(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
91471
+ await writeFile12(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
91471
91472
  } catch {}
91472
91473
  return { manifest, cached: false };
91473
91474
  }
@@ -91681,7 +91682,7 @@ var init_doc_scan = __esm(() => {
91681
91682
 
91682
91683
  // src/hooks/knowledge-reader.ts
91683
91684
  import { existsSync as existsSync51 } from "node:fs";
91684
- import { mkdir as mkdir17, readFile as readFile17, writeFile as writeFile15 } from "node:fs/promises";
91685
+ import { readFile as readFile17 } from "node:fs/promises";
91685
91686
  import * as path95 from "node:path";
91686
91687
  function inferCategoriesFromPhase(phaseDescription) {
91687
91688
  const lower = phaseDescription.toLowerCase();
@@ -91726,19 +91727,32 @@ function inferCategoriesFromPhase(phaseDescription) {
91726
91727
  }
91727
91728
  return ["process", "tooling"];
91728
91729
  }
91730
+ async function transactShownFile(shownFile, mutate) {
91731
+ return transactFile(shownFile, async (filePath) => {
91732
+ if (!existsSync51(filePath))
91733
+ return {};
91734
+ try {
91735
+ const content = await readFile17(filePath, "utf-8");
91736
+ return JSON.parse(content);
91737
+ } catch {
91738
+ return {};
91739
+ }
91740
+ }, async (filePath, data) => {
91741
+ await atomicWriteFile(filePath, JSON.stringify(data, null, 2));
91742
+ }, mutate);
91743
+ }
91729
91744
  async function recordLessonsShown(directory, lessonIds, currentPhase) {
91730
91745
  const shownFile = path95.join(directory, ".swarm", ".knowledge-shown.json");
91731
91746
  try {
91732
- let shownData = {};
91733
- if (existsSync51(shownFile)) {
91734
- const content = await readFile17(shownFile, "utf-8");
91735
- shownData = JSON.parse(content);
91736
- }
91737
91747
  const phaseMatch = /^Phase\s+(\d+)/i.exec(currentPhase);
91738
91748
  const canonicalKey = phaseMatch ? `Phase ${phaseMatch[1]}` : currentPhase;
91739
- shownData[canonicalKey] = lessonIds;
91740
- await mkdir17(path95.dirname(shownFile), { recursive: true });
91741
- await writeFile15(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
91749
+ const ok = await transactShownFile(shownFile, (shownData) => {
91750
+ shownData[canonicalKey] = lessonIds;
91751
+ return shownData;
91752
+ });
91753
+ if (!ok) {
91754
+ warn("[swarm] Knowledge: failed to record shown lessons");
91755
+ }
91742
91756
  } catch {
91743
91757
  warn("[swarm] Knowledge: failed to record shown lessons");
91744
91758
  }
@@ -91843,56 +91857,58 @@ async function updateRetrievalOutcome(directory, phaseInfo, phaseSucceeded) {
91843
91857
  if (!existsSync51(shownFile)) {
91844
91858
  return;
91845
91859
  }
91846
- const content = await readFile17(shownFile, "utf-8");
91847
- const shownData = JSON.parse(content);
91848
- const shownIds = shownData[phaseInfo];
91860
+ let shownIds;
91861
+ try {
91862
+ const content = await readFile17(shownFile, "utf-8");
91863
+ const shownData = JSON.parse(content);
91864
+ shownIds = shownData[phaseInfo];
91865
+ } catch {
91866
+ return;
91867
+ }
91849
91868
  if (!shownIds || shownIds.length === 0) {
91850
91869
  return;
91851
91870
  }
91852
91871
  const swarmPath = resolveSwarmKnowledgePath(directory);
91853
- const entries = await readKnowledge(swarmPath);
91854
- let updated = false;
91855
91872
  const foundInSwarm = new Set;
91856
- for (const entry of entries) {
91857
- if (shownIds.includes(entry.id)) {
91858
- const ro = entry.retrieval_outcomes;
91859
- if (phaseSucceeded) {
91860
- ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
91861
- } else {
91862
- ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
91873
+ await transactKnowledge(swarmPath, (entries) => {
91874
+ let mutated = false;
91875
+ for (const entry of entries) {
91876
+ if (shownIds.includes(entry.id)) {
91877
+ const ro = entry.retrieval_outcomes;
91878
+ if (phaseSucceeded) {
91879
+ ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
91880
+ } else {
91881
+ ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
91882
+ }
91883
+ mutated = true;
91884
+ foundInSwarm.add(entry.id);
91863
91885
  }
91864
- updated = true;
91865
- foundInSwarm.add(entry.id);
91866
91886
  }
91867
- }
91868
- if (updated) {
91869
- await rewriteKnowledge(swarmPath, entries);
91870
- }
91887
+ return mutated ? entries : null;
91888
+ });
91871
91889
  const remainingIds = shownIds.filter((id) => !foundInSwarm.has(id));
91872
- if (remainingIds.length === 0) {
91873
- delete shownData[phaseInfo];
91874
- await writeFile15(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
91875
- return;
91876
- }
91877
- const hivePath = resolveHiveKnowledgePath();
91878
- const hiveEntries = await readKnowledge(hivePath);
91879
- let hiveUpdated = false;
91880
- for (const entry of hiveEntries) {
91881
- if (remainingIds.includes(entry.id)) {
91882
- const ro = entry.retrieval_outcomes;
91883
- if (phaseSucceeded) {
91884
- ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
91885
- } else {
91886
- ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
91890
+ if (remainingIds.length > 0) {
91891
+ const hivePath = resolveHiveKnowledgePath();
91892
+ await transactKnowledge(hivePath, (hiveEntries) => {
91893
+ let mutated = false;
91894
+ for (const entry of hiveEntries) {
91895
+ if (remainingIds.includes(entry.id)) {
91896
+ const ro = entry.retrieval_outcomes;
91897
+ if (phaseSucceeded) {
91898
+ ro.succeeded_after_shown_count = (ro.succeeded_after_shown_count ?? 0) + 1;
91899
+ } else {
91900
+ ro.failed_after_shown_count = (ro.failed_after_shown_count ?? 0) + 1;
91901
+ }
91902
+ mutated = true;
91903
+ }
91887
91904
  }
91888
- hiveUpdated = true;
91889
- }
91890
- }
91891
- if (hiveUpdated) {
91892
- await rewriteKnowledge(hivePath, hiveEntries);
91905
+ return mutated ? hiveEntries : null;
91906
+ });
91893
91907
  }
91894
- delete shownData[phaseInfo];
91895
- await writeFile15(shownFile, JSON.stringify(shownData, null, 2), "utf-8");
91908
+ await transactShownFile(shownFile, (data) => {
91909
+ delete data[phaseInfo];
91910
+ return data;
91911
+ });
91896
91912
  } catch {
91897
91913
  warn("[swarm] Knowledge: failed to update retrieval outcomes");
91898
91914
  }
@@ -91956,6 +91972,7 @@ function scoreDirectiveAgainstContext(entry, ctx) {
91956
91972
  }
91957
91973
  var JACCARD_THRESHOLD2 = 0.6, HIVE_TIER_BOOST = 0.05, SAME_PROJECT_PENALTY = -0.05, NORMAL_RETRIEVAL_STATUSES;
91958
91974
  var init_knowledge_reader = __esm(() => {
91975
+ init_task_file();
91959
91976
  init_logger();
91960
91977
  init_knowledge_store();
91961
91978
  NORMAL_RETRIEVAL_STATUSES = new Set(["established", "promoted"]);
@@ -95318,9 +95335,9 @@ function createPhaseMonitorHook(directory, preflightManager, curatorRunner, dele
95318
95335
  const initResult = await runner(directory, curatorConfig, llmDelegate);
95319
95336
  if (initResult.briefing) {
95320
95337
  const briefingPath = path78.join(directory, ".swarm", "curator-briefing.md");
95321
- const { mkdir: mkdir14, writeFile: writeFile13 } = await import("node:fs/promises");
95338
+ const { mkdir: mkdir14, writeFile: writeFile11 } = await import("node:fs/promises");
95322
95339
  await mkdir14(path78.dirname(briefingPath), { recursive: true });
95323
- await writeFile13(briefingPath, initResult.briefing, "utf-8");
95340
+ await writeFile11(briefingPath, initResult.briefing, "utf-8");
95324
95341
  const { buildApprovedReceipt: buildApprovedReceipt2, persistReviewReceipt: persistReviewReceipt2 } = await Promise.resolve().then(() => (init_review_receipt(), exports_review_receipt));
95325
95342
  const initReceipt = buildApprovedReceipt2({
95326
95343
  agent: "curator",
@@ -102948,7 +102965,7 @@ ${errorSummary}`);
102948
102965
  init_schema();
102949
102966
  init_state();
102950
102967
  init_logger();
102951
- import { appendFile as appendFile10, mkdir as mkdir19 } from "node:fs/promises";
102968
+ import { appendFile as appendFile10, mkdir as mkdir18 } from "node:fs/promises";
102952
102969
  import * as path100 from "node:path";
102953
102970
 
102954
102971
  // src/hooks/knowledge-application.ts
@@ -102956,7 +102973,7 @@ init_logger();
102956
102973
  init_knowledge_store();
102957
102974
  var import_proper_lockfile8 = __toESM(require_proper_lockfile(), 1);
102958
102975
  import { existsSync as existsSync55 } from "node:fs";
102959
- import { appendFile as appendFile9, mkdir as mkdir18, readFile as readFile18 } from "node:fs/promises";
102976
+ import { appendFile as appendFile9, mkdir as mkdir17, readFile as readFile18 } from "node:fs/promises";
102960
102977
  import * as path99 from "node:path";
102961
102978
  function resolveApplicationLogPath(directory) {
102962
102979
  return path99.join(directory, ".swarm", "knowledge-application.jsonl");
@@ -102977,7 +102994,7 @@ function parseAcknowledgments(text) {
102977
102994
  }
102978
102995
  async function appendAudit(directory, record3) {
102979
102996
  const filePath = resolveApplicationLogPath(directory);
102980
- await mkdir18(path99.dirname(filePath), { recursive: true });
102997
+ await mkdir17(path99.dirname(filePath), { recursive: true });
102981
102998
  await appendFile9(filePath, `${JSON.stringify(record3)}
102982
102999
  `, "utf-8");
102983
103000
  }
@@ -103158,7 +103175,7 @@ async function knowledgeApplicationGateBefore(directory, input, config3) {
103158
103175
  }
103159
103176
  async function writeWarnEvent(directory, record3) {
103160
103177
  const filePath = path100.join(directory, ".swarm", "events.jsonl");
103161
- await mkdir19(path100.dirname(filePath), { recursive: true });
103178
+ await mkdir18(path100.dirname(filePath), { recursive: true });
103162
103179
  await appendFile10(filePath, `${JSON.stringify(record3)}
103163
103180
  `, "utf-8");
103164
103181
  }
@@ -103214,10 +103231,20 @@ init_manager();
103214
103231
  import { createHash as createHash9 } from "node:crypto";
103215
103232
 
103216
103233
  // src/services/run-memory.ts
103217
- init_utils2();
103218
- init_path_security();
103219
103234
  import * as crypto10 from "node:crypto";
103220
103235
  import * as fs63 from "node:fs/promises";
103236
+
103237
+ // src/hooks/context-sanitizer.ts
103238
+ function sanitizeContextText(text) {
103239
+ return text.split("").filter((char) => {
103240
+ const code = char.charCodeAt(0);
103241
+ return code === 9 || code === 10 || code === 13 || code > 31 && code !== 127;
103242
+ }).join("").replace(/[\u200B-\u200D\uFEFF]/g, "").replace(/[\u202A-\u202E\u2066-\u2069]/g, "").replace(/```/g, "` ` `").replace(/^system\s*:/gim, "[BLOCKED]:").replace(/<system\b[^>]*>/gi, "[BLOCKED-TAG]").replace(/<\/system>/gi, "[/BLOCKED-TAG]").replace(/<tool_call\b[^>]*>/gi, "[BLOCKED-TOOL]").replace(/<\/tool_call>/gi, "[/BLOCKED-TOOL]").replace(/<\/\w+>/g, "[/BLOCKED-TAG]");
103243
+ }
103244
+
103245
+ // src/services/run-memory.ts
103246
+ init_utils2();
103247
+ init_path_security();
103221
103248
  var RUN_MEMORY_FILENAME = "run-memory.jsonl";
103222
103249
  var MAX_SUMMARY_TOKENS = 500;
103223
103250
  function generateTaskFingerprint(taskId, fileTargets) {
@@ -103297,9 +103324,11 @@ function summarizeTask(taskId, entries) {
103297
103324
  if (lastPass) {
103298
103325
  const passAttempt = lastPass.attemptNumber;
103299
103326
  const failAttempt = lastFailure.attemptNumber;
103300
- return `Task ${taskId}: FAILED attempt ${failAttempt} — ${lastFailure.failureReason || "unknown"}. Passed on attempt ${passAttempt}.`;
103327
+ const reason = sanitizeContextText(lastFailure.failureReason || "unknown");
103328
+ return `Task ${taskId}: FAILED attempt ${failAttempt} — ${reason}. Passed on attempt ${passAttempt}.`;
103301
103329
  } else {
103302
- return `Task ${taskId}: FAILED ${failCount} times — last: ${lastFailure.failureReason || "unknown"}. Still failing.`;
103330
+ const reason = sanitizeContextText(lastFailure.failureReason || "unknown");
103331
+ return `Task ${taskId}: FAILED ${failCount} times — last: ${reason}. Still failing.`;
103303
103332
  }
103304
103333
  }
103305
103334
  async function getRunMemorySummary(directory) {
@@ -103458,12 +103487,7 @@ function buildDirectiveBlock(entries, charBudget, cfg) {
103458
103487
  return null;
103459
103488
  return block;
103460
103489
  }
103461
- function sanitizeLessonForContext(text) {
103462
- return text.split("").filter((char) => {
103463
- const code = char.charCodeAt(0);
103464
- return code === 9 || code === 10 || code === 13 || code > 31 && code !== 127;
103465
- }).join("").replace(/[\u200B-\u200D\uFEFF]/g, "").replace(/[\u202A-\u202E\u2066-\u2069]/g, "").replace(/```/g, "` ` `").replace(/^system\s*:/gim, "[BLOCKED]:");
103466
- }
103490
+ var sanitizeLessonForContext = sanitizeContextText;
103467
103491
  function isOrchestratorAgent(agentName) {
103468
103492
  const stripped = stripKnownSwarmPrefix(agentName);
103469
103493
  return stripped.toLowerCase() === "architect";
@@ -103576,14 +103600,14 @@ function createKnowledgeInjectorHook(directory, config3) {
103576
103600
  const latestReport = driftReports[driftReports.length - 1];
103577
103601
  const driftText = buildDriftInjectionText(latestReport, 500);
103578
103602
  if (driftText) {
103579
- freshPreamble = driftText;
103603
+ freshPreamble = sanitizeContextText(driftText);
103580
103604
  }
103581
103605
  }
103582
103606
  } catch {}
103583
103607
  try {
103584
103608
  const briefingContent = await readSwarmFileAsync(directory, "curator-briefing.md");
103585
103609
  if (briefingContent) {
103586
- const truncatedBriefing = briefingContent.slice(0, 500);
103610
+ const truncatedBriefing = sanitizeContextText(briefingContent).slice(0, 500);
103587
103611
  freshPreamble = freshPreamble ? `<curator_briefing>${truncatedBriefing}</curator_briefing>
103588
103612
 
103589
103613
  ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
@@ -103614,8 +103638,9 @@ ${freshPreamble}` : `<curator_briefing>${truncatedBriefing}</curator_briefing>`;
103614
103638
  remaining -= lessonBlock.length;
103615
103639
  }
103616
103640
  if (runMemory && remaining > 300) {
103617
- parts2.push(runMemory);
103618
- remaining -= runMemory.length;
103641
+ const sanitizedRunMemory = sanitizeContextText(runMemory);
103642
+ parts2.push(sanitizedRunMemory);
103643
+ remaining -= sanitizedRunMemory.length;
103619
103644
  }
103620
103645
  if (freshPreamble && remaining > 200) {
103621
103646
  let preambleToUse = freshPreamble;
@@ -113186,9 +113211,17 @@ var knowledge_remove = createSwarmTool({
113186
113211
  }
113187
113212
  const id = idInput;
113188
113213
  const swarmPath = resolveSwarmKnowledgePath(directory);
113189
- let entries;
113214
+ let found = false;
113215
+ let remaining = 0;
113190
113216
  try {
113191
- entries = await readKnowledge(swarmPath);
113217
+ await transactKnowledge(swarmPath, (entries) => {
113218
+ const filtered = entries.filter((entry) => entry.id !== id);
113219
+ if (filtered.length === entries.length)
113220
+ return null;
113221
+ found = true;
113222
+ remaining = filtered.length;
113223
+ return filtered;
113224
+ });
113192
113225
  } catch (err2) {
113193
113226
  const message = err2 instanceof Error ? err2.message : "Unknown error";
113194
113227
  return JSON.stringify({
@@ -113196,27 +113229,16 @@ var knowledge_remove = createSwarmTool({
113196
113229
  error: message
113197
113230
  });
113198
113231
  }
113199
- const originalCount = entries.length;
113200
- entries = entries.filter((entry) => entry.id !== id);
113201
- if (entries.length === originalCount) {
113232
+ if (!found) {
113202
113233
  return JSON.stringify({
113203
113234
  success: false,
113204
113235
  message: "entry not found"
113205
113236
  });
113206
113237
  }
113207
- try {
113208
- await rewriteKnowledge(swarmPath, entries);
113209
- } catch (err2) {
113210
- const message = err2 instanceof Error ? err2.message : "Unknown error";
113211
- return JSON.stringify({
113212
- success: false,
113213
- error: message
113214
- });
113215
- }
113216
113238
  return JSON.stringify({
113217
113239
  success: true,
113218
113240
  removed: 1,
113219
- remaining: entries.length
113241
+ remaining
113220
113242
  });
113221
113243
  }
113222
113244
  });
@@ -125063,7 +125085,7 @@ init_zod();
125063
125085
  init_config();
125064
125086
  init_schema();
125065
125087
  init_create_tool();
125066
- import { mkdir as mkdir24, rename as rename10, writeFile as writeFile19 } from "node:fs/promises";
125088
+ import { mkdir as mkdir23, rename as rename10, writeFile as writeFile16 } from "node:fs/promises";
125067
125089
  import * as path152 from "node:path";
125068
125090
  var MAX_SPEC_BYTES = 256 * 1024;
125069
125091
  var spec_write = createSwarmTool({
@@ -125106,7 +125128,7 @@ var spec_write = createSwarmTool({
125106
125128
  }, null, 2);
125107
125129
  }
125108
125130
  const target = path152.join(directory, ".swarm", "spec.md");
125109
- await mkdir24(path152.dirname(target), { recursive: true });
125131
+ await mkdir23(path152.dirname(target), { recursive: true });
125110
125132
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
125111
125133
  let finalContent = content;
125112
125134
  if (mode === "append") {
@@ -125125,7 +125147,7 @@ ${content}
125125
125147
  }
125126
125148
  } catch {}
125127
125149
  }
125128
- await writeFile19(tmp, finalContent, "utf-8");
125150
+ await writeFile16(tmp, finalContent, "utf-8");
125129
125151
  await rename10(tmp, target);
125130
125152
  return JSON.stringify({ written: true, path: target, bytes: finalContent.length }, null, 2);
125131
125153
  }
@@ -127798,7 +127820,7 @@ function createWebSearchProvider(config3) {
127798
127820
  init_utils2();
127799
127821
  init_redaction();
127800
127822
  import { createHash as createHash12 } from "node:crypto";
127801
- import { appendFile as appendFile14, mkdir as mkdir25 } from "node:fs/promises";
127823
+ import { appendFile as appendFile14, mkdir as mkdir24 } from "node:fs/promises";
127802
127824
  import * as path161 from "node:path";
127803
127825
  var EVIDENCE_CACHE_FILE = "evidence-cache/documents.jsonl";
127804
127826
  var MAX_EVIDENCE_TEXT_LENGTH = 4000;
@@ -127807,7 +127829,7 @@ async function writeEvidenceDocuments(directory, inputs, now = () => new Date) {
127807
127829
  const capturedAt = now().toISOString();
127808
127830
  const records = inputs.map((input) => createEvidenceDocumentRecord(input, capturedAt)).filter((record3) => record3 !== null);
127809
127831
  if (records.length > 0) {
127810
- await mkdir25(path161.dirname(filePath), { recursive: true });
127832
+ await mkdir24(path161.dirname(filePath), { recursive: true });
127811
127833
  await appendFile14(filePath, `${records.map((record3) => JSON.stringify(record3)).join(`
127812
127834
  `)}
127813
127835
  `, "utf-8");