hippo-memory 1.71.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (625) hide show
  1. package/README.md +7 -5
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +11 -26
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/copilot.d.ts +1 -3
  7. package/dist/agent-memories/copilot.js +1 -17
  8. package/dist/agent-memories/project-folds.d.ts +10 -0
  9. package/dist/agent-memories/project-folds.js +34 -0
  10. package/dist/agent-memories/sync.js +8 -6
  11. package/dist/api/assemble.js +3 -2
  12. package/dist/api/audit.d.ts +30 -2
  13. package/dist/api/audit.js +48 -7
  14. package/dist/api/auth.d.ts +11 -9
  15. package/dist/api/auth.js +39 -40
  16. package/dist/api/auto-sleep.d.ts +5 -2
  17. package/dist/api/auto-sleep.js +7 -3
  18. package/dist/api/availability.js +2 -3
  19. package/dist/api/cards.d.ts +42 -0
  20. package/dist/api/cards.js +52 -0
  21. package/dist/api/conflicts.d.ts +28 -0
  22. package/dist/api/conflicts.js +61 -0
  23. package/dist/api/context-auto.js +4 -2
  24. package/dist/api/context-render.js +4 -3
  25. package/dist/api/context-select.js +15 -29
  26. package/dist/api/context.js +29 -18
  27. package/dist/api/continuity.d.ts +47 -0
  28. package/dist/api/continuity.js +66 -0
  29. package/dist/api/dormant.js +4 -2
  30. package/dist/api/drill-down.js +3 -2
  31. package/dist/api/embeddings.d.ts +17 -0
  32. package/dist/api/embeddings.js +28 -0
  33. package/dist/api/error-reply.d.ts +8 -0
  34. package/dist/api/error-reply.js +21 -0
  35. package/dist/api/forget.d.ts +7 -3
  36. package/dist/api/forget.js +24 -14
  37. package/dist/api/goals.d.ts +1 -1
  38. package/dist/api/goals.js +5 -9
  39. package/dist/api/graph.js +2 -1
  40. package/dist/api/index.d.ts +4 -2
  41. package/dist/api/index.js +4 -2
  42. package/dist/api/instruction-detect.js +5 -1
  43. package/dist/api/learn.d.ts +5 -1
  44. package/dist/api/learn.js +71 -44
  45. package/dist/api/ledger-db.d.ts +2 -6
  46. package/dist/api/ledger-db.js +4 -36
  47. package/dist/api/memories.d.ts +21 -1
  48. package/dist/api/memories.js +51 -1
  49. package/dist/api/objects.d.ts +1 -1
  50. package/dist/api/objects.js +2 -1
  51. package/dist/api/outcome.d.ts +5 -5
  52. package/dist/api/outcome.js +17 -16
  53. package/dist/api/pilot-arm.d.ts +1 -11
  54. package/dist/api/pilot-arm.js +5 -45
  55. package/dist/api/predictions.d.ts +3 -1
  56. package/dist/api/predictions.js +8 -1
  57. package/dist/api/projects.d.ts +21 -0
  58. package/dist/api/projects.js +24 -0
  59. package/dist/api/promote.d.ts +3 -3
  60. package/dist/api/promote.js +26 -28
  61. package/dist/api/prompt-hook.d.ts +17 -2
  62. package/dist/api/prompt-hook.js +45 -4
  63. package/dist/api/quarantine.js +2 -1
  64. package/dist/api/recall-cli.d.ts +3 -0
  65. package/dist/api/recall-cli.js +13 -4
  66. package/dist/api/recall-core.js +10 -5
  67. package/dist/api/recall-pipeline.js +23 -24
  68. package/dist/api/recall-request.js +1 -1
  69. package/dist/api/recall-types.d.ts +3 -1
  70. package/dist/api/recall.d.ts +0 -3
  71. package/dist/api/recall.js +51 -73
  72. package/dist/api/remember-local.d.ts +5 -2
  73. package/dist/api/remember-local.js +15 -7
  74. package/dist/api/remember.d.ts +7 -3
  75. package/dist/api/remember.js +19 -16
  76. package/dist/api/session-end.d.ts +46 -0
  77. package/dist/api/session-end.js +131 -0
  78. package/dist/api/sleep-run.d.ts +1 -1
  79. package/dist/api/sleep-run.js +16 -11
  80. package/dist/api/sleep.js +4 -3
  81. package/dist/api/status.d.ts +24 -0
  82. package/dist/api/status.js +40 -0
  83. package/dist/api/store-init.d.ts +4 -0
  84. package/dist/api/store-init.js +9 -0
  85. package/dist/api/tokens.js +2 -2
  86. package/dist/api/types.d.ts +3 -7
  87. package/dist/api/types.js +6 -1
  88. package/dist/capture/caller-session.d.ts +0 -3
  89. package/dist/capture/caller-session.js +1 -12
  90. package/dist/capture/capture-error.d.ts +2 -2
  91. package/dist/capture/capture-error.js +23 -18
  92. package/dist/capture/codex-patch.js +3 -1
  93. package/dist/capture/command.js +36 -95
  94. package/dist/capture/compact.js +10 -5
  95. package/dist/capture/compaction-items-caller.js +11 -20
  96. package/dist/capture/compaction-record.d.ts +7 -93
  97. package/dist/capture/compaction-record.js +29 -426
  98. package/dist/capture/compaction-spool.d.ts +7 -7
  99. package/dist/capture/compaction-spool.js +60 -51
  100. package/dist/capture/copilot-transcript.d.ts +2 -1
  101. package/dist/capture/copilot-transcript.js +2 -1
  102. package/dist/capture/extract.d.ts +5 -2
  103. package/dist/capture/extract.js +4 -3
  104. package/dist/capture/failure-caller.d.ts +1 -1
  105. package/dist/capture/failure-caller.js +21 -16
  106. package/dist/capture/failure-reading.d.ts +2 -1
  107. package/dist/capture/failure-reading.js +7 -9
  108. package/dist/capture/pre-compact-caller.js +5 -4
  109. package/dist/capture/session-digest.js +4 -3
  110. package/dist/capture/session-end-caller.js +3 -2
  111. package/dist/capture/session-worker.js +22 -10
  112. package/dist/capture/transcript.d.ts +2 -1
  113. package/dist/capture/transcript.js +6 -3
  114. package/dist/capture/working-state.d.ts +4 -2
  115. package/dist/capture/working-state.js +4 -2
  116. package/dist/cli/audit-prune.d.ts +0 -25
  117. package/dist/cli/audit-prune.js +1 -27
  118. package/dist/cli/audit.js +20 -20
  119. package/dist/cli/auth.d.ts +1 -1
  120. package/dist/cli/auth.js +16 -17
  121. package/dist/cli/briefs.d.ts +1 -4
  122. package/dist/cli/briefs.js +37 -292
  123. package/dist/cli/card.js +41 -33
  124. package/dist/cli/client.d.ts +6 -2
  125. package/dist/cli/client.js +37 -21
  126. package/dist/cli/compact-resume-payload.js +1 -1
  127. package/dist/cli/context.d.ts +1 -1
  128. package/dist/cli/context.js +13 -13
  129. package/dist/cli/continuity.d.ts +1 -1
  130. package/dist/cli/continuity.js +36 -39
  131. package/dist/cli/curate.d.ts +2 -2
  132. package/dist/cli/curate.js +32 -36
  133. package/dist/cli/dag.d.ts +1 -1
  134. package/dist/cli/dag.js +23 -8
  135. package/dist/cli/decisions.d.ts +0 -2
  136. package/dist/cli/decisions.js +7 -285
  137. package/dist/cli/eval.d.ts +1 -1
  138. package/dist/cli/eval.js +12 -13
  139. package/dist/cli/explain.d.ts +1 -1
  140. package/dist/cli/explain.js +21 -25
  141. package/dist/cli/flag-values.js +16 -6
  142. package/dist/cli/flags.d.ts +0 -289
  143. package/dist/cli/flags.js +3 -138
  144. package/dist/cli/graph.d.ts +3 -0
  145. package/dist/cli/graph.js +83 -0
  146. package/dist/cli/hook-runtime.d.ts +6 -6
  147. package/dist/cli/hook-runtime.js +9 -36
  148. package/dist/cli/incidents.d.ts +3 -0
  149. package/dist/cli/incidents.js +112 -0
  150. package/dist/cli/init.d.ts +1 -1
  151. package/dist/cli/init.js +28 -19
  152. package/dist/cli/install-steps.d.ts +2 -1
  153. package/dist/cli/install-steps.js +11 -3
  154. package/dist/cli/last-sleep.js +1 -1
  155. package/dist/cli/maintenance.d.ts +3 -3
  156. package/dist/cli/maintenance.js +29 -30
  157. package/dist/cli/notes.d.ts +2 -0
  158. package/dist/cli/notes.js +41 -0
  159. package/dist/cli/object-verbs.d.ts +2 -2
  160. package/dist/cli/object-verbs.js +4 -4
  161. package/dist/cli/open-browser.d.ts +14 -0
  162. package/dist/cli/open-browser.js +26 -0
  163. package/dist/cli/playbooks.d.ts +3 -4
  164. package/dist/cli/playbooks.js +126 -290
  165. package/dist/cli/predictions.d.ts +3 -0
  166. package/dist/cli/predictions.js +174 -0
  167. package/dist/cli/print.js +2 -1
  168. package/dist/cli/projects.js +30 -22
  169. package/dist/cli/quality-repair-once.d.ts +1 -1
  170. package/dist/cli/quality-repair-once.js +6 -5
  171. package/dist/cli/recall.js +13 -7
  172. package/dist/cli/refine-llm.js +18 -17
  173. package/dist/cli/remember.js +17 -17
  174. package/dist/cli/scheduler.js +2 -1
  175. package/dist/cli/serve.js +11 -6
  176. package/dist/cli/session-hooks.d.ts +1 -5
  177. package/dist/cli/session-hooks.js +89 -168
  178. package/dist/cli/setup.d.ts +1 -1
  179. package/dist/cli/setup.js +17 -10
  180. package/dist/cli/shared.d.ts +2 -6
  181. package/dist/cli/shared.js +9 -29
  182. package/dist/cli/sleep-render.js +6 -3
  183. package/dist/cli/sleep.js +6 -37
  184. package/dist/cli/status.d.ts +3 -3
  185. package/dist/cli/status.js +32 -35
  186. package/dist/cli/transfer.d.ts +3 -3
  187. package/dist/cli/transfer.js +64 -43
  188. package/dist/cli/usage.d.ts +1 -80
  189. package/dist/cli/usage.js +2 -696
  190. package/dist/cli/verb-row.d.ts +34 -0
  191. package/dist/cli/verb-row.js +6 -0
  192. package/dist/cli/verbs/health.d.ts +27 -0
  193. package/dist/cli/verbs/health.js +234 -0
  194. package/dist/cli/verbs/memory.d.ts +16 -0
  195. package/dist/cli/verbs/memory.js +236 -0
  196. package/dist/cli/verbs/objects.d.ts +20 -0
  197. package/dist/cli/verbs/objects.js +257 -0
  198. package/dist/cli/verbs/sessions.d.ts +31 -0
  199. package/dist/cli/verbs/sessions.js +314 -0
  200. package/dist/cli/verbs.d.ts +81 -0
  201. package/dist/cli/verbs.js +7 -0
  202. package/dist/cli/versioned-verbs.d.ts +51 -0
  203. package/dist/cli/versioned-verbs.js +79 -0
  204. package/dist/cli.d.ts +1 -272
  205. package/dist/cli.js +24 -315
  206. package/dist/connectors/dlq.d.ts +39 -3
  207. package/dist/connectors/dlq.js +39 -4
  208. package/dist/connectors/github/backfill.js +12 -3
  209. package/dist/connectors/github/deletion.js +2 -1
  210. package/dist/connectors/github/dlq.js +31 -73
  211. package/dist/connectors/github/ingest.d.ts +2 -6
  212. package/dist/connectors/github/ingest.js +5 -29
  213. package/dist/connectors/github/tenant-routing.js +2 -1
  214. package/dist/connectors/github/webhook.d.ts +2 -1
  215. package/dist/connectors/github/webhook.js +35 -2
  216. package/dist/connectors/ingest.d.ts +10 -0
  217. package/dist/connectors/ingest.js +29 -0
  218. package/dist/connectors/slack/deletion.js +2 -1
  219. package/dist/connectors/slack/dlq.js +49 -71
  220. package/dist/connectors/slack/ingest.d.ts +2 -6
  221. package/dist/connectors/slack/ingest.js +4 -28
  222. package/dist/connectors/slack/tenant-routing.js +2 -1
  223. package/dist/connectors/slack/webhook.d.ts +2 -1
  224. package/dist/connectors/slack/webhook.js +2 -1
  225. package/dist/consolidate/conflicts.js +2 -2
  226. package/dist/consolidate/dag.js +29 -18
  227. package/dist/consolidate/dedupe.d.ts +7 -0
  228. package/dist/consolidate/dedupe.js +6 -4
  229. package/dist/consolidate/llm-passes.js +45 -19
  230. package/dist/consolidate/memory-value.js +3 -2
  231. package/dist/consolidate/merge.js +8 -8
  232. package/dist/consolidate/physics-pass.d.ts +6 -1
  233. package/dist/consolidate/physics-pass.js +26 -6
  234. package/dist/consolidate/replay.js +11 -4
  235. package/dist/consolidate/sleep.js +9 -6
  236. package/dist/consolidate/traces.js +5 -5
  237. package/dist/core/ablation.d.ts +10 -0
  238. package/dist/core/ablation.js +12 -0
  239. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  240. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  241. package/dist/core/ambient.d.ts +4 -0
  242. package/dist/core/ambient.js +39 -18
  243. package/dist/core/api-errors.d.ts +16 -0
  244. package/dist/core/api-errors.js +20 -0
  245. package/dist/core/card.js +3 -1
  246. package/dist/core/compaction-timing.d.ts +7 -0
  247. package/dist/core/compaction-timing.js +9 -0
  248. package/dist/core/config.d.ts +1 -1
  249. package/dist/core/config.js +22 -18
  250. package/dist/core/cosine.d.ts +3 -0
  251. package/dist/core/cosine.js +19 -0
  252. package/dist/{store → core}/markdown.d.ts +1 -1
  253. package/dist/{store → core}/markdown.js +4 -4
  254. package/dist/core/memory-audit.d.ts +17 -0
  255. package/dist/core/memory-audit.js +54 -0
  256. package/dist/core/memory.d.ts +14 -8
  257. package/dist/core/memory.js +35 -23
  258. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  259. package/dist/{consolidate → core}/merged-row.js +1 -1
  260. package/dist/core/physics.d.ts +3 -1
  261. package/dist/core/physics.js +23 -18
  262. package/dist/core/prediction.d.ts +3 -0
  263. package/dist/core/prediction.js +6 -0
  264. package/dist/core/project-identity.d.ts +3 -0
  265. package/dist/core/project-identity.js +12 -2
  266. package/dist/{store → core}/recall-scope.d.ts +1 -10
  267. package/dist/{store → core}/recall-scope.js +2 -19
  268. package/dist/core/search-types.d.ts +1 -1
  269. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  270. package/dist/dashboard/dashboard-actions.js +5 -5
  271. package/dist/dashboard/dashboard-queries.js +2 -7
  272. package/dist/dashboard/dashboard-snapshot.js +1 -3
  273. package/dist/dashboard/dashboard.js +16 -5
  274. package/dist/db/busy.d.ts +2 -7
  275. package/dist/db/busy.js +21 -26
  276. package/dist/db/connect.d.ts +2 -2
  277. package/dist/db/connect.js +7 -7
  278. package/dist/db/index.d.ts +3 -3
  279. package/dist/db/index.js +3 -3
  280. package/dist/db/migrate.js +14 -7
  281. package/dist/db/migrations/index.d.ts +1 -1
  282. package/dist/db/migrations/index.js +3 -1
  283. package/dist/db/migrations/v11.js +1 -0
  284. package/dist/db/migrations/v14.js +1 -0
  285. package/dist/db/migrations/v55.d.ts +3 -0
  286. package/dist/db/migrations/v55.js +17 -0
  287. package/dist/db/open.d.ts +0 -2
  288. package/dist/db/open.js +6 -10
  289. package/dist/db/physics-state.d.ts +0 -4
  290. package/dist/db/physics-state.js +7 -33
  291. package/dist/db/request-stores.d.ts +1 -0
  292. package/dist/db/request-stores.js +2 -1
  293. package/dist/db/tables.d.ts +2 -0
  294. package/dist/db/tables.js +6 -2
  295. package/dist/db/vector-store.js +19 -5
  296. package/dist/db/wal-checkpointer.js +2 -1
  297. package/dist/doctor.d.ts +3 -0
  298. package/dist/doctor.js +18 -15
  299. package/dist/embeddings/local.d.ts +62 -0
  300. package/dist/embeddings/local.js +146 -0
  301. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  302. package/dist/{store/embeddings → embeddings}/provider.js +19 -25
  303. package/dist/embeddings/transformers.d.ts +26 -0
  304. package/dist/embeddings/transformers.js +89 -0
  305. package/dist/entry/session-text.d.ts +1 -1
  306. package/dist/entry/session-text.js +1 -1
  307. package/dist/entry/store-kit.d.ts +37 -0
  308. package/dist/entry/store-kit.js +25 -0
  309. package/dist/entry/testing.d.ts +6 -0
  310. package/dist/entry/testing.js +7 -0
  311. package/dist/eval/eval-suite.js +17 -11
  312. package/dist/eval/eval.js +1 -1
  313. package/dist/eval/judgment.js +12 -5
  314. package/dist/graph/extract.js +3 -3
  315. package/dist/graph/recall.js +1 -1
  316. package/dist/graph/view.js +13 -5
  317. package/dist/graph/write.d.ts +1 -1
  318. package/dist/graph/write.js +9 -9
  319. package/dist/hooks/codex-session.js +3 -2
  320. package/dist/hooks/codex-wrapper.js +2 -1
  321. package/dist/hooks/json-hooks.js +10 -4
  322. package/dist/hooks/opencode.js +8 -5
  323. package/dist/hooks/shared.d.ts +0 -6
  324. package/dist/hooks/shared.js +4 -15
  325. package/dist/importers/core.js +4 -4
  326. package/dist/importers/sources.js +5 -4
  327. package/dist/importers/vault.d.ts +1 -1
  328. package/dist/importers/vault.js +25 -23
  329. package/dist/index.d.ts +5 -4
  330. package/dist/index.js +4 -3
  331. package/dist/learn/autolearn.d.ts +15 -3
  332. package/dist/learn/autolearn.js +38 -16
  333. package/dist/learn/churn-git.js +13 -4
  334. package/dist/learn/extract.d.ts +3 -2
  335. package/dist/learn/extract.js +7 -5
  336. package/dist/learn/forward-claim-detector.js +4 -2
  337. package/dist/learn/invalidation.d.ts +2 -1
  338. package/dist/learn/invalidation.js +18 -9
  339. package/dist/mcp/admin-tools.d.ts +2 -2
  340. package/dist/mcp/admin-tools.js +27 -48
  341. package/dist/mcp/format.js +3 -2
  342. package/dist/mcp/framing.d.ts +1 -0
  343. package/dist/mcp/framing.js +1 -1
  344. package/dist/mcp/memory-tools.d.ts +1 -1
  345. package/dist/mcp/memory-tools.js +8 -9
  346. package/dist/mcp/protocol.d.ts +11 -7
  347. package/dist/mcp/protocol.js +25 -12
  348. package/dist/mcp/recall-tools.js +12 -9
  349. package/dist/mcp/request.js +22 -20
  350. package/dist/mcp/stdio.js +37 -16
  351. package/dist/mcp/tool-args.js +2 -1
  352. package/dist/mcp/tools.js +44 -21
  353. package/dist/objects/customer-notes.d.ts +2 -2
  354. package/dist/objects/decisions.d.ts +2 -2
  355. package/dist/objects/descriptor.d.ts +1 -1
  356. package/dist/objects/incidents.d.ts +2 -2
  357. package/dist/objects/lifecycle.d.ts +1 -1
  358. package/dist/objects/lifecycle.js +2 -1
  359. package/dist/objects/policies.d.ts +2 -2
  360. package/dist/objects/policies.js +2 -1
  361. package/dist/objects/processes.d.ts +2 -2
  362. package/dist/objects/project-briefs.d.ts +2 -2
  363. package/dist/objects/project-briefs.js +2 -3
  364. package/dist/objects/skills.d.ts +2 -2
  365. package/dist/postinstall.js +1 -1
  366. package/dist/rerankers/clef.js +3 -6
  367. package/dist/rerankers/cross-encoder.d.ts +31 -2
  368. package/dist/rerankers/cross-encoder.js +71 -98
  369. package/dist/rerankers/index.js +5 -4
  370. package/dist/rerankers/jev.js +2 -4
  371. package/dist/rerankers/outage-warning.d.ts +3 -1
  372. package/dist/rerankers/outage-warning.js +5 -3
  373. package/dist/search/bm25-search.js +1 -1
  374. package/dist/search/boosts.js +1 -1
  375. package/dist/search/embed-memories.d.ts +12 -0
  376. package/dist/search/embed-memories.js +389 -0
  377. package/dist/search/engine.d.ts +8 -0
  378. package/dist/search/engine.js +10 -0
  379. package/dist/search/goal-boost.d.ts +1 -1
  380. package/dist/search/goal-boost.js +6 -3
  381. package/dist/search/hybrid.d.ts +9 -2
  382. package/dist/search/hybrid.js +9 -4
  383. package/dist/search/physics-search.d.ts +6 -3
  384. package/dist/search/physics-search.js +22 -15
  385. package/dist/search/rerank.js +1 -1
  386. package/dist/search/vector.d.ts +8 -6
  387. package/dist/search/vector.js +14 -17
  388. package/dist/server/auth.d.ts +3 -1
  389. package/dist/server/auth.js +24 -15
  390. package/dist/server/boot.d.ts +2 -1
  391. package/dist/server/boot.js +34 -84
  392. package/dist/server/client-ip.d.ts +9 -6
  393. package/dist/server/client-ip.js +36 -17
  394. package/dist/server/deadline.d.ts +0 -2
  395. package/dist/server/deadline.js +1 -7
  396. package/dist/server/defaults.d.ts +1 -0
  397. package/dist/server/defaults.js +1 -0
  398. package/dist/server/mcp-http.js +16 -11
  399. package/dist/server/request.js +7 -2
  400. package/dist/server/route-checks.d.ts +7 -0
  401. package/dist/server/route-checks.js +42 -0
  402. package/dist/server/route-table.d.ts +9 -8
  403. package/dist/server/route-table.js +127 -133
  404. package/dist/server/routes/admin.d.ts +8 -8
  405. package/dist/server/routes/admin.js +13 -21
  406. package/dist/server/routes/customer-notes.d.ts +6 -6
  407. package/dist/server/routes/customer-notes.js +1 -2
  408. package/dist/server/routes/decisions.d.ts +6 -6
  409. package/dist/server/routes/decisions.js +2 -4
  410. package/dist/server/routes/incidents.d.ts +6 -6
  411. package/dist/server/routes/incidents.js +2 -5
  412. package/dist/server/routes/memories.d.ts +9 -9
  413. package/dist/server/routes/memories.js +19 -40
  414. package/dist/server/routes/object-routes.d.ts +6 -6
  415. package/dist/server/routes/object-routes.js +4 -7
  416. package/dist/server/routes/policies.d.ts +7 -7
  417. package/dist/server/routes/policies.js +2 -4
  418. package/dist/server/routes/predictions.d.ts +6 -6
  419. package/dist/server/routes/predictions.js +9 -13
  420. package/dist/server/routes/processes.d.ts +6 -6
  421. package/dist/server/routes/processes.js +1 -2
  422. package/dist/server/routes/project-briefs.d.ts +7 -7
  423. package/dist/server/routes/project-briefs.js +2 -4
  424. package/dist/server/routes/recall.d.ts +5 -5
  425. package/dist/server/routes/recall.js +6 -10
  426. package/dist/server/routes/skills.d.ts +7 -7
  427. package/dist/server/routes/skills.js +2 -4
  428. package/dist/server/server-detect.d.ts +7 -1
  429. package/dist/server/server-detect.js +36 -11
  430. package/dist/server/sleep-child.js +26 -7
  431. package/dist/server/sleep-offload.d.ts +11 -5
  432. package/dist/server/sleep-offload.js +17 -11
  433. package/dist/server/tls.d.ts +7 -2
  434. package/dist/server/tls.js +17 -5
  435. package/dist/server/types.d.ts +29 -12
  436. package/dist/server/validation.d.ts +1 -2
  437. package/dist/server/validation.js +6 -11
  438. package/dist/server.d.ts +4 -40
  439. package/dist/server.js +3 -29
  440. package/dist/sharing/global-store.d.ts +4 -5
  441. package/dist/sharing/global-store.js +8 -13
  442. package/dist/sharing/global-sync.js +38 -45
  443. package/dist/sharing/project-merge.d.ts +7 -14
  444. package/dist/sharing/project-merge.js +57 -121
  445. package/dist/sharing/search-both.js +10 -3
  446. package/dist/sharing/share.d.ts +2 -0
  447. package/dist/sharing/share.js +39 -38
  448. package/dist/store/ambient.js +7 -7
  449. package/dist/store/audit-event.d.ts +1 -1
  450. package/dist/store/audit.d.ts +0 -16
  451. package/dist/store/audit.js +4 -55
  452. package/dist/store/auth.d.ts +4 -2
  453. package/dist/store/auth.js +7 -3
  454. package/dist/store/candidates.d.ts +3 -2
  455. package/dist/store/candidates.js +59 -30
  456. package/dist/store/capture-write.d.ts +17 -0
  457. package/dist/store/capture-write.js +35 -0
  458. package/dist/store/cards.js +6 -5
  459. package/dist/store/compaction-caller.d.ts +18 -0
  460. package/dist/store/compaction-caller.js +29 -0
  461. package/dist/store/compactions-record.d.ts +115 -0
  462. package/dist/store/compactions-record.js +418 -0
  463. package/dist/store/compactions.js +6 -4
  464. package/dist/store/conflicts.d.ts +7 -1
  465. package/dist/store/conflicts.js +13 -9
  466. package/dist/store/connectors/dlq.d.ts +10 -0
  467. package/dist/store/connectors/dlq.js +33 -0
  468. package/dist/store/connectors/event-log.d.ts +13 -0
  469. package/dist/store/connectors/event-log.js +24 -0
  470. package/dist/store/connectors/github.d.ts +7 -9
  471. package/dist/store/connectors/github.js +35 -60
  472. package/dist/store/connectors/slack.d.ts +2 -11
  473. package/dist/store/connectors/slack.js +24 -57
  474. package/dist/store/dashboard-reads.js +8 -6
  475. package/dist/store/delete-and-batch.d.ts +6 -0
  476. package/dist/store/delete-and-batch.js +40 -6
  477. package/dist/store/delivery-recorder.d.ts +12 -5
  478. package/dist/store/delivery-recorder.js +13 -11
  479. package/dist/store/descendant-page.js +8 -4
  480. package/dist/store/dormant.d.ts +1 -1
  481. package/dist/store/dormant.js +10 -4
  482. package/dist/store/embeddings/index.d.ts +2 -12
  483. package/dist/store/embeddings/index.js +5 -374
  484. package/dist/store/entry-reads.d.ts +35 -4
  485. package/dist/store/entry-reads.js +86 -19
  486. package/dist/store/entry-row.js +9 -2
  487. package/dist/store/entry-writes.d.ts +15 -12
  488. package/dist/store/entry-writes.js +54 -22
  489. package/dist/store/failure-log-at.d.ts +8 -0
  490. package/dist/store/failure-log-at.js +16 -0
  491. package/dist/store/failure-log.d.ts +2 -2
  492. package/dist/store/failure-log.js +5 -3
  493. package/dist/{trust → store}/gated-write.d.ts +3 -1
  494. package/dist/{trust → store}/gated-write.js +7 -5
  495. package/dist/store/goals.js +22 -19
  496. package/dist/store/graph-reads.js +9 -6
  497. package/dist/store/graph-view-rows.js +2 -1
  498. package/dist/store/graph-writes.d.ts +6 -6
  499. package/dist/store/graph-writes.js +48 -71
  500. package/dist/store/half-life.js +2 -2
  501. package/dist/store/handoffs.d.ts +10 -4
  502. package/dist/store/handoffs.js +10 -9
  503. package/dist/store/index-and-stats.js +2 -2
  504. package/dist/store/index.d.ts +2 -2
  505. package/dist/store/index.js +1 -1
  506. package/dist/store/key-writes.js +1 -1
  507. package/dist/store/ledger-turn.d.ts +9 -0
  508. package/dist/store/ledger-turn.js +38 -0
  509. package/dist/store/mirrors.js +19 -10
  510. package/dist/store/open.d.ts +2 -5
  511. package/dist/store/open.js +42 -54
  512. package/dist/store/pilot-arm.d.ts +12 -0
  513. package/dist/store/pilot-arm.js +42 -0
  514. package/dist/store/port.d.ts +68 -6
  515. package/dist/store/port.js +8 -0
  516. package/dist/store/predictions.d.ts +1 -2
  517. package/dist/store/predictions.js +3 -6
  518. package/dist/store/project-tags.d.ts +62 -0
  519. package/dist/store/project-tags.js +67 -0
  520. package/dist/store/quality-repair.js +1 -1
  521. package/dist/store/quarantine.js +2 -1
  522. package/dist/store/recall-trace.d.ts +2 -0
  523. package/dist/store/recall-trace.js +20 -3
  524. package/dist/store/rejected-values.js +16 -10
  525. package/dist/store/rejection-probe.d.ts +4 -0
  526. package/dist/store/rejection-probe.js +19 -0
  527. package/dist/store/rejection.d.ts +0 -17
  528. package/dist/store/rejection.js +1 -21
  529. package/dist/store/rows.js +2 -2
  530. package/dist/store/rule-sql.d.ts +11 -0
  531. package/dist/store/rule-sql.js +31 -6
  532. package/dist/store/search-rows.d.ts +5 -5
  533. package/dist/store/search-rows.js +18 -16
  534. package/dist/store/sessions.js +4 -2
  535. package/dist/store/set-aside.d.ts +14 -0
  536. package/dist/store/set-aside.js +23 -0
  537. package/dist/store/sqlite/busy.d.ts +3 -0
  538. package/dist/store/sqlite/busy.js +8 -0
  539. package/dist/store/sqlite/connector-events-group.js +4 -7
  540. package/dist/store/sqlite/connector-writes-group.js +6 -4
  541. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  542. package/dist/store/sqlite/entry-writes-group.js +3 -3
  543. package/dist/store/sqlite/error-codec.js +4 -3
  544. package/dist/store/sqlite/executor.js +10 -4
  545. package/dist/store/sqlite/graph-reads-group.js +1 -1
  546. package/dist/store/sqlite/held-connection.d.ts +11 -0
  547. package/dist/store/sqlite/held-connection.js +41 -0
  548. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  549. package/dist/store/sqlite/last-recall-group.js +57 -0
  550. package/dist/store/sqlite/local.d.ts +0 -17
  551. package/dist/store/sqlite/local.js +0 -31
  552. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  553. package/dist/store/sqlite/maintenance-groups.js +60 -0
  554. package/dist/store/sqlite/object-rows.d.ts +1 -1
  555. package/dist/store/sqlite/objects-group.d.ts +1 -1
  556. package/dist/store/sqlite/objects-group.js +15 -7
  557. package/dist/store/sqlite/store.d.ts +1 -8
  558. package/dist/store/sqlite/store.js +13 -22
  559. package/dist/store/summaries.d.ts +10 -3
  560. package/dist/store/summaries.js +54 -11
  561. package/dist/store/token-ledger-rows.js +3 -2
  562. package/dist/store/token-ledger.d.ts +0 -7
  563. package/dist/store/token-ledger.js +0 -35
  564. package/dist/store/vector-index.js +8 -4
  565. package/dist/support-bundle.js +2 -3
  566. package/dist/trust/reject-flow.js +2 -2
  567. package/dist/util/agent-homes.d.ts +15 -0
  568. package/dist/util/agent-homes.js +34 -0
  569. package/dist/util/anthropic-messages.d.ts +6 -1
  570. package/dist/util/anthropic-messages.js +26 -7
  571. package/dist/util/atomic-write.d.ts +5 -2
  572. package/dist/util/atomic-write.js +12 -8
  573. package/dist/util/chunked.d.ts +3 -0
  574. package/dist/util/chunked.js +10 -0
  575. package/dist/util/ellipsize.d.ts +3 -0
  576. package/dist/util/ellipsize.js +5 -0
  577. package/dist/util/env.d.ts +12 -2
  578. package/dist/util/env.js +12 -2
  579. package/dist/util/format.d.ts +5 -0
  580. package/dist/util/format.js +10 -0
  581. package/dist/util/hook-payload.d.ts +8 -0
  582. package/dist/util/hook-payload.js +37 -0
  583. package/dist/util/http-retry.d.ts +6 -0
  584. package/dist/util/http-retry.js +43 -5
  585. package/dist/util/http-util.d.ts +0 -8
  586. package/dist/util/http-util.js +10 -21
  587. package/dist/util/limits.d.ts +7 -0
  588. package/dist/util/limits.js +14 -0
  589. package/dist/util/log.d.ts +4 -0
  590. package/dist/util/log.js +9 -0
  591. package/dist/util/request-scope.d.ts +9 -3
  592. package/dist/util/request-scope.js +18 -9
  593. package/dist/util/secret-detect.js +6 -1
  594. package/dist/util/spawn-argv.d.ts +9 -0
  595. package/dist/util/spawn-argv.js +57 -0
  596. package/dist/util/sql.d.ts +3 -0
  597. package/dist/util/sql.js +6 -0
  598. package/dist/util/sqlite-blocked.d.ts +2 -0
  599. package/dist/util/sqlite-blocked.js +5 -0
  600. package/dist/util/stream-tee.d.ts +3 -0
  601. package/dist/util/stream-tee.js +35 -0
  602. package/dist/util/time.d.ts +4 -0
  603. package/dist/util/time.js +4 -0
  604. package/dist/util/vector-codec.d.ts +4 -0
  605. package/dist/util/vector-codec.js +15 -0
  606. package/dist/util/version.d.ts +1 -1
  607. package/dist/util/version.js +1 -1
  608. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  609. package/extensions/openclaw-plugin/package.json +1 -1
  610. package/openclaw.plugin.json +1 -1
  611. package/package.json +4 -2
  612. package/dist/api/on-store.d.ts +0 -16
  613. package/dist/api/on-store.js +0 -38
  614. package/dist/store/embeddings/local.d.ts +0 -15
  615. package/dist/store/embeddings/local.js +0 -175
  616. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  617. /package/dist/{cli → api}/correction-latency.js +0 -0
  618. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  619. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  620. /package/dist/{store → core}/object-types.d.ts +0 -0
  621. /package/dist/{store → core}/object-types.js +0 -0
  622. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  623. /package/dist/{capture → util}/compaction-items.js +0 -0
  624. /package/dist/{store → util}/yaml.d.ts +0 -0
  625. /package/dist/{store → util}/yaml.js +0 -0
