kynjal-cli 3.1.4 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. package/.claude/agents/core/coder.md +1 -1
  2. package/.claude/agents/core/planner.md +2 -2
  3. package/.claude/agents/core/researcher.md +1 -1
  4. package/.claude/agents/core/reviewer.md +1 -1
  5. package/.claude/agents/core/tester.md +1 -1
  6. package/.claude/agents/data/data-ml-model.md +4 -4
  7. package/.claude/agents/development/dev-backend-api.md +4 -4
  8. package/.claude/agents/documentation/docs-api-openapi.md +4 -4
  9. package/.claude/agents/github/code-review-swarm.md +2 -2
  10. package/.claude/agents/github/issue-tracker.md +2 -2
  11. package/.claude/agents/github/pr-manager.md +2 -2
  12. package/.claude/agents/github/release-manager.md +2 -2
  13. package/.claude/agents/github/workflow-automation.md +2 -2
  14. package/.claude/agents/sparc/architecture.md +3 -3
  15. package/.claude/agents/sparc/pseudocode.md +2 -2
  16. package/.claude/agents/sparc/refinement.md +3 -3
  17. package/.claude/agents/sparc/specification.md +2 -2
  18. package/.claude/agents/swarm/adaptive-coordinator.md +1 -1
  19. package/.claude/agents/swarm/hierarchical-coordinator.md +1 -1
  20. package/.claude/agents/swarm/mesh-coordinator.md +1 -1
  21. package/.claude/agents/templates/base-template-generator.md +25 -4
  22. package/.claude/agents/templates/sparc-coordinator.md +3 -3
  23. package/.claude/helpers/auto-commit.sh +1 -1
  24. package/.claude/helpers/auto-memory-hook.mjs +27 -9
  25. package/.claude/helpers/hook-handler.cjs +58 -18
  26. package/.claude/helpers/statusline.cjs +420 -613
  27. package/.claude/helpers/statusline.js +3 -3
  28. package/.claude/settings.json +9 -9
  29. package/.claude/skills/reasoningbank-intelligence/SKILL.md +2 -2
  30. package/.claude/skills/swarm-orchestration/SKILL.md +1 -1
  31. package/README.md +383 -170
  32. package/bin/cli.js +6 -6
  33. package/bin/mcp-server.js +1 -1
  34. package/bin/preinstall.cjs +2 -0
  35. package/dist/src/appliance/gguf-engine.d.ts +91 -0
  36. package/dist/src/appliance/gguf-engine.d.ts.map +1 -0
  37. package/dist/src/appliance/gguf-engine.js +425 -0
  38. package/dist/src/appliance/gguf-engine.js.map +1 -0
  39. package/dist/src/appliance/ruvllm-bridge.d.ts +102 -0
  40. package/dist/src/appliance/ruvllm-bridge.d.ts.map +1 -0
  41. package/dist/src/appliance/ruvllm-bridge.js +292 -0
  42. package/dist/src/appliance/ruvllm-bridge.js.map +1 -0
  43. package/dist/src/appliance/rvfa-builder.d.ts +44 -0
  44. package/dist/src/appliance/rvfa-builder.d.ts.map +1 -0
  45. package/dist/src/appliance/rvfa-builder.js +329 -0
  46. package/dist/src/appliance/rvfa-builder.js.map +1 -0
  47. package/dist/src/appliance/rvfa-distribution.d.ts +97 -0
  48. package/dist/src/appliance/rvfa-distribution.d.ts.map +1 -0
  49. package/dist/src/appliance/rvfa-distribution.js +370 -0
  50. package/dist/src/appliance/rvfa-distribution.js.map +1 -0
  51. package/dist/src/appliance/rvfa-format.d.ts +111 -0
  52. package/dist/src/appliance/rvfa-format.d.ts.map +1 -0
  53. package/dist/src/appliance/rvfa-format.js +393 -0
  54. package/dist/src/appliance/rvfa-format.js.map +1 -0
  55. package/dist/src/appliance/rvfa-runner.d.ts +69 -0
  56. package/dist/src/appliance/rvfa-runner.d.ts.map +1 -0
  57. package/dist/src/appliance/rvfa-runner.js +237 -0
  58. package/dist/src/appliance/rvfa-runner.js.map +1 -0
  59. package/dist/src/appliance/rvfa-signing.d.ts +123 -0
  60. package/dist/src/appliance/rvfa-signing.d.ts.map +1 -0
  61. package/dist/src/appliance/rvfa-signing.js +347 -0
  62. package/dist/src/appliance/rvfa-signing.js.map +1 -0
  63. package/dist/src/commands/agent.d.ts.map +1 -1
  64. package/dist/src/commands/agent.js +121 -21
  65. package/dist/src/commands/agent.js.map +1 -1
  66. package/dist/src/commands/appliance-advanced.d.ts +9 -0
  67. package/dist/src/commands/appliance-advanced.d.ts.map +1 -0
  68. package/dist/src/commands/appliance-advanced.js +215 -0
  69. package/dist/src/commands/appliance-advanced.js.map +1 -0
  70. package/dist/src/commands/appliance.d.ts +8 -0
  71. package/dist/src/commands/appliance.d.ts.map +1 -0
  72. package/dist/src/commands/appliance.js +406 -0
  73. package/dist/src/commands/appliance.js.map +1 -0
  74. package/dist/src/commands/benchmark.js +2 -2
  75. package/dist/src/commands/benchmark.js.map +1 -1
  76. package/dist/src/commands/claims.js +1 -1
  77. package/dist/src/commands/claims.js.map +1 -1
  78. package/dist/src/commands/cleanup.d.ts +13 -0
  79. package/dist/src/commands/cleanup.d.ts.map +1 -0
  80. package/dist/src/commands/cleanup.js +218 -0
  81. package/dist/src/commands/cleanup.js.map +1 -0
  82. package/dist/src/commands/config.js +1 -1
  83. package/dist/src/commands/config.js.map +1 -1
  84. package/dist/src/commands/daemon.d.ts.map +1 -1
  85. package/dist/src/commands/daemon.js +81 -18
  86. package/dist/src/commands/daemon.js.map +1 -1
  87. package/dist/src/commands/deployment.js +1 -1
  88. package/dist/src/commands/deployment.js.map +1 -1
  89. package/dist/src/commands/doctor.d.ts.map +1 -1
  90. package/dist/src/commands/doctor.js +99 -51
  91. package/dist/src/commands/doctor.js.map +1 -1
  92. package/dist/src/commands/embeddings.js +1 -1
  93. package/dist/src/commands/embeddings.js.map +1 -1
  94. package/dist/src/commands/hive-mind.js +26 -26
  95. package/dist/src/commands/hive-mind.js.map +1 -1
  96. package/dist/src/commands/hooks.d.ts.map +1 -1
  97. package/dist/src/commands/hooks.js +800 -100
  98. package/dist/src/commands/hooks.js.map +1 -1
  99. package/dist/src/commands/index.d.ts +9 -2
  100. package/dist/src/commands/index.d.ts.map +1 -1
  101. package/dist/src/commands/index.js +20 -2
  102. package/dist/src/commands/index.js.map +1 -1
  103. package/dist/src/commands/init.d.ts +1 -1
  104. package/dist/src/commands/init.d.ts.map +1 -1
  105. package/dist/src/commands/init.js +22 -18
  106. package/dist/src/commands/init.js.map +1 -1
  107. package/dist/src/commands/mcp.d.ts.map +1 -1
  108. package/dist/src/commands/mcp.js +23 -5
  109. package/dist/src/commands/mcp.js.map +1 -1
  110. package/dist/src/commands/memory.d.ts.map +1 -1
  111. package/dist/src/commands/memory.js +24 -0
  112. package/dist/src/commands/memory.js.map +1 -1
  113. package/dist/src/commands/neural.d.ts.map +1 -1
  114. package/dist/src/commands/neural.js +13 -7
  115. package/dist/src/commands/neural.js.map +1 -1
  116. package/dist/src/commands/performance.js +1 -1
  117. package/dist/src/commands/performance.js.map +1 -1
  118. package/dist/src/commands/plugins.js +1 -1
  119. package/dist/src/commands/plugins.js.map +1 -1
  120. package/dist/src/commands/providers.js +1 -1
  121. package/dist/src/commands/providers.js.map +1 -1
  122. package/dist/src/commands/ruvector/import.js +2 -2
  123. package/dist/src/commands/ruvector/import.js.map +1 -1
  124. package/dist/src/commands/ruvector/index.js +1 -1
  125. package/dist/src/commands/ruvector/index.js.map +1 -1
  126. package/dist/src/commands/ruvector/setup.js +6 -6
  127. package/dist/src/commands/security.d.ts.map +1 -1
  128. package/dist/src/commands/security.js +47 -16
  129. package/dist/src/commands/security.js.map +1 -1
  130. package/dist/src/commands/session.d.ts +1 -1
  131. package/dist/src/commands/session.js +1 -1
  132. package/dist/src/commands/start.d.ts +1 -1
  133. package/dist/src/commands/start.js +12 -12
  134. package/dist/src/commands/start.js.map +1 -1
  135. package/dist/src/commands/status.d.ts +1 -1
  136. package/dist/src/commands/status.d.ts.map +1 -1
  137. package/dist/src/commands/status.js +13 -6
  138. package/dist/src/commands/status.js.map +1 -1
  139. package/dist/src/commands/swarm.js +2 -2
  140. package/dist/src/commands/swarm.js.map +1 -1
  141. package/dist/src/commands/task.d.ts +1 -1
  142. package/dist/src/commands/task.js +1 -1
  143. package/dist/src/commands/transfer-store.js +1 -1
  144. package/dist/src/commands/transfer-store.js.map +1 -1
  145. package/dist/src/config-adapter.js +1 -1
  146. package/dist/src/config-adapter.js.map +1 -1
  147. package/dist/src/index.d.ts +4 -3
  148. package/dist/src/index.d.ts.map +1 -1
  149. package/dist/src/index.js +5 -3
  150. package/dist/src/index.js.map +1 -1
  151. package/dist/src/init/claudemd-generator.js +30 -30
  152. package/dist/src/init/claudemd-generator.js.map +1 -1
  153. package/dist/src/init/executor.d.ts.map +1 -1
  154. package/dist/src/init/executor.js +86 -101
  155. package/dist/src/init/executor.js.map +1 -1
  156. package/dist/src/init/helpers-generator.d.ts.map +1 -1
  157. package/dist/src/init/helpers-generator.js +96 -26
  158. package/dist/src/init/helpers-generator.js.map +1 -1
  159. package/dist/src/init/mcp-generator.d.ts +0 -1
  160. package/dist/src/init/mcp-generator.d.ts.map +1 -1
  161. package/dist/src/init/mcp-generator.js +34 -18
  162. package/dist/src/init/mcp-generator.js.map +1 -1
  163. package/dist/src/init/settings-generator.d.ts.map +1 -1
  164. package/dist/src/init/settings-generator.js +107 -41
  165. package/dist/src/init/settings-generator.js.map +1 -1
  166. package/dist/src/init/statusline-generator.d.ts +16 -8
  167. package/dist/src/init/statusline-generator.d.ts.map +1 -1
  168. package/dist/src/init/statusline-generator.js +537 -1019
  169. package/dist/src/init/statusline-generator.js.map +1 -1
  170. package/dist/src/init/types.d.ts +14 -4
  171. package/dist/src/init/types.d.ts.map +1 -1
  172. package/dist/src/init/types.js +9 -2
  173. package/dist/src/init/types.js.map +1 -1
  174. package/dist/src/mcp-client.d.ts.map +1 -1
  175. package/dist/src/mcp-client.js +10 -0
  176. package/dist/src/mcp-client.js.map +1 -1
  177. package/dist/src/mcp-server.d.ts.map +1 -1
  178. package/dist/src/mcp-server.js +30 -4
  179. package/dist/src/mcp-server.js.map +1 -1
  180. package/dist/src/mcp-tools/agentdb-tools.d.ts +30 -0
  181. package/dist/src/mcp-tools/agentdb-tools.d.ts.map +1 -0
  182. package/dist/src/mcp-tools/agentdb-tools.js +557 -0
  183. package/dist/src/mcp-tools/agentdb-tools.js.map +1 -0
  184. package/dist/src/mcp-tools/browser-tools.js +2 -2
  185. package/dist/src/mcp-tools/browser-tools.js.map +1 -1
  186. package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
  187. package/dist/src/mcp-tools/config-tools.js +21 -2
  188. package/dist/src/mcp-tools/config-tools.js.map +1 -1
  189. package/dist/src/mcp-tools/coordination-tools.d.ts.map +1 -1
  190. package/dist/src/mcp-tools/coordination-tools.js +192 -13
  191. package/dist/src/mcp-tools/coordination-tools.js.map +1 -1
  192. package/dist/src/mcp-tools/daa-tools.js +5 -5
  193. package/dist/src/mcp-tools/daa-tools.js.map +1 -1
  194. package/dist/src/mcp-tools/github-tools.js +2 -2
  195. package/dist/src/mcp-tools/github-tools.js.map +1 -1
  196. package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -1
  197. package/dist/src/mcp-tools/hive-mind-tools.js +263 -35
  198. package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -1
  199. package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
  200. package/dist/src/mcp-tools/hooks-tools.js +355 -40
  201. package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
  202. package/dist/src/mcp-tools/index.d.ts +2 -0
  203. package/dist/src/mcp-tools/index.d.ts.map +1 -1
  204. package/dist/src/mcp-tools/index.js +2 -0
  205. package/dist/src/mcp-tools/index.js.map +1 -1
  206. package/dist/src/mcp-tools/memory-tools.d.ts.map +1 -1
  207. package/dist/src/mcp-tools/memory-tools.js +31 -1
  208. package/dist/src/mcp-tools/memory-tools.js.map +1 -1
  209. package/dist/src/mcp-tools/neural-tools.d.ts.map +1 -1
  210. package/dist/src/mcp-tools/neural-tools.js +32 -27
  211. package/dist/src/mcp-tools/neural-tools.js.map +1 -1
  212. package/dist/src/mcp-tools/performance-tools.js +1 -1
  213. package/dist/src/mcp-tools/performance-tools.js.map +1 -1
  214. package/dist/src/mcp-tools/ruvllm-tools.d.ts +9 -0
  215. package/dist/src/mcp-tools/ruvllm-tools.d.ts.map +1 -0
  216. package/dist/src/mcp-tools/ruvllm-tools.js +283 -0
  217. package/dist/src/mcp-tools/ruvllm-tools.js.map +1 -0
  218. package/dist/src/mcp-tools/swarm-tools.d.ts +2 -1
  219. package/dist/src/mcp-tools/swarm-tools.d.ts.map +1 -1
  220. package/dist/src/mcp-tools/swarm-tools.js +216 -30
  221. package/dist/src/mcp-tools/swarm-tools.js.map +1 -1
  222. package/dist/src/mcp-tools/system-tools.d.ts.map +1 -1
  223. package/dist/src/mcp-tools/system-tools.js +109 -6
  224. package/dist/src/mcp-tools/system-tools.js.map +1 -1
  225. package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
  226. package/dist/src/mcp-tools/task-tools.js +102 -0
  227. package/dist/src/mcp-tools/task-tools.js.map +1 -1
  228. package/dist/src/mcp-tools/wasm-agent-tools.d.ts +9 -0
  229. package/dist/src/mcp-tools/wasm-agent-tools.d.ts.map +1 -0
  230. package/dist/src/mcp-tools/wasm-agent-tools.js +230 -0
  231. package/dist/src/mcp-tools/wasm-agent-tools.js.map +1 -0
  232. package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -1
  233. package/dist/src/mcp-tools/workflow-tools.js +91 -0
  234. package/dist/src/mcp-tools/workflow-tools.js.map +1 -1
  235. package/dist/src/memory/ewc-consolidation.d.ts +24 -0
  236. package/dist/src/memory/ewc-consolidation.d.ts.map +1 -1
  237. package/dist/src/memory/ewc-consolidation.js +59 -0
  238. package/dist/src/memory/ewc-consolidation.js.map +1 -1
  239. package/dist/src/memory/intelligence.d.ts +53 -0
  240. package/dist/src/memory/intelligence.d.ts.map +1 -1
  241. package/dist/src/memory/intelligence.js +264 -7
  242. package/dist/src/memory/intelligence.js.map +1 -1
  243. package/dist/src/memory/memory-bridge.d.ts +407 -0
  244. package/dist/src/memory/memory-bridge.d.ts.map +1 -0
  245. package/dist/src/memory/memory-bridge.js +1494 -0
  246. package/dist/src/memory/memory-bridge.js.map +1 -0
  247. package/dist/src/memory/memory-initializer.d.ts +17 -1
  248. package/dist/src/memory/memory-initializer.d.ts.map +1 -1
  249. package/dist/src/memory/memory-initializer.js +320 -42
  250. package/dist/src/memory/memory-initializer.js.map +1 -1
  251. package/dist/src/output.d.ts.map +1 -1
  252. package/dist/src/output.js +1 -0
  253. package/dist/src/output.js.map +1 -1
  254. package/dist/src/parser.d.ts +10 -0
  255. package/dist/src/parser.d.ts.map +1 -1
  256. package/dist/src/parser.js +49 -3
  257. package/dist/src/parser.js.map +1 -1
  258. package/dist/src/plugins/manager.d.ts.map +1 -1
  259. package/dist/src/plugins/manager.js +31 -14
  260. package/dist/src/plugins/manager.js.map +1 -1
  261. package/dist/src/plugins/store/discovery.js +5 -5
  262. package/dist/src/plugins/store/discovery.js.map +1 -1
  263. package/dist/src/plugins/tests/standalone-test.js +4 -4
  264. package/dist/src/plugins/tests/standalone-test.js.map +1 -1
  265. package/dist/src/production/error-handler.js +1 -1
  266. package/dist/src/production/error-handler.js.map +1 -1
  267. package/dist/src/runtime/headless.d.ts +3 -3
  268. package/dist/src/runtime/headless.js +6 -6
  269. package/dist/src/runtime/headless.js.map +1 -1
  270. package/dist/src/ruvector/agent-wasm.d.ts +182 -0
  271. package/dist/src/ruvector/agent-wasm.d.ts.map +1 -0
  272. package/dist/src/ruvector/agent-wasm.js +316 -0
  273. package/dist/src/ruvector/agent-wasm.js.map +1 -0
  274. package/dist/src/ruvector/enhanced-model-router.d.ts.map +1 -1
  275. package/dist/src/ruvector/enhanced-model-router.js +25 -15
  276. package/dist/src/ruvector/enhanced-model-router.js.map +1 -1
  277. package/dist/src/ruvector/index.d.ts +7 -1
  278. package/dist/src/ruvector/index.d.ts.map +1 -1
  279. package/dist/src/ruvector/index.js +17 -1
  280. package/dist/src/ruvector/index.js.map +1 -1
  281. package/dist/src/ruvector/ruvllm-wasm.d.ts +179 -0
  282. package/dist/src/ruvector/ruvllm-wasm.d.ts.map +1 -0
  283. package/dist/src/ruvector/ruvllm-wasm.js +363 -0
  284. package/dist/src/ruvector/ruvllm-wasm.js.map +1 -0
  285. package/dist/src/services/agentic-flow-bridge.d.ts +50 -0
  286. package/dist/src/services/agentic-flow-bridge.d.ts.map +1 -0
  287. package/dist/src/services/agentic-flow-bridge.js +95 -0
  288. package/dist/src/services/agentic-flow-bridge.js.map +1 -0
  289. package/dist/src/services/claim-service.js +1 -1
  290. package/dist/src/services/claim-service.js.map +1 -1
  291. package/dist/src/services/container-worker-pool.d.ts.map +1 -1
  292. package/dist/src/services/container-worker-pool.js +3 -1
  293. package/dist/src/services/container-worker-pool.js.map +1 -1
  294. package/dist/src/services/index.d.ts +1 -1
  295. package/dist/src/services/index.d.ts.map +1 -1
  296. package/dist/src/services/registry-api.d.ts +1 -1
  297. package/dist/src/services/registry-api.js +1 -1
  298. package/dist/src/services/ruvector-training.d.ts +11 -2
  299. package/dist/src/services/ruvector-training.d.ts.map +1 -1
  300. package/dist/src/services/ruvector-training.js +233 -43
  301. package/dist/src/services/ruvector-training.js.map +1 -1
  302. package/dist/src/services/worker-daemon.d.ts +28 -3
  303. package/dist/src/services/worker-daemon.d.ts.map +1 -1
  304. package/dist/src/services/worker-daemon.js +156 -17
  305. package/dist/src/services/worker-daemon.js.map +1 -1
  306. package/dist/src/services/worker-queue.d.ts.map +1 -1
  307. package/dist/src/services/worker-queue.js +2 -0
  308. package/dist/src/services/worker-queue.js.map +1 -1
  309. package/dist/src/transfer/deploy-seraphine.d.ts +1 -1
  310. package/dist/src/transfer/deploy-seraphine.js +4 -4
  311. package/dist/src/transfer/deploy-seraphine.js.map +1 -1
  312. package/dist/src/transfer/ipfs/client.d.ts.map +1 -1
  313. package/dist/src/transfer/ipfs/client.js +8 -0
  314. package/dist/src/transfer/ipfs/client.js.map +1 -1
  315. package/dist/src/transfer/ipfs/upload.d.ts.map +1 -1
  316. package/dist/src/transfer/ipfs/upload.js +0 -2
  317. package/dist/src/transfer/ipfs/upload.js.map +1 -1
  318. package/dist/src/transfer/models/seraphine.d.ts +1 -1
  319. package/dist/src/transfer/models/seraphine.js +5 -5
  320. package/dist/src/transfer/models/seraphine.js.map +1 -1
  321. package/dist/src/transfer/serialization/cfp.d.ts +1 -1
  322. package/dist/src/transfer/serialization/cfp.d.ts.map +1 -1
  323. package/dist/src/transfer/serialization/cfp.js +9 -6
  324. package/dist/src/transfer/serialization/cfp.js.map +1 -1
  325. package/dist/src/transfer/storage/gcs.d.ts.map +1 -1
  326. package/dist/src/transfer/storage/gcs.js +71 -29
  327. package/dist/src/transfer/storage/gcs.js.map +1 -1
  328. package/dist/src/transfer/store/discovery.js +4 -4
  329. package/dist/src/transfer/store/discovery.js.map +1 -1
  330. package/dist/src/transfer/store/registry.js +1 -1
  331. package/dist/src/transfer/store/registry.js.map +1 -1
  332. package/dist/src/transfer/store/tests/standalone-test.js +4 -4
  333. package/dist/src/transfer/store/tests/standalone-test.js.map +1 -1
  334. package/dist/src/transfer/types.d.ts +1 -1
  335. package/dist/src/types.d.ts +1 -1
  336. package/dist/src/types.js +1 -1
  337. package/dist/src/update/validator.js +1 -1
  338. package/dist/src/update/validator.js.map +1 -1
  339. package/dist/tsconfig.tsbuildinfo +1 -1
  340. package/package.json +13 -10
  341. package/.claude/agents/custom/accessibility-auditor.yaml +0 -56
  342. package/.claude/agents/custom/design-architect.yaml +0 -48
  343. package/.claude/agents/custom/ui-developer.yaml +0 -46
  344. package/.claude/agents/custom/ux-researcher.yaml +0 -60
