opencode-swarm 7.93.1 → 7.94.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/.opencode/skills/plan/SKILL.md +2 -2
  2. package/dist/agents/council-prompts.d.ts +3 -3
  3. package/dist/agents/critic.d.ts +6 -6
  4. package/dist/agents/explorer.d.ts +2 -2
  5. package/dist/agents/read-only-lane-guidance.d.ts +1 -0
  6. package/dist/cli/{config-doctor-fkwyrtpq.js → config-doctor-ecmx9scq.js} +2 -2
  7. package/dist/cli/{explorer-4ttwy7jd.js → explorer-jc46negv.js} +1 -1
  8. package/dist/cli/{guardrail-explain-bjsc2ydm.js → guardrail-explain-we8mhb6y.js} +8 -8
  9. package/dist/cli/{guardrail-log-x3w800x5.js → guardrail-log-0q6pvbpx.js} +3 -3
  10. package/dist/cli/{index-1x2608ga.js → index-2a6ppa65.js} +14 -2
  11. package/dist/cli/{index-xsbtbffr.js → index-79dcqsg9.js} +4 -0
  12. package/dist/cli/{index-mv27v975.js → index-a59fjg9v.js} +1141 -15
  13. package/dist/cli/{index-ne4g3mk1.js → index-dgjsa6hy.js} +1 -1
  14. package/dist/cli/{index-5hrexm02.js → index-fjxjb66n.js} +166 -5
  15. package/dist/cli/{index-w7gkpmq8.js → index-hb10a2g8.js} +35 -2
  16. package/dist/cli/{index-dy6zs70b.js → index-jv0bz96v.js} +9 -9
  17. package/dist/cli/{index-9j1xvd8m.js → index-q8qx8p47.js} +2 -2
  18. package/dist/cli/{index-yykcmn6m.js → index-tx5czwpd.js} +1 -1
  19. package/dist/cli/{index-2jpbaedv.js → index-vqg905es.js} +1 -1
  20. package/dist/cli/index.js +7 -7
  21. package/dist/cli/{knowledge-store-eqans52j.js → knowledge-store-pa58msy5.js} +3 -1
  22. package/dist/cli/{schema-1kndsf0c.js → schema-jy18ftky.js} +1 -1
  23. package/dist/cli/{skill-generator-d0jzw6n2.js → skill-generator-3tkwcg4x.js} +12 -2
  24. package/dist/hooks/curator.d.ts +8 -3
  25. package/dist/hooks/knowledge-events.d.ts +12 -1
  26. package/dist/hooks/knowledge-store.d.ts +2 -0
  27. package/dist/index.js +1114 -621
  28. package/dist/services/skill-generator.d.ts +46 -0
  29. package/dist/tools/index.d.ts +1 -0
  30. package/dist/tools/manifest.d.ts +1 -0
  31. package/dist/tools/stale-reconciliation.d.ts +23 -0
  32. package/dist/tools/tool-metadata.d.ts +7 -2
  33. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  // @bun
2
2
  import {
3
3
  stripKnownSwarmPrefix
4
- } from "./index-xsbtbffr.js";
4
+ } from "./index-79dcqsg9.js";
5
5
  import {
6
6
  init_logger,
7
7
  warn
@@ -10,7 +10,7 @@ import {
10
10
  resolveSwarmRejectedPath,
11
11
  rewriteKnowledge,
12
12
  transactKnowledge
13
- } from "./index-w7gkpmq8.js";
13
+ } from "./index-hb10a2g8.js";
14
14
  import {
15
15
  atomicWriteFile
16
16
  } from "./index-kv4dd5c5.js";
@@ -28,7 +28,7 @@ import {
28
28
 
29
29
  // src/services/skill-generator.ts
30
30
  import { existsSync as existsSync3, unlinkSync } from "fs";
31
- import { mkdir as mkdir5, readFile as readFile4, rename as rename2, writeFile as writeFile3 } from "fs/promises";
31
+ import { mkdir as mkdir5, readFile as readFile4, rename as rename2, unlink, writeFile as writeFile3 } from "fs/promises";
32
32
  import * as path5 from "path";
33
33
 
34
34
  // src/hooks/knowledge-events.ts
@@ -2045,10 +2045,81 @@ async function activateProposal(directory, slug, force = false, options = {}) {
2045
2045
  };
2046
2046
  }
