monomind 1.8.0 → 1.9.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 (566) hide show
  1. package/.claude/agents/design/design-monodesign.md +121 -0
  2. package/.claude/agents/github/issue-tracker.md +12 -12
  3. package/.claude/agents/github/pr-manager.md +10 -10
  4. package/.claude/agents/github/release-manager.md +49 -105
  5. package/.claude/agents/github/repo-architect.md +73 -92
  6. package/.claude/agents/github/sync-coordinator.md +55 -123
  7. package/.claude/agents/marketing/marketing-competitive-content.md +155 -0
  8. package/.claude/agents/marketing/marketing-content-creator.md +13 -0
  9. package/.claude/agents/marketing/marketing-cro-specialist.md +147 -0
  10. package/.claude/agents/marketing/marketing-email-specialist.md +90 -0
  11. package/.claude/agents/marketing/marketing-launch-strategist.md +129 -0
  12. package/.claude/agents/marketing/marketing-pricing-strategist.md +127 -0
  13. package/.claude/agents/specialists/integration-architect.md +94 -0
  14. package/.claude/commands/agents/README.md +4 -0
  15. package/.claude/commands/agents/agent-capabilities.md +6 -2
  16. package/.claude/commands/agents/agent-coordination.md +4 -0
  17. package/.claude/commands/agents/agent-spawning.md +4 -0
  18. package/.claude/commands/agents/agent-types.md +6 -2
  19. package/.claude/commands/analysis/README.md +14 -5
  20. package/.claude/commands/analysis/bottleneck-detect.md +30 -123
  21. package/.claude/commands/analysis/performance-bottlenecks.md +14 -14
  22. package/.claude/commands/analysis/performance-report.md +38 -11
  23. package/.claude/commands/analysis/token-efficiency.md +13 -16
  24. package/.claude/commands/analysis/token-usage.md +34 -12
  25. package/.claude/commands/automation/README.md +15 -5
  26. package/.claude/commands/automation/auto-agent.md +49 -85
  27. package/.claude/commands/automation/self-healing.md +20 -18
  28. package/.claude/commands/automation/session-memory.md +28 -29
  29. package/.claude/commands/automation/smart-agents.md +17 -9
  30. package/.claude/commands/automation/smart-spawn.md +52 -11
  31. package/.claude/commands/automation/workflow-select.md +46 -11
  32. package/.claude/commands/browse.md +5 -0
  33. package/.claude/commands/coordination/README.md +9 -5
  34. package/.claude/commands/coordination/agent-spawn.md +53 -9
  35. package/.claude/commands/coordination/swarm-init.md +39 -42
  36. package/.claude/commands/coordination/task-orchestrate.md +65 -11
  37. package/.claude/commands/github/README.md +21 -8
  38. package/.claude/commands/github/github-modes.md +9 -5
  39. package/.claude/commands/github/issue-tracker.md +34 -33
  40. package/.claude/commands/github/pr-manager.md +20 -17
  41. package/.claude/commands/github/release-manager.md +37 -49
  42. package/.claude/commands/github/repo-architect.md +39 -41
  43. package/.claude/commands/github/sync-coordinator.md +45 -49
  44. package/.claude/commands/hive-mind/README.md +42 -17
  45. package/.claude/commands/hive-mind/hive-mind-consensus.md +68 -4
  46. package/.claude/commands/hive-mind/hive-mind-init.md +55 -5
  47. package/.claude/commands/hive-mind/hive-mind-memory.md +69 -4
  48. package/.claude/commands/hive-mind/hive-mind-spawn.md +71 -10
  49. package/.claude/commands/hive-mind/hive-mind-status.md +52 -4
  50. package/.claude/commands/hive-mind/hive-mind-stop.md +51 -4
  51. package/.claude/commands/hive-mind/hive-mind.md +74 -14
  52. package/.claude/commands/hooks/README.md +62 -7
  53. package/.claude/commands/hooks/overview.md +94 -35
  54. package/.claude/commands/hooks/post-edit.md +48 -87
  55. package/.claude/commands/hooks/post-task.md +37 -87
  56. package/.claude/commands/hooks/pre-edit.md +52 -84
  57. package/.claude/commands/hooks/pre-task.md +46 -81
  58. package/.claude/commands/hooks/session-end.md +49 -85
  59. package/.claude/commands/hooks/setup.md +87 -58
  60. package/.claude/commands/mastermind/_repeat.md +308 -0
  61. package/.claude/commands/mastermind/architect.md +49 -0
  62. package/.claude/commands/mastermind/brain.md +98 -0
  63. package/.claude/commands/mastermind/build.md +22 -0
  64. package/.claude/commands/mastermind/content.md +22 -0
  65. package/.claude/commands/mastermind/createorg.md +94 -0
  66. package/.claude/commands/mastermind/finance.md +22 -0
  67. package/.claude/commands/mastermind/idea.md +22 -0
  68. package/.claude/commands/mastermind/marketing.md +22 -0
  69. package/.claude/commands/mastermind/master.md +379 -0
  70. package/.claude/commands/mastermind/ops.md +22 -0
  71. package/.claude/commands/mastermind/release.md +22 -0
  72. package/.claude/commands/mastermind/research.md +22 -0
  73. package/.claude/commands/mastermind/review.md +22 -0
  74. package/.claude/commands/mastermind/runorg.md +106 -0
  75. package/.claude/commands/mastermind/sales.md +22 -0
  76. package/.claude/commands/mastermind/techport.md +17 -0
  77. package/.claude/commands/memory/README.md +75 -5
  78. package/.claude/commands/memory/memory-search.md +63 -11
  79. package/.claude/commands/monitoring/README.md +64 -4
  80. package/.claude/commands/monitoring/agent-metrics.md +50 -10
  81. package/.claude/commands/monitoring/agents.md +59 -32
  82. package/.claude/commands/monitoring/status.md +96 -34
  83. package/.claude/commands/monograph/README.md +102 -0
  84. package/.claude/commands/monograph/monograph-build.md +79 -0
  85. package/.claude/commands/monograph/monograph-search.md +96 -0
  86. package/.claude/commands/monograph/monograph-stats.md +53 -0
  87. package/.claude/commands/monograph/monograph-watch.md +63 -0
  88. package/.claude/commands/monograph/monograph-wiki.md +91 -0
  89. package/.claude/commands/monomind/createtask.md +277 -0
  90. package/.claude/commands/{monomind-do.md → monomind/do.md} +21 -8
  91. package/.claude/commands/monomind/help.md +118 -0
  92. package/.claude/commands/{monomind-idea.md → monomind/idea.md} +22 -28
  93. package/.claude/commands/{monomind-improve.md → monomind/improve.md} +21 -27
  94. package/.claude/commands/monomind/memory.md +230 -0
  95. package/.claude/commands/monomind/repeat.md +201 -0
  96. package/.claude/commands/monomind/review.md +313 -0
  97. package/.claude/commands/monomind/specialagents.md +125 -0
  98. package/.claude/commands/monomind/swarm.md +161 -0
  99. package/.claude/commands/monomind/understand.md +148 -0
  100. package/.claude/commands/optimization/README.md +69 -5
  101. package/.claude/commands/optimization/auto-topology.md +66 -43
  102. package/.claude/commands/optimization/parallel-execution.md +65 -39
  103. package/.claude/commands/optimization/performance-optimize.md +79 -0
  104. package/.claude/commands/pair/README.md +48 -230
  105. package/.claude/commands/pair/examples.md +85 -441
  106. package/.claude/commands/pair/modes.md +77 -303
  107. package/.claude/commands/pair/session.md +76 -359
  108. package/.claude/commands/sparc/analyzer.md +9 -26
  109. package/.claude/commands/sparc/architect.md +8 -25
  110. package/.claude/commands/sparc/ask.md +27 -68
  111. package/.claude/commands/sparc/batch-executor.md +8 -25
  112. package/.claude/commands/sparc/code.md +12 -53
  113. package/.claude/commands/sparc/coder.md +8 -25
  114. package/.claude/commands/sparc/debug.md +12 -53
  115. package/.claude/commands/sparc/debugger.md +8 -25
  116. package/.claude/commands/sparc/designer.md +8 -25
  117. package/.claude/commands/sparc/devops.md +16 -57
  118. package/.claude/commands/sparc/docs-writer.md +12 -53
  119. package/.claude/commands/sparc/documenter.md +8 -25
  120. package/.claude/commands/sparc/innovator.md +8 -25
  121. package/.claude/commands/sparc/integration.md +12 -53
  122. package/.claude/commands/sparc/mcp.md +12 -53
  123. package/.claude/commands/sparc/memory-manager.md +28 -25
  124. package/.claude/commands/sparc/optimizer.md +8 -25
  125. package/.claude/commands/sparc/orchestrator.md +35 -97
  126. package/.claude/commands/sparc/post-deployment-monitoring-mode.md +13 -54
  127. package/.claude/commands/sparc/refinement-optimization-mode.md +13 -54
  128. package/.claude/commands/sparc/researcher.md +8 -25
  129. package/.claude/commands/sparc/reviewer.md +8 -25
  130. package/.claude/commands/sparc/security-review.md +13 -54
  131. package/.claude/commands/sparc/sparc-modes.md +97 -151
  132. package/.claude/commands/sparc/sparc.md +16 -56
  133. package/.claude/commands/sparc/spec-pseudocode.md +13 -54
  134. package/.claude/commands/sparc/supabase-admin.md +19 -66
  135. package/.claude/commands/sparc/swarm-coordinator.md +21 -25
  136. package/.claude/commands/sparc/tdd.md +8 -25
  137. package/.claude/commands/sparc/tester.md +8 -25
  138. package/.claude/commands/sparc/tutorial.md +12 -53
  139. package/.claude/commands/sparc/workflow-manager.md +8 -25
  140. package/.claude/commands/sparc.md +76 -130
  141. package/.claude/commands/stream-chain/pipeline.md +72 -77
  142. package/.claude/commands/stream-chain/run.md +133 -47
  143. package/.claude/commands/swarm/README.md +37 -12
  144. package/.claude/commands/swarm/analysis.md +47 -69
  145. package/.claude/commands/swarm/development.md +45 -69
  146. package/.claude/commands/swarm/examples.md +77 -142
  147. package/.claude/commands/swarm/maintenance.md +47 -74
  148. package/.claude/commands/swarm/optimization.md +54 -87
  149. package/.claude/commands/swarm/research.md +47 -107
  150. package/.claude/commands/swarm/swarm-analysis.md +58 -4
  151. package/.claude/commands/swarm/swarm-background.md +61 -4
  152. package/.claude/commands/swarm/swarm-modes.md +63 -4
  153. package/.claude/commands/swarm/swarm-monitor.md +50 -4
  154. package/.claude/commands/swarm/swarm-status.md +40 -4
  155. package/.claude/commands/swarm/swarm-strategies.md +73 -5
  156. package/.claude/commands/swarm/swarm.md +70 -18
  157. package/.claude/commands/swarm/testing.md +51 -102
  158. package/.claude/commands/tokens.md +6 -1
  159. package/.claude/commands/training/README.md +36 -6
  160. package/.claude/commands/training/model-update.md +68 -15
  161. package/.claude/commands/training/neural-patterns.md +54 -55
  162. package/.claude/commands/training/neural-train.md +70 -16
  163. package/.claude/commands/training/pattern-learn.md +60 -16
  164. package/.claude/commands/training/specialization.md +78 -49
  165. package/.claude/commands/truth/start.md +87 -109
  166. package/.claude/commands/ts.md +7 -2
  167. package/.claude/commands/verify/check.md +90 -34
  168. package/.claude/commands/verify/start.md +71 -94
  169. package/.claude/commands/workflows/README.md +62 -6
  170. package/.claude/commands/workflows/development.md +69 -61
  171. package/.claude/commands/workflows/research.md +73 -47
  172. package/.claude/commands/workflows/workflow-create.md +75 -16
  173. package/.claude/commands/workflows/workflow-execute.md +94 -16
  174. package/.claude/commands/workflows/workflow-export.md +81 -16
  175. package/.claude/helpers/control-start.cjs +91 -0
  176. package/.claude/helpers/extras-registry.json +4104 -1991
  177. package/.claude/helpers/graphify-freshen.cjs +44 -13
  178. package/.claude/helpers/hook-handler.cjs +256 -1
  179. package/.claude/helpers/learning-service.mjs +0 -0
  180. package/.claude/helpers/loop-tracker.cjs +107 -0
  181. package/.claude/helpers/metrics-db.mjs +0 -0
  182. package/.claude/helpers/router.cjs +48 -68
  183. package/.claude/helpers/skill-registry.json +89 -104
  184. package/.claude/helpers/statusline.cjs +33 -2
  185. package/.claude/helpers/swarm-hooks.sh +0 -0
  186. package/.claude/scheduled_tasks.lock +1 -0
  187. package/.claude/settings.json +15 -0
  188. package/.claude/skills/.monomind/data/ranked-context.json +5 -0
  189. package/.claude/skills/.monomind/sessions/current.json +13 -0
  190. package/.claude/skills/.monomind/sessions/session-1777829336455.json +15 -0
  191. package/.claude/skills/.monomind/sessions/session-1777831614725.json +15 -0
  192. package/.claude/skills/.monomind/sessions/session-1777832095857.json +15 -0
  193. package/.claude/skills/.monomind/sessions/session-1777839814183.json +15 -0
  194. package/.claude/skills/.monomind/sessions/session-1777841847131.json +15 -0
  195. package/.claude/skills/.monomind/sessions/session-1777843309463.json +15 -0
  196. package/.claude/skills/.monomind/sessions/session-1777880867159.json +15 -0
  197. package/.claude/skills/.monomind/sessions/session-1777881884593.json +15 -0
  198. package/.claude/skills/.monomind/sessions/session-1777884090471.json +15 -0
  199. package/.claude/skills/.monomind/sessions/session-1777884808221.json +15 -0
  200. package/.claude/skills/.monomind/sessions/session-1777885672155.json +15 -0
  201. package/.claude/skills/.monomind/sessions/session-1777886852818.json +15 -0
  202. package/.claude/skills/.monomind/sessions/session-1777896532690.json +15 -0
  203. package/.claude/skills/agentdb-advanced/SKILL.md +11 -12
  204. package/.claude/skills/agentdb-learning/SKILL.md +20 -21
  205. package/.claude/skills/agentdb-memory-patterns/SKILL.md +28 -30
  206. package/.claude/skills/agentdb-optimization/SKILL.md +11 -12
  207. package/.claude/skills/agentdb-vector-search/SKILL.md +37 -41
  208. package/.claude/skills/{v3-integration-deep → agentic-integration}/SKILL.md +20 -13
  209. package/.claude/skills/agentic-jujutsu/SKILL.md +22 -22
  210. package/.claude/skills/{v3-cli-modernization → cli-modernization}/SKILL.md +17 -8
  211. package/.claude/skills/{v3-core-implementation → core-implementation}/SKILL.md +33 -8
  212. package/.claude/skills/{v3-ddd-architecture → ddd-architecture}/SKILL.md +18 -25
  213. package/.claude/skills/github-code-review/SKILL.md +82 -83
  214. package/.claude/skills/github-multi-repo/SKILL.md +42 -46
  215. package/.claude/skills/github-project-management/SKILL.md +83 -88
  216. package/.claude/skills/github-release-management/SKILL.md +12 -18
  217. package/.claude/skills/github-workflow-automation/SKILL.md +70 -74
  218. package/.claude/skills/hooks-automation/SKILL.md +9 -13
  219. package/.claude/skills/mastermind/_intake.md +83 -0
  220. package/.claude/skills/mastermind/_protocol.md +275 -0
  221. package/.claude/skills/mastermind/architect.md +847 -0
  222. package/.claude/skills/mastermind/build.md +158 -0
  223. package/.claude/skills/mastermind/content.md +185 -0
  224. package/.claude/skills/mastermind/createorg.md +318 -0
  225. package/.claude/skills/mastermind/finance.md +154 -0
  226. package/.claude/skills/mastermind/idea.md +158 -0
  227. package/.claude/skills/mastermind/marketing.md +216 -0
  228. package/.claude/skills/mastermind/monotask.md +350 -0
  229. package/.claude/skills/mastermind/ops.md +156 -0
  230. package/.claude/skills/mastermind/references/copywriting-frameworks.md +181 -0
  231. package/.claude/skills/mastermind/references/persuasion-psychology.md +158 -0
  232. package/.claude/skills/mastermind/release.md +156 -0
  233. package/.claude/skills/mastermind/research.md +156 -0
  234. package/.claude/skills/mastermind/review.md +157 -0
  235. package/.claude/skills/mastermind/runorg.md +308 -0
  236. package/.claude/skills/mastermind/sales.md +158 -0
  237. package/.claude/skills/mastermind/techport.md +743 -0
  238. package/.claude/skills/{v3-mcp-optimization → mcp-optimization}/SKILL.md +35 -14
  239. package/.claude/skills/{v3-memory-unification → memory-unification}/SKILL.md +20 -4
  240. package/.claude/skills/monodesign/SKILL.md +302 -0
  241. package/.claude/skills/monodesign/reference/adapt.md +190 -0
  242. package/.claude/skills/monodesign/reference/animate.md +175 -0
  243. package/.claude/skills/monodesign/reference/antipatterns-catalog.md +187 -0
  244. package/.claude/skills/monodesign/reference/audit.md +133 -0
  245. package/.claude/skills/monodesign/reference/bolder.md +113 -0
  246. package/.claude/skills/monodesign/reference/brand-workflow.md +180 -0
  247. package/.claude/skills/monodesign/reference/brand.md +114 -0
  248. package/.claude/skills/monodesign/reference/clarify.md +174 -0
  249. package/.claude/skills/monodesign/reference/cognitive-load.md +106 -0
  250. package/.claude/skills/monodesign/reference/color-and-contrast.md +105 -0
  251. package/.claude/skills/monodesign/reference/colorize.md +154 -0
  252. package/.claude/skills/monodesign/reference/component-specs.md +260 -0
  253. package/.claude/skills/monodesign/reference/component-states.md +274 -0
  254. package/.claude/skills/monodesign/reference/component-system.md +358 -0
  255. package/.claude/skills/monodesign/reference/copy-formulas.md +160 -0
  256. package/.claude/skills/monodesign/reference/craft.md +193 -0
  257. package/.claude/skills/monodesign/reference/critique.md +213 -0
  258. package/.claude/skills/monodesign/reference/delight.md +302 -0
  259. package/.claude/skills/monodesign/reference/design-principles.md +246 -0
  260. package/.claude/skills/monodesign/reference/distill.md +111 -0
  261. package/.claude/skills/monodesign/reference/document.md +427 -0
  262. package/.claude/skills/monodesign/reference/extract.md +69 -0
  263. package/.claude/skills/monodesign/reference/harden.md +347 -0
  264. package/.claude/skills/monodesign/reference/heuristics-scoring.md +234 -0
  265. package/.claude/skills/monodesign/reference/image-prompts.md +118 -0
  266. package/.claude/skills/monodesign/reference/interaction-design.md +195 -0
  267. package/.claude/skills/monodesign/reference/layout.md +141 -0
  268. package/.claude/skills/monodesign/reference/live.md +622 -0
  269. package/.claude/skills/monodesign/reference/motion-design.md +109 -0
  270. package/.claude/skills/monodesign/reference/onboard.md +234 -0
  271. package/.claude/skills/monodesign/reference/optimize.md +258 -0
  272. package/.claude/skills/monodesign/reference/overdrive.md +130 -0
  273. package/.claude/skills/monodesign/reference/personas.md +179 -0
  274. package/.claude/skills/monodesign/reference/polish.md +233 -0
  275. package/.claude/skills/monodesign/reference/pre-delivery-checklist.md +108 -0
  276. package/.claude/skills/monodesign/reference/product.md +62 -0
  277. package/.claude/skills/monodesign/reference/quieter.md +99 -0
  278. package/.claude/skills/monodesign/reference/responsive-design.md +114 -0
  279. package/.claude/skills/monodesign/reference/shape.md +151 -0
  280. package/.claude/skills/monodesign/reference/spatial-design.md +100 -0
  281. package/.claude/skills/monodesign/reference/teach.md +156 -0
  282. package/.claude/skills/monodesign/reference/token-architecture.md +222 -0
  283. package/.claude/skills/monodesign/reference/typeset.md +124 -0
  284. package/.claude/skills/monodesign/reference/typography.md +159 -0
  285. package/.claude/skills/monodesign/reference/ux-research.md +143 -0
  286. package/.claude/skills/monodesign/reference/ux-rules.md +211 -0
  287. package/.claude/skills/monodesign/reference/ux-writing.md +107 -0
  288. package/.claude/skills/monomotion/SKILL.md +145 -0
  289. package/.claude/skills/monomotion/rules/api-control.md +139 -0
  290. package/.claude/skills/monomotion/rules/effects.md +109 -0
  291. package/.claude/skills/monomotion/rules/integration.md +140 -0
  292. package/.claude/skills/monomotion/rules/scroll.md +131 -0
  293. package/.claude/skills/monomotion/rules/sequencing.md +105 -0
  294. package/.claude/skills/monomotion/rules/svg.md +101 -0
  295. package/.claude/skills/monomotion/rules/text.md +119 -0
  296. package/.claude/skills/pair-programming/SKILL.md +1 -1
  297. package/.claude/skills/performance-analysis/SKILL.md +3 -3
  298. package/.claude/skills/{v3-performance-optimization → performance-optimization}/SKILL.md +16 -8
  299. package/.claude/skills/reasoningbank-agentdb/SKILL.md +17 -19
  300. package/.claude/skills/reasoningbank-intelligence/SKILL.md +4 -6
  301. package/.claude/skills/{v3-security-overhaul → security-hardening}/SKILL.md +13 -3
  302. package/.claude/skills/skill-builder/SKILL.md +19 -19
  303. package/.claude/skills/sparc-methodology/SKILL.md +55 -211
  304. package/.claude/skills/stop-slop/SKILL.md +67 -0
  305. package/.claude/skills/stop-slop/references/examples.md +61 -0
  306. package/.claude/skills/stop-slop/references/phrases.md +130 -0
  307. package/.claude/skills/stop-slop/references/structures.md +136 -0
  308. package/.claude/skills/swarm-advanced/SKILL.md +13 -43
  309. package/.claude/skills/{v3-swarm-coordination → swarm-coordination}/SKILL.md +39 -21
  310. package/.claude/skills/swarm-orchestration/SKILL.md +12 -12
  311. package/.claude/skills/verification-quality/SKILL.md +5 -5
  312. package/.claude/statusline-command.sh +0 -0
  313. package/.claude/statusline.sh +0 -0
  314. package/.claude-plugin/scripts/install.sh +0 -0
  315. package/.claude-plugin/scripts/uninstall.sh +0 -0
  316. package/.claude-plugin/scripts/verify.sh +0 -0
  317. package/README.md +5 -5
  318. package/package.json +17 -17
  319. package/packages/@monomind/cli/README.md +441 -0
  320. package/packages/@monomind/cli/bin/cli.js +78 -13
  321. package/packages/@monomind/cli/bin/mcp-server.js +0 -0
  322. package/packages/@monomind/cli/dist/src/agents/halt-signal.js +33 -7
  323. package/packages/@monomind/cli/dist/src/agents/managed-agent.js +5 -2
  324. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.d.ts +3 -2
  325. package/packages/@monomind/cli/dist/src/agents/prompt-experiment.js +1 -1
  326. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.d.ts +5 -2
  327. package/packages/@monomind/cli/dist/src/agents/prompt-version-manager.js +26 -4
  328. package/packages/@monomind/cli/dist/src/agents/specialization-scorer.js +17 -9
  329. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.d.ts +5 -3
  330. package/packages/@monomind/cli/dist/src/agents/trigger-scanner.js +58 -10
  331. package/packages/@monomind/cli/dist/src/agents/version-store.d.ts +0 -1
  332. package/packages/@monomind/cli/dist/src/agents/version-store.js +44 -21
  333. package/packages/@monomind/cli/dist/src/autopilot-state.js +79 -28
  334. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.d.ts +7 -2
  335. package/packages/@monomind/cli/dist/src/benchmarks/benchmark-runner.js +20 -8
  336. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.d.ts +2 -1
  337. package/packages/@monomind/cli/dist/src/benchmarks/metric-evaluators.js +25 -2
  338. package/packages/@monomind/cli/dist/src/commands/agent.js +6 -4
  339. package/packages/@monomind/cli/dist/src/commands/appliance-advanced.js +23 -0
  340. package/packages/@monomind/cli/dist/src/commands/autopilot.js +3 -3
  341. package/packages/@monomind/cli/dist/src/commands/benchmark.js +119 -8
  342. package/packages/@monomind/cli/dist/src/commands/claims.js +22 -14
  343. package/packages/@monomind/cli/dist/src/commands/config.js +32 -0
  344. package/packages/@monomind/cli/dist/src/commands/daemon.js +13 -11
  345. package/packages/@monomind/cli/dist/src/commands/deployment.js +21 -2
  346. package/packages/@monomind/cli/dist/src/commands/doctor.js +5 -4
  347. package/packages/@monomind/cli/dist/src/commands/embeddings.js +124 -48
  348. package/packages/@monomind/cli/dist/src/commands/hive-mind.js +15 -14
  349. package/packages/@monomind/cli/dist/src/commands/hooks.js +45 -41
  350. package/packages/@monomind/cli/dist/src/commands/index.d.ts +2 -0
  351. package/packages/@monomind/cli/dist/src/commands/index.js +20 -7
  352. package/packages/@monomind/cli/dist/src/commands/init.js +53 -19
  353. package/packages/@monomind/cli/dist/src/commands/mcp.js +31 -44
  354. package/packages/@monomind/cli/dist/src/commands/memory.js +47 -15
  355. package/packages/@monomind/cli/dist/src/commands/migrate.js +156 -108
  356. package/packages/@monomind/cli/dist/src/commands/monograph.d.ts +8 -0
  357. package/packages/@monomind/cli/dist/src/commands/monograph.js +526 -0
  358. package/packages/@monomind/cli/dist/src/commands/neural.js +96 -56
  359. package/packages/@monomind/cli/dist/src/commands/performance.js +30 -8
  360. package/packages/@monomind/cli/dist/src/commands/plugins.js +13 -37
  361. package/packages/@monomind/cli/dist/src/commands/process.js +25 -2
  362. package/packages/@monomind/cli/dist/src/commands/providers.js +37 -5
  363. package/packages/@monomind/cli/dist/src/commands/replay.js +4 -4
  364. package/packages/@monomind/cli/dist/src/commands/route.js +37 -5
  365. package/packages/@monomind/cli/dist/src/commands/ruvector/import.js +12 -2
  366. package/packages/@monomind/cli/dist/src/commands/ruvector/init.js +15 -0
  367. package/packages/@monomind/cli/dist/src/commands/ruvector/status.js +16 -3
  368. package/packages/@monomind/cli/dist/src/commands/security.js +342 -193
  369. package/packages/@monomind/cli/dist/src/commands/session.js +51 -8
  370. package/packages/@monomind/cli/dist/src/commands/start.js +18 -4
  371. package/packages/@monomind/cli/dist/src/commands/swarm.js +47 -36
  372. package/packages/@monomind/cli/dist/src/commands/tokens.js +11 -11
  373. package/packages/@monomind/cli/dist/src/commands/transfer-store.js +1 -1
  374. package/packages/@monomind/cli/dist/src/commands/workflow.js +31 -4
  375. package/packages/@monomind/cli/dist/src/config-adapter.d.ts +2 -1
  376. package/packages/@monomind/cli/dist/src/consensus/audit-writer.js +46 -13
  377. package/packages/@monomind/cli/dist/src/consensus/vote-signer.d.ts +0 -3
  378. package/packages/@monomind/cli/dist/src/consensus/vote-signer.js +9 -1
  379. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.d.ts +4 -2
  380. package/packages/@monomind/cli/dist/src/dlq/dlq-reader.js +25 -8
  381. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.d.ts +10 -3
  382. package/packages/@monomind/cli/dist/src/dlq/dlq-replayer.js +50 -16
  383. package/packages/@monomind/cli/dist/src/dlq/dlq-writer.js +27 -5
  384. package/packages/@monomind/cli/dist/src/eval/dataset-manager.d.ts +2 -2
  385. package/packages/@monomind/cli/dist/src/eval/dataset-manager.js +26 -16
  386. package/packages/@monomind/cli/dist/src/eval/trace-collector.js +23 -3
  387. package/packages/@monomind/cli/dist/src/index.js +12 -10
  388. package/packages/@monomind/cli/dist/src/init/claudemd-generator.js +8 -8
  389. package/packages/@monomind/cli/dist/src/init/executor.js +212 -102
  390. package/packages/@monomind/cli/dist/src/init/helpers-generator.js +35 -22
  391. package/packages/@monomind/cli/dist/src/init/mcp-generator.js +3 -3
  392. package/packages/@monomind/cli/dist/src/init/settings-generator.js +10 -3
  393. package/packages/@monomind/cli/dist/src/init/shared-instructions-generator.js +18 -3
  394. package/packages/@monomind/cli/dist/src/init/statusline-generator.js +3 -1
  395. package/packages/@monomind/cli/dist/src/init/types.d.ts +35 -11
  396. package/packages/@monomind/cli/dist/src/init/types.js +5 -9
  397. package/packages/@monomind/cli/dist/src/interactive/interrupt.js +8 -3
  398. package/packages/@monomind/cli/dist/src/mcp/tool-registry.js +38 -4
  399. package/packages/@monomind/cli/dist/src/mcp-client.js +10 -4
  400. package/packages/@monomind/cli/dist/src/mcp-server.d.ts +9 -2
  401. package/packages/@monomind/cli/dist/src/mcp-server.js +182 -35
  402. package/packages/@monomind/cli/dist/src/mcp-tools/agent-tools.js +66 -34
  403. package/packages/@monomind/cli/dist/src/mcp-tools/agentdb-tools.js +34 -7
  404. package/packages/@monomind/cli/dist/src/mcp-tools/analyze-tools.js +25 -16
  405. package/packages/@monomind/cli/dist/src/mcp-tools/auto-install.js +4 -6
  406. package/packages/@monomind/cli/dist/src/mcp-tools/autopilot-tools.js +12 -2
  407. package/packages/@monomind/cli/dist/src/mcp-tools/browser-tools.js +199 -20
  408. package/packages/@monomind/cli/dist/src/mcp-tools/claims-tools.js +68 -18
  409. package/packages/@monomind/cli/dist/src/mcp-tools/config-tools.js +33 -5
  410. package/packages/@monomind/cli/dist/src/mcp-tools/coordination-tools.js +59 -4
  411. package/packages/@monomind/cli/dist/src/mcp-tools/daa-tools.js +46 -10
  412. package/packages/@monomind/cli/dist/src/mcp-tools/embeddings-tools.js +46 -5
  413. package/packages/@monomind/cli/dist/src/mcp-tools/github-tools.js +29 -16
  414. package/packages/@monomind/cli/dist/src/mcp-tools/guidance-tools.js +38 -10
  415. package/packages/@monomind/cli/dist/src/mcp-tools/hive-mind-tools.js +96 -33
  416. package/packages/@monomind/cli/dist/src/mcp-tools/hooks-tools.js +70 -37
  417. package/packages/@monomind/cli/dist/src/mcp-tools/memory-tools.js +29 -13
  418. package/packages/@monomind/cli/dist/src/mcp-tools/monograph-tools.js +5867 -56
  419. package/packages/@monomind/cli/dist/src/mcp-tools/neural-tools.js +121 -37
  420. package/packages/@monomind/cli/dist/src/mcp-tools/performance-tools.js +21 -8
  421. package/packages/@monomind/cli/dist/src/mcp-tools/progress-tools.js +10 -8
  422. package/packages/@monomind/cli/dist/src/mcp-tools/request-tracker.js +4 -1
  423. package/packages/@monomind/cli/dist/src/mcp-tools/ruvllm-tools.js +19 -8
  424. package/packages/@monomind/cli/dist/src/mcp-tools/session-tools.js +57 -17
  425. package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +35 -17
  426. package/packages/@monomind/cli/dist/src/mcp-tools/system-tools.js +4 -3
  427. package/packages/@monomind/cli/dist/src/mcp-tools/task-tools.js +53 -13
  428. package/packages/@monomind/cli/dist/src/mcp-tools/terminal-tools.js +63 -14
  429. package/packages/@monomind/cli/dist/src/mcp-tools/transfer-tools.js +21 -16
  430. package/packages/@monomind/cli/dist/src/mcp-tools/workflow-tools.js +92 -23
  431. package/packages/@monomind/cli/dist/src/memory/ewc-consolidation.js +41 -10
  432. package/packages/@monomind/cli/dist/src/memory/intelligence.d.ts +2 -2
  433. package/packages/@monomind/cli/dist/src/memory/intelligence.js +39 -13
  434. package/packages/@monomind/cli/dist/src/memory/memory-bridge.d.ts +1 -0
  435. package/packages/@monomind/cli/dist/src/memory/memory-bridge.js +149 -56
  436. package/packages/@monomind/cli/dist/src/memory/memory-initializer.js +107 -45
  437. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.d.ts +8 -1
  438. package/packages/@monomind/cli/dist/src/memory/sona-optimizer.js +25 -8
  439. package/packages/@monomind/cli/dist/src/observability/replay-reader.d.ts +40 -0
  440. package/packages/@monomind/cli/dist/src/observability/replay-reader.js +138 -0
  441. package/packages/@monomind/cli/dist/src/orchestration/routing-modes.js +35 -5
  442. package/packages/@monomind/cli/dist/src/parser.d.ts +8 -0
  443. package/packages/@monomind/cli/dist/src/parser.js +48 -14
  444. package/packages/@monomind/cli/dist/src/plugins/manager.js +112 -19
  445. package/packages/@monomind/cli/dist/src/plugins/store/discovery.d.ts +1 -1
  446. package/packages/@monomind/cli/dist/src/plugins/store/discovery.js +80 -62
  447. package/packages/@monomind/cli/dist/src/production/circuit-breaker.js +8 -1
  448. package/packages/@monomind/cli/dist/src/production/error-handler.d.ts +4 -2
  449. package/packages/@monomind/cli/dist/src/production/error-handler.js +27 -5
  450. package/packages/@monomind/cli/dist/src/production/monitoring.js +8 -4
  451. package/packages/@monomind/cli/dist/src/production/rate-limiter.js +30 -22
  452. package/packages/@monomind/cli/dist/src/ruvector/agent-wasm.js +2 -2
  453. package/packages/@monomind/cli/dist/src/ruvector/coverage-router.js +19 -9
  454. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.d.ts +1 -0
  455. package/packages/@monomind/cli/dist/src/ruvector/diff-classifier.js +26 -6
  456. package/packages/@monomind/cli/dist/src/ruvector/enhanced-model-router.js +24 -2
  457. package/packages/@monomind/cli/dist/src/ruvector/index.d.ts +1 -2
  458. package/packages/@monomind/cli/dist/src/ruvector/index.js +2 -2
  459. package/packages/@monomind/cli/dist/src/ruvector/model-router.d.ts +4 -2
  460. package/packages/@monomind/cli/dist/src/ruvector/model-router.js +30 -6
  461. package/packages/@monomind/cli/dist/src/ruvector/moe-router.d.ts +7 -0
  462. package/packages/@monomind/cli/dist/src/ruvector/moe-router.js +35 -12
  463. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.d.ts +7 -1
  464. package/packages/@monomind/cli/dist/src/ruvector/q-learning-router.js +40 -9
  465. package/packages/@monomind/cli/dist/src/services/claim-service.d.ts +3 -1
  466. package/packages/@monomind/cli/dist/src/services/claim-service.js +33 -2
  467. package/packages/@monomind/cli/dist/src/services/config-file-manager.d.ts +16 -2
  468. package/packages/@monomind/cli/dist/src/services/config-file-manager.js +105 -17
  469. package/packages/@monomind/cli/dist/src/services/container-worker-pool.js +51 -11
  470. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.d.ts +7 -0
  471. package/packages/@monomind/cli/dist/src/services/headless-worker-executor.js +188 -45
  472. package/packages/@monomind/cli/dist/src/services/registry-api.js +62 -9
  473. package/packages/@monomind/cli/dist/src/services/ruvector-training.js +8 -0
  474. package/packages/@monomind/cli/dist/src/services/worker-daemon.d.ts +4 -1
  475. package/packages/@monomind/cli/dist/src/services/worker-daemon.js +112 -28
  476. package/packages/@monomind/cli/dist/src/services/worker-queue.d.ts +9 -2
  477. package/packages/@monomind/cli/dist/src/services/worker-queue.js +86 -5
  478. package/packages/@monomind/cli/dist/src/suggest.js +9 -0
  479. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.d.ts +5 -3
  480. package/packages/@monomind/cli/dist/src/swarm/flow-enforcer.js +17 -5
  481. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.d.ts +3 -0
  482. package/packages/@monomind/cli/dist/src/swarm/flow-visualizer.js +30 -6
  483. package/packages/@monomind/cli/dist/src/transfer/anonymization/index.js +5 -3
  484. package/packages/@monomind/cli/dist/src/transfer/export.js +5 -3
  485. package/packages/@monomind/cli/dist/src/transfer/ipfs/client.js +84 -7
  486. package/packages/@monomind/cli/dist/src/transfer/ipfs/upload.js +13 -4
  487. package/packages/@monomind/cli/dist/src/transfer/storage/gcs.js +19 -10
  488. package/packages/@monomind/cli/dist/src/transfer/store/discovery.d.ts +9 -2
  489. package/packages/@monomind/cli/dist/src/transfer/store/discovery.js +68 -13
  490. package/packages/@monomind/cli/dist/src/transfer/store/download.d.ts +15 -6
  491. package/packages/@monomind/cli/dist/src/transfer/store/download.js +113 -24
  492. package/packages/@monomind/cli/dist/src/transfer/store/publish.d.ts +1 -1
  493. package/packages/@monomind/cli/dist/src/transfer/store/publish.js +13 -14
  494. package/packages/@monomind/cli/dist/src/transfer/store/registry.d.ts +3 -3
  495. package/packages/@monomind/cli/dist/src/transfer/store/registry.js +32 -16
  496. package/packages/@monomind/cli/dist/src/update/checker.js +17 -4
  497. package/packages/@monomind/cli/dist/src/update/executor.js +25 -20
  498. package/packages/@monomind/cli/dist/src/update/rate-limiter.d.ts +11 -0
  499. package/packages/@monomind/cli/dist/src/update/rate-limiter.js +23 -3
  500. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.d.ts +6 -0
  501. package/packages/@monomind/cli/dist/src/utils/parse-jsonl.js +22 -0
  502. package/packages/@monomind/cli/dist/src/workflow/condition-evaluator.js +37 -3
  503. package/packages/@monomind/cli/dist/src/workflow/dag-builder.js +27 -11
  504. package/packages/@monomind/cli/dist/src/workflow/dag-executor.js +51 -13
  505. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.d.ts +3 -0
  506. package/packages/@monomind/cli/dist/src/workflow/dsl-schema.js +6 -2
  507. package/packages/@monomind/cli/dist/src/workflow/template-engine.js +7 -0
  508. package/packages/@monomind/cli/dist/src/workflow/workflow-executor.js +95 -14
  509. package/packages/@monomind/cli/package.json +5 -3
  510. package/packages/@monomind/guidance/README.md +1192 -0
  511. package/packages/@monomind/shared/README.md +322 -0
  512. package/packages/@monomind/shared/dist/types/consensus-audit.d.ts +3 -1
  513. package/packages/README.md +513 -0
  514. package/.claude/agents/design/design-brand-guardian.md +0 -323
  515. package/.claude/agents/design/design-image-prompt-engineer.md +0 -237
  516. package/.claude/agents/design/design-inclusive-visuals-specialist.md +0 -72
  517. package/.claude/agents/design/design-ui-designer.md +0 -384
  518. package/.claude/agents/design/design-ux-architect.md +0 -470
  519. package/.claude/agents/design/design-ux-researcher.md +0 -330
  520. package/.claude/agents/design/design-visual-storyteller.md +0 -150
  521. package/.claude/agents/design/design-whimsy-injector.md +0 -439
  522. package/.claude/agents/v3/integration-architect.md +0 -338
  523. package/.claude/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +0 -54
  524. package/.claude/commands/coordination/init.md +0 -44
  525. package/.claude/commands/coordination/orchestrate.md +0 -43
  526. package/.claude/commands/coordination/spawn.md +0 -45
  527. package/.claude/commands/github/code-review-swarm.md +0 -550
  528. package/.claude/commands/github/code-review.md +0 -25
  529. package/.claude/commands/github/github-swarm.md +0 -121
  530. package/.claude/commands/github/issue-triage.md +0 -25
  531. package/.claude/commands/github/multi-repo-swarm.md +0 -519
  532. package/.claude/commands/github/pr-enhance.md +0 -26
  533. package/.claude/commands/github/project-board-sync.md +0 -471
  534. package/.claude/commands/github/release-swarm.md +0 -590
  535. package/.claude/commands/github/repo-analyze.md +0 -25
  536. package/.claude/commands/github/swarm-issue.md +0 -482
  537. package/.claude/commands/github/swarm-pr.md +0 -310
  538. package/.claude/commands/github/workflow-automation.md +0 -468
  539. package/.claude/commands/hive-mind/hive-mind-metrics.md +0 -8
  540. package/.claude/commands/hive-mind/hive-mind-resume.md +0 -8
  541. package/.claude/commands/hive-mind/hive-mind-sessions.md +0 -8
  542. package/.claude/commands/hive-mind/hive-mind-wizard.md +0 -8
  543. package/.claude/commands/list-agents.md +0 -17
  544. package/.claude/commands/memory/memory-persist.md +0 -25
  545. package/.claude/commands/memory/memory-usage.md +0 -25
  546. package/.claude/commands/memory/neural.md +0 -47
  547. package/.claude/commands/metrics.md +0 -11
  548. package/.claude/commands/monitoring/real-time-view.md +0 -25
  549. package/.claude/commands/monitoring/swarm-monitor.md +0 -25
  550. package/.claude/commands/monomind-createtask.md +0 -302
  551. package/.claude/commands/monomind-help.md +0 -103
  552. package/.claude/commands/monomind-memory.md +0 -107
  553. package/.claude/commands/monomind-repeat.md +0 -149
  554. package/.claude/commands/monomind-swarm.md +0 -205
  555. package/.claude/commands/optimization/cache-manage.md +0 -25
  556. package/.claude/commands/optimization/topology-optimize.md +0 -25
  557. package/.claude/commands/pair/commands.md +0 -546
  558. package/.claude/commands/pair/config.md +0 -510
  559. package/.claude/commands/pair/start.md +0 -209
  560. package/.claude/commands/use-agent.md +0 -67
  561. package/.claude/skills/monomind-createtask/SKILL.md +0 -269
  562. package/.claude/skills/monomind-task-engine/SKILL.md +0 -358
  563. /package/.claude/agents/{v3 → specialists}/memory-specialist.md +0 -0
  564. /package/.claude/agents/{v3 → specialists}/performance-engineer.md +0 -0
  565. /package/.claude/agents/{v3 → specialists}/queen-coordinator.md +0 -0
  566. /package/.claude/agents/{v3 → specialists}/security-architect.md +0 -0
