hippo-memory 1.43.3 → 1.45.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 (534) hide show
  1. package/README.md +14 -12
  2. package/bin/hippo.js +3 -1
  3. package/dist/api.d.ts +21 -21
  4. package/dist/api.js +69 -42
  5. package/dist/audit-prune.js +4 -1
  6. package/dist/audit.d.ts +1 -1
  7. package/dist/audit.js +9 -0
  8. package/dist/autolearn.d.ts +1 -1
  9. package/dist/autolearn.js +2 -1
  10. package/dist/capture.d.ts +11 -10
  11. package/dist/capture.js +22 -30
  12. package/dist/cli.d.ts +4 -0
  13. package/dist/cli.js +309 -171
  14. package/dist/client.d.ts +4 -21
  15. package/dist/client.js +3 -112
  16. package/dist/config.js +2 -1
  17. package/dist/consolidate.d.ts +3 -0
  18. package/dist/consolidate.js +44 -42
  19. package/dist/dag.d.ts +1 -0
  20. package/dist/dag.js +10 -5
  21. package/dist/dashboard.js +7 -3
  22. package/dist/db.js +16 -24
  23. package/dist/dedupe.d.ts +1 -0
  24. package/dist/dedupe.js +4 -7
  25. package/dist/embedding-provider.d.ts +1 -1
  26. package/dist/embedding-provider.js +3 -2
  27. package/dist/embeddings.js +81 -8
  28. package/dist/extract.d.ts +2 -0
  29. package/dist/extract.js +9 -4
  30. package/dist/goals.js +12 -3
  31. package/dist/mcp/server.js +21 -36
  32. package/dist/memory.d.ts +3 -0
  33. package/dist/memory.js +7 -1
  34. package/dist/physics-state.js +4 -1
  35. package/dist/raw-archive.js +5 -2
  36. package/dist/recall-trace.js +4 -1
  37. package/dist/refine-llm.js +3 -2
  38. package/dist/rerankers/jev.js +3 -2
  39. package/dist/rerankers/llm.js +3 -2
  40. package/dist/search.js +3 -3
  41. package/dist/server.d.ts +5 -0
  42. package/dist/server.js +39 -29
  43. package/dist/shared.js +1 -1
  44. package/dist/stdin.d.ts +12 -0
  45. package/dist/stdin.js +41 -0
  46. package/dist/store.d.ts +18 -11
  47. package/dist/store.js +152 -65
  48. package/dist/version.d.ts +4 -6
  49. package/dist/version.js +4 -7
  50. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  51. package/extensions/openclaw-plugin/package.json +1 -1
  52. package/openclaw.plugin.json +1 -1
  53. package/package.json +8 -5
  54. package/dist/ablation.d.ts.map +0 -1
  55. package/dist/ablation.js.map +0 -1
  56. package/dist/ambient.d.ts.map +0 -1
  57. package/dist/ambient.js.map +0 -1
  58. package/dist/api.d.ts.map +0 -1
  59. package/dist/api.js.map +0 -1
  60. package/dist/audit-prune.d.ts.map +0 -1
  61. package/dist/audit-prune.js.map +0 -1
  62. package/dist/audit.d.ts.map +0 -1
  63. package/dist/audit.js.map +0 -1
  64. package/dist/auth.d.ts.map +0 -1
  65. package/dist/auth.js.map +0 -1
  66. package/dist/autolearn.d.ts.map +0 -1
  67. package/dist/autolearn.js.map +0 -1
  68. package/dist/availability.d.ts.map +0 -1
  69. package/dist/availability.js.map +0 -1
  70. package/dist/benchmarks/e1.3/incident-recall-eval.js +0 -78
  71. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +0 -1
  72. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +0 -103
  73. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +0 -1
  74. package/dist/capture.d.ts.map +0 -1
  75. package/dist/capture.js.map +0 -1
  76. package/dist/card-detail.d.ts.map +0 -1
  77. package/dist/card-detail.js.map +0 -1
  78. package/dist/card.d.ts.map +0 -1
  79. package/dist/card.js.map +0 -1
  80. package/dist/cli.d.ts.map +0 -1
  81. package/dist/cli.js.map +0 -1
  82. package/dist/client.d.ts.map +0 -1
  83. package/dist/client.js.map +0 -1
  84. package/dist/compare.d.ts.map +0 -1
  85. package/dist/compare.js.map +0 -1
  86. package/dist/config.d.ts.map +0 -1
  87. package/dist/config.js.map +0 -1
  88. package/dist/connectors/github/backfill.d.ts.map +0 -1
  89. package/dist/connectors/github/backfill.js.map +0 -1
  90. package/dist/connectors/github/cli-impl.d.ts.map +0 -1
  91. package/dist/connectors/github/cli-impl.js.map +0 -1
  92. package/dist/connectors/github/deletion.d.ts.map +0 -1
  93. package/dist/connectors/github/deletion.js.map +0 -1
  94. package/dist/connectors/github/dlq.d.ts.map +0 -1
  95. package/dist/connectors/github/dlq.js.map +0 -1
  96. package/dist/connectors/github/idempotency.d.ts.map +0 -1
  97. package/dist/connectors/github/idempotency.js.map +0 -1
  98. package/dist/connectors/github/ingest.d.ts.map +0 -1
  99. package/dist/connectors/github/ingest.js.map +0 -1
  100. package/dist/connectors/github/octokit-client.d.ts.map +0 -1
  101. package/dist/connectors/github/octokit-client.js.map +0 -1
  102. package/dist/connectors/github/ratelimit.d.ts.map +0 -1
  103. package/dist/connectors/github/ratelimit.js.map +0 -1
  104. package/dist/connectors/github/scope.d.ts.map +0 -1
  105. package/dist/connectors/github/scope.js.map +0 -1
  106. package/dist/connectors/github/signature.d.ts.map +0 -1
  107. package/dist/connectors/github/signature.js.map +0 -1
  108. package/dist/connectors/github/tenant-routing.d.ts.map +0 -1
  109. package/dist/connectors/github/tenant-routing.js.map +0 -1
  110. package/dist/connectors/github/transform.d.ts.map +0 -1
  111. package/dist/connectors/github/transform.js.map +0 -1
  112. package/dist/connectors/github/types.d.ts.map +0 -1
  113. package/dist/connectors/github/types.js.map +0 -1
  114. package/dist/connectors/slack/backfill.d.ts.map +0 -1
  115. package/dist/connectors/slack/backfill.js.map +0 -1
  116. package/dist/connectors/slack/deletion.d.ts.map +0 -1
  117. package/dist/connectors/slack/deletion.js.map +0 -1
  118. package/dist/connectors/slack/dlq.d.ts.map +0 -1
  119. package/dist/connectors/slack/dlq.js.map +0 -1
  120. package/dist/connectors/slack/idempotency.d.ts.map +0 -1
  121. package/dist/connectors/slack/idempotency.js.map +0 -1
  122. package/dist/connectors/slack/ingest.d.ts.map +0 -1
  123. package/dist/connectors/slack/ingest.js.map +0 -1
  124. package/dist/connectors/slack/ratelimit.d.ts.map +0 -1
  125. package/dist/connectors/slack/ratelimit.js.map +0 -1
  126. package/dist/connectors/slack/scope.d.ts.map +0 -1
  127. package/dist/connectors/slack/scope.js.map +0 -1
  128. package/dist/connectors/slack/signature.d.ts.map +0 -1
  129. package/dist/connectors/slack/signature.js.map +0 -1
  130. package/dist/connectors/slack/tenant-routing.d.ts.map +0 -1
  131. package/dist/connectors/slack/tenant-routing.js.map +0 -1
  132. package/dist/connectors/slack/transform.d.ts.map +0 -1
  133. package/dist/connectors/slack/transform.js.map +0 -1
  134. package/dist/connectors/slack/types.d.ts.map +0 -1
  135. package/dist/connectors/slack/types.js.map +0 -1
  136. package/dist/connectors/slack/web-client.d.ts.map +0 -1
  137. package/dist/connectors/slack/web-client.js.map +0 -1
  138. package/dist/connectors/slack/workspaces.d.ts.map +0 -1
  139. package/dist/connectors/slack/workspaces.js.map +0 -1
  140. package/dist/consolidate.d.ts.map +0 -1
  141. package/dist/consolidate.js.map +0 -1
  142. package/dist/correction-latency.d.ts.map +0 -1
  143. package/dist/correction-latency.js.map +0 -1
  144. package/dist/customer-notes.d.ts.map +0 -1
  145. package/dist/customer-notes.js.map +0 -1
  146. package/dist/dag.d.ts.map +0 -1
  147. package/dist/dag.js.map +0 -1
  148. package/dist/dashboard.d.ts.map +0 -1
  149. package/dist/dashboard.js.map +0 -1
  150. package/dist/db.d.ts.map +0 -1
  151. package/dist/db.js.map +0 -1
  152. package/dist/decisions.d.ts.map +0 -1
  153. package/dist/decisions.js.map +0 -1
  154. package/dist/dedupe.d.ts.map +0 -1
  155. package/dist/dedupe.js.map +0 -1
  156. package/dist/embedding-provider.d.ts.map +0 -1
  157. package/dist/embedding-provider.js.map +0 -1
  158. package/dist/embeddings.d.ts.map +0 -1
  159. package/dist/embeddings.js.map +0 -1
  160. package/dist/eval-suite.d.ts.map +0 -1
  161. package/dist/eval-suite.js.map +0 -1
  162. package/dist/eval.d.ts.map +0 -1
  163. package/dist/eval.js.map +0 -1
  164. package/dist/extensions/openclaw-plugin/index.js.map +0 -1
  165. package/dist/extract.d.ts.map +0 -1
  166. package/dist/extract.js.map +0 -1
  167. package/dist/forward-claim-detector.d.ts.map +0 -1
  168. package/dist/forward-claim-detector.js.map +0 -1
  169. package/dist/goals.d.ts.map +0 -1
  170. package/dist/goals.js.map +0 -1
  171. package/dist/graph-extract.d.ts.map +0 -1
  172. package/dist/graph-extract.js.map +0 -1
  173. package/dist/graph-recall.d.ts.map +0 -1
  174. package/dist/graph-recall.js.map +0 -1
  175. package/dist/graph-stream.d.ts.map +0 -1
  176. package/dist/graph-stream.js.map +0 -1
  177. package/dist/graph-view.d.ts.map +0 -1
  178. package/dist/graph-view.js.map +0 -1
  179. package/dist/graph.d.ts.map +0 -1
  180. package/dist/graph.js.map +0 -1
  181. package/dist/handoff.d.ts.map +0 -1
  182. package/dist/handoff.js.map +0 -1
  183. package/dist/hooks.d.ts.map +0 -1
  184. package/dist/hooks.js.map +0 -1
  185. package/dist/importers.d.ts.map +0 -1
  186. package/dist/importers.js.map +0 -1
  187. package/dist/incidents.d.ts.map +0 -1
  188. package/dist/incidents.js.map +0 -1
  189. package/dist/index.d.ts.map +0 -1
  190. package/dist/index.js.map +0 -1
  191. package/dist/invalidation.d.ts.map +0 -1
  192. package/dist/invalidation.js.map +0 -1
  193. package/dist/mcp/framing.d.ts.map +0 -1
  194. package/dist/mcp/framing.js.map +0 -1
  195. package/dist/mcp/server.d.ts.map +0 -1
  196. package/dist/mcp/server.js.map +0 -1
  197. package/dist/memory-value-weights.d.ts.map +0 -1
  198. package/dist/memory-value-weights.js.map +0 -1
  199. package/dist/memory-value.d.ts.map +0 -1
  200. package/dist/memory-value.js.map +0 -1
  201. package/dist/memory.d.ts.map +0 -1
  202. package/dist/memory.js.map +0 -1
  203. package/dist/multihop.d.ts.map +0 -1
  204. package/dist/multihop.js.map +0 -1
  205. package/dist/owner-validation.d.ts.map +0 -1
  206. package/dist/owner-validation.js.map +0 -1
  207. package/dist/path-context.d.ts.map +0 -1
  208. package/dist/path-context.js.map +0 -1
  209. package/dist/physics-config.d.ts.map +0 -1
  210. package/dist/physics-config.js.map +0 -1
  211. package/dist/physics-state.d.ts.map +0 -1
  212. package/dist/physics-state.js.map +0 -1
  213. package/dist/physics.d.ts.map +0 -1
  214. package/dist/physics.js.map +0 -1
  215. package/dist/policies.d.ts.map +0 -1
  216. package/dist/policies.js.map +0 -1
  217. package/dist/postinstall.d.ts.map +0 -1
  218. package/dist/postinstall.js.map +0 -1
  219. package/dist/predictions.d.ts.map +0 -1
  220. package/dist/predictions.js.map +0 -1
  221. package/dist/processes.d.ts.map +0 -1
  222. package/dist/processes.js.map +0 -1
  223. package/dist/project-briefs.d.ts.map +0 -1
  224. package/dist/project-briefs.js.map +0 -1
  225. package/dist/project-identity.d.ts.map +0 -1
  226. package/dist/project-identity.js.map +0 -1
  227. package/dist/provenance-coverage.d.ts.map +0 -1
  228. package/dist/provenance-coverage.js.map +0 -1
  229. package/dist/rate-limit.d.ts.map +0 -1
  230. package/dist/rate-limit.js.map +0 -1
  231. package/dist/raw-archive-mirror-cleanup.d.ts.map +0 -1
  232. package/dist/raw-archive-mirror-cleanup.js.map +0 -1
  233. package/dist/raw-archive.d.ts.map +0 -1
  234. package/dist/raw-archive.js.map +0 -1
  235. package/dist/recall-history.d.ts.map +0 -1
  236. package/dist/recall-history.js.map +0 -1
  237. package/dist/recall-scope.d.ts.map +0 -1
  238. package/dist/recall-scope.js.map +0 -1
  239. package/dist/recall-trace.d.ts.map +0 -1
  240. package/dist/recall-trace.js.map +0 -1
  241. package/dist/refine-llm.d.ts.map +0 -1
  242. package/dist/refine-llm.js.map +0 -1
  243. package/dist/reject-flow.d.ts.map +0 -1
  244. package/dist/reject-flow.js.map +0 -1
  245. package/dist/rejection.d.ts.map +0 -1
  246. package/dist/rejection.js.map +0 -1
  247. package/dist/replay.d.ts.map +0 -1
  248. package/dist/replay.js.map +0 -1
  249. package/dist/rerankers/cross-encoder.d.ts.map +0 -1
  250. package/dist/rerankers/cross-encoder.js.map +0 -1
  251. package/dist/rerankers/index.d.ts.map +0 -1
  252. package/dist/rerankers/index.js.map +0 -1
  253. package/dist/rerankers/jev.d.ts.map +0 -1
  254. package/dist/rerankers/jev.js.map +0 -1
  255. package/dist/rerankers/llm.d.ts.map +0 -1
  256. package/dist/rerankers/llm.js.map +0 -1
  257. package/dist/rerankers/types.d.ts.map +0 -1
  258. package/dist/rerankers/types.js.map +0 -1
  259. package/dist/rrf.d.ts.map +0 -1
  260. package/dist/rrf.js.map +0 -1
  261. package/dist/salience.d.ts.map +0 -1
  262. package/dist/salience.js.map +0 -1
  263. package/dist/scheduler.d.ts.map +0 -1
  264. package/dist/scheduler.js.map +0 -1
  265. package/dist/scope.d.ts.map +0 -1
  266. package/dist/scope.js.map +0 -1
  267. package/dist/search.d.ts.map +0 -1
  268. package/dist/search.js.map +0 -1
  269. package/dist/secret-detect.d.ts.map +0 -1
  270. package/dist/secret-detect.js.map +0 -1
  271. package/dist/server-detect.d.ts.map +0 -1
  272. package/dist/server-detect.js.map +0 -1
  273. package/dist/server.d.ts.map +0 -1
  274. package/dist/server.js.map +0 -1
  275. package/dist/shared.d.ts.map +0 -1
  276. package/dist/shared.js.map +0 -1
  277. package/dist/skills.d.ts.map +0 -1
  278. package/dist/skills.js.map +0 -1
  279. package/dist/sleep-redact.d.ts +0 -58
  280. package/dist/sleep-redact.d.ts.map +0 -1
  281. package/dist/sleep-redact.js +0 -80
  282. package/dist/sleep-redact.js.map +0 -1
  283. package/dist/src/ablation.js +0 -138
  284. package/dist/src/ablation.js.map +0 -1
  285. package/dist/src/ambient.js +0 -148
  286. package/dist/src/ambient.js.map +0 -1
  287. package/dist/src/api.js +0 -2109
  288. package/dist/src/api.js.map +0 -1
  289. package/dist/src/audit-prune.js +0 -106
  290. package/dist/src/audit-prune.js.map +0 -1
  291. package/dist/src/audit.js +0 -213
  292. package/dist/src/audit.js.map +0 -1
  293. package/dist/src/auth.js +0 -97
  294. package/dist/src/auth.js.map +0 -1
  295. package/dist/src/autolearn.js +0 -174
  296. package/dist/src/autolearn.js.map +0 -1
  297. package/dist/src/availability.js +0 -94
  298. package/dist/src/availability.js.map +0 -1
  299. package/dist/src/capture.js +0 -1354
  300. package/dist/src/capture.js.map +0 -1
  301. package/dist/src/card-detail.js +0 -15
  302. package/dist/src/card-detail.js.map +0 -1
  303. package/dist/src/card.js +0 -19
  304. package/dist/src/card.js.map +0 -1
  305. package/dist/src/cli.js +0 -9328
  306. package/dist/src/cli.js.map +0 -1
  307. package/dist/src/client.js +0 -237
  308. package/dist/src/client.js.map +0 -1
  309. package/dist/src/compare.js +0 -122
  310. package/dist/src/compare.js.map +0 -1
  311. package/dist/src/config.js +0 -135
  312. package/dist/src/config.js.map +0 -1
  313. package/dist/src/connectors/github/backfill.js +0 -281
  314. package/dist/src/connectors/github/backfill.js.map +0 -1
  315. package/dist/src/connectors/github/cli-impl.js +0 -234
  316. package/dist/src/connectors/github/cli-impl.js.map +0 -1
  317. package/dist/src/connectors/github/deletion.js +0 -85
  318. package/dist/src/connectors/github/deletion.js.map +0 -1
  319. package/dist/src/connectors/github/dlq.js +0 -190
  320. package/dist/src/connectors/github/dlq.js.map +0 -1
  321. package/dist/src/connectors/github/idempotency.js +0 -27
  322. package/dist/src/connectors/github/idempotency.js.map +0 -1
  323. package/dist/src/connectors/github/ingest.js +0 -156
  324. package/dist/src/connectors/github/ingest.js.map +0 -1
  325. package/dist/src/connectors/github/octokit-client.js +0 -70
  326. package/dist/src/connectors/github/octokit-client.js.map +0 -1
  327. package/dist/src/connectors/github/ratelimit.js +0 -31
  328. package/dist/src/connectors/github/ratelimit.js.map +0 -1
  329. package/dist/src/connectors/github/scope.js +0 -13
  330. package/dist/src/connectors/github/scope.js.map +0 -1
  331. package/dist/src/connectors/github/signature.js +0 -81
  332. package/dist/src/connectors/github/signature.js.map +0 -1
  333. package/dist/src/connectors/github/tenant-routing.js +0 -69
  334. package/dist/src/connectors/github/tenant-routing.js.map +0 -1
  335. package/dist/src/connectors/github/transform.js +0 -103
  336. package/dist/src/connectors/github/transform.js.map +0 -1
  337. package/dist/src/connectors/github/types.js +0 -100
  338. package/dist/src/connectors/github/types.js.map +0 -1
  339. package/dist/src/connectors/slack/backfill.js +0 -78
  340. package/dist/src/connectors/slack/backfill.js.map +0 -1
  341. package/dist/src/connectors/slack/deletion.js +0 -59
  342. package/dist/src/connectors/slack/deletion.js.map +0 -1
  343. package/dist/src/connectors/slack/dlq.js +0 -224
  344. package/dist/src/connectors/slack/dlq.js.map +0 -1
  345. package/dist/src/connectors/slack/idempotency.js +0 -31
  346. package/dist/src/connectors/slack/idempotency.js.map +0 -1
  347. package/dist/src/connectors/slack/ingest.js +0 -109
  348. package/dist/src/connectors/slack/ingest.js.map +0 -1
  349. package/dist/src/connectors/slack/ratelimit.js +0 -18
  350. package/dist/src/connectors/slack/ratelimit.js.map +0 -1
  351. package/dist/src/connectors/slack/scope.js +0 -13
  352. package/dist/src/connectors/slack/scope.js.map +0 -1
  353. package/dist/src/connectors/slack/signature.js +0 -27
  354. package/dist/src/connectors/slack/signature.js.map +0 -1
  355. package/dist/src/connectors/slack/tenant-routing.js +0 -41
  356. package/dist/src/connectors/slack/tenant-routing.js.map +0 -1
  357. package/dist/src/connectors/slack/transform.js +0 -47
  358. package/dist/src/connectors/slack/transform.js.map +0 -1
  359. package/dist/src/connectors/slack/types.js +0 -35
  360. package/dist/src/connectors/slack/types.js.map +0 -1
  361. package/dist/src/connectors/slack/web-client.js +0 -43
  362. package/dist/src/connectors/slack/web-client.js.map +0 -1
  363. package/dist/src/connectors/slack/workspaces.js +0 -62
  364. package/dist/src/connectors/slack/workspaces.js.map +0 -1
  365. package/dist/src/consolidate.js +0 -978
  366. package/dist/src/consolidate.js.map +0 -1
  367. package/dist/src/correction-latency.js +0 -74
  368. package/dist/src/correction-latency.js.map +0 -1
  369. package/dist/src/customer-notes.js +0 -325
  370. package/dist/src/customer-notes.js.map +0 -1
  371. package/dist/src/dag.js +0 -352
  372. package/dist/src/dag.js.map +0 -1
  373. package/dist/src/dashboard.js +0 -258
  374. package/dist/src/dashboard.js.map +0 -1
  375. package/dist/src/db.js +0 -2728
  376. package/dist/src/db.js.map +0 -1
  377. package/dist/src/decisions.js +0 -304
  378. package/dist/src/decisions.js.map +0 -1
  379. package/dist/src/dedupe.js +0 -141
  380. package/dist/src/dedupe.js.map +0 -1
  381. package/dist/src/embedding-provider.js +0 -314
  382. package/dist/src/embedding-provider.js.map +0 -1
  383. package/dist/src/embeddings.js +0 -543
  384. package/dist/src/embeddings.js.map +0 -1
  385. package/dist/src/eval-suite.js +0 -294
  386. package/dist/src/eval-suite.js.map +0 -1
  387. package/dist/src/eval.js +0 -187
  388. package/dist/src/eval.js.map +0 -1
  389. package/dist/src/extract.js +0 -117
  390. package/dist/src/extract.js.map +0 -1
  391. package/dist/src/forward-claim-detector.js +0 -117
  392. package/dist/src/forward-claim-detector.js.map +0 -1
  393. package/dist/src/goals.js +0 -390
  394. package/dist/src/goals.js.map +0 -1
  395. package/dist/src/graph-extract.js +0 -314
  396. package/dist/src/graph-extract.js.map +0 -1
  397. package/dist/src/graph-recall.js +0 -277
  398. package/dist/src/graph-recall.js.map +0 -1
  399. package/dist/src/graph-stream.js +0 -176
  400. package/dist/src/graph-stream.js.map +0 -1
  401. package/dist/src/graph-view.js +0 -310
  402. package/dist/src/graph-view.js.map +0 -1
  403. package/dist/src/graph.js +0 -762
  404. package/dist/src/graph.js.map +0 -1
  405. package/dist/src/handoff.js +0 -65
  406. package/dist/src/handoff.js.map +0 -1
  407. package/dist/src/hooks.js +0 -926
  408. package/dist/src/hooks.js.map +0 -1
  409. package/dist/src/importers.js +0 -881
  410. package/dist/src/importers.js.map +0 -1
  411. package/dist/src/incidents.js +0 -336
  412. package/dist/src/incidents.js.map +0 -1
  413. package/dist/src/index.js +0 -32
  414. package/dist/src/index.js.map +0 -1
  415. package/dist/src/invalidation.js +0 -129
  416. package/dist/src/invalidation.js.map +0 -1
  417. package/dist/src/mcp/framing.js +0 -45
  418. package/dist/src/mcp/framing.js.map +0 -1
  419. package/dist/src/mcp/server.js +0 -1298
  420. package/dist/src/mcp/server.js.map +0 -1
  421. package/dist/src/memory-value-weights.js +0 -31
  422. package/dist/src/memory-value-weights.js.map +0 -1
  423. package/dist/src/memory-value.js +0 -261
  424. package/dist/src/memory-value.js.map +0 -1
  425. package/dist/src/memory.js +0 -425
  426. package/dist/src/memory.js.map +0 -1
  427. package/dist/src/multihop.js +0 -35
  428. package/dist/src/multihop.js.map +0 -1
  429. package/dist/src/owner-validation.js +0 -56
  430. package/dist/src/owner-validation.js.map +0 -1
  431. package/dist/src/path-context.js +0 -48
  432. package/dist/src/path-context.js.map +0 -1
  433. package/dist/src/physics-config.js +0 -26
  434. package/dist/src/physics-config.js.map +0 -1
  435. package/dist/src/physics-state.js +0 -169
  436. package/dist/src/physics-state.js.map +0 -1
  437. package/dist/src/physics.js +0 -378
  438. package/dist/src/physics.js.map +0 -1
  439. package/dist/src/policies.js +0 -414
  440. package/dist/src/policies.js.map +0 -1
  441. package/dist/src/postinstall.js +0 -101
  442. package/dist/src/postinstall.js.map +0 -1
  443. package/dist/src/predictions.js +0 -629
  444. package/dist/src/predictions.js.map +0 -1
  445. package/dist/src/processes.js +0 -349
  446. package/dist/src/processes.js.map +0 -1
  447. package/dist/src/project-briefs.js +0 -492
  448. package/dist/src/project-briefs.js.map +0 -1
  449. package/dist/src/project-identity.js +0 -200
  450. package/dist/src/project-identity.js.map +0 -1
  451. package/dist/src/provenance-coverage.js +0 -23
  452. package/dist/src/provenance-coverage.js.map +0 -1
  453. package/dist/src/rate-limit.js +0 -60
  454. package/dist/src/rate-limit.js.map +0 -1
  455. package/dist/src/raw-archive-mirror-cleanup.js +0 -55
  456. package/dist/src/raw-archive-mirror-cleanup.js.map +0 -1
  457. package/dist/src/raw-archive.js +0 -88
  458. package/dist/src/raw-archive.js.map +0 -1
  459. package/dist/src/recall-history.js +0 -235
  460. package/dist/src/recall-history.js.map +0 -1
  461. package/dist/src/recall-scope.js +0 -89
  462. package/dist/src/recall-scope.js.map +0 -1
  463. package/dist/src/recall-trace.js +0 -183
  464. package/dist/src/recall-trace.js.map +0 -1
  465. package/dist/src/refine-llm.js +0 -156
  466. package/dist/src/refine-llm.js.map +0 -1
  467. package/dist/src/reject-flow.js +0 -209
  468. package/dist/src/reject-flow.js.map +0 -1
  469. package/dist/src/rejection.js +0 -160
  470. package/dist/src/rejection.js.map +0 -1
  471. package/dist/src/replay.js +0 -122
  472. package/dist/src/replay.js.map +0 -1
  473. package/dist/src/rerankers/cross-encoder.js +0 -137
  474. package/dist/src/rerankers/cross-encoder.js.map +0 -1
  475. package/dist/src/rerankers/index.js +0 -20
  476. package/dist/src/rerankers/index.js.map +0 -1
  477. package/dist/src/rerankers/jev.js +0 -119
  478. package/dist/src/rerankers/jev.js.map +0 -1
  479. package/dist/src/rerankers/llm.js +0 -80
  480. package/dist/src/rerankers/llm.js.map +0 -1
  481. package/dist/src/rerankers/types.js +0 -2
  482. package/dist/src/rerankers/types.js.map +0 -1
  483. package/dist/src/rrf.js +0 -61
  484. package/dist/src/rrf.js.map +0 -1
  485. package/dist/src/salience.js +0 -74
  486. package/dist/src/salience.js.map +0 -1
  487. package/dist/src/scheduler.js +0 -77
  488. package/dist/src/scheduler.js.map +0 -1
  489. package/dist/src/scope.js +0 -35
  490. package/dist/src/scope.js.map +0 -1
  491. package/dist/src/search.js +0 -1003
  492. package/dist/src/search.js.map +0 -1
  493. package/dist/src/secret-detect.js +0 -95
  494. package/dist/src/secret-detect.js.map +0 -1
  495. package/dist/src/server-detect.js +0 -231
  496. package/dist/src/server-detect.js.map +0 -1
  497. package/dist/src/server.js +0 -3255
  498. package/dist/src/server.js.map +0 -1
  499. package/dist/src/shared.js +0 -502
  500. package/dist/src/shared.js.map +0 -1
  501. package/dist/src/skills.js +0 -346
  502. package/dist/src/skills.js.map +0 -1
  503. package/dist/src/sleep-redact.js +0 -80
  504. package/dist/src/sleep-redact.js.map +0 -1
  505. package/dist/src/sso.js +0 -22
  506. package/dist/src/sso.js.map +0 -1
  507. package/dist/src/store.js +0 -3743
  508. package/dist/src/store.js.map +0 -1
  509. package/dist/src/tenant.js +0 -17
  510. package/dist/src/tenant.js.map +0 -1
  511. package/dist/src/trace.js +0 -72
  512. package/dist/src/trace.js.map +0 -1
  513. package/dist/src/version.js +0 -40
  514. package/dist/src/version.js.map +0 -1
  515. package/dist/src/working-memory.js +0 -157
  516. package/dist/src/working-memory.js.map +0 -1
  517. package/dist/src/yaml.js +0 -107
  518. package/dist/src/yaml.js.map +0 -1
  519. package/dist/sso.d.ts +0 -13
  520. package/dist/sso.d.ts.map +0 -1
  521. package/dist/sso.js +0 -22
  522. package/dist/sso.js.map +0 -1
  523. package/dist/store.d.ts.map +0 -1
  524. package/dist/store.js.map +0 -1
  525. package/dist/tenant.d.ts.map +0 -1
  526. package/dist/tenant.js.map +0 -1
  527. package/dist/trace.d.ts.map +0 -1
  528. package/dist/trace.js.map +0 -1
  529. package/dist/version.d.ts.map +0 -1
  530. package/dist/version.js.map +0 -1
  531. package/dist/working-memory.d.ts.map +0 -1
  532. package/dist/working-memory.js.map +0 -1
  533. package/dist/yaml.d.ts.map +0 -1
  534. package/dist/yaml.js.map +0 -1