2047
2047
  }
2048
+ async function findSkillsBySourceKnowledgeId(directory, sourceId) {
2049
+ const activeDir = path5.join(directory, ".opencode", "skills", "generated");
2050
+ const fs = await import("fs/promises");
2051
+ if (!existsSync3(activeDir))
2052
+ return [];
2053
+ const entries = await fs.readdir(activeDir, { withFileTypes: true });
2054
+ const matches = [];
2055
+ for (const e of entries) {
2056
+ if (!e.isDirectory())
2057
+ continue;
2058
+ const skillDir = path5.join(activeDir, e.name);
2059
+ const retiredMarker = path5.join(skillDir, "retired.marker");
2060
+ if (existsSync3(retiredMarker))
2061
+ continue;
2062
+ const staleMarker = path5.join(skillDir, "stale.marker");
2063
+ if (existsSync3(staleMarker))
2064
+ continue;
2065
+ const skillPath = path5.join(skillDir, "SKILL.md");
2066
+ if (!existsSync3(skillPath))
2067
+ continue;
2068
+ let content;
2069
+ try {
2070
+ content = await fs.readFile(skillPath, "utf-8");
2071
+ } catch {
2072
+ continue;
2073
+ }
2074
+ const fm = parseDraftFrontmatter(content);
2075
+ if (fm?.sourceKnowledgeIds.includes(sourceId)) {
2076
+ matches.push(skillDir);
2077
+ }
2078
+ }
2079
+ return matches;
2080
+ }
2081
+ async function findStaleSkillsBySourceKnowledgeId(directory, archivedIds) {
2082
+ const activeDir = path5.join(directory, ".opencode", "skills", "generated");
2083
+ if (!existsSync3(activeDir))
2084
+ return [];
2085
+ const fs = await import("fs/promises");
2086
+ const entries = await fs.readdir(activeDir, { withFileTypes: true });
2087
+ const matches = [];
2088
+ for (const e of entries) {
2089
+ if (!e.isDirectory())
2090
+ continue;
2091
+ const skillDir = path5.join(activeDir, e.name);
2092
+ const retiredMarker = path5.join(skillDir, "retired.marker");
2093
+ if (existsSync3(retiredMarker))
2094
+ continue;
2095
+ const staleMarker = path5.join(skillDir, "stale.marker");
2096
+ if (!existsSync3(staleMarker))
2097
+ continue;
2098
+ const skillPath = path5.join(skillDir, "SKILL.md");
2099
+ if (!existsSync3(skillPath))
2100
+ continue;
2101
+ let content;
2102
+ try {
2103
+ content = await fs.readFile(skillPath, "utf-8");
2104
+ } catch {
2105
+ continue;
2106
+ }
2107
+ const fm = parseDraftFrontmatter(content);
2108
+ const sourceIds = fm?.sourceKnowledgeIds ?? [];
2109
+ if (sourceIds.length === 0)
2110
+ continue;
2111
+ const allArchived = sourceIds.every((id) => archivedIds.has(id));
2112
+ if (allArchived) {
2113
+ matches.push(skillDir);
2114
+ }
2115
+ }
2116
+ return matches;
2117
+ }
2048
2118
  async function listSkills(directory) {
2049
2119
  const result = {
2050
2120
  proposals: [],
2051
- active: []
2121
+ active: [],
2122
+ stale: []
2052
2123
  };
2053
2124
  const proposalsDir = path5.join(directory, ".swarm", "skills", "proposals");
2054
2125
  const activeDir = path5.join(directory, ".opencode", "skills", "generated");
@@ -2073,6 +2144,16 @@ async function listSkills(directory) {
2073
2144
  const retiredMarker = path5.join(activeDir, e.name, "retired.marker");
2074
2145
  if (existsSync3(retiredMarker))
2075
2146
  continue;
2147
+ const staleMarker = path5.join(activeDir, e.name, "stale.marker");
2148
+ if (existsSync3(staleMarker)) {
2149
+ let reason = "stale";
2150
+ try {
2151
+ const content = await fs.readFile(staleMarker, "utf-8");
2152
+ reason = content.trim() || "stale";
2153
+ } catch {}
2154
+ result.stale.push({ slug: e.name, reason });
2155
+ continue;
2156
+ }
2076
2157
  const skillPath = path5.join(activeDir, e.name, "SKILL.md");
2077
2158
  if (existsSync3(skillPath)) {
2078
2159
  result.active.push({
@@ -2159,7 +2240,34 @@ async function inspectSkill(directory, slug, prefer = "auto") {
2159
2240
  for (const c of candidates) {
2160
2241
  if (existsSync3(c.p)) {
2161
2242
  const content = await readFile4(c.p, "utf-8");
2162
- return { found: true, path: c.p, content, mode: c.m };
2243
+ const result = { found: true, path: c.p, content, mode: c.m };
2244
+ const fm = parseDraftFrontmatter(content);
2245
+ if (fm && fm.sourceKnowledgeIds.length > 0) {
2246
+ const swarm = await readKnowledge(resolveSwarmKnowledgePath(directory));
2247
+ const hivePath = resolveHiveKnowledgePath();
2248
+ const hive = existsSync3(hivePath) ? await readKnowledge(hivePath) : [];
2249
+ const allEntries = [...swarm, ...hive];
2250
+ const entryMap = new Map(allEntries.map((e) => [e.id, e]));
2251
+ result.source_knowledge_status = fm.sourceKnowledgeIds.map((id) => {
2252
+ const entry = entryMap.get(id);
2253
+ if (!entry)
2254
+ return { id, status: "deleted" };
2255
+ if (entry.status === "archived" || entry.status === "quarantined") {
2256
+ return { id, status: "archived" };
2257
+ }
2258
+ return { id, status: "active" };
2259
+ });
2260
+ }
2261
+ if (c.m === "active") {
2262
+ const skillDir = path5.join(directory, ".opencode", "skills", "generated", cleanSlug);
2263
+ const staleMarker = path5.join(skillDir, "stale.marker");
2264
+ if (existsSync3(staleMarker)) {
2265
+ try {
2266
+ result.stale_reason = await readFile4(staleMarker, "utf-8");
2267
+ } catch {}
2268
+ }
2269
+ }
2270
+ return result;
2163
2271
  }
2164
2272
  }
2165
2273
  return { found: false };
@@ -2198,6 +2306,54 @@ async function retireSkill(directory, slug, reason) {
2198
2306
  reason
2199
2307
  };
2200
2308
  }
2309
+ async function markSkillStale(skillDir, reason) {
2310
+ await mkdir5(skillDir, { recursive: true });
2311
+ await writeFile3(path5.join(skillDir, "stale.marker"), reason, "utf-8");
2312
+ }
2313
+ async function clearSkillStale(skillDir) {
2314
+ const markerPath = path5.join(skillDir, "stale.marker");
2315
+ try {
2316
+ await unlink(markerPath);
2317
+ } catch (err) {
2318
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
2319
+ return;
2320
+ }
2321
+ warn(`[skill-generator] failed to remove stale.marker at ${markerPath}: ${err instanceof Error ? err.message : String(err)}`);
2322
+ }
2323
+ }
2324
+ async function retireOrMarkStale(directory, skillDir, archivedKnowledgeIds) {
2325
+ const fs = await import("fs/promises");
2326
+ const skillPath = path5.join(skillDir, "SKILL.md");
2327
+ if (!existsSync3(skillPath)) {
2328
+ await markSkillStale(skillDir, "source knowledge archived, SKILL.md missing");
2329
+ const slug2 = path5.basename(skillDir);
2330
+ return { action: "stale", slug: slug2, skillDir };
2331
+ }
2332
+ let content;
2333
+ try {
2334
+ content = await fs.readFile(skillPath, "utf-8");
2335
+ } catch {
2336
+ await markSkillStale(skillDir, "source knowledge archived, SKILL.md unreadable");
2337
+ const slug2 = path5.basename(skillDir);
2338
+ return { action: "stale", slug: slug2, skillDir };
2339
+ }
2340
+ const fm = parseDraftFrontmatter(content);
2341
+ const sourceIds = fm?.sourceKnowledgeIds ?? [];
2342
+ if (sourceIds.length === 0) {
2343
+ await markSkillStale(skillDir, "source knowledge archived, no source_knowledge_ids in frontmatter");
2344
+ const slug2 = path5.basename(skillDir);
2345
+ return { action: "stale", slug: slug2, skillDir };
2346
+ }
2347
+ const allArchived = sourceIds.every((id) => archivedKnowledgeIds.has(id));
2348
+ const slug = path5.basename(skillDir);
2349
+ if (allArchived) {
2350
+ await retireSkill(directory, slug, "all source knowledge entries archived or deleted");
2351
+ return { action: "retire", slug, skillDir };
2352
+ } else {
2353
+ await markSkillStale(skillDir, "one or more source knowledge entries archived");
2354
+ return { action: "stale", slug, skillDir };
2355
+ }
2356
+ }
2201
2357
  async function regenerateSkill(directory, slug, options = {}) {
2202
2358
  const cleanSlug = sanitizeSlug(slug);
2203
2359
  if (!isValidSlug2(cleanSlug)) {
@@ -2357,6 +2513,7 @@ async function regenerateSkill(directory, slug, options = {}) {
2357
2513
  try {
2358
2514
  await atomicWrite2(skillPath, content);
2359
2515
  await stampSourceEntries(directory, cleanSlug, matchedEntries.map((e) => e.id));
2516
+ await clearSkillStale(path5.dirname(activePath(directory, cleanSlug)));
2360
2517
  } catch (writeErr) {
2361
2518
  return {
2362
2519
  regenerated: false,
@@ -2391,13 +2548,17 @@ var _internals = {
2391
2548
  generateSkills,
2392
2549
  activateProposal,
2393
2550
  listSkills,
2551
+ findSkillsBySourceKnowledgeId,
2552
+ findStaleSkillsBySourceKnowledgeId,
2394
2553
  inspectSkill,
2395
2554
  stampSourceEntries,
2396
2555
  parseDraftFrontmatter,
2397
2556
  retireSkill,
2557
+ retireOrMarkStale,
2398
2558
  regenerateSkill,
2559
+ clearSkillStale,
2399
2560
  autoApplyProposals,
2400
2561
  unlinkSync
2401
2562
  };
2402
2563
 
2403
- export { resolveKnowledgeEventsPath, readKnowledgeEvents, readKnowledgeCounterRollups, effectiveRetrievalOutcomes, validateLesson, validateActionableFields, validateActionability, resolveUnactionablePath, appendUnactionable, quarantineEntry, restoreEntry, sanitizeSlug, isValidSlug2 as isValidSlug, proposalPath, activePath, activeRepoRelativePath, DEFAULT_SKILL_MIN_CONFIDENCE, DEFAULT_SKILL_MIN_CONFIRMATIONS, STRONG_SKILL_OUTCOME_COUNT, HIGH_PRIORITY_SKILL_MIN_CONFIDENCE, selectCandidateEntries, isSkillMaturityEligible, clusterEntries, renderSkillMarkdown, generateSkills, parseDraftFrontmatter, activateProposal, listSkills, autoApplyProposals, inspectSkill, retireSkill, regenerateSkill, _internals };
2564
+ export { resolveKnowledgeEventsPath, readKnowledgeEvents, readKnowledgeCounterRollups, effectiveRetrievalOutcomes, validateLesson, validateActionableFields, validateActionability, resolveUnactionablePath, appendUnactionable, quarantineEntry, restoreEntry, sanitizeSlug, isValidSlug2 as isValidSlug, proposalPath, activePath, activeRepoRelativePath, DEFAULT_SKILL_MIN_CONFIDENCE, DEFAULT_SKILL_MIN_CONFIRMATIONS, STRONG_SKILL_OUTCOME_COUNT, HIGH_PRIORITY_SKILL_MIN_CONFIDENCE, selectCandidateEntries, isSkillMaturityEligible, clusterEntries, renderSkillMarkdown, generateSkills, parseDraftFrontmatter, activateProposal, findSkillsBySourceKnowledgeId, findStaleSkillsBySourceKnowledgeId, listSkills, autoApplyProposals, inspectSkill, retireSkill, markSkillStale, clearSkillStale, retireOrMarkStale, regenerateSkill, _internals };
@@ -386,6 +386,38 @@ async function transactKnowledge(filePath, mutate) {
386
386
  await atomicWriteFile(fp, content);
387
387
  }, mutate);
388
388
  }
389
+ async function getArchivedKnowledgeIds(directory) {
390
+ const archived = new Set;
391
+ const swarmPath = resolveSwarmKnowledgePath(directory);
392
+ try {
393
+ const content = await readFile(swarmPath, "utf-8");
394
+ const lines = content.split(`
395
+ `).filter((l) => l.trim());
396
+ for (const line of lines) {
397
+ try {
398
+ const entry = JSON.parse(line);
399
+ if (entry.status === "archived" || entry.status === "quarantined" || entry.status === "quarantined_unactionable") {
400
+ archived.add(entry.id);
401
+ }
402
+ } catch {}
403
+ }
404
+ } catch {}
405
+ const hivePath = resolveHiveKnowledgePath();
406
+ try {
407
+ const content = await readFile(hivePath, "utf-8");
408
+ const lines = content.split(`
409
+ `).filter((l) => l.trim());
410
+ for (const line of lines) {
411
+ try {
412
+ const entry = JSON.parse(line);
413
+ if (entry.status === "archived" || entry.status === "quarantined" || entry.status === "quarantined_unactionable") {
414
+ archived.add(entry.id);
415
+ }
416
+ } catch {}
417
+ }
418
+ } catch {}
419
+ return archived;
420
+ }
389
421
  async function appendKnowledgeWithCapEnforcement(filePath, entry, maxEntries) {
390
422
  return transactKnowledge(filePath, (entries) => {
391
423
  const updated = [...entries, entry];
@@ -677,7 +709,8 @@ var _internals = {
677
709
  computeOutcomeSignal,
678
710
  selectKnowledgeCapSurvivors,
679
711
  inferTags,
680
- bumpKnowledgeConfidenceBatch
712
+ bumpKnowledgeConfidenceBatch,
713
+ getArchivedKnowledgeIds
681
714
  };
682
715
 
683
- export { resolveLinkDir, sanitizeLinkId, readLinkPointer, writeLinkPointer, removeLinkPointer, resolveKnowledgeStoreDir, isLinked, getPlatformConfigDir, resolveSwarmKnowledgePath, resolveSwarmRejectedPath, resolveSwarmRetractionsPath, resolveHiveKnowledgePath, resolveHiveRejectedPath, resolveHiveEventsPath, readKnowledge, normalizeEntry, readRejectedLessons, readRetractionRecords, appendRetractionRecord, appendKnowledge, rewriteKnowledge, transactFile, transactKnowledge, appendKnowledgeWithCapEnforcement, enforceKnowledgeCap, sweepAgedEntries, sweepStaleTodos, appendRejectedLesson, normalize, wordBigrams, jaccardBigram, findNearDuplicate, computeConfidence, OUTCOME_SIGNAL_SMOOTHING, computeOutcomeSignal, inferTags, bumpKnowledgeConfidenceBatch, _internals };
716
+ export { resolveLinkDir, sanitizeLinkId, readLinkPointer, writeLinkPointer, removeLinkPointer, resolveKnowledgeStoreDir, isLinked, getPlatformConfigDir, resolveSwarmKnowledgePath, resolveSwarmRejectedPath, resolveSwarmRetractionsPath, resolveHiveKnowledgePath, resolveHiveRejectedPath, resolveHiveEventsPath, readKnowledge, normalizeEntry, readRejectedLessons, readRetractionRecords, appendRetractionRecord, appendKnowledge, rewriteKnowledge, transactFile, transactKnowledge, getArchivedKnowledgeIds, appendKnowledgeWithCapEnforcement, enforceKnowledgeCap, sweepAgedEntries, sweepStaleTodos, appendRejectedLesson, normalize, wordBigrams, jaccardBigram, findNearDuplicate, computeConfidence, OUTCOME_SIGNAL_SMOOTHING, computeOutcomeSignal, inferTags, bumpKnowledgeConfidenceBatch, _internals };
@@ -1,10 +1,10 @@
1
1
  // @bun
2
2
  import {
3
3
  handleGuardrailExplain
4
- } from "./index-9j1xvd8m.js";
4
+ } from "./index-q8qx8p47.js";
5
5
  import {
6
6
  handleGuardrailLog
7
- } from "./index-yykcmn6m.js";
7
+ } from "./index-tx5czwpd.js";
8
8
  import {
9
9
  COMMAND_REGISTRY,
10
10
  SWARM_COMMAND_TOOL_ALLOWLIST,
@@ -78,17 +78,17 @@ import {
78
78
  handleWriteRetroCommand,
79
79
  normalizeSwarmCommandInput,
80
80
  resolveCommand
81
- } from "./index-mv27v975.js";
82
- import"./index-ne4g3mk1.js";
83
- import"./index-1x2608ga.js";
84
- import"./index-5hrexm02.js";
85
- import"./index-w7gkpmq8.js";
86
- import"./index-2jpbaedv.js";
81
+ } from "./index-a59fjg9v.js";
82
+ import"./index-dgjsa6hy.js";
83
+ import"./index-2a6ppa65.js";
84
+ import"./index-fjxjb66n.js";
85
+ import"./index-hb10a2g8.js";
86
+ import"./index-vqg905es.js";
87
87
  import {
88
88
  AGENT_TOOL_MAP,
89
89
  ORCHESTRATOR_NAME,
90
90
  stripKnownSwarmPrefix
91
- } from "./index-xsbtbffr.js";
91
+ } from "./index-79dcqsg9.js";
92
92
  import"./index-y1z6yaq4.js";
93
93
  import"./index-adz3nk9b.js";
94
94
  import"./index-v4fcn4tr.js";
@@ -12,14 +12,14 @@ import {
12
12
  detectPosixWrites,
13
13
  detectWindowsWrites,
14
14
  resolveWriteTargets
15
- } from "./index-mv27v975.js";
15
+ } from "./index-a59fjg9v.js";
16
16
  import {
17
17
  checkFileAuthority,
18
18
  classifyFile,
19
19
  isInDeclaredScope,
20
20
  redactPath,
21
21
  redactShellCommand
22
- } from "./index-ne4g3mk1.js";
22
+ } from "./index-dgjsa6hy.js";
23
23
 
24
24
  // src/services/guardrail-explain-service.ts
25
25
  import path from "path";
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  redactPath,
4
4
  redactShellCommand
5
- } from "./index-ne4g3mk1.js";
5
+ } from "./index-dgjsa6hy.js";
6
6
 
7
7
  // src/services/guardrail-log-service.ts
8
8
  import * as fs from "fs/promises";
@@ -3,7 +3,7 @@ import {
3
3
  ALL_AGENT_NAMES,
4
4
  PluginConfigSchema,
5
5
  stripKnownSwarmPrefix
6
- } from "./index-xsbtbffr.js";
6
+ } from "./index-79dcqsg9.js";
7
7
  import {
8
8
  log
9
9
  } from "./index-zgwm4ryv.js";
package/dist/cli/index.js CHANGED
@@ -7,15 +7,15 @@ import {
7
7
  getPluginLockFilePaths,
8
8
  package_default,
9
9
  resolveCommand
10
- } from "./index-mv27v975.js";
11
- import"./index-ne4g3mk1.js";
12
- import"./index-1x2608ga.js";
13
- import"./index-5hrexm02.js";
14
- import"./index-w7gkpmq8.js";
15
- import"./index-2jpbaedv.js";
10
+ } from "./index-a59fjg9v.js";
11
+ import"./index-dgjsa6hy.js";
12
+ import"./index-2a6ppa65.js";
13
+ import"./index-fjxjb66n.js";
14
+ import"./index-hb10a2g8.js";
15
+ import"./index-vqg905es.js";
16
16
  import {
17
17
  DEFAULT_AGENT_CONFIGS
18
- } from "./index-xsbtbffr.js";
18
+ } from "./index-79dcqsg9.js";
19
19
  import"./index-y1z6yaq4.js";
