cognitive-core 0.0.2 → 0.1.0

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 (329) hide show
  1. package/README.md +302 -116
  2. package/SKILL.md +193 -0
  3. package/dist/agents/index.d.ts +3 -0
  4. package/dist/agents/index.d.ts.map +1 -0
  5. package/dist/agents/index.js +5 -0
  6. package/dist/agents/index.js.map +1 -0
  7. package/dist/agents/mock-provider.d.ts +23 -0
  8. package/dist/agents/mock-provider.d.ts.map +1 -0
  9. package/dist/agents/mock-provider.js +71 -0
  10. package/dist/agents/mock-provider.js.map +1 -0
  11. package/dist/agents/types.d.ts +98 -0
  12. package/dist/agents/types.d.ts.map +1 -0
  13. package/dist/agents/types.js +44 -0
  14. package/dist/agents/types.js.map +1 -0
  15. package/dist/atlas.d.ts +196 -0
  16. package/dist/atlas.d.ts.map +1 -0
  17. package/dist/atlas.js +373 -0
  18. package/dist/atlas.js.map +1 -0
  19. package/dist/bin/cognitive-core.d.ts +18 -0
  20. package/dist/bin/cognitive-core.d.ts.map +1 -0
  21. package/dist/bin/cognitive-core.js +419 -0
  22. package/dist/bin/cognitive-core.js.map +1 -0
  23. package/dist/embeddings/bm25.d.ts +104 -0
  24. package/dist/embeddings/bm25.d.ts.map +1 -0
  25. package/dist/embeddings/bm25.js +264 -0
  26. package/dist/embeddings/bm25.js.map +1 -0
  27. package/dist/embeddings/index.d.ts +12 -0
  28. package/dist/embeddings/index.d.ts.map +1 -0
  29. package/dist/embeddings/index.js +16 -0
  30. package/dist/embeddings/index.js.map +1 -0
  31. package/dist/embeddings/manager.d.ts +112 -0
  32. package/dist/embeddings/manager.d.ts.map +1 -0
  33. package/dist/embeddings/manager.js +215 -0
  34. package/dist/embeddings/manager.js.map +1 -0
  35. package/dist/embeddings/provider.d.ts +101 -0
  36. package/dist/embeddings/provider.d.ts.map +1 -0
  37. package/dist/embeddings/provider.js +232 -0
  38. package/dist/embeddings/provider.js.map +1 -0
  39. package/dist/embeddings/vector-store.d.ts +101 -0
  40. package/dist/embeddings/vector-store.d.ts.map +1 -0
  41. package/dist/embeddings/vector-store.js +256 -0
  42. package/dist/embeddings/vector-store.js.map +1 -0
  43. package/dist/factory.d.ts +193 -0
  44. package/dist/factory.d.ts.map +1 -0
  45. package/dist/factory.js +109 -0
  46. package/dist/factory.js.map +1 -0
  47. package/dist/index.d.ts +30 -453
  48. package/dist/index.d.ts.map +1 -0
  49. package/dist/index.js +84 -509
  50. package/dist/index.js.map +1 -0
  51. package/dist/learning/analyzer.d.ts +110 -0
  52. package/dist/learning/analyzer.d.ts.map +1 -0
  53. package/dist/learning/analyzer.js +213 -0
  54. package/dist/learning/analyzer.js.map +1 -0
  55. package/dist/learning/effectiveness.d.ts +158 -0
  56. package/dist/learning/effectiveness.d.ts.map +1 -0
  57. package/dist/learning/effectiveness.js +251 -0
  58. package/dist/learning/effectiveness.js.map +1 -0
  59. package/dist/learning/index.d.ts +8 -0
  60. package/dist/learning/index.d.ts.map +1 -0
  61. package/dist/learning/index.js +11 -0
  62. package/dist/learning/index.js.map +1 -0
  63. package/dist/learning/llm-extractor.d.ts +88 -0
  64. package/dist/learning/llm-extractor.d.ts.map +1 -0
  65. package/dist/learning/llm-extractor.js +372 -0
  66. package/dist/learning/llm-extractor.js.map +1 -0
  67. package/dist/learning/meta-learner.d.ts +80 -0
  68. package/dist/learning/meta-learner.d.ts.map +1 -0
  69. package/dist/learning/meta-learner.js +355 -0
  70. package/dist/learning/meta-learner.js.map +1 -0
  71. package/dist/learning/pipeline.d.ts +65 -0
  72. package/dist/learning/pipeline.d.ts.map +1 -0
  73. package/dist/learning/pipeline.js +170 -0
  74. package/dist/learning/pipeline.js.map +1 -0
  75. package/dist/learning/playbook-extractor.d.ts +113 -0
  76. package/dist/learning/playbook-extractor.d.ts.map +1 -0
  77. package/dist/learning/playbook-extractor.js +523 -0
  78. package/dist/learning/playbook-extractor.js.map +1 -0
  79. package/dist/learning/usage-inference.d.ts +82 -0
  80. package/dist/learning/usage-inference.d.ts.map +1 -0
  81. package/dist/learning/usage-inference.js +261 -0
  82. package/dist/learning/usage-inference.js.map +1 -0
  83. package/dist/mcp/index.d.ts +6 -0
  84. package/dist/mcp/index.d.ts.map +1 -0
  85. package/dist/mcp/index.js +6 -0
  86. package/dist/mcp/index.js.map +1 -0
  87. package/dist/mcp/playbook-server.d.ts +120 -0
  88. package/dist/mcp/playbook-server.d.ts.map +1 -0
  89. package/dist/mcp/playbook-server.js +427 -0
  90. package/dist/mcp/playbook-server.js.map +1 -0
  91. package/dist/memory/curated-loader.d.ts +62 -0
  92. package/dist/memory/curated-loader.d.ts.map +1 -0
  93. package/dist/memory/curated-loader.js +106 -0
  94. package/dist/memory/curated-loader.js.map +1 -0
  95. package/dist/memory/experience.d.ts +122 -0
  96. package/dist/memory/experience.d.ts.map +1 -0
  97. package/dist/memory/experience.js +392 -0
  98. package/dist/memory/experience.js.map +1 -0
  99. package/dist/memory/index.d.ts +6 -0
  100. package/dist/memory/index.d.ts.map +1 -0
  101. package/dist/memory/index.js +9 -0
  102. package/dist/memory/index.js.map +1 -0
  103. package/dist/memory/meta.d.ts +90 -0
  104. package/dist/memory/meta.d.ts.map +1 -0
  105. package/dist/memory/meta.js +362 -0
  106. package/dist/memory/meta.js.map +1 -0
  107. package/dist/memory/playbook.d.ts +133 -0
  108. package/dist/memory/playbook.d.ts.map +1 -0
  109. package/dist/memory/playbook.js +357 -0
  110. package/dist/memory/playbook.js.map +1 -0
  111. package/dist/memory/system.d.ts +167 -0
  112. package/dist/memory/system.d.ts.map +1 -0
  113. package/dist/memory/system.js +383 -0
  114. package/dist/memory/system.js.map +1 -0
  115. package/dist/runtime/backends/acp.d.ts +67 -0
  116. package/dist/runtime/backends/acp.d.ts.map +1 -0
  117. package/dist/runtime/backends/acp.js +290 -0
  118. package/dist/runtime/backends/acp.js.map +1 -0
  119. package/dist/runtime/backends/index.d.ts +5 -0
  120. package/dist/runtime/backends/index.d.ts.map +1 -0
  121. package/dist/runtime/backends/index.js +6 -0
  122. package/dist/runtime/backends/index.js.map +1 -0
  123. package/dist/runtime/backends/mock.d.ts +67 -0
  124. package/dist/runtime/backends/mock.d.ts.map +1 -0
  125. package/dist/runtime/backends/mock.js +153 -0
  126. package/dist/runtime/backends/mock.js.map +1 -0
  127. package/dist/runtime/backends/subprocess.d.ts +56 -0
  128. package/dist/runtime/backends/subprocess.d.ts.map +1 -0
  129. package/dist/runtime/backends/subprocess.js +260 -0
  130. package/dist/runtime/backends/subprocess.js.map +1 -0
  131. package/dist/runtime/flows/learning.d.ts +73 -0
  132. package/dist/runtime/flows/learning.d.ts.map +1 -0
  133. package/dist/runtime/flows/learning.js +116 -0
  134. package/dist/runtime/flows/learning.js.map +1 -0
  135. package/dist/runtime/flows/validation.d.ts +122 -0
  136. package/dist/runtime/flows/validation.d.ts.map +1 -0
  137. package/dist/runtime/flows/validation.js +223 -0
  138. package/dist/runtime/flows/validation.js.map +1 -0
  139. package/dist/runtime/index.d.ts +6 -0
  140. package/dist/runtime/index.d.ts.map +1 -0
  141. package/dist/runtime/index.js +8 -0
  142. package/dist/runtime/index.js.map +1 -0
  143. package/dist/runtime/manager.d.ts +116 -0
  144. package/dist/runtime/manager.d.ts.map +1 -0
  145. package/dist/runtime/manager.js +416 -0
  146. package/dist/runtime/manager.js.map +1 -0
  147. package/dist/runtime/types.d.ts +138 -0
  148. package/dist/runtime/types.d.ts.map +1 -0
  149. package/dist/runtime/types.js +2 -0
  150. package/dist/runtime/types.js.map +1 -0
  151. package/dist/search/evaluator.d.ts +102 -0
  152. package/dist/search/evaluator.d.ts.map +1 -0
  153. package/dist/search/evaluator.js +352 -0
  154. package/dist/search/evaluator.js.map +1 -0
  155. package/dist/search/index.d.ts +7 -0
  156. package/dist/search/index.d.ts.map +1 -0
  157. package/dist/search/index.js +11 -0
  158. package/dist/search/index.js.map +1 -0
  159. package/dist/search/refinement-loop.d.ts +73 -0
  160. package/dist/search/refinement-loop.d.ts.map +1 -0
  161. package/dist/search/refinement-loop.js +245 -0
  162. package/dist/search/refinement-loop.js.map +1 -0
  163. package/dist/search/refinement-types.d.ts +154 -0
  164. package/dist/search/refinement-types.d.ts.map +1 -0
  165. package/dist/search/refinement-types.js +99 -0
  166. package/dist/search/refinement-types.js.map +1 -0
  167. package/dist/search/router.d.ts +61 -0
  168. package/dist/search/router.d.ts.map +1 -0
  169. package/dist/search/router.js +197 -0
  170. package/dist/search/router.js.map +1 -0
  171. package/dist/search/solver.d.ts +75 -0
  172. package/dist/search/solver.d.ts.map +1 -0
  173. package/dist/search/solver.js +216 -0
  174. package/dist/search/solver.js.map +1 -0
  175. package/dist/search/verification-runner.d.ts +125 -0
  176. package/dist/search/verification-runner.d.ts.map +1 -0
  177. package/dist/search/verification-runner.js +440 -0
  178. package/dist/search/verification-runner.js.map +1 -0
  179. package/dist/surfacing/index.d.ts +2 -0
  180. package/dist/surfacing/index.d.ts.map +1 -0
  181. package/dist/surfacing/index.js +2 -0
  182. package/dist/surfacing/index.js.map +1 -0
  183. package/dist/surfacing/skill-library.d.ts +158 -0
  184. package/dist/surfacing/skill-library.d.ts.map +1 -0
  185. package/dist/surfacing/skill-library.js +429 -0
  186. package/dist/surfacing/skill-library.js.map +1 -0
  187. package/dist/types/config.d.ts +1113 -0
  188. package/dist/types/config.d.ts.map +1 -0
  189. package/dist/types/config.js +274 -0
  190. package/dist/types/config.js.map +1 -0
  191. package/dist/types/index.d.ts +9 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +14 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/memory.d.ts +339 -0
  196. package/dist/types/memory.d.ts.map +1 -0
  197. package/dist/types/memory.js +207 -0
  198. package/dist/types/memory.js.map +1 -0
  199. package/dist/types/meta.d.ts +146 -0
  200. package/dist/types/meta.d.ts.map +1 -0
  201. package/dist/types/meta.js +51 -0
  202. package/dist/types/meta.js.map +1 -0
  203. package/dist/types/outcome.d.ts +42 -0
  204. package/dist/types/outcome.d.ts.map +1 -0
  205. package/dist/types/outcome.js +50 -0
  206. package/dist/types/outcome.js.map +1 -0
  207. package/dist/types/playbook.d.ts +119 -0
  208. package/dist/types/playbook.d.ts.map +1 -0
  209. package/dist/types/playbook.js +71 -0
  210. package/dist/types/playbook.js.map +1 -0
  211. package/dist/types/step.d.ts +44 -0
  212. package/dist/types/step.d.ts.map +1 -0
  213. package/dist/types/step.js +32 -0
  214. package/dist/types/step.js.map +1 -0
  215. package/dist/types/task.d.ts +91 -0
  216. package/dist/types/task.d.ts.map +1 -0
  217. package/dist/types/task.js +39 -0
  218. package/dist/types/task.js.map +1 -0
  219. package/dist/types/trajectory.d.ts +221 -0
  220. package/dist/types/trajectory.d.ts.map +1 -0
  221. package/dist/types/trajectory.js +60 -0
  222. package/dist/types/trajectory.js.map +1 -0
  223. package/dist/utils/index.d.ts +4 -0
  224. package/dist/utils/index.d.ts.map +1 -0
  225. package/dist/utils/index.js +4 -0
  226. package/dist/utils/index.js.map +1 -0
  227. package/dist/utils/similarity.d.ts +31 -0
  228. package/dist/utils/similarity.d.ts.map +1 -0
  229. package/dist/utils/similarity.js +107 -0
  230. package/dist/utils/similarity.js.map +1 -0
  231. package/dist/utils/storage.d.ts +106 -0
  232. package/dist/utils/storage.d.ts.map +1 -0
  233. package/dist/utils/storage.js +203 -0
  234. package/dist/utils/storage.js.map +1 -0
  235. package/dist/utils/validation.d.ts +129 -0
  236. package/dist/utils/validation.d.ts.map +1 -0
  237. package/dist/utils/validation.js +171 -0
  238. package/dist/utils/validation.js.map +1 -0
  239. package/package.json +50 -34
  240. package/scripts/migrate-to-playbooks.ts +307 -0
  241. package/src/agents/index.ts +14 -0
  242. package/src/agents/mock-provider.ts +93 -0
  243. package/src/agents/types.ts +137 -0
  244. package/src/atlas.ts +560 -0
  245. package/src/bin/cognitive-core.ts +470 -0
  246. package/src/embeddings/bm25.ts +337 -0
  247. package/src/embeddings/index.ts +39 -0
  248. package/src/embeddings/manager.ts +288 -0
  249. package/src/embeddings/provider.ts +311 -0
  250. package/src/embeddings/vector-store.ts +353 -0
  251. package/src/factory.ts +263 -0
  252. package/src/index.ts +246 -0
  253. package/src/learning/analyzer.ts +335 -0
  254. package/src/learning/effectiveness.ts +428 -0
  255. package/src/learning/index.ts +58 -0
  256. package/src/learning/llm-extractor.ts +542 -0
  257. package/src/learning/meta-learner.ts +516 -0
  258. package/src/learning/pipeline.ts +244 -0
  259. package/src/learning/playbook-extractor.ts +702 -0
  260. package/src/learning/usage-inference.ts +372 -0
  261. package/src/mcp/index.ts +12 -0
  262. package/src/mcp/playbook-server.ts +565 -0
  263. package/src/memory/curated-loader.ts +160 -0
  264. package/src/memory/experience.ts +515 -0
  265. package/src/memory/index.ts +27 -0
  266. package/src/memory/meta.ts +506 -0
  267. package/src/memory/playbook.ts +493 -0
  268. package/src/memory/system.ts +551 -0
  269. package/src/runtime/backends/acp.ts +378 -0
  270. package/src/runtime/backends/index.ts +24 -0
  271. package/src/runtime/backends/mock.ts +218 -0
  272. package/src/runtime/backends/subprocess.ts +356 -0
  273. package/src/runtime/flows/learning.ts +183 -0
  274. package/src/runtime/flows/validation.ts +381 -0
  275. package/src/runtime/index.ts +53 -0
  276. package/src/runtime/manager.ts +541 -0
  277. package/src/runtime/types.ts +157 -0
  278. package/src/search/evaluator.ts +474 -0
  279. package/src/search/index.ts +59 -0
  280. package/src/search/refinement-loop.ts +363 -0
  281. package/src/search/refinement-types.ts +159 -0
  282. package/src/search/router.ts +261 -0
  283. package/src/search/solver.ts +303 -0
  284. package/src/search/verification-runner.ts +570 -0
  285. package/src/surfacing/index.ts +6 -0
  286. package/src/surfacing/skill-library.ts +594 -0
  287. package/src/types/config.ts +333 -0
  288. package/src/types/index.ts +130 -0
  289. package/src/types/memory.ts +270 -0
  290. package/src/types/meta.ts +218 -0
  291. package/src/types/outcome.ts +66 -0
  292. package/src/types/playbook.ts +196 -0
  293. package/src/types/step.ts +40 -0
  294. package/src/types/task.ts +52 -0
  295. package/src/types/trajectory.ts +80 -0
  296. package/src/utils/index.ts +38 -0
  297. package/src/utils/similarity.ts +139 -0
  298. package/src/utils/storage.ts +249 -0
  299. package/src/utils/validation.ts +286 -0
  300. package/tests/embeddings/bm25.test.ts +130 -0
  301. package/tests/embeddings/manager.test.ts +205 -0
  302. package/tests/integration/atlas.test.ts +266 -0
  303. package/tests/integration/e2e.test.ts +929 -0
  304. package/tests/learning/analyzer.test.ts +426 -0
  305. package/tests/learning/effectiveness.test.ts +542 -0
  306. package/tests/learning/pipeline.test.ts +176 -0
  307. package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
  308. package/tests/learning/usage-inference.test.ts +254 -0
  309. package/tests/mcp/playbook-server.test.ts +252 -0
  310. package/tests/memory/experience.test.ts +198 -0
  311. package/tests/memory/playbook.test.ts +338 -0
  312. package/tests/memory/provenance.test.ts +639 -0
  313. package/tests/memory/system.test.ts +325 -0
  314. package/tests/runtime/agent-manager.test.ts +512 -0
  315. package/tests/runtime/mock-backend.test.ts +248 -0
  316. package/tests/search/refinement-loop.test.ts +468 -0
  317. package/tests/search/refinement.test.ts +267 -0
  318. package/tests/search/router.test.ts +427 -0
  319. package/tests/surfacing/skill-library.test.ts +292 -0
  320. package/tests/types/outcome.test.ts +147 -0
  321. package/tests/types/step.test.ts +133 -0
  322. package/tests/types/task.test.ts +158 -0
  323. package/tests/types/trajectory.test.ts +253 -0
  324. package/tests/utils/similarity.test.ts +188 -0
  325. package/tests/utils/validation.test.ts +252 -0
  326. package/tsconfig.json +25 -0
  327. package/vitest.config.ts +22 -0
  328. package/dist/index.d.mts +0 -466
  329. package/dist/index.mjs +0 -478