@@ -18,10 +18,53 @@
18
18
  */
19
19
  import * as path from 'path';
20
20
  import * as crypto from 'crypto';
21
+ /**
22
+ * Validate a deserialized embedding before use in cosineSim/HNSW math.
23
+ *
24
+ * SECURITY: stored embeddings come from the same write path that any agent or
25
+ * imported pattern bundle can use. Without validation, an attacker can store an
26
+ * embedding of `[1e9 numbers]` (50 MB JSON parse cost), inject NaN values that
27
+ * poison ranking via NaN-comparison undefined behavior, or pass huge dimensions
28
+ * that make cosineSim O(N) per row blow up. The 1000-row search cap then
29
+ * amplifies a single poisoned row into multi-GB allocations on every search.
30
+ *
31
+ * Returns the parsed embedding when valid, or null when the JSON should be
32
+ * skipped (caller treats it like "no embedding stored").
33
+ */
34
+ const MAX_EMBEDDING_DIMS = 8192;
35
+ const MAX_EMBEDDING_JSON_BYTES = MAX_EMBEDDING_DIMS * 32; // ~256KB ceiling
36
+ export function safeParseEmbedding(raw) {
37
+ if (typeof raw !== 'string' || raw.length === 0)
38
+ return null;
39
+ if (raw.length > MAX_EMBEDDING_JSON_BYTES)
40
+ return null;
41
+ let parsed;
42
+ try {
43
+ parsed = JSON.parse(raw);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ if (!Array.isArray(parsed))
49
+ return null;
50
+ if (parsed.length === 0 || parsed.length > MAX_EMBEDDING_DIMS)
51
+ return null;
52
+ for (let i = 0; i < parsed.length; i++) {
53
+ const v = parsed[i];
54
+ if (typeof v !== 'number' || !Number.isFinite(v))
55
+ return null;
56
+ }
57
+ return parsed;
58
+ }
21
59
  // ===== Lazy singleton =====
60
+ // registryInstance is typed as `any` because ControllerRegistry lives in @monomind/memory
61
+ // and cross-package type resolution is currently broken. When that is fixed, replace with
62
+ // the real import: import type { ControllerRegistry } from '@monomind/memory'.
22
63
  let registryPromise = null;
23
64
  let registryInstance = null;
24
65
  let bridgeAvailable = null;
66
+ /** Backpressure flag for A-MEM Zettelkasten linking — see bridgeStoreEntry. */
67
+ let _amemInFlight = false;
25
68
  /**
26
69
  * Resolve database path with path traversal protection.
27
70
  * Only allows paths within or below the project's .swarm directory,
@@ -34,9 +77,10 @@ function getDbPath(customPath) {
34
77
  if (customPath === ':memory:')
35
78
  return ':memory:';
36
79
  const resolved = path.resolve(customPath);
37
- // Ensure the path doesn't escape the working directory
80
+ // Ensure the path doesn't escape the working directory (path-separator-aware check)
38
81
  const cwd = process.cwd();
39
- if (!resolved.startsWith(cwd)) {
82
+ const rel = path.relative(cwd, resolved);
83
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
40
84
  return path.join(swarmDir, 'memory.db'); // fallback to safe default
41
85
  }
42
86
  return resolved;
@@ -49,7 +93,7 @@ function generateId(prefix) {
49
93
  }
50
94
  /**
51
95
  * Lazily initialize the ControllerRegistry singleton.
52
- * Returns null if @monoes/memory is not available.
96
+ * Returns null if @monomind/memory is not available.
53
97
  */
54
98
  async function getRegistry(dbPath) {
55
99
  if (bridgeAvailable === false)
@@ -59,7 +103,7 @@ async function getRegistry(dbPath) {
59
103
  if (!registryPromise) {
60
104
  registryPromise = (async () => {
61
105
  try {
62
- const { ControllerRegistry } = await import('@monoes/memory');
106
+ const { ControllerRegistry } = await import('@monomind/memory');
63
107
  const registry = new ControllerRegistry();
64
108
  // Suppress noisy console.log during init
65
109
  const origLog = console.log;
@@ -117,7 +161,7 @@ function bm25Score(queryTerms, docContent, avgDocLength, docCount, termDocFreqs)
117
161
  const docLength = docWords.length;
118
162
  let score = 0;
119
163
  for (const term of queryTerms) {
120
- const tf = docWords.filter(w => w === term || w.includes(term)).length;
164
+ const tf = docWords.filter(w => w === term).length;
121
165
  if (tf === 0)
122
166
  continue;
123
167
  const df = termDocFreqs.get(term) || 1;
@@ -229,6 +273,7 @@ async function logAttestation(registry, operation, entryId, metadata) {
229
273
  // Non-fatal — attestation is observability, not correctness
230
274
  }
231
275
  }
276
+ const _dbInitialized = new WeakSet();
232
277
  /**
233
278
  * Get the AgentDB database handle and ensure memory_entries table exists.
234
279
  * Returns null if not available.
@@ -238,6 +283,8 @@ function getDb(registry) {
238
283
  if (!agentdb?.database)
239
284
  return null;
240
285
  const db = agentdb.database;
286
+ if (_dbInitialized.has(db))
287
+ return { db, agentdb };
241
288
  // Ensure memory_entries table exists (idempotent)
242
289
  try {
243
290
  db.exec(`CREATE TABLE IF NOT EXISTS memory_entries (
@@ -286,6 +333,7 @@ function getDb(registry) {
286
333
  catch {
287
334
  // Table already exists or db is read-only — that's fine
288
335
  }
336
+ _dbInitialized.add(db);
289
337
  return { db, agentdb };
290
338
  }
291
339
  // ===== Bridge functions — match memory-initializer.ts signatures =====
@@ -302,7 +350,16 @@ export async function bridgeStoreEntry(options) {
302
350
  if (!ctx)
303
351
  return null;
304
352
  try {
305
- const { key, value, namespace = 'default', tags = [], ttl } = options;
353
+ const { key, value, namespace = 'default', tags: rawTags = [], ttl } = options;
354
+ // SECURITY: cap tags array length and per-tag length. Without these, any
355
+ // memory_store caller (every spawned agent) could submit
356
+ // tags: new Array(1e5).fill("x".repeat(1e4)) → ~1GB persisted blob,
357
+ // re-parsed on every bridgeGetEntry. Mirrors the embedding/BM25 caps.
358
+ const MAX_TAGS = 32;
359
+ const MAX_TAG_LEN = 64;
360
+ const tags = Array.isArray(rawTags)
361
+ ? rawTags.filter(t => typeof t === 'string' && t.length > 0 && t.length <= MAX_TAG_LEN).slice(0, MAX_TAGS)
362
+ : [];
306
363
  const id = generateId('entry');
307
364
  const now = Date.now();
308
365
  // Phase 5: MutationGuard validation before write
@@ -345,11 +402,7 @@ export async function bridgeStoreEntry(options) {
345
402
  const stmt = ctx.db.prepare(insertSql);
346
403
  stmt.run(id, key, namespace, value, embeddingJson, dimensions || null, model, tags.length > 0 ? JSON.stringify(tags) : null, '{}', now, now, now, // created_at, updated_at, event_at (bi-temporal: default eventAt = ingestion time)
347
404
  ttl ? now + (ttl * 1000) : null);
348
- // Phase 2: Write-through to TieredCache
349
- const safeNs = String(namespace).replace(/:/g, '_');
350
- const safeKey = String(key).replace(/:/g, '_');
351
- const cacheKey = `entry:${safeNs}:${safeKey}`;
352
- await cacheSet(registry, cacheKey, { id, key, namespace, content: value, embedding: embeddingJson });
405
+ // Phase 2: Write-through to TieredCache deferred — full entry populated on first read
353
406
  // Phase 4: AttestationLog write audit
354
407
  await logAttestation(registry, 'store', id, { key, namespace, hasEmbedding: !!embeddingJson });
355
408
  const storeResult = {
@@ -362,31 +415,42 @@ export async function bridgeStoreEntry(options) {
362
415
  };
363
416
  // A-MEM: Post-write Zettelkasten linking — find top-3 semantic neighbors and create causal edges
364
417
  // Source: https://arxiv.org/abs/2502.12110
365
- void (async () => {
366
- try {
367
- const neighbors = await bridgeSearchEntries({
368
- query: options.value, // A-MEM: search by content, not key string
369
- namespace: options.namespace,
370
- limit: 3,
371
- threshold: 0.7,
372
- dbPath: options.dbPath,
373
- });
374
- if (neighbors?.results) {
375
- for (const neighbor of neighbors.results) {
376
- if (neighbor.id !== id) {
377
- await bridgeRecordCausalEdge({
378
- sourceId: id,
379
- targetId: neighbor.id,
380
- relation: 'similar',
381
- weight: neighbor.score,
382
- dbPath: options.dbPath,
383
- });
418
+ //
419
+ // Backpressure: limit concurrent A-MEM linking to 1 per process. Without this
420
+ // a burst of N concurrent stores triggers N full-corpus searches in flight,
421
+ // each O(rows × dims) on cosineSim, which combined with poisoned embeddings
422
+ // can wedge the process. We drop new linking work if one is already running.
423
+ if (!_amemInFlight) {
424
+ _amemInFlight = true;
425
+ void (async () => {
426
+ try {
427
+ const neighbors = await bridgeSearchEntries({
428
+ query: options.value,
429
+ namespace: options.namespace,
430
+ limit: 3,
431
+ threshold: 0.7,
432
+ dbPath: options.dbPath,
433
+ });
434
+ if (neighbors?.results) {
435
+ for (const neighbor of neighbors.results) {
436
+ if (neighbor.id !== id) {
437
+ await bridgeRecordCausalEdge({
438
+ sourceId: id,
439
+ targetId: neighbor.id,
440
+ relation: 'similar',
441
+ weight: neighbor.score,
442
+ dbPath: options.dbPath,
443
+ });
444
+ }
384
445
  }
385
446
  }
386
447
  }
387
- }
388
- catch { /* non-critical background operation */ }
389
- })();
448
+ catch { /* non-critical background operation */ }
449
+ finally {
450
+ _amemInFlight = false;
451
+ }
452
+ })();
453
+ }
390
454
  return storeResult;
391
455
  }