20
20
  import"./index-adz3nk9b.js";
21
21
  import"./index-v4fcn4tr.js";
@@ -11,6 +11,7 @@ import {
11
11
  computeOutcomeSignal,
12
12
  enforceKnowledgeCap,
13
13
  findNearDuplicate,
14
+ getArchivedKnowledgeIds,
14
15
  getPlatformConfigDir,
15
16
  inferTags,
16
17
  jaccardBigram,
@@ -31,7 +32,7 @@ import {
31
32
  transactFile,
32
33
  transactKnowledge,
33
34
  wordBigrams
34
- } from "./index-w7gkpmq8.js";
35
+ } from "./index-hb10a2g8.js";
35
36
  import"./index-kv4dd5c5.js";
36
37
  import"./index-jtqkh8jf.js";
37
38
  import"./index-91qtsbce.js";
@@ -59,6 +60,7 @@ export {
59
60
  jaccardBigram,
60
61
  inferTags,
61
62
  getPlatformConfigDir,
63
+ getArchivedKnowledgeIds,
62
64
  findNearDuplicate,
63
65
  enforceKnowledgeCap,
64
66
  computeOutcomeSignal,
@@ -81,7 +81,7 @@ import {
81
81
  resolveGeneratedAgentRole,
82
82
  resolveGuardrailsConfig,
83
83
  stripKnownSwarmPrefix
84
- } from "./index-xsbtbffr.js";
84
+ } from "./index-79dcqsg9.js";
85
85
  import"./index-p0arc26j.js";
