cognitive-core 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (397) hide show
  1. package/.claude/settings.json +111 -2
  2. package/.sessionlog/settings.json +4 -0
  3. package/dist/atlas.d.ts +10 -0
  4. package/dist/atlas.d.ts.map +1 -1
  5. package/dist/atlas.js +65 -0
  6. package/dist/atlas.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +5 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/learning/index.d.ts +1 -1
  12. package/dist/learning/index.d.ts.map +1 -1
  13. package/dist/learning/index.js.map +1 -1
  14. package/dist/learning/pipeline.d.ts +4 -31
  15. package/dist/learning/pipeline.d.ts.map +1 -1
  16. package/dist/learning/pipeline.js +12 -64
  17. package/dist/learning/pipeline.js.map +1 -1
  18. package/dist/learning/unified-pipeline.d.ts +30 -0
  19. package/dist/learning/unified-pipeline.d.ts.map +1 -1
  20. package/dist/learning/unified-pipeline.js +207 -0
  21. package/dist/learning/unified-pipeline.js.map +1 -1
  22. package/dist/memory/candidate-retrieval.d.ts.map +1 -1
  23. package/dist/memory/candidate-retrieval.js +3 -1
  24. package/dist/memory/candidate-retrieval.js.map +1 -1
  25. package/dist/memory/curated-loader.d.ts +21 -4
  26. package/dist/memory/curated-loader.d.ts.map +1 -1
  27. package/dist/memory/curated-loader.js +53 -16
  28. package/dist/memory/curated-loader.js.map +1 -1
  29. package/dist/memory/index.d.ts +2 -1
  30. package/dist/memory/index.d.ts.map +1 -1
  31. package/dist/memory/index.js +3 -1
  32. package/dist/memory/index.js.map +1 -1
  33. package/dist/memory/playbook.d.ts +6 -0
  34. package/dist/memory/playbook.d.ts.map +1 -1
  35. package/dist/memory/playbook.js +15 -0
  36. package/dist/memory/playbook.js.map +1 -1
  37. package/dist/memory/source-resolver.d.ts +120 -0
  38. package/dist/memory/source-resolver.d.ts.map +1 -0
  39. package/dist/memory/source-resolver.js +300 -0
  40. package/dist/memory/source-resolver.js.map +1 -0
  41. package/dist/types/config.d.ts +141 -0
  42. package/dist/types/config.d.ts.map +1 -1
  43. package/dist/types/config.js +40 -0
  44. package/dist/types/config.js.map +1 -1
  45. package/dist/types/index.d.ts +1 -1
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/index.js +1 -1
  48. package/dist/types/index.js.map +1 -1
  49. package/dist/utils/error-classifier.js +8 -8
  50. package/dist/utils/error-classifier.js.map +1 -1
  51. package/dist/workspace/efficacy-toolkit.d.ts +164 -0
  52. package/dist/workspace/efficacy-toolkit.d.ts.map +1 -0
  53. package/dist/workspace/efficacy-toolkit.js +281 -0
  54. package/dist/workspace/efficacy-toolkit.js.map +1 -0
  55. package/dist/workspace/index.d.ts +2 -1
  56. package/dist/workspace/index.d.ts.map +1 -1
  57. package/dist/workspace/index.js +3 -1
  58. package/dist/workspace/index.js.map +1 -1
  59. package/dist/workspace/templates/index.d.ts +3 -0
  60. package/dist/workspace/templates/index.d.ts.map +1 -1
  61. package/dist/workspace/templates/index.js +6 -0
  62. package/dist/workspace/templates/index.js.map +1 -1
  63. package/dist/workspace/templates/playbook-decay-detection.d.ts +46 -0
  64. package/dist/workspace/templates/playbook-decay-detection.d.ts.map +1 -0
  65. package/dist/workspace/templates/playbook-decay-detection.js +197 -0
  66. package/dist/workspace/templates/playbook-decay-detection.js.map +1 -0
  67. package/dist/workspace/templates/playbook-efficacy-audit.d.ts +46 -0
  68. package/dist/workspace/templates/playbook-efficacy-audit.d.ts.map +1 -0
  69. package/dist/workspace/templates/playbook-efficacy-audit.js +160 -0
  70. package/dist/workspace/templates/playbook-efficacy-audit.js.map +1 -0
  71. package/dist/workspace/templates/playbook-lifecycle-review.d.ts +51 -0
  72. package/dist/workspace/templates/playbook-lifecycle-review.d.ts.map +1 -0
  73. package/dist/workspace/templates/playbook-lifecycle-review.js +187 -0
  74. package/dist/workspace/templates/playbook-lifecycle-review.js.map +1 -0
  75. package/dist/workspace/types.d.ts +12 -54
  76. package/dist/workspace/types.d.ts.map +1 -1
  77. package/dist/workspace/types.js.map +1 -1
  78. package/package.json +8 -2
  79. package/playbooks/compound-engineering/adversarial-review.json +51 -0
  80. package/playbooks/compound-engineering/agent-native-architecture.json +59 -0
  81. package/playbooks/compound-engineering/agent-native-review.json +54 -0
  82. package/playbooks/compound-engineering/api-contract-review.json +52 -0
  83. package/playbooks/compound-engineering/brainstorm-requirements.json +55 -0
  84. package/playbooks/compound-engineering/bug-reproduction.json +62 -0
  85. package/playbooks/compound-engineering/confidence-calibration.json +49 -0
  86. package/playbooks/compound-engineering/correctness-review.json +49 -0
  87. package/playbooks/compound-engineering/data-migration-safety.json +59 -0
  88. package/playbooks/compound-engineering/deployment-verification.json +63 -0
  89. package/playbooks/compound-engineering/error-recovery-patterns.json +53 -0
  90. package/playbooks/compound-engineering/implementation-planning.json +64 -0
  91. package/playbooks/compound-engineering/issue-pattern-analysis.json +53 -0
  92. package/playbooks/compound-engineering/knowledge-compounding.json +63 -0
  93. package/playbooks/compound-engineering/learnings-research.json +54 -0
  94. package/playbooks/compound-engineering/maintainability-review.json +49 -0
  95. package/playbooks/compound-engineering/performance-review.json +54 -0
  96. package/playbooks/compound-engineering/plan-adversarial-review.json +56 -0
  97. package/playbooks/compound-engineering/plan-feasibility-review.json +56 -0
  98. package/playbooks/compound-engineering/project-standards-review.json +52 -0
  99. package/playbooks/compound-engineering/reliability-review.json +53 -0
  100. package/playbooks/compound-engineering/review-orchestration.json +64 -0
  101. package/playbooks/compound-engineering/security-review.json +54 -0
  102. package/playbooks/compound-engineering/systematic-execution.json +64 -0
  103. package/playbooks/compound-engineering/testing-review.json +50 -0
  104. package/src/atlas.ts +96 -0
  105. package/src/index.ts +27 -0
  106. package/src/learning/index.ts +1 -0
  107. package/src/learning/unified-pipeline.ts +271 -1
  108. package/src/memory/candidate-retrieval.ts +2 -1
  109. package/src/memory/curated-loader.ts +69 -16
  110. package/src/memory/index.ts +16 -0
  111. package/src/memory/playbook.ts +19 -0
  112. package/src/memory/source-resolver.ts +422 -0
  113. package/src/types/config.ts +46 -0
  114. package/src/types/index.ts +4 -0
  115. package/src/utils/error-classifier.ts +8 -8
  116. package/src/workspace/efficacy-toolkit.ts +496 -0
  117. package/src/workspace/index.ts +29 -0
  118. package/src/workspace/templates/index.ts +24 -0
  119. package/src/workspace/templates/playbook-decay-detection.ts +272 -0
  120. package/src/workspace/templates/playbook-efficacy-audit.ts +246 -0
  121. package/src/workspace/templates/playbook-lifecycle-review.ts +274 -0
  122. package/src/workspace/types.ts +22 -78
  123. package/tests/fixtures/behavioral-trajectories.ts +210 -0
  124. package/tests/integration/curated-sources-e2e.test.ts +502 -0
  125. package/tests/integration/pipeline-data-correctness.test.ts +794 -0
  126. package/tests/learning/meta-learner.test.ts +418 -0
  127. package/tests/learning/pipeline-memory-updates.test.ts +721 -0
  128. package/tests/learning/unified-pipeline-efficacy.test.ts +232 -0
  129. package/tests/memory/candidate-retrieval.test.ts +167 -0
  130. package/tests/memory/compound-engineering-seed.test.ts +338 -0
  131. package/tests/memory/curated-loader-extended.test.ts +225 -0
  132. package/tests/memory/meta.test.ts +399 -0
  133. package/tests/memory/playbook-quality-validation.test.ts +430 -0
  134. package/tests/memory/source-resolver.test.ts +700 -0
  135. package/tests/search/evaluator.test.ts +257 -0
  136. package/tests/search/verification-runner.test.ts +357 -0
  137. package/tests/utils/error-classifier.test.ts +149 -0
  138. package/tests/utils/trajectory-helpers.test.ts +163 -0
  139. package/tests/workspace/efficacy-toolkit.test.ts +404 -0
  140. package/tests/workspace/templates/playbook-efficacy.test.ts +377 -0
  141. package/.claude/settings.local.json +0 -11
  142. package/dist/learning/llm-extractor.d.ts +0 -88
  143. package/dist/learning/llm-extractor.d.ts.map +0 -1
  144. package/dist/learning/llm-extractor.js +0 -372
  145. package/dist/learning/llm-extractor.js.map +0 -1
  146. package/dist/learning/loop-coordinator.d.ts +0 -61
  147. package/dist/learning/loop-coordinator.d.ts.map +0 -1
  148. package/dist/learning/loop-coordinator.js +0 -96
  149. package/dist/learning/loop-coordinator.js.map +0 -1
  150. package/references/agent-workspace/CLAUDE.md +0 -74
  151. package/references/agent-workspace/README.md +0 -587
  152. package/references/agent-workspace/media/banner.png +0 -0
  153. package/references/agent-workspace/package-lock.json +0 -2061
  154. package/references/agent-workspace/package.json +0 -54
  155. package/references/agent-workspace/src/handle.ts +0 -122
  156. package/references/agent-workspace/src/index.ts +0 -32
  157. package/references/agent-workspace/src/manager.ts +0 -102
  158. package/references/agent-workspace/src/readers/json.ts +0 -71
  159. package/references/agent-workspace/src/readers/markdown.ts +0 -37
  160. package/references/agent-workspace/src/readers/raw.ts +0 -27
  161. package/references/agent-workspace/src/types.ts +0 -68
  162. package/references/agent-workspace/src/validation.ts +0 -93
  163. package/references/agent-workspace/src/writers/json.ts +0 -17
  164. package/references/agent-workspace/src/writers/markdown.ts +0 -27
  165. package/references/agent-workspace/src/writers/raw.ts +0 -22
  166. package/references/agent-workspace/tests/errors.test.ts +0 -652
  167. package/references/agent-workspace/tests/handle.test.ts +0 -144
  168. package/references/agent-workspace/tests/manager.test.ts +0 -124
  169. package/references/agent-workspace/tests/readers.test.ts +0 -205
  170. package/references/agent-workspace/tests/validation.test.ts +0 -196
  171. package/references/agent-workspace/tests/writers.test.ts +0 -108
  172. package/references/agent-workspace/tsconfig.json +0 -20
  173. package/references/agent-workspace/tsup.config.ts +0 -9
  174. package/references/minimem/.claude/settings.json +0 -7
  175. package/references/minimem/.sudocode/issues.jsonl +0 -18
  176. package/references/minimem/.sudocode/specs.jsonl +0 -1
  177. package/references/minimem/CLAUDE.md +0 -310
  178. package/references/minimem/README.md +0 -556
  179. package/references/minimem/claude-plugin/.claude-plugin/plugin.json +0 -10
  180. package/references/minimem/claude-plugin/.mcp.json +0 -7
  181. package/references/minimem/claude-plugin/README.md +0 -158
  182. package/references/minimem/claude-plugin/commands/recall.md +0 -47
  183. package/references/minimem/claude-plugin/commands/remember.md +0 -41
  184. package/references/minimem/claude-plugin/hooks/__tests__/hooks.test.ts +0 -272
  185. package/references/minimem/claude-plugin/hooks/hooks.json +0 -27
  186. package/references/minimem/claude-plugin/hooks/session-end.sh +0 -86
  187. package/references/minimem/claude-plugin/hooks/session-start.sh +0 -85
  188. package/references/minimem/claude-plugin/skills/memory/SKILL.md +0 -108
  189. package/references/minimem/package-lock.json +0 -5373
  190. package/references/minimem/package.json +0 -60
  191. package/references/minimem/scripts/postbuild.js +0 -35
  192. package/references/minimem/src/__tests__/edge-cases.test.ts +0 -371
  193. package/references/minimem/src/__tests__/errors.test.ts +0 -265
  194. package/references/minimem/src/__tests__/helpers.ts +0 -199
  195. package/references/minimem/src/__tests__/internal.test.ts +0 -407
  196. package/references/minimem/src/__tests__/knowledge.test.ts +0 -287
  197. package/references/minimem/src/__tests__/minimem.integration.test.ts +0 -1127
  198. package/references/minimem/src/__tests__/session.test.ts +0 -190
  199. package/references/minimem/src/cli/__tests__/commands.test.ts +0 -759
  200. package/references/minimem/src/cli/commands/__tests__/conflicts.test.ts +0 -141
  201. package/references/minimem/src/cli/commands/append.ts +0 -76
  202. package/references/minimem/src/cli/commands/config.ts +0 -262
  203. package/references/minimem/src/cli/commands/conflicts.ts +0 -413
  204. package/references/minimem/src/cli/commands/daemon.ts +0 -169
  205. package/references/minimem/src/cli/commands/index.ts +0 -12
  206. package/references/minimem/src/cli/commands/init.ts +0 -88
  207. package/references/minimem/src/cli/commands/mcp.ts +0 -177
  208. package/references/minimem/src/cli/commands/push-pull.ts +0 -213
  209. package/references/minimem/src/cli/commands/search.ts +0 -158
  210. package/references/minimem/src/cli/commands/status.ts +0 -84
  211. package/references/minimem/src/cli/commands/sync-init.ts +0 -290
  212. package/references/minimem/src/cli/commands/sync.ts +0 -70
  213. package/references/minimem/src/cli/commands/upsert.ts +0 -197
  214. package/references/minimem/src/cli/config.ts +0 -584
  215. package/references/minimem/src/cli/index.ts +0 -264
  216. package/references/minimem/src/cli/shared.ts +0 -161
  217. package/references/minimem/src/cli/sync/__tests__/central.test.ts +0 -152
  218. package/references/minimem/src/cli/sync/__tests__/conflicts.test.ts +0 -209
  219. package/references/minimem/src/cli/sync/__tests__/daemon.test.ts +0 -118
  220. package/references/minimem/src/cli/sync/__tests__/detection.test.ts +0 -207
  221. package/references/minimem/src/cli/sync/__tests__/integration.test.ts +0 -476
  222. package/references/minimem/src/cli/sync/__tests__/registry.test.ts +0 -363
  223. package/references/minimem/src/cli/sync/__tests__/state.test.ts +0 -255
  224. package/references/minimem/src/cli/sync/__tests__/validation.test.ts +0 -193
  225. package/references/minimem/src/cli/sync/__tests__/watcher.test.ts +0 -178
  226. package/references/minimem/src/cli/sync/central.ts +0 -292
  227. package/references/minimem/src/cli/sync/conflicts.ts +0 -204
  228. package/references/minimem/src/cli/sync/daemon.ts +0 -407
  229. package/references/minimem/src/cli/sync/detection.ts +0 -138
  230. package/references/minimem/src/cli/sync/index.ts +0 -107
  231. package/references/minimem/src/cli/sync/operations.ts +0 -373
  232. package/references/minimem/src/cli/sync/registry.ts +0 -279
  233. package/references/minimem/src/cli/sync/state.ts +0 -355
  234. package/references/minimem/src/cli/sync/validation.ts +0 -206
  235. package/references/minimem/src/cli/sync/watcher.ts +0 -234
  236. package/references/minimem/src/cli/version.ts +0 -34
  237. package/references/minimem/src/core/index.ts +0 -9
  238. package/references/minimem/src/core/indexer.ts +0 -628
  239. package/references/minimem/src/core/searcher.ts +0 -221
  240. package/references/minimem/src/db/schema.ts +0 -183
  241. package/references/minimem/src/db/sqlite-vec.ts +0 -24
  242. package/references/minimem/src/embeddings/__tests__/embeddings.test.ts +0 -431
  243. package/references/minimem/src/embeddings/batch-gemini.ts +0 -392
  244. package/references/minimem/src/embeddings/batch-openai.ts +0 -409
  245. package/references/minimem/src/embeddings/embeddings.ts +0 -434
  246. package/references/minimem/src/index.ts +0 -109
  247. package/references/minimem/src/internal.ts +0 -299
  248. package/references/minimem/src/minimem.ts +0 -1276
  249. package/references/minimem/src/search/__tests__/hybrid.test.ts +0 -247
  250. package/references/minimem/src/search/graph.ts +0 -234
  251. package/references/minimem/src/search/hybrid.ts +0 -151
  252. package/references/minimem/src/search/search.ts +0 -256
  253. package/references/minimem/src/server/__tests__/mcp.test.ts +0 -341
  254. package/references/minimem/src/server/__tests__/tools.test.ts +0 -364
  255. package/references/minimem/src/server/mcp.ts +0 -326
  256. package/references/minimem/src/server/tools.ts +0 -720
  257. package/references/minimem/src/session.ts +0 -460
  258. package/references/minimem/tsconfig.json +0 -19
  259. package/references/minimem/tsup.config.ts +0 -26
  260. package/references/minimem/vitest.config.ts +0 -24
  261. package/references/sessionlog/.husky/pre-commit +0 -1
  262. package/references/sessionlog/.lintstagedrc.json +0 -4
  263. package/references/sessionlog/.prettierignore +0 -4
  264. package/references/sessionlog/.prettierrc.json +0 -11
  265. package/references/sessionlog/LICENSE +0 -21
  266. package/references/sessionlog/README.md +0 -453
  267. package/references/sessionlog/eslint.config.js +0 -58
  268. package/references/sessionlog/package-lock.json +0 -3672
  269. package/references/sessionlog/package.json +0 -65
  270. package/references/sessionlog/src/__tests__/agent-hooks.test.ts +0 -570
  271. package/references/sessionlog/src/__tests__/agent-registry.test.ts +0 -127
  272. package/references/sessionlog/src/__tests__/claude-code-hooks.test.ts +0 -225
  273. package/references/sessionlog/src/__tests__/claude-generator.test.ts +0 -46
  274. package/references/sessionlog/src/__tests__/commit-msg.test.ts +0 -86
  275. package/references/sessionlog/src/__tests__/cursor-agent.test.ts +0 -224
  276. package/references/sessionlog/src/__tests__/e2e-live.test.ts +0 -890
  277. package/references/sessionlog/src/__tests__/event-log.test.ts +0 -183
  278. package/references/sessionlog/src/__tests__/flush-sentinel.test.ts +0 -105
  279. package/references/sessionlog/src/__tests__/gemini-agent.test.ts +0 -375
  280. package/references/sessionlog/src/__tests__/git-hooks.test.ts +0 -78
  281. package/references/sessionlog/src/__tests__/hook-managers.test.ts +0 -121
  282. package/references/sessionlog/src/__tests__/lifecycle-tasks.test.ts +0 -759
  283. package/references/sessionlog/src/__tests__/opencode-agent.test.ts +0 -338
  284. package/references/sessionlog/src/__tests__/redaction.test.ts +0 -136
  285. package/references/sessionlog/src/__tests__/session-repo.test.ts +0 -353
  286. package/references/sessionlog/src/__tests__/session-store.test.ts +0 -166
  287. package/references/sessionlog/src/__tests__/setup-ccweb.test.ts +0 -466
  288. package/references/sessionlog/src/__tests__/skill-live.test.ts +0 -461
  289. package/references/sessionlog/src/__tests__/summarize.test.ts +0 -348
  290. package/references/sessionlog/src/__tests__/task-plan-e2e.test.ts +0 -610
  291. package/references/sessionlog/src/__tests__/task-plan-live.test.ts +0 -632
  292. package/references/sessionlog/src/__tests__/transcript-timestamp.test.ts +0 -121
  293. package/references/sessionlog/src/__tests__/types.test.ts +0 -166
  294. package/references/sessionlog/src/__tests__/utils.test.ts +0 -333
  295. package/references/sessionlog/src/__tests__/validation.test.ts +0 -103
  296. package/references/sessionlog/src/__tests__/worktree.test.ts +0 -57
  297. package/references/sessionlog/src/agent/agents/claude-code.ts +0 -1089
  298. package/references/sessionlog/src/agent/agents/cursor.ts +0 -361
  299. package/references/sessionlog/src/agent/agents/gemini-cli.ts +0 -632
  300. package/references/sessionlog/src/agent/agents/opencode.ts +0 -540
  301. package/references/sessionlog/src/agent/registry.ts +0 -143
  302. package/references/sessionlog/src/agent/session-types.ts +0 -113
  303. package/references/sessionlog/src/agent/types.ts +0 -220
  304. package/references/sessionlog/src/cli.ts +0 -597
  305. package/references/sessionlog/src/commands/clean.ts +0 -133
  306. package/references/sessionlog/src/commands/disable.ts +0 -84
  307. package/references/sessionlog/src/commands/doctor.ts +0 -145
  308. package/references/sessionlog/src/commands/enable.ts +0 -202
  309. package/references/sessionlog/src/commands/explain.ts +0 -261
  310. package/references/sessionlog/src/commands/reset.ts +0 -105
  311. package/references/sessionlog/src/commands/resume.ts +0 -180
  312. package/references/sessionlog/src/commands/rewind.ts +0 -195
  313. package/references/sessionlog/src/commands/setup-ccweb.ts +0 -275
  314. package/references/sessionlog/src/commands/status.ts +0 -172
  315. package/references/sessionlog/src/config.ts +0 -165
  316. package/references/sessionlog/src/events/event-log.ts +0 -126
  317. package/references/sessionlog/src/git-operations.ts +0 -558
  318. package/references/sessionlog/src/hooks/git-hooks.ts +0 -165
  319. package/references/sessionlog/src/hooks/lifecycle.ts +0 -391
  320. package/references/sessionlog/src/index.ts +0 -650
  321. package/references/sessionlog/src/security/redaction.ts +0 -283
  322. package/references/sessionlog/src/session/state-machine.ts +0 -452
  323. package/references/sessionlog/src/store/checkpoint-store.ts +0 -509
  324. package/references/sessionlog/src/store/native-store.ts +0 -173
  325. package/references/sessionlog/src/store/provider-types.ts +0 -99
  326. package/references/sessionlog/src/store/session-store.ts +0 -266
  327. package/references/sessionlog/src/strategy/attribution.ts +0 -296
  328. package/references/sessionlog/src/strategy/common.ts +0 -207
  329. package/references/sessionlog/src/strategy/content-overlap.ts +0 -228
  330. package/references/sessionlog/src/strategy/manual-commit.ts +0 -988
  331. package/references/sessionlog/src/strategy/types.ts +0 -279
  332. package/references/sessionlog/src/summarize/claude-generator.ts +0 -115
  333. package/references/sessionlog/src/summarize/summarize.ts +0 -432
  334. package/references/sessionlog/src/types.ts +0 -508
  335. package/references/sessionlog/src/utils/chunk-files.ts +0 -49
  336. package/references/sessionlog/src/utils/commit-message.ts +0 -65
  337. package/references/sessionlog/src/utils/detect-agent.ts +0 -36
  338. package/references/sessionlog/src/utils/hook-managers.ts +0 -125
  339. package/references/sessionlog/src/utils/ide-tags.ts +0 -32
  340. package/references/sessionlog/src/utils/paths.ts +0 -79
  341. package/references/sessionlog/src/utils/preview-rewind.ts +0 -80
  342. package/references/sessionlog/src/utils/rewind-conflict.ts +0 -121
  343. package/references/sessionlog/src/utils/shadow-branch.ts +0 -109
  344. package/references/sessionlog/src/utils/string-utils.ts +0 -46
  345. package/references/sessionlog/src/utils/todo-extract.ts +0 -188
  346. package/references/sessionlog/src/utils/trailers.ts +0 -187
  347. package/references/sessionlog/src/utils/transcript-parse.ts +0 -177
  348. package/references/sessionlog/src/utils/transcript-timestamp.ts +0 -59
  349. package/references/sessionlog/src/utils/tree-ops.ts +0 -219
  350. package/references/sessionlog/src/utils/tty.ts +0 -72
  351. package/references/sessionlog/src/utils/validation.ts +0 -65
  352. package/references/sessionlog/src/utils/worktree.ts +0 -58
  353. package/references/sessionlog/src/wire-types.ts +0 -59
  354. package/references/sessionlog/templates/setup-env.sh +0 -153
  355. package/references/sessionlog/tsconfig.json +0 -18
  356. package/references/sessionlog/vitest.config.ts +0 -12
  357. package/references/skill-tree/.claude/settings.json +0 -6
  358. package/references/skill-tree/.sudocode/issues.jsonl +0 -19
  359. package/references/skill-tree/.sudocode/specs.jsonl +0 -3
  360. package/references/skill-tree/CLAUDE.md +0 -126
  361. package/references/skill-tree/README.md +0 -372
  362. package/references/skill-tree/docs/GAPS_v1.md +0 -221
  363. package/references/skill-tree/docs/INTEGRATION_PLAN.md +0 -467
  364. package/references/skill-tree/docs/TODOS.md +0 -91
  365. package/references/skill-tree/docs/anthropic_skill_guide.md +0 -1364
  366. package/references/skill-tree/docs/design/federated-skill-trees.md +0 -524
  367. package/references/skill-tree/docs/design/multi-agent-sync.md +0 -759
  368. package/references/skill-tree/docs/scraper/BRAINSTORM.md +0 -583
  369. package/references/skill-tree/docs/scraper/POC_PLAN.md +0 -420
  370. package/references/skill-tree/docs/scraper/README.md +0 -170
  371. package/references/skill-tree/examples/basic-usage.ts +0 -164
  372. package/references/skill-tree/package-lock.json +0 -1852
  373. package/references/skill-tree/package.json +0 -66
  374. package/references/skill-tree/scraper/README.md +0 -123
  375. package/references/skill-tree/scraper/docs/DESIGN.md +0 -683
  376. package/references/skill-tree/scraper/docs/PLAN.md +0 -336
  377. package/references/skill-tree/scraper/drizzle.config.ts +0 -10
  378. package/references/skill-tree/scraper/package-lock.json +0 -6329
  379. package/references/skill-tree/scraper/package.json +0 -68
  380. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-description.md +0 -7
  381. package/references/skill-tree/scraper/test/fixtures/invalid-skill/missing-name.md +0 -7
  382. package/references/skill-tree/scraper/test/fixtures/minimal-skill/SKILL.md +0 -27
  383. package/references/skill-tree/scraper/test/fixtures/skill-json/SKILL.json +0 -21
  384. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/SKILL.md +0 -54
  385. package/references/skill-tree/scraper/test/fixtures/skill-with-meta/_meta.json +0 -24
  386. package/references/skill-tree/scraper/test/fixtures/valid-skill/SKILL.md +0 -93
  387. package/references/skill-tree/scraper/test/fixtures/valid-skill/_meta.json +0 -22
  388. package/references/skill-tree/scraper/tsup.config.ts +0 -14
  389. package/references/skill-tree/scraper/vitest.config.ts +0 -17
  390. package/references/skill-tree/scripts/convert-to-vitest.ts +0 -166
  391. package/references/skill-tree/skills/skill-writer/SKILL.md +0 -339
  392. package/references/skill-tree/skills/skill-writer/references/examples.md +0 -326
  393. package/references/skill-tree/skills/skill-writer/references/patterns.md +0 -210
  394. package/references/skill-tree/skills/skill-writer/references/quality-checklist.md +0 -123
  395. package/references/skill-tree/test/run-all.ts +0 -106
  396. package/references/skill-tree/test/utils.ts +0 -128
  397. package/references/skill-tree/vitest.config.ts +0 -16