package/dist/client.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * HTTP client wrapper for `hippo serve`.
3
3
  *
4
- * Mirrors the function signatures in src/api.ts so the CLI can route through
5
- * either path uniformly. Each function takes (serverUrl, apiKey?, ...) and
6
- * returns the same shape that api.ts would.
4
+ * Only the writes the CLI routes (remember, forget, archive, promote), which are
5
+ * also all HIPPO_REQUIRE_SERVER covers; every other command opens the store
6
+ * directly. Each call returns the same shape that api.ts would.
7
7
  *
8
8
  * Errors from the server (4xx/5xx) are mapped back into thrown Errors with
9
9
  * the server's `error` message preserved verbatim so existing CLI handlers
@@ -13,9 +13,7 @@
13
13
  * Network errors (ECONNREFUSED on a stale pidfile, etc.) propagate as the
14
14
  * native fetch failure so the caller can detect them and self-heal.
15
15
  */
16
- import type { AuditEvent } from './audit.js';
17
- import type { ApiKeyListItem } from './auth.js';
18
- import type { RememberOpts, RememberResult, RecallOpts, RecallResult, AuthCreateOpts, AuthCreateResult, AuditListOpts } from './api.js';
16
+ import type { RememberOpts, RememberResult } from './api.js';
19
17
  /** An error the server answered with, not one the transport raised. The
20
18
  * refused-connection classifier sniffs message text, and a server message
21
19
  * quotes the caller's own id or content back verbatim. */
