hippo-memory 1.59.0 → 1.61.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 (596) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1260
  53. package/dist/api.js +25 -2711
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +7 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +7 -4
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +319 -13
  123. package/dist/cli.js +436 -8580
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +12 -9
  126. package/dist/config.js +12 -11
  127. package/dist/connectors/github/backfill.js +94 -87
  128. package/dist/connectors/github/cli-impl.js +5 -3
  129. package/dist/connectors/github/dlq.js +67 -54
  130. package/dist/connectors/github/ingest.js +34 -35
  131. package/dist/connectors/github/tenant-routing.js +3 -2
  132. package/dist/connectors/github/webhook.js +135 -216
  133. package/dist/connectors/slack/dlq.js +49 -61
  134. package/dist/connectors/slack/ingest.js +55 -48
  135. package/dist/connectors/slack/tenant-routing.js +4 -3
  136. package/dist/connectors/slack/webhook.js +72 -74
  137. package/dist/consolidate/conflicts.d.ts +10 -0
  138. package/dist/consolidate/conflicts.js +178 -0
  139. package/dist/consolidate/decay.d.ts +12 -0
  140. package/dist/consolidate/decay.js +145 -0
  141. package/dist/consolidate/llm-passes.d.ts +3 -0
  142. package/dist/consolidate/llm-passes.js +141 -0
  143. package/dist/consolidate/merge.d.ts +7 -0
  144. package/dist/consolidate/merge.js +251 -0
  145. package/dist/consolidate/physics-pass.d.ts +3 -0
  146. package/dist/consolidate/physics-pass.js +60 -0
  147. package/dist/consolidate/run.d.ts +69 -0
  148. package/dist/consolidate/run.js +76 -0
  149. package/dist/consolidate/sleep.d.ts +18 -0
  150. package/dist/consolidate/sleep.js +209 -0
  151. package/dist/consolidate/traces.d.ts +4 -0
  152. package/dist/consolidate/traces.js +178 -0
  153. package/dist/context-auto.js +7 -11
  154. package/dist/context-render.d.ts +1 -1
  155. package/dist/context-render.js +1 -1
  156. package/dist/customer-notes.d.ts +3 -0
  157. package/dist/customer-notes.js +6 -4
  158. package/dist/dag.js +13 -12
  159. package/dist/dashboard-actions.d.ts +20 -0
  160. package/dist/dashboard-actions.js +88 -0
  161. package/dist/dashboard-params.d.ts +45 -0
  162. package/dist/dashboard-params.js +127 -0
  163. package/dist/dashboard-queries.d.ts +15 -0
  164. package/dist/dashboard-queries.js +355 -0
  165. package/dist/dashboard-snapshot.d.ts +138 -0
  166. package/dist/dashboard-snapshot.js +308 -0
  167. package/dist/dashboard-types.d.ts +163 -0
  168. package/dist/dashboard-types.js +3 -0
  169. package/dist/dashboard.d.ts +6 -7
  170. package/dist/dashboard.js +231 -203
  171. package/dist/db/busy.d.ts +5 -0
  172. package/dist/db/busy.js +24 -0
  173. package/dist/db/continuity.d.ts +5 -0
  174. package/dist/db/continuity.js +145 -0
  175. package/dist/db/meta.d.ts +8 -0
  176. package/dist/db/meta.js +35 -0
  177. package/dist/db/migrate.d.ts +9 -0
  178. package/dist/db/migrate.js +138 -0
  179. package/dist/db/migrations/index.d.ts +5 -0
  180. package/dist/db/migrations/index.js +109 -0
  181. package/dist/db/migrations/types.d.ts +14 -0
  182. package/dist/db/migrations/types.js +2 -0
  183. package/dist/db/migrations/v01.d.ts +3 -0
  184. package/dist/db/migrations/v01.js +38 -0
  185. package/dist/db/migrations/v02.d.ts +3 -0
  186. package/dist/db/migrations/v02.js +21 -0
  187. package/dist/db/migrations/v03.d.ts +3 -0
  188. package/dist/db/migrations/v03.js +22 -0
  189. package/dist/db/migrations/v04.d.ts +3 -0
  190. package/dist/db/migrations/v04.js +28 -0
  191. package/dist/db/migrations/v05.d.ts +3 -0
  192. package/dist/db/migrations/v05.js +21 -0
  193. package/dist/db/migrations/v06.d.ts +3 -0
  194. package/dist/db/migrations/v06.js +25 -0
  195. package/dist/db/migrations/v07.d.ts +3 -0
  196. package/dist/db/migrations/v07.js +13 -0
  197. package/dist/db/migrations/v08.d.ts +3 -0
  198. package/dist/db/migrations/v08.js +8 -0
  199. package/dist/db/migrations/v09.d.ts +3 -0
  200. package/dist/db/migrations/v09.js +13 -0
  201. package/dist/db/migrations/v10.d.ts +3 -0
  202. package/dist/db/migrations/v10.js +17 -0
  203. package/dist/db/migrations/v11.d.ts +3 -0
  204. package/dist/db/migrations/v11.js +15 -0
  205. package/dist/db/migrations/v12.d.ts +3 -0
  206. package/dist/db/migrations/v12.js +11 -0
  207. package/dist/db/migrations/v13.d.ts +3 -0
  208. package/dist/db/migrations/v13.js +15 -0
  209. package/dist/db/migrations/v14.d.ts +3 -0
  210. package/dist/db/migrations/v14.js +66 -0
  211. package/dist/db/migrations/v15.d.ts +3 -0
  212. package/dist/db/migrations/v15.js +42 -0
  213. package/dist/db/migrations/v16.d.ts +3 -0
  214. package/dist/db/migrations/v16.js +61 -0
  215. package/dist/db/migrations/v17.d.ts +3 -0
  216. package/dist/db/migrations/v17.js +46 -0
  217. package/dist/db/migrations/v18.d.ts +3 -0
  218. package/dist/db/migrations/v18.js +60 -0
  219. package/dist/db/migrations/v19.d.ts +3 -0
  220. package/dist/db/migrations/v19.js +28 -0
  221. package/dist/db/migrations/v20.d.ts +3 -0
  222. package/dist/db/migrations/v20.js +42 -0
  223. package/dist/db/migrations/v21.d.ts +3 -0
  224. package/dist/db/migrations/v21.js +16 -0
  225. package/dist/db/migrations/v22.d.ts +3 -0
  226. package/dist/db/migrations/v22.js +82 -0
  227. package/dist/db/migrations/v23.d.ts +3 -0
  228. package/dist/db/migrations/v23.js +48 -0
  229. package/dist/db/migrations/v24.d.ts +3 -0
  230. package/dist/db/migrations/v24.js +72 -0
  231. package/dist/db/migrations/v25.d.ts +3 -0
  232. package/dist/db/migrations/v25.js +46 -0
  233. package/dist/db/migrations/v26.d.ts +3 -0
  234. package/dist/db/migrations/v26.js +23 -0
  235. package/dist/db/migrations/v27.d.ts +3 -0
  236. package/dist/db/migrations/v27.js +57 -0
  237. package/dist/db/migrations/v28.d.ts +3 -0
  238. package/dist/db/migrations/v28.js +38 -0
  239. package/dist/db/migrations/v29.d.ts +3 -0
  240. package/dist/db/migrations/v29.js +78 -0
  241. package/dist/db/migrations/v30.d.ts +3 -0
  242. package/dist/db/migrations/v30.js +92 -0
  243. package/dist/db/migrations/v31.d.ts +3 -0
  244. package/dist/db/migrations/v31.js +74 -0
  245. package/dist/db/migrations/v32.d.ts +3 -0
  246. package/dist/db/migrations/v32.js +102 -0
  247. package/dist/db/migrations/v33.d.ts +3 -0
  248. package/dist/db/migrations/v33.js +104 -0
  249. package/dist/db/migrations/v34.d.ts +3 -0
  250. package/dist/db/migrations/v34.js +93 -0
  251. package/dist/db/migrations/v35.d.ts +3 -0
  252. package/dist/db/migrations/v35.js +98 -0
  253. package/dist/db/migrations/v36.d.ts +3 -0
  254. package/dist/db/migrations/v36.js +98 -0
  255. package/dist/db/migrations/v37.d.ts +3 -0
  256. package/dist/db/migrations/v37.js +219 -0
  257. package/dist/db/migrations/v38.d.ts +3 -0
  258. package/dist/db/migrations/v38.js +277 -0
  259. package/dist/db/migrations/v39.d.ts +3 -0
  260. package/dist/db/migrations/v39.js +59 -0
  261. package/dist/db/migrations/v40.d.ts +3 -0
  262. package/dist/db/migrations/v40.js +74 -0
  263. package/dist/db/migrations/v41.d.ts +3 -0
  264. package/dist/db/migrations/v41.js +43 -0
  265. package/dist/db/migrations/v42.d.ts +3 -0
  266. package/dist/db/migrations/v42.js +41 -0
  267. package/dist/db/migrations/v43.d.ts +3 -0
  268. package/dist/db/migrations/v43.js +67 -0
  269. package/dist/db/migrations/v44.d.ts +3 -0
  270. package/dist/db/migrations/v44.js +28 -0
  271. package/dist/db/migrations/v45.d.ts +3 -0
  272. package/dist/db/migrations/v45.js +30 -0
  273. package/dist/db/migrations/v46.d.ts +3 -0
  274. package/dist/db/migrations/v46.js +25 -0
  275. package/dist/db/migrations/v47.d.ts +3 -0
  276. package/dist/db/migrations/v47.js +17 -0
  277. package/dist/db/migrations/v48.d.ts +3 -0
  278. package/dist/db/migrations/v48.js +10 -0
  279. package/dist/db/migrations/v49.d.ts +3 -0
  280. package/dist/db/migrations/v49.js +31 -0
  281. package/dist/db/migrations/v50.d.ts +3 -0
  282. package/dist/db/migrations/v50.js +67 -0
  283. package/dist/db/migrations/v51.d.ts +3 -0
  284. package/dist/db/migrations/v51.js +14 -0
  285. package/dist/db/migrations/v52.d.ts +3 -0
  286. package/dist/db/migrations/v52.js +7 -0
  287. package/dist/db/open.d.ts +23 -0
  288. package/dist/db/open.js +146 -0
  289. package/dist/db/sqlite.d.ts +21 -0
  290. package/dist/db/sqlite.js +8 -0
  291. package/dist/db/tables.d.ts +7 -0
  292. package/dist/db/tables.js +38 -0
  293. package/dist/db.d.ts +6 -46
  294. package/dist/db.js +5 -3036
  295. package/dist/decisions.d.ts +4 -1
  296. package/dist/decisions.js +9 -7
  297. package/dist/dedupe.js +3 -2
  298. package/dist/delivery-recorder.js +5 -1
  299. package/dist/doctor.js +4 -3
  300. package/dist/dormant.js +1 -0
  301. package/dist/embedding-provider.d.ts +1 -1
  302. package/dist/embedding-provider.js +7 -5
  303. package/dist/embeddings.d.ts +9 -52
  304. package/dist/embeddings.js +47 -298
  305. package/dist/env.d.ts +75 -0
  306. package/dist/env.js +119 -0
  307. package/dist/eval-suite.js +1 -1
  308. package/dist/eval.js +2 -2
  309. package/dist/extract.js +5 -4
  310. package/dist/gated-write.js +3 -1
  311. package/dist/goals.d.ts +3 -1
  312. package/dist/goals.js +18 -0
  313. package/dist/graph/read.d.ts +73 -0
  314. package/dist/graph/read.js +325 -0
  315. package/dist/graph/rows.d.ts +45 -0
  316. package/dist/graph/rows.js +51 -0
  317. package/dist/graph/types.d.ts +83 -0
  318. package/dist/graph/types.js +11 -0
  319. package/dist/graph/write.d.ts +93 -0
  320. package/dist/{graph.js → graph/write.js} +8 -391
  321. package/dist/graph-extract.js +2 -1
  322. package/dist/graph-recall.d.ts +1 -1
  323. package/dist/graph-recall.js +2 -2
  324. package/dist/graph-stream.js +1 -1
  325. package/dist/graph-view.d.ts +1 -1
  326. package/dist/graph-view.js +1 -1
  327. package/dist/half-life-migration.d.ts +1 -1
  328. package/dist/half-life-migration.js +2 -1
  329. package/dist/handoff.js +3 -0
  330. package/dist/hooks/codex-session.d.ts +8 -0
  331. package/dist/hooks/codex-session.js +76 -0
  332. package/dist/hooks/codex-wrapper.d.ts +55 -0
  333. package/dist/hooks/codex-wrapper.js +288 -0
  334. package/dist/hooks/json-hooks.d.ts +63 -0
  335. package/dist/hooks/json-hooks.js +356 -0
  336. package/dist/hooks/opencode.d.ts +50 -0
  337. package/dist/hooks/opencode.js +202 -0
  338. package/dist/hooks/shared.d.ts +54 -0
  339. package/dist/hooks/shared.js +77 -0
  340. package/dist/http-retry.d.ts +2 -0
  341. package/dist/http-retry.js +4 -3
  342. package/dist/http-util.d.ts +3 -0
  343. package/dist/http-util.js +10 -0
  344. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  345. package/dist/importers/core.js +141 -0
  346. package/dist/importers/markdown-parse.d.ts +41 -0
  347. package/dist/importers/markdown-parse.js +132 -0
  348. package/dist/importers/markdown.d.ts +3 -0
  349. package/dist/importers/markdown.js +92 -0
  350. package/dist/importers/sources.d.ts +7 -0
  351. package/dist/importers/sources.js +229 -0
  352. package/dist/importers/vault.d.ts +11 -0
  353. package/dist/importers/vault.js +352 -0
  354. package/dist/incidents.d.ts +3 -0
  355. package/dist/incidents.js +8 -5
  356. package/dist/index.d.ts +25 -6
  357. package/dist/index.js +23 -6
  358. package/dist/invalidation.js +2 -1
  359. package/dist/judgment.js +7 -3
  360. package/dist/keyset.d.ts +13 -0
  361. package/dist/keyset.js +8 -0
  362. package/dist/local-embedding.d.ts +13 -0
  363. package/dist/local-embedding.js +165 -0
  364. package/dist/log.d.ts +7 -0
  365. package/dist/log.js +19 -1
  366. package/dist/mcp/admin-tools.d.ts +8 -0
  367. package/dist/mcp/admin-tools.js +116 -0
  368. package/dist/mcp/format.d.ts +27 -0
  369. package/dist/mcp/format.js +135 -0
  370. package/dist/mcp/memory-tools.d.ts +5 -0
  371. package/dist/mcp/memory-tools.js +83 -0
  372. package/dist/mcp/protocol.d.ts +83 -0
  373. package/dist/mcp/protocol.js +55 -0
  374. package/dist/mcp/recall-tools.d.ts +6 -0
  375. package/dist/mcp/recall-tools.js +320 -0
  376. package/dist/mcp/request.d.ts +10 -0
  377. package/dist/mcp/request.js +163 -0
  378. package/dist/mcp/server.d.ts +4 -70
  379. package/dist/mcp/server.js +8 -1172
  380. package/dist/mcp/session-state.d.ts +11 -0
  381. package/dist/mcp/session-state.js +28 -0
  382. package/dist/mcp/stdio.d.ts +8 -0
  383. package/dist/mcp/stdio.js +79 -0
  384. package/dist/mcp/tools.d.ts +11 -0
  385. package/dist/mcp/tools.js +247 -0
  386. package/dist/memory.d.ts +8 -3
  387. package/dist/memory.js +27 -1
  388. package/dist/multihop.d.ts +1 -1
  389. package/dist/multihop.js +2 -1
  390. package/dist/owner-validation.js +2 -1
  391. package/dist/physics-state.js +10 -7
  392. package/dist/policies.d.ts +3 -0
  393. package/dist/policies.js +8 -6
  394. package/dist/postinstall.js +3 -2
  395. package/dist/predictions/planning-fallacy.d.ts +100 -0
  396. package/dist/predictions/planning-fallacy.js +190 -0
  397. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  398. package/dist/predictions/store.js +434 -0
  399. package/dist/processes.d.ts +3 -0
  400. package/dist/processes.js +8 -5
  401. package/dist/project-briefs.d.ts +3 -0
  402. package/dist/project-briefs.js +7 -5
  403. package/dist/project-identity.d.ts +1 -1
  404. package/dist/project-identity.js +12 -6
  405. package/dist/project-merge.js +3 -1
  406. package/dist/quarantine.d.ts +2 -1
  407. package/dist/quarantine.js +8 -5
  408. package/dist/raw-archive-mirror-cleanup.js +2 -1
  409. package/dist/raw-archive.js +1 -1
  410. package/dist/recall-history.js +3 -2
  411. package/dist/recall-pipeline.d.ts +2 -2
  412. package/dist/recall-pipeline.js +16 -8
  413. package/dist/recall-scope.js +1 -1
  414. package/dist/recall-trace.d.ts +3 -3
  415. package/dist/recall-trace.js +10 -14
  416. package/dist/refine-llm.js +20 -11
  417. package/dist/reject-flow.js +6 -1
  418. package/dist/rerankers/clef.d.ts +2 -2
  419. package/dist/rerankers/clef.js +72 -30
  420. package/dist/rerankers/cross-encoder.js +6 -4
  421. package/dist/rerankers/jev.d.ts +4 -2
  422. package/dist/rerankers/jev.js +24 -19
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +61 -41
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/same-text.d.ts +2 -0
  428. package/dist/same-text.js +4 -0
  429. package/dist/scheduler.d.ts +1 -0
  430. package/dist/scheduler.js +26 -3
  431. package/dist/scope.js +4 -3
  432. package/dist/search/as-of.d.ts +10 -0
  433. package/dist/search/as-of.js +22 -0
  434. package/dist/search/bm25-search.d.ts +14 -0
  435. package/dist/search/bm25-search.js +43 -0
  436. package/dist/search/bm25.d.ts +15 -0
  437. package/dist/search/bm25.js +54 -0
  438. package/dist/search/boosts.d.ts +54 -0
  439. package/dist/search/boosts.js +94 -0
  440. package/dist/search/breakdown.d.ts +7 -0
  441. package/dist/search/breakdown.js +20 -0
  442. package/dist/search/explain.d.ts +25 -0
  443. package/dist/search/explain.js +31 -0
  444. package/dist/search/finalize.d.ts +8 -0
  445. package/dist/search/finalize.js +52 -0
  446. package/dist/search/fusion.d.ts +27 -0
  447. package/dist/search/fusion.js +42 -0
  448. package/dist/search/hybrid-score.d.ts +20 -0
  449. package/dist/search/hybrid-score.js +73 -0
  450. package/dist/search/hybrid.d.ts +46 -0
  451. package/dist/search/hybrid.js +64 -0
  452. package/dist/search/physics-search.d.ts +29 -0
  453. package/dist/search/physics-search.js +162 -0
  454. package/dist/search/rerank.d.ts +10 -0
  455. package/dist/search/rerank.js +72 -0
  456. package/dist/search/temporal.d.ts +15 -0
  457. package/dist/search/temporal.js +45 -0
  458. package/dist/search/types.d.ts +91 -0
  459. package/dist/search/types.js +2 -0
  460. package/dist/search/vector.d.ts +30 -0
  461. package/dist/search/vector.js +71 -0
  462. package/dist/secret-detect.d.ts +2 -0
  463. package/dist/secret-detect.js +3 -1
  464. package/dist/server/auth.d.ts +52 -0
  465. package/dist/server/auth.js +221 -0
  466. package/dist/server/client-ip.d.ts +25 -0
  467. package/dist/server/client-ip.js +92 -0
  468. package/dist/server/cursor.d.ts +23 -0
  469. package/dist/server/cursor.js +58 -0
  470. package/dist/server/lifecycle.d.ts +7 -0
  471. package/dist/server/lifecycle.js +29 -0
  472. package/dist/server/mcp-http.d.ts +5 -0
  473. package/dist/server/mcp-http.js +199 -0
  474. package/dist/server/request.d.ts +33 -0
  475. package/dist/server/request.js +103 -0
  476. package/dist/server/routes/admin.d.ts +9 -0
  477. package/dist/server/routes/admin.js +158 -0
  478. package/dist/server/routes/customer-notes.d.ts +7 -0
  479. package/dist/server/routes/customer-notes.js +112 -0
  480. package/dist/server/routes/decisions.d.ts +7 -0
  481. package/dist/server/routes/decisions.js +133 -0
  482. package/dist/server/routes/incidents.d.ts +7 -0
  483. package/dist/server/routes/incidents.js +126 -0
  484. package/dist/server/routes/memories.d.ts +10 -0
  485. package/dist/server/routes/memories.js +179 -0
  486. package/dist/server/routes/policies.d.ts +8 -0
  487. package/dist/server/routes/policies.js +151 -0
  488. package/dist/server/routes/predictions.d.ts +7 -0
  489. package/dist/server/routes/predictions.js +164 -0
  490. package/dist/server/routes/processes.d.ts +7 -0
  491. package/dist/server/routes/processes.js +161 -0
  492. package/dist/server/routes/project-briefs.d.ts +8 -0
  493. package/dist/server/routes/project-briefs.js +136 -0
  494. package/dist/server/routes/recall.d.ts +8 -0
  495. package/dist/server/routes/recall.js +340 -0
  496. package/dist/server/routes/skills.d.ts +8 -0
  497. package/dist/server/routes/skills.js +150 -0
  498. package/dist/server/types.d.ts +56 -0
  499. package/dist/server/types.js +2 -0
  500. package/dist/server/validation.d.ts +14 -0
  501. package/dist/server/validation.js +91 -0
  502. package/dist/server.d.ts +7 -61
  503. package/dist/server.js +92 -2368
  504. package/dist/session-digest.d.ts +1 -1
  505. package/dist/session-digest.js +9 -2
  506. package/dist/shared.d.ts +3 -1
  507. package/dist/shared.js +46 -40
  508. package/dist/skills.d.ts +3 -0
  509. package/dist/skills.js +7 -5
  510. package/dist/stdin.js +3 -2
  511. package/dist/store/audit-event.d.ts +19 -0
  512. package/dist/store/audit-event.js +33 -0
  513. package/dist/store/candidates.d.ts +42 -0
  514. package/dist/store/candidates.js +152 -0
  515. package/dist/store/conflicts.d.ts +44 -0
  516. package/dist/store/conflicts.js +444 -0
  517. package/dist/store/delete-and-batch.d.ts +63 -0
  518. package/dist/store/delete-and-batch.js +310 -0
  519. package/dist/store/entry-reads.d.ts +92 -0
  520. package/dist/store/entry-reads.js +255 -0
  521. package/dist/store/entry-row.d.ts +67 -0
  522. package/dist/store/entry-row.js +208 -0
  523. package/dist/store/entry-writes.d.ts +46 -0
  524. package/dist/store/entry-writes.js +148 -0
  525. package/dist/store/handoffs.d.ts +26 -0
  526. package/dist/store/handoffs.js +184 -0
  527. package/dist/store/index-and-stats.d.ts +52 -0
  528. package/dist/store/index-and-stats.js +214 -0
  529. package/dist/store/markdown.d.ts +10 -0
  530. package/dist/store/markdown.js +108 -0
  531. package/dist/store/mirrors.d.ts +49 -0
  532. package/dist/store/mirrors.js +312 -0
  533. package/dist/store/open.d.ts +15 -0
  534. package/dist/store/open.js +223 -0
  535. package/dist/store/rows.d.ts +178 -0
  536. package/dist/store/rows.js +158 -0
  537. package/dist/store/search-rows.d.ts +86 -0
  538. package/dist/store/search-rows.js +254 -0
  539. package/dist/store/sessions.d.ts +83 -0
  540. package/dist/store/sessions.js +272 -0
  541. package/dist/store/summaries.d.ts +94 -0
  542. package/dist/store/summaries.js +377 -0
  543. package/dist/store/tenant-lookup.d.ts +12 -0
  544. package/dist/store/tenant-lookup.js +16 -0
  545. package/dist/store-cards.js +2 -1
  546. package/dist/summary-dirty.d.ts +4 -0
  547. package/dist/summary-dirty.js +32 -0
  548. package/dist/support-bundle.js +4 -3
  549. package/dist/tenant.js +2 -2
  550. package/dist/token-ledger.js +1 -0
  551. package/dist/tokenize.d.ts +2 -0
  552. package/dist/tokenize.js +16 -0
  553. package/dist/transcript-tail.d.ts +7 -0
  554. package/dist/transcript-tail.js +48 -0
  555. package/dist/vector-store.d.ts +27 -0
  556. package/dist/vector-store.js +210 -0
  557. package/dist/version.d.ts +2 -2
  558. package/dist/version.js +2 -2
  559. package/dist/working-memory.js +1 -1
  560. package/dist/yaml.js +36 -11
  561. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  566. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  570. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  571. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  572. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  573. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  574. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  575. package/dist-ui/index.html +3 -25
  576. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  577. package/extensions/openclaw-plugin/package.json +1 -1
  578. package/openclaw.plugin.json +1 -1
  579. package/package.json +2 -1
  580. package/dist/capture.d.ts +0 -155
  581. package/dist/capture.js +0 -1293
  582. package/dist/consolidate.d.ts +0 -58
  583. package/dist/consolidate.js +0 -1123
  584. package/dist/graph.d.ts +0 -245
  585. package/dist/hooks.d.ts +0 -208
  586. package/dist/hooks.js +0 -1073
  587. package/dist/importers.js +0 -897
  588. package/dist/predictions.js +0 -620
  589. package/dist/search.d.ts +0 -320
  590. package/dist/search.js +0 -968
  591. package/dist/store.d.ts +0 -744
  592. package/dist/store.js +0 -3372
  593. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  594. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  595. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  596. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,434 @@
