hippo-memory 1.44.0 → 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 (528) hide show
  1. package/README.md +12 -10
  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.d.ts +1 -1
  6. package/dist/audit.js +9 -0
  7. package/dist/autolearn.d.ts +1 -1
  8. package/dist/autolearn.js +2 -1
  9. package/dist/cli.d.ts +3 -0
  10. package/dist/cli.js +151 -72
  11. package/dist/client.d.ts +4 -21
  12. package/dist/client.js +3 -112
  13. package/dist/config.js +2 -1
  14. package/dist/consolidate.d.ts +3 -0
  15. package/dist/consolidate.js +44 -42
  16. package/dist/dag.d.ts +1 -0
  17. package/dist/dag.js +10 -5
  18. package/dist/dashboard.js +7 -3
  19. package/dist/db.js +12 -23
  20. package/dist/dedupe.d.ts +1 -0
  21. package/dist/dedupe.js +4 -7
  22. package/dist/embedding-provider.js +2 -1
  23. package/dist/embeddings.js +81 -8
  24. package/dist/extract.d.ts +2 -0
  25. package/dist/extract.js +9 -4
  26. package/dist/mcp/server.js +21 -36
  27. package/dist/memory.d.ts +3 -0
  28. package/dist/memory.js +7 -1
  29. package/dist/refine-llm.js +3 -2
  30. package/dist/rerankers/jev.js +3 -2
  31. package/dist/rerankers/llm.js +3 -2
  32. package/dist/search.js +3 -3
  33. package/dist/server.d.ts +5 -0
  34. package/dist/server.js +39 -29
  35. package/dist/shared.js +1 -1
  36. package/dist/store.d.ts +18 -11
  37. package/dist/store.js +144 -63
  38. package/dist/version.d.ts +4 -6
  39. package/dist/version.js +4 -7
  40. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  41. package/extensions/openclaw-plugin/package.json +1 -1
  42. package/openclaw.plugin.json +1 -1
  43. package/package.json +6 -3
  44. package/dist/ablation.d.ts.map +0 -1
  45. package/dist/ablation.js.map +0 -1
  46. package/dist/ambient.d.ts.map +0 -1
  47. package/dist/ambient.js.map +0 -1
  48. package/dist/api.d.ts.map +0 -1
  49. package/dist/api.js.map +0 -1
  50. package/dist/audit-prune.d.ts.map +0 -1
  51. package/dist/audit-prune.js.map +0 -1
  52. package/dist/audit.d.ts.map +0 -1
  53. package/dist/audit.js.map +0 -1
  54. package/dist/auth.d.ts.map +0 -1
  55. package/dist/auth.js.map +0 -1
  56. package/dist/autolearn.d.ts.map +0 -1
  57. package/dist/autolearn.js.map +0 -1
  58. package/dist/availability.d.ts.map +0 -1
  59. package/dist/availability.js.map +0 -1
  60. package/dist/benchmarks/e1.3/incident-recall-eval.js +0 -78
  61. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +0 -1
  62. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +0 -103
  63. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +0 -1
  64. package/dist/capture.d.ts.map +0 -1
  65. package/dist/capture.js.map +0 -1
  66. package/dist/card-detail.d.ts.map +0 -1
  67. package/dist/card-detail.js.map +0 -1
  68. package/dist/card.d.ts.map +0 -1
  69. package/dist/card.js.map +0 -1
  70. package/dist/cli.d.ts.map +0 -1
  71. package/dist/cli.js.map +0 -1
  72. package/dist/client.d.ts.map +0 -1
  73. package/dist/client.js.map +0 -1
  74. package/dist/compare.d.ts.map +0 -1
  75. package/dist/compare.js.map +0 -1
  76. package/dist/config.d.ts.map +0 -1
  77. package/dist/config.js.map +0 -1
  78. package/dist/connectors/github/backfill.d.ts.map +0 -1
  79. package/dist/connectors/github/backfill.js.map +0 -1
  80. package/dist/connectors/github/cli-impl.d.ts.map +0 -1
  81. package/dist/connectors/github/cli-impl.js.map +0 -1
  82. package/dist/connectors/github/deletion.d.ts.map +0 -1
  83. package/dist/connectors/github/deletion.js.map +0 -1
  84. package/dist/connectors/github/dlq.d.ts.map +0 -1
  85. package/dist/connectors/github/dlq.js.map +0 -1
  86. package/dist/connectors/github/idempotency.d.ts.map +0 -1
  87. package/dist/connectors/github/idempotency.js.map +0 -1
  88. package/dist/connectors/github/ingest.d.ts.map +0 -1
  89. package/dist/connectors/github/ingest.js.map +0 -1
  90. package/dist/connectors/github/octokit-client.d.ts.map +0 -1
  91. package/dist/connectors/github/octokit-client.js.map +0 -1
  92. package/dist/connectors/github/ratelimit.d.ts.map +0 -1
  93. package/dist/connectors/github/ratelimit.js.map +0 -1
  94. package/dist/connectors/github/scope.d.ts.map +0 -1
  95. package/dist/connectors/github/scope.js.map +0 -1
  96. package/dist/connectors/github/signature.d.ts.map +0 -1
  97. package/dist/connectors/github/signature.js.map +0 -1
  98. package/dist/connectors/github/tenant-routing.d.ts.map +0 -1
  99. package/dist/connectors/github/tenant-routing.js.map +0 -1
  100. package/dist/connectors/github/transform.d.ts.map +0 -1
  101. package/dist/connectors/github/transform.js.map +0 -1
  102. package/dist/connectors/github/types.d.ts.map +0 -1
  103. package/dist/connectors/github/types.js.map +0 -1
  104. package/dist/connectors/slack/backfill.d.ts.map +0 -1
  105. package/dist/connectors/slack/backfill.js.map +0 -1
  106. package/dist/connectors/slack/deletion.d.ts.map +0 -1
  107. package/dist/connectors/slack/deletion.js.map +0 -1
  108. package/dist/connectors/slack/dlq.d.ts.map +0 -1
  109. package/dist/connectors/slack/dlq.js.map +0 -1
  110. package/dist/connectors/slack/idempotency.d.ts.map +0 -1
  111. package/dist/connectors/slack/idempotency.js.map +0 -1
  112. package/dist/connectors/slack/ingest.d.ts.map +0 -1
  113. package/dist/connectors/slack/ingest.js.map +0 -1
  114. package/dist/connectors/slack/ratelimit.d.ts.map +0 -1
  115. package/dist/connectors/slack/ratelimit.js.map +0 -1
  116. package/dist/connectors/slack/scope.d.ts.map +0 -1
  117. package/dist/connectors/slack/scope.js.map +0 -1
  118. package/dist/connectors/slack/signature.d.ts.map +0 -1
  119. package/dist/connectors/slack/signature.js.map +0 -1
  120. package/dist/connectors/slack/tenant-routing.d.ts.map +0 -1
  121. package/dist/connectors/slack/tenant-routing.js.map +0 -1
  122. package/dist/connectors/slack/transform.d.ts.map +0 -1
  123. package/dist/connectors/slack/transform.js.map +0 -1
  124. package/dist/connectors/slack/types.d.ts.map +0 -1
  125. package/dist/connectors/slack/types.js.map +0 -1
  126. package/dist/connectors/slack/web-client.d.ts.map +0 -1
  127. package/dist/connectors/slack/web-client.js.map +0 -1
  128. package/dist/connectors/slack/workspaces.d.ts.map +0 -1
  129. package/dist/connectors/slack/workspaces.js.map +0 -1
  130. package/dist/consolidate.d.ts.map +0 -1
  131. package/dist/consolidate.js.map +0 -1
  132. package/dist/correction-latency.d.ts.map +0 -1
  133. package/dist/correction-latency.js.map +0 -1
  134. package/dist/customer-notes.d.ts.map +0 -1
  135. package/dist/customer-notes.js.map +0 -1
  136. package/dist/dag.d.ts.map +0 -1
  137. package/dist/dag.js.map +0 -1
  138. package/dist/dashboard.d.ts.map +0 -1
  139. package/dist/dashboard.js.map +0 -1
  140. package/dist/db.d.ts.map +0 -1
  141. package/dist/db.js.map +0 -1
  142. package/dist/decisions.d.ts.map +0 -1
  143. package/dist/decisions.js.map +0 -1
  144. package/dist/dedupe.d.ts.map +0 -1
  145. package/dist/dedupe.js.map +0 -1
  146. package/dist/embedding-provider.d.ts.map +0 -1
  147. package/dist/embedding-provider.js.map +0 -1
  148. package/dist/embeddings.d.ts.map +0 -1
  149. package/dist/embeddings.js.map +0 -1
  150. package/dist/eval-suite.d.ts.map +0 -1
  151. package/dist/eval-suite.js.map +0 -1
  152. package/dist/eval.d.ts.map +0 -1
  153. package/dist/eval.js.map +0 -1
  154. package/dist/extensions/openclaw-plugin/index.js.map +0 -1
  155. package/dist/extract.d.ts.map +0 -1
  156. package/dist/extract.js.map +0 -1
  157. package/dist/forward-claim-detector.d.ts.map +0 -1
  158. package/dist/forward-claim-detector.js.map +0 -1
  159. package/dist/goals.d.ts.map +0 -1
  160. package/dist/goals.js.map +0 -1
  161. package/dist/graph-extract.d.ts.map +0 -1
  162. package/dist/graph-extract.js.map +0 -1
  163. package/dist/graph-recall.d.ts.map +0 -1
  164. package/dist/graph-recall.js.map +0 -1
  165. package/dist/graph-stream.d.ts.map +0 -1
  166. package/dist/graph-stream.js.map +0 -1
  167. package/dist/graph-view.d.ts.map +0 -1
  168. package/dist/graph-view.js.map +0 -1
  169. package/dist/graph.d.ts.map +0 -1
  170. package/dist/graph.js.map +0 -1
  171. package/dist/handoff.d.ts.map +0 -1
  172. package/dist/handoff.js.map +0 -1
  173. package/dist/hooks.d.ts.map +0 -1
  174. package/dist/hooks.js.map +0 -1
  175. package/dist/importers.d.ts.map +0 -1
  176. package/dist/importers.js.map +0 -1
  177. package/dist/incidents.d.ts.map +0 -1
  178. package/dist/incidents.js.map +0 -1
  179. package/dist/index.d.ts.map +0 -1
  180. package/dist/index.js.map +0 -1
  181. package/dist/invalidation.d.ts.map +0 -1
  182. package/dist/invalidation.js.map +0 -1
  183. package/dist/mcp/framing.d.ts.map +0 -1
  184. package/dist/mcp/framing.js.map +0 -1
  185. package/dist/mcp/server.d.ts.map +0 -1
  186. package/dist/mcp/server.js.map +0 -1
  187. package/dist/memory-value-weights.d.ts.map +0 -1
  188. package/dist/memory-value-weights.js.map +0 -1
  189. package/dist/memory-value.d.ts.map +0 -1
  190. package/dist/memory-value.js.map +0 -1
  191. package/dist/memory.d.ts.map +0 -1
  192. package/dist/memory.js.map +0 -1
  193. package/dist/multihop.d.ts.map +0 -1
  194. package/dist/multihop.js.map +0 -1
  195. package/dist/owner-validation.d.ts.map +0 -1
  196. package/dist/owner-validation.js.map +0 -1
  197. package/dist/path-context.d.ts.map +0 -1
  198. package/dist/path-context.js.map +0 -1
  199. package/dist/physics-config.d.ts.map +0 -1
  200. package/dist/physics-config.js.map +0 -1
  201. package/dist/physics-state.d.ts.map +0 -1
  202. package/dist/physics-state.js.map +0 -1
  203. package/dist/physics.d.ts.map +0 -1
  204. package/dist/physics.js.map +0 -1
  205. package/dist/policies.d.ts.map +0 -1
  206. package/dist/policies.js.map +0 -1
  207. package/dist/postinstall.d.ts.map +0 -1
  208. package/dist/postinstall.js.map +0 -1
  209. package/dist/predictions.d.ts.map +0 -1
  210. package/dist/predictions.js.map +0 -1
  211. package/dist/processes.d.ts.map +0 -1
  212. package/dist/processes.js.map +0 -1
  213. package/dist/project-briefs.d.ts.map +0 -1
  214. package/dist/project-briefs.js.map +0 -1
  215. package/dist/project-identity.d.ts.map +0 -1
  216. package/dist/project-identity.js.map +0 -1
  217. package/dist/provenance-coverage.d.ts.map +0 -1
  218. package/dist/provenance-coverage.js.map +0 -1
  219. package/dist/rate-limit.d.ts.map +0 -1
  220. package/dist/rate-limit.js.map +0 -1
  221. package/dist/raw-archive-mirror-cleanup.d.ts.map +0 -1
  222. package/dist/raw-archive-mirror-cleanup.js.map +0 -1
  223. package/dist/raw-archive.d.ts.map +0 -1
  224. package/dist/raw-archive.js.map +0 -1
  225. package/dist/recall-history.d.ts.map +0 -1
  226. package/dist/recall-history.js.map +0 -1
  227. package/dist/recall-scope.d.ts.map +0 -1
  228. package/dist/recall-scope.js.map +0 -1
  229. package/dist/recall-trace.d.ts.map +0 -1
  230. package/dist/recall-trace.js.map +0 -1
  231. package/dist/refine-llm.d.ts.map +0 -1
  232. package/dist/refine-llm.js.map +0 -1
  233. package/dist/reject-flow.d.ts.map +0 -1
  234. package/dist/reject-flow.js.map +0 -1
  235. package/dist/rejection.d.ts.map +0 -1
  236. package/dist/rejection.js.map +0 -1
  237. package/dist/replay.d.ts.map +0 -1
  238. package/dist/replay.js.map +0 -1
  239. package/dist/rerankers/cross-encoder.d.ts.map +0 -1
  240. package/dist/rerankers/cross-encoder.js.map +0 -1
  241. package/dist/rerankers/index.d.ts.map +0 -1
  242. package/dist/rerankers/index.js.map +0 -1
  243. package/dist/rerankers/jev.d.ts.map +0 -1
  244. package/dist/rerankers/jev.js.map +0 -1
  245. package/dist/rerankers/llm.d.ts.map +0 -1
  246. package/dist/rerankers/llm.js.map +0 -1
  247. package/dist/rerankers/types.d.ts.map +0 -1
  248. package/dist/rerankers/types.js.map +0 -1
  249. package/dist/rrf.d.ts.map +0 -1
  250. package/dist/rrf.js.map +0 -1
  251. package/dist/salience.d.ts.map +0 -1
  252. package/dist/salience.js.map +0 -1
  253. package/dist/scheduler.d.ts.map +0 -1
  254. package/dist/scheduler.js.map +0 -1
  255. package/dist/scope.d.ts.map +0 -1
  256. package/dist/scope.js.map +0 -1
  257. package/dist/search.d.ts.map +0 -1
  258. package/dist/search.js.map +0 -1
  259. package/dist/secret-detect.d.ts.map +0 -1
  260. package/dist/secret-detect.js.map +0 -1
  261. package/dist/server-detect.d.ts.map +0 -1
  262. package/dist/server-detect.js.map +0 -1
  263. package/dist/server.d.ts.map +0 -1
  264. package/dist/server.js.map +0 -1
  265. package/dist/shared.d.ts.map +0 -1
  266. package/dist/shared.js.map +0 -1
  267. package/dist/skills.d.ts.map +0 -1
  268. package/dist/skills.js.map +0 -1
  269. package/dist/sleep-redact.d.ts +0 -58
  270. package/dist/sleep-redact.d.ts.map +0 -1
  271. package/dist/sleep-redact.js +0 -80
  272. package/dist/sleep-redact.js.map +0 -1
  273. package/dist/src/ablation.js +0 -138
  274. package/dist/src/ablation.js.map +0 -1
  275. package/dist/src/ambient.js +0 -148
  276. package/dist/src/ambient.js.map +0 -1
  277. package/dist/src/api.js +0 -2109
  278. package/dist/src/api.js.map +0 -1
  279. package/dist/src/audit-prune.js +0 -109
  280. package/dist/src/audit-prune.js.map +0 -1
  281. package/dist/src/audit.js +0 -213
  282. package/dist/src/audit.js.map +0 -1
  283. package/dist/src/auth.js +0 -97
  284. package/dist/src/auth.js.map +0 -1
  285. package/dist/src/autolearn.js +0 -174
  286. package/dist/src/autolearn.js.map +0 -1
  287. package/dist/src/availability.js +0 -94
  288. package/dist/src/availability.js.map +0 -1
  289. package/dist/src/capture.js +0 -1346
  290. package/dist/src/capture.js.map +0 -1
  291. package/dist/src/card-detail.js +0 -15
  292. package/dist/src/card-detail.js.map +0 -1
  293. package/dist/src/card.js +0 -19
  294. package/dist/src/card.js.map +0 -1
  295. package/dist/src/cli.js +0 -9387
  296. package/dist/src/cli.js.map +0 -1
  297. package/dist/src/client.js +0 -237
  298. package/dist/src/client.js.map +0 -1
  299. package/dist/src/compare.js +0 -122
  300. package/dist/src/compare.js.map +0 -1
  301. package/dist/src/config.js +0 -135
  302. package/dist/src/config.js.map +0 -1
  303. package/dist/src/connectors/github/backfill.js +0 -281
  304. package/dist/src/connectors/github/backfill.js.map +0 -1
  305. package/dist/src/connectors/github/cli-impl.js +0 -234
  306. package/dist/src/connectors/github/cli-impl.js.map +0 -1
  307. package/dist/src/connectors/github/deletion.js +0 -85
  308. package/dist/src/connectors/github/deletion.js.map +0 -1
  309. package/dist/src/connectors/github/dlq.js +0 -190
  310. package/dist/src/connectors/github/dlq.js.map +0 -1
  311. package/dist/src/connectors/github/idempotency.js +0 -27
  312. package/dist/src/connectors/github/idempotency.js.map +0 -1
  313. package/dist/src/connectors/github/ingest.js +0 -156
  314. package/dist/src/connectors/github/ingest.js.map +0 -1
  315. package/dist/src/connectors/github/octokit-client.js +0 -70
  316. package/dist/src/connectors/github/octokit-client.js.map +0 -1
  317. package/dist/src/connectors/github/ratelimit.js +0 -31
  318. package/dist/src/connectors/github/ratelimit.js.map +0 -1
  319. package/dist/src/connectors/github/scope.js +0 -13
  320. package/dist/src/connectors/github/scope.js.map +0 -1
  321. package/dist/src/connectors/github/signature.js +0 -81
  322. package/dist/src/connectors/github/signature.js.map +0 -1
  323. package/dist/src/connectors/github/tenant-routing.js +0 -69
  324. package/dist/src/connectors/github/tenant-routing.js.map +0 -1
  325. package/dist/src/connectors/github/transform.js +0 -103
  326. package/dist/src/connectors/github/transform.js.map +0 -1
  327. package/dist/src/connectors/github/types.js +0 -100
  328. package/dist/src/connectors/github/types.js.map +0 -1
  329. package/dist/src/connectors/slack/backfill.js +0 -78
  330. package/dist/src/connectors/slack/backfill.js.map +0 -1
  331. package/dist/src/connectors/slack/deletion.js +0 -59
  332. package/dist/src/connectors/slack/deletion.js.map +0 -1
  333. package/dist/src/connectors/slack/dlq.js +0 -224
  334. package/dist/src/connectors/slack/dlq.js.map +0 -1
  335. package/dist/src/connectors/slack/idempotency.js +0 -31
  336. package/dist/src/connectors/slack/idempotency.js.map +0 -1
  337. package/dist/src/connectors/slack/ingest.js +0 -109
  338. package/dist/src/connectors/slack/ingest.js.map +0 -1
  339. package/dist/src/connectors/slack/ratelimit.js +0 -18
  340. package/dist/src/connectors/slack/ratelimit.js.map +0 -1
  341. package/dist/src/connectors/slack/scope.js +0 -13
  342. package/dist/src/connectors/slack/scope.js.map +0 -1
  343. package/dist/src/connectors/slack/signature.js +0 -27
  344. package/dist/src/connectors/slack/signature.js.map +0 -1
  345. package/dist/src/connectors/slack/tenant-routing.js +0 -41
  346. package/dist/src/connectors/slack/tenant-routing.js.map +0 -1
  347. package/dist/src/connectors/slack/transform.js +0 -47
  348. package/dist/src/connectors/slack/transform.js.map +0 -1
  349. package/dist/src/connectors/slack/types.js +0 -35
  350. package/dist/src/connectors/slack/types.js.map +0 -1
  351. package/dist/src/connectors/slack/web-client.js +0 -43
  352. package/dist/src/connectors/slack/web-client.js.map +0 -1
  353. package/dist/src/connectors/slack/workspaces.js +0 -62
  354. package/dist/src/connectors/slack/workspaces.js.map +0 -1
  355. package/dist/src/consolidate.js +0 -978
  356. package/dist/src/consolidate.js.map +0 -1
  357. package/dist/src/correction-latency.js +0 -74
  358. package/dist/src/correction-latency.js.map +0 -1
  359. package/dist/src/customer-notes.js +0 -325
  360. package/dist/src/customer-notes.js.map +0 -1
  361. package/dist/src/dag.js +0 -352
  362. package/dist/src/dag.js.map +0 -1
  363. package/dist/src/dashboard.js +0 -258
  364. package/dist/src/dashboard.js.map +0 -1
  365. package/dist/src/db.js +0 -2731
  366. package/dist/src/db.js.map +0 -1
  367. package/dist/src/decisions.js +0 -304
  368. package/dist/src/decisions.js.map +0 -1
  369. package/dist/src/dedupe.js +0 -141
  370. package/dist/src/dedupe.js.map +0 -1
  371. package/dist/src/embedding-provider.js +0 -314
  372. package/dist/src/embedding-provider.js.map +0 -1
  373. package/dist/src/embeddings.js +0 -543
  374. package/dist/src/embeddings.js.map +0 -1
  375. package/dist/src/eval-suite.js +0 -294
  376. package/dist/src/eval-suite.js.map +0 -1
  377. package/dist/src/eval.js +0 -187
  378. package/dist/src/eval.js.map +0 -1
  379. package/dist/src/extract.js +0 -117
  380. package/dist/src/extract.js.map +0 -1
  381. package/dist/src/forward-claim-detector.js +0 -117
  382. package/dist/src/forward-claim-detector.js.map +0 -1
  383. package/dist/src/goals.js +0 -399
  384. package/dist/src/goals.js.map +0 -1
  385. package/dist/src/graph-extract.js +0 -314
  386. package/dist/src/graph-extract.js.map +0 -1
  387. package/dist/src/graph-recall.js +0 -277
  388. package/dist/src/graph-recall.js.map +0 -1
  389. package/dist/src/graph-stream.js +0 -176
  390. package/dist/src/graph-stream.js.map +0 -1
  391. package/dist/src/graph-view.js +0 -310
  392. package/dist/src/graph-view.js.map +0 -1
  393. package/dist/src/graph.js +0 -762
  394. package/dist/src/graph.js.map +0 -1
  395. package/dist/src/handoff.js +0 -65
  396. package/dist/src/handoff.js.map +0 -1
  397. package/dist/src/hooks.js +0 -926
  398. package/dist/src/hooks.js.map +0 -1
  399. package/dist/src/importers.js +0 -881
  400. package/dist/src/importers.js.map +0 -1
  401. package/dist/src/incidents.js +0 -336
  402. package/dist/src/incidents.js.map +0 -1
  403. package/dist/src/index.js +0 -32
  404. package/dist/src/index.js.map +0 -1
  405. package/dist/src/invalidation.js +0 -129
  406. package/dist/src/invalidation.js.map +0 -1
  407. package/dist/src/mcp/framing.js +0 -45
  408. package/dist/src/mcp/framing.js.map +0 -1
  409. package/dist/src/mcp/server.js +0 -1298
  410. package/dist/src/mcp/server.js.map +0 -1
  411. package/dist/src/memory-value-weights.js +0 -31
  412. package/dist/src/memory-value-weights.js.map +0 -1
  413. package/dist/src/memory-value.js +0 -261
  414. package/dist/src/memory-value.js.map +0 -1
  415. package/dist/src/memory.js +0 -425
  416. package/dist/src/memory.js.map +0 -1
  417. package/dist/src/multihop.js +0 -35
  418. package/dist/src/multihop.js.map +0 -1
  419. package/dist/src/owner-validation.js +0 -56
  420. package/dist/src/owner-validation.js.map +0 -1
  421. package/dist/src/path-context.js +0 -48
  422. package/dist/src/path-context.js.map +0 -1
  423. package/dist/src/physics-config.js +0 -26
  424. package/dist/src/physics-config.js.map +0 -1
  425. package/dist/src/physics-state.js +0 -172
  426. package/dist/src/physics-state.js.map +0 -1
  427. package/dist/src/physics.js +0 -378
  428. package/dist/src/physics.js.map +0 -1
  429. package/dist/src/policies.js +0 -414
  430. package/dist/src/policies.js.map +0 -1
  431. package/dist/src/postinstall.js +0 -101
  432. package/dist/src/postinstall.js.map +0 -1
  433. package/dist/src/predictions.js +0 -629
  434. package/dist/src/predictions.js.map +0 -1
  435. package/dist/src/processes.js +0 -349
  436. package/dist/src/processes.js.map +0 -1
  437. package/dist/src/project-briefs.js +0 -492
  438. package/dist/src/project-briefs.js.map +0 -1
  439. package/dist/src/project-identity.js +0 -200
  440. package/dist/src/project-identity.js.map +0 -1
  441. package/dist/src/provenance-coverage.js +0 -23
  442. package/dist/src/provenance-coverage.js.map +0 -1
  443. package/dist/src/rate-limit.js +0 -60
  444. package/dist/src/rate-limit.js.map +0 -1
  445. package/dist/src/raw-archive-mirror-cleanup.js +0 -55
  446. package/dist/src/raw-archive-mirror-cleanup.js.map +0 -1
  447. package/dist/src/raw-archive.js +0 -91
  448. package/dist/src/raw-archive.js.map +0 -1
  449. package/dist/src/recall-history.js +0 -235
  450. package/dist/src/recall-history.js.map +0 -1
  451. package/dist/src/recall-scope.js +0 -89
  452. package/dist/src/recall-scope.js.map +0 -1
  453. package/dist/src/recall-trace.js +0 -186
  454. package/dist/src/recall-trace.js.map +0 -1
  455. package/dist/src/refine-llm.js +0 -156
  456. package/dist/src/refine-llm.js.map +0 -1
  457. package/dist/src/reject-flow.js +0 -209
  458. package/dist/src/reject-flow.js.map +0 -1
  459. package/dist/src/rejection.js +0 -160
  460. package/dist/src/rejection.js.map +0 -1
  461. package/dist/src/replay.js +0 -122
  462. package/dist/src/replay.js.map +0 -1
  463. package/dist/src/rerankers/cross-encoder.js +0 -137
  464. package/dist/src/rerankers/cross-encoder.js.map +0 -1
  465. package/dist/src/rerankers/index.js +0 -20
  466. package/dist/src/rerankers/index.js.map +0 -1
  467. package/dist/src/rerankers/jev.js +0 -119
  468. package/dist/src/rerankers/jev.js.map +0 -1
  469. package/dist/src/rerankers/llm.js +0 -80
  470. package/dist/src/rerankers/llm.js.map +0 -1
  471. package/dist/src/rerankers/types.js +0 -2
  472. package/dist/src/rerankers/types.js.map +0 -1
  473. package/dist/src/rrf.js +0 -61
  474. package/dist/src/rrf.js.map +0 -1
  475. package/dist/src/salience.js +0 -74
  476. package/dist/src/salience.js.map +0 -1
  477. package/dist/src/scheduler.js +0 -77
  478. package/dist/src/scheduler.js.map +0 -1
  479. package/dist/src/scope.js +0 -35
  480. package/dist/src/scope.js.map +0 -1
  481. package/dist/src/search.js +0 -1003
  482. package/dist/src/search.js.map +0 -1
  483. package/dist/src/secret-detect.js +0 -95
  484. package/dist/src/secret-detect.js.map +0 -1
  485. package/dist/src/server-detect.js +0 -231
  486. package/dist/src/server-detect.js.map +0 -1
  487. package/dist/src/server.js +0 -3255
  488. package/dist/src/server.js.map +0 -1
  489. package/dist/src/shared.js +0 -502
  490. package/dist/src/shared.js.map +0 -1
  491. package/dist/src/skills.js +0 -346
  492. package/dist/src/skills.js.map +0 -1
  493. package/dist/src/sleep-redact.js +0 -80
  494. package/dist/src/sleep-redact.js.map +0 -1
  495. package/dist/src/sso.js +0 -22
  496. package/dist/src/sso.js.map +0 -1
  497. package/dist/src/stdin.js +0 -41
  498. package/dist/src/stdin.js.map +0 -1
  499. package/dist/src/store.js +0 -3749
  500. package/dist/src/store.js.map +0 -1
  501. package/dist/src/tenant.js +0 -17
  502. package/dist/src/tenant.js.map +0 -1
  503. package/dist/src/trace.js +0 -72
  504. package/dist/src/trace.js.map +0 -1
  505. package/dist/src/version.js +0 -40
  506. package/dist/src/version.js.map +0 -1
  507. package/dist/src/working-memory.js +0 -157
  508. package/dist/src/working-memory.js.map +0 -1
  509. package/dist/src/yaml.js +0 -107
  510. package/dist/src/yaml.js.map +0 -1
  511. package/dist/sso.d.ts +0 -13
  512. package/dist/sso.d.ts.map +0 -1
  513. package/dist/sso.js +0 -22
  514. package/dist/sso.js.map +0 -1
  515. package/dist/stdin.d.ts.map +0 -1
  516. package/dist/stdin.js.map +0 -1
  517. package/dist/store.d.ts.map +0 -1
  518. package/dist/store.js.map +0 -1
  519. package/dist/tenant.d.ts.map +0 -1
  520. package/dist/tenant.js.map +0 -1
  521. package/dist/trace.d.ts.map +0 -1
  522. package/dist/trace.js.map +0 -1
  523. package/dist/version.d.ts.map +0 -1
  524. package/dist/version.js.map +0 -1
  525. package/dist/working-memory.d.ts.map +0 -1
  526. package/dist/working-memory.js.map +0 -1
  527. package/dist/yaml.d.ts.map +0 -1
  528. package/dist/yaml.js.map +0 -1
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);
@@ -2672,8 +2661,8 @@ function ensureOptionalFts(db) {
2672
2661
  backfillFtsIndex(db);
2673
2662
  available = true;
2674
2663
  }
2675
- catch {
2676
- 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`);
2677
2666
  }
2678
2667
  // Read-first: only write when the flag actually changed, so a healthy
2679
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
@@ -31,6 +31,7 @@
31
31
  */
32
32
  import { getEmbedding, isEmbeddingAvailable, resolveEmbeddingModel, DEFAULT_EMBEDDING_MODEL, } from './embeddings.js';
33
33
  import { loadConfig } from './config.js';
34
+ import { redactSecrets } from './secret-detect.js';
34
35
  export const API_PROVIDER_KINDS = ['openai', 'voyage', 'cohere'];
35
36
  function isApiProviderKind(x) {
36
37
  return x === 'openai' || x === 'voyage' || x === 'cohere';
@@ -188,7 +189,7 @@ class ApiEmbeddingProvider {
188
189
  'content-type': 'application/json',
189
190
  authorization: `Bearer ${key}`,
190
191
  },
191
- body: JSON.stringify(spec.buildBody(this.model, chunk, role)),
192
+ body: JSON.stringify(spec.buildBody(this.model, chunk.map(redactSecrets), role)),
192
193
  signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
193
194
  });
194
195
  }