@@ -3,16 +3,35 @@
3
3
  * Properly initializes the memory database with sql.js (WASM SQLite)
4
4
  * Includes pattern tables, vector embeddings, migration state tracking
5
5
  *
6
+ * ADR-053: Routes through ControllerRegistry → AgentDB v3 when available,
7
+ * falls back to raw sql.js for backwards compatibility.
8
+ *
6
9
  * @module v3/cli/memory-initializer
7
10
  */
8
11
  import * as fs from 'fs';
9
12
  import * as path from 'path';
13
+ // ADR-053: Lazy import of AgentDB v3 bridge
14
+ let _bridge;
15
+ async function getBridge() {
16
+ if (_bridge === null)
17
+ return null;
18
+ if (_bridge)
19
+ return _bridge;
20
+ try {
21
+ _bridge = await import('./memory-bridge.js');
22
+ return _bridge;
23
+ }
24
+ catch {
25
+ _bridge = null;
26
+ return null;
27
+ }
28
+ }
10
29
  /**
11
30
  * Enhanced schema with pattern confidence, temporal decay, versioning
12
31
  * Vector embeddings enabled for semantic search
13
32
  */
14
33
  export const MEMORY_SCHEMA_V3 = `
15
- -- KynjalFlow V3 Memory Database
34
+ -- RuFlo V3 Memory Database
16
35
  -- Version: 3.0.0
17
36
  -- Features: Pattern learning, vector embeddings, temporal decay, migration tracking
18
37
 
@@ -452,6 +471,13 @@ function saveHNSWMetadata() {
452
471
  * Add entry to HNSW index (with automatic persistence)
453
472
  */
454
473
  export async function addToHNSWIndex(id, embedding, entry) {
474
+ // ADR-053: Try AgentDB v3 bridge first
475
+ const bridge = await getBridge();
476
+ if (bridge) {
477
+ const bridgeResult = await bridge.bridgeAddToHNSW(id, embedding, entry);
478
+ if (bridgeResult === true)
479
+ return true;
480
+ }
455
481
  const index = await getHNSWIndex({ dimensions: embedding.length });
456
482
  if (!index)
457
483
  return false;
@@ -475,6 +501,13 @@ export async function addToHNSWIndex(id, embedding, entry) {
475
501
  * Returns results sorted by similarity (highest first)
476
502
  */
477
503
  export async function searchHNSWIndex(queryEmbedding, options) {
504
+ // ADR-053: Try AgentDB v3 bridge first
505
+ const bridge = await getBridge();
506
+ if (bridge) {
507
+ const bridgeResult = await bridge.bridgeSearchHNSW(queryEmbedding, options);
508
+ if (bridgeResult)
509
+ return bridgeResult;
510
+ }
478
511
  const index = await getHNSWIndex({ dimensions: queryEmbedding.length });
479
512
  if (!index)
480
513
  return null;
@@ -517,6 +550,16 @@ export async function searchHNSWIndex(queryEmbedding, options) {
517
550
  * Get HNSW index status
518
551
  */
519
552
  export function getHNSWStatus() {
553
+ // ADR-053: If bridge was previously loaded, report availability
554
+ if (_bridge && _bridge !== null) {
555
+ // Bridge is loaded — HNSW-equivalent is available via AgentDB v3
556
+ return {
557
+ available: true,
558
+ initialized: true,
559
+ entryCount: hnswIndex?.entries.size ?? 0,
560
+ dimensions: hnswIndex?.dimensions ?? 384
561
+ };
562
+ }
520
563
  return {
521
564
  available: hnswIndex !== null,
522
565
  initialized: hnswIndex?.initialized ?? false,
@@ -530,6 +573,15 @@ export function getHNSWStatus() {
530
573
  export function clearHNSWIndex() {
531
574
  hnswIndex = null;
532
575
  }
576
+ /**
577
+ * Invalidate the in-memory HNSW cache so the next search rebuilds from DB.
578
+ * Call this after deleting entries that had embeddings to prevent ghost
579
+ * vectors from appearing in search results.
580
+ */
581
+ export function rebuildSearchIndex() {
582
+ hnswIndex = null;
583
+ hnswInitializing = false;
584
+ }
533
585
  // ============================================================================
534
586
  // INT8 VECTOR QUANTIZATION (4x memory reduction)
535
587
  // ============================================================================
@@ -871,6 +923,51 @@ export async function checkAndMigrateLegacy(options) {
871
923
  }
872
924
  return { needsMigration: false };
873
925
  }
926
+ /**
927
+ * ADR-053: Activate ControllerRegistry so AgentDB v3 controllers
928
+ * (ReasoningBank, SkillLibrary, ExplainableRecall, etc.) are instantiated.
929
+ *
930
+ * Uses the memory-bridge's getControllerRegistry() which lazily creates
931
+ * a singleton ControllerRegistry and initializes it with the given dbPath.
932
+ * After this call, all enabled controllers are ready for immediate use.
933
+ *
934
+ * Failures are isolated: if @claude-flow/memory or agentdb is not installed,
935
+ * this returns an empty result without throwing.
936
+ */
937
+ async function activateControllerRegistry(dbPath, verbose) {
938
+ const startTime = performance.now();
939
+ const activated = [];
940
+ const failed = [];
941
+ try {
942
+ const bridge = await getBridge();
943
+ if (!bridge) {
944
+ return { activated, failed, initTimeMs: performance.now() - startTime };
945
+ }
946
+ const registry = await bridge.getControllerRegistry(dbPath);
947
+ if (!registry) {
948
+ return { activated, failed, initTimeMs: performance.now() - startTime };
949
+ }
950
+ // Collect controller status from the registry
951
+ if (typeof registry.listControllers === 'function') {
952
+ const controllers = registry.listControllers();
953
+ for (const ctrl of controllers) {
954
+ if (ctrl.enabled) {
955
+ activated.push(ctrl.name);
956
+ }
957
+ else {
958
+ failed.push(ctrl.name);
959
+ }
960
+ }
961
+ }
962
+ if (verbose && activated.length > 0) {
963
+ console.log(`ControllerRegistry: ${activated.length} controllers activated`);
964
+ }
965
+ }
966
+ catch {
967
+ // ControllerRegistry activation is best-effort
968
+ }
969
+ return { activated, failed, initTimeMs: performance.now() - startTime };
970
+ }
874
971
  /**
875
972
  * Initialize the memory database properly using sql.js
876
973
  */
@@ -944,6 +1041,9 @@ export async function initializeMemoryDatabase(options) {
944
1041
  // Also create schema file for reference
945
1042
  const schemaPath = path.join(dbDir, 'schema.sql');
946
1043
  fs.writeFileSync(schemaPath, MEMORY_SCHEMA_V3 + '\n' + getInitialMetadata(backend));
1044
+ // ADR-053: Activate ControllerRegistry so controllers (ReasoningBank,
1045
+ // SkillLibrary, ExplainableRecall, etc.) are instantiated during init
1046
+ const controllerResult = await activateControllerRegistry(dbPath, verbose);
947
1047
  return {
948
1048
  success: true,
949
1049
  backend,
@@ -981,7 +1081,8 @@ export async function initializeMemoryDatabase(options) {
981
1081
  temporalDecay: true,
982
1082
  hnswIndexing: true,
983
1083
  migrationTracking: true
984
- }
1084
+ },
1085
+ controllers: controllerResult,
985
1086
  };
986
1087
  }
987
1088
  else {
@@ -1001,6 +1102,8 @@ export async function initializeMemoryDatabase(options) {
1001
1102
  sqliteHeader[26] = 0x20; // min embedded payload
1002
1103
  sqliteHeader[27] = 0x20; // leaf payload
1003
1104
  fs.writeFileSync(dbPath, sqliteHeader);
1105
+ // ADR-053: Activate ControllerRegistry even on fallback path
1106
+ const controllerResult = await activateControllerRegistry(dbPath, verbose);
1004
1107
  return {
1005
1108
  success: true,
1006
1109
  backend,
@@ -1024,7 +1127,8 @@ export async function initializeMemoryDatabase(options) {
1024
1127
  temporalDecay: true,
1025
1128
  hnswIndexing: true,
1026
1129
  migrationTracking: true
1027
- }
1130
+ },
1131
+ controllers: controllerResult,
1028
1132
  };
1029
1133
  }
1030
1134
  }
@@ -1154,6 +1258,21 @@ export async function loadEmbeddingModel(options) {
1154
1258
  loadTime: 0
1155
1259
  };
1156
1260
  }
1261
+ // ADR-053: Try AgentDB v3 bridge first
1262
+ const bridge = await getBridge();
1263
+ if (bridge) {
1264
+ const bridgeResult = await bridge.bridgeLoadEmbeddingModel();
1265
+ if (bridgeResult && bridgeResult.success) {
1266
+ // Mark local state as loaded too so subsequent calls use cache
1267
+ embeddingModelState = {
1268
+ loaded: true,
1269
+ model: null, // Bridge handles embedding
1270
+ tokenizer: null,
1271
+ dimensions: bridgeResult.dimensions
1272
+ };
1273
+ return bridgeResult;
1274
+ }
1275
+ }
1157
1276
  try {
1158
1277
  // Try to import @xenova/transformers for ONNX embeddings
1159
1278
  const transformers = await import('@xenova/transformers').catch(() => null);
@@ -1177,7 +1296,62 @@ export async function loadEmbeddingModel(options) {
1177
1296
  loadTime: Date.now() - startTime
1178
1297
  };
1179
1298
  }
1180
- // Fallback: Check for agentic-flow ONNX
1299
+ // Fallback: Check for agentic-flow ReasoningBank embeddings (v3)
1300
+ const reasoningBank = await import('agentic-flow/reasoningbank').catch(() => null);
1301
+ if (reasoningBank?.computeEmbedding) {
1302
+ if (verbose) {
1303
+ console.log('Loading agentic-flow ReasoningBank embedding model...');
1304
+ }
1305
+ embeddingModelState = {
1306
+ loaded: true,
1307
+ model: { embed: reasoningBank.computeEmbedding },
1308
+ tokenizer: null,
1309
+ dimensions: 768
1310
+ };
1311
+ return {
1312
+ success: true,
1313
+ dimensions: 768,
1314
+ modelName: 'agentic-flow/reasoningbank',
1315
+ loadTime: Date.now() - startTime
1316
+ };
1317
+ }
1318
+ // Fallback: Check for ruvector ONNX embedder (bundled MiniLM-L6-v2 since v0.2.15)
1319
+ // v0.2.16: LoRA B=0 fix makes AdaptiveEmbedder safe (identity when untrained)
1320
+ // Note: isReady() returns false until first embed() call (lazy init), so we
1321
+ // skip the isReady() gate and verify with a probe embed instead.
1322
+ const ruvector = await import('ruvector').catch(() => null);
1323
+ if (ruvector?.initOnnxEmbedder) {
1324
+ try {
1325
+ await ruvector.initOnnxEmbedder();
1326
+ // Fallback: OptimizedOnnxEmbedder (raw ONNX, lazy-inits on first embed)
1327
+ const onnxEmb = ruvector.getOptimizedOnnxEmbedder?.();
1328
+ if (onnxEmb?.embed) {
1329
+ // Probe embed to trigger lazy ONNX init and verify it works
1330
+ const probe = await onnxEmb.embed('test');
1331
+ if (probe && probe.length > 0 && (Array.isArray(probe) ? probe.some((v) => v !== 0) : true)) {
1332
+ if (verbose) {
1333
+ console.log(`Loading ruvector ONNX embedder (all-MiniLM-L6-v2, ${probe.length}d)...`);
1334
+ }
1335
+ embeddingModelState = {
1336
+ loaded: true,
1337
+ model: (text) => onnxEmb.embed(text),
1338
+ tokenizer: null,
1339
+ dimensions: probe.length || 384
1340
+ };
1341
+ return {
1342
+ success: true,
1343
+ dimensions: probe.length || 384,
1344
+ modelName: 'ruvector/onnx',
1345
+ loadTime: Date.now() - startTime
1346
+ };
1347
+ }
1348
+ }
1349
+ }
1350
+ catch {
1351
+ // ruvector ONNX init failed, continue to next fallback
1352
+ }
1353
+ }
1354
+ // Legacy fallback: Check for agentic-flow core embeddings
1181
1355
  const agenticFlow = await import('agentic-flow').catch(() => null);
1182
1356
  if (agenticFlow && agenticFlow.embeddings) {
1183
1357
  if (verbose) {
@@ -1224,6 +1398,13 @@ export async function loadEmbeddingModel(options) {
1224
1398
  * Uses ONNX model if available, falls back to deterministic hash
1225
1399
  */
1226
1400
  export async function generateEmbedding(text) {
1401
+ // ADR-053: Try AgentDB v3 bridge first
1402
+ const bridge = await getBridge();
1403
+ if (bridge) {
1404
+ const bridgeResult = await bridge.bridgeGenerateEmbedding(text);
1405
+ if (bridgeResult)
1406
+ return bridgeResult;
1407
+ }
1227
1408
  // Ensure model is loaded
1228
1409
  if (!embeddingModelState?.loaded) {
1229
1410
  await loadEmbeddingModel();
@@ -1233,12 +1414,17 @@ export async function generateEmbedding(text) {
1233
1414
  if (state.model && typeof state.model === 'function') {
1234
1415
  try {
1235
1416
  const output = await state.model(text, { pooling: 'mean', normalize: true });
1236
- const embedding = Array.from(output.data);
1237
- return {
1238
- embedding,
1239
- dimensions: embedding.length,
1240
- model: 'onnx'
1241
- };
1417
+ // Handle both @xenova/transformers (output.data) and ruvector (plain array) formats
1418
+ const embedding = output?.data
1419
+ ? Array.from(output.data)
1420
+ : Array.isArray(output) ? output : null;
1421
+ if (embedding) {
1422
+ return {
1423
+ embedding,
1424
+ dimensions: embedding.length,
1425
+ model: 'onnx'
1426
+ };
1427
+ }
1242
1428
  }
1243
1429
  catch {
1244
1430
  // Fall through to fallback
@@ -1499,6 +1685,14 @@ export async function verifyMemoryInit(dbPath, options) {
1499
1685
  * This bypasses MCP and writes directly to the database
1500
1686
  */
1501
1687
  export async function storeEntry(options) {
1688
+ // ADR-053: Try AgentDB v3 bridge first
1689
+ const bridge = await getBridge();
1690
+ if (bridge) {
1691
+ const bridgeResult = await bridge.bridgeStoreEntry(options);
1692
+ if (bridgeResult)
1693
+ return bridgeResult;
1694
+ }
1695
+ // Fallback: raw sql.js
1502
1696
  const { key, value, namespace = 'default', generateEmbeddingFlag = true, tags = [], ttl, dbPath: customPath, upsert = false } = options;
1503
1697
  const swarmDir = path.join(process.cwd(), '.swarm');
1504
1698
  const dbPath = customPath || path.join(swarmDir, 'memory.db');
@@ -1583,6 +1777,14 @@ export async function storeEntry(options) {
1583
1777
  * Uses HNSW index for 150x faster search when available
1584
1778
  */
1585
1779
  export async function searchEntries(options) {
1780
+ // ADR-053: Try AgentDB v3 bridge first
1781
+ const bridge = await getBridge();
1782
+ if (bridge) {
1783
+ const bridgeResult = await bridge.bridgeSearchEntries(options);
1784
+ if (bridgeResult)
1785
+ return bridgeResult;
1786
+ }
1787
+ // Fallback: raw sql.js
1586
1788
  const { query, namespace = 'default', limit = 10, threshold = 0.3, dbPath: customPath } = options;
1587
1789
  const swarmDir = path.join(process.cwd(), '.swarm');
1588
1790
  const dbPath = customPath || path.join(swarmDir, 'memory.db');
@@ -1613,13 +1815,18 @@ export async function searchEntries(options) {
1613
1815
  const fileBuffer = fs.readFileSync(dbPath);
1614
1816
  const db = new SQL.Database(fileBuffer);
1615
1817
  // Get entries with embeddings
1616
- const entries = db.exec(`
1617
- SELECT id, key, namespace, content, embedding
1618
- FROM memory_entries
1619
- WHERE status = 'active'
1620
- ${namespace !== 'all' ? `AND namespace = '${namespace.replace(/'/g, "''")}'` : ''}
1621
- LIMIT 1000
1622
- `);
1818
+ const searchStmt = db.prepare(namespace !== 'all'
1819
+ ? `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' AND namespace = ? LIMIT 1000`
1820
+ : `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' LIMIT 1000`);
1821
+ if (namespace !== 'all') {
1822
+ searchStmt.bind([namespace]);
1823
+ }
1824
+ const searchRows = [];
1825
+ while (searchStmt.step()) {
1826
+ searchRows.push(searchStmt.get());
1827
+ }
1828
+ searchStmt.free();
1829
+ const entries = searchRows.length > 0 ? [{ values: searchRows }] : [];
1623
1830
  const results = [];