@@ -24,7 +22,6 @@ export declare class HttpResponseError extends Error {
24
22
  constructor(message: string, status: number);
25
23
  }
26
24
  export declare function remember(serverUrl: string, apiKey: string | undefined, opts: RememberOpts): Promise<RememberResult>;
27
- export declare function recall(serverUrl: string, apiKey: string | undefined, opts: RecallOpts): Promise<RecallResult>;
28
25
  export declare function forget(serverUrl: string, apiKey: string | undefined, id: string): Promise<{
29
26
  ok: true;
30
27
  id: string;
@@ -34,24 +31,10 @@ export declare function promote(serverUrl: string, apiKey: string | undefined, i
34
31
  sourceId: string;
35
32
  globalId: string;
36
33
  }>;
37
- export declare function supersede(serverUrl: string, apiKey: string | undefined, oldId: string, newContent: string): Promise<{
38
- ok: true;
39
- oldId: string;
40
- newId: string;
41
- }>;
42
34
  export declare function archiveRaw(serverUrl: string, apiKey: string | undefined, id: string, reason: string): Promise<{
43
35
  ok: true;
44
36
  archivedAt: string;
45
37
  }>;
46
- export declare function authCreate(serverUrl: string, apiKey: string | undefined, opts: AuthCreateOpts): Promise<AuthCreateResult>;
47
- export declare function authList(serverUrl: string, apiKey: string | undefined, opts: {
48
- active: boolean;
49
- }): Promise<ApiKeyListItem[]>;
50
- export declare function authRevoke(serverUrl: string, apiKey: string | undefined, keyId: string): Promise<{
51
- ok: true;
52
- revokedAt: string;
53
- }>;
54
- export declare function auditList(serverUrl: string, apiKey: string | undefined, opts: AuditListOpts): Promise<AuditEvent[]>;
55
38
  /**
56
39
  * How far a request got before the transport failed.
57
40
  *
package/dist/client.js CHANGED
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * HTTP client wrapper for `hippo serve`.
3
3
  *
4
- * Mirrors the function signatures in src/api.ts so the CLI can route through
5
- * either path uniformly. Each function takes (serverUrl, apiKey?, ...) and
6
- * returns the same shape that api.ts would.
4
+ * Only the writes the CLI routes (remember, forget, archive, promote), which are
5
+ * also all HIPPO_REQUIRE_SERVER covers; every other command opens the store
6
+ * directly. Each call returns the same shape that api.ts would.
7
7
  *
8
8
  * Errors from the server (4xx/5xx) are mapped back into thrown Errors with
9
9
  * the server's `error` message preserved verbatim so existing CLI handlers
@@ -65,52 +65,6 @@ export async function remember(serverUrl, apiKey, opts) {
65
65
  const result = await res.json();
66
66
  return result;
67
67
  }
68
- export async function recall(serverUrl, apiKey, opts) {
69
- const params = new URLSearchParams();
70
- params.set('q', opts.query);
71
- if (opts.limit !== undefined)
72
- params.set('limit', String(opts.limit));
73
- if (opts.mode !== undefined)
74
- params.set('mode', opts.mode);
75
- if (opts.scope !== undefined && opts.scope !== '')
76
- params.set('scope', opts.scope);
77
- if (opts.includeContinuity)
78
- params.set('include_continuity', '1');
79
- // v1.7.2 T4 — RecallOpts parity sweep. Pre-v1.7.2 the thin-client only
80
- // serialized the five fields above; the HTTP server already accepted
81
- // fresh_tail_count, fresh_tail_session_id, summarize_overflow. Adding
82
- // scorer_window alone would have perpetuated the drift. Serializing all
83
- // four together. Validation lives in api.recall(); transport just
84
- // forwards.
85
- if (opts.freshTailCount !== undefined)
86
- params.set('fresh_tail_count', String(opts.freshTailCount));
87
- if (opts.freshTailSessionId !== undefined && opts.freshTailSessionId !== '')
88
- params.set('fresh_tail_session_id', opts.freshTailSessionId);
89
- if (opts.summarizeOverflow !== undefined)
90
- params.set('summarize_overflow', opts.summarizeOverflow ? '1' : '0');
91
- if (opts.scorerWindow !== undefined)
92
- params.set('scorer_window', String(opts.scorerWindow));
93
- // v1.7.4 sessionId for dlPFC goal-stack boost + v0.33 / J1 sessionId
94
- // for per-session anchoring ring. Pre-v0.33 the thin-client silently
95
- // dropped opts.sessionId, so HTTP-routed SDK callers got no goal
96
- // boost and (post-J1) the HTTP ring logged recall_anchor_skipped_no_session.
97
- // Codex round-3 P2 catch: align serialization with the RecallOpts type.
98
- // Note: opts.recallHistory is intentionally NOT serialized — it is an
99
- // in-process snapshot only; the HTTP server maintains its own ring per
100
- // sessionId, so passing recallHistory over the wire would be a no-op
101
- // at best and a tenant-leak risk at worst.
102
- if (opts.sessionId !== undefined && opts.sessionId !== '') {
103
- params.set('session_id', opts.sessionId);
104
- }
105
- const res = await fetch(`${serverUrl}/v1/memories?${params.toString()}`, {
106
- method: 'GET',
107
- headers: buildHeaders(apiKey, false),
108
- });
109
- if (!res.ok)
110
- await throwForStatus(res);
111
- const result = await res.json();
112
- return result;
113
- }
114
68
  export async function forget(serverUrl, apiKey, id) {
115
69
  const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(id)}`, {
116
70
  method: 'DELETE',
@@ -131,17 +85,6 @@ export async function promote(serverUrl, apiKey, id) {
131
85
  const result = await res.json();
132
86
  return result;
133
87
  }
134
- export async function supersede(serverUrl, apiKey, oldId, newContent) {
135
- const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(oldId)}/supersede`, {
136
- method: 'POST',
137
- headers: buildHeaders(apiKey, true),
138
- body: JSON.stringify({ content: newContent }),
139
- });
140
- if (!res.ok)
141
- await throwForStatus(res);
142
- const result = await res.json();
143
- return result;
144
- }
145
88
  export async function archiveRaw(serverUrl, apiKey, id, reason) {
146
89
  const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/archive`, {
147
90
  method: 'POST',
@@ -153,58 +96,6 @@ export async function archiveRaw(serverUrl, apiKey, id, reason) {
153
96
  const result = await res.json();
154
97
  return result;
155
98
  }
156
- export async function authCreate(serverUrl, apiKey, opts) {
157
- const res = await fetch(`${serverUrl}/v1/auth/keys`, {
158
- method: 'POST',
159
- headers: buildHeaders(apiKey, true),
160
- body: JSON.stringify(opts),
161
- });
162
- if (!res.ok)
163
- await throwForStatus(res);
164
- const result = await res.json();
165
- return result;
166
- }
167
- export async function authList(serverUrl, apiKey, opts) {
168
- const params = new URLSearchParams();
169
- params.set('active', opts.active ? 'true' : 'false');
170
- const res = await fetch(`${serverUrl}/v1/auth/keys?${params.toString()}`, {
171
- method: 'GET',
172
- headers: buildHeaders(apiKey, false),
173
- });
174
- if (!res.ok)
175
- await throwForStatus(res);
176
- const result = await res.json();
177
- return result;
178
- }
179
- export async function authRevoke(serverUrl, apiKey, keyId) {
180
- const res = await fetch(`${serverUrl}/v1/auth/keys/${encodeURIComponent(keyId)}`, {
181
- method: 'DELETE',
182
- headers: buildHeaders(apiKey, false),
183
- });
184
- if (!res.ok)
185
- await throwForStatus(res);
186
- const result = await res.json();
187
- return result;
188
- }
189
- export async function auditList(serverUrl, apiKey, opts) {
190
- const params = new URLSearchParams();
191
- if (opts.op !== undefined)
192
- params.set('op', opts.op);
193
- if (opts.since !== undefined)
194
- params.set('since', opts.since);
195
- if (opts.limit !== undefined)
196
- params.set('limit', String(opts.limit));
197
- const qs = params.toString();
198
- const url = qs.length > 0 ? `${serverUrl}/v1/audit?${qs}` : `${serverUrl}/v1/audit`;
199
- const res = await fetch(url, {
200
- method: 'GET',
201
- headers: buildHeaders(apiKey, false),
202
- });
203
- if (!res.ok)
204
- await throwForStatus(res);
205
- const result = await res.json();
206
- return result;
207
- }
208
99
  function hasObjectCause(e) {
209
100
  // Node's fs/net system errors (ECONNREFUSED, ECONNRESET) attach the syscall
210
101
  // code on a non-null object `cause`; the strict-equality checks below
package/dist/config.js CHANGED
@@ -4,8 +4,9 @@
4
4
  import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import { DEFAULT_PHYSICS_CONFIG, mergePhysicsConfig } from './physics-config.js';
7
+ import { DEFAULT_HALF_LIFE_DAYS } from './memory.js';
7
8
  const DEFAULT_CONFIG = {
8
- defaultHalfLifeDays: 7,
9
+ defaultHalfLifeDays: DEFAULT_HALF_LIFE_DAYS,
9
10
  defaultBudget: 4000,
10
11
  defaultContextBudget: 3000,
11
12
  decayBasis: 'adaptive',
@@ -26,6 +26,8 @@ export interface ConsolidationResult {
26
26
  dryRun: boolean;
27
27
  details: string[];
28
28
  physicsSimulated: number;
29
+ /** Ids the decay pass removes (or would remove, under dryRun). */
30
+ removedIds?: string[];
29
31
  }