86
86
  import"./index-293f68mj.js";
87
87
  import"./index-a76rekgs.js";
@@ -9,21 +9,26 @@ import {
9
9
  activePath,
10
10
  activeRepoRelativePath,
11
11
  autoApplyProposals,
12
+ clearSkillStale,
12
13
  clusterEntries,
14
+ findSkillsBySourceKnowledgeId,
15
+ findStaleSkillsBySourceKnowledgeId,
13
16
  generateSkills,
14
17
  inspectSkill,
15
18
  isSkillMaturityEligible,
16
19
  isValidSlug,
17
20
  listSkills,
21
+ markSkillStale,
18
22
  parseDraftFrontmatter,
19
23
  proposalPath,
20
24
  regenerateSkill,
21
25
  renderSkillMarkdown,
26
+ retireOrMarkStale,
22
27
  retireSkill,
23
28
  sanitizeSlug,
24
29
  selectCandidateEntries
25
- } from "./index-5hrexm02.js";
26
- import"./index-w7gkpmq8.js";
30
+ } from "./index-fjxjb66n.js";
31
+ import"./index-hb10a2g8.js";
27
32
  import"./index-kv4dd5c5.js";
28
33
  import"./index-jtqkh8jf.js";
29
34
  import"./index-zgwm4ryv.js";
