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
@@ -1,620 +0,0 @@
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.ts:1196). The
18
- * afterWrite hook (store.ts:1199-1201) 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.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 { detectForwardClaim } from './forward-claim-detector.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
- const result = db.prepare(`
97
- INSERT INTO predictions(
98
- memory_id, tenant_id, class_tag, claim_text,
99
- estimate_value, estimate_unit, target_date,
100
- actual_value, closure_state, closed_at, closure_note, created_at
101
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'open', NULL, NULL, ?)
102
- `).run(memoryId, tenantId, opts.classTag, opts.claimText, opts.estimateValue ?? null, opts.estimateUnit ?? null, opts.targetDate ?? null, null, // actual_value — null until close
103
- now);
104
- const predictionId = Number(result.lastInsertRowid ?? 0);
105
- // SAFETY: row's shape matches the columns named in the SELECT above.
106
- const row = db.prepare(`
107
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
108
- estimate_value, estimate_unit, target_date,
109
- actual_value, closure_state, closed_at, closure_note, created_at
110
- FROM predictions WHERE id = ?
111
- `).get(predictionId);
112
- if (!row) {
113
- throw new Error('Failed to reload saved prediction row');
114
- }
115
- savedRow = row;
116
- // GDPR-light audit metadata: prediction_id + class_tag + flags only.
117
- // No claim_text in metadata; the predictions table holds it canonically.
118
- appendAuditEvent(db, {
119
- tenantId,
120
- actor,
121
- op: 'predict_create',
122
- targetId: String(predictionId),
123
- metadata: {
124
- prediction_id: predictionId,
125
- class_tag: opts.classTag,
126
- has_estimate: opts.estimateValue !== undefined && opts.estimateValue !== null,
127
- target_date: opts.targetDate ?? null,
128
- },
129
- });
130
- },
131
- });
132
- if (!savedRow) {
133
- // Cannot reach here without the afterWrite throwing first; defensive.
134
- throw new Error('savePrediction: afterWrite did not populate the row');
135
- }
136
- return rowToPrediction(savedRow);
137
- }
138
- /**
139
- * Close an existing open prediction. Updates the predictions row only;
140
- * the memory mirror is NOT mutated in v1 (predictions table is canonical).
141
- * J3 computes accuracy (clean vs regressed) from (estimateValue,
142
- * actualValue) at query time.
143
- */
144
- export function closePrediction(hippoRoot, tenantId, id, opts, actor = 'cli') {
145
- assertTenantId('closePrediction', tenantId);
146
- if (!VALID_CLOSURE_STATES.has(opts.closureState)) {
147
- throw new BadRequestError(`closePrediction: closureState must be one of ${Array.from(VALID_CLOSURE_STATES).join('|')}; got ${opts.closureState}`);
148
- }
149
- const now = new Date().toISOString();
150
- const db = openHippoDb(hippoRoot);
151
- try {
152
- db.exec('BEGIN IMMEDIATE');
153
- try {
154
- // Codex review finding 2026-05-26: WHERE clause requires
155
- // closure_state='open' so duplicate close requests / retries against
156
- // an already-closed prediction return a clear error instead of
157
- // silently overwriting actual_value + emitting a duplicate
158
- // predict_close audit row. Zero changed rows → caller decides
159
- // whether it's a "not found" or "already closed" case based on the
160
- // load-then-close pattern.
161
- const updateResult = db.prepare(`
162
- UPDATE predictions
163
- SET actual_value = ?, closure_state = ?, closed_at = ?, closure_note = ?
164
- WHERE id = ? AND tenant_id = ? AND closure_state = 'open'
165
- `).run(opts.actualValue ?? null, opts.closureState, now, opts.closureNote ?? null, id, tenantId);
166
- if (updateResult.changes === 0) {
167
- // Distinguish "not found" from "already closed" so callers (CLI, HTTP)
168
- // can surface the right error to the user.
169
- // SAFETY: row shape matches the single `closure_state` column named
170
- // in the SELECT above.
171
- const existing = db.prepare(`
172
- SELECT closure_state FROM predictions WHERE id = ? AND tenant_id = ?
173
- `).get(id, tenantId);
174
- if (!existing) {
175
- throw new NotFoundError(`closePrediction: prediction ${id} not found for tenant ${tenantId}`);
176
- }
177
- throw new BadRequestError(`closePrediction: prediction ${id} is already closed (state='${existing.closure_state}'); ` +
178
- `cannot re-close. Open predictions only.`);
179
- }
180
- // SAFETY: row's shape matches the columns named in the SELECT above.
181
- const row = db.prepare(`
182
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
183
- estimate_value, estimate_unit, target_date,
184
- actual_value, closure_state, closed_at, closure_note, created_at
185
- FROM predictions WHERE id = ? AND tenant_id = ?
186
- `).get(id, tenantId);
187
- if (!row) {
188
- throw new NotFoundError(`closePrediction: prediction ${id} not found after UPDATE`);
189
- }
190
- appendAuditEvent(db, {
191
- tenantId,
192
- actor,
193
- op: 'predict_close',
194
- targetId: String(id),
195
- metadata: {
196
- prediction_id: id,
197
- closure_state: opts.closureState,
198
- has_actual: opts.actualValue !== undefined && opts.actualValue !== null,
199
- },
200
- });
201
- db.exec('COMMIT');
202
- return rowToPrediction(row);
203
- }
204
- catch (e) {
205
- try {
206
- db.exec('ROLLBACK');
207
- }
208
- catch {
209
- // Ignore rollback failures — the throw below is what matters.
210
- }
211
- throw e;
212
- }
213
- }
214
- finally {
215
- closeHippoDb(db);
216
- }
217
- }
218
- export function loadPredictionById(hippoRoot, tenantId, id) {
219
- assertTenantId('loadPredictionById', tenantId);
220
- const db = openHippoDb(hippoRoot);
221
- try {
222
- // SAFETY: row's shape matches the columns named in the SELECT above.
223
- const row = db.prepare(`
224
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
225
- estimate_value, estimate_unit, target_date,
226
- actual_value, closure_state, closed_at, closure_note, created_at
227
- FROM predictions WHERE id = ? AND tenant_id = ?
228
- `).get(id, tenantId);
229
- return row ? rowToPrediction(row) : null;
230
- }
231
- finally {
232
- closeHippoDb(db);
233
- }
234
- }
235
- export function loadPredictionsByClass(hippoRoot, tenantId, classTag, opts = {}) {
236
- assertTenantId('loadPredictionsByClass', tenantId);
237
- const limit = opts.limit ?? 100;
238
- const db = openHippoDb(hippoRoot);
239
- try {
240
- let rows;
241
- if (opts.closureState) {
242
- if (!VALID_CLOSURE_STATES.has(opts.closureState)) {
243
- throw new BadRequestError(`loadPredictionsByClass: closureState must be one of ${Array.from(VALID_CLOSURE_STATES).join('|')}; got ${opts.closureState}`);
244
- }
245
- // SAFETY: rows' shape matches the columns named in the SELECT above.
246
- rows = db.prepare(`
247
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
248
- estimate_value, estimate_unit, target_date,
249
- actual_value, closure_state, closed_at, closure_note, created_at
250
- FROM predictions
251
- WHERE tenant_id = ? AND class_tag = ? AND closure_state = ?
252
- ORDER BY created_at DESC, id DESC
253
- LIMIT ?
254
- `).all(tenantId, classTag, opts.closureState, limit);
255
- }
256
- else {
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 = ?
264
- ORDER BY created_at DESC, id DESC
265
- LIMIT ?
266
- `).all(tenantId, classTag, limit);
267
- }
268
- return rows.map(rowToPrediction);
269
- }
270
- finally {
271
- closeHippoDb(db);
272
- }
273
- }
274
- /**
275
- * Compute base-rate stats for closed predictions in a class. Used by J3
276
- * reference-class / planning-fallacy detector. Direct application of
277
- * Lovallo-Kahneman (2003) inside-vs-outside view.
278
- *
279
- * Filter: closure_state='closed' AND estimate_value IS NOT NULL AND
280
- * actual_value IS NOT NULL. Excludes closed-unknown (no actual to
281
- * compare against) and open (not yet resolved).
282
- *
283
- * Audit-emit is BUILT IN here (single source of truth, no caller-site
284
- * drift risk). Plan-eng-critic round 1 HIGH recommendation: emit inside
285
- * helper, not at 3 call sites.
286
- */
287
- export function computePredictionBaserate(hippoRoot, tenantId, classTag, actor = 'cli',
288
- /** v0.32 / J3.2 — when false, skip the predict_baserate audit emit. The
289
- * J3.2 orchestrator (computePlanningFallacyOutput, below) calls this with
290
- * emitAudit=false and emits its own `recall_autodebias_hint` audit row
291
- * instead, so the predict_baserate channel stays scoped to deliberate
292
- * CLI / HTTP / MCP predict-baserate calls and does NOT pollute on every
293
- * recall containing a forward-claim phrase. Default true preserves the
294
- * v1.13.0 J3 audit semantics for the 3 direct callers (cmdPredict
295
- * baserate, /v1/predictions/stats route, hippo_predict_baserate MCP
296
- * handler) — none of them pass this argument. */
297
- emitAudit = true) {
298
- assertTenantId('computePredictionBaserate', tenantId);
299
- if (!classTag)
300
- throw new BadRequestError('computePredictionBaserate: classTag is required');
301
- const db = openHippoDb(hippoRoot);
302
- try {
303
- // SAFETY: rows' shape matches the two columns named in the SELECT above.
304
- const rows = db.prepare(`
305
- SELECT estimate_value, actual_value
306
- FROM predictions
307
- WHERE tenant_id = ?
308
- AND class_tag = ?
309
- AND closure_state = 'closed'
310
- AND estimate_value IS NOT NULL
311
- AND actual_value IS NOT NULL
312
- `).all(tenantId, classTag);
313
- const nClosed = rows.length;
314
- if (nClosed === 0) {
315
- // Audit zero-result reads too — agents probing empty classes is
316
- // a signal worth recording. Skipped when emitAudit=false (J3.2
317
- // orchestrator path; its own recall_autodebias_hint audit fires
318
- // only when nClosed > 0 anyway, so no signal is lost).
319
- if (emitAudit) {
320
- appendAuditEvent(db, {
321
- tenantId,
322
- actor,
323
- op: 'predict_baserate',
324
- targetId: classTag,
325
- metadata: { class_tag: classTag, n_closed: 0 },
326
- });
327
- }
328
- return {
329
- classTag,
330
- nClosed: 0,
331
- nRatioEligible: 0,
332
- meanEstimate: null,
333
- meanActual: null,
334
- meanRatio: null,
335
- p50Ratio: null,
336
- mae: null,
337
- summary: '',
338
- };
339
- }
340
- const ratioEligible = rows.filter((r) => r.estimate_value > 0);
341
- const nRatioEligible = ratioEligible.length;
342
- const meanEstimate = rows.reduce((s, r) => s + r.estimate_value, 0) / nClosed;
343
- const meanActual = rows.reduce((s, r) => s + r.actual_value, 0) / nClosed;
344
- const mae = rows.reduce((s, r) => s + Math.abs(r.actual_value - r.estimate_value), 0) / nClosed;
345
- let meanRatio = null;
346
- let p50Ratio = null;
347
- if (nRatioEligible > 0) {
348
- const ratios = ratioEligible.map((r) => r.actual_value / r.estimate_value);
349
- meanRatio = ratios.reduce((s, x) => s + x, 0) / nRatioEligible;
350
- const sorted = ratios.slice().sort((a, b) => a - b);
351
- p50Ratio = nRatioEligible % 2 === 1
352
- ? sorted[(nRatioEligible - 1) / 2]
353
- : (sorted[nRatioEligible / 2 - 1] + sorted[nRatioEligible / 2]) / 2;
354
- }
355
- const ratioPart = meanRatio !== null
356
- ? `averaged ${meanRatio.toFixed(2)}x actual`
357
- : 'no ratio-eligible rows (all estimates were 0)';
358
- const summary = `Last ${nClosed} estimate${nClosed === 1 ? '' : 's'} in class ${classTag} ${ratioPart} (MAE ${mae.toFixed(2)}).`;
359
- if (emitAudit) {
360
- appendAuditEvent(db, {
361
- tenantId,
362
- actor,
363
- op: 'predict_baserate',
364
- targetId: classTag,
365
- metadata: { class_tag: classTag, n_closed: nClosed },
366
- });
367
- }
368
- return {
369
- classTag,
370
- nClosed,
371
- nRatioEligible,
372
- meanEstimate,
373
- meanActual,
374
- meanRatio,
375
- p50Ratio,
376
- mae,
377
- summary,
378
- };
379
- }
380
- finally {
381
- closeHippoDb(db);
382
- }
383
- }
384
- export function loadOpenPredictions(hippoRoot, tenantId, opts = {}) {
385
- assertTenantId('loadOpenPredictions', tenantId);
386
- const limit = opts.limit ?? 100;
387
- const db = openHippoDb(hippoRoot);
388
- try {
389
- let rows;
390
- if (opts.classTag) {
391
- // SAFETY: rows' shape matches the columns named in the SELECT above.
392
- rows = db.prepare(`
393
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
394
- estimate_value, estimate_unit, target_date,
395
- actual_value, closure_state, closed_at, closure_note, created_at
396
- FROM predictions
397
- WHERE tenant_id = ? AND class_tag = ? AND closure_state = 'open'
398
- ORDER BY created_at DESC, id DESC
399
- LIMIT ?
400
- `).all(tenantId, opts.classTag, limit);
401
- }
402
- else {
403
- // SAFETY: rows' shape matches the columns named in the SELECT above.
404
- rows = db.prepare(`
405
- SELECT id, memory_id, tenant_id, class_tag, claim_text,
406
- estimate_value, estimate_unit, target_date,
407
- actual_value, closure_state, closed_at, closure_note, created_at
408
- FROM predictions
409
- WHERE tenant_id = ? AND closure_state = 'open'
410
- ORDER BY created_at DESC, id DESC
411
- LIMIT ?
412
- `).all(tenantId, limit);
413
- }
414
- return rows.map(rowToPrediction);
415
- }
416
- finally {
417
- closeHippoDb(db);
418
- }
419
- }
420
- /**
421
- * Resolve a query-token set to a unique best-matching class_tag for the
422
- * tenant. Scores by lower-cased token overlap; requires best score ≥ 1
423
- * AND strictly greater than the 2nd-best score.
424
- *
425
- * Indexed via idx_predictions_tenant_class (db.ts:1015) → O(log n) seek
426
- * plus a small DISTINCT scan over the per-tenant class-tag set.
427
- *
428
- * Scope behaviour (v1 design choice, independent-review-critic round 1
429
- * MED): class_tag selection is TENANT-GLOBAL, NOT scope-filtered against
430
- * the recall's opts.scope. The class_tag is an aggregator label across
431
- * historical predictions in the class, not a per-memory scope-bound
432
- * property. A no-scope recall CAN surface a class_tag from a privately-
433
- * scoped prediction's class in PlanningFallacyHint.classTag — by design,
434
- * because base-rate reasoning needs the full historical sample.
435
- * Implications:
436
- * - The hint payload itself carries no memory content (only the aggregate
437
- * summary string + numeric stats), so memory bodies do not leak.
438
- * - The class_tag NAME is the side-channel. If sensitive labels are a
439
- * concern, callers should either use opaque class names (e.g. hashes
440
- * or numeric tokens) or set HIPPO_AUTODEBIAS=off.
441
- * - tests/api-recall-autodebias.test.ts locks this with an explicit
442
- * test asserting that scope-set predictions surface via no-scope
443
- * recalls (so future "fix" attempts that scope-filter trip CI).
444
- */
445
- function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
446
- if (queryTokens.length === 0)
447
- return { classTag: null, tiebreak: false };
448
- const db = openHippoDb(hippoRoot);
449
- try {
450
- // SAFETY: rows' shape matches the single `class_tag` column named in the SELECT above.
451
- const rows = db.prepare(`SELECT DISTINCT class_tag FROM predictions WHERE tenant_id = ?`).all(tenantId);
452
- const querySet = new Set(queryTokens);
453
- let bestScore = 0;
454
- let bestClass = null;
455
- let secondBest = 0;
456
- for (const { class_tag } of rows) {
457
- const classTokens = class_tag
458
- .toLowerCase()
459
- .split(/[-_\s]+/)
460
- .filter((t) => t.length >= 3);
461
- let score = 0;
462
- for (const t of classTokens)
463
- if (querySet.has(t))
464
- score++;
465
- if (score > bestScore) {
466
- secondBest = bestScore;
467
- bestScore = score;
468
- bestClass = class_tag;
469
- }
470
- else if (score === bestScore && score > 0) {
471
- // Tie at current best — bump secondBest. Do NOT update bestClass
472
- // (alphabetical tiebreak would pick wrong class on ambiguous query
473
- // like "migration will take 3 days" between migration-effort vs
474
- // migration-risk; silent on tie instead).
475
- secondBest = score;
476
- }
477
- else if (score > secondBest) {
478
- secondBest = score;
479
- }
480
- }
481
- if (bestScore < 1)
482
- return { classTag: null, tiebreak: false };
483
- if (bestScore === secondBest)
484
- return { classTag: null, tiebreak: true };
485
- return { classTag: bestClass, tiebreak: false };
486
- }
487
- finally {
488
- closeHippoDb(db);
489
- }
490
- }
491
- /**
492
- * J3.2 orchestrator.
493
- *
494
- * Composes the forward-claim detector + class resolver + baserate compute,
495
- * with telemetry-grade audit emission at every decision point (success,
496
- * no-class-match, tiebreak).
497
- *
498
- * Returns `{}` (neither hint nor watching) on:
499
- * - mode === 'off' (env-disabled; pays only the env read, skips regex)
500
- * - empty queryText
501
- * - no forward-claim regex match
502
- * - resolved class has nClosed=0 (no historical data yet; silent)
503
- *
504
- * Returns `{ watching: ... }` on (v1.13.4 NEW — was silent null pre-1.13.4):
505
- * - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
506
- * - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
507
- *
508
- * Returns `{ hint: ... }` on success: calls computePredictionBaserate(...,
509
- * emitAudit=false) so the predict_baserate audit channel stays scoped to
510
- * deliberate predict-baserate calls (the orchestrator's own recall_autodebias_hint
511
- * audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
512
- * then emits recall_autodebias_hint audit + returns the hint.
513
- *
514
- * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
515
- * on full match+resolve+baserate path. Well under 50ms target.
516
- */
517
- export function computePlanningFallacyOutput(hippoRoot, tenantId, queryText, opts = {}) {
518
- // Env read FIRST so AUTODEBIAS=off pays zero regex cost. Per-call read
519
- // (rather than module-load cache) is deliberate: tests env-toggle this
520
- // via process.env mutation without module reload.
521
- const mode = opts.mode ?? (process.env.HIPPO_AUTODEBIAS === 'off' ? 'off' : 'regex');
522
- if (mode === 'off')
523
- return {};
524
- if (!queryText)
525
- return {};
526
- const match = detectForwardClaim(queryText);
527
- if (!match)
528
- return {};
529
- const actor = opts.actor ?? 'recall';
530
- const resolution = resolveClassFromTokens(hippoRoot, tenantId, match.classQueryTokens);
531
- if (resolution.tiebreak) {
532
- // Telemetry: forward-claim detected, ≥2 classes tied at best overlap.
533
- // v1.13.4: now ALSO returns a watching variant so the caller surface
534
- // can render a "watching but no baserate (tiebreak)" line. Audit emission
535
- // unchanged (the audit channel is the telemetry-grade source of truth).
536
- const db = openHippoDb(hippoRoot);
537
- try {
538
- appendAuditEvent(db, {
539
- tenantId,
540
- actor,
541
- op: 'recall_autodebias_hint_tiebreak',
542
- targetId: match.phrase.slice(0, 100),
543
- metadata: { detected_phrase: match.phrase, token_count: match.classQueryTokens.length },
544
- });
545
- }
546
- finally {
547
- closeHippoDb(db);
548
- }
549
- return {
550
- watching: {
551
- detectedPhrase: match.phrase,
552
- reason: 'tiebreak',
553
- suggestion: 'Multiple prediction classes tied on this query. Refine the query or rename overlapping classes to break the tie.',
554
- },
555
- };
556
- }
557
- if (!resolution.classTag) {
558
- // Telemetry: forward-claim detected, no class scored ≥ 1.
559
- // This is the channel that drives the embedding-fallback decision
560
- // for J3.3 — high volume here = regex+token-overlap is missing
561
- // legitimate forward-claims that have NO obvious class signal.
562
- // v1.13.4: now ALSO returns a watching variant so the caller surface
563
- // can render a "watching but no baserate (no class match)" line.
564
- const db = openHippoDb(hippoRoot);
565
- try {
566
- appendAuditEvent(db, {
567
- tenantId,
568
- actor,
569
- op: 'recall_autodebias_hint_no_class_match',
570
- targetId: match.phrase.slice(0, 100),
571
- metadata: { detected_phrase: match.phrase, token_count: match.classQueryTokens.length },
572
- });
573
- }
574
- finally {
575
- closeHippoDb(db);
576
- }
577
- return {
578
- watching: {
579
- detectedPhrase: match.phrase,
580
- reason: 'no_class_match',
581
- suggestion: 'No matching prediction class for this forward-claim. Tag your prediction with `hippo predict --class <name>` to start tracking this class.',
582
- },
583
- };
584
- }
585
- // emitAudit=false: avoid double-write to predict_baserate channel.
586
- // The recall_autodebias_hint audit below carries n_closed + mean_ratio.
587
- const baserate = computePredictionBaserate(hippoRoot, tenantId, resolution.classTag, actor,
588
- /*emitAudit=*/ false);
589
- if (baserate.nClosed === 0)
590
- return {}; // Silent — wait for closed data.
591
- const db = openHippoDb(hippoRoot);
592
- try {
593
- appendAuditEvent(db, {
594
- tenantId,
595
- actor,
596
- op: 'recall_autodebias_hint',
597
- targetId: resolution.classTag,
598
- metadata: {
599
- class_tag: resolution.classTag,
600
- detected_phrase: match.phrase,
601
- n_closed: baserate.nClosed,
602
- mean_ratio: baserate.meanRatio,
603
- },
604
- });
605
- }
606
- finally {
607
- closeHippoDb(db);
608
- }
609
- return {
610
- hint: {
611
- classTag: resolution.classTag,
612
- baserateSummary: baserate.summary,
613
- source: 'j3.2-auto',
614
- detectedPhrase: match.phrase,
615
- nClosed: baserate.nClosed,
616
- meanRatio: baserate.meanRatio,
617
- },
618
- };
619
- }
620
- //# sourceMappingURL=predictions.js.map