1
+ /**
2
+ * E2 prediction first-class object (v0.31 / docs/plans/2026-05-26-e2-prediction-object.md).
3
+ *
4
+ * Canonical store for ex-ante claims that can be closed against ex-post
5
+ * outcomes. The `predictions` table holds every field (including
6
+ * `claim_text`); a memory row mirrors the claim for recall/inspect surfaces
7
+ * but is NOT the source of truth — ON DELETE SET NULL on memory_id means
8
+ * memory deletion gracefully orphans the prediction without losing data.
9
+ *
10
+ * Tenant scoping: every helper requires tenantId. The schema's BEFORE INSERT
11
+ * + BEFORE UPDATE triggers (`trg_predictions_tenant_match_*`) enforce that
12
+ * `predictions.tenant_id` matches the referenced memory's tenant_id when
13
+ * `memory_id IS NOT NULL`. Cross-tenant references are unrepresentable at
14
+ * the schema level.
15
+ *
16
+ * Dual-write atomicity: `savePrediction` writes the memory + predictions
17
+ * row inside `writeEntry`'s SAVEPOINT 'write_entry' (store/entry-writes.ts). The
18
+ * afterWrite hook (store/entry-writes.ts) runs inside the same SAVEPOINT, so
19
+ * a failure in either step rolls back both. Pattern matches supersede
20
+ * (api.ts:1486) and the Slack/GitHub connectors.
21
+ *
22
+ * J3 (reference-class / planning-fallacy detector) reads from
23
+ * `loadPredictionsByClass` to compute per-class base rates from
24
+ * (estimate_value, actual_value) at query time. J3 is a follow-up episode;
25
+ * this module ships the data layer.
26
+ */
27
+ import { BadRequestError, NotFoundError } from '../api-errors.js';
28
+ import { openHippoDb, closeHippoDb } from '../db.js';
29
+ import { writeEntry } from '../store/entry-writes.js';
30
+ import { assertTenantId } from '../tenant.js';
31
+ import { createMemory, Layer } from '../memory.js';
32
+ import { appendAuditEvent } from '../audit.js';
33
+ import { loadConfig } from '../config.js';
34
+ import { keysetAfter } from '../keyset.js';
35
+ export const VALID_CLOSURE_STATES = new Set([
36
+ 'open',
37
+ 'closed',
38
+ 'closed-unknown',
39
+ ]);
40
+ function rowToPrediction(row) {
41
+ return {
42
+ id: row.id,
43
+ memoryId: row.memory_id,
44
+ tenantId: row.tenant_id,
45
+ classTag: row.class_tag,
46
+ claimText: row.claim_text,
47
+ estimateValue: row.estimate_value,
48
+ estimateUnit: row.estimate_unit,
49
+ targetDate: row.target_date,
50
+ actualValue: row.actual_value,
51
+ // SAFETY: closure_state is DB-constrained to VALID_CLOSURE_STATES; this
52
+ // module is the only writer and always inserts one of those literals.
53
+ closureState: row.closure_state,
54
+ closedAt: row.closed_at,
55
+ closureNote: row.closure_note,
56
+ createdAt: row.created_at,
57
+ };
58
+ }
59
+ // ---------------------------------------------------------------------------
60
+ // Public API
61
+ // ---------------------------------------------------------------------------
62
+ /**
63
+ * Create a new prediction. Writes a memory mirror + a predictions table
64
+ * row atomically inside `writeEntry`'s SAVEPOINT 'write_entry'. On any
65
+ * failure (audit write, predictions INSERT, trigger ABORT), the SAVEPOINT
66
+ * rolls back — neither the memory row nor the predictions row lands.
67
+ *
68
+ * The memory is tagged `['prediction', classTag]` with `source='prediction'`
69
+ * and `kind='distilled'`. It surfaces in `hippo recall` so the agent can
70
+ * see open predictions naturally; the predictions table is the canonical
71
+ * structured store used by J3.
72
+ */
73
+ export function savePrediction(hippoRoot, tenantId, opts, actor = 'cli') {
74
+ assertTenantId('savePrediction', tenantId);
75
+ if (!opts.classTag)
76
+ throw new BadRequestError('savePrediction: classTag is required');
77
+ if (!opts.claimText)
78
+ throw new BadRequestError('savePrediction: claimText is required');
79
+ const now = new Date().toISOString();
80
+ const mem = createMemory(opts.claimText, {
81
+ tags: ['prediction', opts.classTag],
82
+ layer: Layer.Semantic,
83
+ confidence: 'observed',
84
+ source: 'prediction',
85
+ // SAFETY: 'distilled' is a valid MemoryKind literal (see memory.ts).
86
+ kind: 'distilled',
87
+ baseHalfLifeDays: loadConfig(hippoRoot).defaultHalfLifeDays,
88
+ tenantId,
89
+ });
90
+ // Captured for the return value; populated inside afterWrite hook so the
91
+ // INSERT and the memory write share a SAVEPOINT.
92
+ let savedRow;
93
+ writeEntry(hippoRoot, mem, {
94
+ actor,
95
+ afterWrite: (db, memoryId) => {
96
+ savedRow = insertPredictionRow(db, memoryId, tenantId, opts, now, actor);
97
+ },
98
+ });
99
+ if (!savedRow) {
100
+ // Cannot reach here without the afterWrite throwing first; defensive.
101
+ throw new Error('savePrediction: afterWrite did not populate the row');
102
+ }
103
+ return rowToPrediction(savedRow);
104
+ }
105
+ /** Inserts, reloads and audits the predictions row inside writeEntry's SAVEPOINT. */
106
+ function insertPredictionRow(db, memoryId, tenantId, opts, now, actor) {
107
+ const result = db.prepare(`
108
+ INSERT INTO predictions(
109
+ memory_id, tenant_id, class_tag, claim_text,
110
+ estimate_value, estimate_unit, target_date,
111
+ actual_value, closure_state, closed_at, closure_note, created_at
112
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'open', NULL, NULL, ?)
113
+ `).run(memoryId, tenantId, opts.classTag, opts.claimText, opts.estimateValue ?? null, opts.estimateUnit ?? null, opts.targetDate ?? null, null, // actual_value — null until close
114
+ now);
115
+ const predictionId = Number(result.lastInsertRowid ?? 0);
116
+ // SAFETY: row's shape matches the columns named in the SELECT above.
117
+ const row = db.prepare(`
118
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
119
+ estimate_value, estimate_unit, target_date,
120
+ actual_value, closure_state, closed_at, closure_note, created_at
121
+ FROM predictions WHERE id = ?
122
+ `).get(predictionId);
123
+ if (!row) {
124
+ throw new Error('Failed to reload saved prediction row');
125
+ }
126
+ // GDPR-light audit metadata: prediction_id + class_tag + flags only.
127
+ // No claim_text in metadata; the predictions table holds it canonically.
128
+ appendAuditEvent(db, {
129
+ tenantId,
130
+ actor,
131
+ op: 'predict_create',
132
+ targetId: String(predictionId),
133
+ metadata: {
134
+ prediction_id: predictionId,
135
+ class_tag: opts.classTag,
136
+ has_estimate: opts.estimateValue !== undefined && opts.estimateValue !== null,
137
+ target_date: opts.targetDate ?? null,
138
+ },
139
+ });
140
+ return row;
141
+ }
142
+ /**
143
+ * Close an existing open prediction. Updates the predictions row only;
144
+ * the memory mirror is NOT mutated in v1 (predictions table is canonical).
145
+ * J3 computes accuracy (clean vs regressed) from (estimateValue,
146
+ * actualValue) at query time.
147
+ */
148
+ export function closePrediction(hippoRoot, tenantId, id, opts, actor = 'cli') {
149
+ assertTenantId('closePrediction', tenantId);
150
+ if (!VALID_CLOSURE_STATES.has(opts.closureState)) {
151
+ throw new BadRequestError(`closePrediction: closureState must be one of ${Array.from(VALID_CLOSURE_STATES).join('|')}; got ${opts.closureState}`);
152
+ }
153
+ const now = new Date().toISOString();
154
+ const db = openHippoDb(hippoRoot);
155
+ try {
156
+ db.exec('BEGIN IMMEDIATE');
157
+ try {
158
+ const row = closeOpenPredictionRow(db, tenantId, id, opts, now, actor);
159
+ db.exec('COMMIT');
160
+ return rowToPrediction(row);
161
+ }
162
+ catch (e) {
163
+ try {
164
+ db.exec('ROLLBACK');
165
+ }
166
+ catch {
167
+ // Ignore rollback failures — the throw below is what matters.
168
+ }
169
+ throw e;
170
+ }
171
+ }
172
+ finally {
173
+ closeHippoDb(db);
174
+ }
175
+ }
176
+ /** Closes the row, reloads it and audits the close; the caller owns the transaction. */
177
+ function closeOpenPredictionRow(db, tenantId, id, opts, now, actor) {
178
+ // Codex review finding 2026-05-26: WHERE clause requires
179
+ // closure_state='open' so duplicate close requests / retries against
180
+ // an already-closed prediction return a clear error instead of
181
+ // silently overwriting actual_value + emitting a duplicate
182
+ // predict_close audit row. Zero changed rows → caller decides
183
+ // whether it's a "not found" or "already closed" case based on the
184
+ // load-then-close pattern.
185
+ const updateResult = db.prepare(`
186
+ UPDATE predictions
187
+ SET actual_value = ?, closure_state = ?, closed_at = ?, closure_note = ?
188
+ WHERE id = ? AND tenant_id = ? AND closure_state = 'open'
189
+ `).run(opts.actualValue ?? null, opts.closureState, now, opts.closureNote ?? null, id, tenantId);
190
+ if (updateResult.changes === 0)
191
+ throwCloseMiss(db, tenantId, id);
192
+ // SAFETY: row's shape matches the columns named in the SELECT above.
193
+ const row = db.prepare(`
194
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
195
+ estimate_value, estimate_unit, target_date,
196
+ actual_value, closure_state, closed_at, closure_note, created_at
197
+ FROM predictions WHERE id = ? AND tenant_id = ?
198
+ `).get(id, tenantId);
199
+ if (!row) {
200
+ throw new NotFoundError(`closePrediction: prediction ${id} not found after UPDATE`);
201
+ }
202
+ appendAuditEvent(db, {
203
+ tenantId,
204
+ actor,
205
+ op: 'predict_close',
206
+ targetId: String(id),
207
+ metadata: {
208
+ prediction_id: id,
209
+ closure_state: opts.closureState,
210
+ has_actual: opts.actualValue !== undefined && opts.actualValue !== null,
211
+ },
212
+ });
213
+ return row;
214
+ }
215
+ function throwCloseMiss(db, tenantId, id) {
216
+ // Distinguish "not found" from "already closed" so callers (CLI, HTTP)
217
+ // can surface the right error to the user.
218
+ // SAFETY: row shape matches the single `closure_state` column named
219
+ // in the SELECT above.
220
+ const existing = db.prepare(`
221
+ SELECT closure_state FROM predictions WHERE id = ? AND tenant_id = ?
222
+ `).get(id, tenantId);
223
+ if (!existing) {
224
+ throw new NotFoundError(`closePrediction: prediction ${id} not found for tenant ${tenantId}`);
225
+ }
226
+ throw new BadRequestError(`closePrediction: prediction ${id} is already closed (state='${existing.closure_state}'); ` +
227
+ `cannot re-close. Open predictions only.`);
228
+ }
229
+ export function loadPredictionById(hippoRoot, tenantId, id) {
230
+ assertTenantId('loadPredictionById', tenantId);
231
+ const db = openHippoDb(hippoRoot);
232
+ try {
233
+ // SAFETY: row's shape matches the columns named in the SELECT above.
234
+ const row = db.prepare(`
235
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
236
+ estimate_value, estimate_unit, target_date,
237
+ actual_value, closure_state, closed_at, closure_note, created_at
238
+ FROM predictions WHERE id = ? AND tenant_id = ?
239
+ `).get(id, tenantId);
240
+ return row ? rowToPrediction(row) : null;
241
+ }
242
+ finally {
243
+ closeHippoDb(db);
244
+ }
245
+ }
246
+ export function loadPredictionsByClass(hippoRoot, tenantId, classTag, opts = {}) {
247
+ assertTenantId('loadPredictionsByClass', tenantId);
248
+ const limit = opts.limit ?? 100;
249
+ const after = keysetAfter('created_at', 'id', opts.after);
250
+ const db = openHippoDb(hippoRoot);
251
+ try {
252
+ let rows;
253
+ if (opts.closureState) {
254
+ if (!VALID_CLOSURE_STATES.has(opts.closureState)) {
255
+ throw new BadRequestError(`loadPredictionsByClass: closureState must be one of ${Array.from(VALID_CLOSURE_STATES).join('|')}; got ${opts.closureState}`);
256
+ }
257
+ // SAFETY: rows' shape matches the columns named in the SELECT above.
258
+ rows = db.prepare(`
259
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
260
+ estimate_value, estimate_unit, target_date,
261
+ actual_value, closure_state, closed_at, closure_note, created_at
262
+ FROM predictions
263
+ WHERE tenant_id = ? AND class_tag = ? AND closure_state = ?${after.sql}
264
+ ORDER BY created_at DESC, id DESC
265
+ LIMIT ?
266
+ `).all(tenantId, classTag, opts.closureState, ...after.params, limit);
267
+ }
268
+ else {
269
+ // SAFETY: rows' shape matches the columns named in the SELECT above.
270
+ rows = db.prepare(`
271
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
272
+ estimate_value, estimate_unit, target_date,
273
+ actual_value, closure_state, closed_at, closure_note, created_at
274
+ FROM predictions
275
+ WHERE tenant_id = ? AND class_tag = ?${after.sql}
276
+ ORDER BY created_at DESC, id DESC
277
+ LIMIT ?
278
+ `).all(tenantId, classTag, ...after.params, limit);
279
+ }
280
+ return rows.map(rowToPrediction);
281
+ }
282
+ finally {
283
+ closeHippoDb(db);
284
+ }
285
+ }
286
+ /**
287
+ * Compute base-rate stats for closed predictions in a class. Used by J3
288
+ * reference-class / planning-fallacy detector. Direct application of
289
+ * Lovallo-Kahneman (2003) inside-vs-outside view.
290
+ *
291
+ * Filter: closure_state='closed' AND estimate_value IS NOT NULL AND
292
+ * actual_value IS NOT NULL. Excludes closed-unknown (no actual to
293
+ * compare against) and open (not yet resolved).
294
+ *
295
+ * Audit-emit is BUILT IN here (single source of truth, no caller-site
296
+ * drift risk). Plan-eng-critic round 1 HIGH recommendation: emit inside
297
+ * helper, not at 3 call sites.
298
+ */
299
+ export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor = 'cli',
300
+ /** v0.32 / J3.2 — when false, skip the predict_baserate audit emit. The
301
+ * J3.2 orchestrator (computePlanningFallacyOutput, below) calls this with
302
+ * emitAudit=false and emits its own `recall_autodebias_hint` audit row
303
+ * instead, so the predict_baserate channel stays scoped to deliberate
304
+ * CLI / HTTP / MCP predict-baserate calls and does NOT pollute on every
305
+ * recall containing a forward-claim phrase. Default true preserves the
306
+ * v1.13.0 J3 audit semantics for the 3 direct callers (cmdPredict
307
+ * baserate, /v1/predictions/stats route, hippo_predict_baserate MCP
308
+ * handler) — none of them pass this argument. */
309
+ emitAudit = true) {
310
+ assertTenantId('computePredictionBaserate', tenantId);
311
+ if (!classTag)
312
+ throw new BadRequestError('computePredictionBaserate: classTag is required');
313
+ const db = openHippoDb(hippoRoot);
314
+ try {
315
+ // SAFETY: rows' shape matches the two columns named in the SELECT above.
316
+ const rows = db.prepare(`
317
+ SELECT estimate_value, actual_value
318
+ FROM predictions
319
+ WHERE tenant_id = ?
320
+ AND class_tag = ?
321
+ AND closure_state = 'closed'
322
+ AND estimate_value IS NOT NULL
323
+ AND actual_value IS NOT NULL
324
+ `).all(tenantId, classTag);
325
+ const nClosed = rows.length;
326
+ if (nClosed === 0) {
327
+ // Audit zero-result reads too — agents probing empty classes is
328
+ // a signal worth recording. Skipped when emitAudit=false (J3.2
329
+ // orchestrator path; its own recall_autodebias_hint audit fires
330
+ // only when nClosed > 0 anyway, so no signal is lost).
331
+ if (emitAudit)
332
+ auditBaserateRead(db, tenantId, actor, classTag, 0);
333
+ return {
334
+ classTag,
335
+ nClosed: 0,
336
+ nRatioEligible: 0,
337
+ meanEstimate: null,
338
+ meanActual: null,
339
+ meanRatio: null,
340
+ p50Ratio: null,
341
+ mae: null,
342
+ summary: '',
343
+ };
344
+ }
345
+ const baserate = baserateFromRows(classTag, rows);
346
+ if (emitAudit)
347
+ auditBaserateRead(db, tenantId, actor, classTag, nClosed);
348
+ return baserate;
349
+ }
350
+ finally {
351
+ closeHippoDb(db);
352
+ }
353
+ }
354
+ function auditBaserateRead(db, tenantId, actor, classTag, nClosed) {
355
+ appendAuditEvent(db, {
356
+ tenantId,
357
+ actor,
358
+ op: 'predict_baserate',
359
+ targetId: classTag,
360
+ metadata: { class_tag: classTag, n_closed: nClosed },
361
+ });
362
+ }
363
+ /** Stats over a non-empty set of closed rows. */
364
+ function baserateFromRows(classTag, rows) {
365
+ const nClosed = rows.length;
366
+ const ratioEligible = rows.filter((r) => r.estimate_value > 0);
367
+ const nRatioEligible = ratioEligible.length;
368
+ const meanEstimate = rows.reduce((s, r) => s + r.estimate_value, 0) / nClosed;
369
+ const meanActual = rows.reduce((s, r) => s + r.actual_value, 0) / nClosed;
370
+ const mae = rows.reduce((s, r) => s + Math.abs(r.actual_value - r.estimate_value), 0) / nClosed;
371
+ let meanRatio = null;
372
+ let p50Ratio = null;
373
+ if (nRatioEligible > 0) {
374
+ const ratios = ratioEligible.map((r) => r.actual_value / r.estimate_value);
375
+ meanRatio = ratios.reduce((s, x) => s + x, 0) / nRatioEligible;
376
+ const sorted = ratios.slice().sort((a, b) => a - b);
377
+ p50Ratio = nRatioEligible % 2 === 1
378
+ ? sorted[(nRatioEligible - 1) / 2]
379
+ : (sorted[nRatioEligible / 2 - 1] + sorted[nRatioEligible / 2]) / 2;
380
+ }
381
+ const ratioPart = meanRatio !== null
382
+ ? `averaged ${meanRatio.toFixed(2)}x actual`
383
+ : 'no ratio-eligible rows (all estimates were 0)';
384
+ const summary = `Last ${nClosed} estimate${nClosed === 1 ? '' : 's'} in class ${classTag} ${ratioPart} (MAE ${mae.toFixed(2)}).`;
385
+ return {
386
+ classTag,
387
+ nClosed,
388
+ nRatioEligible,
389
+ meanEstimate,
390
+ meanActual,
391
+ meanRatio,
392
+ p50Ratio,
393
+ mae,
394
+ summary,
395
+ };
396
+ }
397
+ export function loadOpenPredictions(hippoRoot, tenantId, opts = {}) {
398
+ assertTenantId('loadOpenPredictions', tenantId);
399
+ const limit = opts.limit ?? 100;
400
+ const after = keysetAfter('created_at', 'id', opts.after);
401
+ const db = openHippoDb(hippoRoot);
402
+ try {
403
+ let rows;
404
+ if (opts.classTag) {
405
+ // SAFETY: rows' shape matches the columns named in the SELECT above.
406
+ rows = db.prepare(`
407
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
408
+ estimate_value, estimate_unit, target_date,
409
+ actual_value, closure_state, closed_at, closure_note, created_at
410
+ FROM predictions
411
+ WHERE tenant_id = ? AND class_tag = ? AND closure_state = 'open'${after.sql}
412
+ ORDER BY created_at DESC, id DESC
413
+ LIMIT ?
414
+ `).all(tenantId, opts.classTag, ...after.params, limit);
415
+ }
416
+ else {
417
+ // SAFETY: rows' shape matches the columns named in the SELECT above.
418
+ rows = db.prepare(`
419
+ SELECT id, memory_id, tenant_id, class_tag, claim_text,
420
+ estimate_value, estimate_unit, target_date,
421
+ actual_value, closure_state, closed_at, closure_note, created_at
422
+ FROM predictions
423
+ WHERE tenant_id = ? AND closure_state = 'open'${after.sql}
424
+ ORDER BY created_at DESC, id DESC
425
+ LIMIT ?
426
+ `).all(tenantId, ...after.params, limit);
427
+ }
428
+ return rows.map(rowToPrediction);
429
+ }
430
+ finally {
431
+ closeHippoDb(db);
432
+ }
433
+ }
434
+ //# sourceMappingURL=store.js.map
@@ -30,6 +30,7 @@
30
30
  * 'write_entry' via the afterWrite hook, so a failure in any step rolls all of
