hippo-memory 1.60.0 → 1.62.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 (593) hide show
  1. package/README.md +29 -54
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.d.ts +1 -1
  4. package/dist/agent-memories/apply.js +4 -1
  5. package/dist/agent-memories/claude-code.d.ts +3 -1
  6. package/dist/agent-memories/claude-code.js +54 -10
  7. package/dist/agent-memories/codex.js +1 -1
  8. package/dist/agent-memories/gemini.js +1 -1
  9. package/dist/agent-memories/legacy.js +1 -1
  10. package/dist/agent-memories/source.js +1 -1
  11. package/dist/agent-memories/sync.d.ts +3 -3
  12. package/dist/agent-memories/sync.js +22 -9
  13. package/dist/agent-memories/types.d.ts +0 -2
  14. package/dist/ambient-store.d.ts +14 -0
  15. package/dist/ambient-store.js +90 -0
  16. package/dist/ambient.d.ts +23 -0
  17. package/dist/ambient.js +72 -50
  18. package/dist/api/assemble.d.ts +93 -0
  19. package/dist/api/assemble.js +153 -0
  20. package/dist/api/audit.d.ts +17 -0
  21. package/dist/api/audit.js +23 -0
  22. package/dist/api/auth.d.ts +79 -0
  23. package/dist/api/auth.js +178 -0
  24. package/dist/api/context-select.d.ts +49 -0
  25. package/dist/api/context-select.js +344 -0
  26. package/dist/api/context-types.d.ts +105 -0
  27. package/dist/api/context-types.js +3 -0
  28. package/dist/api/context.d.ts +31 -0
  29. package/dist/api/context.js +378 -0
  30. package/dist/api/dormant.d.ts +30 -0
  31. package/dist/api/dormant.js +140 -0
  32. package/dist/api/drill-down.d.ts +84 -0
  33. package/dist/api/drill-down.js +126 -0
  34. package/dist/api/forget.d.ts +57 -0
  35. package/dist/api/forget.js +87 -0
  36. package/dist/api/goals.d.ts +18 -0
  37. package/dist/api/goals.js +33 -0
  38. package/dist/api/learn.d.ts +31 -0
  39. package/dist/api/learn.js +88 -0
  40. package/dist/api/outcome.d.ts +61 -0
  41. package/dist/api/outcome.js +66 -0
  42. package/dist/api/promote.d.ts +54 -0
  43. package/dist/api/promote.js +192 -0
  44. package/dist/api/quarantine.d.ts +24 -0
  45. package/dist/api/quarantine.js +121 -0
  46. package/dist/api/recall-types.d.ts +390 -0
  47. package/dist/api/recall-types.js +3 -0
  48. package/dist/api/recall.d.ts +36 -0
  49. package/dist/api/recall.js +499 -0
  50. package/dist/api/remember.d.ts +35 -0
  51. package/dist/api/remember.js +43 -0
  52. package/dist/api/sleep.d.ts +136 -0
  53. package/dist/api/sleep.js +256 -0
  54. package/dist/api/tokens.d.ts +26 -0
  55. package/dist/api/tokens.js +60 -0
  56. package/dist/api/types.d.ts +56 -0
  57. package/dist/api/types.js +38 -0
  58. package/dist/api.d.ts +20 -1262
  59. package/dist/api.js +25 -2727
  60. package/dist/audit.d.ts +3 -0
  61. package/dist/audit.js +6 -3
  62. package/dist/auth.d.ts +45 -4
  63. package/dist/auth.js +125 -48
  64. package/dist/autolearn.js +2 -2
  65. package/dist/capture/command.d.ts +33 -0
  66. package/dist/capture/command.js +264 -0
  67. package/dist/capture/compact.d.ts +44 -0
  68. package/dist/capture/compact.js +354 -0
  69. package/dist/capture/extract.d.ts +21 -0
  70. package/dist/capture/extract.js +464 -0
  71. package/dist/capture/transcript.d.ts +40 -0
  72. package/dist/capture/transcript.js +193 -0
  73. package/dist/capture-error.js +2 -1
  74. package/dist/churn-git.js +4 -2
  75. package/dist/cli/audit.d.ts +3 -0
  76. package/dist/cli/audit.js +159 -0
  77. package/dist/cli/auth.d.ts +2 -0
  78. package/dist/cli/auth.js +171 -0
  79. package/dist/cli/briefs.d.ts +4 -0
  80. package/dist/cli/briefs.js +453 -0
  81. package/dist/cli/card.d.ts +3 -0
  82. package/dist/cli/card.js +333 -0
  83. package/dist/cli/context.d.ts +15 -0
  84. package/dist/cli/context.js +376 -0
  85. package/dist/cli/continuity.d.ts +6 -0
  86. package/dist/cli/continuity.js +457 -0
  87. package/dist/cli/curate.d.ts +19 -0
  88. package/dist/cli/curate.js +556 -0
  89. package/dist/cli/dag.d.ts +5 -0
  90. package/dist/cli/dag.js +177 -0
  91. package/dist/cli/decisions.d.ts +4 -0
  92. package/dist/cli/decisions.js +528 -0
  93. package/dist/cli/eval.d.ts +5 -0
  94. package/dist/cli/eval.js +213 -0
  95. package/dist/cli/explain.d.ts +4 -0
  96. package/dist/cli/explain.js +156 -0
  97. package/dist/cli/goals.d.ts +2 -0
  98. package/dist/cli/goals.js +196 -0
  99. package/dist/cli/hook-blocks.d.ts +18 -0
  100. package/dist/cli/hook-blocks.js +233 -0
  101. package/dist/cli/init.d.ts +2 -0
  102. package/dist/cli/init.js +305 -0
  103. package/dist/cli/maintenance.d.ts +4 -0
  104. package/dist/cli/maintenance.js +190 -0
  105. package/dist/cli/playbooks.d.ts +4 -0
  106. package/dist/cli/playbooks.js +573 -0
  107. package/dist/cli/projects.js +9 -6
  108. package/dist/cli/recall.d.ts +7 -0
  109. package/dist/cli/recall.js +582 -0
  110. package/dist/cli/remember.d.ts +5 -0
  111. package/dist/cli/remember.js +485 -0
  112. package/dist/cli/serve.d.ts +5 -0
  113. package/dist/cli/serve.js +40 -0
  114. package/dist/cli/session-hooks.d.ts +29 -0
  115. package/dist/cli/session-hooks.js +647 -0
  116. package/dist/cli/setup.d.ts +4 -0
  117. package/dist/cli/setup.js +397 -0
  118. package/dist/cli/shared.d.ts +15 -19
  119. package/dist/cli/shared.js +50 -341
  120. package/dist/cli/slack.d.ts +2 -0
  121. package/dist/cli/slack.js +171 -0
  122. package/dist/cli/status.d.ts +18 -0
  123. package/dist/cli/status.js +409 -0
  124. package/dist/cli/transfer.d.ts +10 -0
  125. package/dist/cli/transfer.js +424 -0
  126. package/dist/cli/usage.d.ts +85 -0
  127. package/dist/cli/usage.js +741 -0
  128. package/dist/cli.d.ts +71 -120
  129. package/dist/cli.js +170 -8469
  130. package/dist/client.js +15 -8
  131. package/dist/compaction-record.d.ts +0 -2
  132. package/dist/compaction-record.js +7 -5
  133. package/dist/connectors/github/backfill.js +94 -87
  134. package/dist/connectors/github/cli-impl.js +4 -3
  135. package/dist/connectors/github/dlq.js +67 -54
  136. package/dist/connectors/github/ingest.js +34 -35
  137. package/dist/connectors/github/tenant-routing.js +3 -2
  138. package/dist/connectors/github/webhook.js +135 -216
  139. package/dist/connectors/slack/dlq.js +49 -61
  140. package/dist/connectors/slack/ingest.js +55 -48
  141. package/dist/connectors/slack/tenant-routing.js +4 -3
  142. package/dist/connectors/slack/webhook.js +72 -74
  143. package/dist/consolidate/conflicts.d.ts +10 -0
  144. package/dist/consolidate/conflicts.js +178 -0
  145. package/dist/consolidate/decay.d.ts +12 -0
  146. package/dist/consolidate/decay.js +145 -0
  147. package/dist/consolidate/llm-passes.d.ts +3 -0
  148. package/dist/consolidate/llm-passes.js +141 -0
  149. package/dist/consolidate/merge.d.ts +7 -0
  150. package/dist/consolidate/merge.js +251 -0
  151. package/dist/consolidate/physics-pass.d.ts +3 -0
  152. package/dist/consolidate/physics-pass.js +60 -0
  153. package/dist/consolidate/run.d.ts +69 -0
  154. package/dist/consolidate/run.js +76 -0
  155. package/dist/consolidate/sleep.d.ts +18 -0
  156. package/dist/consolidate/sleep.js +209 -0
  157. package/dist/consolidate/traces.d.ts +4 -0
  158. package/dist/consolidate/traces.js +178 -0
  159. package/dist/context-auto.js +7 -11
  160. package/dist/context-render.d.ts +1 -1
  161. package/dist/context-render.js +1 -1
  162. package/dist/customer-notes.d.ts +3 -0
  163. package/dist/customer-notes.js +83 -72
  164. package/dist/dag.js +225 -188
  165. package/dist/dashboard-actions.d.ts +20 -0
  166. package/dist/dashboard-actions.js +88 -0
  167. package/dist/dashboard-params.d.ts +45 -0
  168. package/dist/dashboard-params.js +127 -0
  169. package/dist/dashboard-queries.d.ts +15 -0
  170. package/dist/dashboard-queries.js +355 -0
  171. package/dist/dashboard-snapshot.d.ts +138 -0
  172. package/dist/dashboard-snapshot.js +308 -0
  173. package/dist/dashboard-types.d.ts +163 -0
  174. package/dist/dashboard-types.js +3 -0
  175. package/dist/dashboard.d.ts +6 -7
  176. package/dist/dashboard.js +228 -202
  177. package/dist/db/busy.d.ts +5 -0
  178. package/dist/db/busy.js +24 -0
  179. package/dist/db/continuity.d.ts +5 -0
  180. package/dist/db/continuity.js +145 -0
  181. package/dist/db/meta.d.ts +8 -0
  182. package/dist/db/meta.js +35 -0
  183. package/dist/db/migrate.d.ts +9 -0
  184. package/dist/db/migrate.js +138 -0
  185. package/dist/db/migrations/index.d.ts +5 -0
  186. package/dist/db/migrations/index.js +109 -0
  187. package/dist/db/migrations/types.d.ts +14 -0
  188. package/dist/db/migrations/types.js +2 -0
  189. package/dist/db/migrations/v01.d.ts +3 -0
  190. package/dist/db/migrations/v01.js +38 -0
  191. package/dist/db/migrations/v02.d.ts +3 -0
  192. package/dist/db/migrations/v02.js +21 -0
  193. package/dist/db/migrations/v03.d.ts +3 -0
  194. package/dist/db/migrations/v03.js +22 -0
  195. package/dist/db/migrations/v04.d.ts +3 -0
  196. package/dist/db/migrations/v04.js +28 -0
  197. package/dist/db/migrations/v05.d.ts +3 -0
  198. package/dist/db/migrations/v05.js +21 -0
  199. package/dist/db/migrations/v06.d.ts +3 -0
  200. package/dist/db/migrations/v06.js +25 -0
  201. package/dist/db/migrations/v07.d.ts +3 -0
  202. package/dist/db/migrations/v07.js +13 -0
  203. package/dist/db/migrations/v08.d.ts +3 -0
  204. package/dist/db/migrations/v08.js +8 -0
  205. package/dist/db/migrations/v09.d.ts +3 -0
  206. package/dist/db/migrations/v09.js +13 -0
  207. package/dist/db/migrations/v10.d.ts +3 -0
  208. package/dist/db/migrations/v10.js +17 -0
  209. package/dist/db/migrations/v11.d.ts +3 -0
  210. package/dist/db/migrations/v11.js +15 -0
  211. package/dist/db/migrations/v12.d.ts +3 -0
  212. package/dist/db/migrations/v12.js +11 -0
  213. package/dist/db/migrations/v13.d.ts +3 -0
  214. package/dist/db/migrations/v13.js +15 -0
  215. package/dist/db/migrations/v14.d.ts +3 -0
  216. package/dist/db/migrations/v14.js +66 -0
  217. package/dist/db/migrations/v15.d.ts +3 -0
  218. package/dist/db/migrations/v15.js +42 -0
  219. package/dist/db/migrations/v16.d.ts +3 -0
  220. package/dist/db/migrations/v16.js +61 -0
  221. package/dist/db/migrations/v17.d.ts +3 -0
  222. package/dist/db/migrations/v17.js +46 -0
  223. package/dist/db/migrations/v18.d.ts +3 -0
  224. package/dist/db/migrations/v18.js +60 -0
  225. package/dist/db/migrations/v19.d.ts +3 -0
  226. package/dist/db/migrations/v19.js +28 -0
  227. package/dist/db/migrations/v20.d.ts +3 -0
  228. package/dist/db/migrations/v20.js +42 -0
  229. package/dist/db/migrations/v21.d.ts +3 -0
  230. package/dist/db/migrations/v21.js +16 -0
  231. package/dist/db/migrations/v22.d.ts +3 -0
  232. package/dist/db/migrations/v22.js +82 -0
  233. package/dist/db/migrations/v23.d.ts +3 -0
  234. package/dist/db/migrations/v23.js +48 -0
  235. package/dist/db/migrations/v24.d.ts +3 -0
  236. package/dist/db/migrations/v24.js +72 -0
  237. package/dist/db/migrations/v25.d.ts +3 -0
  238. package/dist/db/migrations/v25.js +46 -0
  239. package/dist/db/migrations/v26.d.ts +3 -0
  240. package/dist/db/migrations/v26.js +23 -0
  241. package/dist/db/migrations/v27.d.ts +3 -0
  242. package/dist/db/migrations/v27.js +57 -0
  243. package/dist/db/migrations/v28.d.ts +3 -0
  244. package/dist/db/migrations/v28.js +38 -0
  245. package/dist/db/migrations/v29.d.ts +3 -0
  246. package/dist/db/migrations/v29.js +78 -0
  247. package/dist/db/migrations/v30.d.ts +3 -0
  248. package/dist/db/migrations/v30.js +92 -0
  249. package/dist/db/migrations/v31.d.ts +3 -0
  250. package/dist/db/migrations/v31.js +74 -0
  251. package/dist/db/migrations/v32.d.ts +3 -0
  252. package/dist/db/migrations/v32.js +102 -0
  253. package/dist/db/migrations/v33.d.ts +3 -0
  254. package/dist/db/migrations/v33.js +104 -0
  255. package/dist/db/migrations/v34.d.ts +3 -0
  256. package/dist/db/migrations/v34.js +93 -0
  257. package/dist/db/migrations/v35.d.ts +3 -0
  258. package/dist/db/migrations/v35.js +98 -0
  259. package/dist/db/migrations/v36.d.ts +3 -0
  260. package/dist/db/migrations/v36.js +98 -0
  261. package/dist/db/migrations/v37.d.ts +3 -0
  262. package/dist/db/migrations/v37.js +219 -0
  263. package/dist/db/migrations/v38.d.ts +3 -0
  264. package/dist/db/migrations/v38.js +277 -0
  265. package/dist/db/migrations/v39.d.ts +3 -0
  266. package/dist/db/migrations/v39.js +59 -0
  267. package/dist/db/migrations/v40.d.ts +3 -0
  268. package/dist/db/migrations/v40.js +74 -0
  269. package/dist/db/migrations/v41.d.ts +3 -0
  270. package/dist/db/migrations/v41.js +43 -0
  271. package/dist/db/migrations/v42.d.ts +3 -0
  272. package/dist/db/migrations/v42.js +41 -0
  273. package/dist/db/migrations/v43.d.ts +3 -0
  274. package/dist/db/migrations/v43.js +67 -0
  275. package/dist/db/migrations/v44.d.ts +3 -0
  276. package/dist/db/migrations/v44.js +28 -0
  277. package/dist/db/migrations/v45.d.ts +3 -0
  278. package/dist/db/migrations/v45.js +30 -0
  279. package/dist/db/migrations/v46.d.ts +3 -0
  280. package/dist/db/migrations/v46.js +25 -0
  281. package/dist/db/migrations/v47.d.ts +3 -0
  282. package/dist/db/migrations/v47.js +17 -0
  283. package/dist/db/migrations/v48.d.ts +3 -0
  284. package/dist/db/migrations/v48.js +10 -0
  285. package/dist/db/migrations/v49.d.ts +3 -0
  286. package/dist/db/migrations/v49.js +31 -0
  287. package/dist/db/migrations/v50.d.ts +3 -0
  288. package/dist/db/migrations/v50.js +67 -0
  289. package/dist/db/migrations/v51.d.ts +3 -0
  290. package/dist/db/migrations/v51.js +14 -0
  291. package/dist/db/migrations/v52.d.ts +3 -0
  292. package/dist/db/migrations/v52.js +7 -0
  293. package/dist/db/open.d.ts +23 -0
  294. package/dist/db/open.js +146 -0
  295. package/dist/db/sqlite.d.ts +21 -0
  296. package/dist/db/sqlite.js +8 -0
  297. package/dist/db/tables.d.ts +7 -0
  298. package/dist/db/tables.js +38 -0
  299. package/dist/db.d.ts +6 -46
  300. package/dist/db.js +5 -3049
  301. package/dist/decisions.d.ts +4 -1
  302. package/dist/decisions.js +102 -83
  303. package/dist/dedupe.js +3 -2
  304. package/dist/delivery-recorder.js +4 -1
  305. package/dist/doctor.js +14 -10
  306. package/dist/embedding-provider.d.ts +1 -1
  307. package/dist/embedding-provider.js +4 -3
  308. package/dist/embeddings.d.ts +9 -52
  309. package/dist/embeddings.js +43 -297
  310. package/dist/env.d.ts +75 -0
  311. package/dist/env.js +119 -0
  312. package/dist/eval-suite.js +1 -1
  313. package/dist/eval.js +2 -2
  314. package/dist/extract.js +1 -1
  315. package/dist/gated-write.js +3 -1
  316. package/dist/goals.d.ts +3 -1
  317. package/dist/goals.js +117 -86
  318. package/dist/graph/read.d.ts +73 -0
  319. package/dist/graph/read.js +325 -0
  320. package/dist/graph/rows.d.ts +45 -0
  321. package/dist/graph/rows.js +51 -0
  322. package/dist/graph/types.d.ts +83 -0
  323. package/dist/graph/types.js +11 -0
  324. package/dist/graph/write.d.ts +93 -0
  325. package/dist/{graph.js → graph/write.js} +6 -384
  326. package/dist/graph-extract.js +2 -1
  327. package/dist/graph-recall.d.ts +1 -1
  328. package/dist/graph-recall.js +2 -2
  329. package/dist/graph-stream.js +1 -1
  330. package/dist/graph-view.d.ts +1 -1
  331. package/dist/graph-view.js +1 -1
  332. package/dist/half-life-migration.d.ts +1 -1
  333. package/dist/half-life-migration.js +2 -1
  334. package/dist/hooks/codex-session.d.ts +8 -0
  335. package/dist/hooks/codex-session.js +76 -0
  336. package/dist/hooks/codex-wrapper.d.ts +55 -0
  337. package/dist/hooks/codex-wrapper.js +288 -0
  338. package/dist/hooks/json-hooks.d.ts +63 -0
  339. package/dist/hooks/json-hooks.js +356 -0
  340. package/dist/hooks/opencode.d.ts +50 -0
  341. package/dist/hooks/opencode.js +202 -0
  342. package/dist/hooks/shared.d.ts +54 -0
  343. package/dist/hooks/shared.js +77 -0
  344. package/dist/http-retry.d.ts +2 -0
  345. package/dist/http-retry.js +4 -3
  346. package/dist/http-util.d.ts +3 -0
  347. package/dist/http-util.js +10 -0
  348. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  349. package/dist/importers/core.js +141 -0
  350. package/dist/importers/markdown-parse.d.ts +41 -0
  351. package/dist/importers/markdown-parse.js +132 -0
  352. package/dist/importers/markdown.d.ts +3 -0
  353. package/dist/importers/markdown.js +92 -0
  354. package/dist/importers/sources.d.ts +7 -0
  355. package/dist/importers/sources.js +229 -0
  356. package/dist/importers/vault.d.ts +11 -0
  357. package/dist/importers/vault.js +352 -0
  358. package/dist/incidents.d.ts +3 -0
  359. package/dist/incidents.js +52 -43
  360. package/dist/index.d.ts +25 -6
  361. package/dist/index.js +23 -6
  362. package/dist/invalidation.js +2 -1
  363. package/dist/judgment.js +2 -1
  364. package/dist/keyset.d.ts +13 -0
  365. package/dist/keyset.js +8 -0
  366. package/dist/local-embedding.d.ts +13 -0
  367. package/dist/local-embedding.js +165 -0
  368. package/dist/log.d.ts +7 -0
  369. package/dist/log.js +19 -1
  370. package/dist/mcp/admin-tools.d.ts +8 -0
  371. package/dist/mcp/admin-tools.js +116 -0
  372. package/dist/mcp/format.d.ts +27 -0
  373. package/dist/mcp/format.js +135 -0
  374. package/dist/mcp/memory-tools.d.ts +5 -0
  375. package/dist/mcp/memory-tools.js +83 -0
  376. package/dist/mcp/protocol.d.ts +83 -0
  377. package/dist/mcp/protocol.js +55 -0
  378. package/dist/mcp/recall-tools.d.ts +6 -0
  379. package/dist/mcp/recall-tools.js +320 -0
  380. package/dist/mcp/request.d.ts +10 -0
  381. package/dist/mcp/request.js +163 -0
  382. package/dist/mcp/server.d.ts +4 -75
  383. package/dist/mcp/server.js +7 -1190
  384. package/dist/mcp/session-state.d.ts +11 -0
  385. package/dist/mcp/session-state.js +28 -0
  386. package/dist/mcp/stdio.d.ts +8 -0
  387. package/dist/mcp/stdio.js +79 -0
  388. package/dist/mcp/tools.d.ts +11 -0
  389. package/dist/mcp/tools.js +247 -0
  390. package/dist/memory.d.ts +3 -0
  391. package/dist/memory.js +27 -1
  392. package/dist/multihop.d.ts +1 -1
  393. package/dist/multihop.js +2 -1
  394. package/dist/owner-validation.js +2 -1
  395. package/dist/physics-state.js +10 -7
  396. package/dist/policies.d.ts +3 -0
  397. package/dist/policies.js +93 -74
  398. package/dist/postinstall.js +3 -2
  399. package/dist/predictions/planning-fallacy.d.ts +100 -0
  400. package/dist/predictions/planning-fallacy.js +190 -0
  401. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  402. package/dist/predictions/store.js +434 -0
  403. package/dist/processes.d.ts +3 -0
  404. package/dist/processes.js +94 -76
  405. package/dist/project-briefs.d.ts +3 -0
  406. package/dist/project-briefs.js +142 -113
  407. package/dist/project-identity.js +3 -2
  408. package/dist/project-merge.d.ts +12 -4
  409. package/dist/project-merge.js +132 -45
  410. package/dist/quarantine.d.ts +2 -1
  411. package/dist/quarantine.js +8 -5
  412. package/dist/raw-archive.js +1 -1
  413. package/dist/recall-history.js +3 -2
  414. package/dist/recall-pipeline.d.ts +2 -2
  415. package/dist/recall-pipeline.js +16 -8
  416. package/dist/recall-scope.js +1 -1
  417. package/dist/recall-trace.d.ts +1 -1
  418. package/dist/refine-llm.js +2 -1
  419. package/dist/reject-flow.js +6 -1
  420. package/dist/rerankers/clef.js +6 -5
  421. package/dist/rerankers/jev.d.ts +1 -1
  422. package/dist/rerankers/jev.js +4 -4
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +58 -38
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/scheduler.d.ts +1 -0
  428. package/dist/scheduler.js +26 -4
  429. package/dist/scope.js +4 -3
  430. package/dist/search/as-of.d.ts +10 -0
  431. package/dist/search/as-of.js +22 -0
  432. package/dist/search/bm25-search.d.ts +14 -0
  433. package/dist/search/bm25-search.js +43 -0
  434. package/dist/search/bm25.d.ts +15 -0
  435. package/dist/search/bm25.js +54 -0
  436. package/dist/search/boosts.d.ts +54 -0
  437. package/dist/search/boosts.js +94 -0
  438. package/dist/search/breakdown.d.ts +7 -0
  439. package/dist/search/breakdown.js +20 -0
  440. package/dist/search/explain.d.ts +25 -0
  441. package/dist/search/explain.js +31 -0
  442. package/dist/search/finalize.d.ts +8 -0
  443. package/dist/search/finalize.js +52 -0
  444. package/dist/search/fusion.d.ts +27 -0
  445. package/dist/search/fusion.js +42 -0
  446. package/dist/search/hybrid-score.d.ts +20 -0
  447. package/dist/search/hybrid-score.js +73 -0
  448. package/dist/search/hybrid.d.ts +46 -0
  449. package/dist/search/hybrid.js +64 -0
  450. package/dist/search/physics-search.d.ts +29 -0
  451. package/dist/search/physics-search.js +162 -0
  452. package/dist/search/rerank.d.ts +10 -0
  453. package/dist/search/rerank.js +72 -0
  454. package/dist/search/temporal.d.ts +15 -0
  455. package/dist/search/temporal.js +45 -0
  456. package/dist/search/types.d.ts +91 -0
  457. package/dist/search/types.js +2 -0
  458. package/dist/search/vector.d.ts +30 -0
  459. package/dist/search/vector.js +71 -0
  460. package/dist/secret-detect.d.ts +2 -0
  461. package/dist/secret-detect.js +2 -1
  462. package/dist/server/auth.d.ts +52 -0
  463. package/dist/server/auth.js +221 -0
  464. package/dist/server/client-ip.d.ts +25 -0
  465. package/dist/server/client-ip.js +92 -0
  466. package/dist/server/cursor.d.ts +23 -0
  467. package/dist/server/cursor.js +58 -0
  468. package/dist/server/lifecycle.d.ts +7 -0
  469. package/dist/server/lifecycle.js +29 -0
  470. package/dist/server/mcp-http.d.ts +5 -0
  471. package/dist/server/mcp-http.js +199 -0
  472. package/dist/server/request.d.ts +33 -0
  473. package/dist/server/request.js +103 -0
  474. package/dist/server/routes/admin.d.ts +9 -0
  475. package/dist/server/routes/admin.js +158 -0
  476. package/dist/server/routes/customer-notes.d.ts +7 -0
  477. package/dist/server/routes/customer-notes.js +112 -0
  478. package/dist/server/routes/decisions.d.ts +7 -0
  479. package/dist/server/routes/decisions.js +133 -0
  480. package/dist/server/routes/incidents.d.ts +7 -0
  481. package/dist/server/routes/incidents.js +126 -0
  482. package/dist/server/routes/memories.d.ts +10 -0
  483. package/dist/server/routes/memories.js +179 -0
  484. package/dist/server/routes/policies.d.ts +8 -0
  485. package/dist/server/routes/policies.js +151 -0
  486. package/dist/server/routes/predictions.d.ts +7 -0
  487. package/dist/server/routes/predictions.js +164 -0
  488. package/dist/server/routes/processes.d.ts +7 -0
  489. package/dist/server/routes/processes.js +161 -0
  490. package/dist/server/routes/project-briefs.d.ts +8 -0
  491. package/dist/server/routes/project-briefs.js +136 -0
  492. package/dist/server/routes/recall.d.ts +8 -0
  493. package/dist/server/routes/recall.js +340 -0
  494. package/dist/server/routes/skills.d.ts +8 -0
  495. package/dist/server/routes/skills.js +150 -0
  496. package/dist/server/types.d.ts +56 -0
  497. package/dist/server/types.js +2 -0
  498. package/dist/server/validation.d.ts +14 -0
  499. package/dist/server/validation.js +91 -0
  500. package/dist/server.d.ts +7 -61
  501. package/dist/server.js +69 -2362
  502. package/dist/session-digest.d.ts +1 -1
  503. package/dist/session-digest.js +9 -2
  504. package/dist/shared.d.ts +12 -1
  505. package/dist/shared.js +33 -27
  506. package/dist/skills.d.ts +3 -0
  507. package/dist/skills.js +88 -70
  508. package/dist/stdin.js +2 -2
  509. package/dist/store/audit-event.d.ts +19 -0
  510. package/dist/store/audit-event.js +33 -0
  511. package/dist/store/candidates.d.ts +42 -0
  512. package/dist/store/candidates.js +152 -0
  513. package/dist/store/conflicts.d.ts +44 -0
  514. package/dist/store/conflicts.js +444 -0
  515. package/dist/store/delete-and-batch.d.ts +63 -0
  516. package/dist/store/delete-and-batch.js +310 -0
  517. package/dist/store/entry-reads.d.ts +92 -0
  518. package/dist/store/entry-reads.js +255 -0
  519. package/dist/store/entry-row.d.ts +67 -0
  520. package/dist/store/entry-row.js +208 -0
  521. package/dist/store/entry-writes.d.ts +46 -0
  522. package/dist/store/entry-writes.js +148 -0
  523. package/dist/store/handoffs.d.ts +26 -0
  524. package/dist/store/handoffs.js +184 -0
  525. package/dist/store/index-and-stats.d.ts +52 -0
  526. package/dist/store/index-and-stats.js +214 -0
  527. package/dist/store/markdown.d.ts +10 -0
  528. package/dist/store/markdown.js +108 -0
  529. package/dist/store/mirrors.d.ts +49 -0
  530. package/dist/store/mirrors.js +312 -0
  531. package/dist/store/open.d.ts +15 -0
  532. package/dist/store/open.js +223 -0
  533. package/dist/store/rows.d.ts +178 -0
  534. package/dist/store/rows.js +158 -0
  535. package/dist/store/search-rows.d.ts +86 -0
  536. package/dist/store/search-rows.js +260 -0
  537. package/dist/store/sessions.d.ts +83 -0
  538. package/dist/store/sessions.js +272 -0
  539. package/dist/store/summaries.d.ts +94 -0
  540. package/dist/store/summaries.js +377 -0
  541. package/dist/store/tenant-lookup.d.ts +12 -0
  542. package/dist/store/tenant-lookup.js +16 -0
  543. package/dist/store-cards.js +2 -1
  544. package/dist/summary-dirty.d.ts +4 -0
  545. package/dist/summary-dirty.js +32 -0
  546. package/dist/support-bundle.js +4 -3
  547. package/dist/tenant.js +2 -2
  548. package/dist/tokenize.d.ts +2 -0
  549. package/dist/tokenize.js +16 -0
  550. package/dist/transcript-tail.d.ts +7 -0
  551. package/dist/transcript-tail.js +48 -0
  552. package/dist/vector-store.d.ts +27 -0
  553. package/dist/vector-store.js +210 -0
  554. package/dist/version.d.ts +2 -2
  555. package/dist/version.js +2 -2
  556. package/dist/working-memory.js +1 -1
  557. package/dist/yaml.js +36 -11
  558. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  559. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  560. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  566. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  570. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  571. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  572. package/dist-ui/index.html +3 -25
  573. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  574. package/extensions/openclaw-plugin/package.json +1 -1
  575. package/openclaw.plugin.json +1 -1
  576. package/package.json +1 -1
  577. package/dist/capture.d.ts +0 -155
  578. package/dist/capture.js +0 -1295
  579. package/dist/consolidate.d.ts +0 -58
  580. package/dist/consolidate.js +0 -1124
  581. package/dist/graph.d.ts +0 -245
  582. package/dist/hooks.d.ts +0 -208
  583. package/dist/hooks.js +0 -1076
  584. package/dist/importers.js +0 -900
  585. package/dist/predictions.js +0 -620
  586. package/dist/search.d.ts +0 -320
  587. package/dist/search.js +0 -970
  588. package/dist/store.d.ts +0 -776
  589. package/dist/store.js +0 -3473
  590. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  591. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  592. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  593. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
