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
package/README.md CHANGED
@@ -137,7 +137,7 @@ hippo init
137
137
  # Scheduled machine-level daily runner (6:15am) via crontab
138
138
  ```
139
139
 
140
- To leave parts out: `--no-hooks` skips the instruction files and hooks, `--no-schedule` the daily run, and `--no-learn` the git history and agent memory import. `HIPPO_SKIP_AUTO_INTEGRATIONS=1` skips the same files and hooks that `--no-hooks` does.
140
+ To leave parts out: `--no-hooks` skips the instruction files and hooks, `--no-schedule` the daily run, and `--no-learn` the git history and agent memory import. `HIPPO_SKIP_AUTO_INTEGRATIONS=1` skips the same files and hooks that `--no-hooks` does, and `HIPPO_SKIP_SCHEDULE=1` skips the daily run as `--no-schedule` does.
141
141
 
142
142
  ### Agent memories
143
143
 
@@ -675,11 +675,13 @@ hippo sleep
675
675
  Wrap any command with `hippo watch` to auto-learn from failures:
676
676
 
677
677
  ```bash
678
- hippo watch "npm run build"
678
+ hippo watch -- npm run build
679
679
  # if it fails, Hippo captures the error automatically
680
680
  # next time an agent asks about build issues, the memory is there