@@ -0,0 +1,594 @@
1
+ /**
2
+ * Skill Library
3
+ * Tiered surfacing of playbooks for agent consumption
4
+ *
5
+ * Tiers:
6
+ * 1. Core Skills - Always in system prompt (highest confidence)
7
+ * 2. Domain Skills - Loaded when domain matches
8
+ * 3. Contextual - Injected based on task query
9
+ * 4. On-Demand - Available via MCP tool
10
+ */
11
+
12
+ import type {
13
+ Task,
14
+ Playbook,
15
+ SkillLibraryConfig,
16
+ } from '../types/index.js';
17
+ import type { PlaybookLibrary } from '../memory/playbook.js';
18
+ import { getPlaybookSuccessRate } from '../types/playbook.js';
19
+
20
+ /**
21
+ * Skills organized for agent context
22
+ */
23
+ export interface AgentSkills {
24
+ /** Core skills - always included */
25
+ core: Playbook[];
26
+ /** Domain-specific skills */
27
+ domain: Playbook[];
28
+ /** Task-specific contextual playbooks */
29
+ contextual: Playbook[];
30
+ /** Estimated token count */
31
+ totalTokenEstimate: number;
32
+ }
33
+
34
+ /**
35
+ * Result of refreshing skill tiers
36
+ */
37
+ export interface TierRefreshResult {
38
+ /** Playbook IDs promoted to core */
39
+ promoted: string[];
40
+ /** Playbook IDs demoted from core */
41
+ demoted: string[];
42
+ /** Current core skill count */
43
+ coreCount: number;
44
+ /** Domain skill counts */
45
+ domainCounts: Record<string, number>;
46
+ }
47
+
48
+ /**
49
+ * Default configuration
50
+ */
51
+ const DEFAULT_CONFIG: SkillLibraryConfig = {
52
+ promotion: {
53
+ minConfidence: 0.85,
54
+ minSuccessCount: 5,
55
+ minSuccessRate: 0.8,
56
+ },
57
+ limits: {
58
+ maxCoreSkills: 10,
59
+ maxDomainSkills: 5,
60
+ maxContextualPlaybooks: 3,
61
+ },
62
+ context: {
63
+ maxTokensForSkills: 2000,
64
+ includeRefinements: true,
65
+ includeExamples: false,
66
+ cacheRefreshInterval: 5 * 60 * 1000, // 5 minutes
67
+ },
68
+ demotion: {
69
+ failureThreshold: 3,
70
+ minConfidenceToRetain: 0.6,
71
+ },
72
+ };
73
+
74
+ /**
75
+ * Skill Library
76
+ * Manages tiered access to playbooks for agent consumption
77
+ */
78
+ export class SkillLibrary {
79
+ private playbooks: PlaybookLibrary;
80
+ private config: SkillLibraryConfig;
81
+
82
+ // Cached promoted skills (refreshed periodically)
83
+ private coreSkills: Playbook[] = [];
84
+ private domainSkills: Map<string, Playbook[]> = new Map();
85
+ private lastRefresh: Date | null = null;
86
+ private consecutiveFailures: Map<string, number> = new Map();
87
+
88
+ constructor(
89
+ playbooks: PlaybookLibrary,
90
+ config?: Partial<SkillLibraryConfig>
91
+ ) {
92
+ this.playbooks = playbooks;
93
+ this.config = this.mergeConfig(DEFAULT_CONFIG, config);
94
+ }
95
+
96
+ /**
97
+ * Merge configuration with defaults
98
+ */
99
+ private mergeConfig(
100
+ defaults: SkillLibraryConfig,
101
+ overrides?: Partial<SkillLibraryConfig>
102
+ ): SkillLibraryConfig {
103
+ if (!overrides) return defaults;
104
+
105
+ return {
106
+ promotion: { ...defaults.promotion, ...overrides.promotion },
107
+ limits: { ...defaults.limits, ...overrides.limits },
108
+ context: { ...defaults.context, ...overrides.context },
109
+ demotion: { ...defaults.demotion, ...overrides.demotion },
110
+ };
111
+ }
112
+
113
+ // === TIER MANAGEMENT ===
114
+
115
+ /**
116
+ * Refresh skill tiers based on current playbook state
117
+ * Called periodically or after significant learning
118
+ */
119
+ async refreshTiers(): Promise<TierRefreshResult> {
120
+ const allPlaybooks = await this.playbooks.getAll();
121
+ const previousCoreIds = new Set(this.coreSkills.map((p) => p.id));
122
+
123
+ // Find playbooks that meet promotion criteria
124
+ const promotionCandidates = allPlaybooks
125
+ .filter((p) => this.meetsPromotionCriteria(p))
126
+ .sort((a, b) => {
127
+ // Sort by confidence * success rate
128
+ const scoreA = a.confidence * getPlaybookSuccessRate(a);
129
+ const scoreB = b.confidence * getPlaybookSuccessRate(b);
130
+ return scoreB - scoreA;
131
+ });
132
+
133
+ // Check for demotions
134
+ const demotions: string[] = [];
135
+ for (const playbook of this.coreSkills) {
136
+ if (this.meetsDemotionCriteria(playbook)) {
137
+ demotions.push(playbook.id);
138
+ }
139
+ }
140
+
141
+ // Update core skills (respecting max limit)
142
+ this.coreSkills = promotionCandidates
143
+ .filter((p) => !demotions.includes(p.id))
144
+ .slice(0, this.config.limits.maxCoreSkills);
145
+
146
+ const newCoreIds = new Set(this.coreSkills.map((p) => p.id));
147
+
148
+ // Calculate promotions and demotions
149
+ const promoted = [...newCoreIds].filter((id) => !previousCoreIds.has(id));
150
+ const demoted = [...previousCoreIds].filter((id) => !newCoreIds.has(id));
151
+
152
+ // Update domain skills
153
+ this.domainSkills.clear();
154
+ for (const playbook of allPlaybooks) {
155
+ if (newCoreIds.has(playbook.id)) continue; // Skip core skills
156
+
157
+ for (const domain of playbook.applicability.domains) {
158
+ const domainList = this.domainSkills.get(domain) ?? [];
159
+
160
+ if (domainList.length < this.config.limits.maxDomainSkills) {
161
+ domainList.push(playbook);
162
+ this.domainSkills.set(domain, domainList);
163
+ }
164
+ }
165
+ }
166
+
167
+ // Sort domain skills by confidence
168
+ for (const [domain, skills] of this.domainSkills) {
169
+ this.domainSkills.set(
170
+ domain,
171
+ skills.sort((a, b) => b.confidence - a.confidence)
172
+ );
173
+ }
174
+
175
+ this.lastRefresh = new Date();
176
+
177
+ // Build domain counts
178
+ const domainCounts: Record<string, number> = {};
179
+ for (const [domain, skills] of this.domainSkills) {
180
+ domainCounts[domain] = skills.length;
181
+ }
182
+
183
+ return {
184
+ promoted,
185
+ demoted,
186
+ coreCount: this.coreSkills.length,
187
+ domainCounts,
188
+ };
189
+ }
190
+
191
+ /**
192
+ * Check if a playbook qualifies for core skill status
193
+ */
194
+ private meetsPromotionCriteria(playbook: Playbook): boolean {
195
+ const { minConfidence, minSuccessCount, minSuccessRate } =
196
+ this.config.promotion;
197
+ const { successCount, failureCount } = playbook.evolution;
198
+ const totalUses = successCount + failureCount;
199
+ const actualSuccessRate = totalUses > 0 ? successCount / totalUses : 0;
200
+
201
+ return (
202
+ playbook.confidence >= minConfidence &&
203
+ successCount >= minSuccessCount &&
204
+ actualSuccessRate >= minSuccessRate
205
+ );
206
+ }
207
+
208
+ /**
209
+ * Check if a core skill should be demoted
210
+ */
211
+ private meetsDemotionCriteria(playbook: Playbook): boolean {
212
+ const { failureThreshold, minConfidenceToRetain } = this.config.demotion;
213
+ const recentFailures = this.consecutiveFailures.get(playbook.id) ?? 0;
214
+
215
+ return (
216
+ recentFailures >= failureThreshold ||
217
+ playbook.confidence < minConfidenceToRetain
218
+ );
219
+ }
220
+
221
+ // === RETRIEVAL FOR AGENT CONTEXT ===
222
+
223
+ /**
224
+ * Get skills for agent system prompt
225
+ * Returns tiered skills based on task context
226
+ */
227
+ async getSkillsForAgent(
228
+ task: Task,
229
+ options?: {
230
+ includeCore?: boolean;
231
+ includeDomain?: boolean;
232
+ includeContextual?: boolean;
233
+ }
234
+ ): Promise<AgentSkills> {
235
+ const includeCore = options?.includeCore ?? true;
236
+ const includeDomain = options?.includeDomain ?? true;
237
+ const includeContextual = options?.includeContextual ?? true;
238
+
239
+ // Ensure tiers are fresh (refresh if older than cache interval)
240
+ if (
241
+ !this.lastRefresh ||
242
+ Date.now() - this.lastRefresh.getTime() > this.config.context.cacheRefreshInterval
243
+ ) {
244
+ await this.refreshTiers();
245
+ }
246
+
247
+ const result: AgentSkills = {
248
+ core: [],
249
+ domain: [],
250
+ contextual: [],
251
+ totalTokenEstimate: 0,
252
+ };
253
+
254
+ // Add core skills
255
+ if (includeCore) {
256
+ result.core = [...this.coreSkills];
257
+ result.totalTokenEstimate += this.estimateTokens(result.core);
258
+ }
259
+
260
+ // Add domain skills
261
+ if (includeDomain && task.domain) {
262
+ const domainSkills = this.domainSkills.get(task.domain) ?? [];
263
+ result.domain = domainSkills.filter(
264
+ (p) => !result.core.some((c) => c.id === p.id)
265
+ );
266
+ result.totalTokenEstimate += this.estimateTokens(result.domain);
267
+ }
268
+
269
+ // Add contextual playbooks (from query)
270
+ if (includeContextual) {
271
+ const matches = await this.playbooks.findMatching(task.description, {
272
+ k: this.config.limits.maxContextualPlaybooks,
273
+ domains: task.domain ? [task.domain] : undefined,
274
+ excludeAntiPatterns: true,
275
+ });
276
+
277
+ result.contextual = matches
278
+ .map((m) => m.playbook)
279
+ .filter(
280
+ (p) =>
281
+ !result.core.some((c) => c.id === p.id) &&
282
+ !result.domain.some((d) => d.id === p.id)
283
+ );
284
+ result.totalTokenEstimate += this.estimateTokens(result.contextual);
285
+ }
286
+
287
+ // Trim if over token budget
288
+ while (
289
+ result.totalTokenEstimate > this.config.context.maxTokensForSkills &&
290
+ result.contextual.length > 0
291
+ ) {
292
+ result.contextual.pop();
293
+ result.totalTokenEstimate = this.estimateTokens([
294
+ ...result.core,
295
+ ...result.domain,
296
+ ...result.contextual,
297
+ ]);
298
+ }
299
+
300
+ return result;
301
+ }
302
+
303
+ /**
304
+ * Estimate token count for playbooks
305
+ */
306
+ private estimateTokens(playbooks: Playbook[]): number {
307
+ let tokens = 0;
308
+
309
+ for (const playbook of playbooks) {
310
+ // Rough estimate: 4 characters per token
311
+ tokens += playbook.name.length / 4;
312
+ tokens += playbook.guidance.strategy.length / 4;
313
+ tokens += playbook.guidance.tactics.join(' ').length / 4;
314
+
315
+ if (this.config.context.includeRefinements) {
316
+ tokens +=
317
+ playbook.evolution.refinements
318
+ .map((r) => `${r.context}: ${r.addition}`)
319
+ .join(' ').length / 4;
320
+ }
321
+
322
+ if (playbook.guidance.steps) {
323
+ tokens += playbook.guidance.steps.join(' ').length / 4;
324
+ }
325
+ }
326
+
327
+ return Math.ceil(tokens);
328
+ }
329
+
330
+ /**
331
+ * Format skills for system prompt injection
332
+ */
333
+ formatForSystemPrompt(skills: AgentSkills): string {
334
+ const sections: string[] = [];
335
+
336
+ // Format core skills
337
+ if (skills.core.length > 0) {
338
+ sections.push('## Core Skills\n');
339
+ sections.push('These are proven approaches you should follow:\n');
340
+ for (const playbook of skills.core) {
341
+ sections.push(this.formatPlaybookForPrompt(playbook, 'core'));
342
+ }
343
+ }
344
+
345
+ // Format domain skills
346
+ if (skills.domain.length > 0) {
347
+ sections.push('## Domain Skills\n');
348
+ for (const playbook of skills.domain) {
349
+ sections.push(this.formatPlaybookForPrompt(playbook, 'domain'));
350
+ }
351
+ }
352
+
353
+ // Format contextual playbooks
354
+ if (skills.contextual.length > 0) {
355
+ sections.push('## Relevant Playbooks\n');
356
+ for (const playbook of skills.contextual) {
357
+ sections.push(this.formatPlaybookForPrompt(playbook, 'contextual'));
358
+ }
359
+ }
360
+
361
+ return sections.join('\n');
362
+ }
363
+
364
+ /**
365
+ * Format a single playbook for prompt
366
+ */
367
+ private formatPlaybookForPrompt(
368
+ playbook: Playbook,
369
+ _tier: 'core' | 'domain' | 'contextual'
370
+ ): string {
371
+ const lines: string[] = [];
372
+ const confidencePercent = Math.round(playbook.confidence * 100);
373
+
374
+ lines.push(`### ${playbook.name} (${confidencePercent}% confidence)`);
375
+ lines.push(`**When**: ${playbook.applicability.situations[0] ?? 'General use'}`);
376
+ lines.push(`**Strategy**: ${playbook.guidance.strategy}`);
377
+
378
+ if (playbook.guidance.tactics.length > 0) {
379
+ lines.push('**Tactics**:');
380
+ for (const tactic of playbook.guidance.tactics.slice(0, 5)) {
381
+ lines.push(` - ${tactic}`);
382
+ }
383
+ }
384
+
385
+ if (
386
+ this.config.context.includeRefinements &&
387
+ playbook.evolution.refinements.length > 0
388
+ ) {
389
+ lines.push('**Notes**:');
390
+ for (const ref of playbook.evolution.refinements.slice(0, 2)) {
391
+ lines.push(` - In ${ref.context}: ${ref.addition}`);
392
+ }
393
+ }
394
+
395
+ lines.push('');
396
+ return lines.join('\n');
397
+ }
398
+
399
+ // === LIFECYCLE INTEGRATION ===
400
+
401
+ /**
402
+ * Record playbook usage outcome (inferred from trajectory)
403
+ * Called by learning pipeline after trajectory analysis
404
+ */
405
+ async recordOutcome(
406
+ playbookId: string,
407
+ trajectoryId: string,
408
+ success: boolean,
409
+ context?: string
410
+ ): Promise<void> {
411
+ if (success) {
412
+ // Reset consecutive failures
413
+ this.consecutiveFailures.set(playbookId, 0);
414
+ await this.playbooks.recordSuccess(playbookId, trajectoryId);
415
+ } else {
416
+ // Increment consecutive failures
417
+ const currentFailures = this.consecutiveFailures.get(playbookId) ?? 0;
418
+ this.consecutiveFailures.set(playbookId, currentFailures + 1);
419
+ await this.playbooks.recordFailure(
420
+ playbookId,
421
+ trajectoryId,
422
+ context ?? 'Unknown',
423
+ 'Task failed'
424
+ );
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Get promotion candidates
430
+ */
431
+ async getPromotionCandidates(): Promise<Playbook[]> {
432
+ const allPlaybooks = await this.playbooks.getAll();
433
+ const coreIds = new Set(this.coreSkills.map((p) => p.id));
434
+
435
+ return allPlaybooks.filter(
436
+ (p) => !coreIds.has(p.id) && this.meetsPromotionCriteria(p)
437
+ );
438
+ }
439
+
440
+ /**
441
+ * Get demotion candidates
442
+ */
443
+ async getDemotionCandidates(): Promise<Playbook[]> {
444
+ return this.coreSkills.filter((p) => this.meetsDemotionCriteria(p));
445
+ }
446
+
447
+ /**
448
+ * Get current core skills
449
+ */
450
+ getCoreSkills(): Playbook[] {
451
+ return [...this.coreSkills];
452
+ }
453
+
454
+ /**
455
+ * Get domain skills
456
+ */
457
+ getDomainSkills(domain: string): Playbook[] {
458
+ return [...(this.domainSkills.get(domain) ?? [])];
459
+ }
460
+
461
+ /**
462
+ * Get all domains with skills
463
+ */
464
+ getDomains(): string[] {
465
+ return Array.from(this.domainSkills.keys());
466
+ }
467
+
468
+ /**
469
+ * Get statistics
470
+ */
471
+ getStats(): {
472
+ coreSkillCount: number;
473
+ domainSkillCounts: Record<string, number>;
474
+ lastRefresh: Date | null;
475
+ consecutiveFailures: Record<string, number>;
476
+ } {
477
+ const domainSkillCounts: Record<string, number> = {};
478
+ for (const [domain, skills] of this.domainSkills) {
479
+ domainSkillCounts[domain] = skills.length;
480
+ }
481
+
482
+ // Convert consecutive failures map to record
483
+ const failureRecord: Record<string, number> = {};
484
+ for (const [id, count] of this.consecutiveFailures) {
485
+ if (count > 0) {
486
+ failureRecord[id] = count;
487
+ }
488
+ }
489
+
490
+ return {
491
+ coreSkillCount: this.coreSkills.length,
492
+ domainSkillCounts,
493
+ lastRefresh: this.lastRefresh,
494
+ consecutiveFailures: failureRecord,
495
+ };
496
+ }
497
+
498
+ /**
499
+ * Get consecutive failure count for a playbook
500
+ */
501
+ getConsecutiveFailures(playbookId: string): number {
502
+ return this.consecutiveFailures.get(playbookId) ?? 0;
503
+ }
504
+
505
+ /**
506
+ * Reset consecutive failures for a playbook
507
+ */
508
+ resetConsecutiveFailures(playbookId: string): void {
509
+ this.consecutiveFailures.delete(playbookId);
510
+ }
511
+
512
+ /**
513
+ * Get all playbooks at risk of demotion
514
+ */
515
+ getAtRiskPlaybooks(): Array<{
516
+ playbook: Playbook;
517
+ consecutiveFailures: number;
518
+ failuresUntilDemotion: number;
519
+ }> {
520
+ const atRisk: Array<{
521
+ playbook: Playbook;
522
+ consecutiveFailures: number;
523
+ failuresUntilDemotion: number;
524
+ }> = [];
525
+
526
+ for (const playbook of this.coreSkills) {
527
+ const failures = this.consecutiveFailures.get(playbook.id) ?? 0;
528
+ const threshold = this.config.demotion.failureThreshold;
529
+
530
+ if (failures > 0) {
531
+ atRisk.push({
532
+ playbook,
533
+ consecutiveFailures: failures,
534
+ failuresUntilDemotion: Math.max(0, threshold - failures),
535
+ });
536
+ }
537
+ }
538
+
539
+ return atRisk.sort(
540
+ (a, b) => a.failuresUntilDemotion - b.failuresUntilDemotion
541
+ );
542
+ }
543
+
544
+ /**
545
+ * Apply time-based decay to consecutive failures
546
+ * Reduces failure counts for playbooks that haven't been used recently
547
+ * @param decayAmount Amount to reduce failure count by (default: 1)
548
+ */
549
+ applyFailureDecay(decayAmount = 1): void {
550
+ for (const [playbookId, count] of this.consecutiveFailures) {
551
+ const newCount = Math.max(0, count - decayAmount);
552
+ if (newCount === 0) {
553
+ this.consecutiveFailures.delete(playbookId);
554
+ } else {
555
+ this.consecutiveFailures.set(playbookId, newCount);
556
+ }
557
+ }
558
+ }
559
+
560
+ /**
561
+ * Export consecutive failure state for persistence
562
+ */
563
+ exportFailureState(): Record<string, number> {
564
+ const state: Record<string, number> = {};
565
+ for (const [id, count] of this.consecutiveFailures) {
566
+ if (count > 0) {
567
+ state[id] = count;
568
+ }
569
+ }
570
+ return state;
571
+ }
572
+
573
+ /**
574
+ * Import consecutive failure state from persistence
575
+ */
576
+ importFailureState(state: Record<string, number>): void {
577
+ this.consecutiveFailures.clear();
578
+ for (const [id, count] of Object.entries(state)) {
579
+ if (count > 0) {
580
+ this.consecutiveFailures.set(id, count);
581
+ }
582
+ }
583
+ }
584
+ }
585
+
586
+ /**
587
+ * Create a skill library
588
+ */
589
+ export function createSkillLibrary(
590
+ playbooks: PlaybookLibrary,
591
+ config?: Partial<SkillLibraryConfig>
592
+ ): SkillLibrary {
593
+ return new SkillLibrary(playbooks, config);
594
+ }