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
@@ -1,7 +1,57 @@
1
- import { storeFor } from '../store/index.js';
1
+ import { loadStrengthTallies } from '../store/candidates.js';
2
+ import { countOpenConflicts } from '../store/conflicts.js';
3
+ import { NotFoundError } from '../core/api-errors.js';
4
+ import { canTouchScope } from '../core/recall-scope.js';
5
+ import { storeFor } from '../store/sqlite/store.js';
6
+ import { countAllEntries, loadEntriesByIds, loadEntriesPage } from '../store/entry-reads.js';
7
+ import { requireHostAdmin } from './types.js';
2
8
  /** The row `id` in the caller's tenant, or null when it is missing or another tenant's. */
3
9
  export async function getMemory(ctx, id) {
4
10
  const [entry] = await storeFor(ctx).entriesByIds([id], ctx.tenantId);
5
11
  return entry ?? null;
6
12
  }
13
+ /** getMemory, but NotFound when the row is another person's personal one, so the reply does not reveal that the id exists. */
14
+ export async function getTouchableMemory(ctx, id) {
15
+ const entry = await getMemory(ctx, id);
16
+ if (!canTouchScope(ctx.actor, entry?.scope ?? null))
17
+ throw new NotFoundError(`Memory not found: ${id}`);
18
+ return entry;
19
+ }
20
+ /** Tenant-wide counts behind the status verbs: strength tallies at `now` (at risk is under `atRiskBelow`) and open conflicts. */
21
+ export function getMemoryStatus(ctx, now, atRiskBelow) {
22
+ return {
23
+ ...loadStrengthTallies(ctx.hippoRoot, ctx.tenantId, now, atRiskBelow),
24
+ openConflicts: countOpenConflicts(ctx.hippoRoot, ctx.tenantId),
25
+ };
26
+ }
27
+ function tenantFilter(ctx, reach) {
28
+ if (!reach.everyTenant)
29
+ return ctx.tenantId;
30
+ requireHostAdmin(ctx, 'Reading every tenant');
31
+ return undefined;
32
+ }
33
+ /** Rows a listing reads per query by default; the verbs still receive every row. */
34
+ const LIST_PAGE_SIZE = 1000;
35
+ /** Every memory row in reach, oldest first, read `pageSize` rows per query so no single read grows with the store. */
36
+ export function listMemories(ctx, reach = {}, opts = {}) {
37
+ const tenant = tenantFilter(ctx, reach);
38
+ const limit = Math.max(1, Math.trunc(opts.pageSize ?? LIST_PAGE_SIZE));
39
+ const all = [];
40
+ let after;
41
+ do {
42
+ const page = loadEntriesPage(ctx.hippoRoot, tenant, { limit, after });
43
+ all.push(...page.entries);
44
+ after = page.next ?? undefined;
45
+ } while (after);
46
+ return all;
47
+ }
48
+ /** How many memory rows the whole store holds, counted in SQL. */
49
+ export function countAllMemories(ctx) {
50
+ requireHostAdmin(ctx, 'Reading every tenant');
51
+ return countAllEntries(ctx.hippoRoot);
52
+ }
53
+ /** The rows in reach among `ids`; a missing id or one out of reach is absent. */
54
+ export function listMemoriesByIds(ctx, ids, reach = {}) {
55
+ return loadEntriesByIds(ctx.hippoRoot, ids, tenantFilter(ctx, reach));
56
+ }
7
57
  //# sourceMappingURL=memories.js.map
@@ -1,5 +1,5 @@
1
1
  import type { SavableDescriptor } from '../objects/descriptor.js';
2
- import type { ObjectByKind, SavableKind } from '../store/object-types.js';
2
+ import type { ObjectByKind, SavableKind } from '../core/object-types.js';
3
3
  import type { Objects } from '../store/port.js';
4
4
  import type { Context } from './types.js';
5
5
  /** The request store's object group; the dispatcher has already answered 501 for a store without it. */
@@ -1,5 +1,6 @@
1
1
  import { saveObject } from '../objects/lifecycle.js';
2
- import { requireGroup, storeFor } from '../store/index.js';
2
+ import { requireGroup } from '../store/index.js';
3
+ import { storeFor } from '../store/sqlite/store.js';
3
4
  /** The request store's object group; the dispatcher has already answered 501 for a store without it. */
