cognitive-core 0.1.2 → 0.2.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 (483) hide show
  1. package/CLAUDE.md +233 -0
  2. package/README.md +370 -54
  3. package/dist/atlas.d.ts +10 -10
  4. package/dist/atlas.d.ts.map +1 -1
  5. package/dist/atlas.js +79 -48
  6. package/dist/atlas.js.map +1 -1
  7. package/dist/bin/cli-utils.d.ts +37 -0
  8. package/dist/bin/cli-utils.d.ts.map +1 -0
  9. package/dist/bin/cli-utils.js +176 -0
  10. package/dist/bin/cli-utils.js.map +1 -0
  11. package/dist/bin/cognitive-core.d.ts +2 -12
  12. package/dist/bin/cognitive-core.d.ts.map +1 -1
  13. package/dist/bin/cognitive-core.js +76 -351
  14. package/dist/bin/cognitive-core.js.map +1 -1
  15. package/dist/bin/commands/kb.d.ts +6 -0
  16. package/dist/bin/commands/kb.d.ts.map +1 -0
  17. package/dist/bin/commands/kb.js +240 -0
  18. package/dist/bin/commands/kb.js.map +1 -0
  19. package/dist/bin/commands/learn.d.ts +6 -0
  20. package/dist/bin/commands/learn.d.ts.map +1 -0
  21. package/dist/bin/commands/learn.js +91 -0
  22. package/dist/bin/commands/learn.js.map +1 -0
  23. package/dist/bin/commands/legacy.d.ts +12 -0
  24. package/dist/bin/commands/legacy.d.ts.map +1 -0
  25. package/dist/bin/commands/legacy.js +142 -0
  26. package/dist/bin/commands/legacy.js.map +1 -0
  27. package/dist/bin/commands/run.d.ts +3 -0
  28. package/dist/bin/commands/run.d.ts.map +1 -0
  29. package/dist/bin/commands/run.js +99 -0
  30. package/dist/bin/commands/run.js.map +1 -0
  31. package/dist/bin/commands/sessions.d.ts +9 -0
  32. package/dist/bin/commands/sessions.d.ts.map +1 -0
  33. package/dist/bin/commands/sessions.js +183 -0
  34. package/dist/bin/commands/sessions.js.map +1 -0
  35. package/dist/bin/commands/skills.d.ts +6 -0
  36. package/dist/bin/commands/skills.d.ts.map +1 -0
  37. package/dist/bin/commands/skills.js +135 -0
  38. package/dist/bin/commands/skills.js.map +1 -0
  39. package/dist/embeddings/index.d.ts +1 -0
  40. package/dist/embeddings/index.d.ts.map +1 -1
  41. package/dist/embeddings/index.js +2 -0
  42. package/dist/embeddings/index.js.map +1 -1
  43. package/dist/embeddings/inverted-index.d.ts +47 -0
  44. package/dist/embeddings/inverted-index.d.ts.map +1 -0
  45. package/dist/embeddings/inverted-index.js +122 -0
  46. package/dist/embeddings/inverted-index.js.map +1 -0
  47. package/dist/embeddings/manager.d.ts +3 -1
  48. package/dist/embeddings/manager.d.ts.map +1 -1
  49. package/dist/embeddings/manager.js +12 -7
  50. package/dist/embeddings/manager.js.map +1 -1
  51. package/dist/embeddings/vector-store.d.ts +7 -3
  52. package/dist/embeddings/vector-store.d.ts.map +1 -1
  53. package/dist/embeddings/vector-store.js +22 -6
  54. package/dist/embeddings/vector-store.js.map +1 -1
  55. package/dist/factory.d.ts +11 -12
  56. package/dist/factory.d.ts.map +1 -1
  57. package/dist/factory.js +20 -7
  58. package/dist/factory.js.map +1 -1
  59. package/dist/index.d.ts +7 -6
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +37 -5
  62. package/dist/index.js.map +1 -1
  63. package/dist/learning/analyzer.d.ts.map +1 -1
  64. package/dist/learning/analyzer.js +17 -35
  65. package/dist/learning/analyzer.js.map +1 -1
  66. package/dist/learning/energy-evaluator.d.ts +128 -0
  67. package/dist/learning/energy-evaluator.d.ts.map +1 -0
  68. package/dist/learning/energy-evaluator.js +175 -0
  69. package/dist/learning/energy-evaluator.js.map +1 -0
  70. package/dist/learning/healing-orchestrator.d.ts +182 -0
  71. package/dist/learning/healing-orchestrator.d.ts.map +1 -0
  72. package/dist/learning/healing-orchestrator.js +250 -0
  73. package/dist/learning/healing-orchestrator.js.map +1 -0
  74. package/dist/learning/index.d.ts +7 -2
  75. package/dist/learning/index.d.ts.map +1 -1
  76. package/dist/learning/index.js +13 -2
  77. package/dist/learning/index.js.map +1 -1
  78. package/dist/learning/instant-loop.d.ts +87 -0
  79. package/dist/learning/instant-loop.d.ts.map +1 -0
  80. package/dist/learning/instant-loop.js +264 -0
  81. package/dist/learning/instant-loop.js.map +1 -0
  82. package/dist/learning/loop-coordinator.d.ts +61 -0
  83. package/dist/learning/loop-coordinator.d.ts.map +1 -0
  84. package/dist/learning/loop-coordinator.js +96 -0
  85. package/dist/learning/loop-coordinator.js.map +1 -0
  86. package/dist/learning/maintenance-scheduler.d.ts +141 -0
  87. package/dist/learning/maintenance-scheduler.d.ts.map +1 -0
  88. package/dist/learning/maintenance-scheduler.js +186 -0
  89. package/dist/learning/maintenance-scheduler.js.map +1 -0
  90. package/dist/learning/meta-learner.d.ts.map +1 -1
  91. package/dist/learning/meta-learner.js +4 -21
  92. package/dist/learning/meta-learner.js.map +1 -1
  93. package/dist/learning/pipeline.d.ts +31 -4
  94. package/dist/learning/pipeline.d.ts.map +1 -1
  95. package/dist/learning/pipeline.js +64 -12
  96. package/dist/learning/pipeline.js.map +1 -1
  97. package/dist/learning/reflexion-generator.d.ts +64 -0
  98. package/dist/learning/reflexion-generator.d.ts.map +1 -0
  99. package/dist/learning/reflexion-generator.js +194 -0
  100. package/dist/learning/reflexion-generator.js.map +1 -0
  101. package/dist/learning/trajectory-sources/entire.d.ts +8 -5
  102. package/dist/learning/trajectory-sources/entire.d.ts.map +1 -1
  103. package/dist/learning/trajectory-sources/entire.js +13 -6
  104. package/dist/learning/trajectory-sources/entire.js.map +1 -1
  105. package/dist/learning/trajectory-sources/index.d.ts +1 -1
  106. package/dist/learning/trajectory-sources/index.d.ts.map +1 -1
  107. package/dist/learning/trajectory-sources/index.js +1 -1
  108. package/dist/learning/trajectory-sources/index.js.map +1 -1
  109. package/dist/learning/trajectory-sources/pipeline.d.ts +4 -4
  110. package/dist/learning/trajectory-sources/pipeline.d.ts.map +1 -1
  111. package/dist/learning/trajectory-sources/pipeline.js +2 -2
  112. package/dist/learning/trajectory-sources/pipeline.js.map +1 -1
  113. package/dist/learning/unified-pipeline.d.ts +281 -0
  114. package/dist/learning/unified-pipeline.d.ts.map +1 -0
  115. package/dist/learning/unified-pipeline.js +637 -0
  116. package/dist/learning/unified-pipeline.js.map +1 -0
  117. package/dist/memory/candidate-retrieval.d.ts +43 -0
  118. package/dist/memory/candidate-retrieval.d.ts.map +1 -0
  119. package/dist/memory/candidate-retrieval.js +41 -0
  120. package/dist/memory/candidate-retrieval.js.map +1 -0
  121. package/dist/memory/causal-store.d.ts +97 -0
  122. package/dist/memory/causal-store.d.ts.map +1 -0
  123. package/dist/memory/causal-store.js +209 -0
  124. package/dist/memory/causal-store.js.map +1 -0
  125. package/dist/memory/coherence.d.ts +71 -0
  126. package/dist/memory/coherence.d.ts.map +1 -0
  127. package/dist/memory/coherence.js +176 -0
  128. package/dist/memory/coherence.js.map +1 -0
  129. package/dist/memory/experience.d.ts +39 -6
  130. package/dist/memory/experience.d.ts.map +1 -1
  131. package/dist/memory/experience.js +193 -49
  132. package/dist/memory/experience.js.map +1 -1
  133. package/dist/memory/index.d.ts +7 -0
  134. package/dist/memory/index.d.ts.map +1 -1
  135. package/dist/memory/index.js +12 -0
  136. package/dist/memory/index.js.map +1 -1
  137. package/dist/memory/knowledge-bank.d.ts +14 -0
  138. package/dist/memory/knowledge-bank.d.ts.map +1 -1
  139. package/dist/memory/knowledge-bank.js +45 -0
  140. package/dist/memory/knowledge-bank.js.map +1 -1
  141. package/dist/memory/meta.d.ts +7 -8
  142. package/dist/memory/meta.d.ts.map +1 -1
  143. package/dist/memory/meta.js +73 -79
  144. package/dist/memory/meta.js.map +1 -1
  145. package/dist/memory/playbook.d.ts +26 -9
  146. package/dist/memory/playbook.d.ts.map +1 -1
  147. package/dist/memory/playbook.js +198 -74
  148. package/dist/memory/playbook.js.map +1 -1
  149. package/dist/memory/reasoning-bank.d.ts +130 -0
  150. package/dist/memory/reasoning-bank.d.ts.map +1 -0
  151. package/dist/memory/reasoning-bank.js +342 -0
  152. package/dist/memory/reasoning-bank.js.map +1 -0
  153. package/dist/memory/reflexion.d.ts +59 -0
  154. package/dist/memory/reflexion.d.ts.map +1 -0
  155. package/dist/memory/reflexion.js +96 -0
  156. package/dist/memory/reflexion.js.map +1 -0
  157. package/dist/memory/system.d.ts +7 -2
  158. package/dist/memory/system.d.ts.map +1 -1
  159. package/dist/memory/system.js +19 -7
  160. package/dist/memory/system.js.map +1 -1
  161. package/dist/memory/temporal-compressor.d.ts +126 -0
  162. package/dist/memory/temporal-compressor.d.ts.map +1 -0
  163. package/dist/memory/temporal-compressor.js +335 -0
  164. package/dist/memory/temporal-compressor.js.map +1 -0
  165. package/dist/persistence/index.d.ts +11 -0
  166. package/dist/persistence/index.d.ts.map +1 -0
  167. package/dist/persistence/index.js +11 -0
  168. package/dist/persistence/index.js.map +1 -0
  169. package/dist/persistence/migrator.d.ts +40 -0
  170. package/dist/persistence/migrator.d.ts.map +1 -0
  171. package/dist/persistence/migrator.js +238 -0
  172. package/dist/persistence/migrator.js.map +1 -0
  173. package/dist/persistence/serializers.d.ts +45 -0
  174. package/dist/persistence/serializers.d.ts.map +1 -0
  175. package/dist/persistence/serializers.js +80 -0
  176. package/dist/persistence/serializers.js.map +1 -0
  177. package/dist/persistence/sqlite-persistence.d.ts +228 -0
  178. package/dist/persistence/sqlite-persistence.d.ts.map +1 -0
  179. package/dist/persistence/sqlite-persistence.js +588 -0
  180. package/dist/persistence/sqlite-persistence.js.map +1 -0
  181. package/dist/runtime/flows/learning.d.ts +10 -12
  182. package/dist/runtime/flows/learning.d.ts.map +1 -1
  183. package/dist/runtime/flows/learning.js +10 -23
  184. package/dist/runtime/flows/learning.js.map +1 -1
  185. package/dist/search/index.d.ts +1 -0
  186. package/dist/search/index.d.ts.map +1 -1
  187. package/dist/search/index.js +2 -0
  188. package/dist/search/index.js.map +1 -1
  189. package/dist/search/moe-gate.d.ts +124 -0
  190. package/dist/search/moe-gate.d.ts.map +1 -0
  191. package/dist/search/moe-gate.js +234 -0
  192. package/dist/search/moe-gate.js.map +1 -0
  193. package/dist/search/router.d.ts +32 -2
  194. package/dist/search/router.d.ts.map +1 -1
  195. package/dist/search/router.js +87 -4
  196. package/dist/search/router.js.map +1 -1
  197. package/dist/session-bank/git-reader.d.ts +9 -4
  198. package/dist/session-bank/git-reader.d.ts.map +1 -1
  199. package/dist/session-bank/git-reader.js +22 -15
  200. package/dist/session-bank/git-reader.js.map +1 -1
  201. package/dist/session-bank/index.d.ts +2 -2
  202. package/dist/session-bank/index.d.ts.map +1 -1
  203. package/dist/session-bank/index.js +2 -2
  204. package/dist/session-bank/index.js.map +1 -1
  205. package/dist/session-bank/parser.d.ts +16 -5
  206. package/dist/session-bank/parser.d.ts.map +1 -1
  207. package/dist/session-bank/parser.js +187 -80
  208. package/dist/session-bank/parser.js.map +1 -1
  209. package/dist/session-bank/session-bank.d.ts +5 -0
  210. package/dist/session-bank/session-bank.d.ts.map +1 -1
  211. package/dist/session-bank/session-bank.js +30 -9
  212. package/dist/session-bank/session-bank.js.map +1 -1
  213. package/dist/session-bank/types.d.ts +4 -1
  214. package/dist/session-bank/types.d.ts.map +1 -1
  215. package/dist/session-bank/types.js +3 -3
  216. package/dist/session-bank/types.js.map +1 -1
  217. package/dist/surfacing/skill-publisher.d.ts.map +1 -1
  218. package/dist/surfacing/skill-publisher.js +15 -43
  219. package/dist/surfacing/skill-publisher.js.map +1 -1
  220. package/dist/surfacing/sqlite-storage-adapter.d.ts.map +1 -1
  221. package/dist/surfacing/sqlite-storage-adapter.js +13 -21
  222. package/dist/surfacing/sqlite-storage-adapter.js.map +1 -1
  223. package/dist/types/config.d.ts +100 -0
  224. package/dist/types/config.d.ts.map +1 -1
  225. package/dist/types/config.js +27 -0
  226. package/dist/types/config.js.map +1 -1
  227. package/dist/types/index.d.ts +2 -2
  228. package/dist/types/index.d.ts.map +1 -1
  229. package/dist/types/index.js +1 -1
  230. package/dist/types/index.js.map +1 -1
  231. package/dist/types/memory.d.ts +52 -0
  232. package/dist/types/memory.d.ts.map +1 -1
  233. package/dist/types/memory.js +13 -0
  234. package/dist/types/memory.js.map +1 -1
  235. package/dist/types/playbook.d.ts +4 -0
  236. package/dist/types/playbook.d.ts.map +1 -1
  237. package/dist/types/playbook.js.map +1 -1
  238. package/dist/utils/error-classifier.d.ts +30 -0
  239. package/dist/utils/error-classifier.d.ts.map +1 -0
  240. package/dist/utils/error-classifier.js +85 -0
  241. package/dist/utils/error-classifier.js.map +1 -0
  242. package/dist/utils/index.d.ts +3 -0
  243. package/dist/utils/index.d.ts.map +1 -1
  244. package/dist/utils/index.js +3 -0
  245. package/dist/utils/index.js.map +1 -1
  246. package/dist/utils/partitioned-store.d.ts +93 -0
  247. package/dist/utils/partitioned-store.d.ts.map +1 -0
  248. package/dist/utils/partitioned-store.js +251 -0
  249. package/dist/utils/partitioned-store.js.map +1 -0
  250. package/dist/utils/trajectory-helpers.d.ts +39 -0
  251. package/dist/utils/trajectory-helpers.d.ts.map +1 -0
  252. package/dist/utils/trajectory-helpers.js +57 -0
  253. package/dist/utils/trajectory-helpers.js.map +1 -0
  254. package/dist/workspace/runner.d.ts +3 -4
  255. package/dist/workspace/runner.d.ts.map +1 -1
  256. package/dist/workspace/runner.js.map +1 -1
  257. package/dist/workspace/types.d.ts +9 -2
  258. package/dist/workspace/types.d.ts.map +1 -1
  259. package/dist/workspace/types.js.map +1 -1
  260. package/package.json +6 -4
  261. package/references/sessionlog/.husky/pre-commit +1 -0
  262. package/references/sessionlog/.lintstagedrc.json +4 -0
  263. package/references/sessionlog/.prettierignore +4 -0
  264. package/references/sessionlog/.prettierrc.json +11 -0
  265. package/references/sessionlog/LICENSE +21 -0
  266. package/references/sessionlog/README.md +453 -0
  267. package/references/sessionlog/eslint.config.js +58 -0
  268. package/references/sessionlog/package-lock.json +3672 -0
  269. package/references/sessionlog/package.json +65 -0
  270. package/references/sessionlog/src/__tests__/agent-hooks.test.ts +570 -0
  271. package/references/sessionlog/src/__tests__/agent-registry.test.ts +127 -0
  272. package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +225 -0
  273. package/references/sessionlog/src/__tests__/claude-generator.test.ts +46 -0
  274. package/references/sessionlog/src/__tests__/commit-msg.test.ts +86 -0
  275. package/references/sessionlog/src/__tests__/cursor-agent.test.ts +224 -0
  276. package/references/sessionlog/src/__tests__/e2e-live.test.ts +890 -0
  277. package/references/sessionlog/src/__tests__/event-log.test.ts +183 -0
  278. package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +105 -0
  279. package/references/sessionlog/src/__tests__/gemini-agent.test.ts +375 -0
  280. package/references/sessionlog/src/__tests__/git-hooks.test.ts +78 -0
  281. package/references/sessionlog/src/__tests__/hook-managers.test.ts +121 -0
  282. package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +759 -0
  283. package/references/sessionlog/src/__tests__/opencode-agent.test.ts +338 -0
  284. package/references/sessionlog/src/__tests__/redaction.test.ts +136 -0
  285. package/references/sessionlog/src/__tests__/session-repo.test.ts +353 -0
  286. package/references/sessionlog/src/__tests__/session-store.test.ts +166 -0
  287. package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +466 -0
  288. package/references/sessionlog/src/__tests__/skill-live.test.ts +461 -0
  289. package/references/sessionlog/src/__tests__/summarize.test.ts +348 -0
  290. package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +610 -0
  291. package/references/sessionlog/src/__tests__/task-plan-live.test.ts +632 -0
  292. package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +121 -0
  293. package/references/sessionlog/src/__tests__/types.test.ts +166 -0
  294. package/references/sessionlog/src/__tests__/utils.test.ts +333 -0
  295. package/references/sessionlog/src/__tests__/validation.test.ts +103 -0
  296. package/references/sessionlog/src/__tests__/worktree.test.ts +57 -0
  297. package/references/sessionlog/src/agent/agents/claude-code.ts +1089 -0
  298. package/references/sessionlog/src/agent/agents/cursor.ts +361 -0
  299. package/references/sessionlog/src/agent/agents/gemini-cli.ts +632 -0
  300. package/references/sessionlog/src/agent/agents/opencode.ts +540 -0
  301. package/references/sessionlog/src/agent/registry.ts +143 -0
  302. package/references/sessionlog/src/agent/session-types.ts +113 -0
  303. package/references/sessionlog/src/agent/types.ts +220 -0
  304. package/references/sessionlog/src/cli.ts +597 -0
  305. package/references/sessionlog/src/commands/clean.ts +133 -0
  306. package/references/sessionlog/src/commands/disable.ts +84 -0
  307. package/references/sessionlog/src/commands/doctor.ts +145 -0
  308. package/references/sessionlog/src/commands/enable.ts +202 -0
  309. package/references/sessionlog/src/commands/explain.ts +261 -0
  310. package/references/sessionlog/src/commands/reset.ts +105 -0
  311. package/references/sessionlog/src/commands/resume.ts +180 -0
  312. package/references/sessionlog/src/commands/rewind.ts +195 -0
  313. package/references/sessionlog/src/commands/setup-ccweb.ts +275 -0
  314. package/references/sessionlog/src/commands/status.ts +172 -0
  315. package/references/sessionlog/src/config.ts +165 -0
  316. package/references/sessionlog/src/events/event-log.ts +126 -0
  317. package/references/sessionlog/src/git-operations.ts +558 -0
  318. package/references/sessionlog/src/hooks/git-hooks.ts +165 -0
  319. package/references/sessionlog/src/hooks/lifecycle.ts +391 -0
  320. package/references/sessionlog/src/index.ts +650 -0
  321. package/references/sessionlog/src/security/redaction.ts +283 -0
  322. package/references/sessionlog/src/session/state-machine.ts +452 -0
  323. package/references/sessionlog/src/store/checkpoint-store.ts +509 -0
  324. package/references/sessionlog/src/store/native-store.ts +173 -0
  325. package/references/sessionlog/src/store/provider-types.ts +99 -0
  326. package/references/sessionlog/src/store/session-store.ts +266 -0
  327. package/references/sessionlog/src/strategy/attribution.ts +296 -0
  328. package/references/sessionlog/src/strategy/common.ts +207 -0
  329. package/references/sessionlog/src/strategy/content-overlap.ts +228 -0
  330. package/references/sessionlog/src/strategy/manual-commit.ts +988 -0
  331. package/references/sessionlog/src/strategy/types.ts +279 -0
  332. package/references/sessionlog/src/summarize/claude-generator.ts +115 -0
  333. package/references/sessionlog/src/summarize/summarize.ts +432 -0
  334. package/references/sessionlog/src/types.ts +508 -0
  335. package/references/sessionlog/src/utils/chunk-files.ts +49 -0
  336. package/references/sessionlog/src/utils/commit-message.ts +65 -0
  337. package/references/sessionlog/src/utils/detect-agent.ts +36 -0
  338. package/references/sessionlog/src/utils/hook-managers.ts +125 -0
  339. package/references/sessionlog/src/utils/ide-tags.ts +32 -0
  340. package/references/sessionlog/src/utils/paths.ts +79 -0
  341. package/references/sessionlog/src/utils/preview-rewind.ts +80 -0
  342. package/references/sessionlog/src/utils/rewind-conflict.ts +121 -0
  343. package/references/sessionlog/src/utils/shadow-branch.ts +109 -0
  344. package/references/sessionlog/src/utils/string-utils.ts +46 -0
  345. package/references/sessionlog/src/utils/todo-extract.ts +188 -0
  346. package/references/sessionlog/src/utils/trailers.ts +187 -0
  347. package/references/sessionlog/src/utils/transcript-parse.ts +177 -0
  348. package/references/sessionlog/src/utils/transcript-timestamp.ts +59 -0
  349. package/references/sessionlog/src/utils/tree-ops.ts +219 -0
  350. package/references/sessionlog/src/utils/tty.ts +72 -0
  351. package/references/sessionlog/src/utils/validation.ts +65 -0
  352. package/references/sessionlog/src/utils/worktree.ts +58 -0
  353. package/references/sessionlog/src/wire-types.ts +59 -0
  354. package/references/sessionlog/templates/setup-env.sh +153 -0
  355. package/references/sessionlog/tsconfig.json +18 -0
  356. package/references/sessionlog/vitest.config.ts +12 -0
  357. package/references/skill-tree/.sudocode/issues.jsonl +8 -0
  358. package/references/skill-tree/.sudocode/specs.jsonl +2 -0
  359. package/references/skill-tree/CLAUDE.md +56 -80
  360. package/references/skill-tree/README.md +188 -140
  361. package/references/skill-tree/examples/basic-usage.ts +95 -121
  362. package/references/skill-tree/package-lock.json +369 -26
  363. package/references/skill-tree/package.json +1 -1
  364. package/src/atlas.ts +97 -67
  365. package/src/bin/cli-utils.ts +220 -0
  366. package/src/bin/cognitive-core.ts +84 -392
  367. package/src/bin/commands/kb.ts +266 -0
  368. package/src/bin/commands/learn.ts +100 -0
  369. package/src/bin/commands/legacy.ts +182 -0
  370. package/src/bin/commands/run.ts +113 -0
  371. package/src/bin/commands/sessions.ts +221 -0
  372. package/src/bin/commands/skills.ts +146 -0
  373. package/src/embeddings/index.ts +3 -0
  374. package/src/embeddings/inverted-index.ts +134 -0
  375. package/src/embeddings/manager.ts +13 -8
  376. package/src/embeddings/vector-store.ts +21 -9
  377. package/src/factory.ts +33 -16
  378. package/src/index.ts +109 -9
  379. package/src/learning/analyzer.ts +21 -37
  380. package/src/learning/energy-evaluator.ts +282 -0
  381. package/src/learning/healing-orchestrator.ts +383 -0
  382. package/src/learning/index.ts +65 -9
  383. package/src/learning/instant-loop.ts +357 -0
  384. package/src/learning/maintenance-scheduler.ts +271 -0
  385. package/src/learning/meta-learner.ts +5 -23
  386. package/src/learning/reflexion-generator.ts +273 -0
  387. package/src/learning/trajectory-sources/entire.ts +24 -13
  388. package/src/learning/trajectory-sources/index.ts +2 -2
  389. package/src/learning/trajectory-sources/pipeline.ts +5 -5
  390. package/src/learning/unified-pipeline.ts +921 -0
  391. package/src/memory/candidate-retrieval.ts +71 -0
  392. package/src/memory/causal-store.ts +273 -0
  393. package/src/memory/coherence.ts +252 -0
  394. package/src/memory/experience.ts +217 -50
  395. package/src/memory/index.ts +43 -0
  396. package/src/memory/knowledge-bank.ts +57 -0
  397. package/src/memory/meta.ts +78 -96
  398. package/src/memory/playbook.ts +239 -75
  399. package/src/memory/reasoning-bank.ts +458 -0
  400. package/src/memory/reflexion.ts +122 -0
  401. package/src/memory/system.ts +21 -5
  402. package/src/memory/temporal-compressor.ts +409 -0
  403. package/src/persistence/index.ts +37 -0
  404. package/src/persistence/migrator.ts +298 -0
  405. package/src/persistence/serializers.ts +79 -0
  406. package/src/persistence/sqlite-persistence.ts +925 -0
  407. package/src/runtime/flows/learning.ts +25 -42
  408. package/src/search/index.ts +10 -0
  409. package/src/search/moe-gate.ts +304 -0
  410. package/src/search/router.ts +111 -4
  411. package/src/session-bank/git-reader.ts +29 -19
  412. package/src/session-bank/index.ts +4 -2
  413. package/src/session-bank/parser.ts +280 -98
  414. package/src/session-bank/session-bank.ts +33 -12
  415. package/src/session-bank/types.ts +8 -5
  416. package/src/surfacing/skill-publisher.ts +17 -49
  417. package/src/surfacing/sqlite-storage-adapter.ts +16 -32
  418. package/src/types/config.ts +30 -0
  419. package/src/types/index.ts +3 -0
  420. package/src/types/memory.ts +30 -0
  421. package/src/types/playbook.ts +4 -0
  422. package/src/utils/error-classifier.ts +113 -0
  423. package/src/utils/index.ts +18 -0
  424. package/src/utils/partitioned-store.ts +299 -0
  425. package/src/utils/trajectory-helpers.ts +79 -0
  426. package/src/workspace/runner.ts +3 -3
  427. package/src/workspace/types.ts +10 -2
  428. package/tests/embeddings/inverted-index.test.ts +138 -0
  429. package/tests/feature-toggles.test.ts +275 -0
  430. package/tests/gap-fixes.test.ts +17 -4
  431. package/tests/integration/cli-e2e.test.ts +621 -0
  432. package/tests/integration/e2e.test.ts +6 -5
  433. package/tests/integration/entire-e2e.test.ts +314 -125
  434. package/tests/integration/persistence-e2e.test.ts +741 -0
  435. package/tests/integration/phase-e2e.test.ts +1143 -0
  436. package/tests/integration/session-bank.test.ts +20 -14
  437. package/tests/integration/sessionlog-e2e.test.ts +329 -0
  438. package/tests/integration/unified-pipeline-e2e.test.ts +634 -0
  439. package/tests/learning/analyzer.test.ts +1 -1
  440. package/tests/learning/energy-evaluator.test.ts +180 -0
  441. package/tests/learning/entire-trajectory-source.test.ts +25 -25
  442. package/tests/learning/healing-orchestrator.test.ts +269 -0
  443. package/tests/learning/instant-loop.test.ts +243 -0
  444. package/tests/learning/maintenance-scheduler.test.ts +191 -0
  445. package/tests/learning/reflexion-generator.test.ts +411 -0
  446. package/tests/learning/trajectory-sources.test.ts +12 -4
  447. package/tests/learning/unified-pipeline.test.ts +322 -0
  448. package/tests/mcp/playbook-server.test.ts +6 -1
  449. package/tests/memory/causal-store.test.ts +276 -0
  450. package/tests/memory/coherence.test.ts +232 -0
  451. package/tests/memory/experience.test.ts +8 -3
  452. package/tests/memory/playbook.test.ts +307 -1
  453. package/tests/memory/provenance.test.ts +11 -2
  454. package/tests/memory/reasoning-bank.test.ts +239 -0
  455. package/tests/memory/reflexion.test.ts +166 -0
  456. package/tests/memory/skill-exporter.test.ts +6 -1
  457. package/tests/memory/system.test.ts +6 -1
  458. package/tests/memory/temporal-compressor.test.ts +318 -0
  459. package/tests/persistence/migrator.test.ts +1009 -0
  460. package/tests/persistence/sqlite-persistence.test.ts +635 -0
  461. package/tests/runtime/agent-manager.test.ts +6 -1
  462. package/tests/runtime/delegate.test.ts +6 -1
  463. package/tests/search/moe-gate.test.ts +250 -0
  464. package/tests/search/refinement-loop.test.ts +11 -2
  465. package/tests/search/router.test.ts +81 -2
  466. package/tests/session-bank/fixtures/sessionlog-root-metadata.json +16 -0
  467. package/tests/session-bank/fixtures/sessionlog-session/full.jsonl +6 -0
  468. package/tests/session-bank/fixtures/sessionlog-session/metadata.json +55 -0
  469. package/tests/session-bank/git-reader.test.ts +13 -13
  470. package/tests/session-bank/parser.test.ts +135 -3
  471. package/tests/session-bank/session-bank.test.ts +1 -1
  472. package/tests/surfacing/skill-library.test.ts +6 -1
  473. package/tests/surfacing/skill-publisher.test.ts +24 -58
  474. package/tests/surfacing/sqlite-storage-adapter.test.ts +11 -23
  475. package/tests/utils/partitioned-store.test.ts +230 -0
  476. package/tests/workspace/full-flow.test.ts +10 -4
  477. package/tests/workspace/runner.test.ts +10 -4
  478. package/docs/DESIGN-workspace-migration.md +0 -1079
  479. package/docs/PLAN-agentic-workspace-implementation.md +0 -717
  480. package/docs/PLAN-graph-migration.md +0 -299
  481. package/docs/PLAN-session-bank-implementation.md +0 -474
  482. package/src/learning/pipeline.ts +0 -323
  483. package/tests/learning/pipeline.test.ts +0 -176