1624
1831
  if (entries[0]?.values) {
1625
1832
  for (const row of entries[0].values) {
@@ -1697,6 +1904,14 @@ function cosineSim(a, b) {
1697
1904
  * List all entries from the memory database
1698
1905
  */
1699
1906
  export async function listEntries(options) {
1907
+ // ADR-053: Try AgentDB v3 bridge first
1908
+ const bridge = await getBridge();
1909
+ if (bridge) {
1910
+ const bridgeResult = await bridge.bridgeListEntries(options);
1911
+ if (bridgeResult)
1912
+ return bridgeResult;
1913
+ }
1914
+ // Fallback: raw sql.js
1700
1915
  const { namespace, limit = 20, offset = 0, dbPath: customPath } = options;
1701
1916
  const swarmDir = path.join(process.cwd(), '.swarm');
1702
1917
  const dbPath = customPath || path.join(swarmDir, 'memory.db');
@@ -1711,21 +1926,37 @@ export async function listEntries(options) {
1711
1926
  const fileBuffer = fs.readFileSync(dbPath);
1712
1927
  const db = new SQL.Database(fileBuffer);
1713
1928
  // Get total count
1714
- const countQuery = namespace
1715
- ? `SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND namespace = '${namespace.replace(/'/g, "''")}'`
1716
- : `SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`;
1717
- const countResult = db.exec(countQuery);
1929
+ const countStmt = namespace
1930
+ ? db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active' AND namespace = ?`)
1931
+ : db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE status = 'active'`);
1932
+ if (namespace) {
1933
+ countStmt.bind([namespace]);
1934
+ }
1935
+ const countRows = [];
1936
+ while (countStmt.step()) {
1937
+ countRows.push(countStmt.get());
1938
+ }
1939
+ countStmt.free();
1940
+ const countResult = countRows.length > 0 ? [{ values: countRows }] : [];
1718
1941
  const total = countResult[0]?.values?.[0]?.[0] || 0;
1719
1942
  // Get entries
1720
- const listQuery = `
1721
- SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at
1722
- FROM memory_entries
1723
- WHERE status = 'active'
1724
- ${namespace ? `AND namespace = '${namespace.replace(/'/g, "''")}'` : ''}
1725
- ORDER BY updated_at DESC
1726
- LIMIT ${limit} OFFSET ${offset}
1727
- `;
1728
- const result = db.exec(listQuery);
1943
+ const safeLimit = parseInt(String(limit), 10) || 100;
1944
+ const safeOffset = parseInt(String(offset), 10) || 0;
1945
+ const listStmt = namespace
1946
+ ? db.prepare(`SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at FROM memory_entries WHERE status = 'active' AND namespace = ? ORDER BY updated_at DESC LIMIT ? OFFSET ?`)
1947
+ : db.prepare(`SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at FROM memory_entries WHERE status = 'active' ORDER BY updated_at DESC LIMIT ? OFFSET ?`);
1948
+ if (namespace) {
1949
+ listStmt.bind([namespace, safeLimit, safeOffset]);
1950
+ }
1951
+ else {
1952
+ listStmt.bind([safeLimit, safeOffset]);
1953
+ }
1954
+ const listRows = [];
1955
+ while (listStmt.step()) {
1956
+ listRows.push(listStmt.get());
1957
+ }
1958
+ listStmt.free();
1959
+ const result = listRows.length > 0 ? [{ values: listRows }] : [];
1729
1960
  const entries = [];
1730
1961
  if (result[0]?.values) {
1731
1962
  for (const row of result[0].values) {
@@ -1758,6 +1989,14 @@ export async function listEntries(options) {
1758
1989
  * Get a specific entry from the memory database
1759
1990
  */
1760
1991
  export async function getEntry(options) {
1992
+ // ADR-053: Try AgentDB v3 bridge first
1993
+ const bridge = await getBridge();
1994
+ if (bridge) {
1995
+ const bridgeResult = await bridge.bridgeGetEntry(options);
1996
+ if (bridgeResult)
1997
+ return bridgeResult;
1998
+ }
1999
+ // Fallback: raw sql.js
1761
2000
  const { key, namespace = 'default', dbPath: customPath } = options;
1762
2001
  const swarmDir = path.join(process.cwd(), '.swarm');
1763
2002
  const dbPath = customPath || path.join(swarmDir, 'memory.db');
@@ -1772,14 +2011,21 @@ export async function getEntry(options) {
1772
2011
  const fileBuffer = fs.readFileSync(dbPath);
1773
2012
  const db = new SQL.Database(fileBuffer);
1774
2013
  // Find entry by key
1775
- const result = db.exec(`
2014
+ const getStmt = db.prepare(`
1776
2015
  SELECT id, key, namespace, content, embedding, access_count, created_at, updated_at, tags
1777
2016
  FROM memory_entries
1778
2017
  WHERE status = 'active'
1779
- AND key = '${key.replace(/'/g, "''")}'
1780
- AND namespace = '${namespace.replace(/'/g, "''")}'
2018
+ AND key = ?
2019
+ AND namespace = ?
1781
2020
  LIMIT 1
1782
2021
  `);
2022
+ getStmt.bind([key, namespace]);
2023
+ const getRows = [];
2024
+ while (getStmt.step()) {
2025
+ getRows.push(getStmt.get());
2026
+ }
2027
+ getStmt.free();
2028
+ const result = getRows.length > 0 ? [{ values: getRows }] : [];
1783
2029
  if (!result[0]?.values?.[0]) {
1784
2030
  db.close();
1785
2031
  return { success: true, found: false };
@@ -1789,8 +2035,8 @@ export async function getEntry(options) {
1789
2035
  db.run(`
1790
2036
  UPDATE memory_entries
1791
2037
  SET access_count = access_count + 1, last_accessed_at = strftime('%s', 'now') * 1000
1792
- WHERE id = '${String(id).replace(/'/g, "''")}'
1793
- `);
2038
+ WHERE id = ?
2039
+ `, [String(id)]);
1794
2040
  // Save updated database
1795
2041
  const data = db.export();
1796
2042
  fs.writeFileSync(dbPath, Buffer.from(data));
@@ -1833,6 +2079,14 @@ export async function getEntry(options) {
1833
2079
  * Issue #980: Properly supports namespaced entries
1834
2080
  */
1835
2081
  export async function deleteEntry(options) {
2082
+ // ADR-053: Try AgentDB v3 bridge first
2083
+ const bridge = await getBridge();
2084
+ if (bridge) {
2085
+ const bridgeResult = await bridge.bridgeDeleteEntry(options);
2086
+ if (bridgeResult)
2087
+ return bridgeResult;
2088
+ }
2089
+ // Fallback: raw sql.js
1836
2090
  const { key, namespace = 'default', dbPath: customPath } = options;
1837
2091
  const swarmDir = path.join(process.cwd(), '.swarm');
1838
2092
  const dbPath = customPath || path.join(swarmDir, 'memory.db');
@@ -1854,13 +2108,20 @@ export async function deleteEntry(options) {
1854
2108
  const fileBuffer = fs.readFileSync(dbPath);
1855
2109
  const db = new SQL.Database(fileBuffer);
1856
2110
  // Check if entry exists first
1857
- const checkResult = db.exec(`
2111
+ const checkStmt = db.prepare(`
1858
2112
  SELECT id FROM memory_entries
1859
2113
  WHERE status = 'active'
1860
- AND key = '${key.replace(/'/g, "''")}'
1861
- AND namespace = '${namespace.replace(/'/g, "''")}'
2114
+ AND key = ?
2115
+ AND namespace = ?
1862
2116
  LIMIT 1
1863
2117
  `);
2118
+ checkStmt.bind([key, namespace]);
2119
+ const checkRows = [];
2120
+ while (checkStmt.step()) {
2121
+ checkRows.push(checkStmt.get());
2122
+ }
2123
+ checkStmt.free();
2124
+ const checkResult = checkRows.length > 0 ? [{ values: checkRows }] : [];
1864
2125
  if (!checkResult[0]?.values?.[0]) {
1865
2126
  // Get remaining count before closing
1866
2127
  const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
@@ -1875,14 +2136,19 @@ export async function deleteEntry(options) {
1875
2136
  error: `Key '${key}' not found in namespace '${namespace}'`
1876
2137
  };
1877
2138
  }
2139
+ // Capture the entry ID for HNSW cleanup
2140
+ const entryId = String(checkResult[0].values[0][0]);
1878
2141
  // Delete the entry (soft delete by setting status to 'deleted')
2142
+ // Also null out the embedding to clean up vector data from SQLite
1879
2143
  db.run(`
1880
2144
  UPDATE memory_entries
1881
- SET status = 'deleted', updated_at = strftime('%s', 'now') * 1000
1882
- WHERE key = '${key.replace(/'/g, "''")}'
1883
- AND namespace = '${namespace.replace(/'/g, "''")}'
2145
+ SET status = 'deleted',
2146
+ embedding = NULL,
2147
+ updated_at = strftime('%s', 'now') * 1000
2148
+ WHERE key = ?
2149
+ AND namespace = ?
1884
2150
  AND status = 'active'
1885
- `);
2151
+ `, [key, namespace]);
1886
2152
  // Get remaining count
1887
2153
  const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
1888
2154
  const remainingEntries = countResult[0]?.values?.[0]?.[0] || 0;
@@ -1890,6 +2156,17 @@ export async function deleteEntry(options) {
1890
2156
  const data = db.export();
1891
2157
  fs.writeFileSync(dbPath, Buffer.from(data));
1892
2158
  db.close();
2159
+ // Clean up in-memory HNSW index so ghost vectors don't appear in searches.
2160
+ // Remove the entry from the HNSW entries map and invalidate the index.
2161
+ // The next search will rebuild the HNSW index from the remaining DB rows.
2162
+ if (hnswIndex?.entries) {
2163
+ hnswIndex.entries.delete(entryId);
2164
+ saveHNSWMetadata();
2165
+ // Invalidate the HNSW index so it rebuilds from DB on next search.
2166
+ // We can't surgically remove a vector from the HNSW graph, so we
2167
+ // clear the entire index; it will be lazily rebuilt from SQLite.
2168
+ rebuildSearchIndex();
2169
+ }
1893
2170
  return {
1894
2171
  success: true,
1895
2172
  deleted: true,
@@ -1923,6 +2200,7 @@ export default {
1923
2200
  listEntries,
1924
2201
  getEntry,
1925
2202
  deleteEntry,
2203
+ rebuildSearchIndex,
1926
2204
  MEMORY_SCHEMA_V3,
1927
2205
  getInitialMetadata
1928
2206
  };