@@ -1,1127 +0,0 @@
1
- /**
2
- * Integration tests for Minimem
3
- *
4
- * These tests exercise the full e2e flow:
5
- * - Real SQLite database
6
- * - Real file system operations
7
- * - Mocked embeddings (deterministic, no API calls)
8
- *
9
- * Run with Node.js native test runner:
10
- * npm run test:integration
11
- */
12
-
13
- import fs from "node:fs/promises";
14
- import os from "node:os";
15
- import path from "node:path";
16
- import { after, before, describe, it } from "node:test";
17
- import assert from "node:assert";
18
-
19
- import { Minimem } from "../minimem.js";
20
- import { createMockFetch } from "./helpers.js";
21
-
22
- describe("Minimem E2E Integration", () => {
23
- let tempDir: string;
24
- let minimem: Minimem;
25
- let originalFetch: typeof fetch;
26
- let mockFetch: ReturnType<typeof createMockFetch>;
27
-
28
- before(async () => {
29
- // Create temp directory
30
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-e2e-"));
31
- await fs.mkdir(path.join(tempDir, "memory"));
32
-
33
- // Create test memory files
34
- await fs.writeFile(
35
- path.join(tempDir, "MEMORY.md"),
36
- `# Memory
37
-
38
- ## Important Decisions
39
- - We decided to use PostgreSQL for the database
40
- - API design follows REST principles
41
- - All meetings should have action items
42
-
43
- ## Project Notes
44
- - Project alpha is the main focus
45
- - Beta testing starts next month
46
- `
47
- );
48
-
49
- await fs.writeFile(
50
- path.join(tempDir, "memory", "2024-01-15.md"),
51
- `# Daily Log - 2024-01-15
52
-
53
- ## Meeting Notes
54
- Had a meeting about the API design. Key decisions:
55
- - Use REST for external APIs
56
- - GraphQL for internal services
57
- - Authentication via JWT tokens
58
-
59
- ## Todo
60
- - [ ] Review PR #123
61
- - [ ] Fix bug in user authentication
62
- - [x] Deploy to staging
63
- `
64
- );
65
-
66
- await fs.writeFile(
67
- path.join(tempDir, "memory", "2024-01-16.md"),
68
- `# Daily Log - 2024-01-16
69
-
70
- ## Bug Fix
71
- Fixed critical bug in the database connection pool.
72
- The error was caused by not properly closing connections.
73
-
74
- ## Feature Work
75
- Started working on the new user dashboard feature.
76
- Design review scheduled for tomorrow.
77
- `
78
- );
79
-
80
- // Mock fetch
81
- originalFetch = globalThis.fetch;
82
- mockFetch = createMockFetch();
83
- globalThis.fetch = mockFetch as unknown as typeof fetch;
84
-
85
- // Set fake API key
86
- process.env.OPENAI_API_KEY = "test-api-key-for-integration-tests";
87
-
88
- // Create Minimem instance
89
- minimem = await Minimem.create({
90
- memoryDir: tempDir,
91
- embedding: {
92
- provider: "openai",
93
- model: "text-embedding-3-small",
94
- },
95
- watch: { enabled: false }, // Disable watching for tests
96
- hybrid: { enabled: true },
97
- query: { minScore: 0.0 }, // Lower threshold for testing
98
- });
99
- });
100
-
101
- after(async () => {
102
- // Cleanup
103
- minimem?.close();
104
- globalThis.fetch = originalFetch;
105
- delete process.env.OPENAI_API_KEY;
106
- await fs.rm(tempDir, { recursive: true, force: true });
107
- });
108
-
109
- it("indexes memory files and creates database", async () => {
110
- // Trigger sync (happens lazily on first search or explicit call)
111
- await minimem.sync();
112
-
113
- const status = await minimem.status();
114
-
115
- assert.equal(status.memoryDir, tempDir);
116
- assert.equal(status.provider, "openai");
117
- assert.equal(status.model, "text-embedding-3-small");
118
- assert.ok(status.fileCount >= 3, `Expected at least 3 files, got ${status.fileCount}`);
119
- assert.ok(status.chunkCount > 0, `Expected chunks, got ${status.chunkCount}`);
120
- });
121
-
122
- it("searches and returns relevant results for 'database'", async () => {
123
- const results = await minimem.search("database connection bug fix");
124
-
125
- assert.ok(results.length > 0, "Expected search results");
126
-
127
- // Should find the bug fix entry
128
- const hasBugFix = results.some(r =>
129
- r.snippet.toLowerCase().includes("bug") ||
130
- r.snippet.toLowerCase().includes("database")
131
- );
132
- assert.ok(hasBugFix, "Expected to find database/bug related content");
133
- });
134
-
135
- it("searches and returns relevant results for 'meeting'", async () => {
136
- const results = await minimem.search("meeting API design decisions");
137
-
138
- assert.ok(results.length > 0, "Expected search results");
139
-
140
- // Should find meeting notes
141
- const hasMeeting = results.some(r =>
142
- r.snippet.toLowerCase().includes("meeting") ||
143
- r.snippet.toLowerCase().includes("api")
144
- );
145
- assert.ok(hasMeeting, "Expected to find meeting/API related content");
146
- });
147
-
148
- it("returns results with correct metadata", async () => {
149
- const results = await minimem.search("project alpha beta");
150
-
151
- assert.ok(results.length > 0, "Expected search results");
152
-
153
- for (const result of results) {
154
- // Each result should have required fields
155
- assert.ok(typeof result.path === "string", "Result should have path");
156
- assert.ok(typeof result.startLine === "number", "Result should have startLine");
157
- assert.ok(typeof result.endLine === "number", "Result should have endLine");
158
- assert.ok(typeof result.score === "number", "Result should have score");
159
- assert.ok(typeof result.snippet === "string", "Result should have snippet");
160
- assert.ok(result.score >= 0 && result.score <= 1, "Score should be between 0 and 1");
161
- assert.ok(result.startLine <= result.endLine, "startLine should be <= endLine");
162
- }
163
- });
164
-
165
- it("respects maxResults parameter", async () => {
166
- const results = await minimem.search("meeting todo bug", { maxResults: 2 });
167
-
168
- assert.ok(results.length <= 2, `Expected at most 2 results, got ${results.length}`);
169
- });
170
-
171
- it("respects minScore parameter", async () => {
172
- const lowThreshold = await minimem.search("test", { minScore: 0.0 });
173
- const highThreshold = await minimem.search("test", { minScore: 0.99 });
174
-
175
- // High threshold should return fewer or equal results
176
- assert.ok(
177
- highThreshold.length <= lowThreshold.length,
178
- "Higher minScore should return fewer results"
179
- );
180
- });
181
-
182
- it("handles empty query gracefully", async () => {
183
- const results = await minimem.search("");
184
- assert.deepEqual(results, [], "Empty query should return empty results");
185
-
186
- const whitespaceResults = await minimem.search(" ");
187
- assert.deepEqual(whitespaceResults, [], "Whitespace query should return empty results");
188
- });
189
-
190
- it("syncs new files when sync is called", async () => {
191
- // Add a new file
192
- await fs.writeFile(
193
- path.join(tempDir, "memory", "2024-01-17.md"),
194
- `# Daily Log - 2024-01-17
195
-
196
- ## New Feature
197
- Implemented the epsilon feature for the gamma module.
198
- This was an urgent request from the product team.
199
- `
200
- );
201
-
202
- // Force sync
203
- await minimem.sync({ force: true });
204
-
205
- // Search for new content
206
- const results = await minimem.search("epsilon gamma urgent feature");
207
-
208
- assert.ok(results.length > 0, "Expected to find newly synced content");
209
- const hasNewContent = results.some(r =>
210
- r.snippet.toLowerCase().includes("epsilon") ||
211
- r.snippet.toLowerCase().includes("gamma")
212
- );
213
- assert.ok(hasNewContent, "Expected to find epsilon/gamma content from new file");
214
- });
215
-
216
- it("removes stale entries when files are deleted", async () => {
217
- // Delete the file we just added
218
- await fs.rm(path.join(tempDir, "memory", "2024-01-17.md"));
219
-
220
- // Force sync
221
- await minimem.sync({ force: true });
222
-
223
- // The epsilon/gamma content should be gone or ranked lower
224
- const results = await minimem.search("epsilon gamma urgent");
225
-
226
- // Either no results or none containing epsilon
227
- const hasEpsilon = results.some(r => r.snippet.toLowerCase().includes("epsilon"));
228
- assert.ok(!hasEpsilon, "Deleted file content should not appear in results");
229
- });
230
-
231
- it("caches embeddings for repeated content", async () => {
232
- const initialCallCount = mockFetch.mock.callCount();
233
-
234
- // Search twice with same query
235
- await minimem.search("database connection");
236
- await minimem.search("database connection");
237
-
238
- const finalCallCount = mockFetch.mock.callCount();
239
-
240
- // Second search should use cached query embedding
241
- // (may still make 1 call for query, but not re-embed all chunks)
242
- assert.ok(
243
- finalCallCount - initialCallCount <= 2,
244
- "Expected caching to reduce API calls"
245
- );
246
- });
247
- });
248
-
249
- describe("Minimem File Operations", () => {
250
- let tempDir: string;
251
- let minimem: Minimem;
252
- let originalFetch: typeof fetch;
253
-
254
- before(async () => {
255
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-files-"));
256
- await fs.mkdir(path.join(tempDir, "memory"));
257
-
258
- originalFetch = globalThis.fetch;
259
- globalThis.fetch = createMockFetch() as unknown as typeof fetch;
260
- process.env.OPENAI_API_KEY = "test-key";
261
-
262
- minimem = await Minimem.create({
263
- memoryDir: tempDir,
264
- embedding: { provider: "openai" },
265
- watch: { enabled: false },
266
- });
267
- });
268
-
269
- after(async () => {
270
- minimem?.close();
271
- globalThis.fetch = originalFetch;
272
- delete process.env.OPENAI_API_KEY;
273
- await fs.rm(tempDir, { recursive: true, force: true });
274
- });
275
-
276
- it("lists memory files", async () => {
277
- await fs.writeFile(path.join(tempDir, "MEMORY.md"), "# Test");
278
- await fs.writeFile(path.join(tempDir, "memory", "note.md"), "# Note");
279
-
280
- const files = await minimem.listFiles();
281
-
282
- assert.ok(files.includes("MEMORY.md"), "Should list MEMORY.md");
283
- assert.ok(files.some(f => f.includes("note.md")), "Should list note.md");
284
- });
285
-
286
- it("reads file content", async () => {
287
- await fs.writeFile(path.join(tempDir, "MEMORY.md"), "Line 1\nLine 2\nLine 3");
288
-
289
- const content = await minimem.readFile("MEMORY.md");
290
-
291
- assert.equal(content, "Line 1\nLine 2\nLine 3");
292
- });
293
-
294
- it("reads specific lines", async () => {
295
- await fs.writeFile(
296
- path.join(tempDir, "MEMORY.md"),
297
- "Line 1\nLine 2\nLine 3\nLine 4\nLine 5"
298
- );
299
-
300
- const result = await minimem.readLines("MEMORY.md", { from: 2, lines: 2 });
301
-
302
- assert.ok(result !== null);
303
- assert.equal(result.content, "Line 2\nLine 3");
304
- assert.equal(result.startLine, 2);
305
- assert.equal(result.endLine, 3);
306
- });
307
-
308
- it("writes new file", async () => {
309
- await minimem.writeFile("memory/new-file.md", "# New Content\nTest");
310
-
311
- const content = await fs.readFile(
312
- path.join(tempDir, "memory", "new-file.md"),
313
- "utf-8"
314
- );
315
- assert.equal(content, "# New Content\nTest");
316
- });
317
-
318
- it("appends to existing file", async () => {
319
- await fs.writeFile(path.join(tempDir, "memory", "append.md"), "First line");
320
-
321
- await minimem.appendFile("memory/append.md", "Second line");
322
-
323
- const content = await fs.readFile(
324
- path.join(tempDir, "memory", "append.md"),
325
- "utf-8"
326
- );
327
- assert.ok(content.includes("First line"));
328
- assert.ok(content.includes("Second line"));
329
- });
330
-
331
- it("appends to today's log", async () => {
332
- const today = new Date().toISOString().split("T")[0];
333
-
334
- const resultPath = await minimem.appendToday("Today's note");
335
-
336
- assert.equal(resultPath, `memory/${today}.md`);
337
-
338
- const content = await fs.readFile(
339
- path.join(tempDir, `memory/${today}.md`),
340
- "utf-8"
341
- );
342
- assert.ok(content.includes("Today's note"));
343
- });
344
-
345
- it("rejects invalid memory paths", async () => {
346
- await assert.rejects(
347
- () => minimem.writeFile("../outside.md", "content"),
348
- /Invalid memory path/
349
- );
350
-
351
- await assert.rejects(
352
- () => minimem.writeFile("src/code.ts", "content"),
353
- /Invalid memory path/
354
- );
355
- });
356
- });
357
-
358
- describe("Minimem BM25-Only Mode", () => {
359
- let tempDir: string;
360
- let minimem: Minimem;
361
-
362
- before(async () => {
363
- // Create temp directory
364
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-bm25-"));
365
- await fs.mkdir(path.join(tempDir, "memory"));
366
-
367
- // Create test memory files with distinct keywords
368
- await fs.writeFile(
369
- path.join(tempDir, "MEMORY.md"),
370
- `# Memory
371
-
372
- ## Database Decisions
373
- We chose PostgreSQL for the main database.
374
- SQLite is used for local development.
375
- Redis handles caching requirements.
376
-
377
- ## API Architecture
378
- REST endpoints for external clients.
379
- GraphQL for internal microservices.
380
- WebSocket connections for real-time features.
381
- `
382
- );
383
-
384
- await fs.writeFile(
385
- path.join(tempDir, "memory", "meetings.md"),
386
- `# Meeting Notes
387
-
388
- ## Sprint Planning
389
- Discussed authentication requirements.
390
- JWT tokens will be used for API authentication.
391
- OAuth integration for third-party login.
392
-
393
- ## Design Review
394
- Reviewed the dashboard wireframes.
395
- Mobile-first approach approved.
396
- Accessibility requirements confirmed.
397
- `
398
- );
399
-
400
- await fs.writeFile(
401
- path.join(tempDir, "memory", "bugs.md"),
402
- `# Bug Tracker
403
-
404
- ## Critical Issues
405
- Memory leak in connection pooling.
406
- Fixed by properly closing database handles.
407
-
408
- ## Performance
409
- Slow queries on user search.
410
- Added index on email column.
411
- Response time improved by 80%.
412
- `
413
- );
414
-
415
- // Ensure no API keys are set for this test
416
- delete process.env.OPENAI_API_KEY;
417
- delete process.env.GOOGLE_API_KEY;
418
- delete process.env.GEMINI_API_KEY;
419
-
420
- // Create Minimem instance with explicit "none" provider (BM25-only)
421
- minimem = await Minimem.create({
422
- memoryDir: tempDir,
423
- embedding: {
424
- provider: "none",
425
- },
426
- watch: { enabled: false },
427
- hybrid: { enabled: true },
428
- query: { minScore: 0.0 },
429
- });
430
- });
431
-
432
- after(async () => {
433
- minimem?.close();
434
- await fs.rm(tempDir, { recursive: true, force: true });
435
- });
436
-
437
- it("creates instance in BM25-only mode", async () => {
438
- const status = await minimem.status();
439
-
440
- assert.equal(status.provider, "none");
441
- assert.equal(status.model, "bm25-only");
442
- assert.equal(status.bm25Only, true);
443
- assert.equal(status.ftsAvailable, true);
444
- });
445
-
446
- it("indexes files without embeddings", async () => {
447
- await minimem.sync();
448
-
449
- const status = await minimem.status();
450
-
451
- assert.ok(status.fileCount >= 3, `Expected at least 3 files, got ${status.fileCount}`);
452
- assert.ok(status.chunkCount > 0, `Expected chunks, got ${status.chunkCount}`);
453
- });
454
-
455
- it("finds results for 'PostgreSQL database'", async () => {
456
- const results = await minimem.search("PostgreSQL database");
457
-
458
- assert.ok(results.length > 0, "Expected search results for 'PostgreSQL database'");
459
-
460
- // Should find the database decisions section
461
- const hasPostgres = results.some(r =>
462
- r.snippet.toLowerCase().includes("postgresql")
463
- );
464
- assert.ok(hasPostgres, "Expected to find PostgreSQL in results");
465
- });
466
-
467
- it("finds results for 'authentication JWT'", async () => {
468
- const results = await minimem.search("authentication JWT tokens");
469
-
470
- assert.ok(results.length > 0, "Expected search results for 'authentication JWT'");
471
-
472
- // Should find the meeting notes about authentication
473
- const hasAuth = results.some(r =>
474
- r.snippet.toLowerCase().includes("jwt") ||
475
- r.snippet.toLowerCase().includes("authentication")
476
- );
477
- assert.ok(hasAuth, "Expected to find JWT/authentication in results");
478
- });
479
-
480
- it("finds results for 'connection pooling'", async () => {
481
- const results = await minimem.search("connection pooling");
482
-
483
- assert.ok(results.length > 0, "Expected search results for 'connection pooling'");
484
-
485
- // Should find the bug tracker content
486
- const hasBug = results.some(r =>
487
- r.snippet.toLowerCase().includes("connection") ||
488
- r.snippet.toLowerCase().includes("pooling")
489
- );
490
- assert.ok(hasBug, "Expected to find connection/pooling in results");
491
- });
492
-
493
- it("returns no results for non-existent terms", async () => {
494
- const results = await minimem.search("xyzzy quantum blockchain cryptocurrency");
495
-
496
- // Should have no or very low scoring results
497
- const highScoreResults = results.filter(r => r.score > 0.3);
498
- assert.equal(highScoreResults.length, 0, "Expected no high-scoring results for nonsense query");
499
- });
500
-
501
- it("respects maxResults parameter", async () => {
502
- const results = await minimem.search("database API", { maxResults: 2 });
503
-
504
- assert.ok(results.length <= 2, `Expected at most 2 results, got ${results.length}`);
505
- });
506
-
507
- it("syncs new files correctly", async () => {
508
- // Add a new file
509
- await fs.writeFile(
510
- path.join(tempDir, "memory", "deployment.md"),
511
- `# Deployment Guide
512
-
513
- ## Production Setup
514
- Kubernetes cluster configuration.
515
- Docker images pushed to ECR registry.
516
- Terraform manages infrastructure.
517
- `
518
- );
519
-
520
- await minimem.sync({ force: true });
521
-
522
- // Search for new content
523
- const results = await minimem.search("Kubernetes Docker deployment");
524
-
525
- assert.ok(results.length > 0, "Expected to find newly synced content");
526
- const hasDeployment = results.some(r =>
527
- r.snippet.toLowerCase().includes("kubernetes") ||
528
- r.snippet.toLowerCase().includes("docker")
529
- );
530
- assert.ok(hasDeployment, "Expected to find Kubernetes/Docker content");
531
- });
532
-
533
- it("removes deleted files from index", async () => {
534
- // Delete the deployment file
535
- await fs.rm(path.join(tempDir, "memory", "deployment.md"));
536
-
537
- await minimem.sync({ force: true });
538
-
539
- // Search for deleted content
540
- const results = await minimem.search("Kubernetes Docker Terraform");
541
-
542
- // Should not find the deleted content
543
- const hasKubernetes = results.some(r =>
544
- r.snippet.toLowerCase().includes("kubernetes")
545
- );
546
- assert.ok(!hasKubernetes, "Deleted file content should not appear in results");
547
- });
548
- });
549
-
550
- describe("Minimem Auto-Fallback to BM25", () => {
551
- let tempDir: string;
552
- let minimem: Minimem;
553
-
554
- before(async () => {
555
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-autobm25-"));
556
- await fs.mkdir(path.join(tempDir, "memory"));
557
-
558
- await fs.writeFile(
559
- path.join(tempDir, "MEMORY.md"),
560
- `# Test Memory
561
- Important notes about the project.
562
- Database uses PostgreSQL.
563
- `
564
- );
565
-
566
- // Ensure no API keys
567
- delete process.env.OPENAI_API_KEY;
568
- delete process.env.GOOGLE_API_KEY;
569
- delete process.env.GEMINI_API_KEY;
570
-
571
- // Use "auto" provider - should fall back to BM25-only
572
- minimem = await Minimem.create({
573
- memoryDir: tempDir,
574
- embedding: {
575
- provider: "auto",
576
- },
577
- watch: { enabled: false },
578
- hybrid: { enabled: true },
579
- });
580
- });
581
-
582
- after(async () => {
583
- minimem?.close();
584
- await fs.rm(tempDir, { recursive: true, force: true });
585
- });
586
-
587
- it("auto-falls back to BM25-only when no API keys available", async () => {
588
- const status = await minimem.status();
589
-
590
- assert.equal(status.provider, "none");
591
- assert.equal(status.bm25Only, true);
592
- assert.ok(status.fallbackReason?.includes("BM25"), "Should have fallback reason");
593
- });
594
-
595
- it("search still works in auto-fallback mode", async () => {
596
- await minimem.sync();
597
-
598
- const results = await minimem.search("PostgreSQL database");
599
-
600
- assert.ok(results.length > 0, "Expected search results");
601
- const hasDb = results.some(r =>
602
- r.snippet.toLowerCase().includes("postgresql") ||
603
- r.snippet.toLowerCase().includes("database")
604
- );
605
- assert.ok(hasDb, "Expected to find PostgreSQL/database in results");
606
- });
607
- });
608
-
609
- describe("Minimem Staleness Detection", () => {
610
- let tempDir: string;
611
- let minimem: Minimem;
612
- let originalFetch: typeof global.fetch;
613
-
614
- before(async () => {
615
- originalFetch = global.fetch;
616
- global.fetch = createMockFetch() as unknown as typeof global.fetch;
617
-
618
- // Set fake API key (required by provider validation)
619
- process.env.OPENAI_API_KEY = "test-api-key-for-staleness-tests";
620
-
621
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-stale-test-"));
622
-
623
- await fs.writeFile(
624
- path.join(tempDir, "MEMORY.md"),
625
- "# Original Content\n\nThis is the original memory content."
626
- );
627
-
628
- // Create with watch disabled - this is the scenario we're testing
629
- minimem = await Minimem.create({
630
- memoryDir: tempDir,
631
- embedding: { provider: "openai" },
632
- watch: { enabled: false },
633
- hybrid: { enabled: true },
634
- query: { minScore: 0.0 }, // Lower threshold for testing
635
- });
636
-
637
- // Initial sync
638
- await minimem.sync();
639
- });
640
-
641
- after(async () => {
642
- global.fetch = originalFetch;
643
- delete process.env.OPENAI_API_KEY;
644
- minimem?.close();
645
- await fs.rm(tempDir, { recursive: true, force: true });
646
- });
647
-
648
- it("detects modified files without watcher", async () => {
649
- // First search - should find original content
650
- const results1 = await minimem.search("original content");
651
- assert.ok(results1.length > 0, "Should find original content");
652
-
653
- // Modify the file externally (simulating user edit)
654
- await fs.writeFile(
655
- path.join(tempDir, "MEMORY.md"),
656
- "# Updated Content\n\nThis is completely new modified content about bananas."
657
- );
658
-
659
- // Search again - should detect staleness and re-sync
660
- const results2 = await minimem.search("bananas");
661
- assert.ok(results2.length > 0, "Should find new content after mtime-based staleness detection");
662
- const hasBananas = results2.some(r => r.snippet.toLowerCase().includes("banana"));
663
- assert.ok(hasBananas, "Should have indexed the new content");
664
- });
665
-
666
- it("detects new files without watcher", async () => {
667
- // Add a new file
668
- await fs.mkdir(path.join(tempDir, "memory"), { recursive: true });
669
- await fs.writeFile(
670
- path.join(tempDir, "memory", "new-topic.md"),
671
- "# New Topic\n\nThis document discusses elephants and their habitats."
672
- );
673
-
674
- // Search - should detect the new file and sync
675
- const results = await minimem.search("elephants habitats");
676
- assert.ok(results.length > 0, "Should find content from new file");
677
- const hasElephants = results.some(r => r.snippet.toLowerCase().includes("elephant"));
678
- assert.ok(hasElephants, "Should have indexed the new file");
679
- });
680
-
681
- it("detects deleted files without watcher", async () => {
682
- // Delete the file we just created
683
- await fs.rm(path.join(tempDir, "memory", "new-topic.md"));
684
-
685
- // Search - should detect the deletion and re-sync
686
- const results = await minimem.search("elephants");
687
-
688
- // After re-sync, the deleted content should no longer be found
689
- // (or have lower relevance since it's not in the index anymore)
690
- const hasElephants = results.some(r => r.snippet.toLowerCase().includes("elephant"));
691
- assert.ok(!hasElephants, "Should not find content from deleted file after staleness detection");
692
- });
693
- });
694
-
695
- describe("Minimem Type Filtering", () => {
696
- let tempDir: string;
697
- let minimem: Minimem;
698
- let originalFetch: typeof global.fetch;
699
-
700
- before(async () => {
701
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-type-filter-"));
702
- await fs.mkdir(path.join(tempDir, "memory"));
703
-
704
- // Create memory files with different observation types
705
- await fs.writeFile(
706
- path.join(tempDir, "MEMORY.md"),
707
- `# Memory
708
-
709
- ## API Design Decision
710
- <!-- type: decision -->
711
- We decided to use REST for external APIs and GraphQL for internal services.
712
- Authentication will use JWT tokens.
713
-
714
- ## General Notes
715
- Some general project notes without a type tag.
716
- The project uses TypeScript and Node.js.
717
- `
718
- );
719
-
720
- await fs.writeFile(
721
- path.join(tempDir, "memory", "bugs.md"),
722
- `# Bug Tracker
723
-
724
- ## Login Bug
725
- <!-- type: bugfix -->
726
- Fixed critical login failure caused by expired JWT token not being refreshed.
727
- Root cause was missing refresh token rotation logic.
728
-
729
- ## Dashboard Crash
730
- <!-- type: bugfix -->
731
- Fixed dashboard crash when user had no recent activity.
732
- Added null check for empty activity arrays.
733
- `
734
- );
735
-
736
- await fs.writeFile(
737
- path.join(tempDir, "memory", "features.md"),
738
- `# Features
739
-
740
- ## Search Feature
741
- <!-- type: feature -->
742
- Implemented full-text search with BM25 ranking.
743
- Users can now search across all memory files.
744
-
745
- ## Export Feature
746
- <!-- type: feature -->
747
- Added CSV and JSON export for memory entries.
748
- `
749
- );
750
-
751
- originalFetch = global.fetch;
752
- global.fetch = createMockFetch() as unknown as typeof global.fetch;
753
- process.env.OPENAI_API_KEY = "test-key-type-filter";
754
-
755
- minimem = await Minimem.create({
756
- memoryDir: tempDir,
757
- embedding: { provider: "openai" },
758
- watch: { enabled: false },
759
- hybrid: { enabled: true },
760
- query: { minScore: 0.0 },
761
- });
762
-
763
- await minimem.sync();
764
- });
765
-
766
- after(async () => {
767
- minimem?.close();
768
- global.fetch = originalFetch;
769
- delete process.env.OPENAI_API_KEY;
770
- await fs.rm(tempDir, { recursive: true, force: true });
771
- });
772
-
773
- it("returns all results when no type filter is specified", async () => {
774
- const results = await minimem.search("API login search export");
775
-
776
- assert.ok(results.length > 0, "Expected search results without type filter");
777
- });
778
-
779
- it("filters results by type: decision", async () => {
780
- const results = await minimem.search("API design REST GraphQL JWT", { type: "decision" });
781
-
782
- assert.ok(results.length > 0, "Expected decision results");
783
-
784
- // Every result should come from the decision chunk
785
- for (const r of results) {
786
- assert.ok(
787
- r.snippet.toLowerCase().includes("rest") ||
788
- r.snippet.toLowerCase().includes("graphql") ||
789
- r.snippet.toLowerCase().includes("decision") ||
790
- r.snippet.toLowerCase().includes("jwt"),
791
- `Decision result should contain relevant content, got: ${r.snippet.slice(0, 80)}`
792
- );
793
- }
794
- });
795
-
796
- it("filters results by type: bugfix", async () => {
797
- const results = await minimem.search("login crash bug fix", { type: "bugfix" });
798
-
799
- assert.ok(results.length > 0, "Expected bugfix results");
800
-
801
- // Should only find bug-related content
802
- const hasDecision = results.some(r =>
803
- r.snippet.toLowerCase().includes("rest for external apis")
804
- );
805
- assert.ok(!hasDecision, "Bugfix filter should not return decision content");
806
- });
807
-
808
- it("filters results by type: feature", async () => {
809
- const results = await minimem.search("search export feature", { type: "feature" });
810
-
811
- assert.ok(results.length > 0, "Expected feature results");
812
-
813
- // Should only find feature-related content
814
- const hasBugfix = results.some(r =>
815
- r.snippet.toLowerCase().includes("login failure") ||
816
- r.snippet.toLowerCase().includes("dashboard crash")
817
- );
818
- assert.ok(!hasBugfix, "Feature filter should not return bugfix content");
819
- });
820
-
821
- it("returns empty results for non-matching type filter", async () => {
822
- const results = await minimem.search("API design REST", { type: "discovery" });
823
-
824
- // Should have no results since nothing is tagged as "discovery"
825
- assert.equal(results.length, 0, "Expected no results for unused type");
826
- });
827
-
828
- it("type filter works with maxResults", async () => {
829
- const results = await minimem.search("bug fix crash login", {
830
- type: "bugfix",
831
- maxResults: 1,
832
- });
833
-
834
- assert.ok(results.length <= 1, `Expected at most 1 result, got ${results.length}`);
835
- });
836
- });
837
-
838
- describe("Minimem Privacy Tags", () => {
839
- let tempDir: string;
840
- let minimem: Minimem;
841
- let originalFetch: typeof global.fetch;
842
-
843
- before(async () => {
844
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-privacy-"));
845
- await fs.mkdir(path.join(tempDir, "memory"));
846
-
847
- // Create memory files with private content
848
- await fs.writeFile(
849
- path.join(tempDir, "MEMORY.md"),
850
- `# Memory
851
-
852
- ## API Configuration
853
- API endpoint: api.example.com/v2
854
- Rate limit: 1000 requests per minute
855
-
856
- <private>
857
- API_KEY=sk-secret-key-12345
858
- DB_PASSWORD=hunter2
859
- AWS_SECRET=AKIAIOSFODNN7EXAMPLE
860
- </private>
861
-
862
- ## Public Notes
863
- The API uses versioned endpoints.
864
- Documentation is at docs.example.com.
865
- `
866
- );
867
-
868
- await fs.writeFile(
869
- path.join(tempDir, "memory", "credentials.md"),
870
- `# Service Credentials
871
-
872
- ## Production Database
873
- Host: db.prod.example.com
874
- Port: 5432
875
-
876
- <private>
877
- username: admin
878
- password: super-secret-password-123
879
- connection_string: postgres://admin:super-secret-password-123@db.prod.example.com:5432/main
880
- </private>
881
-
882
- ## Staging Database
883
- Host: db.staging.example.com
884
- Port: 5432
885
- `
886
- );
887
-
888
- originalFetch = global.fetch;
889
- global.fetch = createMockFetch() as unknown as typeof global.fetch;
890
- process.env.OPENAI_API_KEY = "test-key-privacy";
891
-
892
- minimem = await Minimem.create({
893
- memoryDir: tempDir,
894
- embedding: { provider: "openai" },
895
- watch: { enabled: false },
896
- hybrid: { enabled: true },
897
- query: { minScore: 0.0 },
898
- });
899
-
900
- await minimem.sync();
901
- });
902
-
903
- after(async () => {
904
- minimem?.close();
905
- global.fetch = originalFetch;
906
- delete process.env.OPENAI_API_KEY;
907
- await fs.rm(tempDir, { recursive: true, force: true });
908
- });
909
-
910
- it("does not include private content in search snippets", async () => {
911
- const results = await minimem.search("API key password secret credentials");
912
-
913
- // Check that no snippet contains the actual secret values
914
- for (const r of results) {
915
- assert.ok(
916
- !r.snippet.includes("sk-secret-key-12345"),
917
- "Snippet should not contain API key"
918
- );
919
- assert.ok(
920
- !r.snippet.includes("hunter2"),
921
- "Snippet should not contain DB password"
922
- );
923
- assert.ok(
924
- !r.snippet.includes("super-secret-password-123"),
925
- "Snippet should not contain production password"
926
- );
927
- assert.ok(
928
- !r.snippet.includes("AKIAIOSFODNN7EXAMPLE"),
929
- "Snippet should not contain AWS secret"
930
- );
931
- }
932
- });
933
-
934
- it("still indexes non-private content from files with private blocks", async () => {
935
- const results = await minimem.search("API endpoint rate limit documentation");
936
-
937
- assert.ok(results.length > 0, "Expected to find non-private content");
938
-
939
- const hasPublic = results.some(r =>
940
- r.snippet.toLowerCase().includes("api endpoint") ||
941
- r.snippet.toLowerCase().includes("rate limit") ||
942
- r.snippet.toLowerCase().includes("documentation") ||
943
- r.snippet.toLowerCase().includes("api.example.com")
944
- );
945
- assert.ok(hasPublic, "Should find public content from files with private blocks");
946
- });
947
-
948
- it("indexes content around private blocks correctly", async () => {
949
- const results = await minimem.search("staging database host port");
950
-
951
- assert.ok(results.length > 0, "Expected to find staging database content");
952
-
953
- const hasStaging = results.some(r =>
954
- r.snippet.toLowerCase().includes("staging")
955
- );
956
- assert.ok(hasStaging, "Should find staging database content after private block");
957
- });
958
- });
959
-
960
- describe("Minimem Schema Migration", () => {
961
- let tempDir: string;
962
-
963
- before(async () => {
964
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "minimem-migration-"));
965
- });
966
-
967
- after(async () => {
968
- await fs.rm(tempDir, { recursive: true, force: true });
969
- });
970
-
971
- it("migrates from schema v2 to v3, preserving embedding cache", async () => {
972
- const { DatabaseSync } = await import("node:sqlite");
973
- const { ensureMemoryIndexSchema, SCHEMA_VERSION } = await import("../db/schema.js");
974
-
975
- const dbPath = path.join(tempDir, "migration-test.db");
976
- const db = new DatabaseSync(dbPath);
977
-
978
- // Set up a v2 database manually
979
- db.exec(`CREATE TABLE IF NOT EXISTS meta (key TEXT PRIMARY KEY, value TEXT NOT NULL)`);
980
- db.prepare(`INSERT OR REPLACE INTO meta (key, value) VALUES ('schema_version', '2')`).run();
981
-
982
- db.exec(`CREATE TABLE IF NOT EXISTS files (
983
- path TEXT PRIMARY KEY,
984
- source TEXT NOT NULL DEFAULT 'memory',
985
- hash TEXT NOT NULL,
986
- mtime INTEGER NOT NULL,
987
- size INTEGER NOT NULL
988
- )`);
989
- db.exec(`CREATE TABLE IF NOT EXISTS chunks (
990
- id TEXT PRIMARY KEY,
991
- path TEXT NOT NULL,
992
- source TEXT NOT NULL DEFAULT 'memory',
993
- start_line INTEGER NOT NULL,
994
- end_line INTEGER NOT NULL,
995
- hash TEXT NOT NULL,
996
- model TEXT NOT NULL,
997
- text TEXT NOT NULL,
998
- embedding TEXT NOT NULL,
999
- updated_at INTEGER NOT NULL
1000
- )`);
1001
-
1002
- // Insert some data to verify migration drops tables
1003
- db.prepare(`INSERT INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`)
1004
- .run("MEMORY.md", "memory", "abc123", 1000, 100);
1005
- db.prepare(`INSERT INTO chunks (id, path, source, start_line, end_line, hash, model, text, embedding, updated_at)
1006
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
1007
- .run("chunk1", "MEMORY.md", "memory", 1, 5, "hash1", "test", "text", "[]", 1000);
1008
-
1009
- // Create embedding cache with data that should be preserved
1010
- db.exec(`CREATE TABLE IF NOT EXISTS embedding_cache (
1011
- provider TEXT NOT NULL,
1012
- model TEXT NOT NULL,
1013
- provider_key TEXT NOT NULL,
1014
- hash TEXT NOT NULL,
1015
- embedding TEXT NOT NULL,
1016
- dims INTEGER,
1017
- updated_at INTEGER NOT NULL,
1018
- PRIMARY KEY (provider, model, provider_key, hash)
1019
- )`);
1020
- db.prepare(`INSERT INTO embedding_cache (provider, model, provider_key, hash, embedding, dims, updated_at)
1021
- VALUES (?, ?, ?, ?, ?, ?, ?)`)
1022
- .run("openai", "text-embedding-3-small", "key1", "cachehash1", "[0.1, 0.2]", 2, 2000);
1023
-
1024
- // Run migration by calling ensureMemoryIndexSchema
1025
- const result = ensureMemoryIndexSchema({
1026
- db,
1027
- embeddingCacheTable: "embedding_cache",
1028
- ftsTable: "chunks_fts",
1029
- ftsEnabled: true,
1030
- });
1031
-
1032
- // Verify migration occurred
1033
- assert.ok(result.migrated, "Migration should have been performed");
1034
-
1035
- // Verify schema version is now current
1036
- const versionRow = db.prepare(`SELECT value FROM meta WHERE key = 'schema_version'`).get() as { value: string };
1037
- assert.equal(versionRow.value, String(SCHEMA_VERSION), "Schema version should be updated");
1038
-
1039
- // Verify old data was dropped (tables recreated empty)
1040
- const fileCount = db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };
1041
- assert.equal(fileCount.count, 0, "Files table should be empty after migration");
1042
-
1043
- const chunkCount = db.prepare(`SELECT COUNT(*) as count FROM chunks`).get() as { count: number };
1044
- assert.equal(chunkCount.count, 0, "Chunks table should be empty after migration");
1045
-
1046
- // Verify embedding cache was preserved
1047
- const cacheCount = db.prepare(`SELECT COUNT(*) as count FROM embedding_cache`).get() as { count: number };
1048
- assert.equal(cacheCount.count, 1, "Embedding cache should be preserved after migration");
1049
-
1050
- const cacheRow = db.prepare(`SELECT hash, embedding FROM embedding_cache WHERE hash = ?`).get("cachehash1") as { hash: string; embedding: string } | undefined;
1051
- assert.ok(cacheRow, "Cached embedding should still exist");
1052
- assert.equal(cacheRow.embedding, "[0.1, 0.2]", "Cached embedding data should be intact");
1053
-
1054
- // Verify the type column exists on chunks table
1055
- const columns = db.prepare(`PRAGMA table_info(chunks)`).all() as Array<{ name: string }>;
1056
- const hasTypeColumn = columns.some(c => c.name === "type");
1057
- assert.ok(hasTypeColumn, "Chunks table should have 'type' column after migration");
1058
-
1059
- // Verify type index exists
1060
- const indexes = db.prepare(`PRAGMA index_list(chunks)`).all() as Array<{ name: string }>;
1061
- const hasTypeIndex = indexes.some(idx => idx.name === "idx_chunks_type");
1062
- assert.ok(hasTypeIndex, "Should have idx_chunks_type index after migration");
1063
-
1064
- db.close();
1065
- });
1066
-
1067
- it("fresh database (no prior version) does not trigger migration flag", async () => {
1068
- const { DatabaseSync } = await import("node:sqlite");
1069
- const { ensureMemoryIndexSchema } = await import("../db/schema.js");
1070
-
1071
- const dbPath = path.join(tempDir, "fresh-test.db");
1072
- const db = new DatabaseSync(dbPath);
1073
-
1074
- const result = ensureMemoryIndexSchema({
1075
- db,
1076
- embeddingCacheTable: "embedding_cache",
1077
- ftsTable: "chunks_fts",
1078
- ftsEnabled: true,
1079
- });
1080
-
1081
- // Fresh database should not report migration
1082
- assert.ok(!result.migrated, "Fresh database should not report migration");
1083
-
1084
- // But schema should be fully set up
1085
- const columns = db.prepare(`PRAGMA table_info(chunks)`).all() as Array<{ name: string }>;
1086
- const hasTypeColumn = columns.some(c => c.name === "type");
1087
- assert.ok(hasTypeColumn, "Fresh database should have 'type' column");
1088
-
1089
- db.close();
1090
- });
1091
-
1092
- it("same version does not re-migrate", async () => {
1093
- const { DatabaseSync } = await import("node:sqlite");
1094
- const { ensureMemoryIndexSchema, SCHEMA_VERSION } = await import("../db/schema.js");
1095
-
1096
- const dbPath = path.join(tempDir, "same-version-test.db");
1097
- const db = new DatabaseSync(dbPath);
1098
-
1099
- // First call sets up schema
1100
- ensureMemoryIndexSchema({
1101
- db,
1102
- embeddingCacheTable: "embedding_cache",
1103
- ftsTable: "chunks_fts",
1104
- ftsEnabled: true,
1105
- });
1106
-
1107
- // Insert some data
1108
- db.prepare(`INSERT INTO files (path, source, hash, mtime, size) VALUES (?, ?, ?, ?, ?)`)
1109
- .run("test.md", "memory", "hash", 1000, 50);
1110
-
1111
- // Second call should not drop data
1112
- const result = ensureMemoryIndexSchema({
1113
- db,
1114
- embeddingCacheTable: "embedding_cache",
1115
- ftsTable: "chunks_fts",
1116
- ftsEnabled: true,
1117
- });
1118
-
1119
- assert.ok(!result.migrated, "Same version should not trigger migration");
1120
-
1121
- // Data should still exist
1122
- const fileCount = db.prepare(`SELECT COUNT(*) as count FROM files`).get() as { count: number };
1123
- assert.equal(fileCount.count, 1, "Files should be preserved when no migration needed");
1124
-
1125
- db.close();
1126
- });
1127
- });