package/dist/policies.js CHANGED
@@ -38,12 +38,13 @@
38
38
  */
39
39
  import { BadRequestError, ConflictError, NotFoundError } from './api-errors.js';
40
40
  import { openHippoDb, closeHippoDb } from './db.js';
41
- import { writeEntry } from './store.js';
41
+ import { writeEntry } from './store/entry-writes.js';
42
42
  import { assertTenantId } from './tenant.js';
43
- import { markGraphDirty, removeGraphEntitiesForObject } from './graph.js';
43
+ import { markGraphDirty, removeGraphEntitiesForObject } from './graph/write.js';
44
44
  import { createMemory, Layer } from './memory.js';
45
45
  import { appendAuditEvent } from './audit.js';
46
46
  import { objectHalfLifeDays } from './half-life-migration.js';
47
+ import { keysetAfter } from './keyset.js';
47
48
  export const VALID_POLICY_STATES = new Set([
48
49
  'active',
49
50
  'superseded',
@@ -110,9 +111,79 @@ function buildPolicyContent(policyName, policyText, validFrom, validTo) {
110
111
  const range = validTo ? `${validFrom} to ${validTo}` : `${validFrom} onward`;
111
112
  return `${policyName}\n\n${policyText}\n\nEffective: ${range}`;
112
113
  }
113
- // ---------------------------------------------------------------------------
114
- // Public API
115
- // ---------------------------------------------------------------------------
114
+ // Preflight the supersede target BEFORE inserting the new row (so the new
115
+ // autoincrement id can never be its own supersede target); read the
116
+ // predecessor version in the same SELECT for server-derived versioning.
117
+ // Mirrors saveProcess / saveDecision (codex P1 2026-05-28).
118
+ function preflightPolicySupersede(db, tenantId, supersedesId) {
119
+ // SAFETY: SELECT projects exactly status, version; .get() returns that
120
+ // shape for the matching row, or undefined when no policy/tenant pair matches.
121
+ const pred = db.prepare(`SELECT status, version FROM policies WHERE id = ? AND tenant_id = ?`).get(supersedesId, tenantId);
122
+ if (!pred) {
123
+ throw new NotFoundError(`savePolicy: policy ${supersedesId} to supersede not found for tenant ${tenantId}`);
124
+ }
125
+ if (pred.status !== 'active') {
126
+ throw new ConflictError(`savePolicy: policy ${supersedesId} is not active (status='${pred.status}'); only active policies can be superseded.`);
127
+ }
128
+ return pred.version + 1;
129
+ }
130
+ function insertPolicyRow(db, memoryId, w, version) {
131
+ const result = db.prepare(`
132
+ INSERT INTO policies(
133
+ memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
134
+ version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
135
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, ?, NULL, ?)
136
+ `).run(memoryId, w.tenantId, w.policyName, w.policyText, w.validFrom, w.validTo, version, w.changeSummary, w.now);
137
+ return Number(result.lastInsertRowid ?? 0);
138
+ }
139
+ function supersedePolicyRow(db, w, supersedesId, policyId, version) {
140
+ const sup = db.prepare(`
141
+ UPDATE policies
142
+ SET status = 'superseded', superseded_by = ?, superseded_at = ?
143
+ WHERE id = ? AND tenant_id = ? AND status = 'active' AND id != ?
144
+ `).run(policyId, w.now, supersedesId, w.tenantId, policyId);
145
+ if (sup.changes === 0) {
146
+ throw new ConflictError(`savePolicy: policy ${supersedesId} could not be superseded (no longer active or self-reference).`);
147
+ }
148
+ appendAuditEvent(db, {
149
+ tenantId: w.tenantId,
150
+ actor: w.actor,
151
+ op: 'policy_supersede',
152
+ targetId: String(supersedesId),
153
+ metadata: {
154
+ policy_id: supersedesId,
155
+ superseded_by: policyId,
156
+ new_version: version,
157
+ },
158
+ });
159
+ }
160
+ /** The afterWrite body: preflight, INSERT, supersede, reload, create audit, all in one SAVEPOINT. */
161
+ function writePolicyRow(db, memoryId, w) {
162
+ const version = w.supersedesId !== undefined ? preflightPolicySupersede(db, w.tenantId, w.supersedesId) : 1;
163
+ const policyId = insertPolicyRow(db, memoryId, w, version);
164
+ if (w.supersedesId !== undefined)
165
+ supersedePolicyRow(db, w, w.supersedesId, policyId, version);
166
+ // SAFETY: SELECT ${POLICY_COLS} projects exactly the PolicyRow columns;
167
+ // .get() returns that row, or undefined only if the just-inserted id can't
168
+ // be found.
169
+ const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ?`)
170
+ .get(policyId);
171
+ if (!row)
172
+ throw new Error('savePolicy: failed to reload saved policy row');
173
+ // GDPR-light metadata: ids + flags only, no policy text.
174
+ appendAuditEvent(db, {
175
+ tenantId: w.tenantId,
176
+ actor: w.actor,
177
+ op: 'policy_create',
178
+ targetId: String(policyId),
179
+ metadata: {
180
+ policy_id: policyId,
181
+ version,
182
+ open_ended: w.validTo === null,
183
+ },
184
+ });
185
+ return row;
186
+ }
116
187
  /**
117
188
  * Create a policy (or a new version that supersedes an existing one). Writes the
118
189
  * memory mirror + the policies row atomically inside writeEntry's SAVEPOINT.
@@ -150,75 +221,22 @@ export function savePolicy(hippoRoot, tenantId, opts, actor = 'cli') {
150
221
  baseHalfLifeDays: objectHalfLifeDays(hippoRoot),
151
222
  tenantId,
152
223
  });
224
+ const w = {
225
+ tenantId,
226
+ actor,
227
+ policyName: opts.policyName,
228
+ policyText: opts.policyText,
229
+ validFrom,
230
+ validTo,
231
+ changeSummary,
232
+ supersedesId: opts.supersedesPolicyId,
233
+ now,
234
+ };
153
235
  let savedRow;
154
236
  writeEntry(hippoRoot, mem, {
155
237
  actor,
156
238
  afterWrite: (db, memoryId) => {
157
- // Preflight the supersede target BEFORE inserting the new row (so the new
158
- // autoincrement id can never be its own supersede target); read the
159
- // predecessor version in the same SELECT for server-derived versioning.
160
- // Mirrors saveProcess / saveDecision (codex P1 2026-05-28).
161
- let version = 1;
162
- if (opts.supersedesPolicyId !== undefined) {
163
- // SAFETY: SELECT projects exactly status, version; .get() returns that
164
- // shape for the matching row, or undefined when no policy/tenant pair matches.
165
- const pred = db.prepare(`SELECT status, version FROM policies WHERE id = ? AND tenant_id = ?`).get(opts.supersedesPolicyId, tenantId);
166
- if (!pred) {
167
- throw new NotFoundError(`savePolicy: policy ${opts.supersedesPolicyId} to supersede not found for tenant ${tenantId}`);
168
- }
169
- if (pred.status !== 'active') {
170
- throw new ConflictError(`savePolicy: policy ${opts.supersedesPolicyId} is not active (status='${pred.status}'); only active policies can be superseded.`);
171
- }
172
- version = pred.version + 1;
173
- }
174
- const result = db.prepare(`
175
- INSERT INTO policies(
176
- memory_id, tenant_id, policy_name, policy_text, valid_from, valid_to,
177
- version, status, superseded_by, superseded_at, change_summary, closed_at, created_at
178
- ) VALUES (?, ?, ?, ?, ?, ?, ?, 'active', NULL, NULL, ?, NULL, ?)
179
- `).run(memoryId, tenantId, opts.policyName, opts.policyText, validFrom, validTo, version, changeSummary, now);
180
- const policyId = Number(result.lastInsertRowid ?? 0);
181
- if (opts.supersedesPolicyId !== undefined) {
182
- const sup = db.prepare(`
183
- UPDATE policies
184
- SET status = 'superseded', superseded_by = ?, superseded_at = ?
185
- WHERE id = ? AND tenant_id = ? AND status = 'active' AND id != ?
186
- `).run(policyId, now, opts.supersedesPolicyId, tenantId, policyId);
187
- if (sup.changes === 0) {
188
- throw new ConflictError(`savePolicy: policy ${opts.supersedesPolicyId} could not be superseded (no longer active or self-reference).`);
189
- }
190
- appendAuditEvent(db, {
191
- tenantId,
192
- actor,
193
- op: 'policy_supersede',
194
- targetId: String(opts.supersedesPolicyId),
195
- metadata: {
196
- policy_id: opts.supersedesPolicyId,
197
- superseded_by: policyId,
198
- new_version: version,
199
- },
200
- });
201
- }
202
- // SAFETY: SELECT ${POLICY_COLS} projects exactly the PolicyRow columns;
203
- // .get() returns that row, or undefined only if the just-inserted id can't
204
- // be found.
205
- const row = db.prepare(`SELECT ${POLICY_COLS} FROM policies WHERE id = ?`)
206
- .get(policyId);
207
- if (!row)
208
- throw new Error('savePolicy: failed to reload saved policy row');
209
- savedRow = row;
210
- // GDPR-light metadata: ids + flags only, no policy text.
211
- appendAuditEvent(db, {
212
- tenantId,
213
- actor,
214
- op: 'policy_create',
215
- targetId: String(policyId),
216
- metadata: {
217
- policy_id: policyId,
218
- version,
219
- open_ended: validTo === null,
220
- },
221
- });
239
+ savedRow = writePolicyRow(db, memoryId, w);
222
240
  },
223
241
  afterCommit: () => markGraphDirty(hippoRoot, tenantId, mem.id),
224
242
  });
@@ -311,6 +329,7 @@ export function loadPolicyById(hippoRoot, tenantId, id) {
311
329
  export function loadPolicies(hippoRoot, tenantId, opts = {}) {
312
330
  assertTenantId('loadPolicies', tenantId);
313
331
  const limit = opts.limit ?? 100;
332
+ const after = keysetAfter('created_at', 'id', opts.after);
314
333
  const db = openHippoDb(hippoRoot);
315
334
  try {
316
335
  let rows;
@@ -322,20 +341,20 @@ export function loadPolicies(hippoRoot, tenantId, opts = {}) {
322
341
  // .all() returns rows in that shape regardless of the status filter applied.
323
342
  rows = db.prepare(`
324
343
  SELECT ${POLICY_COLS} FROM policies
325
- WHERE tenant_id = ? AND status = ?
344
+ WHERE tenant_id = ? AND status = ?${after.sql}
326
345
  ORDER BY created_at DESC, id DESC
327
346
  LIMIT ?
328
- `).all(tenantId, opts.status, limit);
347
+ `).all(tenantId, opts.status, ...after.params, limit);
329
348
  }
330
349
  else {
331
350
  // SAFETY: SELECT ${POLICY_COLS} projects exactly the PolicyRow columns;
332
351
  // .all() returns rows in that shape for every tenant-scoped row.
333
352
  rows = db.prepare(`
334
353
  SELECT ${POLICY_COLS} FROM policies
335
- WHERE tenant_id = ?
354
+ WHERE tenant_id = ?${after.sql}
336
355
  ORDER BY created_at DESC, id DESC
337
356
  LIMIT ?
338
- `).all(tenantId, limit);
357
+ `).all(tenantId, ...after.params, limit);
339
358
  }
340
359
  return rows.map(rowToPolicy);
341
360
  }
@@ -1,9 +1,10 @@
1
+ import { envSkipPostinstall } from './env.js';
1
2
  import * as fs from 'node:fs';
2
3
  import * as os from 'node:os';
3
4
  import * as path from 'node:path';
4
- import { detectRealCodexPath, isCodexWrapperInstalled, repairCodexWrapperIfInstalled, } from './hooks.js';
5
+ import { detectRealCodexPath, isCodexWrapperInstalled, repairCodexWrapperIfInstalled } from './hooks/codex-wrapper.js';
5
6
  function main() {
6
- if (process.env.HIPPO_SKIP_POSTINSTALL === '1')
7
+ if (envSkipPostinstall())
7
8
  return;
8
9
  try {
9
10
  // Repair-only: re-ensure the wrapper for users who previously opted in
@@ -0,0 +1,100 @@
1
+ /**
2
+ * J3.2 surface delivered on `RecallResult.planningFallacyHint` when an
3
+ * agent's recall query carries a forward-prediction phrase AND the closest
4
+ * matching prediction class has closed historical data.
5
+ *
6
+ * The agent sees its track record at the moment of forecasting, anchoring
7
+ * on the outside view (Lovallo-Kahneman 2003) rather than the inside-view
8
+ * inside the planning fallacy.
9
+ *
10
+ * Plan: docs/plans/2026-05-26-j32-auto-injection.md.
11
+ */
12
+ export interface PlanningFallacyHint {
13
+ classTag: string;
14
+ /** Verbatim PredictionBaserate.summary, e.g.
15
+ * "Last 5 estimates in class migration-effort averaged 2.10x actual (MAE 1.40)." */
16
+ baserateSummary: string;
17
+ /** Discriminator vs hypothetical future manual-override hints. */
18
+ source: 'j3.2-auto';
19
+ /** The regex match snippet that triggered detection. Lets the agent
20
+ * see WHY the hint appeared and self-correct if detection misfires
21
+ * (e.g. "I wasn't predicting; ignore"). */
22
+ detectedPhrase: string;
23
+ nClosed: number;
24
+ /** Null only when every closed-row had estimate_value=0 (ratio undefined). */
25
+ meanRatio: number | null;
26
+ }
27
+ /**
28
+ * v1.13.4 / J3.2 follow-up — "watching" variant emitted when the
29
+ * forward-claim regex matched but no PlanningFallacyHint baserate was
30
+ * returned. Dogfood diary (docs/dogfood/2026-05-27-track-j-warnings.md)
31
+ * Trial 2a confirmed the pre-v1.13.4 silent paths were the most common
32
+ * real-world J3.2 failure mode: a natural-language query carries a
33
+ * forward-claim phrase but its non-stopword tokens don't overlap with
34
+ * any prediction class tag, so hippo silently emitted nothing despite
35
+ * the regex match. The watching variant surfaces the detection event
36
+ * + a one-line suggestion so the agent can either re-tag the prediction
37
+ * or pass the suggestion through to the user.
38
+ */
39
+ export interface PlanningFallacyWatching {
40
+ /** The forward-claim phrase the detector matched (verbatim regex match snippet). */
41
+ detectedPhrase: string;
42
+ /** Why hippo couldn't produce a baserate hint despite the match.
43
+ * - 'no_class_match': no class scored >=1 on token overlap.
44
+ * - 'tiebreak': >=2 classes tied at the same best score (silent on ambiguity). */
45
+ reason: 'no_class_match' | 'tiebreak';
46
+ /** One-line agent-facing suggestion for how the user can give hippo
47
+ * enough signal to produce a baserate next time. */
48
+ suggestion: string;
49
+ }
50
+ /**
51
+ * v1.13.4 / J3.2 follow-up — richer return type for
52
+ * `computePlanningFallacyOutput`. Carries EITHER `hint` (baserate
53
+ * available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
54
+ * no queryText, no regex match, or nClosed=0 silent path). Never both.
55
+ */
56
+ export interface PlanningFallacyOutput {
57
+ hint?: PlanningFallacyHint;
58
+ watching?: PlanningFallacyWatching;
59
+ }
60
+ export type AutodebiasMode = 'off' | 'regex';
61
+ export interface ComputePlanningFallacyHintOpts {
62
+ /** Override env. When undefined, reads process.env.HIPPO_AUTODEBIAS at
63
+ * call time (per-call to allow test-time env toggling without module
64
+ * reload). 'off' short-circuits to null BEFORE the regex gate so the
65
+ * AUTODEBIAS=off path pays zero work. */
66
+ mode?: AutodebiasMode;
67
+ /** Actor for any audit emissions. Defaults to 'recall' (caller didn't
68
+ * specify). MUST thread through to the inner computePredictionBaserate
69
+ * call (passed as its `actor` arg) so MCP/HTTP-originated auto-hints
70
+ * carry the right attribution instead of the 'cli' default. */
71
+ actor?: string;
72
+ }
73
+ /**
74
+ * J3.2 orchestrator.
75
+ *
76
+ * Composes the forward-claim detector + class resolver + baserate compute,
77
+ * with telemetry-grade audit emission at every decision point (success,
78
+ * no-class-match, tiebreak).
79
+ *
80
+ * Returns `{}` (neither hint nor watching) on:
81
+ * - mode === 'off' (env-disabled; pays only the env read, skips regex)
82
+ * - empty queryText
83
+ * - no forward-claim regex match
84
+ * - resolved class has nClosed=0 (no historical data yet; silent)
85
+ *
86
+ * Returns `{ watching: ... }` on (v1.13.4 NEW — was silent null pre-1.13.4):
87
+ * - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
88
+ * - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
89
+ *
90
+ * Returns `{ hint: ... }` on success: calls computePredictionBaserate(...,
91
+ * emitAudit=false) so the predict_baserate audit channel stays scoped to
92
+ * deliberate predict-baserate calls (the orchestrator's own recall_autodebias_hint
93
+ * audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
94
+ * then emits recall_autodebias_hint audit + returns the hint.
95
+ *
96
+ * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
97
+ * on full match+resolve+baserate path. Well under 50ms target.
98
+ */
99
+ export declare function computePlanningFallacyOutput(hippoRoot: string, tenantId: string, queryText: string, opts?: ComputePlanningFallacyHintOpts): PlanningFallacyOutput;
100
+ //# sourceMappingURL=planning-fallacy.d.ts.map
@@ -0,0 +1,190 @@
1
+ import { envAutodebiasOff } from '../env.js';
2
+ import { openHippoDb, closeHippoDb } from '../db.js';
3
+ import { appendAuditEvent } from '../audit.js';
4
+ import { detectForwardClaim } from '../forward-claim-detector.js';
5
+ import { computePredictionBaserate } from './store.js';
6
+ /**
7
+ * Resolve a query-token set to a unique best-matching class_tag for the
8
+ * tenant. Scores by lower-cased token overlap; requires best score ≥ 1
9
+ * AND strictly greater than the 2nd-best score.
10
+ *
11
+ * Indexed via idx_predictions_tenant_class (db.ts:1015) → O(log n) seek
12
+ * plus a small DISTINCT scan over the per-tenant class-tag set.
13
+ *
14
+ * Scope behaviour (v1 design choice, independent-review-critic round 1
15
+ * MED): class_tag selection is TENANT-GLOBAL, NOT scope-filtered against
16
+ * the recall's opts.scope. The class_tag is an aggregator label across
17
+ * historical predictions in the class, not a per-memory scope-bound
18
+ * property. A no-scope recall CAN surface a class_tag from a privately-
19
+ * scoped prediction's class in PlanningFallacyHint.classTag — by design,
20
+ * because base-rate reasoning needs the full historical sample.
21
+ * Implications:
22
+ * - The hint payload itself carries no memory content (only the aggregate
23
+ * summary string + numeric stats), so memory bodies do not leak.
24
+ * - The class_tag NAME is the side-channel. If sensitive labels are a
25
+ * concern, callers should either use opaque class names (e.g. hashes
26
+ * or numeric tokens) or set HIPPO_AUTODEBIAS=off.
27
+ * - tests/api-recall-autodebias.test.ts locks this with an explicit
28
+ * test asserting that scope-set predictions surface via no-scope
29
+ * recalls (so future "fix" attempts that scope-filter trip CI).
30
+ */
31
+ function resolveClassFromTokens(hippoRoot, tenantId, queryTokens) {
32
+ if (queryTokens.length === 0)
33
+ return { classTag: null, tiebreak: false };
34
+ const db = openHippoDb(hippoRoot);
35
+ try {
36
+ // SAFETY: rows' shape matches the single `class_tag` column named in the SELECT above.
37
+ const rows = db.prepare(`SELECT DISTINCT class_tag FROM predictions WHERE tenant_id = ?`).all(tenantId);
38
+ const querySet = new Set(queryTokens);
39
+ let bestScore = 0;
40
+ let bestClass = null;
41
+ let secondBest = 0;
42
+ for (const { class_tag } of rows) {
43
+ const classTokens = class_tag
44
+ .toLowerCase()
45
+ .split(/[-_\s]+/)
46
+ .filter((t) => t.length >= 3);
47
+ let score = 0;
48
+ for (const t of classTokens)
49
+ if (querySet.has(t))
50
+ score++;
51
+ if (score > bestScore) {
52
+ secondBest = bestScore;
53
+ bestScore = score;
54
+ bestClass = class_tag;
55
+ }
56
+ else if (score === bestScore && score > 0) {
57
+ // Tie at current best — bump secondBest. Do NOT update bestClass
58
+ // (alphabetical tiebreak would pick wrong class on ambiguous query
59
+ // like "migration will take 3 days" between migration-effort vs
60
+ // migration-risk; silent on tie instead).
61
+ secondBest = score;
62
+ }
63
+ else if (score > secondBest) {
64
+ secondBest = score;
65
+ }
66
+ }
67
+ if (bestScore < 1)
68
+ return { classTag: null, tiebreak: false };
69
+ if (bestScore === secondBest)
70
+ return { classTag: null, tiebreak: true };
71
+ return { classTag: bestClass, tiebreak: false };
72
+ }
73
+ finally {
74
+ closeHippoDb(db);
75
+ }
76
+ }
77
+ /**
78
+ * J3.2 orchestrator.
79
+ *
80
+ * Composes the forward-claim detector + class resolver + baserate compute,
81
+ * with telemetry-grade audit emission at every decision point (success,
82
+ * no-class-match, tiebreak).
83
+ *
84
+ * Returns `{}` (neither hint nor watching) on:
85
+ * - mode === 'off' (env-disabled; pays only the env read, skips regex)
86
+ * - empty queryText
87
+ * - no forward-claim regex match
88
+ * - resolved class has nClosed=0 (no historical data yet; silent)
89
+ *
90
+ * Returns `{ watching: ... }` on (v1.13.4 NEW — was silent null pre-1.13.4):
91
+ * - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
92
+ * - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
93
+ *
94
+ * Returns `{ hint: ... }` on success: calls computePredictionBaserate(...,
95
+ * emitAudit=false) so the predict_baserate audit channel stays scoped to
96
+ * deliberate predict-baserate calls (the orchestrator's own recall_autodebias_hint
97
+ * audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
98
+ * then emits recall_autodebias_hint audit + returns the hint.
99
+ *
100
+ * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
101
+ * on full match+resolve+baserate path. Well under 50ms target.
102
+ */
103
+ export function computePlanningFallacyOutput(hippoRoot, tenantId, queryText, opts = {}) {
104
+ // Env read FIRST so AUTODEBIAS=off pays zero regex cost. Per-call read
105
+ // (rather than module-load cache) is deliberate: tests env-toggle this
106
+ // via process.env mutation without module reload.
107
+ const mode = opts.mode ?? (envAutodebiasOff() ? 'off' : 'regex');
108
+ if (mode === 'off')
109
+ return {};
110
+ if (!queryText)
111
+ return {};
112
+ const match = detectForwardClaim(queryText);
113
+ if (!match)
114
+ return {};
115
+ const actor = opts.actor ?? 'recall';
116
+ const resolution = resolveClassFromTokens(hippoRoot, tenantId, match.classQueryTokens);
117
+ if (resolution.tiebreak) {
118
+ // Telemetry: forward-claim detected, ≥2 classes tied at best overlap.
119
+ // v1.13.4: now ALSO returns a watching variant so the caller surface
120
+ // can render a "watching but no baserate (tiebreak)" line. Audit emission
121
+ // unchanged (the audit channel is the telemetry-grade source of truth).
122
+ return watchingWithAudit(hippoRoot, tenantId, actor, match, 'tiebreak', TIEBREAK_SUGGESTION);
123
+ }
124
+ if (!resolution.classTag) {
125
+ // Telemetry: forward-claim detected, no class scored ≥ 1.
126
+ // This is the channel that drives the embedding-fallback decision
127
+ // for J3.3 — high volume here = regex+token-overlap is missing
128
+ // legitimate forward-claims that have NO obvious class signal.
129
+ // v1.13.4: now ALSO returns a watching variant so the caller surface
130
+ // can render a "watching but no baserate (no class match)" line.
131
+ return watchingWithAudit(hippoRoot, tenantId, actor, match, 'no_class_match', NO_CLASS_MATCH_SUGGESTION);
132
+ }
133
+ // emitAudit=false: avoid double-write to predict_baserate channel.
134
+ // The recall_autodebias_hint audit below carries n_closed + mean_ratio.
135
+ const baserate = computePredictionBaserate(hippoRoot, tenantId, resolution.classTag, actor,
136
+ /*emitAudit=*/ false);
137
+ if (baserate.nClosed === 0)
138
+ return {}; // Silent — wait for closed data.
139
+ appendAuditEventOnce(hippoRoot, {
140
+ tenantId,
141
+ actor,
142
+ op: 'recall_autodebias_hint',
143
+ targetId: resolution.classTag,
144
+ metadata: {
145
+ class_tag: resolution.classTag,
146
+ detected_phrase: match.phrase,
147
+ n_closed: baserate.nClosed,
148
+ mean_ratio: baserate.meanRatio,
149
+ },
150
+ });
151
+ return {
152
+ hint: {
153
+ classTag: resolution.classTag,
154
+ baserateSummary: baserate.summary,
155
+ source: 'j3.2-auto',
156
+ detectedPhrase: match.phrase,
157
+ nClosed: baserate.nClosed,
158
+ meanRatio: baserate.meanRatio,
159
+ },
160
+ };
161
+ }
162
+ const TIEBREAK_SUGGESTION = 'Multiple prediction classes tied on this query. Refine the query or rename overlapping classes to break the tie.';
163
+ const NO_CLASS_MATCH_SUGGESTION = 'No matching prediction class for this forward-claim. Tag your prediction with `hippo predict --class <name>` to start tracking this class.';
164
+ /** One audit row on its own short-lived connection. */
165
+ function appendAuditEventOnce(hippoRoot, event) {
166
+ const db = openHippoDb(hippoRoot);
167
+ try {
168
+ appendAuditEvent(db, event);
169
+ }
170
+ finally {
171
+ closeHippoDb(db);
172
+ }
173
+ }
174
+ function watchingWithAudit(hippoRoot, tenantId, actor, match, reason, suggestion) {
175
+ appendAuditEventOnce(hippoRoot, {
176
+ tenantId,
177
+ actor,
178
+ op: reason === 'tiebreak' ? 'recall_autodebias_hint_tiebreak' : 'recall_autodebias_hint_no_class_match',
179
+ targetId: match.phrase.slice(0, 100),
180
+ metadata: { detected_phrase: match.phrase, token_count: match.classQueryTokens.length },
181
+ });
182
+ return {
183
+ watching: {
184
+ detectedPhrase: match.phrase,
185
+ reason,
186
+ suggestion,
187
+ },
188
+ };
189
+ }
190
+ //# sourceMappingURL=planning-fallacy.js.map
@@ -14,8 +14,8 @@
14
14
  * the schema level.
15
15
  *
16
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
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
19
  * a failure in either step rolls back both. Pattern matches supersede
20
20
  * (api.ts:1486) and the Slack/GitHub connectors.
21
21
  *
@@ -24,6 +24,7 @@
24
24
  * (estimate_value, actual_value) at query time. J3 is a follow-up episode;
25
25
  * this module ships the data layer.
26
26
  */
27
+ import { type KeysetPosition } from '../keyset.js';
27
28
  export type ClosureState = 'open' | 'closed' | 'closed-unknown';
28
29
  export declare const VALID_CLOSURE_STATES: ReadonlySet<ClosureState>;
29
30
  export interface Prediction {
@@ -58,6 +59,8 @@ export interface ClosePredictionOpts {
58
59
  export interface ListPredictionsOpts {
59
60
  closureState?: ClosureState;
60
61
  limit?: number;
62
+ /** Resume after this row: the position the previous page ended on. */
63
+ after?: KeysetPosition;
61
64
  }
62
65
  /**
63
66
  * Create a new prediction. Writes a memory mirror + a predictions table
@@ -128,104 +131,6 @@ emitAudit?: boolean): PredictionBaserate;
128
131
  export declare function loadOpenPredictions(hippoRoot: string, tenantId: string, opts?: {
129
132
  classTag?: string;
130
133
  limit?: number;
134
+ after?: KeysetPosition;
131
135
  }): Prediction[];
132
- /**
133
- * J3.2 surface delivered on `RecallResult.planningFallacyHint` when an
134
- * agent's recall query carries a forward-prediction phrase AND the closest
135
- * matching prediction class has closed historical data.
136
- *
137
- * The agent sees its track record at the moment of forecasting, anchoring
138
- * on the outside view (Lovallo-Kahneman 2003) rather than the inside-view
139
- * inside the planning fallacy.
140
- *
141
- * Plan: docs/plans/2026-05-26-j32-auto-injection.md.
142
- */
143
- export interface PlanningFallacyHint {
144
- classTag: string;
145
- /** Verbatim PredictionBaserate.summary, e.g.
146
- * "Last 5 estimates in class migration-effort averaged 2.10x actual (MAE 1.40)." */
147
- baserateSummary: string;
148
- /** Discriminator vs hypothetical future manual-override hints. */
149
- source: 'j3.2-auto';
150
- /** The regex match snippet that triggered detection. Lets the agent
151
- * see WHY the hint appeared and self-correct if detection misfires
152
- * (e.g. "I wasn't predicting; ignore"). */
153
- detectedPhrase: string;
154
- nClosed: number;
155
- /** Null only when every closed-row had estimate_value=0 (ratio undefined). */
156
- meanRatio: number | null;
157
- }
158
- /**
159
- * v1.13.4 / J3.2 follow-up — "watching" variant emitted when the
160
- * forward-claim regex matched but no PlanningFallacyHint baserate was
161
- * returned. Dogfood diary (docs/dogfood/2026-05-27-track-j-warnings.md)
162
- * Trial 2a confirmed the pre-v1.13.4 silent paths were the most common
163
- * real-world J3.2 failure mode: a natural-language query carries a
164
- * forward-claim phrase but its non-stopword tokens don't overlap with
165
- * any prediction class tag, so hippo silently emitted nothing despite
166
- * the regex match. The watching variant surfaces the detection event
167
- * + a one-line suggestion so the agent can either re-tag the prediction
168
- * or pass the suggestion through to the user.
169
- */
170
- export interface PlanningFallacyWatching {
171
- /** The forward-claim phrase the detector matched (verbatim regex match snippet). */
172
- detectedPhrase: string;
173
- /** Why hippo couldn't produce a baserate hint despite the match.
174
- * - 'no_class_match': no class scored >=1 on token overlap.
175
- * - 'tiebreak': >=2 classes tied at the same best score (silent on ambiguity). */
176
- reason: 'no_class_match' | 'tiebreak';
177
- /** One-line agent-facing suggestion for how the user can give hippo
178
- * enough signal to produce a baserate next time. */
179
- suggestion: string;
180
- }
181
- /**
182
- * v1.13.4 / J3.2 follow-up — richer return type for
183
- * `computePlanningFallacyOutput`. Carries EITHER `hint` (baserate
184
- * available) OR `watching` (regex fired, no baserate), or NEITHER (mode=off,
185
- * no queryText, no regex match, or nClosed=0 silent path). Never both.
186
- */
187
- export interface PlanningFallacyOutput {
188
- hint?: PlanningFallacyHint;
189
- watching?: PlanningFallacyWatching;
190
- }
191
- export type AutodebiasMode = 'off' | 'regex';
192
- export interface ComputePlanningFallacyHintOpts {
193
- /** Override env. When undefined, reads process.env.HIPPO_AUTODEBIAS at
194
- * call time (per-call to allow test-time env toggling without module
195
- * reload). 'off' short-circuits to null BEFORE the regex gate so the
196
- * AUTODEBIAS=off path pays zero work. */
197
- mode?: AutodebiasMode;
198
- /** Actor for any audit emissions. Defaults to 'recall' (caller didn't
199
- * specify). MUST thread through to the inner computePredictionBaserate
200
- * call (passed as its `actor` arg) so MCP/HTTP-originated auto-hints
201
- * carry the right attribution instead of the 'cli' default. */
202
- actor?: string;
203
- }
204
- /**
205
- * J3.2 orchestrator.
206
- *
207
- * Composes the forward-claim detector + class resolver + baserate compute,
208
- * with telemetry-grade audit emission at every decision point (success,
209
- * no-class-match, tiebreak).
210
- *
211
- * Returns `{}` (neither hint nor watching) on:
212
- * - mode === 'off' (env-disabled; pays only the env read, skips regex)
213
- * - empty queryText
214
- * - no forward-claim regex match
215
- * - resolved class has nClosed=0 (no historical data yet; silent)
216
- *
217
- * Returns `{ watching: ... }` on (v1.13.4 NEW — was silent null pre-1.13.4):
218
- * - resolver returns no class (no overlap ≥ 1; emits no_class_match audit)
219
- * - resolver returns tiebreak (≥2 classes tied at best; emits tiebreak audit)
220
- *
221
- * Returns `{ hint: ... }` on success: calls computePredictionBaserate(...,
222
- * emitAudit=false) so the predict_baserate audit channel stays scoped to
223
- * deliberate predict-baserate calls (the orchestrator's own recall_autodebias_hint
224
- * audit carries n_closed + mean_ratio in metadata so no telemetry is lost),
225
- * then emits recall_autodebias_hint audit + returns the hint.
226
- *
227
- * Latency budget (plan §Latency): ~50us regex-only on miss; ~750-850us
228
- * on full match+resolve+baserate path. Well under 50ms target.
229
- */
230
- export declare function computePlanningFallacyOutput(hippoRoot: string, tenantId: string, queryText: string, opts?: ComputePlanningFallacyHintOpts): PlanningFallacyOutput;
231
- //# sourceMappingURL=predictions.d.ts.map
136
+ //# sourceMappingURL=store.d.ts.map