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,209 @@
1
+ /**
2
+ * Consolidation engine ("Sleep") for Hippo.
3
+ *
4
+ * Steps:
5
+ * 1. Decay pass - remove entries below strength threshold
6
+ * 2. Merge pass - find episodic entries with high text overlap, create semantic summaries
7
+ * 3. Stats tracking
8
+ */
9
+ import { evalNow } from '../ablation.js';
10
+ import { canAutoDelete } from '../memory.js';
11
+ import { loadAllEntries } from '../store/entry-reads.js';
12
+ import { batchWriteAndDelete, memoriesBackingObjects } from '../store/delete-and-batch.js';
13
+ import { appendConsolidationRun, loadSessionDecayContext, incrementSleepCount } from '../store/index-and-stats.js';
14
+ import { replaceDetectedConflicts } from '../store/conflicts.js';
15
+ import { openHippoDb, closeHippoDb } from '../db.js';
16
+ import { countExpiredDormant, purgeExpiredDormant } from '../dormant.js';
17
+ import { loadConfig } from '../config.js';
18
+ import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
19
+ import { migrateDefaultHalfLife, LEGACY_TYPED_HALF_LIFE } from '../half-life-migration.js';
20
+ import { log } from '../log.js';
21
+ import { decayPass } from './decay.js';
22
+ import { retireHeldTexts, mergePass } from './merge.js';
23
+ import { detectConflicts } from './conflicts.js';
24
+ import { lazyConsolidateDb, newConsolidationResult } from './run.js';
25
+ import { promoteSessionTraces, replayPass } from './traces.js';
26
+ import { llmPasses } from './llm-passes.js';
27
+ import { physicsPass } from './physics-pass.js';
28
+ /**
29
+ * Run a full consolidation pass.
30
+ */
31
+ export async function consolidate(hippoRoot, options = {}) {
32
+ const now = options.now ?? evalNow(); // honors HIPPO_FAKE_NOW (eval-only; see ablation.ts)
33
+ const dryRun = options.dryRun ?? false;
34
+ const result = newConsolidationResult(dryRun);
35
+ const halfLife = migrateHalfLives(hippoRoot, dryRun, result);
36
+ // L9: host-wide by design. Consolidation runs across all tenants in one
37
+ // pass — per-tenant filtering would create N consolidation runs per host
38
+ // with no cross-tenant dedup. The api.sleep audit row tags this with the
39
+ // admin synthetic actor; see api.ts:2050 for the rationale.
40
+ const all = loadAllEntries(hippoRoot);
41
+ if (dryRun)
42
+ for (const e of all)
43
+ e.half_life_days = halfLife.halfLives.get(e.id) ?? e.half_life_days;
44
+ const backingObjects = memoriesBackingObjects(hippoRoot);
45
+ // Retirable: auto-deletable (never pinned, raw or kept for good) and not backing a first-class object.
46
+ const retirable = (entry) => canAutoDelete(entry) && !backingObjects.has(entry.id);
47
+ const snapshot = new Map(structuredClone(all).map((e) => [e.id, e]));
48
+ // Load decay options from config + session context
49
+ const config = loadConfig(hippoRoot);
50
+ const sessionCtx = loadSessionDecayContext(hippoRoot);
51
+ const decayOpts = {
52
+ decayBasis: config.decayBasis,
53
+ avgSessionIntervalDays: sessionCtx.avgSessionIntervalDays,
54
+ sleepCount: sessionCtx.sleepCount,
55
+ };
56
+ const consolidateDb = lazyConsolidateDb(hippoRoot, dryRun);
57
+ const run = {
58
+ hippoRoot, now, dryRun, config, decayOpts, result, all, retirable,
59
+ getConsolidateDb: consolidateDb.get,
60
+ survivors: [],
61
+ // Collect all writes/deletes and batch them at the end
62
+ pendingWrites: [],
63
+ pendingDeletes: [],
64
+ pendingDormant: [],
65
+ };
66
+ const decay = decayPass(run);
67
+ let mergesSkippedRejected = 0;
68
+ try {
69
+ promoteSessionTraces(run);
70
+ replayPass(run);
71
+ await llmPasses(run, options.fetcher);
72
+ physicsPass(run);
73
+ retireHeldTexts(run);
74
+ mergesSkippedRejected = mergePass(run);
75
+ }
76
+ finally {
77
+ consolidateDb.close();
78
+ }
79
+ if (mergesSkippedRejected > 0) {
80
+ log.warn(`consolidate: skipped ${mergesSkippedRejected} merge(s) whose content matches a rejected value`);
81
+ }
82
+ flushPending(run, snapshot);
83
+ expireDormant(run);
84
+ if (!dryRun)
85
+ logRun(run, decay);
86
+ return result;
87
+ }
88
+ // A changed default half-life moves memories still on the old base first,
89
+ // so this pass decays them at the new one (src/half-life-migration.ts).
90
+ function migrateHalfLives(hippoRoot, dryRun, result) {
91
+ const halfLife = migrateDefaultHalfLife(hippoRoot, loadConfig(hippoRoot).defaultHalfLifeDays, { dryRun });
92
+ if (halfLife.rescaled > 0) {
93
+ result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.rescaled} memories from the ${halfLife.from}-day to the ${halfLife.to}-day half-life`);
94
+ }
95
+ if (halfLife.typed > 0) {
96
+ result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects from the ${LEGACY_TYPED_HALF_LIFE}-day to the ${halfLife.to}-day half-life`);
97
+ }
98
+ return halfLife;
99
+ }
100
+ function flushPending(run, snapshot) {
101
+ const { result, pendingDeletes, pendingDormant } = run;
102
+ result.removedIds = pendingDeletes;
103
+ // One transaction; the snapshot keeps what the DAG passes and other writers changed while sleep ran.
104
+ // Dormant moves ride in the same transaction (src/dormant.ts).
105
+ if (run.dryRun)
106
+ return;
107
+ const left = new Set(batchWriteAndDelete(run.hippoRoot, run.pendingWrites, pendingDeletes, { snapshot, dormant: pendingDormant }));
108
+ for (const id of [...pendingDeletes, ...pendingDormant.map((m) => m.entry.id)]) {
109
+ if (!left.has(id))
110
+ result.details.push(` ↩ ${id} not removed: pinned or already gone before sleep saved`);
111
+ }
112
+ result.removedIds = pendingDeletes.filter((id) => left.has(id));
113
+ result.removed = result.removedIds.length;
114
+ result.dormant = pendingDormant.filter((m) => left.has(m.entry.id)).length;
115
+ }
116
+ // Dormant retention: a dormant memory nobody restored within
117
+ // dormant.retentionDays is deleted for good (0 keeps them forever). Runs
118
+ // even when dormant.enabled is off, so turning it off still ages out what
119
+ // earlier sleeps kept.
120
+ function expireDormant(run) {
121
+ const { config, result, dryRun } = run;
122
+ if (!(config.dormant.retentionDays > 0))
123
+ return;
124
+ const cutoff = new Date(run.now.getTime() - config.dormant.retentionDays * 24 * 60 * 60 * 1000).toISOString();
125
+ const db = openHippoDb(run.hippoRoot);
126
+ try {
127
+ result.dormantExpired = dryRun ? countExpiredDormant(db, cutoff) : purgeExpiredDormant(db, cutoff);
128
+ }
129
+ finally {
130
+ closeHippoDb(db);
131
+ }
132
+ if (result.dormantExpired > 0) {
133
+ result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} older than ${config.dormant.retentionDays} days`);
134
+ }
135
+ }
136
+ // -------------------------------------------------------------------------
137
+ // 4. Log run
138
+ // -------------------------------------------------------------------------
139
+ function logRun(run, decay) {
140
+ const { hippoRoot, now, result } = run;
141
+ const detectedConflicts = detectConflicts(run.survivors, now, run.decayOpts, decay.rescuedIds);
142
+ replaceDetectedConflicts(hippoRoot, detectedConflicts, now.toISOString());
143
+ if (detectedConflicts.length > 0) {
144
+ result.details.push(` ⚠️ detected ${detectedConflicts.length} memory conflict${detectedConflicts.length === 1 ? '' : 's'}`);
145
+ }
146
+ appendConsolidationRun(hippoRoot, {
147
+ timestamp: now.toISOString(),
148
+ decayed: result.decayed,
149
+ merged: result.merged,
150
+ removed: result.removed,
151
+ });
152
+ incrementSleepCount(hippoRoot);
153
+ if (decay.rescuedEntries.length > 0)
154
+ auditRescues(run, decay);
155
+ }
156
+ // One audit row per rescue (attributability, D1). Written here, AFTER
157
+ // batchWriteAndDelete has committed this cycle's writes/deletes
158
+ // (and after conflict detection + run logging), not inline in the decay
159
+ // pass — same durability posture as api.ts's top-level 'consolidate'
160
+ // summary audit row (written only once the whole sleep has completed).
161
+ // Writing it earlier would assert rescues for a cycle whose effects
162
+ // never landed if a later phase threw. Real writes only — dry-run
163
+ // previews the decision (details line above) but persists nothing.
164
+ function auditRescues(run, { rescuedEntries, rankById }) {
165
+ const { result } = run;
166
+ try {
167
+ const auditDb = openHippoDb(run.hippoRoot);
168
+ try {
169
+ // Review-round F5: per-row try/catch, not one try/catch around the
170
+ // whole loop — a single failed appendAuditEvent must not silently
171
+ // drop every remaining row. Mirrors the physics pass's
172
+ // skipped-warning precedent: count losses, keep
173
+ // the overall fail-soft posture, tell the operator via details.
174
+ let auditFailures = 0;
175
+ for (const entry of rescuedEntries) {
176
+ try {
177
+ const rank = rankById.get(entry.id);
178
+ appendAuditEvent(auditDb, {
179
+ tenantId: entry.tenantId,
180
+ actor: 'sleep',
181
+ op: 'mv_rescue',
182
+ targetId: entry.id,
183
+ metadata: rank
184
+ ? { rank: rank.rank, totalNonPinned: rank.totalNonPinned, keepN: rank.keepN, score: rank.score }
185
+ : {},
186
+ });
187
+ }
188
+ catch (error) {
189
+ auditFailures++;
190
+ reportAuditWriteFailure('mv_rescue', String(error), entry.id);
191
+ }
192
+ }
193
+ if (auditFailures > 0) {
194
+ result.details.push(` ⚠️ memory-value: ${auditFailures} mv_rescue audit row${auditFailures === 1 ? '' : 's'} ` +
195
+ `failed to write (the rescue itself still landed)`);
196
+ }
197
+ }
198
+ finally {
199
+ closeHippoDb(auditDb);
200
+ }
201
+ }
202
+ catch {
203
+ // openHippoDb/closeHippoDb-level failure: audit must never crash a
204
+ // mutation (mirrors store.ts's audit() posture).
205
+ result.details.push(` ⚠️ memory-value: mv_rescue audit unavailable this cycle ` +
206
+ `(${rescuedEntries.length} rescue${rescuedEntries.length === 1 ? '' : 's'} not audited)`);
207
+ }
208
+ }
209
+ //# sourceMappingURL=sleep.js.map
@@ -0,0 +1,4 @@
1
+ import { type SleepRun } from './run.js';
2
+ export declare function promoteSessionTraces(run: SleepRun): void;
3
+ export declare function replayPass(run: SleepRun): void;
4
+ //# sourceMappingURL=traces.d.ts.map
@@ -0,0 +1,178 @@
1
+ import { isRecallBoostAblated } from '../ablation.js';
2
+ import { Layer, createMemory, markRetrieved } from '../memory.js';
3
+ import { findPromotableSessions, traceExistsForSession, listSessionEvents } from '../store/sessions.js';
4
+ import { rejectionDigest, findRejectedValue } from '../rejection.js';
5
+ import { sampleForReplay } from '../replay.js';
6
+ import { renderTraceContent } from '../trace.js';
7
+ import { resolveTenantId } from '../tenant.js';
8
+ import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
9
+ import { commonDerivationScope } from '../recall-scope.js';
10
+ import { log } from '../log.js';
11
+ import { REPLAY_COUNT_DEFAULT, isJsonString } from './run.js';
12
+ // -------------------------------------------------------------------------
13
+ // 1.4. Auto-promote complete sessions to traces
14
+ // -------------------------------------------------------------------------
15
+ //
16
+ // For each session within the configured window that has a `session_complete`
17
+ // event and no existing trace (idempotency via the source_session_id column),
18
+ // render the action sequence as markdown and persist a Layer.Trace memory.
19
+ // Traces inherit decay, search, replay, and physics from the base MemoryEntry.
20
+ export function promoteSessionTraces(run) {
21
+ const { result } = run;
22
+ if (run.dryRun || run.config.autoTraceCapture === false)
23
+ return;
24
+ let tracesSkippedRejected = 0;
25
+ const windowDays = run.config.autoTraceWindowDays ?? 7;
26
+ const sinceMs = run.now.getTime() - windowDays * 24 * 60 * 60 * 1000;
27
+ // Auto-trace currently runs in a single-tenant context (the env-resolved
28
+ // tenant for this process). Multi-tenant deployments that want
29
+ // consolidation across all tenants need a per-tenant loop layered on top
30
+ // of this — tracked in docs/plans/2026-05-02-continuity-tables-tenant-scope.md.
31
+ const consolidationTenant = resolveTenantId({});
32
+ const promotable = findPromotableSessions(run.hippoRoot, consolidationTenant, sinceMs);
33
+ for (const session of promotable) {
34
+ const built = sessionTrace(run, consolidationTenant, session.session_id);
35
+ if (!built)
36
+ continue;
37
+ const { trace, outcome } = built;
38
+ if (traceRejected(run, trace, session.session_id)) {
39
+ tracesSkippedRejected++;
40
+ continue;
41
+ }
42
+ run.pendingWrites.push(trace);
43
+ run.survivors.push(trace);
44
+ result.promotedTraces++;
45
+ result.details.push(` 🧬 promoted trace ${trace.id} from session ${session.session_id} (${outcome})`);
46
+ }
47
+ if (result.promotedTraces > 0) {
48
+ result.details.push(` 🧬 promoted ${result.promotedTraces} trace${result.promotedTraces === 1 ? '' : 's'} from completed session${result.promotedTraces === 1 ? '' : 's'}`);
49
+ }
50
+ if (tracesSkippedRejected > 0) {
51
+ log.warn(`consolidate: skipped ${tracesSkippedRejected} auto-promoted trace(s) whose content matches a rejected value`);
52
+ }
53
+ }
54
+ /** The trace a completed session renders to, or null when it already has one or cannot be promoted. */
55
+ function sessionTrace(run, consolidationTenant, sessionId) {
56
+ // Idempotency: skip if a trace for this session already exists.
57
+ if (traceExistsForSession(run.hippoRoot, consolidationTenant, sessionId))
58
+ return null;
59
+ const events = listSessionEvents(run.hippoRoot, consolidationTenant, {
60
+ session_id: sessionId,
61
+ limit: 1000,
62
+ });
63
+ // T7: a mixed-scope session would otherwise leak into one trace.
64
+ const sessionScope = commonDerivationScope(events.map((e) => e.scope));
65
+ if (!sessionScope.ok) {
66
+ run.result.tracesSkippedMixedScope++;
67
+ run.result.details.push(` ⏭ skipped session ${sessionId}: events span mixed scopes`);
68
+ return null;
69
+ }
70
+ const completeEvent = events.find((e) => e.event_type === 'session_complete');
71
+ if (!completeEvent)
72
+ return null; // defence-in-depth; findPromotableSessions filters already.
73
+ const outcomeRaw = completeEvent.content;
74
+ if (outcomeRaw !== 'success' && outcomeRaw !== 'failure' && outcomeRaw !== 'partial') {
75
+ // Malformed terminal event — skip rather than crash the whole sleep.
76
+ return null;
77
+ }
78
+ const outcome = outcomeRaw;
79
+ const steps = events
80
+ .filter((e) => e.event_type !== 'session_complete')
81
+ .map((e) => ({ action: e.content, observation: '' }));
82
+ // SAFETY: session event metadata is a free-form Record<string, unknown>
83
+ // bag; summary is optional and is only trusted once isJsonString below
84
+ // confirms it is actually a string.
85
+ const summaryValue = completeEvent.metadata.summary;
86
+ const summary = isJsonString(summaryValue) ? summaryValue : '(untitled)';
87
+ const trace = createMemory(renderTraceContent({ task: summary, steps, outcome }), {
88
+ layer: Layer.Trace,
89
+ trace_outcome: outcome,
90
+ source_session_id: sessionId,
91
+ tags: ['auto-promoted'],
92
+ source: 'auto-promote',
93
+ scope: sessionScope.scope,
94
+ // T1 fix (2026-08-15 hardening pass): stamp the trace into the SAME
95
+ // tenant the traceExistsForSession idempotency check (above) runs
96
+ // under. Before
97
+ // this, createMemory omitted tenantId and the trace always landed
98
+ // 'default' (memory.ts:535) while the idempotency check ran under
99
+ // consolidationTenant — for any non-default tenant that check never
100
+ // hit, and the trace regenerated every sleep.
101
+ tenantId: consolidationTenant,
102
+ baseHalfLifeDays: run.config.defaultHalfLifeDays,
103
+ });
104
+ return { trace, outcome };
105
+ }
106
+ // AT1 (same producer-side pattern as the merge pass below): traceExistsForSession
107
+ // only sees rows CURRENTLY in the store — once a rejected trace is
108
+ // removed, that idempotency check no longer blocks regeneration, and
109
+ // this write would otherwise reach batchWriteAndDelete's guard bypass
110
+ // unchecked, resurrecting it every sleep. Check under THE ENTRY'S OWN
111
+ // stamped tenantId (read off `trace` after createMemory — never guess
112
+ // the tenant) + the built content's digest. A hit skips the push
113
+ // entirely: not counted as promoted, not added to survivors.
114
+ function traceRejected(run, trace, sessionId) {
115
+ const consolidateDb = run.getConsolidateDb();
116
+ if (!consolidateDb)
117
+ return false;
118
+ const traceDigest = rejectionDigest(trace.content);
119
+ const tombstone = findRejectedValue(consolidateDb, trace.tenantId, traceDigest);
120
+ if (!tombstone)
121
+ return false;
122
+ try {
123
+ appendAuditEvent(consolidateDb, {
124
+ tenantId: trace.tenantId,
125
+ actor: 'sleep',
126
+ op: 'reject_refusal',
127
+ metadata: {
128
+ digest: traceDigest,
129
+ reason: tombstone.reason,
130
+ sourceSessionId: sessionId,
131
+ },
132
+ });
133
+ }
134
+ catch (error) {
135
+ reportAuditWriteFailure('reject_refusal', String(error));
136
+ }
137
+ return true;
138
+ }
139
+ // -------------------------------------------------------------------------
140
+ // 1.5. Replay pass — rehearse high-value survivors
141
+ // -------------------------------------------------------------------------
142
+ //
143
+ // Biologically-inspired counterpart to hippocampal replay during slow-wave
144
+ // sleep: sample N memories weighted by outcome + valence + under-rehearsal
145
+ // + idle time, then apply the same retrieval-strengthening `markRetrieved`
146
+ // applies to real queries. Distinct from decay (removal), physics (motion),
147
+ // and merge (compression) — this is the "rehearse the important stuff so
148
+ // it doesn't fade" pass.
149
+ export function replayPass(run) {
150
+ const { survivors, now } = run;
151
+ const replayCount = run.config.replay?.count ?? REPLAY_COUNT_DEFAULT;
152
+ // EVAL-ONLY ablation (see ablation.ts): replay rehearsal IS recall
153
+ // strengthening (same markRetrieved dynamics), so the strengthen-off arm
154
+ // silences the whole pass - markRetrieved would return unmutated entries
155
+ // and persisting them anyway would still refresh updated_at / mirrors.
156
+ if (!(replayCount > 0 && survivors.length > 0 && !isRecallBoostAblated()))
157
+ return;
158
+ const seed = Math.floor(now.getTime() / 1000) & 0xffffffff;
159
+ const picked = sampleForReplay(survivors, replayCount, now, seed);
160
+ if (picked.length === 0)
161
+ return;
162
+ const rehearsed = markRetrieved(picked, now);
163
+ const rehearsedById = new Map(rehearsed.map((e) => [e.id, e]));
164
+ // Update survivors in place so downstream passes see rehearsed state.
165
+ for (let i = 0; i < survivors.length; i++) {
166
+ const replacement = rehearsedById.get(survivors[i].id);
167
+ if (replacement)
168
+ survivors[i] = replacement;
169
+ }
170
+ run.result.replayed = rehearsed.length;
171
+ run.result.details.push(` 💭 replayed ${rehearsed.length} memor${rehearsed.length === 1 ? 'y' : 'ies'}: ` +
172
+ rehearsed.map((e) => e.id).join(', '));
173
+ if (!run.dryRun) {
174
+ for (const r of rehearsed)
175
+ run.pendingWrites.push(r);
176
+ }
177
+ }
178
+ //# sourceMappingURL=traces.js.map
@@ -1,13 +1,13 @@
1
- import { execSync } from 'child_process';
1
+ import { execFileSync } from 'child_process';
2
2
  const SKIPPED_PATH_TERMS = ['src', 'dist', 'test', 'tests', 'node_modules', 'index'];
3
+ // stderr is dropped because git's warnings (line-ending notices, for one) would otherwise become query terms.
4
+ function readGit(args) {
5
+ return execFileSync('git', args, { encoding: 'utf8', timeout: 3000, stdio: ['ignore', 'pipe', 'ignore'], windowsHide: true }).trim();
6
+ }
3
7
  /** A context query from the cwd's git state ('' means `getContext` lists by strength); kept out of the api layer, which never shells out. */
4
8
  export function autoDetectContext() {
5
9
  try {
6
- const diff = execSync('git diff --name-only HEAD 2>&1', {
7
- encoding: 'utf8',
8
- timeout: 3000,
9
- windowsHide: true,
10
- }).trim();
10
+ const diff = readGit(['diff', '--name-only', 'HEAD']);
11
11
  if (diff) {
12
12
  const terms = diff
13
13
  .split('\n')
@@ -17,11 +17,7 @@ export function autoDetectContext() {
17
17
  if (terms.length > 0)
18
18
  return terms.join(' ');
19
19
  }
20
- const branch = execSync('git branch --show-current 2>&1', {
21
- encoding: 'utf8',
22
- timeout: 3000,
23
- windowsHide: true,
24
- }).trim();
20
+ const branch = readGit(['branch', '--show-current']);
25
21
  if (branch && branch !== 'main' && branch !== 'master') {
26
22
  return branch.replace(/[-_/]/g, ' ');
27
23
  }
@@ -1,6 +1,6 @@
1
1
  import { type MemoryEntry } from './memory.js';
2
2
  import { type SessionHandoff } from './handoff.js';
3
- import type { SessionEvent, TaskSnapshot } from './store.js';
3
+ import type { SessionEvent, TaskSnapshot } from './store/rows.js';
4
4
  import type { AssembleCost, AssembleResult, AssembledContextItem, ContextCost, ContextResultEntry, DrillDownChild, DrillDownCost, DrillDownResult } from './api.js';
5
5
  export declare function snapshotText(s: TaskSnapshot): string;
6
6
  export declare function handoffText(h: SessionHandoff): string;
@@ -1,7 +1,7 @@
1
1
  // The strings a context block prints. The budget prices these same strings, so selection and print cannot drift.
2
2
  import { calculateStrength, confidenceFacets, confidenceLabel } from './memory.js';
3
3
  import { evalNow } from './ablation.js';
4
- import { estimateTokens } from './search.js';
4
+ import { estimateTokens } from './token-ledger.js';
5
5
  import { renderAmbientSummary } from './ambient.js';
6
6
  import { formatHandoffEvidenceLine } from './handoff.js';
7
7
  export function snapshotText(s) {
@@ -19,6 +19,7 @@
19
19
  *
20
20
  * Lifecycle: active -> superseded (a corrected version) or active -> closed (retired).
21
21
  */
22
+ import { type KeysetPosition } from './keyset.js';
22
23
  export type NoteStatus = 'active' | 'superseded' | 'closed';
23
24
  export declare const VALID_NOTE_STATES: ReadonlySet<NoteStatus>;
24
25
  /** Field caps (untrusted at the HTTP/SDK boundary). note is a body, so a larger cap
@@ -61,6 +62,8 @@ export interface ListCustomerNotesOpts {
61
62
  /** Filter to a single customer. */
62
63
  customer?: string;
63
64
  limit?: number;
65
+ /** Resume after this row: the position the previous page ended on. */
66
+ after?: KeysetPosition;
64
67
  }
65
68
  /**
66
69
  * Create a customer_note (or a new version that supersedes an existing one). Writes
@@ -21,12 +21,13 @@
21
21
  */
22
22
  import { BadRequestError, ConflictError, NotFoundError } from './api-errors.js';
23
23
  import { openHippoDb, closeHippoDb } from './db.js';
24
- import { writeEntry } from './store.js';
24
+ import { writeEntry } from './store/entry-writes.js';
25
25
  import { assertTenantId } from './tenant.js';
26
- import { markGraphDirty, removeGraphEntitiesForObject } from './graph.js';
26
+ import { markGraphDirty, removeGraphEntitiesForObject } from './graph/write.js';
27
27
  import { createMemory, Layer } from './memory.js';
28
28
  import { appendAuditEvent } from './audit.js';
29
29
  import { objectHalfLifeDays } from './half-life-migration.js';
30
+ import { keysetAfter } from './keyset.js';
30
31
  export const VALID_NOTE_STATES = new Set([
31
32
  'active',
32
33
  'superseded',
@@ -284,6 +285,7 @@ export function loadCustomerNoteById(hippoRoot, tenantId, id) {
284
285
  export function loadCustomerNotes(hippoRoot, tenantId, opts = {}) {
285
286
  assertTenantId('loadCustomerNotes', tenantId);
286
287
  const limit = opts.limit ?? 100;
288
+ const after = keysetAfter('created_at', 'id', opts.after);
287
289
  if (opts.status && !VALID_NOTE_STATES.has(opts.status)) {
288
290
  throw new BadRequestError(`loadCustomerNotes: status must be one of ${Array.from(VALID_NOTE_STATES).join('|')}; got ${opts.status}`);
289
291
  }
@@ -299,13 +301,13 @@ export function loadCustomerNotes(hippoRoot, tenantId, opts = {}) {
299
301
  clauses.push('customer = ?');
300
302
  params.push(opts.customer);
301
303
  }
302
- params.push(limit);
304
+ params.push(...after.params, limit);
303
305
  // SAFETY: SELECT ${NOTE_COLS} projects exactly the CustomerNoteRow columns
304
306
  // regardless of the dynamic WHERE clause built above; .all() returns rows
305
307
  // in that shape.
306
308
  const rows = db.prepare(`
307
309
  SELECT ${NOTE_COLS} FROM customer_notes
308
- WHERE ${clauses.join(' AND ')}
310
+ WHERE ${clauses.join(' AND ')}${after.sql}
309
311
  ORDER BY created_at DESC, id DESC
310
312
  LIMIT ?
311
313
  `).all(...params);
package/dist/dag.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import { createMemory, Layer } from './memory.js';
2
- import { writeEntry, loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from './store.js';
2
+ import { writeEntry } from './store/entry-writes.js';
3
+ import { loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from './store/summaries.js';
3
4
  import { RejectedValueError } from './rejection.js';
4
- import { redactSecrets } from './secret-detect.js';
5
+ import { redactSecretsStrict } from './secret-detect.js';
5
6
  import { fetchWithRetry, llmTimeoutMs } from './http-retry.js';
6
7
  import { derivationScope, derivationPartitionKey } from './recall-scope.js';
7
8
  import { loadConfig } from './config.js';
8
9
  import { neverAutoShareTags } from './shared.js';
10
+ import { log } from './log.js';
9
11
  export function clusterFacts(facts) {
10
12
  if (facts.length === 0)
11
13
  return [];
@@ -47,9 +49,9 @@ Write a single concise paragraph (2-4 sentences) that captures all the key infor
47
49
  export async function generateDagSummary(label, factContents, opts) {
48
50
  const model = opts.model ?? 'claude-sonnet-4-6';
49
51
  const fetchFn = opts.fetcher ?? fetch;
50
- const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecrets(f)}`).join('\n');
52
+ const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecretsStrict(f)}`).join('\n');
51
53
  const prompt = DAG_SUMMARY_PROMPT
52
- .replace('{label}', redactSecrets(label))
54
+ .replace('{label}', redactSecretsStrict(label))
53
55
  .replace('{facts}', factsBlock);
54
56
  let res;
55
57
  try {
@@ -144,7 +146,7 @@ export async function buildDag(hippoRoot, facts, opts) {
144
146
  // The tombstone check itself is tenant-scoped for free: writeEntry ->
145
147
  // writeEntryDbOnly -> upsertEntryRow calls
146
148
  // checkRejectionGuard(db, entry.tenantId ?? 'default', ...)
147
- // (store.ts:1172), reading tenantId off the entry being written. Now
149
+ // (store/entry-writes.ts), reading tenantId off the entry being written. Now
148
150
  // that summaryEntry carries factTenant instead of the implicit
149
151
  // 'default', the guard consults that tenant's tombstones — no
150
152
  // separate check needed here (unlike consolidate.ts's merge pass,
@@ -157,7 +159,7 @@ export async function buildDag(hippoRoot, facts, opts) {
157
159
  catch (err) {
158
160
  if (err instanceof RejectedValueError) {
159
161
  result.rejected++;
160
- console.error(`[buildDag] cluster "${cluster.label}" skipped: summary matches a rejected value`);
162
+ log.warn(`buildDag: cluster "${cluster.label}" skipped: summary matches a rejected value`);
161
163
  continue;
162
164
  }
163
165
  throw err;
@@ -169,7 +171,7 @@ export async function buildDag(hippoRoot, facts, opts) {
169
171
  result.factsLinked++;
170
172
  }
171
173
  // v0.30 / E3 — cancel the cascade of dirty-marks fired by member
172
- // writeEntry calls (E2 hook on writeEntryDbOnly at store.ts:1214).
174
+ // writeEntry calls (E2 hook on writeEntryDbOnly in store/entry-writes.ts).
173
175
  // The summary we just built IS fresh, no rebuild needed. Without this,
174
176
  // E3 in the SAME sleep cycle would re-rebuild every new summary
175
177
  // (2x LLM cost). plan-eng-r1 HIGH must-fix.
@@ -235,7 +237,7 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
235
237
  result.zeroChildSkipped++;
236
238
  // changed=false → race lost / row vanished; silently skip. `refused`
237
239
  // is always false here — applyRebuildResult only checks the
238
- // tombstone when bumpRebuildCount is true (store.ts:3398).
240
+ // tombstone when bumpRebuildCount is true (store/summaries.ts).
239
241
  continue;
240
242
  }
241
243
  // Derive label from summary's existing entity tags (mirrors clusterFacts)
@@ -271,11 +273,10 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
271
273
  catch (err) {
272
274
  // Per-summary failure isolation — one throw doesn't abort the queue.
273
275
  // independent-review MED #2 fold: log enough to triage in production
274
- // (audit() wraps its own writes try/catch per store.ts:2566, so a
276
+ // (audit() wraps its own writes try/catch per store/audit-event.ts, so a
275
277
  // throw here is exotic: SQLite I/O error, prepare failure, etc).
276
278
  result.failed++;
277
- // eslint-disable-next-line no-console
278
- console.error(`[rebuildDirtySummaries] summary ${summary.id} (tenant ${summary.tenantId}) failed: ${err instanceof Error ? err.message : String(err)}`);
279
+ log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenantId}) failed: ${err instanceof Error ? err.message : String(err)}`);
279
280
  }
