hippo-memory 1.59.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (596) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1260
  53. package/dist/api.js +25 -2711
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +7 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +7 -4
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +319 -13
  123. package/dist/cli.js +436 -8580
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +12 -9
  126. package/dist/config.js +12 -11
  127. package/dist/connectors/github/backfill.js +94 -87
  128. package/dist/connectors/github/cli-impl.js +5 -3
  129. package/dist/connectors/github/dlq.js +67 -54
  130. package/dist/connectors/github/ingest.js +34 -35
  131. package/dist/connectors/github/tenant-routing.js +3 -2
  132. package/dist/connectors/github/webhook.js +135 -216
  133. package/dist/connectors/slack/dlq.js +49 -61
  134. package/dist/connectors/slack/ingest.js +55 -48
  135. package/dist/connectors/slack/tenant-routing.js +4 -3
  136. package/dist/connectors/slack/webhook.js +72 -74
  137. package/dist/consolidate/conflicts.d.ts +10 -0
  138. package/dist/consolidate/conflicts.js +178 -0
  139. package/dist/consolidate/decay.d.ts +12 -0
  140. package/dist/consolidate/decay.js +145 -0
  141. package/dist/consolidate/llm-passes.d.ts +3 -0
  142. package/dist/consolidate/llm-passes.js +141 -0
  143. package/dist/consolidate/merge.d.ts +7 -0
  144. package/dist/consolidate/merge.js +251 -0
  145. package/dist/consolidate/physics-pass.d.ts +3 -0
  146. package/dist/consolidate/physics-pass.js +60 -0
  147. package/dist/consolidate/run.d.ts +69 -0
  148. package/dist/consolidate/run.js +76 -0
  149. package/dist/consolidate/sleep.d.ts +18 -0
  150. package/dist/consolidate/sleep.js +209 -0
  151. package/dist/consolidate/traces.d.ts +4 -0
  152. package/dist/consolidate/traces.js +178 -0
  153. package/dist/context-auto.js +7 -11
  154. package/dist/context-render.d.ts +1 -1
  155. package/dist/context-render.js +1 -1
  156. package/dist/customer-notes.d.ts +3 -0
  157. package/dist/customer-notes.js +6 -4
  158. package/dist/dag.js +13 -12
  159. package/dist/dashboard-actions.d.ts +20 -0
  160. package/dist/dashboard-actions.js +88 -0
  161. package/dist/dashboard-params.d.ts +45 -0
  162. package/dist/dashboard-params.js +127 -0
  163. package/dist/dashboard-queries.d.ts +15 -0
  164. package/dist/dashboard-queries.js +355 -0
  165. package/dist/dashboard-snapshot.d.ts +138 -0
  166. package/dist/dashboard-snapshot.js +308 -0
  167. package/dist/dashboard-types.d.ts +163 -0
  168. package/dist/dashboard-types.js +3 -0
  169. package/dist/dashboard.d.ts +6 -7
  170. package/dist/dashboard.js +231 -203
  171. package/dist/db/busy.d.ts +5 -0
  172. package/dist/db/busy.js +24 -0
  173. package/dist/db/continuity.d.ts +5 -0
  174. package/dist/db/continuity.js +145 -0
  175. package/dist/db/meta.d.ts +8 -0
  176. package/dist/db/meta.js +35 -0
  177. package/dist/db/migrate.d.ts +9 -0
  178. package/dist/db/migrate.js +138 -0
  179. package/dist/db/migrations/index.d.ts +5 -0
  180. package/dist/db/migrations/index.js +109 -0
  181. package/dist/db/migrations/types.d.ts +14 -0
  182. package/dist/db/migrations/types.js +2 -0
  183. package/dist/db/migrations/v01.d.ts +3 -0
  184. package/dist/db/migrations/v01.js +38 -0
  185. package/dist/db/migrations/v02.d.ts +3 -0
  186. package/dist/db/migrations/v02.js +21 -0
  187. package/dist/db/migrations/v03.d.ts +3 -0
  188. package/dist/db/migrations/v03.js +22 -0
  189. package/dist/db/migrations/v04.d.ts +3 -0
  190. package/dist/db/migrations/v04.js +28 -0
  191. package/dist/db/migrations/v05.d.ts +3 -0
  192. package/dist/db/migrations/v05.js +21 -0
  193. package/dist/db/migrations/v06.d.ts +3 -0
  194. package/dist/db/migrations/v06.js +25 -0
  195. package/dist/db/migrations/v07.d.ts +3 -0
  196. package/dist/db/migrations/v07.js +13 -0
  197. package/dist/db/migrations/v08.d.ts +3 -0
  198. package/dist/db/migrations/v08.js +8 -0
  199. package/dist/db/migrations/v09.d.ts +3 -0
  200. package/dist/db/migrations/v09.js +13 -0
  201. package/dist/db/migrations/v10.d.ts +3 -0
  202. package/dist/db/migrations/v10.js +17 -0
  203. package/dist/db/migrations/v11.d.ts +3 -0
  204. package/dist/db/migrations/v11.js +15 -0
  205. package/dist/db/migrations/v12.d.ts +3 -0
  206. package/dist/db/migrations/v12.js +11 -0
  207. package/dist/db/migrations/v13.d.ts +3 -0
  208. package/dist/db/migrations/v13.js +15 -0
  209. package/dist/db/migrations/v14.d.ts +3 -0
  210. package/dist/db/migrations/v14.js +66 -0
  211. package/dist/db/migrations/v15.d.ts +3 -0
  212. package/dist/db/migrations/v15.js +42 -0
  213. package/dist/db/migrations/v16.d.ts +3 -0
  214. package/dist/db/migrations/v16.js +61 -0
  215. package/dist/db/migrations/v17.d.ts +3 -0
  216. package/dist/db/migrations/v17.js +46 -0
  217. package/dist/db/migrations/v18.d.ts +3 -0
  218. package/dist/db/migrations/v18.js +60 -0
  219. package/dist/db/migrations/v19.d.ts +3 -0
  220. package/dist/db/migrations/v19.js +28 -0
  221. package/dist/db/migrations/v20.d.ts +3 -0
  222. package/dist/db/migrations/v20.js +42 -0
  223. package/dist/db/migrations/v21.d.ts +3 -0
  224. package/dist/db/migrations/v21.js +16 -0
  225. package/dist/db/migrations/v22.d.ts +3 -0
  226. package/dist/db/migrations/v22.js +82 -0
  227. package/dist/db/migrations/v23.d.ts +3 -0
  228. package/dist/db/migrations/v23.js +48 -0
  229. package/dist/db/migrations/v24.d.ts +3 -0
  230. package/dist/db/migrations/v24.js +72 -0
  231. package/dist/db/migrations/v25.d.ts +3 -0
  232. package/dist/db/migrations/v25.js +46 -0
  233. package/dist/db/migrations/v26.d.ts +3 -0
  234. package/dist/db/migrations/v26.js +23 -0
  235. package/dist/db/migrations/v27.d.ts +3 -0
  236. package/dist/db/migrations/v27.js +57 -0
  237. package/dist/db/migrations/v28.d.ts +3 -0
  238. package/dist/db/migrations/v28.js +38 -0
  239. package/dist/db/migrations/v29.d.ts +3 -0
  240. package/dist/db/migrations/v29.js +78 -0
  241. package/dist/db/migrations/v30.d.ts +3 -0
  242. package/dist/db/migrations/v30.js +92 -0
  243. package/dist/db/migrations/v31.d.ts +3 -0
  244. package/dist/db/migrations/v31.js +74 -0
  245. package/dist/db/migrations/v32.d.ts +3 -0
  246. package/dist/db/migrations/v32.js +102 -0
  247. package/dist/db/migrations/v33.d.ts +3 -0
  248. package/dist/db/migrations/v33.js +104 -0
  249. package/dist/db/migrations/v34.d.ts +3 -0
  250. package/dist/db/migrations/v34.js +93 -0
  251. package/dist/db/migrations/v35.d.ts +3 -0
  252. package/dist/db/migrations/v35.js +98 -0
  253. package/dist/db/migrations/v36.d.ts +3 -0
  254. package/dist/db/migrations/v36.js +98 -0
  255. package/dist/db/migrations/v37.d.ts +3 -0
  256. package/dist/db/migrations/v37.js +219 -0
  257. package/dist/db/migrations/v38.d.ts +3 -0
  258. package/dist/db/migrations/v38.js +277 -0
  259. package/dist/db/migrations/v39.d.ts +3 -0
  260. package/dist/db/migrations/v39.js +59 -0
  261. package/dist/db/migrations/v40.d.ts +3 -0
  262. package/dist/db/migrations/v40.js +74 -0
  263. package/dist/db/migrations/v41.d.ts +3 -0
  264. package/dist/db/migrations/v41.js +43 -0
  265. package/dist/db/migrations/v42.d.ts +3 -0
  266. package/dist/db/migrations/v42.js +41 -0
  267. package/dist/db/migrations/v43.d.ts +3 -0
  268. package/dist/db/migrations/v43.js +67 -0
  269. package/dist/db/migrations/v44.d.ts +3 -0
  270. package/dist/db/migrations/v44.js +28 -0
  271. package/dist/db/migrations/v45.d.ts +3 -0
  272. package/dist/db/migrations/v45.js +30 -0
  273. package/dist/db/migrations/v46.d.ts +3 -0
  274. package/dist/db/migrations/v46.js +25 -0
  275. package/dist/db/migrations/v47.d.ts +3 -0
  276. package/dist/db/migrations/v47.js +17 -0
  277. package/dist/db/migrations/v48.d.ts +3 -0
  278. package/dist/db/migrations/v48.js +10 -0
  279. package/dist/db/migrations/v49.d.ts +3 -0
  280. package/dist/db/migrations/v49.js +31 -0
  281. package/dist/db/migrations/v50.d.ts +3 -0
  282. package/dist/db/migrations/v50.js +67 -0
  283. package/dist/db/migrations/v51.d.ts +3 -0
  284. package/dist/db/migrations/v51.js +14 -0
  285. package/dist/db/migrations/v52.d.ts +3 -0
  286. package/dist/db/migrations/v52.js +7 -0
  287. package/dist/db/open.d.ts +23 -0
  288. package/dist/db/open.js +146 -0
  289. package/dist/db/sqlite.d.ts +21 -0
  290. package/dist/db/sqlite.js +8 -0
  291. package/dist/db/tables.d.ts +7 -0
  292. package/dist/db/tables.js +38 -0
  293. package/dist/db.d.ts +6 -46
  294. package/dist/db.js +5 -3036
  295. package/dist/decisions.d.ts +4 -1
  296. package/dist/decisions.js +9 -7
  297. package/dist/dedupe.js +3 -2
  298. package/dist/delivery-recorder.js +5 -1
  299. package/dist/doctor.js +4 -3
  300. package/dist/dormant.js +1 -0
  301. package/dist/embedding-provider.d.ts +1 -1
  302. package/dist/embedding-provider.js +7 -5
  303. package/dist/embeddings.d.ts +9 -52
  304. package/dist/embeddings.js +47 -298
  305. package/dist/env.d.ts +75 -0
  306. package/dist/env.js +119 -0
  307. package/dist/eval-suite.js +1 -1
  308. package/dist/eval.js +2 -2
  309. package/dist/extract.js +5 -4
  310. package/dist/gated-write.js +3 -1
  311. package/dist/goals.d.ts +3 -1
  312. package/dist/goals.js +18 -0
  313. package/dist/graph/read.d.ts +73 -0
  314. package/dist/graph/read.js +325 -0
  315. package/dist/graph/rows.d.ts +45 -0
  316. package/dist/graph/rows.js +51 -0
  317. package/dist/graph/types.d.ts +83 -0
  318. package/dist/graph/types.js +11 -0
  319. package/dist/graph/write.d.ts +93 -0
  320. package/dist/{graph.js → graph/write.js} +8 -391
  321. package/dist/graph-extract.js +2 -1
  322. package/dist/graph-recall.d.ts +1 -1
  323. package/dist/graph-recall.js +2 -2
  324. package/dist/graph-stream.js +1 -1
  325. package/dist/graph-view.d.ts +1 -1
  326. package/dist/graph-view.js +1 -1
  327. package/dist/half-life-migration.d.ts +1 -1
  328. package/dist/half-life-migration.js +2 -1
  329. package/dist/handoff.js +3 -0
  330. package/dist/hooks/codex-session.d.ts +8 -0
  331. package/dist/hooks/codex-session.js +76 -0
  332. package/dist/hooks/codex-wrapper.d.ts +55 -0
  333. package/dist/hooks/codex-wrapper.js +288 -0
  334. package/dist/hooks/json-hooks.d.ts +63 -0
  335. package/dist/hooks/json-hooks.js +356 -0
  336. package/dist/hooks/opencode.d.ts +50 -0
  337. package/dist/hooks/opencode.js +202 -0
  338. package/dist/hooks/shared.d.ts +54 -0
  339. package/dist/hooks/shared.js +77 -0
  340. package/dist/http-retry.d.ts +2 -0
  341. package/dist/http-retry.js +4 -3
  342. package/dist/http-util.d.ts +3 -0
  343. package/dist/http-util.js +10 -0
  344. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  345. package/dist/importers/core.js +141 -0
  346. package/dist/importers/markdown-parse.d.ts +41 -0
  347. package/dist/importers/markdown-parse.js +132 -0
  348. package/dist/importers/markdown.d.ts +3 -0
  349. package/dist/importers/markdown.js +92 -0
  350. package/dist/importers/sources.d.ts +7 -0
  351. package/dist/importers/sources.js +229 -0
  352. package/dist/importers/vault.d.ts +11 -0
  353. package/dist/importers/vault.js +352 -0
  354. package/dist/incidents.d.ts +3 -0
  355. package/dist/incidents.js +8 -5
  356. package/dist/index.d.ts +25 -6
  357. package/dist/index.js +23 -6
  358. package/dist/invalidation.js +2 -1
  359. package/dist/judgment.js +7 -3
  360. package/dist/keyset.d.ts +13 -0
  361. package/dist/keyset.js +8 -0
  362. package/dist/local-embedding.d.ts +13 -0
  363. package/dist/local-embedding.js +165 -0
  364. package/dist/log.d.ts +7 -0
  365. package/dist/log.js +19 -1
  366. package/dist/mcp/admin-tools.d.ts +8 -0
  367. package/dist/mcp/admin-tools.js +116 -0
  368. package/dist/mcp/format.d.ts +27 -0
  369. package/dist/mcp/format.js +135 -0
  370. package/dist/mcp/memory-tools.d.ts +5 -0
  371. package/dist/mcp/memory-tools.js +83 -0
  372. package/dist/mcp/protocol.d.ts +83 -0
  373. package/dist/mcp/protocol.js +55 -0
  374. package/dist/mcp/recall-tools.d.ts +6 -0
  375. package/dist/mcp/recall-tools.js +320 -0
  376. package/dist/mcp/request.d.ts +10 -0
  377. package/dist/mcp/request.js +163 -0
  378. package/dist/mcp/server.d.ts +4 -70
  379. package/dist/mcp/server.js +8 -1172
  380. package/dist/mcp/session-state.d.ts +11 -0
  381. package/dist/mcp/session-state.js +28 -0
  382. package/dist/mcp/stdio.d.ts +8 -0
  383. package/dist/mcp/stdio.js +79 -0
  384. package/dist/mcp/tools.d.ts +11 -0
  385. package/dist/mcp/tools.js +247 -0
  386. package/dist/memory.d.ts +8 -3
  387. package/dist/memory.js +27 -1
  388. package/dist/multihop.d.ts +1 -1
  389. package/dist/multihop.js +2 -1
  390. package/dist/owner-validation.js +2 -1
  391. package/dist/physics-state.js +10 -7
  392. package/dist/policies.d.ts +3 -0
  393. package/dist/policies.js +8 -6
  394. package/dist/postinstall.js +3 -2
  395. package/dist/predictions/planning-fallacy.d.ts +100 -0
  396. package/dist/predictions/planning-fallacy.js +190 -0
  397. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  398. package/dist/predictions/store.js +434 -0
  399. package/dist/processes.d.ts +3 -0
  400. package/dist/processes.js +8 -5
  401. package/dist/project-briefs.d.ts +3 -0
  402. package/dist/project-briefs.js +7 -5
  403. package/dist/project-identity.d.ts +1 -1
  404. package/dist/project-identity.js +12 -6
  405. package/dist/project-merge.js +3 -1
  406. package/dist/quarantine.d.ts +2 -1
  407. package/dist/quarantine.js +8 -5
  408. package/dist/raw-archive-mirror-cleanup.js +2 -1
  409. package/dist/raw-archive.js +1 -1
  410. package/dist/recall-history.js +3 -2
  411. package/dist/recall-pipeline.d.ts +2 -2
  412. package/dist/recall-pipeline.js +16 -8
  413. package/dist/recall-scope.js +1 -1
  414. package/dist/recall-trace.d.ts +3 -3
  415. package/dist/recall-trace.js +10 -14
  416. package/dist/refine-llm.js +20 -11
  417. package/dist/reject-flow.js +6 -1
  418. package/dist/rerankers/clef.d.ts +2 -2
  419. package/dist/rerankers/clef.js +72 -30
  420. package/dist/rerankers/cross-encoder.js +6 -4
  421. package/dist/rerankers/jev.d.ts +4 -2
  422. package/dist/rerankers/jev.js +24 -19
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +61 -41
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/same-text.d.ts +2 -0
  428. package/dist/same-text.js +4 -0
  429. package/dist/scheduler.d.ts +1 -0
  430. package/dist/scheduler.js +26 -3
  431. package/dist/scope.js +4 -3
  432. package/dist/search/as-of.d.ts +10 -0
  433. package/dist/search/as-of.js +22 -0
  434. package/dist/search/bm25-search.d.ts +14 -0
  435. package/dist/search/bm25-search.js +43 -0
  436. package/dist/search/bm25.d.ts +15 -0
  437. package/dist/search/bm25.js +54 -0
  438. package/dist/search/boosts.d.ts +54 -0
  439. package/dist/search/boosts.js +94 -0
  440. package/dist/search/breakdown.d.ts +7 -0
  441. package/dist/search/breakdown.js +20 -0
  442. package/dist/search/explain.d.ts +25 -0
  443. package/dist/search/explain.js +31 -0
  444. package/dist/search/finalize.d.ts +8 -0
  445. package/dist/search/finalize.js +52 -0
  446. package/dist/search/fusion.d.ts +27 -0
  447. package/dist/search/fusion.js +42 -0
  448. package/dist/search/hybrid-score.d.ts +20 -0
  449. package/dist/search/hybrid-score.js +73 -0
  450. package/dist/search/hybrid.d.ts +46 -0
  451. package/dist/search/hybrid.js +64 -0
  452. package/dist/search/physics-search.d.ts +29 -0
  453. package/dist/search/physics-search.js +162 -0
  454. package/dist/search/rerank.d.ts +10 -0
  455. package/dist/search/rerank.js +72 -0
  456. package/dist/search/temporal.d.ts +15 -0
  457. package/dist/search/temporal.js +45 -0
  458. package/dist/search/types.d.ts +91 -0
  459. package/dist/search/types.js +2 -0
  460. package/dist/search/vector.d.ts +30 -0
  461. package/dist/search/vector.js +71 -0
  462. package/dist/secret-detect.d.ts +2 -0
  463. package/dist/secret-detect.js +3 -1
  464. package/dist/server/auth.d.ts +52 -0
  465. package/dist/server/auth.js +221 -0
  466. package/dist/server/client-ip.d.ts +25 -0
  467. package/dist/server/client-ip.js +92 -0
  468. package/dist/server/cursor.d.ts +23 -0
  469. package/dist/server/cursor.js +58 -0
  470. package/dist/server/lifecycle.d.ts +7 -0
  471. package/dist/server/lifecycle.js +29 -0
  472. package/dist/server/mcp-http.d.ts +5 -0
  473. package/dist/server/mcp-http.js +199 -0
  474. package/dist/server/request.d.ts +33 -0
  475. package/dist/server/request.js +103 -0
  476. package/dist/server/routes/admin.d.ts +9 -0
  477. package/dist/server/routes/admin.js +158 -0
  478. package/dist/server/routes/customer-notes.d.ts +7 -0
  479. package/dist/server/routes/customer-notes.js +112 -0
  480. package/dist/server/routes/decisions.d.ts +7 -0
  481. package/dist/server/routes/decisions.js +133 -0
  482. package/dist/server/routes/incidents.d.ts +7 -0
  483. package/dist/server/routes/incidents.js +126 -0
  484. package/dist/server/routes/memories.d.ts +10 -0
  485. package/dist/server/routes/memories.js +179 -0
  486. package/dist/server/routes/policies.d.ts +8 -0
  487. package/dist/server/routes/policies.js +151 -0
  488. package/dist/server/routes/predictions.d.ts +7 -0
  489. package/dist/server/routes/predictions.js +164 -0
  490. package/dist/server/routes/processes.d.ts +7 -0
  491. package/dist/server/routes/processes.js +161 -0
  492. package/dist/server/routes/project-briefs.d.ts +8 -0
  493. package/dist/server/routes/project-briefs.js +136 -0
  494. package/dist/server/routes/recall.d.ts +8 -0
  495. package/dist/server/routes/recall.js +340 -0
  496. package/dist/server/routes/skills.d.ts +8 -0
  497. package/dist/server/routes/skills.js +150 -0
  498. package/dist/server/types.d.ts +56 -0
  499. package/dist/server/types.js +2 -0
  500. package/dist/server/validation.d.ts +14 -0
  501. package/dist/server/validation.js +91 -0
  502. package/dist/server.d.ts +7 -61
  503. package/dist/server.js +92 -2368
  504. package/dist/session-digest.d.ts +1 -1
  505. package/dist/session-digest.js +9 -2
  506. package/dist/shared.d.ts +3 -1
  507. package/dist/shared.js +46 -40
  508. package/dist/skills.d.ts +3 -0
  509. package/dist/skills.js +7 -5
  510. package/dist/stdin.js +3 -2
  511. package/dist/store/audit-event.d.ts +19 -0
  512. package/dist/store/audit-event.js +33 -0
  513. package/dist/store/candidates.d.ts +42 -0
  514. package/dist/store/candidates.js +152 -0
  515. package/dist/store/conflicts.d.ts +44 -0
  516. package/dist/store/conflicts.js +444 -0
  517. package/dist/store/delete-and-batch.d.ts +63 -0
  518. package/dist/store/delete-and-batch.js +310 -0
  519. package/dist/store/entry-reads.d.ts +92 -0
  520. package/dist/store/entry-reads.js +255 -0
  521. package/dist/store/entry-row.d.ts +67 -0
  522. package/dist/store/entry-row.js +208 -0
  523. package/dist/store/entry-writes.d.ts +46 -0
  524. package/dist/store/entry-writes.js +148 -0
  525. package/dist/store/handoffs.d.ts +26 -0
  526. package/dist/store/handoffs.js +184 -0
  527. package/dist/store/index-and-stats.d.ts +52 -0
  528. package/dist/store/index-and-stats.js +214 -0
  529. package/dist/store/markdown.d.ts +10 -0
  530. package/dist/store/markdown.js +108 -0
  531. package/dist/store/mirrors.d.ts +49 -0
  532. package/dist/store/mirrors.js +312 -0
  533. package/dist/store/open.d.ts +15 -0
  534. package/dist/store/open.js +223 -0
  535. package/dist/store/rows.d.ts +178 -0
  536. package/dist/store/rows.js +158 -0
  537. package/dist/store/search-rows.d.ts +86 -0
  538. package/dist/store/search-rows.js +254 -0
  539. package/dist/store/sessions.d.ts +83 -0
  540. package/dist/store/sessions.js +272 -0
  541. package/dist/store/summaries.d.ts +94 -0
  542. package/dist/store/summaries.js +377 -0
  543. package/dist/store/tenant-lookup.d.ts +12 -0
  544. package/dist/store/tenant-lookup.js +16 -0
  545. package/dist/store-cards.js +2 -1
  546. package/dist/summary-dirty.d.ts +4 -0
  547. package/dist/summary-dirty.js +32 -0
  548. package/dist/support-bundle.js +4 -3
  549. package/dist/tenant.js +2 -2
  550. package/dist/token-ledger.js +1 -0
  551. package/dist/tokenize.d.ts +2 -0
  552. package/dist/tokenize.js +16 -0
  553. package/dist/transcript-tail.d.ts +7 -0
  554. package/dist/transcript-tail.js +48 -0
  555. package/dist/vector-store.d.ts +27 -0
  556. package/dist/vector-store.js +210 -0
  557. package/dist/version.d.ts +2 -2
  558. package/dist/version.js +2 -2
  559. package/dist/working-memory.js +1 -1
  560. package/dist/yaml.js +36 -11
  561. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  566. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  570. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  571. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  572. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  573. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  574. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  575. package/dist-ui/index.html +3 -25
  576. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  577. package/extensions/openclaw-plugin/package.json +1 -1
  578. package/openclaw.plugin.json +1 -1
  579. package/package.json +2 -1
  580. package/dist/capture.d.ts +0 -155
  581. package/dist/capture.js +0 -1293
  582. package/dist/consolidate.d.ts +0 -58
  583. package/dist/consolidate.js +0 -1123
  584. package/dist/graph.d.ts +0 -245
  585. package/dist/hooks.d.ts +0 -208
  586. package/dist/hooks.js +0 -1073
  587. package/dist/importers.js +0 -897
  588. package/dist/predictions.js +0 -620
  589. package/dist/search.d.ts +0 -320
  590. package/dist/search.js +0 -968
  591. package/dist/store.d.ts +0 -744
  592. package/dist/store.js +0 -3372
  593. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  594. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  595. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  596. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,634 @@