@@ -3,70 +3,63 @@ import { BadRequestError } from '../core/api-errors.js';
3
3
  import * as fs from 'fs';
4
4
  import * as path from 'path';
5
5
  import { AGENT_MEMORY_SOURCE_PREFIX } from '../core/agent-memory-tools.js';
6
- import { writeEntry } from '../store/entry-writes.js';
7
- import { loadAllEntries } from '../store/entry-reads.js';
6
+ import { writeEntriesSkippingRejected } from '../store/entry-writes.js';
7
+ import { loadEntriesByIds, loadEntryTextKeys } from '../store/entry-reads.js';
8
+ import { chunked } from '../util/chunked.js';
9
+ import { withRequestStoresSync } from '../db/request-stores.js';
8
10
  import { classifyOriginProject, resolveProjectIdentity } from '../core/project-identity.js';
9
11
  import { isSharedStore } from '../core/config.js';
10
12
  import { detectSecret } from '../util/secret-detect.js';
11
- import { RejectedValueError } from '../store/rejection.js';
12
- import { embedAll } from '../store/embeddings/index.js';
13
+ import { embedAll } from '../search/embed-memories.js';
13
14
  import { log } from '../util/log.js';
14
15
  import { logEmbedAllFailure } from './search-both.js';
15
16
  /** Copy all global memories into the local store, skipping entries that already exist locally by ID or text (promote and share copy under a new ID).
16
17
  * Returns the count of newly copied entries. */