@@ -0,0 +1,232 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { CoherenceChecker } from '../../src/memory/coherence.js';
3
+ import { createObservation } from '../../src/types/knowledge.js';
4
+ import type { KnowledgeNote } from '../../src/types/knowledge.js';
5
+
6
+ function makeNote(opts: {
7
+ id?: string;
8
+ body: string;
9
+ domain?: string[];
10
+ entities?: string[];
11
+ }): KnowledgeNote {
12
+ return createObservation({
13
+ id: opts.id ?? `k-${crypto.randomUUID().slice(0, 8)}`,
14
+ title: 'Test note',
15
+ body: opts.body,
16
+ domain: opts.domain ?? ['testing'],
17
+ entities: opts.entities ?? ['vitest'],
18
+ confidence: 0.7,
19
+ source: { origin: 'extracted' },
20
+ });
21
+ }
22
+
23
+ describe('CoherenceChecker', () => {
24
+ const checker = new CoherenceChecker();
25
+
26
+ describe('coherent notes', () => {
27
+ it('should pass check for non-contradictory notes', async () => {
28
+ const newNote = makeNote({
29
+ body: 'Always use TypeScript for type safety in production code',
30
+ entities: ['typescript'],
31
+ domain: ['typescript'],
32
+ });
33
+ const existingNotes = [
34
+ makeNote({
35
+ body: 'TypeScript provides excellent type checking capabilities',
36
+ entities: ['typescript'],
37
+ domain: ['typescript'],
38
+ }),
39
+ makeNote({
40
+ body: 'Enable strict mode in tsconfig for better type safety',
41
+ entities: ['typescript'],
42
+ domain: ['typescript'],
43
+ }),
44
+ ];
45
+
46
+ const result = await checker.check(newNote, existingNotes);
47
+
48
+ expect(result.isCoherent).toBe(true);
49
+ expect(result.contradictions).toHaveLength(0);
50
+ });
51
+
52
+ it('should skip notes in different domains', async () => {
53
+ const newNote = makeNote({
54
+ body: 'Always use strict mode in Python for better error handling',
55
+ entities: ['python'],
56
+ domain: ['python'],
57
+ });
58
+ const existingNotes = [
59
+ makeNote({
60
+ body: 'Never use strict mode — it slows down development',
61
+ entities: ['javascript'],
62
+ domain: ['javascript'],
63
+ }),
64
+ ];
65
+
66
+ const result = await checker.check(newNote, existingNotes);
67
+
68
+ expect(result.isCoherent).toBe(true);
69
+ expect(result.contradictions).toHaveLength(0);
70
+ });
71
+ });
72
+
73
+ describe('contradictory notes', () => {
74
+ it('should detect "always use X" vs "never use X" contradiction', async () => {
75
+ const newNote = makeNote({
76
+ body: 'Always use semicolons in TypeScript code for consistency',
77
+ entities: ['typescript'],
78
+ domain: ['typescript'],
79
+ });
80
+ const existingNotes = [
81
+ makeNote({
82
+ body: 'Never use semicolons in TypeScript code — the parser handles it automatically',
83
+ entities: ['typescript'],
84
+ domain: ['typescript'],
85
+ }),
86
+ ];
87
+
88
+ const result = await checker.check(newNote, existingNotes);
89
+
90
+ expect(result.isCoherent).toBe(false);
91
+ expect(result.contradictions.length).toBeGreaterThan(0);
92
+ expect(result.contradictions[0].residualEnergy).toBeGreaterThan(0.2);
93
+ });
94
+
95
+ it('should detect "use X" vs "avoid X" contradiction', async () => {
96
+ const newNote = makeNote({
97
+ body: 'For TypeScript projects, use the any type when working with dynamic data structures',
98
+ entities: ['typescript'],
99
+ domain: ['typescript'],
100
+ });
101
+ const existingNotes = [
102
+ makeNote({
103
+ body: 'For TypeScript projects, avoid the any type when working with dynamic data structures',
104
+ entities: ['typescript'],
105
+ domain: ['typescript'],
106
+ }),
107
+ ];
108
+
109
+ const result = await checker.check(newNote, existingNotes);
110
+
111
+ expect(result.isCoherent).toBe(false);
112
+ expect(result.contradictions.length).toBeGreaterThan(0);
113
+ });
114
+
115
+ it('should detect "do X" vs "don\'t X" contradiction', async () => {
116
+ const newNote = makeNote({
117
+ body: 'When configuring eslint rules for the project, do enable strict type checking',
118
+ entities: ['eslint'],
119
+ domain: ['tooling'],
120
+ });
121
+ const existingNotes = [
122
+ makeNote({
123
+ body: "When configuring eslint rules for the project, don't enable strict type checking",
124
+ entities: ['eslint'],
125
+ domain: ['tooling'],
126
+ }),
127
+ ];
128
+
129
+ const result = await checker.check(newNote, existingNotes);
130
+
131
+ expect(result.isCoherent).toBe(false);
132
+ expect(result.contradictions.length).toBeGreaterThan(0);
133
+ });
134
+ });
135
+
136
+ describe('same-entity filtering', () => {
137
+ it('should compare notes with the same entities', async () => {
138
+ const newNote = makeNote({
139
+ body: 'Always use vitest for testing TypeScript projects',
140
+ entities: ['vitest'],
141
+ domain: ['testing'],
142
+ });
143
+ const existingNotes = [
144
+ makeNote({
145
+ body: 'Never use vitest for testing TypeScript projects — use jest instead',
146
+ entities: ['vitest'],
147
+ domain: ['testing'],
148
+ }),
149
+ makeNote({
150
+ body: 'Deploy applications to production every Friday',
151
+ entities: ['deployment'],
152
+ domain: ['devops'],
153
+ }),
154
+ ];
155
+
156
+ const result = await checker.check(newNote, existingNotes);
157
+
158
+ // Should only find contradiction with vitest note, not deployment note
159
+ expect(result.isCoherent).toBe(false);
160
+ expect(result.contradictions.length).toBe(1);
161
+ });
162
+ });
163
+
164
+ describe('global energy', () => {
165
+ it('should return 0 for a single note', () => {
166
+ const notes = [
167
+ makeNote({ body: 'TypeScript is great', domain: ['typescript'] }),
168
+ ];
169
+
170
+ const energy = checker.computeGlobalEnergy(notes);
171
+ expect(energy).toBe(0);
172
+ });
173
+
174
+ it('should increase energy with more contradictions', () => {
175
+ const coherentNotes = [
176
+ makeNote({
177
+ body: 'Use TypeScript for type safety',
178
+ domain: ['typescript'],
179
+ entities: ['typescript'],
180
+ }),
181
+ makeNote({
182
+ body: 'TypeScript provides compile-time checking',
183
+ domain: ['typescript'],
184
+ entities: ['typescript'],
185
+ }),
186
+ ];
187
+
188
+ const contradictoryNotes = [
189
+ makeNote({
190
+ body: 'Always use strict TypeScript types for safety',
191
+ domain: ['typescript'],
192
+ entities: ['typescript'],
193
+ }),
194
+ makeNote({
195
+ body: 'Never use strict TypeScript types — they slow development',
196
+ domain: ['typescript'],
197
+ entities: ['typescript'],
198
+ }),
199
+ ];
200
+
201
+ const coherentEnergy = checker.computeGlobalEnergy(coherentNotes);
202
+ const contradictoryEnergy = checker.computeGlobalEnergy(contradictoryNotes);
203
+
204
+ expect(contradictoryEnergy).toBeGreaterThan(coherentEnergy);
205
+ });
206
+ });
207
+
208
+ describe('configuration', () => {
209
+ it('should respect maxComparisons', async () => {
210
+ const checker2 = new CoherenceChecker({ maxComparisons: 1 });
211
+ const newNote = makeNote({
212
+ body: 'Always use semicolons for consistency',
213
+ entities: ['typescript'],
214
+ domain: ['typescript'],
215
+ });
216
+ // Create many existing notes — only 1 should be compared
217
+ const existingNotes = Array.from({ length: 10 }, (_, i) =>
218
+ makeNote({
219
+ id: `note-${i}`,
220
+ body: `Never use semicolons — note ${i} for consistency`,
221
+ entities: ['typescript'],
222
+ domain: ['typescript'],
223
+ })
224
+ );
225
+
226
+ const result = await checker2.check(newNote, existingNotes);
227
+
228
+ // Should find at most 1 contradiction since maxComparisons=1
229
+ expect(result.contradictions.length).toBeLessThanOrEqual(1);
230
+ });
231
+ });
232
+ });
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { ExperienceMemory } from '../../src/memory/experience.js';
3
3
  import { createExperience, type Experience } from '../../src/types/memory.js';