31
31
  * them back. Pattern matches saveDecision (decisions.ts).
32
32
  */
33
+ import { type KeysetPosition } from './keyset.js';
33
34
  export type ProcessStatus = 'active' | 'superseded' | 'closed';
34
35
  export declare const VALID_PROCESS_STATES: ReadonlySet<ProcessStatus>;
35
36
  /** Arbitrary JSON-shaped value; the domain type for untrusted input at the
@@ -75,6 +76,8 @@ export interface SaveProcessOpts {
75
76
  export interface ListProcessesOpts {
76
77
  status?: ProcessStatus;
77
78
  limit?: number;
79
+ /** Resume after this row: the position the previous page ended on. */
80
+ after?: KeysetPosition;
78
81
  }
79
82
  /**
80
83
  * Validate + normalise the steps body. Returns the trimmed step strings
package/dist/processes.js CHANGED
@@ -32,11 +32,12 @@
32
32
  */
33
33
  import { BadRequestError, ConflictError, NotFoundError } from './api-errors.js';
34
34
  import { openHippoDb, closeHippoDb } from './db.js';
35
- import { writeEntry } from './store.js';
35
+ import { writeEntry } from './store/entry-writes.js';
36
36
  import { assertTenantId } from './tenant.js';
37
37
  import { createMemory, Layer } from './memory.js';