17
18
  export function syncGlobalToLocal(localRoot, globalRoot, opts = {}) {
18
19
  if (isSharedStore(localRoot)) {
19
- throw new BadRequestError(`Refusing to sync into ${localRoot}: a shared store takes no copies of a personal global store, whose rows would reach every member.`);
20
+ throw new BadRequestError(`Refusing to sync into ${localRoot}: a shared store takes no copies of a personal global store, ` +
21
+ `whose rows would reach every member.`);
20
22
  }
21
23
  if (!fs.existsSync(globalRoot))
22
24
  return 0;
23
- // Host-wide read: the global union is copied into a tenant-scoped local store, and writeEntry carries the tenant if the local-root context has one.
24
- const globalEntries = loadAllEntries(globalRoot);
25
- const textKey = (e) => `${e.tenantId}\n${e.content}`;
26
- const localEntries = loadAllEntries(localRoot);
27
- const localIds = new Set(localEntries.map((e) => e.id));
28
- const localText = new Set(localEntries.map(textKey));
25
+ return withRequestStoresSync(() => copyMissingRows(localRoot, globalRoot, opts.includeCrossProject === true));
26
+ }
27
+ const textKey = (e) => `${e.tenant_id}\n${e.content}`;
28
+ /** One open per store and one transaction: id, tenant and text decide which rows to read whole, and the copies commit together. */
29
+ function copyMissingRows(localRoot, globalRoot, includeCrossProject) {
30
+ // Host-wide read: the global union is copied into a tenant-scoped local store, and each copy keeps its own tenant.
31
+ const localKeys = loadEntryTextKeys(localRoot);
32
+ const localIds = new Set(localKeys.map((k) => k.id));
33
+ const localText = new Set(localKeys.map(textKey));
34
+ // Only the global store's user pass sets an imported note's row aside, so a copy would outlive the note.
35
+ const candidates = loadEntryTextKeys(globalRoot).filter((k) => !localIds.has(k.id) && !k.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX) && !localText.has(textKey(k)));
36
+ if (candidates.length === 0)
37
+ return 0;
38
+ const byId = new Map(chunked(candidates.map((k) => k.id)).flatMap((ids) => loadEntriesByIds(globalRoot, ids)).map((e) => [e.id, e]));
29
39
  // Syncing down must not re-import what ambient context excludes: other-project rows are skipped by default and secret rows never copied.