4
+ import { createSqlitePersistence } from '../../src/persistence/index.js';
4
5
  import { mkdtemp, rm } from 'node:fs/promises';
5
6
  import { join } from 'node:path';
6
7
  import { tmpdir } from 'node:os';
@@ -8,15 +9,19 @@ import { tmpdir } from 'node:os';
8
9
  describe('ExperienceMemory', () => {
9
10
  let tempDir: string;
10
11
  let memory: ExperienceMemory;
12
+ let persistence: any;
11
13
 
12
14
  beforeEach(async () => {
13
15
  tempDir = await mkdtemp(join(tmpdir(), 'atlas-test-'));
14
- memory = new ExperienceMemory(tempDir);
16
+ persistence = createSqlitePersistence({ baseDir: tempDir });
17
+ await persistence.init();
18
+ memory = new ExperienceMemory(persistence);
15
19
  await memory.init();
16
20
  });
17
21
 
18
22
  afterEach(async () => {
19
23
  await memory.close();
24
+ persistence.close();
20
25
  await rm(tempDir, { recursive: true, force: true });
21
26
  });
22
27
 
@@ -184,8 +189,8 @@ describe('ExperienceMemory', () => {
184
189
  await memory.add(exp);
185
190
  await memory.close();
186
191
 
187
- // Create new memory instance
188
- const memory2 = new ExperienceMemory(tempDir);
192
+ // Create new memory instance from the same persistence (shared SQLite DB)
193
+ const memory2 = new ExperienceMemory(persistence);
189
194
  await memory2.init();
190
195
 
191
196
  const retrieved = await memory2.get(exp.id);
@@ -1,6 +1,7 @@
1
1
  import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
2
  import { PlaybookLibrary, createPlaybookLibrary } from '../../src/memory/playbook.js';
3
3
  import type { Playbook } from '../../src/types/playbook.js';
4
+ import { createSqlitePersistence } from '../../src/persistence/index.js';
4
5
  import { mkdtemp, rm } from 'node:fs/promises';
5
6
  import { join } from 'node:path';
6
7
  import { tmpdir } from 'node:os';
@@ -8,15 +9,19 @@ import { tmpdir } from 'node:os';
8
9
  describe('PlaybookLibrary', () => {
9
10
  let tempDir: string;
10
11
  let library: PlaybookLibrary;
12
+ let persistence: any;
11
13
 
12
14
  beforeEach(async () => {
13
15
  tempDir = await mkdtemp(join(tmpdir(), 'atlas-test-'));
14
- library = createPlaybookLibrary(tempDir);
16
+ persistence = createSqlitePersistence({ baseDir: tempDir });
17
+ await persistence.init();
18
+ library = createPlaybookLibrary(persistence);
15
19
  await library.init();
16
20
  });
17
21
 
18
22
  afterEach(async () => {
19
23
  await library.close();
24
+ persistence.close();
20
25
  await rm(tempDir, { recursive: true, force: true });
21
26
  });
22
27
 
@@ -322,6 +327,164 @@ describe('PlaybookLibrary', () => {
322
327
  });
323
328
  });
324
329
 
330
+ describe('stability-plasticity', () => {
331
+ it('should dampen confidence changes for high consolidationStrength', async () => {
332
+ // Create a highly consolidated playbook
333
+ const consolidated = createSamplePlaybook({
334
+ name: 'consolidated',
335
+ confidence: 0.7,
336
+ evolution: {
337
+ version: '1.0.0',
338
+ createdFrom: [],
339
+ failures: [],
340
+ refinements: [],
341
+ successCount: 50,
342
+ failureCount: 2,
343
+ consolidationStrength: 5,
344
+ },
345
+ });
346
+ await library.add(consolidated);
347
+
348
+ // Create a fresh playbook
349
+ const fresh = createSamplePlaybook({
350
+ name: 'fresh',
351
+ confidence: 0.7,
352
+ evolution: {
353
+ version: '1.0.0',
354
+ createdFrom: [],
355
+ failures: [],
356
+ refinements: [],
357
+ successCount: 0,
358
+ failureCount: 0,
359
+ consolidationStrength: 0,
360
+ },
361
+ });
362
+ await library.add(fresh);
363
+
364
+ // Apply failure to both
365
+ await library.recordFailure(consolidated.id, 'traj-1', 'test', 'test fail');
366
+ await library.recordFailure(fresh.id, 'traj-2', 'test', 'test fail');
367
+
368
+ const updatedConsolidated = await library.get(consolidated.id);
369
+ const updatedFresh = await library.get(fresh.id);
370
+
371
+ // Both should decrease, but consolidated should decrease less
372
+ const consolidatedDelta = 0.7 - updatedConsolidated!.confidence;
373
+ const freshDelta = 0.7 - updatedFresh!.confidence;
374
+ expect(consolidatedDelta).toBeLessThan(freshDelta);
375
+ });
376
+
377
+ it('should behave as before when consolidationStrength is 0', async () => {
378
+ // A playbook with no consolidation should update like the original EMA
379
+ const playbook = createSamplePlaybook({
380
+ confidence: 0.5,
381
+ evolution: {
382
+ version: '1.0.0',
383
+ createdFrom: [],
384
+ failures: [],
385
+ refinements: [],
386
+ successCount: 0,
387
+ failureCount: 0,
388
+ consolidationStrength: 0,
389
+ },
390
+ });
391
+ await library.add(playbook);
392
+
393
+ await library.recordSuccess(playbook.id, 'traj-1');
394
+
395
+ const updated = await library.get(playbook.id);
396
+ // With cs=0: dampedDelta = rawDelta / (1 + 0) = rawDelta
397
+ // rawDelta = (1 - 0.5) * 0.1 = 0.05
398
+ // new confidence = 0.5 + 0.05 = 0.55
399
+ expect(updated!.confidence).toBeCloseTo(0.55, 2);
400
+ });
401
+
402
+ it('should grow consolidationStrength on success', async () => {
403
+ const playbook = createSamplePlaybook({
404
+ evolution: {
405
+ version: '1.0.0',
406
+ createdFrom: [],
407
+ failures: [],
408
+ refinements: [],
409
+ successCount: 0,
410
+ failureCount: 0,
411
+ consolidationStrength: 0,
412
+ },
413
+ });
414
+ await library.add(playbook);
415
+
416
+ await library.recordSuccess(playbook.id, 'traj-1');
417
+ const after1 = await library.get(playbook.id);
418
+ expect(after1!.evolution.consolidationStrength).toBeCloseTo(0.05, 3);
419
+
420
+ await library.recordSuccess(playbook.id, 'traj-2');
421
+ const after2 = await library.get(playbook.id);
422
+ expect(after2!.evolution.consolidationStrength).toBeCloseTo(0.10, 3);
423
+ });
424
+
425
+ it('should not reduce consolidationStrength on failure', async () => {
426
+ const playbook = createSamplePlaybook({
427
+ evolution: {
428
+ version: '1.0.0',
429
+ createdFrom: [],
430
+ failures: [],
431
+ refinements: [],
432
+ successCount: 10,
433
+ failureCount: 0,
434
+ consolidationStrength: 2.0,
435
+ },
436
+ });
437
+ await library.add(playbook);
438
+
439
+ await library.recordFailure(playbook.id, 'traj-1', 'test', 'failed');
440
+ const updated = await library.get(playbook.id);
441
+ // consolidationStrength should remain at 2.0 (failures don't reduce it)
442
+ expect(updated!.evolution.consolidationStrength).toBe(2.0);
443
+ });
444
+
445
+ it('should cap consolidationStrength at 10', async () => {
446
+ const playbook = createSamplePlaybook({
447
+ evolution: {
448
+ version: '1.0.0',
449
+ createdFrom: [],
450
+ failures: [],
451
+ refinements: [],
452
+ successCount: 100,
453
+ failureCount: 0,
454
+ consolidationStrength: 9.98,
455
+ },
456
+ });
457
+ await library.add(playbook);
458
+
459
+ await library.recordSuccess(playbook.id, 'traj-1');
460
+ const updated = await library.get(playbook.id);
461
+ expect(updated!.evolution.consolidationStrength).toBeLessThanOrEqual(10);
462
+ });
463
+
464
+ it('should backward compat — missing consolidationStrength defaults to 0', async () => {
465
+ // Playbook without consolidationStrength field
466
+ const playbook = createSamplePlaybook({
467
+ confidence: 0.5,
468
+ evolution: {
469
+ version: '1.0.0',
470
+ createdFrom: [],
471
+ failures: [],
472
+ refinements: [],
473
+ successCount: 0,
474
+ failureCount: 0,
475
+ // No consolidationStrength or domainBreadth
476
+ },
477
+ });
478
+ await library.add(playbook);
479
+
480
+ await library.recordSuccess(playbook.id, 'traj-1');
481
+ const updated = await library.get(playbook.id);
482
+ // Should still work, same as cs=0
483
+ expect(updated!.confidence).toBeCloseTo(0.55, 2);
484
+ expect(updated!.evolution.consolidationStrength).toBeCloseTo(0.05, 3);
485
+ });
486
+ });
487
+
325
488
  describe('count and getAll', () => {
326
489
  it('should return correct counts', async () => {
327
490
  expect(await library.count()).toBe(0);
@@ -335,4 +498,147 @@ describe('PlaybookLibrary', () => {
335
498
  expect(all).toHaveLength(2);
336
499
  });
337
500
  });
501
+
502
+ describe('MMR diversity', () => {
503
+ it('should match pure relevance ranking when lambda=1.0', async () => {
504
+ await library.add(createSamplePlaybook({
505
+ name: 'pb-a',
506
+ applicability: {
507
+ situations: ['Fix TypeScript type errors in production code'],
508
+ triggers: ['TS2322'],
509
+ antiPatterns: [],
510
+ domains: ['typescript'],
511
+ },
512
+ guidance: {
513
+ strategy: 'Analyze and fix type mismatches',
514
+ tactics: [],
515
+ steps: [],
516
+ },
517
+ }));
518
+ await library.add(createSamplePlaybook({
519
+ name: 'pb-b',
520
+ applicability: {
521
+ situations: ['Fix TypeScript import errors'],
522
+ triggers: ['import'],
523
+ antiPatterns: [],
524
+ domains: ['typescript'],
525
+ },
526
+ guidance: {
527
+ strategy: 'Check and resolve import paths',
528
+ tactics: [],
529
+ steps: [],
530
+ },
531
+ }));
532
+
533
+ // lambda=1.0 should give same order as no MMR
534
+ const pureRelevance = await library.findMatching('TypeScript type errors', { k: 2 });
535
+ const mmr1 = await library.findMatching('TypeScript type errors', { k: 2, lambda: 1.0 });
536
+
537
+ expect(pureRelevance.length).toBe(mmr1.length);
538
+ // Same top result
539
+ expect(pureRelevance[0].playbook.name).toBe(mmr1[0].playbook.name);
540
+ });
541
+
542
+ it('should diversify results when lambda is low', async () => {
543
+ // Add two very similar playbooks and one different
544
+ await library.add(createSamplePlaybook({
545
+ name: 'similar-1',
546
+ applicability: {
547
+ situations: ['Debug TypeScript type error in code'],
548
+ triggers: ['type error'],
549
+ antiPatterns: [],
550
+ domains: ['typescript'],
551
+ },
552
+ guidance: {
553
+ strategy: 'Read the full error message and trace back to the source type declaration',
554
+ tactics: [],
555
+ steps: [],
556
+ },
557
+ }));
558
+ await library.add(createSamplePlaybook({
559
+ name: 'similar-2',
560
+ applicability: {
561
+ situations: ['Debug TypeScript type error in tests'],
562
+ triggers: ['type error'],
563
+ antiPatterns: [],
564
+ domains: ['typescript'],
565
+ },
566
+ guidance: {
567
+ strategy: 'Read the full error message and trace back to the source type declaration',
568
+ tactics: [],
569
+ steps: [],
570
+ },
571
+ }));
572
+ await library.add(createSamplePlaybook({
573
+ name: 'different',
574
+ applicability: {
575
+ situations: ['Debug TypeScript type error using alternative approach'],
576
+ triggers: ['type error'],
577
+ antiPatterns: [],
578
+ domains: ['typescript'],
579
+ },
580
+ guidance: {
581
+ strategy: 'Use the TypeScript compiler API to programmatically analyze types',
582
+ tactics: [],
583
+ steps: [],
584
+ },
585
+ }));
586
+
587
+ // With low lambda, MMR should prefer the diverse playbook over the near-duplicate
588
+ const diverseResults = await library.findMatching('TypeScript type error', {
589
+ k: 3,
590
+ lambda: 0.3,
591
+ });
592
+
593
+ expect(diverseResults.length).toBe(3);
594
+ // The "different" strategy playbook should appear in the top results
595
+ const names = diverseResults.map((r) => r.playbook.name);
596
+ expect(names).toContain('different');
597
+ });
598
+
599
+ it('should avoid returning near-duplicates with strong diversity bias', async () => {
600
+ // Add 3 playbooks with identical strategies
601
+ for (let i = 0; i < 3; i++) {
602
+ await library.add(createSamplePlaybook({
603
+ name: `clone-${i}`,
604
+ applicability: {
605
+ situations: ['Resolve eslint warnings in codebase'],
606
+ triggers: ['eslint warning'],
607
+ antiPatterns: [],
608
+ domains: ['typescript'],
609
+ },
610
+ guidance: {
611
+ strategy: 'Run eslint with auto-fix flag',
612
+ tactics: [],
613
+ steps: [],
614
+ },
615
+ }));
616
+ }
617
+
618
+ // Add one unique playbook
619
+ await library.add(createSamplePlaybook({
620
+ name: 'unique-lint',
621
+ applicability: {
622
+ situations: ['Resolve eslint warnings using custom rules'],
623
+ triggers: ['eslint warning'],
624
+ antiPatterns: [],
625
+ domains: ['typescript'],
626
+ },
627
+ guidance: {
628
+ strategy: 'Create custom eslint rule to prevent the warning pattern',
629
+ tactics: [],
630
+ steps: [],
631
+ },
632
+ }));
633
+
634
+ // With diversity bias, the unique one should appear by position 2
635
+ const results = await library.findMatching('eslint warnings', {
636
+ k: 2,
637
+ lambda: 0.3,
638
+ });
639
+
640
+ const names = results.map((r) => r.playbook.name);
641
+ expect(names).toContain('unique-lint');
642
+ });
643
+ });
338
644
  });
@@ -3,6 +3,7 @@ import { PlaybookLibrary, createPlaybookLibrary } from '../../src/memory/playboo
3
3
  import { loadCuratedPlaybooks, type CuratedPlaybookFile } from '../../src/memory/curated-loader.js';
4
4
  import type { Playbook, PlaybookProvenance } from '../../src/types/playbook.js';
5
5
  import { createPlaybook } from '../../src/types/playbook.js';
6
+ import { createSqlitePersistence } from '../../src/persistence/index.js';
6
7
  import { mkdtemp, rm, mkdir, writeFile } from 'node:fs/promises';
7
8
  import { join } from 'node:path';
8
9
  import { tmpdir } from 'node:os';
@@ -10,15 +11,19 @@ import { tmpdir } from 'node:os';
10
11
  describe('Playbook Provenance', () => {
11
12
  let tempDir: string;
12
13
  let library: PlaybookLibrary;
14
+ let persistence: any;
13
15
 
14
16
  beforeEach(async () => {
15
17
  tempDir = await mkdtemp(join(tmpdir(), 'atlas-prov-test-'));
16
- library = createPlaybookLibrary(tempDir);
18
+ persistence = createSqlitePersistence({ baseDir: tempDir });
19
+ await persistence.init();
20
+ library = createPlaybookLibrary(persistence);
17
21
  await library.init();
18
22
  });
19
23
 
20
24
  afterEach(async () => {
21
25
  await library.close();
26
+ persistence.close();
22
27
  await rm(tempDir, { recursive: true, force: true });
23
28
  });
24
29
 
@@ -373,17 +378,21 @@ describe('Curated Playbook Loader', () => {
373
378
  let tempDir: string;
374
379
  let curatedDir: string;
375
380
  let library: PlaybookLibrary;
381
+ let persistence: any;
376
382
 
377
383
  beforeEach(async () => {
378
384
  tempDir = await mkdtemp(join(tmpdir(), 'atlas-curated-test-'));
379
385
  curatedDir = join(tempDir, 'curated');
380
386
  await mkdir(curatedDir, { recursive: true });
381
- library = createPlaybookLibrary(tempDir);
387
+ persistence = createSqlitePersistence({ baseDir: tempDir });
388
+ await persistence.init();
389
+ library = createPlaybookLibrary(persistence);
382
390
  await library.init();
383
391
  });
384
392
 
385
393
  afterEach(async () => {
386
394
  await library.close();
395
+ persistence.close();
387
396
  await rm(tempDir, { recursive: true, force: true });
388
397
  });
389
398