@@ -35,16 +40,21 @@ export {
35
40
  selectCandidateEntries,
36
41
  sanitizeSlug,
37
42
  retireSkill,
43
+ retireOrMarkStale,
38
44
  renderSkillMarkdown,
39
45
  regenerateSkill,
40
46
  proposalPath,
41
47
  parseDraftFrontmatter,
48
+ markSkillStale,
42
49
  listSkills,
43
50
  isValidSlug,
44
51
  isSkillMaturityEligible,
45
52
  inspectSkill,
46
53
  generateSkills,
54
+ findStaleSkillsBySourceKnowledgeId,
55
+ findSkillsBySourceKnowledgeId,
47
56
  clusterEntries,
57
+ clearSkillStale,
48
58
  autoApplyProposals,
49
59
  activeRepoRelativePath,
50
60
  activePath,
@@ -24,10 +24,10 @@
24
24
  * This dual dispatch means agent lists are incomplete — they capture factory-dispatched
25
25
  * curators but omit hook-dispatched ones. This is by design for hook-internal operations.
26
26
  */
27
- import { listSkills, parseDraftFrontmatter, retireSkill } from '../services/skill-generator.js';
27
+ import { listSkills, parseDraftFrontmatter, retireOrMarkStale, retireSkill } from '../services/skill-generator.js';
28
28
  import { getSkillVersion, reviseSkill } from '../services/skill-reviser.js';
29
29
  import type { ComplianceObservation, CuratorConfig, CuratorInitResult, CuratorPhaseResult, CuratorSummary, KnowledgeRecommendation } from './curator-types.js';
30
- import { readKnowledge } from './knowledge-store.js';
30
+ import { getArchivedKnowledgeIds, readKnowledge } from './knowledge-store.js';
31
31
  import type { KnowledgeConfig } from './knowledge-types.js';
32
32
  import { readSkillUsageEntries } from './skill-usage-log.js';
33
33
  /**
@@ -48,7 +48,9 @@ export declare const _internals: {
48
48
  readSkillUsageEntries: typeof readSkillUsageEntries;
49
49
  listSkills: typeof listSkills;
50
50
  parseDraftFrontmatter: typeof parseDraftFrontmatter;
51
+ retireOrMarkStale: typeof retireOrMarkStale;
51
52
  retireSkill: typeof retireSkill;
53
+ getArchivedKnowledgeIds: typeof getArchivedKnowledgeIds;
52
54
  readFileAsync: (filePath: string, encoding: string) => Promise<string>;
53
55
  readKnowledge: typeof readKnowledge;
54
56
  reviseSkill: typeof reviseSkill;
@@ -63,10 +65,13 @@ export interface RecommendationParseDiagnostic {
63
65
  * Auto-retire generated skills whose violation rate exceeds 30% or
64
66
  * whose source knowledge entries are all archived.
65
67
  *
68
+ * Also marks skills stale when some (but not all) source knowledge entries
69
+ * are archived.
70
+ *
66
71
  * Non-blocking: errors are caught and logged but never propagated.
67
72
  * Returns an array of observation strings to include in the phase digest.
68
73
  */
69
- declare function autoRetireSkills(directory: string, curatorKnowledgePath: string, excludeSlugs?: ReadonlySet<string>): Promise<string[]>;
74
+ declare function autoRetireSkills(directory: string, _curatorKnowledgePath: string, excludeSlugs?: ReadonlySet<string>): Promise<string[]>;
70
75
  /**
71
76
  * Parse OBSERVATIONS section from curator LLM output.
72
77
  * Expected format per line: "- entry <uuid> (<observable>): [text]"
@@ -132,7 +132,18 @@ export interface EscalationEvent {
132
132
  reason: string;
133
133
  enforcement_mode?: string;
134
134
  }
135
- export type KnowledgeEvent = RetrievedEvent | ReceiptEvent | OutcomeEvent | ArchivedEvent | EscalationEvent;
135
+ /** A batch of skills were invalidated after a knowledge entry was archived/purged. */
136
+ export interface SkillStaleBatchEvent {
137
+ type: 'skill-stale-batch';
138
+ schema_version?: number;
139
+ event_id?: string;
140
+ timestamp?: string;
141
+ skillIds: string[];
142
+ archivedIds: string[];
143
+ retiredCount: number;
144
+ staleCount: number;
145
+ }
146
+ export type KnowledgeEvent = RetrievedEvent | ReceiptEvent | OutcomeEvent | ArchivedEvent | EscalationEvent | SkillStaleBatchEvent;
136
147
  export type KnowledgeEventType = KnowledgeEvent['type'];
137
148
  /**
138
149
  * Event shape accepted by {@link appendKnowledgeEvent} / {@link recordKnowledgeEvent}.
@@ -26,6 +26,7 @@ export declare function appendKnowledge<T>(filePath: string, entry: T): Promise<
26
26
  export declare function rewriteKnowledge<T>(filePath: string, entries: T[]): Promise<void>;
27
27
  export declare function transactFile<T>(filePath: string, read: (filePath: string) => Promise<T>, write: (filePath: string, data: T) => Promise<void>, mutate: (data: T) => T | null): Promise<boolean>;
28
28
  export declare function transactKnowledge<T>(filePath: string, mutate: (entries: T[]) => T[] | null): Promise<boolean>;
29
+ export declare function getArchivedKnowledgeIds(directory: string): Promise<Set<string>>;
29
30
  export declare function appendKnowledgeWithCapEnforcement<T>(filePath: string, entry: T, maxEntries: number): Promise<boolean>;
30
31
  export declare function enforceKnowledgeCap<T>(filePath: string, maxEntries: number): Promise<void>;
31
32
  declare function selectKnowledgeCapSurvivors<T>(entries: T[], maxEntries: number): T[];
@@ -95,5 +96,6 @@ export declare const _internals: {
95
96
  selectKnowledgeCapSurvivors: typeof selectKnowledgeCapSurvivors;
96
97
  inferTags: typeof inferTags;
97
98
  bumpKnowledgeConfidenceBatch: typeof bumpKnowledgeConfidenceBatch;
99
+ getArchivedKnowledgeIds: typeof getArchivedKnowledgeIds;
98
100
  };
99
101
  export {};