681
681
  ```
682
682
 
683
+ The command runs with no shell, so each argument reaches the program as written. To run a shell line with pipes or `&&`, pass it as one string after `--shell`: `hippo watch --shell "npm test && npm run build"`.
684
+
683
685
  ---
684
686
 
685
687
  ## CLI Reference
@@ -736,7 +738,7 @@ hippo watch "npm run build"
736
738
  | `hippo failures [--days n]` | Failed tool calls the capture-error hook saw, by outcome, and how many errors first happened in another session |
737
739
  | `hippo embed` | Embed all memories for semantic search |
738
740
  | `hippo embed --status` | Show embedding coverage |
739
- | `hippo watch "<command>"` | Run command, auto-learn from failures |
741
+ | `hippo watch -- <command> [args...]` | Run command with no shell, auto-learn from failures (`--shell "<line>"` runs one line through the shell) |
740
742
  | `hippo learn --git` | Scan recent git commits for lessons |
741
743
  | `hippo learn --git --days <n>` | Scan N days back (default: 7) |
742
744
  | `hippo learn --git --repos <paths>` | Scan multiple repos (comma-separated) |
@@ -784,8 +786,8 @@ hippo watch "npm run build"
784
786
  | `hippo dashboard` | Open web dashboard at localhost:3333 (memory health by project, and the card board); open the printed URL, which carries a per-start access token |
785
787
  | `hippo dashboard --port <n>` | Use custom port |
786
788
  | `hippo mcp` | Start MCP server (stdio transport) |
787
- | `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as host admin; `HIPPO_REQUIRE_AUTH=1` wins over it |
788
- | `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind still starts, and warns once that API keys and memory text travel in cleartext unless a TLS-terminating proxy sits in front |
789
+ | `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as a member (`HIPPO_KEYLESS_LOCAL_ROLE=admin` makes them host admin, for sleep and the quarantine routes); `HIPPO_REQUIRE_AUTH=1` wins over it. Each caller gets 20 requests a second, burst 40 (`HIPPO_CALLER_RPS`; `0` turns it off). See [Security defaults](docs/UPGRADING-2.0.md#security-defaults) |
790
+ | `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind refuses to start, since API keys and memory text would travel in cleartext; behind a TLS-terminating proxy, pass `--allow-cleartext` (or set `HIPPO_ALLOW_CLEARTEXT=1`) |
789
791
 
790
792
  On `heartbeat`, `block`, `review` and `complete`, a given `--run` is checked against the card's live run and the command is refused, unchanged, if the two do not match.
791
793
 
@@ -3,7 +3,6 @@ import { type MemoryEntry } from '../core/memory.js';
3
3
  import { type Tally } from './report.js';
4
4
  import type { AgentMemoryTool } from '../core/agent-memory-tools.js';
5
5
  import type { Container } from './types.js';
6
- export declare const SYNC_ACTOR = "agent-memories";
7
6
  export interface StoreSession {
8
7
  readonly db: DatabaseSyncLike;
9
8
  readonly hippoRoot: string;
@@ -36,14 +35,4 @@ export interface ContainerOutcome {
36
35
  }
37
36
  /** Throws SQLITE_BUSY when another writer holds the store past its busy timeout; nothing is written then. */
38
37
  export declare function syncContainer(s: StoreSession, work: ContainerWork): ContainerOutcome;
39
- export type SetAsideWhy = 'note-gone' | 'note-changed' | 'handover' | 'project-merge' | 'project-repair';
40
- export type SetAsideResult = {
41
- readonly kind: 'untagged';
42
- readonly entry: MemoryEntry;
43
- } | {
44
- readonly kind: 'dormant';
45
- readonly id: string;
46
- };
47
- /** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
48
- export declare function setAsideRow(db: DatabaseSyncLike, tag: string, row: MemoryEntry, why: SetAsideWhy): SetAsideResult;
49
38
  //# sourceMappingURL=apply.d.ts.map
@@ -1,41 +1,26 @@
1
1
  // One container's sync in one transaction on the caller's handle: lookup, plan, then every write (plan designs 6 to 8).
2
2
  import { appendAuditEvent } from '../store/audit.js';
3
3
  import { withTrialScope, withWriteScope } from '../db/index.js';
4
- import { deleteDormantRow, dormantSnapshotsBySourcePrefix, insertDormantRow, readDormantSnapshot, replaceDormantEntry } from '../store/dormant.js';
5
- import { gatedWrite } from '../trust/gated-write.js';
4
+ import { deleteDormantRow, dormantSnapshotsBySourcePrefix, readDormantSnapshot, replaceDormantEntry } from '../store/dormant.js';
5
+ import { gatedWrite } from '../store/gated-write.js';
6
+ import { strengthAblation } from '../core/ablation.js';
6
7
  import { Layer, calculateStrength, createMemory } from '../core/memory.js';
7
8
  import { findRejectedValue, rejectionDigest } from '../store/rejection.js';
8
9
  import { redactSecretsStrict } from '../util/secret-detect.js';
9
10
  import { stampOriginProject } from '../store/entry-row.js';
10
- import { deleteEntryRowInTx, renameEntrySourceAndOriginAt, renameEntrySourceAt, setEntryTagsInTx, supersedeEntryAt } from '../store/entry-writes.js';
11
+ import { renameEntrySourceAndOriginAt, renameEntrySourceAt, setEntryTagsInTx, supersedeEntryAt } from '../store/entry-writes.js';
12
+ import { SYNC_ACTOR, setAsideRow } from '../store/set-aside.js';
11
13
  import { entryIdTakenAt, selectLiveEntriesBySourcePrefix } from '../store/entry-reads.js';
12
14
  import { markSummaryDirtyInTx } from '../store/summary-dirty.js';
13
15
  import { itemHash } from './keys.js';
14
16
  import { planContainer } from './plan.js';
15
17
  import { emptyTally } from './report.js';
16
18
  import { MIN_ITEM_CHARS, itemSource, splitSource, storedText } from './source.js';
17
- export const SYNC_ACTOR = 'agent-memories';
18
19
  /** Throws SQLITE_BUSY when another writer holds the store past its busy timeout; nothing is written then. */
19
20
  export function syncContainer(s, work) {
20
21
  const run = () => new ContainerRun(s, work).run();
21
22
  return s.dryRun ? withTrialScope(s.db, 'sync_container', run) : withWriteScope(s.db, 'sync_container', run);
22
23
  }
23
- /** Design 6's set-aside on the caller's transaction: a pinned row only loses the tag, any other goes dormant, restorable. */
24
- export function setAsideRow(db, tag, row, why) {
25
- const untagged = { ...row, tags: row.tags.filter((t) => t !== tag) };
26
- const audit = (metadata) => appendAuditEvent(db, { tenantId: row.tenantId, actor: SYNC_ACTOR, op: 'agent_memory_set_aside', targetId: row.id, metadata });
27
- if (row.pinned) {
28
- setEntryTagsInTx(db, untagged);
29
- audit({ why, untagged: true });
30
- return { kind: 'untagged', entry: untagged };
31
- }
32
- const now = new Date();
33
- // Sleep's dormant move skips kept rows, so the steps are written out here without its filter.
34
- insertDormantRow(db, { entry: untagged, strength: calculateStrength(row, now), reason: 'source-deleted', dormantAt: now.toISOString() });
35
- deleteEntryRowInTx(db, row, SYNC_ACTOR);
36
- audit({ why });
37
- return { kind: 'dormant', id: row.id };
38
- }
39
24
  class ContainerRun {
40
25
  s;
41
26
  w;
@@ -99,7 +84,7 @@ class ContainerRun {
99
84
  continue;
100
85
  const source = itemSource(this.w.prefix, key, item.text);
101
86
  for (const row of rows) {
102
- if (renameEntrySourceAt(this.s.db, row.tenantId, row.id, row.source, source) === 0)
87
+ if (renameEntrySourceAt(this.s.db, row.tenant_id, row.id, row.source, source) === 0)
103
88
  continue;
104
89
  this.tally.adopted++;
105
90
  this.mirror.push({ ...row, source });
@@ -112,7 +97,7 @@ class ContainerRun {
112
97
  let moved = 0;
113
98
  for (const row of selectLiveEntriesBySourcePrefix(this.s.db, this.s.tenantId, old)) {
114
99
  const source = this.w.prefix + row.source.slice(old.length);
115
- if (renameEntrySourceAndOriginAt(this.s.db, row.tenantId, row.id, { from: row.source, to: source, origin }) === 0)
100
+ if (renameEntrySourceAndOriginAt(this.s.db, row.tenant_id, row.id, { from: row.source, to: source, origin }) === 0)
116
101
  continue;
117
102
  moved++;
118
103
  this.mirror.push({ ...row, source, origin_project: origin ?? row.origin_project });
@@ -165,11 +150,11 @@ class ContainerRun {
165
150
  }
166
151
  /** api.supersede's steps on this transaction; false when another writer superseded the row first. */
167
152
  supersede(old, newId) {
168
- if (!supersedeEntryAt(this.s.db, old.tenantId, old.id, newId))
153
+ if (!supersedeEntryAt(this.s.db, old.tenant_id, old.id, newId))
169
154
  return false;
170
155
  if (old.dag_parent_id)
171
- markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.tenantId, SYNC_ACTOR);
172
- appendAuditEvent(this.s.db, { tenantId: old.tenantId, actor: SYNC_ACTOR, op: 'supersede', targetId: old.id, metadata: { newId } });
156
+ markSummaryDirtyInTx(this.s.db, old.dag_parent_id, old.tenant_id, SYNC_ACTOR);
157
+ appendAuditEvent(this.s.db, { tenantId: old.tenant_id, actor: SYNC_ACTOR, op: 'supersede', targetId: old.id, metadata: { newId } });
173
158
  this.mirror.push({ ...old, superseded_by: newId });
174
159
  return true;
175
160
  }
@@ -223,7 +208,7 @@ class ContainerRun {
223
208
  tags: [...tags, this.tag],
224
209
  last_retrieved: now.toISOString(),
225
210
  };
226
- if (!this.gated(stampOriginProject(this.s.hippoRoot, { ...revived, strength: calculateStrength(revived, now) })))
211
+ if (!this.gated(stampOriginProject(this.s.hippoRoot, { ...revived, strength: calculateStrength(revived, now, { ablation: strengthAblation() }) })))
227
212
  return;
228
213
  deleteDormantRow(this.s.db, this.s.tenantId, dormantId);
229
214
  appendAuditEvent(this.s.db, {
@@ -4,7 +4,7 @@ import path from 'node:path';
4
4
  import { resolveProjectIdentity } from '../core/project-identity.js';
5
5
  import { realpathOrResolve } from '../util/real-path.js';
6
6
  import { isStringValue } from '../core/capture-contract.js';
7
- import { claudeConfigDir } from '../hooks/shared.js';
7
+ import { claudeConfigDir } from '../util/agent-homes.js';
8
8
  import { expandHome, frontmatterField, itemTime, readTextFile, splitFrontmatter } from './files.js';
9
9
  import { markdownNotes, readFolderStore, uniqueFolders } from './folder-store.js';
10
10
  import { gitLayout } from './git.js';
@@ -1,7 +1,7 @@
1
1
  // Codex CLI's memory_summary.md, the one memory file Codex puts in its prompt, read as a single text-keyed file.
2
2
  import fs from 'node:fs';
3
3
  import path from 'node:path';
4
- import { codexHomeDir } from '../hooks/shared.js';
4
+ import { codexHomeDir } from '../util/agent-homes.js';
5
5
  import { readTextFile } from './files.js';
6
6
  import { textItemKeys } from './keys.js';
7
7
  import { splitMarkdownItems } from './markdown.js';
@@ -1,5 +1,3 @@
1
- import type { Adapter, AdapterContext } from './types.js';
2
- /** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
3
- export declare function vscodeDataFolders(ctx: Pick<AdapterContext, 'env' | 'home' | 'platform'>): string[];
1
+ import type { Adapter } from './types.js';
4
2
  export declare const copilotAdapter: Adapter;
5
3
  //# sourceMappingURL=copilot.d.ts.map
@@ -5,24 +5,8 @@ import { readTextFile } from './files.js';
5
5
  import { readFolderStore } from './folder-store.js';
6
6
  import { gitLayout } from './git.js';
7
7
  import { errorMessage } from '../util/log.js';
8
- const PRODUCTS = ['Code', 'Code - Insiders'];
8
+ import { vscodeDataFolders } from '../util/agent-homes.js';
9
9
  const MEMORY_TOOL = ['github.copilot-chat', 'memory-tool', 'memories'];
10
- /** VS Code's user-data resolution: portable install first, then the app-data override, then the platform default. */
11
- export function vscodeDataFolders(ctx) {
12
- const { env, home, platform } = ctx;
13
- if (env.VSCODE_PORTABLE)
14
- return [path.join(env.VSCODE_PORTABLE, 'user-data')];
15
- let appData;
16
- if (env.VSCODE_APPDATA)
17
- appData = env.VSCODE_APPDATA;
18
- else if (platform === 'win32')
19
- appData = env.APPDATA || path.join(home, 'AppData', 'Roaming');
20
- else if (platform === 'darwin')
21
- appData = path.join(home, 'Library', 'Application Support');
22
- else
23
- appData = env.XDG_CONFIG_HOME || path.join(home, '.config');
24
- return PRODUCTS.map((product) => path.join(appData, product));
25
- }
26
10
  /** A `file:` URI as a local path; null for any other scheme or a URI with a host part. */
27
11
  function fileUriToPath(uri, platform) {
28
12
  if (!uri.startsWith('file://'))
@@ -0,0 +1,10 @@
1
+ import type { ProjectTagReads } from '../store/project-tags.js';
2
+ export interface ProjectFold {
3
+ readonly from: string;
4
+ readonly into: string;
5
+ }
6
+ export declare function foldEdges(store: Pick<ProjectTagReads, 'auditEvents'>): ProjectFold[];
7
+ export declare function foldedInto(edges: readonly ProjectFold[], names: readonly string[]): string[];
8
+ /** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
9
+ export declare function namesFoldedInto(store: Pick<ProjectTagReads, 'auditEvents'>, names: readonly string[]): string[];
10
+ //# sourceMappingURL=project-folds.d.ts.map
@@ -0,0 +1,34 @@
1
+ // Project names folded into others, read from the audit trail: the sync files imports under the surviving name, and `hippo projects` repair agrees.
2
+ import { isObjectLike, isStringValue } from '../core/capture-contract.js';
3
+ function foldOf(value) {
4
+ if (!isObjectLike(value) || Array.isArray(value))
5
+ return [];
6
+ const { from, into } = value;
7
+ return isStringValue(from) && isStringValue(into) ? [{ from, into }] : [];
8
+ }
9
+ export function foldEdges(store) {
10
+ return [
11
+ ...store.auditEvents('project_merge').flatMap((e) => foldOf(e.metadata)),
12
+ ...store.auditEvents('project_repair')
13
+ .flatMap((e) => (Array.isArray(e.metadata.folds) ? e.metadata.folds.flatMap(foldOf) : [])),
14
+ ];
15
+ }
16
+ export function foldedInto(edges, names) {
17
+ const seen = new Set(names);
18
+ let grew = true;
19
+ while (grew) {
20
+ grew = false;
21
+ for (const { from, into } of edges) {
22
+ if (!seen.has(into) || seen.has(from))
23
+ continue;
24
+ seen.add(from);
25
+ grew = true;
26
+ }
27
+ }
28
+ return [...seen].filter((n) => !names.includes(n));
29
+ }
30
+ /** Names folded, directly or through others, into one of `names`; the sync moves imports still filed under them. */
31
+ export function namesFoldedInto(store, names) {
32
+ return foldedInto(foldEdges(store), names);
33
+ }
34
+ //# sourceMappingURL=project-folds.js.map
@@ -6,16 +6,18 @@ import path from 'node:path';
6
6
  import { errorMessage } from '../util/log.js';
7
7
  import { loadConfig } from '../core/config.js';
8
8
  import { closeHippoDb, isSqliteBusy, openHippoDb, outsideRequestStores, withWriteScope } from '../db/index.js';
9
- import { namesFoldedInto } from '../sharing/project-merge.js';
10
- import { isGlobalStoreRoot, projectNames, resolveGlobalRootDir, resolveProjectIdentity } from '../core/project-identity.js';
9
+ import { namesFoldedInto } from './project-folds.js';
10
+ import { projectTagReads } from '../store/project-tags.js';
11
+ import { isGlobalStoreRoot, isInitialized, projectNames, resolveGlobalRootDir, resolveProjectIdentity, } from '../core/project-identity.js';
11
12
  import { duplicateKey, heldTextKeys } from '../util/same-text.js';
12
13
  import { removeEntryMirrors } from '../store/mirrors.js';
13
- import { initStore, isInitialized } from '../store/open.js';
14
+ import { initStore } from '../store/open.js';
14
15
  import { writeEntryMirrors } from '../store/entry-writes.js';
15
16
  import { selectLiveEntriesBySourcePrefix, selectRowsOutsideSourcePrefixAt } from '../store/entry-reads.js';
16
17
  import { updateStats } from '../store/index-and-stats.js';
17
18
  import { resolveTenantId } from '../store/tenant.js';
18
- import { setAsideRow, syncContainer } from './apply.js';
19
+ import { setAsideRow } from '../store/set-aside.js';
20
+ import { syncContainer } from './apply.js';
19
21
  import { claudeCodeAdapter, claudeTranscriptListing, transcriptNotesProject } from './claude-code.js';
20
22
  import { codexAdapter } from './codex.js';
21
23
  import { copilotAdapter } from './copilot.js';
@@ -230,7 +232,7 @@ function syncStore(pass, listings, store, opts, report) {
230
232
  /** The legacy names plus every name a merge or repair folded into the project; the audit read runs once per pass. */
231
233
  function earlierNames(db, tenantId, id, legacyOrigins) {
232
234
  const names = [id, ...legacyOrigins];
233
- return [...legacyOrigins, ...namesFoldedInto(db, tenantId, names)].filter((n) => n !== '' && n !== id);
235
+ return [...legacyOrigins, ...namesFoldedInto(projectTagReads(db, tenantId), names)].filter((n) => n !== '' && n !== id);
234
236
  }
235
237
  function containerWork(tool, container, options) {
236
238
  const { platform, legacy, origin, earlier } = options;
@@ -316,7 +318,7 @@ function handOver(synced, projectRoot, opts, report) {
316
318
  // A folder with no git and no marker wrote as '' before its store existed, and as its own name after.
317
319
  // Names folded into this project's in the global store were its rows too.
318
320
  const names = projectNames(resolveProjectIdentity(projectRoot));
319
- const origins = [...new Set([...names, ...namesFoldedInto(db, tenantId, names), ''])];
321
+ const origins = [...new Set([...names, ...namesFoldedInto(projectTagReads(db, tenantId), names), ''])];
320
322
  for (const work of synced)
321
323
  handOverContainer(db, globalRoot, tenantId, work, { origins, platform: opts.machine.platform, report });
322
324
  }
@@ -1,7 +1,8 @@
1
1
  // Session context assembly under a token budget.
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
  import { estimateTokens } from '../util/token-text.js';
4
- import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../store/recall-scope.js';
5
+ import { passesScopeFilterForRecall, assertScopeRequestAllowed, personalScopeOf } from '../core/recall-scope.js';
5
6
  import { classifyOriginProject, projectNames } from '../core/project-identity.js';
6
7
  const DEFAULT_FRESH_TAIL_COUNT = 10;
7
8
  const DEFAULT_ROW_CAP = 5000;
@@ -1,4 +1,6 @@
1
- import type { AuditEvent, AuditIssue, AuditOp } from '../store/audit.js';
1
+ import type { AuditEvent, AuditOp } from '../store/audit.js';
2
+ import { type AuditIssue, type AuditResult } from '../core/memory-audit.js';
3
+ import type { QualityRepairResult } from '../store/quality-repair.js';
2
4
  import type { KeysetPosition } from '../util/keyset.js';
3
5
  import type { Context } from './types.js';
4
6
  export interface AuditListOpts {
@@ -14,5 +16,31 @@ export declare function auditList(ctx: Context, opts: AuditListOpts): Promise<Au
14
16
  /** The pass that removes audit errors; it leads the reason on each forget row. */
15
17
  export type AuditPass = 'audit --fix' | 'sleep-audit';
16
18
  /** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
17
- export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): string[];
19
+ export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): Promise<string[]>;
20
+ /** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
21
+ export declare function auditMemoryQuality(ctx: Context): Promise<AuditResult>;
22
+ /** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
23
+ export declare function repairMemoryQuality(ctx: Context, apply: boolean): Promise<QualityRepairResult>;
24
+ /** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
25
+ export declare function repairMemoryQualityOnce(ctx: Context): Promise<QualityRepairResult | null>;
26
+ export interface PruneAuditOpts {
27
+ /** Cutoff in days. Rows with `ts < (now - N days)` are deleted. */
28
+ olderThanDays: number;
29
+ /** When true, count matching rows but do NOT delete. Default false. */
30
+ dryRun?: boolean;
31
+ }
32
+ export interface PruneAuditResult {
33
+ /** ISO timestamp of the cutoff. Rows with ts strictly less than this were deleted. */
34
+ cutoff: string;
35
+ /** Number of audit_log rows deleted (or that would be deleted, if dryRun). */
36
+ count: number;
37
+ /** Echo back whether this was a dry run. */
38
+ dryRun: boolean;
39
+ }
40
+ /** Cutoff ISO timestamp for N days ago; exported so tests can pin "now" without mocking Date. */
41
+ export declare function computeCutoff(days: number, now?: Date): string;
42
+ /** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
43
+ * retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
44
+ * Throws on non-positive days or an empty tenant. */
45
+ export declare function pruneAuditLog(ctx: Context, opts: PruneAuditOpts): Promise<PruneAuditResult>;
18
46
  //# sourceMappingURL=audit.d.ts.map
package/dist/api/audit.js CHANGED
@@ -1,17 +1,58 @@
1
- // Audit log queries, and the removal of the memories a quality audit marks as errors.
2
- import { deleteEntry } from '../store/delete-and-batch.js';
3
- import { requireGroup, storeFor } from '../store/index.js';
1
+ // Audit log queries and retention, and the memory-quality audit with its repair passes.
2
+ import { auditMemories } from '../core/memory-audit.js';
3
+ import { DAY_MS } from '../util/time.js';
4
+ import { requireGroup } from '../store/index.js';
5
+ import { storeFor } from '../store/sqlite/store.js';
4
6
  /** Read audit events scoped to `ctx.tenantId` on the store the request runs on. Read-only, no audit emit. */
5
7
  export async function auditList(ctx, opts) {
6
8
  return requireGroup(storeFor(ctx), 'auditLog').listAuditEvents({
7
9
  tenantId: ctx.tenantId, op: opts.op, since: opts.since, limit: opts.limit, after: opts.after,
8
10
  });
9
11
  }
12
+ function maintenanceOf(ctx) {
13
+ return requireGroup(storeFor(ctx), 'auditMaintenance');
14
+ }
10
15
  /** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
11
- export function removeAuditErrors(ctx, pass, issues) {
12
- return issues
16
+ export async function removeAuditErrors(ctx, pass, issues) {
17
+ const removals = issues
13
18
  .filter((issue) => issue.severity === 'error')
14
- .filter((issue) => deleteEntry(ctx.hippoRoot, issue.memoryId, { actor: ctx.actor.subject, reason: `${pass}: ${issue.reason}`, automatic: true }))
15
- .map((issue) => issue.memoryId);
19
+ .map((issue) => ({ id: issue.memoryId, reason: `${pass}: ${issue.reason}` }));
20
+ if (removals.length === 0)
21
+ return [];
22
+ return maintenanceOf(ctx).deleteAutomatically(removals, ctx.actor.subject);
23
+ }
24
+ /** The caller's memories run through the quality audit; a memory that backs an object is never marked for removal. */
25
+ export async function auditMemoryQuality(ctx) {
26
+ const maintenance = maintenanceOf(ctx);
27
+ return auditMemories(await maintenance.tenantEntries(ctx.tenantId), await maintenance.objectBackedIds());
28
+ }
29
+ /** Audit repair for the caller's tenant: a preview, or with `apply` the moves of certain defects to dormant storage behind a backup. */
30
+ export async function repairMemoryQuality(ctx, apply) {
31
+ return maintenanceOf(ctx).repairQuality(ctx.tenantId, apply);
32
+ }
33
+ /** The repair sleep and the daily runner apply once per store after an upgrade; null when it already ran there. */
34
+ export async function repairMemoryQualityOnce(ctx) {
35
+ return maintenanceOf(ctx).repairQualityOnce(ctx.tenantId);
36
+ }
37
+ /** Cutoff ISO timestamp for N days ago; exported so tests can pin "now" without mocking Date. */
38
+ export function computeCutoff(days, now = new Date()) {
39
+ const cutoff = new Date(now.getTime() - days * DAY_MS);
40
+ return cutoff.toISOString();
41
+ }
42
+ /** Delete the caller's tenant's audit_log rows older than `olderThanDays`, then record an `audit_prune` row as `ctx.actor`; opt-in, since
43
+ * retention floors (HIPAA, SOX, GDPR) apply. The row is written after the DELETE, so a call never prunes its own record.
44
+ * Throws on non-positive days or an empty tenant. */
45
+ export async function pruneAuditLog(ctx, opts) {
46
+ if (!Number.isFinite(opts.olderThanDays) || opts.olderThanDays <= 0) {
47
+ throw new Error(`pruneAuditLog: olderThanDays must be a positive number, got ${opts.olderThanDays}`);
48
+ }
49
+ if (!ctx.tenantId) {
50
+ throw new Error('pruneAuditLog: tenantId is required');
51
+ }
52
+ const dryRun = opts.dryRun === true;
53
+ const cutoff = computeCutoff(opts.olderThanDays);
54
+ const prune = { tenantId: ctx.tenantId, cutoff, actor: ctx.actor.subject, olderThanDays: opts.olderThanDays, dryRun };
55
+ const count = await maintenanceOf(ctx).pruneAuditRows(prune);
56
+ return { cutoff, count, dryRun };
16
57
  }
17
58
  //# sourceMappingURL=audit.js.map
@@ -1,6 +1,6 @@
1
- import { type ApiKeyListRow } from '../store/auth.js';
1
+ import { DEFAULT_KEY_TTL_DAYS, type ApiKeyListItem, type ApiKeyListRow } from '../store/auth.js';
2
2
  import type { KeysetPosition } from '../util/keyset.js';
3
- import type { Context, StoreReply } from './types.js';
3
+ import { type Context } from './types.js';
4
4
  export interface AuthCreateOpts {
5
5
  label?: string;
6
6
  /** Defaults to `'member'`, which admin-gated routes such as `POST /v1/sleep` refuse; an admin key has to be asked for by name. */
@@ -21,7 +21,9 @@ export interface AuthCreateResult {
21
21
  }
22
22
  /** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
23
23
  * Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
24
- export declare function authCreate<C extends Context>(ctx: C, opts: AuthCreateOpts): StoreReply<C, AuthCreateResult>;
24
+ export declare function authCreate(ctx: Context, opts: AuthCreateOpts): Promise<AuthCreateResult>;
25
+ export { DEFAULT_KEY_TTL_DAYS };
26
+ export declare const MAX_TTL_DAYS = 3650;
25
27
  export interface AuthCreateSelfOpts {
26
28
  label?: string;
27
29
  /** Days until the new key expires. */
@@ -35,25 +37,26 @@ export interface AuthCreateSelfResult extends AuthCreateResult {
35
37
  }
36
38
  /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
37
39
  * binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
38
- export declare function authCreateSelf<C extends Context>(ctx: C, opts: AuthCreateSelfOpts): StoreReply<C, AuthCreateSelfResult>;
40
+ export declare function authCreateSelf(ctx: Context, opts: AuthCreateSelfOpts): Promise<AuthCreateSelfResult>;
39
41
  type KeyListOpts = {
40
42
  active: boolean;
41
43
  limit?: number;
42
44
  after?: KeysetPosition;
43
45
  };
44
46
  /** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
45
- export declare function authListRows<C extends Context>(ctx: C, opts: KeyListOpts): StoreReply<C, ApiKeyListRow[]>;
47
+ export declare function authListRows(ctx: Context, opts: KeyListOpts): Promise<ApiKeyListRow[]>;
48
+ /** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
49
+ export declare function authListAllTenants(ctx: Context, active: boolean): ApiKeyListItem[];
46
50
  export interface AuthRevokeResult {
47
51
  ok: true;
48
52
  revokedAt: string;
49
53
  }
50
- export type AuthRevokeReply<C extends Context> = StoreReply<C, AuthRevokeResult>;
51
54
  /** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
52
55
  * The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
53
- export declare function authRevoke<C extends Context>(ctx: C, keyId: string): AuthRevokeReply<C>;
56
+ export declare function authRevoke(ctx: Context, keyId: string): Promise<AuthRevokeResult>;
54
57
  /** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
55
58
  * so the local CLI can run revoke and grant in the key's own tenant. */
56
- export declare function authKeyTenant(ctx: Context, keyId: string): string | undefined;
59
+ export declare function authKeyTenant(ctx: Context, keyId: string): Promise<string | undefined>;
57
60
  /** Shared result shape for authGrant/authUngrant, named per the file's oxlint anti-slop rule. */
58
61
  export interface AuthGrantResult {
59
62
  ok: true;
@@ -62,5 +65,4 @@ export interface AuthGrantResult {
62
65
  export declare function authGrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
63
66
  /** Revoke `keyId`'s grant on `scope`. Same authorization and lookup rules as authGrant. */
64
67
  export declare function authUngrant(ctx: Context, keyId: string, scope: string): AuthGrantResult;
65
- export {};
66
68
  //# sourceMappingURL=auth.d.ts.map
package/dist/api/auth.js CHANGED
@@ -1,10 +1,11 @@
1
1
  // API key management: create, list, revoke, and grant or ungrant restricted scopes.
2
2
  import { BadRequestError, ForbiddenError, NotFoundError } from '../core/api-errors.js';
3
- import { mintApiKey, } from '../store/auth.js';
3
+ import { DEFAULT_KEY_TTL_DAYS, listApiKeys, mintApiKey, } from '../store/auth.js';
4
+ import { requireGroup } from '../store/index.js';
5
+ import { storeFor } from '../store/sqlite/store.js';
4
6
  import { changeScopeGrant } from '../store/sqlite/local.js';
5
- import { sqliteSyncStore } from '../store/sqlite/store.js';
6
7
  import { DAY_MS } from '../util/time.js';
7
- import { andThen, notPorted, onStore } from './on-store.js';
8
+ import { requireHostAdmin } from './types.js';
8
9
  const API_KEY_SUBJECT = 'api_key:';
9
10
  /** The key id an API-key actor's subject names, or null for any other actor. */
10
11
  function keyIdOfSubject(subject) {
@@ -12,23 +13,21 @@ function keyIdOfSubject(subject) {
12
13
  }
13
14
  /** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
14
15
  * Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
15
- export function authCreate(ctx, opts) {
16
- // The key and its auth_create row commit together on either store, so a failed audit write leaves no key.
17
- return onStore(ctx, (port) => {
18
- const keyWrites = port.keyWrites ?? notPorted(port, 'keyWrites');
19
- const { plaintext, mint } = adminKeyMint(ctx, opts);
20
- return andThen(keyWrites.createApiKey(mint), () => createResult(mint, plaintext));
21
- });
16
+ export async function authCreate(ctx, opts) {
17
+ // The key and its auth_create row commit together on every store, so a failed audit write leaves no key.
18
+ const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
19
+ const { plaintext, mint } = adminKeyMint(ctx, opts);
20
+ await keyWrites.createApiKey(mint);
21
+ return createResult(mint, plaintext);
22
22
  }
23
23
  /** A key row in the caller's tenant, made here so only its hash ever reaches a store. */
24
24
  function newKey(ctx, fields) {
25
25
  const { keyId, plaintext, keyHash } = mintApiKey();
26
26
  return { plaintext, key: { ...fields, keyId, keyHash, tenantId: ctx.tenantId, createdAt: new Date().toISOString() } };
27
27
  }
28
- /** Days a key lives when its mint names no expiry, so a key nobody remembers stops working by itself. */
29
- const DEFAULT_KEY_TTL_DAYS = 90;
28
+ export { DEFAULT_KEY_TTL_DAYS };
30
29
  // The ceiling keeps toISOString in range.
31
- const MAX_TTL_DAYS = 3650;
30
+ export const MAX_TTL_DAYS = 3650;
32
31
  /** A 400, not a RangeError, since the caller of the mint chose these. */
33
32
  function mintExpiry({ ttlDays, noExpiry }) {
34
33
  if (noExpiry && ttlDays !== undefined) {
@@ -70,12 +69,11 @@ function assertSelfMintOpts({ ttlDays, perSubject }) {
70
69
  }
71
70
  /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
72
71
  * binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
73
- export function authCreateSelf(ctx, opts) {
74
- return onStore(ctx, (port) => {
75
- const keyWrites = port.keyWrites ?? notPorted(port, 'keyWrites');
76
- const { plaintext, mint } = selfKeyMint(ctx, opts);
77
- return andThen(keyWrites.createSelfApiKey(mint), () => selfResult(mint, plaintext));
78
- });
72
+ export async function authCreateSelf(ctx, opts) {
73
+ const keyWrites = requireGroup(storeFor(ctx), 'keyWrites');
74
+ const { plaintext, mint } = selfKeyMint(ctx, opts);
75
+ await keyWrites.createSelfApiKey(mint);
76
+ return selfResult(mint, plaintext);
79
77
  }
80
78
  function selfKeyMint(ctx, opts) {
81
79
  if (!ctx.actor.viaAuthResolver) {
@@ -97,16 +95,20 @@ function selfResult({ key }, plaintext) {
97
95
  return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: 'member', expiresAt: key.expiresAt };
98
96
  }
99
97
  /** One page of the caller's tenant's keys, newest first, with the row ids a next-page cursor is built from. */
100
- export function authListRows(ctx, opts) {
101
- return onStore(ctx, (port) => listRows(ctx, port, opts));
98
+ export async function authListRows(ctx, opts) {
99
+ return listRows(ctx, storeFor(ctx), opts);
102
100
  }
103
- function listRows(ctx, port, opts) {
104
- const keyWrites = port.keyWrites ?? notPorted(port, 'keyWrites');
101
+ /** Every tenant's keys in the store, live ones only unless `active` is false; the host's own view, so the host admin only. */
102
+ export function authListAllTenants(ctx, active) {
103
+ requireHostAdmin(ctx, "Listing every tenant's keys");
104
+ return listApiKeys(ctx.hippoRoot, { active });
105
+ }
106
+ async function listRows(ctx, store, opts) {
107
+ const keyWrites = requireGroup(store, 'keyWrites');
105
108
  const keyId = memberKeyIdOf(ctx.actor);
106
- return andThen(keyId === null ? undefined : port.findApiKey(keyId), (record) => {
107
- const filter = memberListFilter(ctx.actor, record?.ownerSubject);
108
- return filter === null ? [] : keyWrites.listApiKeys({ ...opts, tenantId: ctx.tenantId, ...filter });
109
- });
109
+ const record = keyId === null ? undefined : await store.findApiKey(keyId);
110
+ const filter = memberListFilter(ctx.actor, record?.ownerSubject);
111
+ return filter === null ? [] : keyWrites.listApiKeys({ ...opts, tenantId: ctx.tenantId, ...filter });
110
112
  }
111
113
  /** The key id of a member API key caller, whose owner decides what it lists; null for any other caller. */
112
114
  function memberKeyIdOf(actor) {
@@ -139,16 +141,14 @@ function assertMayRevoke(ctx, keyId, row) {
139
141
  }
140
142
  /** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
141
143
  * The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
142
- export function authRevoke(ctx, keyId) {
143
- return onStore(ctx, (port) => {
144
- const keyAudit = port.keyAudit ?? notPorted(port, 'keyAudit');
145
- assertMemberKeyRevokesSelf(ctx, keyId);
146
- return andThen(port.findApiKey(keyId), (record) => {
147
- assertMayRevoke(ctx, keyId, keyOwnerOf(record));
148
- const revoke = { tenantId: ctx.tenantId, keyId, actor: ctx.actor.subject, at: new Date().toISOString() };
149
- return andThen(keyAudit.revokeApiKey(revoke), (revokedAt) => ({ ok: true, revokedAt }));
150
- });
151
- });
144
+ export async function authRevoke(ctx, keyId) {
145
+ const store = storeFor(ctx);
146
+ const keyAudit = requireGroup(store, 'keyAudit');
147
+ assertMemberKeyRevokesSelf(ctx, keyId);
148
+ const record = await store.findApiKey(keyId);
149
+ assertMayRevoke(ctx, keyId, keyOwnerOf(record));
150
+ const revoke = { tenantId: ctx.tenantId, keyId, actor: ctx.actor.subject, at: new Date().toISOString() };
151
+ return { ok: true, revokedAt: await keyAudit.revokeApiKey(revoke) };
152
152
  }
153
153
  function assertMemberKeyRevokesSelf(ctx, keyId) {
154
154
  if (ctx.actor.role !== 'admin' && !ctx.actor.viaAuthResolver && keyIdOfSubject(ctx.actor.subject) !== keyId) {
@@ -160,12 +160,11 @@ function keyOwnerOf(record) {
160
160
  }
161
161
  /** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
162
162
  * so the local CLI can run revoke and grant in the key's own tenant. */
163
- export function authKeyTenant(ctx, keyId) {
163
+ export async function authKeyTenant(ctx, keyId) {
164
164
  if (!ctx.actor.hostAdmin) {
165
165
  throw new ForbiddenError('Only the host admin can look up a key across tenants');
166
166
  }
167
- // Synchronous for the CLI, so it reads hippo.db whatever store ctx names.
168
- return sqliteSyncStore(ctx.hippoRoot).findApiKey(keyId)?.tenantId;
167
+ return (await storeFor(ctx).findApiKey(keyId))?.tenantId;
169
168
  }
170
169
  /** Grant `keyId` read access to one restricted `scope`. Admin only. */
171
170
  export function authGrant(ctx, keyId, scope) {