30
32
  /**
31
33
  * Run a full consolidation pass.
@@ -33,5 +35,6 @@ export interface ConsolidationResult {
33
35
  export declare function consolidate(hippoRoot: string, options?: {
34
36
  dryRun?: boolean;
35
37
  now?: Date;
38
+ fetcher?: typeof fetch;
36
39
  }): Promise<ConsolidationResult>;
37
40
  //# sourceMappingURL=consolidate.d.ts.map
@@ -7,7 +7,7 @@
7
7
  * 3. Stats tracking
8
8
  */
9
9
  import { evalNow, isRecallBoostAblated } from './ablation.js';
10
- import { Layer, calculateStrength, createMemory } from './memory.js';
10
+ import { Layer, calculateStrength, canAutoDelete, createMemory } from './memory.js';
11
11
  import { loadAllEntries, batchWriteAndDelete, appendConsolidationRun, replaceDetectedConflicts, loadSessionDecayContext, incrementSleepCount, findPromotableSessions, traceExistsForSession, listSessionEvents, } from './store.js';
12
12
  import { textOverlap, markRetrieved } from './search.js';
13
13
  import { compareEntryIdentity } from './compare.js';
@@ -91,6 +91,7 @@ export async function consolidate(hippoRoot, options = {}) {
91
91
  // with no cross-tenant dedup. The api.sleep audit row tags this with the
92
92
  // admin synthetic actor; see api.ts:2050 for the rationale.
93
93
  const all = loadAllEntries(hippoRoot);
94
+ const snapshot = new Map(structuredClone(all).map((e) => [e.id, e]));
94
95
  // Load decay options from config + session context
95
96
  const config = loadConfig(hippoRoot);
96
97
  const sessionCtx = loadSessionDecayContext(hippoRoot);
@@ -131,12 +132,12 @@ export async function consolidate(hippoRoot, options = {}) {
131
132
  for (const entry of all) {
132
133
  const strength = calculateStrength(entry, now, decayOpts);
133
134
  strengthById.set(entry.id, strength);
134
- if (!entry.pinned && strength < DECAY_THRESHOLD) {
135
+ if (canAutoDelete(entry) && strength < DECAY_THRESHOLD) {
135
136
  condemned.push(entry);
136
137
  }
137
138
  }
138
139
  // --- Phase 2a: rescue decision (pure compute) ---
139
- // Runs under --dry-run too (only pendingDeletes/the audit write in
140
+ // Runs under --dry-run too (only the pendingDeletes flush and the audit write in
140
141
  // "4. Log run" below stay !dryRun-gated), so the preview matches what a
141
142
  // real run would decide.
142
143
  const condemnedIds = new Set(condemned.map((e) => e.id));
@@ -173,7 +174,7 @@ export async function consolidate(hippoRoot, options = {}) {
173
174
  // preserves flag-off's ordering semantics exactly.)
174
175
  for (const entry of all) {
175
176
  const strength = strengthById.get(entry.id);
176
- if (!entry.pinned && strength < DECAY_THRESHOLD) {
177
+ if (canAutoDelete(entry) && strength < DECAY_THRESHOLD) {
177
178
  if (rescuedIds.has(entry.id)) {
178
179
  // Rescued (D1): standard survivor stored-strength refresh (P2-1).
179
180
  // Confidence is left alone here: it is an epistemic tier, not a
@@ -194,9 +195,7 @@ export async function consolidate(hippoRoot, options = {}) {
194
195
  else {
195
196
  result.removed++;
196
197
  result.details.push(` 🗑 removed ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`);
197
- if (!dryRun) {
198
- pendingDeletes.push(entry.id);
199
- }
198
+ pendingDeletes.push(entry.id);
200
199
  }
201
200
  }
202
201
  else {
@@ -212,12 +211,10 @@ export async function consolidate(hippoRoot, options = {}) {
212
211
  else {
213
212
  for (const entry of all) {
214
213
  const strength = calculateStrength(entry, now, decayOpts);
215
- if (!entry.pinned && strength < DECAY_THRESHOLD) {
214
+ if (canAutoDelete(entry) && strength < DECAY_THRESHOLD) {
216
215
  result.removed++;
217
216
  result.details.push(` 🗑 removed ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`);
218
- if (!dryRun) {
219
- pendingDeletes.push(entry.id);
220
- }
217
+ pendingDeletes.push(entry.id);
221
218
  }
222
219
  else {
223
220
  // Only strength is a cached computation; confidence stays as stored.
@@ -423,26 +420,34 @@ export async function consolidate(hippoRoot, options = {}) {
423
420
  // 1.6. Batch extraction — extract facts from episodic memories missing them
424
421
  // -------------------------------------------------------------------------
425
422
  const extractedFromIds = new Set(survivors.filter((e) => e.extracted_from).map((e) => e.extracted_from));
426
- const extractionCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !extractedFromIds.has(e.id));
423
+ const extractionCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !extractedFromIds.has(e.id));
427
424
  result.extractionCandidates = extractionCandidates.length;
428
- const apiKey = process.env.ANTHROPIC_API_KEY ?? '';
425
+ // extraction.enabled=false is the opt-out for every LLM phase below, key or no key.
426
+ const apiKey = config.extraction.enabled !== false ? (process.env.ANTHROPIC_API_KEY ?? '') : '';
427
+ const llmErrorsSeen = new Set();
428
+ const llmError = (phase) => (msg) => {
429
+ const line = ` ⚠️ ${phase}: ${msg}`;
430
+ if (llmErrorsSeen.has(line))
431
+ return;
432
+ llmErrorsSeen.add(line);
433
+ result.details.push(line);
434
+ console.error(`consolidate ${phase}: ${msg}`);
435
+ };
436
+ const llmOpts = { apiKey, model: config.extraction.model, fetcher: options.fetcher };
429
437
  if (apiKey && extractionCandidates.length > 0 && !dryRun) {
430
438
  const { extractFacts, storeExtractedFacts } = await import('./extract.js');
431
439
  const batchLimit = 20;
432
440
  let extractedCount = 0;
433
441
  for (const candidate of extractionCandidates.slice(0, batchLimit)) {
434
442
  try {
435
- const facts = await extractFacts(candidate.content, {
436
- apiKey,
437
- model: config.extraction.model,
438
- });
443
+ const facts = await extractFacts(candidate.content, { ...llmOpts, onError: llmError('extraction') });
439
444
  if (facts.length > 0) {
440
445
  storeExtractedFacts(hippoRoot, candidate, facts);
441
446
  extractedCount += facts.length;
442
447
  }
443
448
  }
444
- catch {
445
- // Best-effort — continue with next candidate
449
+ catch (err) {
450
+ llmError('extraction')(String(err));
446
451
  }
447
452
  }
448
453
  result.extracted = extractedCount;
@@ -450,22 +455,19 @@ export async function consolidate(hippoRoot, options = {}) {
450
455
  // -------------------------------------------------------------------------
451
456
  // 1.7. DAG summarization — cluster extracted facts and generate summaries
452
457
  // -------------------------------------------------------------------------
453
- const extractedFacts = survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1);
458
+ const extractedFacts = survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1 && !e.superseded_by);
454
459
  if (apiKey && extractedFacts.length >= 3 && !dryRun) {
455
460
  try {
456
461
  const { buildDag } = await import('./dag.js');
457
- const dagResult = await buildDag(hippoRoot, extractedFacts, {
458
- apiKey,
459
- model: config.extraction.model,
460
- });
462
+ const dagResult = await buildDag(hippoRoot, extractedFacts, { ...llmOpts, onError: llmError('dag') });
461
463
  result.dagCandidateClusters = dagResult.candidateClusters;
462
464
  result.dagSummariesCreated = dagResult.summariesCreated;
463
465
  if (dagResult.summariesCreated > 0) {
464
466
  result.details.push(` 🌳 DAG: ${dagResult.summariesCreated} summaries created, ${dagResult.factsLinked} facts linked`);
465
467
  }
466
468
  }
467
- catch {
468
- // Best-effort
469
+ catch (err) {
470
+ llmError('dag')(String(err));
469
471
  }
470
472
  }
471
473
  // -------------------------------------------------------------------------
@@ -485,11 +487,7 @@ export async function consolidate(hippoRoot, options = {}) {
485
487
  const cap = Number.isFinite(rawCap) && rawCap > 0
486
488
  ? Math.min(rawCap, 1000)
487
489
  : 20;
488
- const rebuildResult = await rebuildDirtySummaries(hippoRoot, {
489
- apiKey,
490
- model: config.extraction.model,
491
- cap,
492
- });
490
+ const rebuildResult = await rebuildDirtySummaries(hippoRoot, { ...llmOpts, onError: llmError('dag rebuild'), cap });
493
491
  result.summariesRebuilt = rebuildResult.rebuilt;
494
492
  result.summariesRebuildFailed = rebuildResult.failed;
495
493
  result.summariesZeroChildSkipped = rebuildResult.zeroChildSkipped;
@@ -510,8 +508,8 @@ export async function consolidate(hippoRoot, options = {}) {
510
508
  result.details.push(` 🌳 DAG rebuild: ${parts.join(', ')}`);
511
509
  }
512
510
  }
513
- catch {
514
- // Best-effort — same posture as buildDag block above.
511
+ catch (err) {
512
+ llmError('dag rebuild')(String(err));
515
513
  }
516
514
  }
517
515
  // -------------------------------------------------------------------------
@@ -529,18 +527,15 @@ export async function consolidate(hippoRoot, options = {}) {
529
527
  const { loadAllL2Summaries } = await import('./store.js');
530
528
  const l2Summaries = loadAllL2Summaries(hippoRoot);
531
529
  if (l2Summaries.length >= 2) {
532
- const profileResult = await buildEntityProfiles(hippoRoot, l2Summaries, {
533
- apiKey,
534
- model: config.extraction.model,
535
- });
530
+ const profileResult = await buildEntityProfiles(hippoRoot, l2Summaries, { ...llmOpts, onError: llmError('dag profiles') });
536
531
  result.entityProfilesCreated = profileResult.profilesCreated;
537
532
  if (profileResult.profilesCreated > 0) {
538
533
  result.details.push(` 🌲 DAG L3: ${profileResult.profilesCreated} entity profiles, ${profileResult.l2sLinked} L2s linked`);
539
534
  }
540
535
  }
541
536
  }
542
- catch {
543
- // Best-effort.
537
+ catch (err) {
538
+ llmError('dag profiles')(String(err));
544
539
  }
545
540
  }
546
541
  // -------------------------------------------------------------------------
@@ -599,7 +594,7 @@ export async function consolidate(hippoRoot, options = {}) {
599
594
  // -------------------------------------------------------------------------
600
595
  // 3. Merge pass - episodic entries only
601
596
  // -------------------------------------------------------------------------
602
- const mergeCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.tags.includes('extracted'));
597
+ const mergeCandidates = survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !e.tags.includes('extracted'));
603
598
  const used = new Set();
604
599
  // T1 fix (2026-08-15 hardening pass): partition by tenantId BEFORE the
605
600
  // overlap loop so a cluster can never span tenants. Previously textOverlap
@@ -735,9 +730,16 @@ export async function consolidate(hippoRoot, options = {}) {
735
730
  if (mergesSkippedRejected > 0) {
736
731
  console.error(`consolidate: skipped ${mergesSkippedRejected} merge(s) whose content matches a rejected value`);
737
732
  }
738
- // Flush all writes/deletes in a single transaction
733
+ result.removedIds = pendingDeletes;
734
+ // One transaction; the snapshot keeps what the DAG passes and other writers changed while sleep ran.
739
735
  if (!dryRun) {
740
- batchWriteAndDelete(hippoRoot, pendingWrites, pendingDeletes);
736
+ const deleted = new Set(batchWriteAndDelete(hippoRoot, pendingWrites, pendingDeletes, { snapshot }));
737
+ for (const id of pendingDeletes) {
738
+ if (!deleted.has(id))
739
+ result.details.push(` ↩ ${id} not removed: pinned or already gone before sleep saved`);
740
+ }
741
+ result.removedIds = pendingDeletes.filter((id) => deleted.has(id));
742
+ result.removed = result.removedIds.length;
741
743
  }
742
744
  // -------------------------------------------------------------------------
743
745
  // 4. Log run
package/dist/dag.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface DagSummaryOptions {
9
9
  apiKey: string;
10
10
  model?: string;
11
11
  fetcher?: typeof fetch;
12
+ onError?: (msg: string) => void;
12
13
  }
13
14
  export declare function generateDagSummary(label: string, factContents: string[], opts: DagSummaryOptions): Promise<string | null>;
14
15
  export interface DagBuildResult {
package/dist/dag.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { createMemory, Layer } from './memory.js';
2
2
  import { writeEntry, loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from './store.js';
3
3
  import { RejectedValueError } from './rejection.js';
4
+ import { redactSecrets } from './secret-detect.js';
4
5
  export function clusterFacts(facts) {
5
6
  if (facts.length === 0)
6
7
  return [];
@@ -42,9 +43,9 @@ Write a single concise paragraph (2-4 sentences) that captures all the key infor
42
43
  export async function generateDagSummary(label, factContents, opts) {
43
44
  const model = opts.model ?? 'claude-sonnet-4-6';
44
45
  const fetchFn = opts.fetcher ?? fetch;
45
- const factsBlock = factContents.map((f, i) => `${i + 1}. ${f}`).join('\n');
46
+ const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecrets(f)}`).join('\n');
46
47
  const prompt = DAG_SUMMARY_PROMPT
47
- .replace('{label}', label)
48
+ .replace('{label}', redactSecrets(label))
48
49
  .replace('{facts}', factsBlock);
49
50
  let res;
50
51
  try {
@@ -62,17 +63,21 @@ export async function generateDagSummary(label, factContents, opts) {
62
63
  }),
63
64
  });
64
65
  }
65
- catch {
66
+ catch (err) {
67
+ opts.onError?.(`request failed: ${err instanceof Error ? err.message : String(err)}`);
66
68
  return null;
67
69
  }
68
- if (!res.ok)
70
+ if (!res.ok) {
71
+ opts.onError?.(`HTTP ${res.status}`);
69
72
  return null;
73
+ }
70
74
  try {
71
75
  const data = await res.json();
72
76
  const text = data.content?.[0]?.text?.trim() ?? '';
73
77
  return text.length >= 20 ? text : null;
74
78
  }
75
- catch {
79
+ catch (err) {
80
+ opts.onError?.(`unparseable response: ${err instanceof Error ? err.message : String(err)}`);
76
81
  return null;
77
82
  }
78
83
  }
package/dist/dashboard.js CHANGED
@@ -14,6 +14,7 @@ import { listPeers } from './shared.js';
14
14
  import { loadEmbeddingIndex } from './embeddings.js';
15
15
  import { resolveTenantId } from './tenant.js';
16
16
  import { loadCardDetail } from './card-detail.js';
17
+ import { isCrossSite, LOOPBACK_HOST_HEADER } from './server.js';
17
18
  function buildDashboardData(hippoRoot) {
18
19
  // A5: scope dashboard to active tenant. Without this, the UI surfaces every
19
20
  // tenant's memories on a multi-tenant deployment.
@@ -122,8 +123,6 @@ const MIME_TYPES = {
122
123
  '.ico': 'image/x-icon',
123
124
  '.woff2': 'font/woff2',
124
125
  };
125
- // Binds 127.0.0.1 only; refusing other Hosts closes the DNS-rebinding route.
126
- const LOOPBACK_HOST = /^(localhost|127\.0\.0\.1)(:\d+)?$/i;
127
126
  function isStaticFileExtension(ext) {
128
127
  return Object.hasOwn(MIME_TYPES, ext);
129
128
  }
@@ -156,7 +155,7 @@ export function serveDashboard(hippoRoot, port = 3333) {
156
155
  const hasDistUi = fs.existsSync(path.join(distUiDir, 'index.html'));
157
156
  const handleRequest = (req, res) => {
158
157
  const host = req.headers.host;
159
- if (host !== undefined && !LOOPBACK_HOST.test(host)) {
158
+ if (host !== undefined && !LOOPBACK_HOST_HEADER.test(host)) {
160
159
  res.writeHead(403, { 'Content-Type': 'text/plain' });
161
160
  res.end('Forbidden');
162
161
  return;
@@ -168,6 +167,11 @@ export function serveDashboard(hippoRoot, port = 3333) {
168
167
  // POST /api/star/:id - toggle starred on a memory
169
168
  const starMatch = pathname.match(/^\/api\/star\/([A-Za-z0-9_\-]+)$/);
170
169
  if (starMatch && req.method === 'POST') {
170
+ if (isCrossSite(req)) {
171
+ res.writeHead(403, { 'Content-Type': 'text/plain' });
172
+ res.end('Forbidden');
173
+ return;
174
+ }
171
175
  const id = starMatch[1];
172
176
  const entry = readEntry(hippoRoot, id, resolveTenantId({}));
173
177
  if (!entry)
package/dist/db.js CHANGED
@@ -2389,16 +2389,12 @@ export function getHippoDbPath(hippoRoot) {
2389
2389
  export function getCurrentSchemaVersion() {
2390
2390
  return CURRENT_SCHEMA_VERSION;
2391
2391
  }
2392
- function readMinCompatibleBinary(db) {
2393
- // Tolerate the meta table not yet existing on a fresh DB.
2394
- try {
2395
- // SAFETY: row's shape matches the single `value` column named in the
2396
- // SELECT above.
2397
- const row = db.prepare(`SELECT value FROM meta WHERE key = 'min_compatible_binary'`).get();
2398
- return row?.value ?? null;
2399
- }
2400
- catch {
2401
- return null;
2392
+ /** Refuse a store stamped for a newer binary. Fails closed: runMigrations creates meta first, so a failed read is a real error. */
2393
+ function assertBinaryCompatible(db) {
2394
+ const minRequired = getMeta(db, 'min_compatible_binary');
2395
+ if (minRequired && compareSemver(minRequired, PACKAGE_VERSION) > 0) {
2396
+ throw new Error(`hippo-memory: this database requires hippo-memory >= ${minRequired}, but the running binary is ${PACKAGE_VERSION}. ` +
2397
+ `Upgrade hippo-memory to open it; an older binary does not know this schema and could expose private rows or damage the store.`);
2402
2398
  }
2403
2399
  }
2404
2400
  function isSqliteBusy(error) {
@@ -2456,17 +2452,8 @@ export function openHippoDb(hippoRoot) {
2456
2452
  }
2457
2453
  function runMigrations(db, hippoRoot) {
2458
2454
  ensureMetaTable(db);
2459
- // v1.3.1 rollback-safety guard. Schema v24 stamped meta.min_compatible_binary;
2460
- // older binaries that lack the generic *:private:* default-deny filter would
2461
- // leak github:private:* rows on no-scope recall. Refuse to open a DB stamped
2462
- // with a min newer than this binary's version. Read BEFORE migrations so a
2463
- // stale v1.2.0 binary cannot apply unknown future migrations either.
2464
- const minRequired = readMinCompatibleBinary(db);
2465
- if (minRequired && compareSemver(minRequired, PACKAGE_VERSION) > 0) {
2466
- throw new Error(`hippo-memory: this database requires hippo-memory >= ${minRequired}, but the running binary is ${PACKAGE_VERSION}. ` +
2467
- `Upgrade hippo-memory to open this database. Running an older binary against this DB would leak private rows that the ` +
2468
- `older filter does not recognize.`);
2469
- }
2455
+ // Before anything writes, so a stale binary never repairs or migrates a store it does not understand.
2456
+ assertBinaryCompatible(db);
2470
2457
  let currentVersion = getSchemaVersion(db);
2471
2458
  if (currentVersion > 0)
2472
2459
  ensureContinuityTables(db);
@@ -2475,6 +2462,8 @@ function runMigrations(db, hippoRoot) {
2475
2462
  continue;
2476
2463
  execWithBusyRetry(db, 'BEGIN IMMEDIATE');
2477
2464
  try {
2465
+ // A newer binary may have migrated and raised the minimum while we waited for the lock.
2466
+ assertBinaryCompatible(db);
2478
2467
  // Re-read under the write lock: another process may have applied this
2479
2468
  // migration while we waited, and re-running one is not idempotent.
2480
2469
  const applied = getSchemaVersion(db);
@@ -2489,7 +2478,10 @@ function runMigrations(db, hippoRoot) {
2489
2478
  currentVersion = migration.version;
2490
2479
  }
2491
2480
  catch (error) {
2492
- db.exec('ROLLBACK');
2481
+ try {
2482
+ db.exec('ROLLBACK');
2483
+ }
2484
+ catch { /* already rolled back; keep the original error */ }
2493
2485
  throw error;
2494
2486
  }
2495
2487
  }
@@ -2669,8 +2661,8 @@ function ensureOptionalFts(db) {
2669
2661
  backfillFtsIndex(db);
2670
2662
  available = true;
2671
2663
  }
2672
- catch {
2673
- available = false;
2664
+ catch (err) {
2665
+ console.error(`hippo: full-text index unavailable (${err instanceof Error ? err.message : String(err)}); search falls back to slower LIKE matching`);
2674
2666
  }
2675
2667
  // Read-first: only write when the flag actually changed, so a healthy
2676
2668
  // store's open doesn't take a write lock for a same-value upsert.
package/dist/dedupe.d.ts CHANGED
@@ -70,5 +70,6 @@ export declare function strengthBucket(strength: number | null | undefined): num
70
70
  export declare function deduplicateStore(hippoRoot: string, options?: {
71
71
  threshold?: number;
72
72
  dryRun?: boolean;
73
+ actor?: string;
73
74
  }): DedupResult;
74
75
  //# sourceMappingURL=dedupe.d.ts.map
package/dist/dedupe.js CHANGED
@@ -23,6 +23,7 @@
23
23
  import { textOverlap } from './search.js';
24
24
  import { loadAllEntries, deleteEntry } from './store.js';
25
25
  import { compareEntryIdentity } from './compare.js';
26
+ import { canAutoDelete } from './memory.js';
26
27
  /** Quantization step for strength-tie comparisons. The historical 0.01
27
28
  * epsilon (see `strengthBucket` below) applied via rounding instead of a
28
29
  * raw abs-diff threshold, so the tiebreak is transitive. */
@@ -111,7 +112,7 @@ export function deduplicateStore(hippoRoot, options = {}) {
111
112
  if (removed.has(tenantEntries[i].id))
112
113
  continue;
113
114
  for (let j = i + 1; j < tenantEntries.length; j++) {
114
- if (removed.has(tenantEntries[j].id))
115
+ if (removed.has(tenantEntries[j].id) || !canAutoDelete(tenantEntries[j]))
115
116
  continue;
116
117
  const similarity = textOverlap(tenantEntries[i].content, tenantEntries[j].content);
117
118
  if (similarity <= threshold)
@@ -131,11 +132,7 @@ export function deduplicateStore(hippoRoot, options = {}) {
131
132
  }
132
133
  }
133
134
  }
134
- if (!dryRun) {
135
- for (const id of removed) {
136
- deleteEntry(hippoRoot, id);
137
- }
138
- }
139
- return { removed: removed.size, pairs };
135
+ const done = dryRun ? pairs : pairs.filter((p) => deleteEntry(hippoRoot, p.removed, { actor: options.actor, reason: `dedup: duplicate of ${p.kept}`, automatic: true }));
136
+ return { removed: done.length, pairs: done };
140
137
  }
141
138
  //# sourceMappingURL=dedupe.js.map
@@ -4,7 +4,7 @@
4
4
  * The local `@huggingface/transformers` path stays the zero-DEPENDENCY DEFAULT. Opt-in
5
5
  * API providers (OpenAI / Voyage / Cohere) let a user bring a frontier embedder
6
6
  * (e.g. text-embedding-3-large) for frontier-class retrieval. They use the native
7
- * `fetch` global (Node >= 22.5, see package.json engines — NO new dependency) and
7
+ * `fetch` global (Node >= 22.16, see package.json engines; NO new dependency) and
8
8
  * read their key from a conventional env var. The provider is selected by
9
9
  * `config.embeddings.provider` (default `'local'`).
10
10
  *