30
- // origin_project is preserved on the copy (writeEntry stamps it only when missing).
40
+ // origin_project is preserved on the copy (the write stamps it only when missing).
31
41
  const currentProject = resolveProjectIdentity(path.dirname(path.resolve(localRoot)));
32
- let count = 0;
33
- // A locally rejected value must not come back through sync down: caught per item, printed as one line.
42
+ // A locally rejected value must not come back through sync down: skipped per item, printed as one line.
34
43
  let rejected = 0;
35
- for (const entry of globalEntries) {
36
- // Skip if already present by ID
37
- if (localIds.has(entry.id))
38
- continue;
39
- // Only the global store's user pass sets an imported note's row aside, so a copy would outlive the note.
40
- if (entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX))
41
- continue;
42
- if (localText.has(textKey(entry)))
43
- continue;
44
- if (detectSecret(entry).flagged)
45
- continue;
46
- if (!opts.includeCrossProject && classifyOriginProject(entry.origin_project, currentProject) === 'cross-project')
47
- continue;
48
- if (!writeUnlessRejected(localRoot, entry)) {
49
- rejected++;
50
- continue;
44
+ const count = writeEntriesSkippingRejected(localRoot, (put) => {
45
+ for (const { id } of candidates) {
46
+ const entry = byId.get(id);
47
+ // A row the global store dropped between the two reads, or a text an earlier copy in this batch already brought down.
48
+ if (!entry || localText.has(textKey(entry)))
49
+ continue;
50
+ if (detectSecret(entry).flagged)
51
+ continue;
52
+ if (!includeCrossProject && classifyOriginProject(entry.origin_project, currentProject) === 'cross-project')
53
+ continue;
54
+ if (put(entry))
55
+ localText.add(textKey(entry));
56
+ else
57
+ rejected++;
51
58
  }
52
- localText.add(textKey(entry));
53
- count++;
54
- }
59
+ });
55
60
  finishSyncDown(localRoot, count, rejected);