280
281
  }
281
282
  return result;
@@ -353,7 +354,7 @@ export async function buildEntityProfiles(hippoRoot, l2Summaries, opts) {
353
354
  catch (err) {
354
355
  if (err instanceof RejectedValueError) {
355
356
  result.rejected++;
356
- console.error(`[buildEntityProfiles] cluster "${cluster.label}" skipped: profile matches a rejected value`);
357
+ log.warn(`buildEntityProfiles: cluster "${cluster.label}" skipped: profile matches a rejected value`);
357
358
  continue;
358
359
  }
359
360
  throw err;
@@ -0,0 +1,20 @@
1
+ import type { MemoryEntry } from './memory.js';
2
+ import { type ActionBody } from './dashboard-params.js';
3
+ /** What an action hands the router: a status, a JSON body, and whether the store changed. */
4
+ export interface ActionResult {
5
+ status: number;
6
+ body: unknown;
7
+ /** True when a write committed, so the router drops the snapshot. */
8
+ changed: boolean;
9
+ /** The live entry an action acted on, so the router can build the detail after the cache is dropped. */
10
+ entry?: MemoryEntry;
11
+ }
12
+ /** Sets `pinned`; the audit row says `remember` with actor `dashboard`, the same op the old star toggle wrote. */
13
+ export declare function pinMemory(hippoRoot: string, tenantId: string, rawId: string, body: ActionBody): ActionResult;
14
+ /** Marks a memory wrong, the same signal as `hippo outcome --bad`. */
15
+ export declare function markWrong(hippoRoot: string, tenantId: string, rawId: string): ActionResult;
16
+ /** Deletes a memory like `hippo forget`; a raw receipt is append-only and answers 409 with the archive hint. */
17
+ export declare function forgetMemory(hippoRoot: string, tenantId: string, rawId: string): ActionResult;
18
+ /** Keeps one side of an open conflict and weakens the other; every refusal maps to its own status. */
19
+ export declare function resolveOpenConflict(hippoRoot: string, tenantId: string, conflictId: number, body: ActionBody): ActionResult;
20
+ //# sourceMappingURL=dashboard-actions.d.ts.map