4
5
  export function objectsOf(ctx) {
5
6
  return requireGroup(storeFor(ctx), 'objects');
@@ -1,4 +1,4 @@
1
- import type { Context, StoreReply } from './types.js';
1
+ import type { Context } from './types.js';
2
2
  /** An id outside ctx.tenantId, or in someone else's personal scope, is skipped, so a stale id never fails the call.
3
3
  * `appliedIds` holds only the ids applied: a caller that answers across tenants returns it, never the ids it was sent. */
4
4
  export interface OutcomeResult {
@@ -6,14 +6,14 @@ export interface OutcomeResult {
6
6
  appliedIds: string[];
7
7
  }
8
8
  /** `opts.traceId` links the outcome to the recall trace it judges. Only outcomeForLastRecall sends one: explicit ids may follow no recall at all. */
9
- export declare function outcome<C extends Context>(ctx: C, ids: ReadonlyArray<string>, good: boolean, opts?: {
9
+ export declare function outcome(ctx: Context, ids: ReadonlyArray<string>, good: boolean, opts?: {
10
10
  traceId?: number;
11
- }): StoreReply<C, OutcomeResult>;
12
- /** The last recall's ids and its trace sit in hippo.db's meta table, which only the CLI and context write, so a store of another kind is refused.
11
+ }): Promise<OutcomeResult>;
12
+ /** The last recall's ids and its trace sit with the store's lastRecall group, which only the CLI and context write; a store without it is refused.
13
13
  * `ids` holds only the ids applied in ctx.tenantId: the index is not tenant-scoped, so the ids read from it are never returned. */
14
14
  export interface OutcomeForLastRecallResult {
15
15
  applied: number;
16
16
  ids: string[];
17
17
  }
18
- export declare function outcomeForLastRecall<C extends Context>(ctx: C, good: boolean): StoreReply<C, OutcomeForLastRecallResult>;
18
+ export declare function outcomeForLastRecall(ctx: Context, good: boolean): Promise<OutcomeForLastRecallResult>;
19
19
  //# sourceMappingURL=outcome.d.ts.map
@@ -1,21 +1,22 @@
1
1
  // Outcome feedback on recalled memories.
2
- import { personalScopeOf } from '../store/recall-scope.js';
3
- import { andThen, notPorted, onStore } from './on-store.js';
2
+ import { personalScopeOf } from '../core/recall-scope.js';
3
+ import { requireGroup } from '../store/index.js';
4
+ import { storeFor } from '../store/sqlite/store.js';
4
5
  /** `opts.traceId` links the outcome to the recall trace it judges. Only outcomeForLastRecall sends one: explicit ids may follow no recall at all. */
5
- export function outcome(ctx, ids, good, opts) {
6
- return onStore(ctx, (port, local) => {
7
- const entryWrites = port.entryWrites ?? notPorted(port, 'entryWrites');
8
- const write = { tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), ids, good };
9
- const traceId = opts?.traceId;
10
- // The trace link is written on hippo.db's own handle after the commit, so a served store refuses a traceId.
11
- const applied = traceId === undefined ? entryWrites.applyOutcome(write) : local.applyOutcome(write, traceId);
12
- return andThen(applied, (appliedIds) => ({ applied: appliedIds.length, appliedIds }));
13
- });
6
+ export async function outcome(ctx, ids, good, opts) {
7
+ const store = storeFor(ctx);
8
+ const entryWrites = requireGroup(store, 'entryWrites');
9
+ const write = { tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), ids, good };
10
+ const traceId = opts?.traceId;
11
+ // Recall traces live beside the last recall, so only a store with the lastRecall group can link one.
12
+ const appliedIds = traceId === undefined
13
+ ? await entryWrites.applyOutcome(write)
14
+ : await requireGroup(store, 'lastRecall').applyTracedOutcome(write, traceId);
15
+ return { applied: appliedIds.length, appliedIds };
14
16
  }
15
- export function outcomeForLastRecall(ctx, good) {
16
- return onStore(ctx, (_port, local) => {
17
- const ids = local.applyOutcomeToLastRecall({ tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor) }, good);
18
- return { applied: ids.length, ids };
19
- });
17
+ export async function outcomeForLastRecall(ctx, good) {
18
+ const lastRecall = requireGroup(storeFor(ctx), 'lastRecall');
19
+ const ids = await lastRecall.applyOutcomeToLast({ tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor) }, good);
20
+ return { applied: ids.length, ids };
20
21
  }
21
22
  //# sourceMappingURL=outcome.js.map
@@ -1,19 +1,9 @@
1
- import { type DatabaseSyncLike } from '../db/index.js';
2
1
  import { type LedgerRootOpts } from './ledger-db.js';
3
- export type PilotArm = 'hippo' | 'holdout';
2
+ import { type PilotArm } from '../store/pilot-arm.js';
4
3
  export interface SessionArmOpts extends LedgerRootOpts {
5
4
  /** Only the caller tenant's arm row counts, so a caller holding another tenant's session id cannot claim that session's arm. */
6
5
  readonly ownTenantOnly?: boolean;
7
6
  }
8
- /** Deterministic split: the same session and rate always land in the same arm. */
9
- export declare function hashArm(sessionId: string, rateBp: number): PilotArm;
10
- /** The session's first stored arm, or null; never writes. Without `tenantId` any tenant's row counts, since on one machine a session has one arm. */
11
- export declare function readPilotArm(db: DatabaseSyncLike, sessionId: string, tenantId?: string): PilotArm | null;
12
- /** The stored arm, else the hash arm written once; on any error the hash arm comes back unrecorded. */
13
- export declare function ensurePilotArm(db: DatabaseSyncLike, tenantId: string, sessionId: string, rateBp: number, opts?: {
14
- ownTenantOnly?: boolean;
15
- now?: string;
16
- }): PilotArm;
17
7
  /** The session's arm, or null at rate 0, with no session id, or with no store.
18
8
  * `write` books the arm row; a read-only caller (env-only id, sub-agent) follows the stored arm, else the hash. */
19
9
  export declare function sessionPilotArm(hippoRoot: string, tenantId: string, sessionId: string | undefined, write: boolean, opts?: SessionArmOpts): PilotArm | null;
@@ -1,46 +1,8 @@
1
- // Pilot arm: one token_ledger row per session names its arm, `hippo` or `holdout`, so a pilot can compare them.
2
- // `items` holds the holdout rate in basis points; readers outside this repo depend on these rows, so their shape is fixed.
3
- import { createHash } from 'node:crypto';
1
+ // Which pilot arm a session is in: the rate comes from the ledger store's config, the arm row from src/store/pilot-arm.ts.
4
2
  import { loadConfig } from '../core/config.js';
5
- import { HOOK_DB_WAIT_MS, scopedBusyWait, withWriteScope } from '../db/index.js';
6
- import { ledgerRoot, withLedgerDb } from './ledger-db.js';
7
- import { errorMessage, log } from '../util/log.js';
8
- import { firstPilotArmHash } from '../store/token-ledger-rows.js';
9
- import { recordTokenUse } from '../store/token-ledger.js';
10
- /** Deterministic split: the same session and rate always land in the same arm. */
11
- export function hashArm(sessionId, rateBp) {
12
- const bucket = parseInt(createHash('sha256').update(sessionId).digest('hex').slice(0, 8), 16) % 10000;
13
- return bucket < rateBp ? 'holdout' : 'hippo';
14
- }
15
- /** The session's first stored arm, or null; never writes. Without `tenantId` any tenant's row counts, since on one machine a session has one arm. */
16
- export function readPilotArm(db, sessionId, tenantId) {
17
- const row = firstPilotArmHash(db, sessionId, tenantId);
18
- return row?.block_hash === 'holdout' || row?.block_hash === 'hippo' ? row.block_hash : null;
19
- }
20
- /** The stored arm, else the hash arm written once; on any error the hash arm comes back unrecorded. */
21
- // The wait is the caller's lock-wait scope (a hook's 1 s, a server request's 250 ms); it holds on a handle opened in that scope.
22
- export function ensurePilotArm(db, tenantId, sessionId, rateBp, opts = {}) {
23
- const hashed = hashArm(sessionId, rateBp);
24
- const readTenant = opts.ownTenantOnly ? tenantId : undefined;
25
- try {
26
- // A stored row is the common case after the first prompt, so it must not take the write lock.
27
- const existing = readPilotArm(db, sessionId, readTenant);
28
- if (existing !== null)
29
- return existing;
30
- return withWriteScope(db, 'pilot_arm', () => {
31
- const stored = readPilotArm(db, sessionId, readTenant);
32
- if (stored === null) {
33
- recordTokenUse(db, { tenantId, sessionId, surface: 'pilot', event: 'arm', items: rateBp, tokens: 0, hash: hashed, now: opts.now });
34
- }
35
- return stored ?? hashed;
36
- }, { busyWaitMs: scopedBusyWait() ?? HOOK_DB_WAIT_MS });
37
- }
38
- catch (err) {
39
- // A prompt hook must not fail on pilot bookkeeping; concurrent callers still agree on the hash arm.
40
- log.debug(`pilot arm not stored, using the hash arm: ${errorMessage(err)}`);
41
- return hashed;
42
- }
43
- }
3
+ import { ledgerRoot, onLedgerRoot } from './ledger-db.js';
4
+ import { pilotArmOnRoot } from '../store/ledger-turn.js';
5
+ import { hashArm } from '../store/pilot-arm.js';
44
6
  /** The session's arm, or null at rate 0, with no session id, or with no store.
45
7
  * `write` books the arm row; a read-only caller (env-only id, sub-agent) follows the stored arm, else the hash. */
46
8
  export function sessionPilotArm(hippoRoot, tenantId, sessionId, write, opts = {}) {
@@ -53,9 +15,7 @@ export function sessionPilotArm(hippoRoot, tenantId, sessionId, write, opts = {}
53
15
  if (rate <= 0)
54
16
  return null;
55
17
  const { ownTenantOnly } = opts;
56
- const arm = withLedgerDb(hippoRoot, (db) => write
57
- ? ensurePilotArm(db, tenantId, sessionId, rate, { ownTenantOnly })
58
- : readPilotArm(db, sessionId, ownTenantOnly ? tenantId : undefined) ?? hashArm(sessionId, rate), opts);
18
+ const arm = onLedgerRoot(hippoRoot, opts, (at) => pilotArmOnRoot(at, tenantId, sessionId, rate, { write, ownTenantOnly }));
59
19
  return arm ?? hashArm(sessionId, rate);
60
20
  }
61
21
  //# sourceMappingURL=pilot-arm.js.map
@@ -1,7 +1,9 @@
1
- import type { Prediction, PredictionBaserate } from '../store/predictions.js';
1
+ import { type Prediction, type PredictionBaserate, type SavePredictionOpts } from '../store/predictions.js';
2
2
  import type { PredictionClose, PredictionSave, Predictions } from '../store/port.js';
3
3
  import type { Context } from './types.js';
4
4
  export declare function savePrediction(ctx: Context, input: PredictionSave): Promise<Prediction>;
5
+ /** A claim saved with its recall mirror, built under the store root's half-life as the HTTP create route builds it. */
6
+ export declare function recordPrediction(ctx: Context, claim: SavePredictionOpts): Promise<Prediction>;
5
7
  export declare function listPredictions(ctx: Context, query: Parameters<Predictions['listPredictions']>[1]): Promise<Prediction[]>;
6
8
  export declare function predictionBaserate(ctx: Context, classTag: string): Promise<PredictionBaserate>;
7
9
  export declare function predictionById(ctx: Context, id: number): Promise<Prediction | null>;
@@ -1,8 +1,15 @@
1
- import { requireGroup, storeFor } from '../store/index.js';
1
+ import { predictionMirror } from '../store/predictions.js';
2
+ import { loadConfig } from '../core/config.js';
3
+ import { requireGroup } from '../store/index.js';
4
+ import { storeFor } from '../store/sqlite/store.js';
2
5
  const predictionsOf = (ctx) => requireGroup(storeFor(ctx), 'predictions');
3
6
  export async function savePrediction(ctx, input) {
4
7
  return predictionsOf(ctx).savePrediction(ctx.tenantId, input, ctx.actor.subject);
5
8
  }
9
+ /** A claim saved with its recall mirror, built under the store root's half-life as the HTTP create route builds it. */
10
+ export async function recordPrediction(ctx, claim) {
11
+ return savePrediction(ctx, { ...claim, mirror: predictionMirror(ctx.tenantId, claim, loadConfig(ctx.hippoRoot).defaultHalfLifeDays) });
12
+ }
6
13
  export async function listPredictions(ctx, query) {
7
14
  return predictionsOf(ctx).listPredictions(ctx.tenantId, query);
8
15
  }
@@ -0,0 +1,21 @@
1
+ import { type MergeResult, type ProjectSummary, type RepairResult } from '../sharing/project-merge.js';
2
+ import type { Context } from './types.js';
3
+ export type { MergeResult, ProjectCollision, ProjectSummary, RepairResult } from '../sharing/project-merge.js';
4
+ export type { ProjectFold } from '../agent-memories/project-folds.js';
5
+ export interface MergeProjectNamesOpts {
6
+ from: string;
7
+ into: string;
8
+ /** Plans in a transaction that rolls back: nothing is written, mirrors and backup included. */
9
+ dryRun: boolean;
10
+ }
11
+ /** Live rows per project name in the caller's tenant, newest write first. */
12
+ export declare function listProjectNames(ctx: Context): ProjectSummary[];
13
+ /** Folds project `from` into `into`, backed up and audited as `ctx.actor`; throws on user-global, unknown or equal names. */
14
+ export declare function mergeProjectNames(ctx: Context, opts: MergeProjectNamesOpts): MergeResult;
15
+ /** Sets aside stray imports, folds renamed projects and re-tags sleep's user-global merges; a dry run only plans. */
16
+ export declare function repairProjectNames(ctx: Context, opts: {
17
+ dryRun: boolean;
18
+ }): RepairResult;
19
+ /** The repair sleep runs once per store; null when it already ran. */
20
+ export declare function repairProjectNamesOnce(ctx: Context): RepairResult | null;
21
+ //# sourceMappingURL=projects.d.ts.map
@@ -0,0 +1,24 @@
1
+ // Project names for every front end: list them, fold one into another, and repair old tags; the store opens hippo.db and owns each transaction.
2
+ // SHORTCUT: hippo.db only, since the store port has no project calls; a projects group when a served store needs them.
3
+ import { listProjects, mergeProjects, repairOnceOnSleep, repairProjects, } from '../sharing/project-merge.js';
4
+ import { onProjectTags } from '../store/project-tags.js';
5
+ function onProjects(ctx, fn) {
6
+ return onProjectTags({ hippoRoot: ctx.hippoRoot, tenantId: ctx.tenantId, actor: ctx.actor.subject }, fn);
7
+ }
8
+ /** Live rows per project name in the caller's tenant, newest write first. */
9
+ export function listProjectNames(ctx) {
10
+ return onProjects(ctx, listProjects);
11
+ }
12
+ /** Folds project `from` into `into`, backed up and audited as `ctx.actor`; throws on user-global, unknown or equal names. */
13
+ export function mergeProjectNames(ctx, opts) {
14
+ return onProjects(ctx, (store) => mergeProjects(store, opts));
15
+ }
16
+ /** Sets aside stray imports, folds renamed projects and re-tags sleep's user-global merges; a dry run only plans. */
17
+ export function repairProjectNames(ctx, opts) {
18
+ return onProjects(ctx, (store) => repairProjects(store, opts));
19
+ }
20
+ /** The repair sleep runs once per store; null when it already ran. */
21
+ export function repairProjectNamesOnce(ctx) {
22
+ return onProjects(ctx, repairOnceOnSleep);
23
+ }
24
+ //# sourceMappingURL=projects.js.map
@@ -1,6 +1,6 @@
1
1
  import type { ConnectorEvent } from '../store/port.js';
2
2
  import { type Layer } from '../core/memory.js';
3
- import type { Context, StoreReply } from './types.js';
3
+ import type { Context } from './types.js';
4
4
  /** Copies a local memory into the global store; the inner writeEntry emits 'remember' there, and we add a 'promote' audit event so intent stays distinct.
5
5
  * promoteToGlobal reads via `readEntry` with no tenant filter and keeps the entry's existing tenantId on the global side. */
6
6
  export interface PromoteResult {
@@ -21,7 +21,7 @@ export interface SupersedeOverrides {
21
21
  tags?: string[];
22
22
  pinned?: boolean;
23
23
  }
24
- export declare function supersede<C extends Context>(ctx: C, oldId: string, newContent: string, overrides?: SupersedeOverrides): StoreReply<C, SupersedeResult>;
24
+ export declare function supersede(ctx: Context, oldId: string, newContent: string, overrides?: SupersedeOverrides): Promise<SupersedeResult>;
25
25
  /** Archive a kind='raw' memory: its metadata moves to raw_archive and the row is
26
26
  * deleted. The store writes the one archive_raw audit row, under the caller's subject. */
27
27
  export interface ArchiveRawOpts {
@@ -32,5 +32,5 @@ export interface ArchiveRawResult {
32
32
  ok: true;
33
33
  archivedAt: string;
34
34
  }
35
- export declare function archiveRaw<C extends Context>(ctx: C, id: string, reason: string, opts?: ArchiveRawOpts): StoreReply<C, ArchiveRawResult>;
35
+ export declare function archiveRaw(ctx: Context, id: string, reason: string, opts?: ArchiveRawOpts): Promise<ArchiveRawResult>;
36
36
  //# sourceMappingURL=promote.d.ts.map
@@ -4,9 +4,10 @@ import { stampOriginProject } from '../store/entry-row.js';
4
4
  import { createSuccessor } from '../core/memory.js';
5
5
  import { promoteToGlobal } from '../sharing/global-store.js';
6
6
  import { loadConfig } from '../core/config.js';
7
- import { andThen, notPorted, onStore } from './on-store.js';
7
+ import { requireGroup } from '../store/index.js';
8
+ import { storeFor } from '../store/sqlite/store.js';
8
9
  import { memoryReach } from '../store/tenant-lookup.js';
9
- import { canTouchScope, personalScopeOf } from '../store/recall-scope.js';
10
+ import { canTouchScope, personalScopeOf } from '../core/recall-scope.js';
10
11
  export function promote(ctx, id) {
11
12
  // promoteToGlobal reads without a tenant filter, so pre-check the row's tenant_id and deny cross-tenant access with archiveRaw's not-found wording
12
13
  // (no leak about whether the id exists in another tenant).
@@ -22,23 +23,21 @@ export function promote(ctx, id) {
22
23
  });
23
24
  return { ok: true, sourceId: id, globalId: globalEntry.id };
24
25
  }
25
- export function supersede(ctx, oldId, newContent, overrides = {}) {
26
- return onStore(ctx, (port) => {
27
- const entryWrites = port.entryWrites ?? notPorted(port, 'entryWrites');
28
- return andThen(port.entriesByIds([oldId], ctx.tenantId), ([old]) => {
29
- const newEntry = createSuccessor(assertSupersedable(ctx, oldId, old ?? null), newContent, {
30
- tenantId: ctx.tenantId,
31
- baseHalfLifeDays: loadConfig(ctx.hippoRoot).defaultHalfLifeDays,
32
- layer: overrides.layer,
33
- tags: overrides.tags,
34
- pinned: overrides.pinned,
35
- });
36
- // A store writes origin_project as given, so the served folder's fallback is stamped here.
37
- const successor = stampOriginProject(ctx.hippoRoot, newEntry);
38
- const write = { tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), oldId, successor };
39
- return andThen(entryWrites.supersede(write), () => ({ ok: true, oldId, newId: successor.id }));
40
- });
26
+ export async function supersede(ctx, oldId, newContent, overrides = {}) {
27
+ const store = storeFor(ctx);
28
+ const entryWrites = requireGroup(store, 'entryWrites');
29
+ const [old] = await store.entriesByIds([oldId], ctx.tenantId);
30
+ const newEntry = createSuccessor(assertSupersedable(ctx, oldId, old ?? null), newContent, {
31
+ tenantId: ctx.tenantId,
32
+ baseHalfLifeDays: loadConfig(ctx.hippoRoot).defaultHalfLifeDays,
33
+ layer: overrides.layer,
34
+ tags: overrides.tags,
35
+ pinned: overrides.pinned,
41
36
  });
37
+ // A store writes origin_project as given, so the served folder's fallback is stamped here.
38
+ const successor = stampOriginProject(ctx.hippoRoot, newEntry);
39
+ await entryWrites.supersede({ tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), oldId, successor });
40
+ return { ok: true, oldId, newId: successor.id };
42
41
  }
43
42
  /** The tenant-scoped row to supersede; another tenant's id, or someone else's personal row, reads as not found. */
44
43
  function assertSupersedable(ctx, oldId, old) {
@@ -51,15 +50,14 @@ function assertSupersedable(ctx, oldId, old) {
51
50
  }
52
51
  return old;
53
52
  }
54
- export function archiveRaw(ctx, id, reason, opts = {}) {
55
- return onStore(ctx, (port) => {
56
- const entryWrites = port.entryWrites ?? notPorted(port, 'entryWrites');
57
- const archive = { tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), id, reason };
58
- const { event } = opts;
59
- const archived = event
60
- ? (port.connectorWrites ?? notPorted(port, 'connectorWrites')).archiveConnectorEntry({ ...archive, event })
61
- : entryWrites.archiveRaw(archive);
62
- return andThen(archived, (archivedAt) => ({ ok: true, archivedAt }));
63
- });
53
+ export async function archiveRaw(ctx, id, reason, opts = {}) {
54
+ const store = storeFor(ctx);
55
+ const entryWrites = requireGroup(store, 'entryWrites');
56
+ const archive = { tenantId: ctx.tenantId, actor: ctx.actor.subject, ownScope: personalScopeOf(ctx.actor), id, reason };
57
+ const { event } = opts;
58
+ const archivedAt = event
59
+ ? await requireGroup(store, 'connectorWrites').archiveConnectorEntry({ ...archive, event })
60
+ : await entryWrites.archiveRaw(archive);
61
+ return { ok: true, archivedAt };
64
62
  }
65
63
  //# sourceMappingURL=promote.js.map
@@ -1,9 +1,24 @@
1
1
  import { type Context, type ContextResult, type ContextResultEntry } from './index.js';
2
- import type { DeliveryRecorder } from '../store/delivery-recorder.js';
2
+ import { type DeliveryEventType, type DeliveryFault, type DeliveryRecorder } from '../store/delivery-recorder.js';
3
+ import type { HookRuntime } from '../core/capture-contract.js';
3
4
  import { type JsonValue } from '../util/json.js';
4
5
  import type { MemoryEntry } from '../core/memory.js';
5
- import { type PilotArm } from './pilot-arm.js';
6
+ import type { PilotArm } from '../store/pilot-arm.js';
6
7
  import type { DeliveryWrite } from '../store/ledger-turn.js';
8
+ /** What a hook's delivery row says about the call it records. */
9
+ export interface DeliveryStart {
10
+ stdinText: string | undefined;
11
+ runtime: HookRuntime;
12
+ eventType?: DeliveryEventType;
13
+ /** The host's own session id from its environment, used when the payload names none. */
14
+ envSessionId: string | undefined;
15
+ /** Passed through to the recorder; only tests set it. */
16
+ fault?: DeliveryFault;
17
+ }
18
+ /** A delivery recorder for a hook on `ctx.hippoRoot` when the ledger store enables one, else null; never throws. */
19
+ export declare function startDeliveryRecorder(ctx: Context, start: DeliveryStart): DeliveryRecorder | null;
20
+ /** A recorder for `hippo capture-error`, only when the failure log and the ledger are one store, so `failure_id` never points into another. */
21
+ export declare function startToolFailureRecorder(ctx: Context, start: Omit<DeliveryStart, 'eventType'>): DeliveryRecorder | null;
7
22
  /** With `write`, stores on the token ledger's connection (same store); without it, opens its own. A second flush is a no-op. */
8
23
  export declare function flushDeliveryRecorder(rec: DeliveryRecorder | null, write?: DeliveryWrite): void;
9
24
  /** What one render needs once api.getContext has answered. */
@@ -5,16 +5,57 @@ import { getContext } from './index.js';
5
5
  import { BadRequestError } from '../core/api-errors.js';
6
6
  import { isSharedStore, loadConfig } from '../core/config.js';
7
7
  import { contextBlockLines, contextCost, crossProjectLines, handoffText, sessionTrailText, settleTokens, snapshotText } from './context-render.js';
8
- import { MAX_ID_LEN } from '../util/http-util.js';
8
+ import { createDeliveryRecorder } from '../store/delivery-recorder.js';
9
+ import { realpathOrResolve } from '../util/real-path.js';
10
+ import { MAX_ID_LEN } from '../util/limits.js';
9
11
  import { isJsonString } from '../util/json.js';
10
- import { bookLedgerTurn, ledgerLastSent, noteLedgerRowSkipped } from './ledger-db.js';
12
+ import { bookLedgerTurn, ledgerLastSent, ledgerRoot } from './ledger-db.js';
13
+ import { noteLedgerRowSkipped } from '../store/ledger-turn.js';
11
14
  import { sessionPilotArm } from './pilot-arm.js';
12
- import { assertCallerProject, MAX_PROJECT_ALIASES } from '../core/project-identity.js';
15
+ import { assertCallerProject, isGlobalStoreRoot, MAX_PROJECT_ALIASES } from '../core/project-identity.js';
13
16
  import { writeDeliveryEventAtRoot } from '../store/recall-trace.js';
14
- import { hookPayloadString, isSubagentPayload, shouldSkipUnchanged, } from '../store/token-ledger.js';
17
+ import { shouldSkipUnchanged } from '../store/token-ledger.js';
18
+ import { hookPayloadString, isSubagentPayload } from '../util/hook-payload.js';
15
19
  import { blockHash, estimateTokens } from '../util/token-text.js';
16
20
  import { errorMessage, log } from '../util/log.js';
17
21
  import { DEFAULT_CONTEXT_BUDGET } from './context.js';
22
+ /** A delivery recorder for a hook on `ctx.hippoRoot` when the ledger store enables one, else null; never throws. */
23
+ export function startDeliveryRecorder(ctx, start) {
24
+ try {
25
+ // The same store the token ledger writes to, so its config governs both.
26
+ const root = ledgerRoot(ctx.hippoRoot);
27
+ if (root === null || !loadConfig(root).deliveryLedger.enabled)
28
+ return null;
29
+ return createDeliveryRecorder({
30
+ root,
31
+ storeHash: blockHash(realpathOrResolve(root)),
32
+ writeStore: isGlobalStoreRoot(root) ? 'global' : 'local',
33
+ tenantId: ctx.tenantId,
34
+ stdinText: start.stdinText,
35
+ envSessionId: start.envSessionId,
36
+ runtime: start.runtime === 'copilot' ? 'copilot' : undefined,
37
+ eventType: start.eventType,
38
+ fault: start.fault,
39
+ });
40
+ }
41
+ catch (error) {
42
+ log.warn(`delivery ledger skipped: ${errorMessage(error)}`);
43
+ return null;
44
+ }
45
+ }
46
+ /** A recorder for `hippo capture-error`, only when the failure log and the ledger are one store, so `failure_id` never points into another. */
47
+ export function startToolFailureRecorder(ctx, start) {
48
+ try {
49
+ const root = ledgerRoot(ctx.hippoRoot);
50
+ if (root === null || realpathOrResolve(root) !== realpathOrResolve(ctx.hippoRoot))
51
+ return null;
52
+ return startDeliveryRecorder(ctx, { ...start, eventType: 'tool-failure' });
53
+ }
54
+ catch (error) {
55
+ log.warn(`delivery ledger skipped: ${errorMessage(error)}`);
56
+ return null;
57
+ }
58
+ }
18
59
  /** With `write`, stores on the token ledger's connection (same store); without it, opens its own. A second flush is a no-op. */
19
60
  export function flushDeliveryRecorder(rec, write) {
20
61
  if (rec === null)
@@ -1,6 +1,7 @@
1
1
  // Quarantine review: list, approve and reject held memories.
2
2
  import { ConflictError, ForbiddenError, NotFoundError } from '../core/api-errors.js';
3
- import { requireGroup, storeFor } from '../store/index.js';
3
+ import { requireGroup } from '../store/index.js';
4
+ import { storeFor } from '../store/sqlite/store.js';
4
5
  const QUARANTINE_PREVIEW_CHARS = 200;
5
6
  /** A tenant's quarantined memories, newest first. Default `status` is 'pending' (the review queue). */
6
7
  export async function quarantineList(ctx, opts = {}) {
@@ -19,6 +19,9 @@ export interface CliRecallOrigin {
19
19
  readonly isGlobal: (id: string) => boolean;
20
20
  }
21
21
  export declare function cliRecallOrigin(ctx: Context, setting: CliRecallSetting): CliRecallOrigin;
22
+ /** How many of `query`'s search candidates the scope rule hides from a recall asking for `requested`; the read is
23
+ * window-capped, so this is a floor on a large store. */
24
+ export declare function scopeHiddenCount(ctx: Context, query: string, globalRoot: string | undefined, requested: string | undefined): number;
22
25
  /** The active snapshot, its session's latest handoff and last five events, each kept only when its scope passes. */
23
26
  export declare function loadCliRecallContinuity(ctx: Context, setting: CliRecallSetting, wanted: boolean): ContinuityBlock;
24
27
  export interface CliRecallRerankerPick {
@@ -1,17 +1,17 @@
1
1
  // What the `hippo recall` verb reads beside its ranking core: the stores it searches, the resume packet and the JSON rows.
2
2
  import { confidenceFacets, Layer } from '../core/memory.js';
3
- import { isGlobalStoreRoot } from '../core/project-identity.js';
3
+ import { isGlobalStoreRoot, isInitialized } from '../core/project-identity.js';
4
4
  import { getReranker } from '../rerankers/index.js';
5
5
  import { isClefModel } from '../rerankers/clef.js';
6
6
  import { JEV_DEFAULT_TOP_K } from '../rerankers/jev.js';
7
7
  import { explainMatch } from '../search/explain.js';
8
8
  import { fitBudget } from '../search/finalize.js';
9
9
  import { getGlobalRoot } from '../sharing/global-store.js';
10
- import { detectScope } from '../sharing/scope.js';
10
+ import { detectScope } from '../core/active-scope.js';
11
11
  import { loadLatestHandoff } from '../store/handoffs.js';
12
12
  import { loadIndex } from '../store/index-and-stats.js';
13
- import { isInitialized } from '../store/open.js';
14
- import { passesScopeFilterForRecall } from '../store/recall-scope.js';
13
+ import { passesCliRecallScopeFilter, passesScopeFilterForRecall } from '../core/recall-scope.js';
14
+ import { loadSearchEntries } from '../store/search-rows.js';
15
15
  import { listSessionEvents, loadActiveTaskSnapshot } from '../store/sessions.js';
16
16
  export { DEFAULT_MAX_NEIGHBORS, MAX_HOPS } from '../graph/recall.js';
17
17
  /** The active scope merges `--scope` with the detected one, which only boosts. */
@@ -23,6 +23,15 @@ export function cliRecallOrigin(ctx, setting) {
23
23
  const globalOn = isInitialized(setting.globalRoot);
24
24
  return { globalOn, isGlobal: (id) => setting.primaryIsGlobal || (globalOn && !localIndex.entries[id]) };
25
25
  }
26
+ /** How many of `query`'s search candidates the scope rule hides from a recall asking for `requested`; the read is
27
+ * window-capped, so this is a floor on a large store. */
28
+ export function scopeHiddenCount(ctx, query, globalRoot, requested) {
29
+ const probe = [
30
+ ...loadSearchEntries(ctx.hippoRoot, query, undefined, ctx.tenantId),
31
+ ...(globalRoot ? loadSearchEntries(globalRoot, query, undefined, ctx.tenantId) : []),
32
+ ];
33
+ return probe.filter((e) => !passesCliRecallScopeFilter(e.scope ?? null, requested)).length;
34
+ }
26
35
  /** The active snapshot, its session's latest handoff and last five events, each kept only when its scope passes. */
27
36
  export function loadCliRecallContinuity(ctx, setting, wanted) {
28
37
  if (!wanted || setting.primaryIsGlobal)
@@ -5,7 +5,7 @@ import { decidePlanningFallacy, detectPlanningClaim } from '../predictions/plann
5
5
  import { rankRecall } from './recall-pipeline.js';
6
6
  import { writeRecallTraceAtRoot } from '../store/recall-trace.js';
7
7
  import { saveIndex } from '../store/index-and-stats.js';
8
- import { sqliteStore } from '../store/index.js';
8
+ import { storeFor } from '../store/sqlite/store.js';
9
9
  import { estimateTokens } from '../util/token-text.js';
10
10
  import { callerOf, recallAuditMetadata, recallAuditRow, strengthenOf } from './recall-record.js';
11
11
  import { RECALL_RECORDING, recordShownRecall } from './recall-finish.js';
@@ -16,8 +16,8 @@ export async function retrieveWithCliCore(ctx, opts, core) {
16
16
  if (!ctx.actor.hostAdmin)
17
17
  throw new ForbiddenError('The CLI ranking core serves the host admin only');
18
18
  const globalRoot = core.sources?.globalRoot;
19
- // The ranking core reads hippo.db itself, so its writes go to the same file whatever store the context names.
20
- const store = sqliteStore(ctx.hippoRoot);
19
+ // The ranking core reads hippo.db under hippoRoot, yet writes through the caller's store, whose finishRecall skips any id it does not hold.
20
+ const store = storeFor(ctx);
21
21
  const ranking = await rankRecall({ hippoRoot: ctx.hippoRoot, globalRoot, tenantId: ctx.tenantId, note: core.note }, { ...core.rank, query: opts.query, sessionId: opts.sessionId, goalTag: opts.goalTag });
22
22
  if (ranking.halted) {
23
23
  // The stages that ran earned these rows, so the caller's flag error does not drop them.
@@ -58,7 +58,7 @@ async function recordShown(ctx, store, opts, core, done) {
58
58
  const { ranking, shown, planningAudit } = done;
59
59
  const ids = shown.results.map((r) => r.entry.id);
60
60
  const recallRow = recallAuditRow(callerOf(ctx), 'recall', undefined, recallAuditMetadata(opts.query, ids.length));
61
- const second = core.sources?.globalRoot !== undefined && core.sources.globalRoot !== ctx.hippoRoot ? core.sources.globalRoot : undefined;
61
+ const second = secondStore(ctx, core);
62
62
  const heldElsewhere = second !== undefined ? await idsNotHeld(store, ids, ctx.tenantId) : [];
63
63
  const audited = await finishOrReport(store, {
64
64
  goalLog: ranking.goalRecallLog,
@@ -68,7 +68,7 @@ async function recordShown(ctx, store, opts, core, done) {
68
68
  if (audited) {
69
69
  // The second store logs that it was searched, and strengthens only the rows the first does not hold.
70
70
  if (second !== undefined)
71
- await finishOrReport(sqliteStore(second), { goalLog: [], audit: [recallRow], strengthen: strengthenOf(ctx, heldElsewhere) });
71
+ await finishOrReport(second, { goalLog: [], audit: [recallRow], strengthen: strengthenOf(ctx, heldElsewhere) });
72
72
  traceAndMark(ctx, opts, core, shown.results);
73
73
  }
74
74
  // The caller prints whether or not the record was written, so the ring and the ledger still take this list; `written` holds back the count.
@@ -83,6 +83,11 @@ async function recordShown(ctx, store, opts, core, done) {
83
83
  written: audited,
84
84
  });
85
85
  }
86
+ /** The second store's writes go where the first's do: the store named for its root, else hippo.db under that root. */
87
+ function secondStore(ctx, core) {
88
+ const root = core.sources?.globalRoot;
89
+ return root !== undefined && root !== ctx.hippoRoot ? storeFor({ hippoRoot: root, store: core.sources?.globalStore }) : undefined;
90
+ }
86
91
  // The caller has ranked and is about to print, so a failed audit write is logged and counted, never thrown.
87
92
  async function finishOrReport(store, writes) {
88
93
  try {