38
38
  import { appendAuditEvent } from './audit.js';
39
39
  import { objectHalfLifeDays } from './half-life-migration.js';
40
+ import { keysetAfter } from './keyset.js';
40
41
  export const VALID_PROCESS_STATES = new Set([
41
42
  'active',
42
43
  'superseded',
@@ -91,6 +92,7 @@ function parseSteps(raw) {
91
92
  return [];
92
93
  }
93
94
  catch {
95
+ // Legacy garbage reads back as no steps, per the docblock.
94
96
  return [];
95
97
  }
96
98
  }
@@ -314,6 +316,7 @@ export function loadProcessById(hippoRoot, tenantId, id) {
314
316
  export function loadProcesses(hippoRoot, tenantId, opts = {}) {
315
317
  assertTenantId('loadProcesses', tenantId);
316
318
  const limit = opts.limit ?? 100;
319
+ const after = keysetAfter('created_at', 'id', opts.after);
317
320
  const db = openHippoDb(hippoRoot);
318
321
  try {
319
322
  let rows;
@@ -325,20 +328,20 @@ export function loadProcesses(hippoRoot, tenantId, opts = {}) {
325
328
  // 1:1 (see PROCESS_COLS above).
326
329
  rows = db.prepare(`
327
330
  SELECT ${PROCESS_COLS} FROM processes
328
- WHERE tenant_id = ? AND status = ?
331
+ WHERE tenant_id = ? AND status = ?${after.sql}
329
332
  ORDER BY created_at DESC, id DESC
330
333
  LIMIT ?
331
- `).all(tenantId, opts.status, limit);
334
+ `).all(tenantId, opts.status, ...after.params, limit);
332
335
  }
333
336
  else {
334
337
  // SAFETY: SELECT ${PROCESS_COLS} enumerates every ProcessRow field
335
338
  // 1:1 (see PROCESS_COLS above).
336
339
  rows = db.prepare(`
337
340
  SELECT ${PROCESS_COLS} FROM processes
338
- WHERE tenant_id = ?
341
+ WHERE tenant_id = ?${after.sql}
339
342
  ORDER BY created_at DESC, id DESC
340
343
  LIMIT ?
341
- `).all(tenantId, limit);
344
+ `).all(tenantId, ...after.params, limit);
342
345
  }
343
346
  return rows.map(rowToProcess);
344
347
  }
@@ -21,6 +21,7 @@
21
21
  * Lifecycle: active -> superseded (a newer version replaces it) or active ->
22
22
  * closed (retired).
23
23
  */
24
+ import { type KeysetPosition } from './keyset.js';
24
25
  export type BriefStatus = 'active' | 'superseded' | 'closed';
25
26
  export declare const VALID_BRIEF_STATES: ReadonlySet<BriefStatus>;
26
27
  /** Field caps (untrusted at the HTTP/SDK boundary). summary is a body, so a larger
@@ -72,6 +73,8 @@ export interface ListProjectBriefsOpts {
72
73
  /** Filter to a single repo. */
73
74
  repo?: string;
74
75
  limit?: number;
76
+ /** Resume after this row: the position the previous page ended on. */
77
+ after?: KeysetPosition;
75
78
  }
76
79
  /**
77
80
  * Create a project_brief (or a new version that supersedes an existing one). Writes
@@ -23,13 +23,14 @@
23
23
  */
24
24
  import { BadRequestError, ConflictError, NotFoundError } from './api-errors.js';
25
25
  import { openHippoDb, closeHippoDb } from './db.js';
26
- import { writeEntry } from './store.js';
26
+ import { writeEntry } from './store/entry-writes.js';
27
27
  import { assertTenantId } from './tenant.js';
28
28
  import { RECALL_DEFAULT_DENY_SCOPES } from './recall-scope.js';
29
- import { markGraphDirty, removeGraphEntitiesForObject } from './graph.js';
29
+ import { markGraphDirty, removeGraphEntitiesForObject } from './graph/write.js';
30
30
  import { createMemory, Layer } from './memory.js';
31
31
  import { appendAuditEvent } from './audit.js';
32
32
  import { objectHalfLifeDays } from './half-life-migration.js';
33
+ import { keysetAfter } from './keyset.js';
33
34
  export const VALID_BRIEF_STATES = new Set([
34
35
  'active',
35
36
  'superseded',
@@ -298,6 +299,7 @@ export function loadProjectBriefById(hippoRoot, tenantId, id) {
298
299
  export function loadProjectBriefs(hippoRoot, tenantId, opts = {}) {
299
300
  assertTenantId('loadProjectBriefs', tenantId);
300
301
  const limit = opts.limit ?? 100;
302
+ const after = keysetAfter('created_at', 'id', opts.after);
301
303
  if (opts.status && !VALID_BRIEF_STATES.has(opts.status)) {
302
304
  throw new BadRequestError(`loadProjectBriefs: status must be one of ${Array.from(VALID_BRIEF_STATES).join('|')}; got ${opts.status}`);
303
305
  }
@@ -313,13 +315,13 @@ export function loadProjectBriefs(hippoRoot, tenantId, opts = {}) {
313
315
  clauses.push('repo = ?');
314
316
  params.push(opts.repo);
315
317
  }
316
- params.push(limit);
318
+ params.push(...after.params, limit);
317
319
  // SAFETY: SELECT ${BRIEF_COLS} projects exactly the ProjectBriefRow columns
318
320
  // regardless of the dynamic WHERE clause built above; .all() returns rows
319
321
  // in that shape.
320
322
  const rows = db.prepare(`
321
323
  SELECT ${BRIEF_COLS} FROM project_briefs
322
- WHERE ${clauses.join(' AND ')}
324
+ WHERE ${clauses.join(' AND ')}${after.sql}
323
325
  ORDER BY created_at DESC, id DESC
324
326
  LIMIT ?
325
327
  `).all(...params);
@@ -356,7 +358,7 @@ export function loadActiveBriefForRepo(hippoRoot, tenantId, repo) {
356
358
  // ---------------------------------------------------------------------------
357
359
  // Refresh assembler (the distinguishing deliverable)
358
360
  // ---------------------------------------------------------------------------
359
- /** Escape LIKE wildcards in operator-supplied text (mirror of store.ts:782). */
361
+ /** Escape LIKE wildcards in operator-supplied text (mirror of store/search-rows.ts). */
360
362
  function escapeLike(term) {
361
363
  return term.replace(/[%_\\]/g, '\\$&');
362
364
  }
@@ -7,7 +7,7 @@
7
7
  * directory is the project root; if none exists, the nearest ancestor
8
8
  * containing `.git` (directory or worktree file).
9
9
  * - The user home directory is NEVER a project, even though it contains the
10
- * global store at `~/.hippo`. Reaching home ends the walk.
10
+ * global store at `~/.hippo`. Reaching home or the temp root (inside home on Windows) ends the walk.
11
11
  * - A directory with no marker anywhere up the walk is NOT a project: it
12
12
  * resolves to the user-global identity (empty name), so memories written
13
13
  * there stay injectable everywhere (matches pre-isolation behavior).
@@ -1,6 +1,8 @@
1
+ import { envHippoHome, envXdgDataHome } from './env.js';
1
2
  import * as fs from 'fs';
2
3
  import * as os from 'os';
3
4
  import * as path from 'path';
5
+ import { log } from './log.js';
4
6
  const MAX_WALK_DEPTH = 64;
5
7
  const identityCache = new Map();
6
8
  /** Clear the per-process identity cache (test seam). */
@@ -15,7 +17,8 @@ export function realpathOrResolve(p) {
15
17
  try {
16
18
  return fs.realpathSync.native(p);
17
19
  }
18
- catch {
20
+ catch (err) {
21
+ log.debug(`project identity: realpath fell back to resolve for ${p}: ${err instanceof Error ? err.message : String(err)}`);
19
22
  return path.resolve(p);
20
23
  }
21
24
  }
@@ -43,7 +46,8 @@ function isDirectoryAt(p) {
43
46
  try {
44
47
  return fs.statSync(p).isDirectory();
45
48
  }
46
- catch {
49
+ catch (err) {
50
+ log.debug(`project identity: no marker at ${p}: ${err instanceof Error ? err.message : String(err)}`);
47
51
  return false;
48
52
  }
49
53
  }
@@ -60,9 +64,11 @@ export function resolveProjectIdentity(cwd, opts) {
60
64
  return cached;
61
65
  }
62
66
  const home = realpathOrResolve(opts?.homeDir ?? os.homedir());
63
- const stopDir = opts?.stopDir ? realpathOrResolve(opts.stopDir) : null;
67
+ const stops = [realpathOrResolve(os.tmpdir())];
68
+ if (opts?.stopDir)
69
+ stops.push(realpathOrResolve(opts.stopDir));
64
70
  const start = realpathOrResolve(startInput);
65
- const { hippoRoot, gitRoot, reachedHome } = walkProjectMarkers(start, home, stopDir === null ? [] : [stopDir]);
71
+ const { hippoRoot, gitRoot, reachedHome } = walkProjectMarkers(start, home, stops);
66
72
  let identity;
67
73
  const root = hippoRoot ?? gitRoot;
68
74
  if (root !== null) {
@@ -165,10 +171,10 @@ export function classifyOriginProject(origin, currentName) {
165
171
  * shared.getGlobalRoot delegates to this.
166
172
  */
167
173
  export function resolveGlobalRootDir() {
168
- const hippoHome = process.env.HIPPO_HOME?.trim();
174
+ const hippoHome = envHippoHome();
169
175
  if (hippoHome)
170
176
  return hippoHome;
171
- const xdgData = process.env.XDG_DATA_HOME?.trim();
177
+ const xdgData = envXdgDataHome();
172
178
  if (xdgData)
173
179
  return path.join(xdgData, 'hippo');
174
180
  return path.join(os.homedir(), '.hippo');
@@ -6,7 +6,9 @@ import { AGENT_MEMORY_SOURCE_PREFIX, AGENT_MEMORY_TOOLS } from './agent-memories
6
6
  import { appendAuditEvent } from './audit.js';
7
7
  import { insertDormantRow, listDormantSnapshots, replaceDormantEntry } from './dormant.js';
8
8
  import { calculateStrength } from './memory.js';
9
- import { deleteEntryRowInTx, removeEntryMirrors, selectAllEntries, writeEntryMirrors } from './store.js';
9
+ import { removeEntryMirrors } from './store/mirrors.js';
10
+ import { deleteEntryRowInTx, writeEntryMirrors } from './store/entry-writes.js';
11
+ import { selectAllEntries } from './store/entry-reads.js';
10
12
  const ACTOR = 'cli';
11
13
  function isImport(entry) {
12
14
  return entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX);
@@ -1,5 +1,6 @@
1
1
  /** Quarantine tier (CD5, AT3): pending/approved/rejected record for a memory `remember` flagged as untrusted. */
2
2
  import type { DatabaseSyncLike } from './db.js';
3
+ import { type KeysetPosition } from './keyset.js';
3
4
  export declare const QUARANTINE_SCOPE_PREFIX = "quarantine:private:";
4
5
  /** Scope a quarantined memory is stored under; matches PRIVATE_SCOPE_RE so every default-deny site hides it. */
5
6
  export declare function quarantineScopeFor(original: string | null): string;
@@ -25,7 +26,7 @@ export interface RecordQuarantineOpts {
25
26
  /** Insert the quarantine row + its audit event; caller runs this inside the memory's own write transaction. */
26
27
  export declare function recordQuarantine(db: DatabaseSyncLike, opts: RecordQuarantineOpts): void;
27
28
  export declare function getQuarantineRow(db: DatabaseSyncLike, tenantId: string, memoryId: string): QuarantineRow | null;
28
- export declare function listQuarantineRows(db: DatabaseSyncLike, tenantId: string, status?: QuarantineStatus | 'all', limit?: number): QuarantineRow[];
29
+ export declare function listQuarantineRows(db: DatabaseSyncLike, tenantId: string, status?: QuarantineStatus | 'all', limit?: number, afterRow?: KeysetPosition): QuarantineRow[];
29
30
  export declare function approveQuarantineRow(db: DatabaseSyncLike, tenantId: string, memoryId: string, decidedBy: string): void;
30
31
  export declare function rejectQuarantineRow(db: DatabaseSyncLike, tenantId: string, memoryId: string, decidedBy: string): void;
31
32
  //# sourceMappingURL=quarantine.d.ts.map