392
456
  catch {
@@ -438,23 +502,25 @@ export async function bridgeSearchEntries(options) {
438
502
  catch {
439
503
  return null;
440
504
  }
441
- // Phase 2: Compute BM25 term stats for the corpus
442
- const queryTerms = queryStr.toLowerCase().split(/\s+/).filter(t => t.length > 1);
505
+ // Phase 2: Compute BM25 term stats for the corpus.
506
+ // Cap query terms to 32 — bm25Score is O(terms × rows × words/row), so an
507
+ // attacker passing "x ".repeat(10000) would otherwise burn multi-second CPU per
508
+ // search, and the post-store fan-out (bridgeStoreEntry IIFE) amplifies this.
509
+ const MAX_QUERY_TERMS = 32;
510
+ const queryTerms = Array.from(new Set(queryStr.toLowerCase().split(/\s+/).filter(t => t.length > 1))).slice(0, MAX_QUERY_TERMS);
443
511
  const { termDocFreqs, avgDocLength } = computeTermDocFreqs(queryTerms, rows);
444
512
  const docCount = rows.length;
445
513
  const results = [];
446
514
  for (const row of rows) {
447
515
  let semanticScore = 0;
448
516
  let bm25ScoreVal = 0;
449
- // Semantic scoring via cosine similarity
517
+ // Semantic scoring via cosine similarity (validated to reject oversized,
518
+ // NaN-poisoned, or non-array embeddings — see safeParseEmbedding above).
450
519
  if (queryEmbedding && row.embedding) {
451
- try {
452
- const embedding = JSON.parse(row.embedding);
520
+ const embedding = safeParseEmbedding(row.embedding);
521
+ if (embedding && embedding.length === queryEmbedding.length) {
453
522
  semanticScore = cosineSim(queryEmbedding, embedding);
454
523
  }
455
- catch {
456
- // Invalid embedding
457
- }
458
524
  }
459
525
  // Phase 2: BM25 keyword scoring (replaces String.includes fallback)
460
526
  if (queryTerms.length > 0 && row.content) {
@@ -473,7 +539,7 @@ export async function bridgeSearchEntries(options) {
473
539
  ? `semantic:${semanticScore.toFixed(3)}+bm25:${bm25ScoreVal.toFixed(3)}`
474
540
  : `bm25:${bm25ScoreVal.toFixed(3)}`;
475
541
  results.push({
476
- id: String(row.id).substring(0, 12),
542
+ id: String(row.id),
477
543
  key: row.key || String(row.id).substring(0, 15),
478
544
  content: (row.content || '').substring(0, 60) + ((row.content || '').length > 60 ? '...' : ''),
479
545
  score,
@@ -505,7 +571,11 @@ export async function bridgeListEntries(options) {
505
571
  if (!ctx)
506
572
  return null;
507
573
  try {
508
- const { namespace, limit = 20, offset = 0 } = options;
574
+ const rawLimit = options.limit ?? 20;
575
+ const rawOffset = options.offset ?? 0;
576
+ const limit = Math.max(1, Math.min(Number.isFinite(rawLimit) ? rawLimit : 20, 500));
577
+ const offset = Math.max(0, Number.isFinite(rawOffset) ? rawOffset : 0);
578
+ const { namespace } = options;
509
579
  const nsFilter = namespace ? `AND namespace = ?` : '';
510
580
  const nsParams = namespace ? [namespace] : [];
511
581
  // Count
@@ -531,13 +601,13 @@ export async function bridgeListEntries(options) {
531
601
  const rows = stmt.all(...nsParams, limit, offset);
532
602
  for (const row of rows) {
533
603
  entries.push({
534
- id: String(row.id).substring(0, 20),
604
+ id: String(row.id),
535
605
  key: row.key || String(row.id).substring(0, 15),
536
606
  namespace: row.namespace || 'default',
537
607
  size: (row.content || '').length,
538
608
  accessCount: row.access_count ?? 0,
539
- createdAt: row.created_at || new Date().toISOString(),
540
- updatedAt: row.updated_at || new Date().toISOString(),
609
+ createdAt: row.created_at ? new Date(row.created_at).toISOString() : new Date().toISOString(),
610
+ updatedAt: row.updated_at ? new Date(row.updated_at).toISOString() : new Date().toISOString(),
541
611
  hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
542
612
  });
543
613
  }
@@ -624,10 +694,16 @@ export async function bridgeGetEntry(options) {
624
694
  }
625
695
  catch { /* non-critical */ }
626
696
  }
697
+ // Bounded tags read — refuse to JSON.parse a multi-MB tags blob that an
698
+ // older write may have persisted before the write-side cap was added.
699
+ const MAX_TAGS_JSON_BYTES = 32 * 64 + 256;
627
700
  let tags = [];
628
- if (row.tags) {
701
+ if (row.tags && typeof row.tags === 'string' && row.tags.length <= MAX_TAGS_JSON_BYTES) {
629
702
  try {
630
- tags = JSON.parse(row.tags);
703
+ const parsed = JSON.parse(row.tags);
704
+ if (Array.isArray(parsed)) {
705
+ tags = parsed.filter((t) => typeof t === 'string' && t.length <= 64).slice(0, 32);
706
+ }
631
707
  }
632
708
  catch { /* invalid */ }
633
709
  }
@@ -637,8 +713,8 @@ export async function bridgeGetEntry(options) {
637
713
  namespace: row.namespace || 'default',
638
714
  content: row.content || '',
639
715
  accessCount: (row.access_count ?? 0) + 1,
640
- createdAt: row.created_at || new Date().toISOString(),
641
- updatedAt: row.updated_at || new Date().toISOString(),
716
+ createdAt: row.created_at ? new Date(row.created_at).toISOString() : new Date().toISOString(),
717
+ updatedAt: row.updated_at ? new Date(row.updated_at).toISOString() : new Date().toISOString(),
642
718
  hasEmbedding: !!(row.embedding && String(row.embedding).length > 10),
643
719
  tags,
644
720
  };
@@ -837,11 +913,13 @@ export async function bridgeSearchHNSW(queryEmbedding, options, dbPath) {
837
913
  if (!row.embedding)
838
914
  continue;
839
915
  try {
840
- const emb = JSON.parse(row.embedding);
916
+ const emb = safeParseEmbedding(row.embedding);
917
+ if (!emb || emb.length !== queryEmbedding.length)
918
+ continue;
841
919
  const score = cosineSim(queryEmbedding, emb);
842
920
  if (score >= threshold) {
843
921
  results.push({
844
- id: String(row.id).substring(0, 12),
922
+ id: String(row.id),
845
923
  key: row.key || String(row.id).substring(0, 15),
846
924
  content: (row.content || '').substring(0, 60) +
847
925
  ((row.content || '').length > 60 ? '...' : ''),
@@ -873,6 +951,13 @@ export async function bridgeAddToHNSW(id, embedding, entry, dbPath) {
873
951
  if (!ctx)
874
952
  return null;
875
953
  try {
954
+ if (!Array.isArray(embedding) || embedding.length === 0 || embedding.length > MAX_EMBEDDING_DIMS) {
955
+ return null;
956
+ }
957
+ for (const v of embedding) {
958
+ if (typeof v !== 'number' || !Number.isFinite(v))
959
+ return null;
960
+ }
876
961
  const now = Date.now();
877
962
  const embeddingJson = JSON.stringify(embedding);
878
963
  ctx.db.prepare(`
@@ -1439,6 +1524,11 @@ export async function bridgeConsolidate(params) {
1439
1524
  * - update: calls bulkUpdate(table, updates, conditions) on episodes table
1440
1525
  */
1441
1526
  export async function bridgeBatchOperation(params) {
1527
+ const MAX_BATCH_ENTRIES = 500;
1528
+ const MAX_ENTRY_CONTENT_BYTES = 1 * 1024 * 1024;
1529
+ if (!Array.isArray(params.entries) || params.entries.length > MAX_BATCH_ENTRIES) {
1530
+ return { success: false, error: 'Batch too large or entries not an array' };
1531
+ }
1442
1532
  const registry = await getRegistry();
1443
1533
  if (!registry)
1444
1534
  return null;
@@ -1450,10 +1540,13 @@ export async function bridgeBatchOperation(params) {
1450
1540
  switch (params.operation) {
1451
1541
  case 'insert': {
1452
1542
  // insertEpisodes expects [{content, metadata?, embedding?}]
1453
- const episodes = params.entries.map((e) => ({
1454
- content: e.value || e.content || JSON.stringify(e),
1455
- metadata: e.metadata || { key: e.key },
1456
- }));
1543
+ const episodes = params.entries.map((e) => {
1544
+ const rawContent = e.value || e.content || JSON.stringify(e);
1545
+ const content = typeof rawContent === 'string' && rawContent.length <= MAX_ENTRY_CONTENT_BYTES
1546
+ ? rawContent
1547
+ : typeof rawContent === 'string' ? rawContent.slice(0, MAX_ENTRY_CONTENT_BYTES) : '';
1548
+ return { content, metadata: e.metadata || { key: e.key } };
1549
+ });
1457
1550
  result = await batch.insertEpisodes(episodes);
1458
1551
  break;
1459
1552
  }
@@ -10,6 +10,36 @@
10
10
  */
11
11
  import * as fs from 'fs';
12
12
  import * as path from 'path';
13
+ /**
14
+ * Local validator for stored embeddings — rejects oversized JSON, NaN/Infinity
15
+ * values, non-arrays, and out-of-bound dimensions before they reach cosineSim
16
+ * or HNSW math (which would otherwise OOM or poison ranking with NaN).
17
+ */
18
+ const _MAX_EMBEDDING_DIMS = 8192;
19
+ const _MAX_EMBEDDING_JSON_BYTES = _MAX_EMBEDDING_DIMS * 32;
20
+ function safeParseEmbeddingLocal(raw) {
21
+ if (typeof raw !== 'string' || raw.length === 0)
22
+ return null;
23
+ if (raw.length > _MAX_EMBEDDING_JSON_BYTES)
24
+ return null;
25
+ let parsed;
26
+ try {
27
+ parsed = JSON.parse(raw);
28
+ }
29
+ catch {
30
+ return null;
31
+ }
32
+ if (!Array.isArray(parsed))
33
+ return null;
34
+ if (parsed.length === 0 || parsed.length > _MAX_EMBEDDING_DIMS)
35
+ return null;
36
+ for (let i = 0; i < parsed.length; i++) {
37
+ const v = parsed[i];
38
+ if (typeof v !== 'number' || !Number.isFinite(v))
39
+ return null;
40
+ }
41
+ return parsed;
42
+ }
13
43
  // ADR-053: Lazy import of AgentDB v1 bridge
14
44
  let _bridge;
15
45
  async function getBridge() {
@@ -334,9 +364,14 @@ export async function getHNSWIndex(options) {
334
364
  }
335
365
  // Prevent concurrent initialization
336
366
  if (hnswInitializing) {
337
- // Wait for initialization to complete
338
- while (hnswInitializing) {
367
+ // Wait for initialization to complete (max 5s)
368
+ let waitIterations = 0;
369
+ while (hnswInitializing && waitIterations < 500) {
339
370
  await new Promise(resolve => setTimeout(resolve, 10));
371
+ waitIterations++;
372
+ }
373
+ if (hnswInitializing) {
374
+ throw new Error('HNSW initialization timed out after 5s');
340
375
  }
341
376
  return hnswIndex;
342
377
  }
@@ -401,6 +436,13 @@ export async function getHNSWIndex(options) {
401
436
  }
402
437
  if (fs.existsSync(dbPath)) {
403
438
  try {
439
+ // Reject symlinks and oversized DB files. Without this a symlink at the
440
+ // dbPath pointing at /dev/zero or a 100GB sparse file would OOM the CLI
441
+ // on the next memory operation.
442
+ const stat = fs.lstatSync(dbPath);
443
+ if (stat.isSymbolicLink() || stat.size > 256 * 1024 * 1024) {
444
+ return null;
445
+ }
404
446
  const initSqlJs = (await import('sql.js')).default;
405
447
  const SQL = await initSqlJs();
406
448
  const fileBuffer = fs.readFileSync(dbPath);
@@ -417,7 +459,9 @@ export async function getHNSWIndex(options) {
417
459
  const [id, key, ns, content, embeddingJson] = row;
418
460
  if (embeddingJson) {
419
461
  try {
420
- const embedding = JSON.parse(embeddingJson);
462
+ const embedding = safeParseEmbeddingLocal(embeddingJson);
463
+ if (!embedding)
464
+ continue;
421
465
  const vector = new Float32Array(embedding);
422
466
  await db.insert({
423
467
  id: String(id),
@@ -461,7 +505,9 @@ function saveHNSWMetadata() {
461
505
  const swarmDir = path.join(process.cwd(), '.swarm');
462
506
  const metadataPath = path.join(swarmDir, 'hnsw.metadata.json');
463
507
  const metadata = Array.from(hnswIndex.entries.entries());
464
- fs.writeFileSync(metadataPath, JSON.stringify(metadata));
508
+ const tmp = metadataPath + '.tmp';
509
+ fs.writeFileSync(tmp, JSON.stringify(metadata));
510
+ fs.renameSync(tmp, metadataPath);
465
511
  }
466
512
  catch {
467
513
  // Silently fail - metadata save is best-effort
@@ -799,10 +845,11 @@ export function flashAttentionSearch(query, vectors, options = {}) {
799
845
  * Initial metadata to insert after schema creation
800
846
  */
801
847
  export function getInitialMetadata(backend) {
848
+ const safeBackend = backend.replace(/'/g, "''");
802
849
  return `
803
850
  INSERT OR REPLACE INTO metadata (key, value) VALUES
804
851
  ('schema_version', '3.0.0'),
805
- ('backend', '${backend}'),
852
+ ('backend', '${safeBackend}'),
806
853
  ('created_at', '${new Date().toISOString()}'),
807
854
  ('sql_js', 'true'),
808
855
  ('vector_embeddings', 'enabled'),
@@ -863,9 +910,11 @@ export async function ensureSchemaColumns(dbPath) {
863
910
  }
864
911
  }
865
912
  if (modified) {
866
- // Save updated database
913
+ // Save updated database (atomic to avoid corruption on crash)
867
914
  const data = db.export();
868
- fs.writeFileSync(dbPath, Buffer.from(data));
915
+ const tmp = dbPath + '.tmp';
916
+ fs.writeFileSync(tmp, Buffer.from(data));
917
+ fs.renameSync(tmp, dbPath);
869
918
  }
870
919
  db.close();
871
920
  return { success: true, columnsAdded };
@@ -931,7 +980,7 @@ export async function checkAndMigrateLegacy(options) {
931
980
  * a singleton ControllerRegistry and initializes it with the given dbPath.
932
981
  * After this call, all enabled controllers are ready for immediate use.
933
982
  *
934
- * Failures are isolated: if @monoes/memory or agentdb is not installed,
983
+ * Failures are isolated: if @monomind/memory or agentdb is not installed,
935
984
  * this returns an empty result without throwing.
936
985
  */
937
986
  async function activateControllerRegistry(dbPath, verbose) {
@@ -1032,15 +1081,20 @@ export async function initializeMemoryDatabase(options) {
1032
1081
  db.run(MEMORY_SCHEMA);
1033
1082
  // Insert initial metadata
1034
1083
  db.run(getInitialMetadata(backend));
1035
- // Save to file
1084
+ // Save to file atomically — direct writeFileSync to dbPath would corrupt
1085
+ // the SQLite file if the process crashes mid-write. tmp+rename is atomic on POSIX.
1036
1086
  const data = db.export();
1037
1087
  const buffer = Buffer.from(data);
1038
- fs.writeFileSync(dbPath, buffer);
1088
+ const dbTmp = dbPath + '.tmp';
1089
+ fs.writeFileSync(dbTmp, buffer);
1090
+ fs.renameSync(dbTmp, dbPath);
1039
1091
  // Close database
1040
1092
  db.close();
1041
- // Also create schema file for reference
1093
+ // Also create schema file for reference (atomic)
1042
1094
  const schemaPath = path.join(dbDir, 'schema.sql');
1043
- fs.writeFileSync(schemaPath, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
1095
+ const schemaTmp = schemaPath + '.tmp';
1096
+ fs.writeFileSync(schemaTmp, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
1097
+ fs.renameSync(schemaTmp, schemaPath);
1044
1098
  // ADR-053: Activate ControllerRegistry so controllers (ReasoningBank,
1045
1099
  // SkillLibrary, ExplainableRecall, etc.) are instantiated during init
1046
1100
  const controllerResult = await activateControllerRegistry(dbPath, verbose);
@@ -1086,9 +1140,11 @@ export async function initializeMemoryDatabase(options) {
1086
1140
  };
1087
1141
  }
1088
1142
  else {
1089
- // Fall back to schema file approach
1143
+ // Fall back to schema file approach (atomic writes)
1090
1144
  const schemaPath = path.join(dbDir, 'schema.sql');
1091
- fs.writeFileSync(schemaPath, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
1145
+ const schemaTmpFb = schemaPath + '.tmp';
1146
+ fs.writeFileSync(schemaTmpFb, MEMORY_SCHEMA + '\n' + getInitialMetadata(backend));
1147
+ fs.renameSync(schemaTmpFb, schemaPath);
1092
1148
  // Create minimal valid SQLite file
1093
1149
  const sqliteHeader = Buffer.alloc(4096, 0);
1094
1150
  // SQLite format 3 header
@@ -1101,7 +1157,9 @@ export async function initializeMemoryDatabase(options) {
1101
1157
  sqliteHeader[25] = 0x40;
1102
1158
  sqliteHeader[26] = 0x20; // min embedded payload
1103
1159
  sqliteHeader[27] = 0x20; // leaf payload
1104
- fs.writeFileSync(dbPath, sqliteHeader);
1160
+ const dbTmpFb = dbPath + '.tmp';
1161
+ fs.writeFileSync(dbTmpFb, sqliteHeader);
1162
+ fs.renameSync(dbTmpFb, dbPath);
1105
1163
  // ADR-053: Activate ControllerRegistry even on fallback path
1106
1164
  const controllerResult = await activateControllerRegistry(dbPath, verbose);
1107
1165
  return {
@@ -1224,9 +1282,11 @@ export async function applyTemporalDecay(dbPath) {
1224
1282
  `;
1225
1283
  db.run(decayQuery, [now, now, now]);
1226
1284
  const changes = db.getRowsModified();
1227
- // Save
1285
+ // Save atomically
1228
1286
  const data = db.export();
1229
- fs.writeFileSync(path_, Buffer.from(data));
1287
+ const dbTmpDecay = path_ + '.tmp';
1288
+ fs.writeFileSync(dbTmpDecay, Buffer.from(data));
1289
+ fs.renameSync(dbTmpDecay, path_);
1230
1290
  db.close();
1231
1291
  return {
1232
1292
  success: true,
@@ -1398,6 +1458,13 @@ export async function loadEmbeddingModel(options) {
1398
1458
  * Uses ONNX model if available, falls back to deterministic hash
1399
1459
  */
1400
1460
  export async function generateEmbedding(text) {
1461
+ // Cap input text — caller may pass arbitrarily large content. Without this
1462
+ // cap, the hash-fallback below burns O(text.length × dimension) sin() calls
1463
+ // per call, and ONNX tokenization can saturate memory on multi-MB inputs.
1464
+ if (typeof text !== 'string')
1465
+ text = String(text ?? '');
1466
+ if (text.length > 16 * 1024)
1467
+ text = text.slice(0, 16 * 1024);
1401
1468
  // ADR-053: Try AgentDB v1 bridge first
1402
1469
  const bridge = await getBridge();
1403
1470
  if (bridge) {
@@ -1652,9 +1719,11 @@ export async function verifyMemoryInit(dbPath, options) {
1652
1719
  }
1653
1720
  // Cleanup test entry
1654
1721
  db.run(`DELETE FROM memory_entries WHERE id = ?`, [testId]);
1655
- // Save changes
1722
+ // Save changes atomically
1656
1723
  const data = db.export();
1657
- fs.writeFileSync(dbPath, Buffer.from(data));
1724
+ const dbTmpHealth = dbPath + '.tmp';
1725
+ fs.writeFileSync(dbTmpHealth, Buffer.from(data));
1726
+ fs.renameSync(dbTmpHealth, dbPath);
1658
1727
  db.close();
1659
1728
  const passed = tests.filter(t => t.passed).length;
1660
1729
  const failed = tests.filter(t => !t.passed).length;
@@ -1744,19 +1813,22 @@ export async function storeEntry(options) {
1744
1813
  now,
1745
1814
  ttl ? now + (ttl * 1000) : null
1746
1815
  ]);
1747
- // Save
1816
+ // Save atomically
1748
1817
  const data = db.export();
1749
- fs.writeFileSync(dbPath, Buffer.from(data));
1818
+ const dbTmpStore = dbPath + '.tmp';
1819
+ fs.writeFileSync(dbTmpStore, Buffer.from(data));
1820
+ fs.renameSync(dbTmpStore, dbPath);
1750
1821
  db.close();
1751
- // Add to HNSW index for faster future searches
1822
+ // Add to HNSW index for faster future searches (validated to reject malformed embeddings)
1752
1823
  if (embeddingJson) {
1753
- const embResult = JSON.parse(embeddingJson);
1754
- await addToHNSWIndex(id, embResult, {
1755
- id,
1756
- key,
1757
- namespace,
1758
- content: value
1759
- });
1824
+ const embResult = safeParseEmbeddingLocal(embeddingJson);
1825
+ if (embResult)
1826
+ await addToHNSWIndex(id, embResult, {
1827
+ id,
1828
+ key,
1829
+ namespace,
1830
+ content: value
1831
+ });
1760
1832
  }
1761
1833
  return {
1762
1834
  success: true,
@@ -1834,13 +1906,10 @@ export async function searchEntries(options) {
1834
1906
  const [id, key, ns, content, embeddingJson] = row;
1835
1907
  let score = 0;
1836
1908
  if (embeddingJson) {
1837
- try {
1838
- const embedding = JSON.parse(embeddingJson);
1909
+ const embedding = safeParseEmbeddingLocal(embeddingJson);
1910
+ if (embedding && embedding.length === queryEmbedding.length) {
1839
1911
  score = cosineSim(queryEmbedding, embedding);
1840
1912
  }
1841
- catch {
1842
- // Invalid embedding, use keyword score
1843
- }
1844
1913
  }
1845
1914
  // Fallback to keyword matching
1846
1915
  if (score < threshold) {
@@ -2032,15 +2101,6 @@ export async function getEntry(options) {
2032
2101
  return { success: true, found: false };
2033
2102
  }
2034
2103
  const [id, entryKey, ns, content, embedding, accessCount, createdAt, updatedAt, tagsJson] = result[0].values[0];
2035
- // Update access count
2036
- db.run(`
2037
- UPDATE memory_entries
2038
- SET access_count = access_count + 1, last_accessed_at = strftime('%s', 'now') * 1000
2039
- WHERE id = ?
2040
- `, [String(id)]);
2041
- // Save updated database
2042
- const data = db.export();
2043
- fs.writeFileSync(dbPath, Buffer.from(data));
2044
2104
  db.close();
2045
2105
  let tags = [];
2046
2106
  if (tagsJson) {
@@ -2167,9 +2227,11 @@ export async function deleteEntry(options) {
2167
2227
  // Get remaining count
2168
2228
  const countResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE status = 'active'`);
2169
2229
  const remainingEntries = countResult[0]?.values?.[0]?.[0] || 0;
2170
- // Save updated database
2230
+ // Save updated database atomically
2171
2231
  const data = db.export();
2172
- fs.writeFileSync(dbPath, Buffer.from(data));
2232
+ const dbTmpDelete = dbPath + '.tmp';
2233
+ fs.writeFileSync(dbTmpDelete, Buffer.from(data));
2234
+ fs.renameSync(dbTmpDelete, dbPath);
2173
2235
  db.close();
2174
2236
  // Clean up in-memory HNSW index so ghost vectors don't appear in searches.
2175
2237
  // Remove the entry from the HNSW entries map and invalidate the index.