1
+ // Read path: recall (sync) and retrieve (async, adds the vector arm).
2
+ import { envRequireSessionScopedFreshTail } from '../env.js';
3
+ import { openHippoDb, closeHippoDb } from '../db.js';
4
+ import { DEFAULT_SEARCH_CANDIDATE_LIMIT } from '../store/rows.js';
5
+ import { strengthenRetrieved } from '../store/entry-writes.js';
6
+ import { isRecallBoostAblated } from '../ablation.js';
7
+ import { loadEntriesByIds, loadFreshRawMemories } from '../store/entry-reads.js';
8
+ import { loadRecallSearchEntries, recallScopeFilter } from '../store/search-rows.js';
9
+ import { loadActiveTaskSnapshot, listSessionEvents } from '../store/sessions.js';
10
+ import { loadLatestHandoff } from '../store/handoffs.js';
11
+ import { estimateTokens } from '../token-ledger.js';
12
+ import { formatHandoffEvidenceLine } from '../handoff.js';
13
+ import { appendAuditEvent, auditQueryFields } from '../audit.js';
14
+ import { writeRecallTrace, writeRecallTraceAtRoot } from '../recall-trace.js';
15
+ import { applyGoalStackBoost } from '../goals.js';
16
+ import { hybridSearch } from '../search/hybrid.js';
17
+ import { physicsSearch } from '../search/physics-search.js';
18
+ import { churnStaleFactor } from '../search/boosts.js';
19
+ import { compareEntryIdentity } from '../compare.js';
20
+ import { dropHeldCopies, duplicateKey, storedTextKeys } from '../same-text.js';
21
+ import { loadConfig } from '../config.js';
22
+ import { computePlanningFallacyOutput } from '../predictions/planning-fallacy.js';
23
+ import { detectAnchoring, hashQueryText, biasHintEnabled } from '../recall-history.js';
24
+ import { detectAvailabilityBias } from '../availability.js';
25
+ import { passesScopeFilterForRecall, assertScopeRequestAllowed, isRestrictedScope } from '../recall-scope.js';
26
+ import { RecallContractError } from './types.js';
27
+ /**
28
+ * Shared construction helper for `RecallSuppressionSummary`. Used by
29
+ * `api.recall`, `cmdRecall`, and the MCP `hippo_recall` handler so all three
30
+ * pipelines produce the same shape without duplicating field-construction
31
+ * logic. Pass-through identity today; kept as a helper so future field
32
+ * additions (B4 interference counter wiring, etc.) land at one site.
33
+ */
34
+ export function buildSuppressionSummary(counts) {
35
+ return {
36
+ totalCandidates: counts.totalCandidates,
37
+ droppedPreRank: counts.droppedPreRank,
38
+ droppedByBudget: counts.droppedByBudget,
39
+ summarySubstitutionsAdded: counts.summarySubstitutionsAdded,
40
+ freshTailAdded: counts.freshTailAdded,
41
+ suppressedByInterference: counts.suppressedByInterference,
42
+ };
43
+ }
44
+ /**
45
+ * Domain-level recall. Loads BM25-ranked candidates from SQLite scoped to
46
+ * `ctx.tenantId` and keeps that order whatever `mode` says; `retrieve` is the
47
+ * mode-aware, strengthening variant the HTTP route uses.
48
+ *
49
+ * **api.recall does NOT mutate `index.last_retrieval_ids`** (v1.11.5 contract
50
+ * lock). The CLI `cmdRecall` (cli.ts) writes `last_retrieval_ids` because the
51
+ * CLI is interactive (user is about to run `hippo outcome --good`). SDK callers
52
+ * are programmatic: they either pass explicit ids to `api.outcome` or call
53
+ * `api.getContext` first for the context-then-outcome workflow (getContext
54
+ * DOES write `last_retrieval_ids`). Adding the side-effect here would change
55
+ * `api.recall` from a pure read into a read+write, breaking SDK callers who
56
+ * batch recall calls in a row. Locked by
57
+ * `tests/api-recall-no-side-effects.test.ts`.
58
+ */
59
+ export function recall(ctx, opts) {
60
+ // A member key may not unlock a private or quarantined scope by naming it.
61
+ assertScopeRequestAllowed(ctx.actor, opts.scope);
62
+ const windowSize = recallWindowSize(opts);
63
+ return recallFrom(ctx, opts, windowSize, loadRecallSearchEntries(ctx.hippoRoot, opts.query, windowSize, ctx.tenantId, opts.scope, 'exact', false));
64
+ }
65
+ /** Mode-aware recall that strengthens each returned row; never writes last_retrieval_ids (v1.11.5 lock). */
66
+ export async function retrieve(ctx, opts) {
67
+ assertScopeRequestAllowed(ctx.actor, opts.scope);
68
+ const windowSize = recallWindowSize(opts);
69
+ if (opts.showRanked)
70
+ return retrieveFromStore(ctx, opts, windowSize, opts.showRanked);
71
+ let candidates = loadRecallSearchEntries(ctx.hippoRoot, opts.query, windowSize, ctx.tenantId, opts.scope, 'exact', false);
72
+ if (opts.mode === 'hybrid' || opts.mode === 'physics') {
73
+ const searchOpts = { budget: Infinity, hippoRoot: ctx.hippoRoot, scope: opts.scope ?? null, vectorCandidates: recallVectorSpec(ctx, opts) };
74
+ const ranked = opts.mode === 'physics'
75
+ ? await physicsSearch(opts.query, candidates, { ...searchOpts, physicsConfig: loadConfig(ctx.hippoRoot).physics })
76
+ : await hybridSearch(opts.query, candidates, searchOpts);
77
+ const rankedIds = new Set(ranked.map((r) => r.entry.id));
78
+ candidates = [...ranked.map((r) => r.entry), ...candidates.filter((e) => !rankedIds.has(e.id))];
79
+ }
80
+ const result = recallFrom(ctx, opts, windowSize, candidates);
81
+ strengthenRetrieved(ctx.hippoRoot, result.results.map((r) => r.id), { tenantId: ctx.tenantId, recallBoostAblated: isRecallBoostAblated() });
82
+ return result;
83
+ }
84
+ /** api.retrieve's vector arm: the recall load's exact-scope rule, current rows only. */
85
+ function recallVectorSpec(ctx, opts) {
86
+ return {
87
+ tenantId: ctx.tenantId,
88
+ scope: recallScopeFilter(opts.scope, 'exact'),
89
+ includeSuperseded: false,
90
+ admit: (e) => passesScopeFilterForRecall(e.scope ?? null, opts.scope),
91
+ };
92
+ }
93
+ // Tag, pin and recency boosts can lift a row from deep in the BM25 order, so MCP ranks a wide lexical window.
94
+ const SHOW_RANKED_LEXICAL_WINDOW = 1000;
95
+ /** `retrieve` under `showRanked`: physics when `mode` says so, hybrid otherwise, over a wide lexical window plus the nearest vectors. */
96
+ async function retrieveFromStore(ctx, opts, windowSize, show) {
97
+ const loaded = loadRecallSearchEntries(ctx.hippoRoot, opts.query, Math.max(windowSize, SHOW_RANKED_LEXICAL_WINDOW), ctx.tenantId, opts.scope, 'exact', false);
98
+ const pool = loaded.filter((e) => passesScopeFilterForRecall(e.scope ?? null, opts.scope));
99
+ // No scope option: the scope boost follows HIPPO_SCOPE and the skill env, as MCP recall always ranked.
100
+ const searchOpts = { budget: Infinity, hippoRoot: ctx.hippoRoot, vectorCandidates: recallVectorSpec(ctx, opts) };
101
+ let ranked = opts.mode === 'physics'
102
+ ? await physicsSearch(opts.query, pool, { ...searchOpts, physicsConfig: loadConfig(ctx.hippoRoot).physics })
103
+ : await hybridSearch(opts.query, pool, searchOpts);
104
+ if (opts.sessionId && !opts.goalTag) {
105
+ const db = openHippoDb(ctx.hippoRoot);
106
+ try {
107
+ ranked = applyGoalStackBoost(db, ranked, { sessionId: opts.sessionId, tenantId: ctx.tenantId, limit: ranked.length });
108
+ }
109
+ finally {
110
+ closeHippoDb(db);
111
+ }
112
+ }
113
+ const window = ranked.slice(0, windowSize).map((r) => r.entry);
114
+ const result = recallFrom(ctx, { ...opts, suppressRecallTrace: true }, windowSize, window);
115
+ // Rows the vector arm added count as candidates too.
116
+ const inPool = new Set(pool.map((e) => e.id));
117
+ const candidates = [...pool, ...ranked.map((r) => r.entry).filter((e) => !inPool.has(e.id))];
118
+ const shown = show({ ranked, pool: candidates, droppedByScope: loaded.length - pool.length }, result);
119
+ strengthenRetrieved(ctx.hippoRoot, shown, { tenantId: ctx.tenantId, recallBoostAblated: isRecallBoostAblated() });
120
+ if (!opts.suppressRecallTrace) {
121
+ const scores = new Map(ranked.map((r) => [r.entry.id, r.score]));
122
+ writeRecallTraceAtRoot(ctx.hippoRoot, {
123
+ tenantId: ctx.tenantId,
124
+ sessionId: opts.sessionId ?? null,
125
+ pipeline: 'mcp',
126
+ query: opts.query,
127
+ results: shown.map((id) => ({ memoryId: id, score: scores.get(id) ?? 0 })),
128
+ });
129
+ }
130
+ return result;
131
+ }
132
+ /** Contract preflight: throws before any store-touching work. */
133
+ function recallWindowSize(opts) {
134
+ // F5 (v1.6.5) preflight — codex P1: original guard fired AFTER
135
+ // loadSearchEntries (which runs initStore, migrating legacy state on first
136
+ // call). For a true contract preflight we want the throw before any
137
+ // store-touching work. Single check here; the consumer site at
138
+ // `if (freshTailCount > 0)` does NOT re-validate (would be a no-op).
139
+ const freshTailCountPreflight = opts.freshTailCount ?? 0;
140
+ if (freshTailCountPreflight > 0 &&
141
+ !opts.freshTailSessionId &&
142
+ envRequireSessionScopedFreshTail()) {
143
+ throw new RecallContractError('fresh_tail_requires_session_id', 'fresh-tail requires a session id when HIPPO_REQUIRE_SESSION_SCOPED_FRESH_TAIL=1; ' +
144
+ 'pass opts.freshTailSessionId or unset the env to allow tenant-wide fresh-tail.');
145
+ }
146
+ // F3 (v1.7.0): scorerWindow opt-in. When undefined (default),
147
+ // loadSearchEntries uses its own store-internal default — this
148
+ // preserves every pre-v1.7.0 caller's behaviour bit-for-bit (codex
149
+ // mk2-pass P0-1: defaulting to `limit` would have shrunk the
150
+ // candidate pool and killed overflow summaries).
151
+ // DEFAULT_SEARCH_CANDIDATE_LIMIT is imported from store.ts so the two
152
+ // values cannot drift (codex diff-pass P1 #3).
153
+ // Validate the input — codex diff-pass P1 #1 caught that scorerWindow=0
154
+ // would route through FTS/LIKE LIMIT 0 and then fall through to an
155
+ // uncapped full-store fallback. Reject non-positive / non-finite values.
156
+ if (opts.scorerWindow !== undefined) {
157
+ if (!Number.isFinite(opts.scorerWindow) ||
158
+ !Number.isInteger(opts.scorerWindow) ||
159
+ opts.scorerWindow < 1) {
160
+ throw new RecallContractError('invalid_scorer_window', `scorerWindow must be a positive integer; got ${opts.scorerWindow}`);
161
+ }
162
+ }
163
+ return opts.scorerWindow ?? DEFAULT_SEARCH_CANDIDATE_LIMIT;
164
+ }
165
+ function recallFrom(ctx, opts, windowSize, all) {
166
+ const limit = opts.limit ?? 10;
167
+ // v1.7.1 — root-cause fix for the `unknown:legacy` leak. Scope predicate
168
+ // is now pushed into `loadSearchRows` SQL via `loadRecallSearchEntries`.
169
+ // - opts.scope undefined / '': SQL excludes `unknown:legacy`.
170
+ // - opts.scope non-empty: SQL exact-matches m.scope = opts.scope.
171
+ // Tenant predicate still runs first, so a tenant-mismatched scope cannot
172
+ // surface another tenant's row even when both share the same scope string.
173
+ //
174
+ // **CALLER CONTRACT:** any future recall-mode loader MUST go through
175
+ // `loadRecallSearchEntries` (or invoke the SQL scope predicate equivalently).
176
+ // Calling `loadSearchEntries` from this code path re-introduces the v1.6.5
177
+ // codex-flagged leak. See `passesScopeFilterForRecall` in this file for
178
+ // the canonical recall-side scope rule (kept in sync with the SQL clause
179
+ // in loadSearchRows).
180
+ //
181
+ // Also fixes a latent code smell: pre-v1.7.1 passed `opts.scorerWindow`
182
+ // (raw, possibly undefined) where `windowSize` was intended.
183
+ // v1.12.13 / C5 — WYSIATI counters. Declared BEFORE the load step so the
184
+ // assignments at the existing filter sites (load / scope-filter / limit-
185
+ // slice / substitution / fresh-tail) are after declaration. The return at
186
+ // end-of-function reads them via buildSuppressionSummary.
187
+ let totalCandidatesCount = 0;
188
+ let droppedPreRankCount = 0;
189
+ let droppedByBudgetCount = 0;
190
+ let summarySubstitutionsCount = 0;
191
+ let freshTailAddedCount = 0;
192
+ // v1.12.13 / C5 — WYSIATI totalCandidates counter (post tenant + SQL scope
193
+ // predicate, pre JS scope filter).
194
+ totalCandidatesCount = all.length;
195
+ const current = all.filter((e) => !e.superseded_by);
196
+ let entries;
197
+ if (opts.scope !== undefined && opts.scope !== '') {
198
+ // SQL already exact-matched in loadRecallSearchEntries; keep the JS
199
+ // filter as defense-in-depth so a future SQL-clause regression cannot
200
+ // silently surface cross-scope rows.
201
+ entries = current.filter((e) => e.scope === opts.scope);
202
+ }
203
+ else {
204
+ // SQL already excluded `unknown:legacy` AND (v1.25.0) pre-filtered
205
+ // ':private:' scopes with a conservative LIKE before the candidate
206
+ // window, so private rows can no longer starve admitted rows out of the
207
+ // LIMIT (codex review-stage P2). This JS filter stays as the exact
208
+ // anchored `<source>:private:*` rule (v1.2.1 generalization) and
209
+ // defense-in-depth: connector authors cannot silently surface private
210
+ // rows to no-scope callers even if the SQL clause regresses.
211
+ entries = current.filter((e) => !isRestrictedScope(e.scope ?? null));
212
+ }
213
+ // v1.12.13 / C5 — WYSIATI dropped_pre_rank counter (JS scope filter drops
214
+ // for api.recall; cmdRecall pipeline rolls --outcome/--layer/--as-of/etc.
215
+ // into the same field per the plan's Task 3 mapping table).
216
+ droppedPreRankCount = all.length - entries.length;
217
+ entries = entries
218
+ .map((e, i) => ({ e, s: (1 - i / entries.length) * churnStaleFactor(e) }))
219
+ .sort((a, b) => b.s - a.s)
220
+ .map((r) => r.e);
221
+ // BM25 ordering already comes from loadRecallSearchEntries; cap to `limit`.
222
+ // Score is a placeholder — the physics/hybrid scorers in src/search.ts
223
+ // produce richer breakdowns and will replace this when wired up.
224
+ let baseSlice = entries.slice(0, limit);
225
+ // v1.12.13 / C5 — WYSIATI dropped_by_budget counter (candidates loaded but
226
+ // excluded by the final limit slice).
227
+ droppedByBudgetCount = entries.length - baseSlice.length;
228
+ // v1.7.4 -- single db handle for the goal-stack boost AND the audit-event
229
+ // emit below (codex P1: do not open a second short-lived handle for the
230
+ // appendAuditEvent call). The handle is closed in the matching `finally`
231
+ // immediately above the continuity block.
232
+ const db = openHippoDb(ctx.hippoRoot);
233
+ // v1.7.4 -- declared outside the try so the return statement (which lives
234
+ // outside, after the continuity block) can read the final values.
235
+ let rankedOut = [];
236
+ let tokensOut = 0;
237
+ let totalOut = 0;
238
+ // v1.7.4 -- dlPFC goal-stack boost on the PRIMARY band only. Appendix paths
239
+ // (fresh-tail, summary substitutions) are appended AFTER and keep their
240
+ // semantically-special placement.
241
+ let baseScored = baseSlice.map((entry, idx) => ({
242
+ entry,
243
+ score: Math.max(0, 1 - idx / Math.max(1, limit)),
244
+ }));
245
+ // A7 recall-trace: separate side-channel accumulator, allocated ONLY under
246
+ // explain. applyGoalStackBoost writes goal-boost steps here keyed by entry
247
+ // id; the baseRanked map reads it. When !explain it stays undefined and is
248
+ // never passed → the helper's default-path math is byte-identical.
249
+ const explainTrace = opts.explain ? new Map() : undefined;
250
+ try {
251
+ if (opts.sessionId && !opts.goalTag) {
252
+ baseScored = applyGoalStackBoost(db, baseScored, {
253
+ sessionId: opts.sessionId,
254
+ tenantId: ctx.tenantId,
255
+ limit,
256
+ // trace is optional on applyGoalStackBoost; explicitly passing
257
+ // undefined when !explain is identical to omitting the key.
258
+ trace: explainTrace,
259
+ });
260
+ baseSlice = baseScored.map((r) => r.entry);
261
+ }
262
+ // v1.5.0 DAG-aware substitution (Phase 1, Task 2). When entries overflow the
263
+ // limit and ≥2 of them share a level-2 parent summary, append the parent
264
+ // summary so the user sees a compact pointer to the dropped detail. Capped
265
+ // at ceil(limit * 0.3) substitutions so a runaway DAG can't expand results.
266
+ // Each substituted summary is tenant-scoped via loadEntriesByIds and
267
+ // re-checked against the active scope filter (default-deny on private).
268
+ // Drill-down (Task 3) reverses substitution: caller passes substitutedFor[]
269
+ // ids back through `drillDown` to recover the children.
270
+ const summarizeOverflow = opts.summarizeOverflow ?? true;
271
+ let substituted = [];
272
+ if (summarizeOverflow && entries.length > limit) {
273
+ const overflow = entries.slice(limit);
274
+ const baseIds = new Set(baseSlice.map((e) => e.id));
275
+ const overflowByParent = new Map();
276
+ for (const e of overflow) {
277
+ const parentId = e.dag_parent_id;
278
+ if (!parentId)
279
+ continue;
280
+ if ((e.dag_level ?? 0) > 1)
281
+ continue;
282
+ const list = overflowByParent.get(parentId) ?? [];
283
+ list.push(e);
284
+ overflowByParent.set(parentId, list);
285
+ }
286
+ const eligibleParentIds = Array.from(overflowByParent.keys()).filter((pid) => (overflowByParent.get(pid)?.length ?? 0) >= 2 && !baseIds.has(pid));
287
+ if (eligibleParentIds.length > 0) {
288
+ const parents = loadEntriesByIds(ctx.hippoRoot, eligibleParentIds, ctx.tenantId);
289
+ const eligibleParents = parents.filter((p) => (p.dag_level ?? 0) === 2 && !p.superseded_by && passesScopeFilterForRecall(p.scope ?? null, opts.scope));
290
+ const maxSub = Math.max(1, Math.ceil(limit * 0.3));
291
+ // Order parents by overflow count descending so the most
292
+ // information-dense substitutions come first. Overflow count is the
293
+ // true primary key (unchanged); compareEntryIdentity is only a TAIL
294
+ // for the case two parents overflow the same number of children —
295
+ // without it that tie fell to SQLite scan order / loadEntriesByIds
296
+ // batch order (T2, deterministic tie keys).
297
+ eligibleParents.sort((a, b) => {
298
+ const ac = overflowByParent.get(a.id)?.length ?? 0;
299
+ const bc = overflowByParent.get(b.id)?.length ?? 0;
300
+ return bc !== ac ? bc - ac : compareEntryIdentity(a, b);
301
+ });
302
+ substituted = eligibleParents.slice(0, maxSub).map((p) => ({
303
+ entry: p,
304
+ childIds: (overflowByParent.get(p.id) ?? []).map((e) => e.id),
305
+ }));
306
+ }
307
+ }
308
+ if (!opts.keepHeldCopies) {
309
+ const shownIds = new Set(dropHeldCopies([...baseScored.map((r) => r.entry), ...substituted.map((s) => s.entry)], (e) => e).map((e) => e.id));
310
+ droppedPreRankCount += baseScored.filter((r) => !shownIds.has(r.entry.id)).length;
311
+ baseScored = baseScored.filter((r) => shownIds.has(r.entry.id));
312
+ baseSlice = baseScored.map((r) => r.entry);
313
+ substituted = substituted.filter((s) => shownIds.has(s.entry.id));
314
+ }
315
+ // v1.12.13 / C5 — WYSIATI summary_substitutions_added counter.
316
+ summarySubstitutionsCount = substituted.length;
317
+ // v1.7.4 -- baseScored carries the (possibly boosted) per-row scores. When
318
+ // the goal-stack boost did not run, scores are identical to the original
319
+ // positional placeholder; when it did run, scores reflect the boost AND the
320
+ // rows are in the boosted order (helper sort()).
321
+ const baseRanked = baseScored.map((r) => {
322
+ const item = {
323
+ id: r.entry.id,
324
+ content: r.entry.content,
325
+ score: r.score,
326
+ layer: r.entry.layer,
327
+ strength: r.entry.strength,
328
+ };
329
+ // A7 recall-trace: under explain, every api band carries rerankPipeline:'api';
330
+ // only baseRanked passes through the goal-boost helper, so only it can carry
331
+ // a step (and only for rows that actually matched an active goal).
332
+ if (opts.explain) {
333
+ item.rerankPipeline = 'api';
334
+ const step = explainTrace?.get(r.entry.id);
335
+ if (step)
336
+ item.rerankTrace = [step];
337
+ }
338
+ return item;
339
+ });
340
+ // Substituted summaries land at the end with score = 0.5 (mid-rank), so
341
+ // they don't outrank top-N strong matches but stay above lowest-rank
342
+ // leaves on the consumer side. Caller sorts/filters as it sees fit.
343
+ const summaryRanked = substituted.map((s) => {
344
+ const item = {
345
+ id: s.entry.id,
346
+ content: s.entry.content,
347
+ score: 0.5,
348
+ layer: s.entry.layer,
349
+ strength: s.entry.strength,
350
+ isSummary: true,
351
+ substitutedFor: s.childIds,
352
+ descendantCount: s.entry.descendant_count ?? s.childIds.length,
353
+ };
354
+ // A7 recall-trace: summary band runs no re-ranking, but under explain it
355
+ // still carries the pipeline marker (no steps). Absent when !explain.
356
+ if (opts.explain)
357
+ item.rerankPipeline = 'api';
358
+ return item;
359
+ });
360
+ // v1.5.2 fresh-tail. Surface the last N kind='raw' rows so an agent's
361
+ // "what did I just see" recall path always covers the recent window even
362
+ // when the query terms don't match. Tenant + scope filtered.
363
+ //
364
+ // Dual-membership semantics: `loadSearchEntries` returns all tenant-scoped
365
+ // rows scored by BM25 (even rows with no token overlap can surface at
366
+ // score≈0), so a row in the recent window often ALSO appears as a BM25
367
+ // hit. We don't duplicate. Instead:
368
+ // 1. Mark any baseRanked entry that's in the recent set with isFreshTail.
369
+ // 2. Prepend genuinely-new recent rows (not in BM25 hits or summaries).
370
+ // Net: every recent row carries `isFreshTail=true`, exactly once.
371
+ const freshTailCount = opts.freshTailCount ?? 0;
372
+ const freshRanked = [];
373
+ if (freshTailCount > 0) {
374
+ // F5 contract guard fires at recall() preflight (top of function).
375
+ // No re-check needed here — by the time we reach this block the
376
+ // env/session policy has already been validated.
377
+ const recent = loadFreshRawMemories(ctx.hippoRoot, freshTailCount, ctx.tenantId, opts.freshTailSessionId);
378
+ const recentScoped = recent.filter((m) => passesScopeFilterForRecall(m.scope ?? null, opts.scope));
379
+ const recentIdSet = new Set(recentScoped.map((m) => m.id));
380
+ for (const r of baseRanked) {
381
+ if (recentIdSet.has(r.id))
382
+ r.isFreshTail = true;
383
+ }
384
+ const seenIds = new Set([
385
+ ...baseRanked.map((r) => r.id),
386
+ ...summaryRanked.map((r) => r.id),
387
+ ]);
388
+ const shownKeys = storedTextKeys(opts.keepHeldCopies ? [] : [...baseSlice, ...substituted.map((s) => s.entry)]);
389
+ for (const m of recentScoped) {
390
+ if (seenIds.has(m.id) || shownKeys.has(duplicateKey(m.content)))
391
+ continue;
392
+ shownKeys.add(duplicateKey(m.content));
393
+ const item = {
394
+ id: m.id,
395
+ content: m.content,
396
+ score: 1.0,
397
+ layer: m.layer,
398
+ strength: m.strength,
399
+ isFreshTail: true,
400
+ };
401
+ // A7 recall-trace: fresh-tail band runs no re-ranking; under explain
402
+ // it carries the pipeline marker (no steps). Absent when !explain.
403
+ if (opts.explain)
404
+ item.rerankPipeline = 'api';
405
+ freshRanked.push(item);
406
+ seenIds.add(m.id);
407
+ }
408
+ }
409
+ // v1.12.13 / C5 — WYSIATI fresh_tail_added counter. Captures the new rows
410
+ // prepended (NOT rows already in baseRanked that got tagged isFreshTail).
411
+ freshTailAddedCount = freshRanked.length;
412
+ rankedOut = [...freshRanked, ...baseRanked, ...summaryRanked];
413
+ tokensOut = rankedOut.reduce((acc, r) => acc + estimateTokens(r.content), 0);
414
+ totalOut = entries.length;
415
+ // TODO(a1-task-4): emit via the shared audit hook in store.ts so we don't
416
+ // double-emit. Recall does not currently write through writeEntry, so no
417
+ // duplicate exists today, but we keep the same shape for symmetry.
418
+ // v1.7.4: reuse the `db` handle opened above for the goal-stack boost --
419
+ // single open/close spans both side effects.
420
+ // GDPR Path A: store a sha256 hash (16 hex chars) of the query text
421
+ // instead of the truncated query itself. If a caller queries with content
422
+ // that matches an archived (RTBF) memory, the original text must not
423
+ // persist in audit_log. query_length is preserved for debugging
424
+ // long-prompt patterns and compliance metrics.
425
+ appendAuditEvent(db, {
426
+ tenantId: ctx.tenantId,
427
+ actor: ctx.actor.subject,
428
+ op: 'recall',
429
+ metadata: {
430
+ ...auditQueryFields(opts.query),
431
+ results: rankedOut.length,
432
+ },
433
+ });
434
+ // LC1 (docs/plans/2026-08-02-lc1-recall-trace-persistence.md): trace the
435
+ // returned ids+ranks+scores next to the audit emit, on the SAME open
436
+ // handle. v1.11.5 contract lock holds — api.recall does NOT write
437
+ // last_trace_id (tests/api-recall-no-side-effects.test.ts); a trace INSERT
438
+ // is the same observability class as the audit row it sits beside, not
439
+ // retrieval state. F2 fix: suppressed when the caller traces its own,
440
+ // different result set (retrieve under showRanked traces the shown list as
441
+ // 'mcp'). Fail-soft internally; never throws.
442
+ if (!opts.suppressRecallTrace) {
443
+ writeRecallTrace(db, {
444
+ tenantId: ctx.tenantId,
445
+ sessionId: opts.sessionId ?? null,
446
+ pipeline: 'api',
447
+ query: opts.query,
448
+ explainMode: opts.explain === true,
449
+ results: rankedOut.map((r) => ({
450
+ memoryId: r.id,
451
+ score: r.score,
452
+ rerankSteps: r.rerankTrace,
453
+ })),
454
+ });
455
+ }
456
+ }
457
+ finally {
458
+ closeHippoDb(db);
459
+ }
460
+ let continuity;
461
+ let continuityTokens;
462
+ if (opts.includeContinuity) {
463
+ const snapshot = loadActiveTaskSnapshot(ctx.hippoRoot, ctx.tenantId);
464
+ // No active snapshot = no anchor = no handoff/events. Avoids resurrecting
465
+ // a stale handoff from a deleted/completed session.
466
+ const sessionId = snapshot?.session_id ?? undefined;
467
+ const sessionHandoff = sessionId
468
+ ? loadLatestHandoff(ctx.hippoRoot, ctx.tenantId, sessionId)
469
+ : null;
470
+ const recentSessionEvents = sessionId
471
+ ? listSessionEvents(ctx.hippoRoot, ctx.tenantId, { session_id: sessionId, limit: 5 })
472
+ : [];
473
+ // Scope filtering on continuity. Mirrors the memory-recall path:
474
+ // - opts.scope set: EXACT match required (no cross-scope leakage)
475
+ // - opts.scope unset: default-deny on ANY `<source>:private:*` AND on
476
+ // legacy 'unknown:legacy' rows quarantined by the v23 migration.
477
+ // Public and null scopes pass through.
478
+ // v1.1.0 wrongly wrote this as `opts.scope || isPublic`, which allowed
479
+ // ANY explicit scope to see ALL continuity rows. v1.2 closed the latent
480
+ // leak. v1.2.1 generalizes the private check from slack-only to any
481
+ // source so v1.3 GitHub (and future Jira/Linear/etc.) cannot leak.
482
+ const rowScope = (r) => r?.scope ?? null;
483
+ // v1.2: TaskSnapshot / SessionHandoff / SessionEvent now carry scope; the
484
+ // wrapper just normalizes null vs undefined. W1: was its own copy of
485
+ // passesScopeFilterForRecall (cloned 3x); calls the shared helper now.
486
+ const filteredSnapshot = snapshot && passesScopeFilterForRecall(rowScope(snapshot), opts.scope) ? snapshot : null;
487
+ const filteredHandoff = sessionHandoff && passesScopeFilterForRecall(rowScope(sessionHandoff), opts.scope) ? sessionHandoff : null;
488
+ const filteredEvents = recentSessionEvents.filter((e) => passesScopeFilterForRecall(rowScope(e), opts.scope));
489
+ continuity = {
490
+ activeSnapshot: filteredSnapshot,
491
+ sessionHandoff: filteredHandoff,
492
+ recentSessionEvents: filteredEvents,
493
+ };
494
+ const tokenize = (s) => s ? estimateTokens(s) : 0;
495
+ continuityTokens =
496
+ tokenize(filteredSnapshot?.task) +
497
+ tokenize(filteredSnapshot?.summary) +
498
+ tokenize(filteredSnapshot?.next_step) +
499
+ tokenize(filteredHandoff?.summary) +
500
+ tokenize(filteredHandoff?.nextAction) +
501
+ (filteredHandoff?.artifacts ?? []).reduce((acc, a) => acc + tokenize(a), 0) +
502
+ (filteredHandoff?.constraints ?? []).reduce((acc, c) => acc + tokenize(c), 0) +
503
+ tokenize(filteredHandoff?.evidence ? formatHandoffEvidenceLine(filteredHandoff.evidence) : null) +
504
+ tokenize(filteredHandoff?.outcome) +
505
+ tokenize(filteredHandoff?.targetRuntime) +
506
+ tokenize(filteredHandoff?.cardId) +
507
+ filteredEvents.reduce((acc, e) => acc + tokenize(e.content), 0);
508
+ }
509
+ // v0.32 / J3.2 — auto-injection of reference-class baserate when the
510
+ // query carries a forward-prediction phrase AND the closest matching
511
+ // class has closed historical data. Pipeline-invariant (queryText-
512
+ // derived), so MCP and CLI both read this as the single source of
513
+ // truth instead of recomputing (unlike suppressionSummary which IS
514
+ // per-pipeline). opts.actor threads through to the inner
515
+ // computePredictionBaserate call so MCP/HTTP-originated hints attribute
516
+ // correctly instead of defaulting to 'cli'. Disabled by HIPPO_AUTODEBIAS=off.
517
+ // The hint and the no-class-match / tiebreak watching variant are mutually exclusive; both go out as optional fields.
518
+ const planningFallacyOutput = computePlanningFallacyOutput(ctx.hippoRoot, ctx.tenantId, opts.query, { actor: ctx.actor.subject });
519
+ const planningFallacyHint = planningFallacyOutput.hint ?? null;
520
+ const planningFallacyWatching = planningFallacyOutput.watching ?? null;
521
+ // v0.33 / J1 (v1.13.2) — recall-recurrence anchoring detection.
522
+ // Uses opts.recallHistory (caller-supplied snapshot) + this pipeline's
523
+ // own top-1 from rankedOut[0]. PURE read — does NOT mutate the snapshot
524
+ // or any caller-side Map. Disabled by HIPPO_ANCHORING=off (which gates
525
+ // even the detectAnchoring call so disabled tenants pay zero work on
526
+ // this surface). On CLI-routed call paths opts.recallHistory is
527
+ // undefined because cmdRecall computes its own hint separately; the
528
+ // detect call returns null and api.recall's anchoringHint stays absent.
529
+ let anchoringHint = null;
530
+ let suppressedByInterferenceCount = 0;
531
+ if (biasHintEnabled('anchoring') && opts.recallHistory) {
532
+ const queryHash = hashQueryText(opts.query);
533
+ const topMemoryId = rankedOut[0]?.id ?? null;
534
+ anchoringHint = detectAnchoring(opts.recallHistory, queryHash, topMemoryId);
535
+ if (anchoringHint?.reason === 'memory_dominance') {
536
+ suppressedByInterferenceCount = 1;
537
+ // Emit audit op for the memory-dominance detection.
538
+ const db = openHippoDb(ctx.hippoRoot);
539
+ try {
540
+ appendAuditEvent(db, {
541
+ tenantId: ctx.tenantId,
542
+ actor: ctx.actor.subject,
543
+ op: 'recall_anchor_detected_memory_dominance',
544
+ targetId: anchoringHint.memoryId,
545
+ metadata: {
546
+ memory_id: anchoringHint.memoryId,
547
+ query_count: anchoringHint.queryCount ?? null,
548
+ },
549
+ });
550
+ }
551
+ finally {
552
+ closeHippoDb(db);
553
+ }
554
+ }
555
+ else if (anchoringHint?.reason === 'query_repeat') {
556
+ const db = openHippoDb(ctx.hippoRoot);
557
+ try {
558
+ appendAuditEvent(db, {
559
+ tenantId: ctx.tenantId,
560
+ actor: ctx.actor.subject,
561
+ op: 'recall_anchor_detected_query_repeat',
562
+ targetId: anchoringHint.memoryId,
563
+ metadata: { memory_id: anchoringHint.memoryId },
564
+ });
565
+ }
566
+ finally {
567
+ closeHippoDb(db);
568
+ }
569
+ }
570
+ }
571
+ // v1.13.x / J2 — availability/recency-bias detection. PURE read: compares
572
+ // the age distribution of the returned top-K (baseSlice, the post-goal-boost
573
+ // slice) against the matched candidate pool it was drawn from (entries, the
574
+ // scope/private-FILTERED candidate set baseSlice is sliced from — NOT `all`,
575
+ // which still holds private/cross-scope rows the caller is not eligible to see
576
+ // and that could never enter the top-K; counting them would leak hidden pool
577
+ // shape and inflate the signal). Soft warning only — does NOT filter, reorder,
578
+ // or suppress. Disabled by HIPPO_AVAILABILITY=off (gates even the detect call
579
+ // so disabled tenants pay zero work). Suppressed via opts.suppressAvailabilityHint
580
+ // when the caller computes its own per-pipeline hint (MCP), mirroring the J1
581
+ // opts.recallHistory gate above so we never double-emit the audit op. Audit
582
+ // emission is pipeline-local, mirroring the J1 block above.
583
+ let availabilityHint = null;
584
+ if (biasHintEnabled('availability') && !opts.suppressAvailabilityHint) {
585
+ availabilityHint = detectAvailabilityBias({
586
+ topK: baseSlice.map((e) => ({ id: e.id, created: e.created })),
587
+ pool: entries.map((e) => ({ id: e.id, created: e.created })),
588
+ });
589
+ if (availabilityHint) {
590
+ const db = openHippoDb(ctx.hippoRoot);
591
+ try {
592
+ appendAuditEvent(db, {
593
+ tenantId: ctx.tenantId,
594
+ actor: ctx.actor.subject,
595
+ op: 'recall_availability_detected',
596
+ metadata: {
597
+ recent_fraction: availabilityHint.recentFraction,
598
+ older_passed_over: availabilityHint.olderCandidatesPassedOver,
599
+ returned_count: availabilityHint.returnedCount,
600
+ },
601
+ });
602
+ }
603
+ finally {
604
+ closeHippoDb(db);
605
+ }
606
+ }
607
+ }
608
+ const result = {
609
+ results: rankedOut,
610
+ total: totalOut,
611
+ tokens: tokensOut,
612
+ continuity,
613
+ continuityTokens,
614
+ windowSize,
615
+ suppressionSummary: buildSuppressionSummary({
616
+ totalCandidates: totalCandidatesCount,
617
+ droppedPreRank: droppedPreRankCount,
618
+ droppedByBudget: droppedByBudgetCount,
619
+ summarySubstitutionsAdded: summarySubstitutionsCount,
620
+ freshTailAdded: freshTailAddedCount,
621
+ suppressedByInterference: suppressedByInterferenceCount,
622
+ }),
623
+ };
624
+ if (planningFallacyHint)
625
+ result.planningFallacyHint = planningFallacyHint;
626
+ if (planningFallacyWatching)
627
+ result.planningFallacyWatching = planningFallacyWatching;
628
+ if (anchoringHint)
629
+ result.anchoringHint = anchoringHint;
630
+ if (availabilityHint)
631
+ result.availabilityHint = availabilityHint;
632
+ return result;
633
+ }
634
+ //# sourceMappingURL=recall.js.map
@@ -0,0 +1,35 @@
1
+ import type { DatabaseSyncLike } from '../db.js';
2
+ import { type MemoryKind } from '../memory.js';
3
+ import type { Context } from './types.js';
4
+ export interface RememberOpts {
5
+ content: string;
6
+ kind?: MemoryKind;
7
+ scope?: string;
8
+ owner?: string;
9
+ artifactRef?: string;
10
+ tags?: string[];
11
+ /**
12
+ * Optional hook invoked inside the same transaction as the underlying
13
+ * memories INSERT. Used by ingestion connectors (E1.3+) to stamp
14
+ * idempotency / cursor rows atomically with the memory row, so a crash
15
+ * mid-write cannot produce a memory without its corresponding side-effect
16
+ * log row (or vice versa). If the callback throws, the INSERT is rolled
17
+ * back and the error is rethrown.
18
+ */
19
+ afterWrite?: (db: DatabaseSyncLike, memoryId: string) => void;
20
+ /** CD5: connector-ingested content an agent doesn't control; gates detectInstruction. CLI/HTTP/MCP never set this. */
21
+ untrusted?: boolean;
22
+ }
23
+ export interface RememberResult {
24
+ id: string;
25
+ kind: MemoryKind;
26
+ tenantId: string;
27
+ /** Set only when untrusted content was flagged and quarantined instead of stored under its requested scope. */
28
+ quarantined?: {
29
+ reason: string;
30
+ };
31
+ /** Set only when the content held secret material: untrusted text had it redacted, typed text was stored as sent. */
32
+ warnings?: string[];
33
+ }
34
+ export declare function remember(ctx: Context, opts: RememberOpts): RememberResult;
35
+ //# sourceMappingURL=remember.d.ts.map