56
61
  return count;
57
62
  }
58
- /** False when the local store rejects the value; any other failure still throws. */
59
- function writeUnlessRejected(localRoot, entry) {
60
- try {
61
- writeEntry(localRoot, entry);
62
- return true;
63
- }
64
- catch (err) {
65
- if (err instanceof RejectedValueError)
66
- return false;
67
- throw err;
68
- }
69
- }
70
63
  function finishSyncDown(localRoot, count, rejected) {
71
64
  if (rejected > 0) {
72
65
  log.warn(`syncGlobalToLocal: skipped ${rejected} rejected value(s) (run \`hippo unreject\` on the local store to allow).`);
@@ -1,4 +1,5 @@
1
- import { type DatabaseSyncLike } from '../db/index.js';
1
+ import { type ProjectFold } from '../agent-memories/project-folds.js';
2
+ import type { ProjectTagReads, ProjectTagStore } from '../store/project-tags.js';
2
3
  export interface ProjectSummary {
3
4
  /** '' is user-global, null is unknown; neither can be merged. */
4
5
  readonly origin: string | null;
@@ -18,10 +19,6 @@ export interface MergeResult {
18
19
  readonly compactions: number;
19
20
  readonly backup: string | null;
20
21
  }
21
- export interface ProjectFold {
22
- readonly from: string;
23
- readonly into: string;
24
- }
25
22
  /** An old name whose session folders now resolve to several projects: no fold can say whose rows are whose. */
26
23
  export interface ProjectCollision {
27
24
  readonly name: string;
@@ -45,28 +42,24 @@ export interface RepairResult {
45
42
  readonly backup: string | null;
46
43
  }
47
44
  /** Live rows per project name, newest write first, with how many of its imported notes are copies held elsewhere. */
48
- export declare function listProjects(db: DatabaseSyncLike, tenantId: string): ProjectSummary[];
45
+ export declare function listProjects(store: ProjectTagReads): ProjectSummary[];
49
46
  /** Refuses user-global and unknown: they are not projects, and folding them would leak or hide every row. */
50
47
  export declare function validateMergeNames(from: string, into: string): string | null;
51
48
  /** Folds project `from` into `into` for one tenant in one transaction; a dry run rolls back and writes nothing, mirrors included. */
52
- export declare function mergeProjects(db: DatabaseSyncLike, hippoRoot: string, opts: {
53
- tenantId: string;
49
+ export declare function mergeProjects(store: ProjectTagStore, opts: {
54
50
  from: string;
55
51
  into: string;
56
52
  dryRun: boolean;
57
53
  }): MergeResult;
58
- /** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
59
- export declare function namesFoldedInto(db: DatabaseSyncLike, tenantId: string, names: readonly string[]): string[];
60
54
  /** Reads only, so doctor and a dry run take no write lock; merged rows are planned before any fold, so a few may re-tag differently once folds apply. */
61
- export declare function planProjectRepair(db: DatabaseSyncLike, hippoRoot: string, tenantId: string, globalFolds?: boolean): Omit<RepairResult, 'backup'>;
55
+ export declare function planProjectRepair(store: ProjectTagReads, hippoRoot: string, globalFolds?: boolean): Omit<RepairResult, 'backup'>;
62
56
  /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
63
57
  * re-tags sleep's user-global merges by their parents; a dry run only plans. */
64
- export declare function repairProjects(db: DatabaseSyncLike, hippoRoot: string, opts: {
65
- tenantId: string;
58
+ export declare function repairProjects(store: ProjectTagStore, opts: {
66
59
  dryRun: boolean;
67
60
  globalFolds?: boolean;
68
61
  }): RepairResult;
69
62
  /** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
70
63
  * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
71
- export declare function repairOnceOnSleep(db: DatabaseSyncLike, hippoRoot: string, tenantId: string): RepairResult | null;
64
+ export declare function repairOnceOnSleep(store: ProjectTagStore): RepairResult | null;
72
65
  //# sourceMappingURL=project-merge.d.ts.map
@@ -1,26 +1,14 @@
1
1
  // `hippo projects`: list the project names a store holds, fold one into another, and repair old tags in one reversible pass.
2
2
  import * as fs from 'node:fs';
3
3
  import * as path from 'node:path';
4
- import { setAsideRow } from '../agent-memories/apply.js';
5
4
  import { transcriptNotesProject } from '../agent-memories/claude-code.js';
6
5
  import { containerId, containerPrefix } from '../agent-memories/source.js';
6
+ import { foldEdges, foldedInto } from '../agent-memories/project-folds.js';
7
7
  import { AGENT_MEMORY_SOURCE_PREFIX, AGENT_MEMORY_TOOLS, toolSourcePrefix } from '../core/agent-memory-tools.js';
8
- import { appendAuditEvent, queryAuditEvents } from '../store/audit.js';
9
8
  import { isSharedStore } from '../core/config.js';
10
- import { withTrialScope, withWriteScope } from '../db/index.js';
11
- import { withBackup } from '../db/backup.js';
12
- import { getMeta, setMeta } from '../db/meta.js';
13
- import { insertDormantRow, listDormantSnapshots, replaceDormantEntry } from '../store/dormant.js';
14
9
  import { processEnv } from '../util/env.js';
15
- import { calculateStrength } from '../core/memory.js';
16
- import { isObjectLike, isStringValue } from '../core/capture-contract.js';
17
10
  import { isGlobalStoreRoot, projectNames, resolveProjectIdentity } from '../core/project-identity.js';
18
11
  import { duplicateKey } from '../util/same-text.js';
19
- import { compactionOriginsWithCwd, compactionTranscripts, holdsOrigin, restampCompactionOrigin } from '../store/compactions.js';
20
- import { removeEntryMirrors } from '../store/mirrors.js';
21
- import { deleteEntryRowInTx, restampOriginProjectAt, stampOriginProjectsAt, writeEntryMirrors } from '../store/entry-writes.js';
22
- import { selectAllEntries, selectLiveEntriesBySourcePrefix } from '../store/entry-reads.js';
23
- const ACTOR = 'cli';
24
12
  function isImport(entry) {
25
13
  return entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX);
26
14
  }
@@ -29,8 +17,8 @@ function toolTag(source) {
29
17
  return AGENT_MEMORY_TOOLS.find((t) => t.id === id)?.tag ?? null;
30
18
  }
31
19
  /** Live rows per project name, newest write first, with how many of its imported notes are copies held elsewhere. */
32
- export function listProjects(db, tenantId) {
33
- const live = selectAllEntries(db, tenantId).filter((e) => !e.superseded_by);
20
+ export function listProjects(store) {
21
+ const live = store.entries().filter((e) => !e.superseded_by);
34
22
  const byOrigin = new Map();
35
23
  const holders = new Map();
36
24
  for (const e of live) {
@@ -51,9 +39,6 @@ export function listProjects(db, tenantId) {
51
39
  };
52
40
  }).sort((a, b) => b.newest.localeCompare(a.newest));
53
41
  }
54
- function inTransaction(db, dryRun, body) {
55
- return dryRun ? withTrialScope(db, 'merge_projects', body) : withWriteScope(db, 'merge_projects', body);
56
- }
57
42
  /** Refuses user-global and unknown: they are not projects, and folding them would leak or hide every row. */
58
43
  export function validateMergeNames(from, into) {
59
44
  if (from.trim() === '' || into.trim() === '')
@@ -63,23 +48,19 @@ export function validateMergeNames(from, into) {
63
48
  return null;
64
49
  }
65
50
  /** Folds project `from` into `into` for one tenant in one transaction; a dry run rolls back and writes nothing, mirrors included. */
66
- export function mergeProjects(db, hippoRoot, opts) {
51
+ export function mergeProjects(store, opts) {
67
52
  const refusal = validateMergeNames(opts.from, opts.into);
68
53
  if (refusal)
69
54
  throw new Error(refusal);
70
- const { tenantId, from, into, dryRun } = opts;
71
- const fold = (backup) => inTransaction(db, dryRun, () => {
72
- const folded = foldInTx(db, tenantId, from, into);
73
- appendAuditEvent(db, { tenantId, actor: ACTOR, op: 'project_merge', metadata: { from, into, backup, ...folded } });
74
- return { from, into, ...folded, backup };
55
+ const { from, into, dryRun } = opts;
56
+ return store.rewrite({ dryRun, backupLabel: 'before-merge' }, (tx, backup) => {
57
+ const folded = foldInTx(tx, from, into);
58
+ tx.audit('project_merge', { from, into, backup, ...folded });
59
+ return { result: { from, into, ...folded, backup }, rewrite: folded.restamped, purge: folded.setAside };
75
60
  });
76
- const result = dryRun ? fold(null) : withBackup(db, hippoRoot, 'before-merge', fold);
77
- if (!dryRun)
78
- refreshMirrors(db, hippoRoot, tenantId, result.restamped, result.setAside);
79
- return result;
80
61
  }
81
- function foldInTx(db, tenantId, from, into) {
82
- const all = selectAllEntries(db, tenantId);
62
+ function foldInTx(tx, from, into) {
63
+ const all = tx.entries();
83
64
  const rows = all.filter((e) => e.origin_project === from);
84
65
  // The sync renames the rest to `into`'s prefix and keeps their ids; only a note `into` already holds would show twice.
85
66
  const held = new Set(all.filter((e) => e.origin_project === into && !e.superseded_by && isImport(e)).map(noteKey));
@@ -88,20 +69,20 @@ function foldInTx(db, tenantId, from, into) {
88
69
  const tag = toolTag(row.source);
89
70
  if (!isImport(row) || row.superseded_by || row.kind === 'raw' || tag === null || !held.has(noteKey(row)))
90
71
  continue;
91
- if (setAsideRow(db, tag, { ...row, origin_project: into }, 'project-merge').kind === 'dormant')
72
+ if (tx.setAside(tag, { ...row, origin_project: into }, 'project-merge').kind === 'dormant')
92
73
  setAside.push(row.id);
93
74
  }
94
75
  const gone = new Set(setAside);
95
76
  const restamped = rows.filter((e) => !gone.has(e.id)).map((e) => e.id);
96
- restampOriginProjectAt(db, tenantId, from, into);
77
+ tx.restampOrigin(from, into);
97
78
  const dormantRestamped = [];
98
- for (const snap of listDormantSnapshots(db, tenantId)) {
79
+ for (const snap of tx.dormant()) {
99
80
  if (snap.entry.origin_project !== from || gone.has(snap.entry.id))
100
81
  continue;
101
- replaceDormantEntry(db, tenantId, snap.entry.id, { ...snap.entry, origin_project: into });
82
+ tx.replaceDormant(snap.entry.id, { ...snap.entry, origin_project: into });
102
83
  dormantRestamped.push(snap.entry.id);
103
84
  }
104
- const compactions = restampCompactionOrigin(db, tenantId, from, into);
85
+ const compactions = tx.restampCompactions(from, into);
105
86
  return { setAside, restamped, dormantRestamped, compactions };
106
87
  }
107
88
  /** Tool, note key and hash of an import, without the container, whose id hashes the project name. */
@@ -110,20 +91,20 @@ function noteKey(entry) {
110
91
  return `${rest.split(':')[0]}:${rest.slice(rest.indexOf('/') + 1)}`;
111
92
  }
112
93
  /** Live imports under a project name whose exact text a user-global import holds: a session folder's notes stamped with the folder it ended in. */
113
- function importCopies(db, tenantId) {
114
- const live = selectAllEntries(db, tenantId).filter((e) => !e.superseded_by && isImport(e));
94
+ function importCopies(store) {
95
+ const live = store.entries().filter((e) => !e.superseded_by && isImport(e));
115
96
  const userGlobal = new Set(live.filter((e) => e.origin_project === '').map((e) => duplicateKey(e.content)));
116
97
  return live.filter((e) => e.origin_project && e.kind !== 'raw' && !e.pinned && toolTag(e.source) !== null && userGlobal.has(duplicateKey(e.content)));
117
98
  }
118
99
  /** Imports to set aside. The global store also checks each Claude session folder a compaction recorded: its
119
100
  * notes under any other project are misfiled, edited or not, and a text copy in the right folder is kept. */
120
- function strayImports(db, hippoRoot, tenantId) {
121
- const copies = importCopies(db, tenantId);
101
+ function strayImports(store, hippoRoot) {
102
+ const copies = importCopies(store);
122
103
  if (!isGlobalStoreRoot(hippoRoot))
123
104
  return copies;
124
105
  const machine = { platform: process.platform, env: processEnv() };
125
106
  const { platform } = machine;
126
- const sessions = compactionTranscripts(db, tenantId);
107
+ const sessions = store.compactionTranscripts();
127
108
  const owners = new Map();
128
109
  for (const { transcript, cwd } of sessions) {
129
110
  const project = transcriptNotesProject(transcript, cwd, machine);
@@ -134,9 +115,9 @@ function strayImports(db, hippoRoot, tenantId) {
134
115
  owners.set(dir, ids.set(project.name, [...new Set([...(ids.get(project.name) ?? []), ...projectNames(project)])]));
135
116
  }
136
117
  const tool = toolSourcePrefix('claude-code');
137
- const live = selectLiveEntriesBySourcePrefix(db, tenantId, tool).filter((e) => e.kind !== 'raw' && !e.pinned);
118
+ const live = store.liveEntriesBySourcePrefix(tool).filter((e) => e.kind !== 'raw' && !e.pinned);
138
119
  const origins = new Set(live.map((e) => e.origin_project ?? ''));
139
- const edges = foldEdges(db, tenantId);
120
+ const edges = foldEdges(store);
140
121
  const right = new Set();
141
122
  const wrong = new Set();
142
123
  for (const [dir, ids] of owners) {
@@ -154,12 +135,12 @@ function strayImports(db, hippoRoot, tenantId) {
154
135
  return [...misfiled, ...copies.filter((e) => !seen.has(e.id) && !right.has(prefix(e)))];
155
136
  }
156
137
  /** The global store reads each name's recorded session folders, where a compaction's name came from its cwd; a project store folds only its own folder name. */
157
- function planFolds(db, hippoRoot, tenantId, globalFolds) {
138
+ function planFolds(store, hippoRoot, globalFolds) {
158
139
  // A name someone merged into by hand stays: undoing their choice would rest on the resolver alone.
159
- const chosen = new Set(queryAuditEvents(db, { tenantId, op: 'project_merge', limit: 10000 }).map((e) => e.metadata.into));
140
+ const chosen = new Set(store.auditEvents('project_merge').map((e) => e.metadata.into));
160
141
  if (!isGlobalStoreRoot(hippoRoot))
161
- return { folds: ownLegacyFold(db, hippoRoot, tenantId).filter((f) => !chosen.has(f.from)), collisions: [] };
162
- const rows = compactionOriginsWithCwd(db, tenantId);
142
+ return { folds: ownLegacyFold(store, hippoRoot).filter((f) => !chosen.has(f.from)), collisions: [] };
143
+ const rows = store.compactionOriginsWithCwd();
163
144
  const today = new Map();
164
145
  for (const { origin, cwd } of rows) {
165
146
  if (fs.existsSync(cwd))
@@ -181,60 +162,29 @@ function planFolds(db, hippoRoot, tenantId, globalFolds) {
181
162
  return { folds: globalFolds ? folds.filter((f) => !sources.has(f.into)) : [], collisions };
182
163
  }
183
164
  /** A project store's rows, dormant snapshots and compaction records written before its id existed carry its folder name. */
184
- function ownLegacyFold(db, hippoRoot, tenantId) {
165
+ function ownLegacyFold(store, hippoRoot) {
185
166
  // A shared store's rows carry their callers' names, so one matching its folder's is a member's project, not a legacy tag.
186
167
  if (isSharedStore(hippoRoot))
187
168
  return [];
188
169
  const { name, legacyName } = resolveProjectIdentity(path.dirname(path.resolve(hippoRoot)));
189
170
  if (legacyName === '' || legacyName === name)
190
171
  return [];
191
- const held = holdsOrigin(db, 'memories', tenantId, legacyName)
192
- || holdsOrigin(db, 'compactions', tenantId, legacyName)
193
- || listDormantSnapshots(db, tenantId).some((s) => s.entry.origin_project === legacyName);
172
+ const held = store.holdsOrigin('memories', legacyName)
173
+ || store.holdsOrigin('compactions', legacyName)
174
+ || store.dormant().some((s) => s.entry.origin_project === legacyName);
194
175
  return held ? [{ from: legacyName, into: name }] : [];
195
176
  }
196
- function foldOf(value) {
197
- if (!isObjectLike(value) || Array.isArray(value))
198
- return [];
199
- const { from, into } = value;
200
- return isStringValue(from) && isStringValue(into) ? [{ from, into }] : [];
201
- }
202
- function foldEdges(db, tenantId) {
203
- return [
204
- ...queryAuditEvents(db, { tenantId, op: 'project_merge', limit: 10000 }).flatMap((e) => foldOf(e.metadata)),
205
- ...queryAuditEvents(db, { tenantId, op: 'project_repair', limit: 10000 })
206
- .flatMap((e) => (Array.isArray(e.metadata.folds) ? e.metadata.folds.flatMap(foldOf) : [])),
207
- ];
208
- }
209
- function foldedInto(edges, names) {
210
- const seen = new Set(names);
211
- let grew = true;
212
- while (grew) {
213
- grew = false;
214
- for (const { from, into } of edges) {
215
- if (!seen.has(into) || seen.has(from))
216
- continue;
217
- seen.add(from);
218
- grew = true;
219
- }
220
- }
221
- return [...seen].filter((n) => !names.includes(n));
222
- }
223
- /** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
224
- export function namesFoldedInto(db, tenantId, names) {
225
- return foldedInto(foldEdges(db, tenantId), names);
226
- }
227
177
  /** Reads only, so doctor and a dry run take no write lock; merged rows are planned before any fold, so a few may re-tag differently once folds apply. */
228
- export function planProjectRepair(db, hippoRoot, tenantId, globalFolds = true) {
229
- const { folds, collisions } = planFolds(db, hippoRoot, tenantId, globalFolds);
230
- return { copies: strayImports(db, hippoRoot, tenantId).map((e) => e.id), folds, collisions, ...planUserGlobalRepair(db, tenantId, folds) };
178
+ export function planProjectRepair(store, hippoRoot, globalFolds = true) {
179
+ const { folds, collisions } = planFolds(store, hippoRoot, globalFolds);
180
+ return { copies: strayImports(store, hippoRoot).map((e) => e.id), folds, collisions, ...planUserGlobalRepair(store, folds) };
231
181
  }
232
182
  /** Parents read with `folds` already applied, so a plan matches what apply does after folding. */
233
- function planUserGlobalRepair(db, tenantId, folds) {
234
- const all = selectAllEntries(db, tenantId);
183
+ function planUserGlobalRepair(store, folds) {
184
+ const all = store.entries();
235
185
  const renamed = new Map(folds.map((f) => [f.from, f.into]));
236
186
  const after = (origin) => (origin ? renamed.get(origin) ?? origin : origin ?? null);
237
- const origins = new Map(listDormantSnapshots(db, tenantId).map((s) => [s.entry.id, after(s.entry.origin_project)]));
187
+ const origins = new Map(store.dormant().map((s) => [s.entry.id, after(s.entry.origin_project)]));
238
188
  for (const e of all)
239
189
  origins.set(e.id, after(e.origin_project));
240
190
  const toProject = [];
@@ -258,59 +208,45 @@ function planUserGlobalRepair(db, tenantId, folds) {
258
208
  }
259
209
  /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
260
210
  * re-tags sleep's user-global merges by their parents; a dry run only plans. */
261
- export function repairProjects(db, hippoRoot, opts) {
262
- const { tenantId, dryRun, globalFolds = true } = opts;
211
+ export function repairProjects(store, opts) {
212
+ const { dryRun, globalFolds = true } = opts;
213
+ const { hippoRoot } = store;
263
214
  if (dryRun)
264
- return { ...planProjectRepair(db, hippoRoot, tenantId, globalFolds), backup: null };
265
- const { result, rewrite, purge } = withBackup(db, hippoRoot, 'before-repair', (backup) => inTransaction(db, false, () => {
215
+ return { ...planProjectRepair(store, hippoRoot, globalFolds), backup: null };
216
+ return store.rewrite({ dryRun: false, backupLabel: 'before-repair' }, (tx, backup) => {
266
217
  const copies = [];
267
- for (const row of strayImports(db, hippoRoot, tenantId)) {
218
+ for (const row of strayImports(tx, hippoRoot)) {
268
219
  const tag = toolTag(row.source);
269
- if (tag !== null && setAsideRow(db, tag, row, 'project-repair').kind === 'dormant')
220
+ if (tag !== null && tx.setAside(tag, row, 'project-repair').kind === 'dormant')
270
221
  copies.push(row.id);
271
222
  }
272
- const { folds, collisions } = planFolds(db, hippoRoot, tenantId, globalFolds);
273
- const folded = folds.map((f) => foldInTx(db, tenantId, f.from, f.into));
274
- const plan = planUserGlobalRepair(db, tenantId, []);
275
- stampOriginProjectsAt(db, tenantId, plan.toProject);
276
- const aside = new Set(plan.setAside);
223
+ const { folds, collisions } = planFolds(tx, hippoRoot, globalFolds);
224
+ const folded = folds.map((f) => foldInTx(tx, f.from, f.into));
225
+ const plan = planUserGlobalRepair(tx, []);
226
+ tx.stampOrigins(plan.toProject);
277
227
  const now = new Date();
278
- for (const row of selectAllEntries(db, tenantId).filter((e) => aside.has(e.id))) {
279
- insertDormantRow(db, { entry: row, strength: calculateStrength(row, now), reason: 'project-repair', dormantAt: now.toISOString() });
280
- deleteEntryRowInTx(db, row, ACTOR);
281
- }
282
- appendAuditEvent(db, { tenantId, actor: ACTOR, op: 'project_repair', metadata: { backup, copies, folds, folded, ...plan } });
228
+ for (const row of tx.entriesByIds(plan.setAside).values())
229
+ tx.retire(row, 'project-repair', now);
230
+ tx.audit('project_repair', { backup, copies, folds, folded, ...plan });
283
231
  return {
284
232
  result: { copies, folds, collisions, ...plan, backup },
285
233
  rewrite: [...plan.toProject.map((r) => r.id), ...folded.flatMap((f) => f.restamped)],
286
234
  purge: [...copies, ...plan.setAside, ...folded.flatMap((f) => f.setAside)],
287
235
  };
288
- }));
289
- refreshMirrors(db, hippoRoot, tenantId, rewrite, purge);
290
- return result;
236
+ });
291
237
  }
292
- const AUTO_REPAIR_META_KEY = 'project_repair_auto';
293
238
  /** True when a repair would change nothing. */
294
239
  function repairIsEmpty(r) {
295
240
  return r.copies.length + r.folds.length + r.toProject.length + r.setAside.length === 0;
296
241
  }
297
242
  /** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
298
243
  * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
299
- export function repairOnceOnSleep(db, hippoRoot, tenantId) {
300
- if (getMeta(db, AUTO_REPAIR_META_KEY) === '1')
244
+ export function repairOnceOnSleep(store) {
245
+ if (store.repairedOnce())
301
246
  return null;
302
- const plan = planProjectRepair(db, hippoRoot, tenantId, false);
303
- const result = repairIsEmpty(plan) ? null : repairProjects(db, hippoRoot, { tenantId, dryRun: false, globalFolds: false });
304
- setMeta(db, AUTO_REPAIR_META_KEY, '1');
247
+ const plan = planProjectRepair(store, store.hippoRoot, false);
248
+ const result = repairIsEmpty(plan) ? null : repairProjects(store, { dryRun: false, globalFolds: false });
249
+ store.markRepairedOnce();
305
250
  return result;
306
251
  }
307
- /** After commit, as the agent memory sync does: a stale mirror would bring the old tag back on the next rebuild. */
308
- function refreshMirrors(db, hippoRoot, tenantId, rewrite, purge) {
309
- const ids = new Set(rewrite);
310
- for (const entry of selectAllEntries(db, tenantId))
311
- if (ids.has(entry.id))
312
- writeEntryMirrors(hippoRoot, entry);
313
- for (const id of purge)
314
- removeEntryMirrors(hippoRoot, id);
315
- }
316
252
  //# sourceMappingURL=project-merge.js.map
@@ -1,8 +1,8 @@
1
1
  // Search across the local and global stores, merged into one ranked, budgeted list.
2
2
  import { compareScoresDesc } from '../core/compare.js';
3
3
  import * as fs from 'fs';
4
- import { loadSearchEntries, loadRecallSearchEntries, recallScopeFilter } from '../store/search-rows.js';
5
- import { passesScopeFilterForRecall, passesCliRecallScopeFilter } from '../store/recall-scope.js';
4
+ import { loadSearchEntries, loadRecallEntries, recallScopeFilter } from '../store/search-rows.js';
5
+ import { passesScopeFilterForRecall, passesCliRecallScopeFilter } from '../core/recall-scope.js';
6
6
  import { search } from '../search/bm25-search.js';
7
7
  import { hybridSearch } from '../search/hybrid.js';
8
8
  import { fitBudget } from '../search/finalize.js';
@@ -79,7 +79,14 @@ export async function searchBothHybrid(query, localRoot, globalRoot, options = {
79
79
  if (!fs.existsSync(root))
80
80
  return [];
81
81
  return recallScope
82
- ? loadRecallSearchEntries(root, query, searchWindow, tenantId, recallScope.requested, recallScope.additive ? 'additive' : 'exact', Boolean(includeSuperseded) || Boolean(asOf), undefined, recallScope.ownScope)
82
+ ? loadRecallEntries(root, query, {
83
+ limit: searchWindow,
84
+ tenantId,
85
+ requestedScope: recallScope.requested,
86
+ explicitScopeMode: recallScope.additive ? 'additive' : 'exact',
87
+ includeSuperseded: Boolean(includeSuperseded) || Boolean(asOf),
88
+ ownScope: recallScope.ownScope,
89
+ })
83
90
  : loadSearchEntries(root, query, searchWindow, tenantId);
84
91
  };
85
92
  const passesScope = (e) => !recallScope || (recallScope.additive
@@ -4,6 +4,8 @@ export declare const NEVER_AUTO_SHARE_TAGS: ReadonlySet<string>;
4
4
  export declare function neverAutoShareTags(sources: readonly MemoryEntry[]): string[];
5
5
  /** Tags whose rows sleep keeps as written: never merged, never sent to LLM extraction. Conflict detection keeps its own list. */
6
6
  export declare const NO_MERGE_TAGS: ReadonlySet<string>;
7
+ /** The transfer score a memory needs before sleep or `hippo share --auto` copies it to the global store. */
8
+ export declare const AUTO_SHARE_MIN_SCORE = 0.6;
7
9
  /** Estimate how well a memory would transfer to other projects.
8
10
  * Returns 0..1 where >0.5 = good candidate for sharing. */
9
11
  export declare function transferScore(entry: MemoryEntry): number;