hippo-memory 1.44.0 → 1.46.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 (554) hide show
  1. package/README.md +68 -24
  2. package/bin/hippo.js +3 -1
  3. package/dist/ablation.d.ts +10 -1
  4. package/dist/ablation.js +17 -1
  5. package/dist/api.d.ts +81 -22
  6. package/dist/api.js +258 -49
  7. package/dist/audit.d.ts +2 -2
  8. package/dist/audit.js +9 -0
  9. package/dist/autolearn.d.ts +1 -1
  10. package/dist/autolearn.js +2 -1
  11. package/dist/capture-error.d.ts +20 -0
  12. package/dist/capture-error.js +82 -0
  13. package/dist/capture.d.ts +25 -8
  14. package/dist/capture.js +100 -5
  15. package/dist/cli.d.ts +9 -1
  16. package/dist/cli.js +531 -119
  17. package/dist/client.d.ts +4 -21
  18. package/dist/client.js +3 -112
  19. package/dist/config.d.ts +20 -0
  20. package/dist/config.js +37 -1
  21. package/dist/consolidate.d.ts +9 -0
  22. package/dist/consolidate.js +133 -46
  23. package/dist/dag.d.ts +1 -0
  24. package/dist/dag.js +10 -5
  25. package/dist/dashboard.js +7 -3
  26. package/dist/db.js +69 -24
  27. package/dist/dedupe.d.ts +1 -0
  28. package/dist/dedupe.js +4 -7
  29. package/dist/doctor.d.ts +34 -0
  30. package/dist/doctor.js +174 -0
  31. package/dist/dormant.d.ts +91 -0
  32. package/dist/dormant.js +121 -0
  33. package/dist/embedding-provider.js +2 -1
  34. package/dist/embeddings.js +81 -8
  35. package/dist/eval-stats.d.ts +123 -0
  36. package/dist/eval-stats.js +187 -0
  37. package/dist/extract.d.ts +2 -0
  38. package/dist/extract.js +9 -4
  39. package/dist/half-life-migration.d.ts +55 -0
  40. package/dist/half-life-migration.js +111 -0
  41. package/dist/hooks.d.ts +4 -0
  42. package/dist/hooks.js +47 -0
  43. package/dist/mcp/server.d.ts +6 -0
  44. package/dist/mcp/server.js +90 -48
  45. package/dist/memory.d.ts +18 -1
  46. package/dist/memory.js +33 -5
  47. package/dist/physics-config.js +5 -1
  48. package/dist/recall-scope.d.ts +24 -0
  49. package/dist/recall-scope.js +41 -0
  50. package/dist/refine-llm.js +3 -2
  51. package/dist/reject-flow.d.ts +3 -3
  52. package/dist/reject-flow.js +10 -3
  53. package/dist/rerankers/jev.js +3 -2
  54. package/dist/rerankers/llm.js +3 -2
  55. package/dist/search.d.ts +4 -4
  56. package/dist/search.js +26 -21
  57. package/dist/server.d.ts +5 -0
  58. package/dist/server.js +49 -29
  59. package/dist/shared.js +1 -1
  60. package/dist/store.d.ts +29 -11
  61. package/dist/store.js +197 -70
  62. package/dist/token-ledger.d.ts +119 -0
  63. package/dist/token-ledger.js +181 -0
  64. package/dist/version.d.ts +4 -6
  65. package/dist/version.js +4 -7
  66. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  67. package/extensions/openclaw-plugin/package.json +1 -1
  68. package/openclaw.plugin.json +1 -1
  69. package/package.json +7 -3
  70. package/dist/ablation.d.ts.map +0 -1
  71. package/dist/ablation.js.map +0 -1
  72. package/dist/ambient.d.ts.map +0 -1
  73. package/dist/ambient.js.map +0 -1
  74. package/dist/api.d.ts.map +0 -1
  75. package/dist/api.js.map +0 -1
  76. package/dist/audit-prune.d.ts.map +0 -1
  77. package/dist/audit-prune.js.map +0 -1
  78. package/dist/audit.d.ts.map +0 -1
  79. package/dist/audit.js.map +0 -1
  80. package/dist/auth.d.ts.map +0 -1
  81. package/dist/auth.js.map +0 -1
  82. package/dist/autolearn.d.ts.map +0 -1
  83. package/dist/autolearn.js.map +0 -1
  84. package/dist/availability.d.ts.map +0 -1
  85. package/dist/availability.js.map +0 -1
  86. package/dist/benchmarks/e1.3/incident-recall-eval.js +0 -78
  87. package/dist/benchmarks/e1.3/incident-recall-eval.js.map +0 -1
  88. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js +0 -103
  89. package/dist/benchmarks/e1.3/slack-1000-event-smoke.js.map +0 -1
  90. package/dist/capture.d.ts.map +0 -1
  91. package/dist/capture.js.map +0 -1
  92. package/dist/card-detail.d.ts.map +0 -1
  93. package/dist/card-detail.js.map +0 -1
  94. package/dist/card.d.ts.map +0 -1
  95. package/dist/card.js.map +0 -1
  96. package/dist/cli.d.ts.map +0 -1
  97. package/dist/cli.js.map +0 -1
  98. package/dist/client.d.ts.map +0 -1
  99. package/dist/client.js.map +0 -1
  100. package/dist/compare.d.ts.map +0 -1
  101. package/dist/compare.js.map +0 -1
  102. package/dist/config.d.ts.map +0 -1
  103. package/dist/config.js.map +0 -1
  104. package/dist/connectors/github/backfill.d.ts.map +0 -1
  105. package/dist/connectors/github/backfill.js.map +0 -1
  106. package/dist/connectors/github/cli-impl.d.ts.map +0 -1
  107. package/dist/connectors/github/cli-impl.js.map +0 -1
  108. package/dist/connectors/github/deletion.d.ts.map +0 -1
  109. package/dist/connectors/github/deletion.js.map +0 -1
  110. package/dist/connectors/github/dlq.d.ts.map +0 -1
  111. package/dist/connectors/github/dlq.js.map +0 -1
  112. package/dist/connectors/github/idempotency.d.ts.map +0 -1
  113. package/dist/connectors/github/idempotency.js.map +0 -1
  114. package/dist/connectors/github/ingest.d.ts.map +0 -1
  115. package/dist/connectors/github/ingest.js.map +0 -1
  116. package/dist/connectors/github/octokit-client.d.ts.map +0 -1
  117. package/dist/connectors/github/octokit-client.js.map +0 -1
  118. package/dist/connectors/github/ratelimit.d.ts.map +0 -1
  119. package/dist/connectors/github/ratelimit.js.map +0 -1
  120. package/dist/connectors/github/scope.d.ts.map +0 -1
  121. package/dist/connectors/github/scope.js.map +0 -1
  122. package/dist/connectors/github/signature.d.ts.map +0 -1
  123. package/dist/connectors/github/signature.js.map +0 -1
  124. package/dist/connectors/github/tenant-routing.d.ts.map +0 -1
  125. package/dist/connectors/github/tenant-routing.js.map +0 -1
  126. package/dist/connectors/github/transform.d.ts.map +0 -1
  127. package/dist/connectors/github/transform.js.map +0 -1
  128. package/dist/connectors/github/types.d.ts.map +0 -1
  129. package/dist/connectors/github/types.js.map +0 -1
  130. package/dist/connectors/slack/backfill.d.ts.map +0 -1
  131. package/dist/connectors/slack/backfill.js.map +0 -1
  132. package/dist/connectors/slack/deletion.d.ts.map +0 -1
  133. package/dist/connectors/slack/deletion.js.map +0 -1
  134. package/dist/connectors/slack/dlq.d.ts.map +0 -1
  135. package/dist/connectors/slack/dlq.js.map +0 -1
  136. package/dist/connectors/slack/idempotency.d.ts.map +0 -1
  137. package/dist/connectors/slack/idempotency.js.map +0 -1
  138. package/dist/connectors/slack/ingest.d.ts.map +0 -1
  139. package/dist/connectors/slack/ingest.js.map +0 -1
  140. package/dist/connectors/slack/ratelimit.d.ts.map +0 -1
  141. package/dist/connectors/slack/ratelimit.js.map +0 -1
  142. package/dist/connectors/slack/scope.d.ts.map +0 -1
  143. package/dist/connectors/slack/scope.js.map +0 -1
  144. package/dist/connectors/slack/signature.d.ts.map +0 -1
  145. package/dist/connectors/slack/signature.js.map +0 -1
  146. package/dist/connectors/slack/tenant-routing.d.ts.map +0 -1
  147. package/dist/connectors/slack/tenant-routing.js.map +0 -1
  148. package/dist/connectors/slack/transform.d.ts.map +0 -1
  149. package/dist/connectors/slack/transform.js.map +0 -1
  150. package/dist/connectors/slack/types.d.ts.map +0 -1
  151. package/dist/connectors/slack/types.js.map +0 -1
  152. package/dist/connectors/slack/web-client.d.ts.map +0 -1
  153. package/dist/connectors/slack/web-client.js.map +0 -1
  154. package/dist/connectors/slack/workspaces.d.ts.map +0 -1
  155. package/dist/connectors/slack/workspaces.js.map +0 -1
  156. package/dist/consolidate.d.ts.map +0 -1
  157. package/dist/consolidate.js.map +0 -1
  158. package/dist/correction-latency.d.ts.map +0 -1
  159. package/dist/correction-latency.js.map +0 -1
  160. package/dist/customer-notes.d.ts.map +0 -1
  161. package/dist/customer-notes.js.map +0 -1
  162. package/dist/dag.d.ts.map +0 -1
  163. package/dist/dag.js.map +0 -1
  164. package/dist/dashboard.d.ts.map +0 -1
  165. package/dist/dashboard.js.map +0 -1
  166. package/dist/db.d.ts.map +0 -1
  167. package/dist/db.js.map +0 -1
  168. package/dist/decisions.d.ts.map +0 -1
  169. package/dist/decisions.js.map +0 -1
  170. package/dist/dedupe.d.ts.map +0 -1
  171. package/dist/dedupe.js.map +0 -1
  172. package/dist/embedding-provider.d.ts.map +0 -1
  173. package/dist/embedding-provider.js.map +0 -1
  174. package/dist/embeddings.d.ts.map +0 -1
  175. package/dist/embeddings.js.map +0 -1
  176. package/dist/eval-suite.d.ts.map +0 -1
  177. package/dist/eval-suite.js.map +0 -1
  178. package/dist/eval.d.ts.map +0 -1
  179. package/dist/eval.js.map +0 -1
  180. package/dist/extensions/openclaw-plugin/index.js.map +0 -1
  181. package/dist/extract.d.ts.map +0 -1
  182. package/dist/extract.js.map +0 -1
  183. package/dist/forward-claim-detector.d.ts.map +0 -1
  184. package/dist/forward-claim-detector.js.map +0 -1
  185. package/dist/goals.d.ts.map +0 -1
  186. package/dist/goals.js.map +0 -1
  187. package/dist/graph-extract.d.ts.map +0 -1
  188. package/dist/graph-extract.js.map +0 -1
  189. package/dist/graph-recall.d.ts.map +0 -1
  190. package/dist/graph-recall.js.map +0 -1
  191. package/dist/graph-stream.d.ts.map +0 -1
  192. package/dist/graph-stream.js.map +0 -1
  193. package/dist/graph-view.d.ts.map +0 -1
  194. package/dist/graph-view.js.map +0 -1
  195. package/dist/graph.d.ts.map +0 -1
  196. package/dist/graph.js.map +0 -1
  197. package/dist/handoff.d.ts.map +0 -1
  198. package/dist/handoff.js.map +0 -1
  199. package/dist/hooks.d.ts.map +0 -1
  200. package/dist/hooks.js.map +0 -1
  201. package/dist/importers.d.ts.map +0 -1
  202. package/dist/importers.js.map +0 -1
  203. package/dist/incidents.d.ts.map +0 -1
  204. package/dist/incidents.js.map +0 -1
  205. package/dist/index.d.ts.map +0 -1
  206. package/dist/index.js.map +0 -1
  207. package/dist/invalidation.d.ts.map +0 -1
  208. package/dist/invalidation.js.map +0 -1
  209. package/dist/mcp/framing.d.ts.map +0 -1
  210. package/dist/mcp/framing.js.map +0 -1
  211. package/dist/mcp/server.d.ts.map +0 -1
  212. package/dist/mcp/server.js.map +0 -1
  213. package/dist/memory-value-weights.d.ts.map +0 -1
  214. package/dist/memory-value-weights.js.map +0 -1
  215. package/dist/memory-value.d.ts.map +0 -1
  216. package/dist/memory-value.js.map +0 -1
  217. package/dist/memory.d.ts.map +0 -1
  218. package/dist/memory.js.map +0 -1
  219. package/dist/multihop.d.ts.map +0 -1
  220. package/dist/multihop.js.map +0 -1
  221. package/dist/owner-validation.d.ts.map +0 -1
  222. package/dist/owner-validation.js.map +0 -1
  223. package/dist/path-context.d.ts.map +0 -1
  224. package/dist/path-context.js.map +0 -1
  225. package/dist/physics-config.d.ts.map +0 -1
  226. package/dist/physics-config.js.map +0 -1
  227. package/dist/physics-state.d.ts.map +0 -1
  228. package/dist/physics-state.js.map +0 -1
  229. package/dist/physics.d.ts.map +0 -1
  230. package/dist/physics.js.map +0 -1
  231. package/dist/policies.d.ts.map +0 -1
  232. package/dist/policies.js.map +0 -1
  233. package/dist/postinstall.d.ts.map +0 -1
  234. package/dist/postinstall.js.map +0 -1
  235. package/dist/predictions.d.ts.map +0 -1
  236. package/dist/predictions.js.map +0 -1
  237. package/dist/processes.d.ts.map +0 -1
  238. package/dist/processes.js.map +0 -1
  239. package/dist/project-briefs.d.ts.map +0 -1
  240. package/dist/project-briefs.js.map +0 -1
  241. package/dist/project-identity.d.ts.map +0 -1
  242. package/dist/project-identity.js.map +0 -1
  243. package/dist/provenance-coverage.d.ts.map +0 -1
  244. package/dist/provenance-coverage.js.map +0 -1
  245. package/dist/rate-limit.d.ts.map +0 -1
  246. package/dist/rate-limit.js.map +0 -1
  247. package/dist/raw-archive-mirror-cleanup.d.ts.map +0 -1
  248. package/dist/raw-archive-mirror-cleanup.js.map +0 -1
  249. package/dist/raw-archive.d.ts.map +0 -1
  250. package/dist/raw-archive.js.map +0 -1
  251. package/dist/recall-history.d.ts.map +0 -1
  252. package/dist/recall-history.js.map +0 -1
  253. package/dist/recall-scope.d.ts.map +0 -1
  254. package/dist/recall-scope.js.map +0 -1
  255. package/dist/recall-trace.d.ts.map +0 -1
  256. package/dist/recall-trace.js.map +0 -1
  257. package/dist/refine-llm.d.ts.map +0 -1
  258. package/dist/refine-llm.js.map +0 -1
  259. package/dist/reject-flow.d.ts.map +0 -1
  260. package/dist/reject-flow.js.map +0 -1
  261. package/dist/rejection.d.ts.map +0 -1
  262. package/dist/rejection.js.map +0 -1
  263. package/dist/replay.d.ts.map +0 -1
  264. package/dist/replay.js.map +0 -1
  265. package/dist/rerankers/cross-encoder.d.ts.map +0 -1
  266. package/dist/rerankers/cross-encoder.js.map +0 -1
  267. package/dist/rerankers/index.d.ts.map +0 -1
  268. package/dist/rerankers/index.js.map +0 -1
  269. package/dist/rerankers/jev.d.ts.map +0 -1
  270. package/dist/rerankers/jev.js.map +0 -1
  271. package/dist/rerankers/llm.d.ts.map +0 -1
  272. package/dist/rerankers/llm.js.map +0 -1
  273. package/dist/rerankers/types.d.ts.map +0 -1
  274. package/dist/rerankers/types.js.map +0 -1
  275. package/dist/rrf.d.ts.map +0 -1
  276. package/dist/rrf.js.map +0 -1
  277. package/dist/salience.d.ts.map +0 -1
  278. package/dist/salience.js.map +0 -1
  279. package/dist/scheduler.d.ts.map +0 -1
  280. package/dist/scheduler.js.map +0 -1
  281. package/dist/scope.d.ts.map +0 -1
  282. package/dist/scope.js.map +0 -1
  283. package/dist/search.d.ts.map +0 -1
  284. package/dist/search.js.map +0 -1
  285. package/dist/secret-detect.d.ts.map +0 -1
  286. package/dist/secret-detect.js.map +0 -1
  287. package/dist/server-detect.d.ts.map +0 -1
  288. package/dist/server-detect.js.map +0 -1
  289. package/dist/server.d.ts.map +0 -1
  290. package/dist/server.js.map +0 -1
  291. package/dist/shared.d.ts.map +0 -1
  292. package/dist/shared.js.map +0 -1
  293. package/dist/skills.d.ts.map +0 -1
  294. package/dist/skills.js.map +0 -1
  295. package/dist/sleep-redact.d.ts +0 -58
  296. package/dist/sleep-redact.d.ts.map +0 -1
  297. package/dist/sleep-redact.js +0 -80
  298. package/dist/sleep-redact.js.map +0 -1
  299. package/dist/src/ablation.js +0 -138
  300. package/dist/src/ablation.js.map +0 -1
  301. package/dist/src/ambient.js +0 -148
  302. package/dist/src/ambient.js.map +0 -1
  303. package/dist/src/api.js +0 -2109
  304. package/dist/src/api.js.map +0 -1
  305. package/dist/src/audit-prune.js +0 -109
  306. package/dist/src/audit-prune.js.map +0 -1
  307. package/dist/src/audit.js +0 -213
  308. package/dist/src/audit.js.map +0 -1
  309. package/dist/src/auth.js +0 -97
  310. package/dist/src/auth.js.map +0 -1
  311. package/dist/src/autolearn.js +0 -174
  312. package/dist/src/autolearn.js.map +0 -1
  313. package/dist/src/availability.js +0 -94
  314. package/dist/src/availability.js.map +0 -1
  315. package/dist/src/capture.js +0 -1346
  316. package/dist/src/capture.js.map +0 -1
  317. package/dist/src/card-detail.js +0 -15
  318. package/dist/src/card-detail.js.map +0 -1
  319. package/dist/src/card.js +0 -19
  320. package/dist/src/card.js.map +0 -1
  321. package/dist/src/cli.js +0 -9387
  322. package/dist/src/cli.js.map +0 -1
  323. package/dist/src/client.js +0 -237
  324. package/dist/src/client.js.map +0 -1
  325. package/dist/src/compare.js +0 -122
  326. package/dist/src/compare.js.map +0 -1
  327. package/dist/src/config.js +0 -135
  328. package/dist/src/config.js.map +0 -1
  329. package/dist/src/connectors/github/backfill.js +0 -281
  330. package/dist/src/connectors/github/backfill.js.map +0 -1
  331. package/dist/src/connectors/github/cli-impl.js +0 -234
  332. package/dist/src/connectors/github/cli-impl.js.map +0 -1
  333. package/dist/src/connectors/github/deletion.js +0 -85
  334. package/dist/src/connectors/github/deletion.js.map +0 -1
  335. package/dist/src/connectors/github/dlq.js +0 -190
  336. package/dist/src/connectors/github/dlq.js.map +0 -1
  337. package/dist/src/connectors/github/idempotency.js +0 -27
  338. package/dist/src/connectors/github/idempotency.js.map +0 -1
  339. package/dist/src/connectors/github/ingest.js +0 -156
  340. package/dist/src/connectors/github/ingest.js.map +0 -1
  341. package/dist/src/connectors/github/octokit-client.js +0 -70
  342. package/dist/src/connectors/github/octokit-client.js.map +0 -1
  343. package/dist/src/connectors/github/ratelimit.js +0 -31
  344. package/dist/src/connectors/github/ratelimit.js.map +0 -1
  345. package/dist/src/connectors/github/scope.js +0 -13
  346. package/dist/src/connectors/github/scope.js.map +0 -1
  347. package/dist/src/connectors/github/signature.js +0 -81
  348. package/dist/src/connectors/github/signature.js.map +0 -1
  349. package/dist/src/connectors/github/tenant-routing.js +0 -69
  350. package/dist/src/connectors/github/tenant-routing.js.map +0 -1
  351. package/dist/src/connectors/github/transform.js +0 -103
  352. package/dist/src/connectors/github/transform.js.map +0 -1
  353. package/dist/src/connectors/github/types.js +0 -100
  354. package/dist/src/connectors/github/types.js.map +0 -1
  355. package/dist/src/connectors/slack/backfill.js +0 -78
  356. package/dist/src/connectors/slack/backfill.js.map +0 -1
  357. package/dist/src/connectors/slack/deletion.js +0 -59
  358. package/dist/src/connectors/slack/deletion.js.map +0 -1
  359. package/dist/src/connectors/slack/dlq.js +0 -224
  360. package/dist/src/connectors/slack/dlq.js.map +0 -1
  361. package/dist/src/connectors/slack/idempotency.js +0 -31
  362. package/dist/src/connectors/slack/idempotency.js.map +0 -1
  363. package/dist/src/connectors/slack/ingest.js +0 -109
  364. package/dist/src/connectors/slack/ingest.js.map +0 -1
  365. package/dist/src/connectors/slack/ratelimit.js +0 -18
  366. package/dist/src/connectors/slack/ratelimit.js.map +0 -1
  367. package/dist/src/connectors/slack/scope.js +0 -13
  368. package/dist/src/connectors/slack/scope.js.map +0 -1
  369. package/dist/src/connectors/slack/signature.js +0 -27
  370. package/dist/src/connectors/slack/signature.js.map +0 -1
  371. package/dist/src/connectors/slack/tenant-routing.js +0 -41
  372. package/dist/src/connectors/slack/tenant-routing.js.map +0 -1
  373. package/dist/src/connectors/slack/transform.js +0 -47
  374. package/dist/src/connectors/slack/transform.js.map +0 -1
  375. package/dist/src/connectors/slack/types.js +0 -35
  376. package/dist/src/connectors/slack/types.js.map +0 -1
  377. package/dist/src/connectors/slack/web-client.js +0 -43
  378. package/dist/src/connectors/slack/web-client.js.map +0 -1
  379. package/dist/src/connectors/slack/workspaces.js +0 -62
  380. package/dist/src/connectors/slack/workspaces.js.map +0 -1
  381. package/dist/src/consolidate.js +0 -978
  382. package/dist/src/consolidate.js.map +0 -1
  383. package/dist/src/correction-latency.js +0 -74
  384. package/dist/src/correction-latency.js.map +0 -1
  385. package/dist/src/customer-notes.js +0 -325
  386. package/dist/src/customer-notes.js.map +0 -1
  387. package/dist/src/dag.js +0 -352
  388. package/dist/src/dag.js.map +0 -1
  389. package/dist/src/dashboard.js +0 -258
  390. package/dist/src/dashboard.js.map +0 -1
  391. package/dist/src/db.js +0 -2731
  392. package/dist/src/db.js.map +0 -1
  393. package/dist/src/decisions.js +0 -304
  394. package/dist/src/decisions.js.map +0 -1
  395. package/dist/src/dedupe.js +0 -141
  396. package/dist/src/dedupe.js.map +0 -1
  397. package/dist/src/embedding-provider.js +0 -314
  398. package/dist/src/embedding-provider.js.map +0 -1
  399. package/dist/src/embeddings.js +0 -543
  400. package/dist/src/embeddings.js.map +0 -1
  401. package/dist/src/eval-suite.js +0 -294
  402. package/dist/src/eval-suite.js.map +0 -1
  403. package/dist/src/eval.js +0 -187
  404. package/dist/src/eval.js.map +0 -1
  405. package/dist/src/extract.js +0 -117
  406. package/dist/src/extract.js.map +0 -1
  407. package/dist/src/forward-claim-detector.js +0 -117
  408. package/dist/src/forward-claim-detector.js.map +0 -1
  409. package/dist/src/goals.js +0 -399
  410. package/dist/src/goals.js.map +0 -1
  411. package/dist/src/graph-extract.js +0 -314
  412. package/dist/src/graph-extract.js.map +0 -1
  413. package/dist/src/graph-recall.js +0 -277
  414. package/dist/src/graph-recall.js.map +0 -1
  415. package/dist/src/graph-stream.js +0 -176
  416. package/dist/src/graph-stream.js.map +0 -1
  417. package/dist/src/graph-view.js +0 -310
  418. package/dist/src/graph-view.js.map +0 -1
  419. package/dist/src/graph.js +0 -762
  420. package/dist/src/graph.js.map +0 -1
  421. package/dist/src/handoff.js +0 -65
  422. package/dist/src/handoff.js.map +0 -1
  423. package/dist/src/hooks.js +0 -926
  424. package/dist/src/hooks.js.map +0 -1
  425. package/dist/src/importers.js +0 -881
  426. package/dist/src/importers.js.map +0 -1
  427. package/dist/src/incidents.js +0 -336
  428. package/dist/src/incidents.js.map +0 -1
  429. package/dist/src/index.js +0 -32
  430. package/dist/src/index.js.map +0 -1
  431. package/dist/src/invalidation.js +0 -129
  432. package/dist/src/invalidation.js.map +0 -1
  433. package/dist/src/mcp/framing.js +0 -45
  434. package/dist/src/mcp/framing.js.map +0 -1
  435. package/dist/src/mcp/server.js +0 -1298
  436. package/dist/src/mcp/server.js.map +0 -1
  437. package/dist/src/memory-value-weights.js +0 -31
  438. package/dist/src/memory-value-weights.js.map +0 -1
  439. package/dist/src/memory-value.js +0 -261
  440. package/dist/src/memory-value.js.map +0 -1
  441. package/dist/src/memory.js +0 -425
  442. package/dist/src/memory.js.map +0 -1
  443. package/dist/src/multihop.js +0 -35
  444. package/dist/src/multihop.js.map +0 -1
  445. package/dist/src/owner-validation.js +0 -56
  446. package/dist/src/owner-validation.js.map +0 -1
  447. package/dist/src/path-context.js +0 -48
  448. package/dist/src/path-context.js.map +0 -1
  449. package/dist/src/physics-config.js +0 -26
  450. package/dist/src/physics-config.js.map +0 -1
  451. package/dist/src/physics-state.js +0 -172
  452. package/dist/src/physics-state.js.map +0 -1
  453. package/dist/src/physics.js +0 -378
  454. package/dist/src/physics.js.map +0 -1
  455. package/dist/src/policies.js +0 -414
  456. package/dist/src/policies.js.map +0 -1
  457. package/dist/src/postinstall.js +0 -101
  458. package/dist/src/postinstall.js.map +0 -1
  459. package/dist/src/predictions.js +0 -629
  460. package/dist/src/predictions.js.map +0 -1
  461. package/dist/src/processes.js +0 -349
  462. package/dist/src/processes.js.map +0 -1
  463. package/dist/src/project-briefs.js +0 -492
  464. package/dist/src/project-briefs.js.map +0 -1
  465. package/dist/src/project-identity.js +0 -200
  466. package/dist/src/project-identity.js.map +0 -1
  467. package/dist/src/provenance-coverage.js +0 -23
  468. package/dist/src/provenance-coverage.js.map +0 -1
  469. package/dist/src/rate-limit.js +0 -60
  470. package/dist/src/rate-limit.js.map +0 -1
  471. package/dist/src/raw-archive-mirror-cleanup.js +0 -55
  472. package/dist/src/raw-archive-mirror-cleanup.js.map +0 -1
  473. package/dist/src/raw-archive.js +0 -91
  474. package/dist/src/raw-archive.js.map +0 -1
  475. package/dist/src/recall-history.js +0 -235
  476. package/dist/src/recall-history.js.map +0 -1
  477. package/dist/src/recall-scope.js +0 -89
  478. package/dist/src/recall-scope.js.map +0 -1
  479. package/dist/src/recall-trace.js +0 -186
  480. package/dist/src/recall-trace.js.map +0 -1
  481. package/dist/src/refine-llm.js +0 -156
  482. package/dist/src/refine-llm.js.map +0 -1
  483. package/dist/src/reject-flow.js +0 -209
  484. package/dist/src/reject-flow.js.map +0 -1
  485. package/dist/src/rejection.js +0 -160
  486. package/dist/src/rejection.js.map +0 -1
  487. package/dist/src/replay.js +0 -122
  488. package/dist/src/replay.js.map +0 -1
  489. package/dist/src/rerankers/cross-encoder.js +0 -137
  490. package/dist/src/rerankers/cross-encoder.js.map +0 -1
  491. package/dist/src/rerankers/index.js +0 -20
  492. package/dist/src/rerankers/index.js.map +0 -1
  493. package/dist/src/rerankers/jev.js +0 -119
  494. package/dist/src/rerankers/jev.js.map +0 -1
  495. package/dist/src/rerankers/llm.js +0 -80
  496. package/dist/src/rerankers/llm.js.map +0 -1
  497. package/dist/src/rerankers/types.js +0 -2
  498. package/dist/src/rerankers/types.js.map +0 -1
  499. package/dist/src/rrf.js +0 -61
  500. package/dist/src/rrf.js.map +0 -1
  501. package/dist/src/salience.js +0 -74
  502. package/dist/src/salience.js.map +0 -1
  503. package/dist/src/scheduler.js +0 -77
  504. package/dist/src/scheduler.js.map +0 -1
  505. package/dist/src/scope.js +0 -35
  506. package/dist/src/scope.js.map +0 -1
  507. package/dist/src/search.js +0 -1003
  508. package/dist/src/search.js.map +0 -1
  509. package/dist/src/secret-detect.js +0 -95
  510. package/dist/src/secret-detect.js.map +0 -1
  511. package/dist/src/server-detect.js +0 -231
  512. package/dist/src/server-detect.js.map +0 -1
  513. package/dist/src/server.js +0 -3255
  514. package/dist/src/server.js.map +0 -1
  515. package/dist/src/shared.js +0 -502
  516. package/dist/src/shared.js.map +0 -1
  517. package/dist/src/skills.js +0 -346
  518. package/dist/src/skills.js.map +0 -1
  519. package/dist/src/sleep-redact.js +0 -80
  520. package/dist/src/sleep-redact.js.map +0 -1
  521. package/dist/src/sso.js +0 -22
  522. package/dist/src/sso.js.map +0 -1
  523. package/dist/src/stdin.js +0 -41
  524. package/dist/src/stdin.js.map +0 -1
  525. package/dist/src/store.js +0 -3749
  526. package/dist/src/store.js.map +0 -1
  527. package/dist/src/tenant.js +0 -17
  528. package/dist/src/tenant.js.map +0 -1
  529. package/dist/src/trace.js +0 -72
  530. package/dist/src/trace.js.map +0 -1
  531. package/dist/src/version.js +0 -40
  532. package/dist/src/version.js.map +0 -1
  533. package/dist/src/working-memory.js +0 -157
  534. package/dist/src/working-memory.js.map +0 -1
  535. package/dist/src/yaml.js +0 -107
  536. package/dist/src/yaml.js.map +0 -1
  537. package/dist/sso.d.ts +0 -13
  538. package/dist/sso.d.ts.map +0 -1
  539. package/dist/sso.js +0 -22
  540. package/dist/sso.js.map +0 -1
  541. package/dist/stdin.d.ts.map +0 -1
  542. package/dist/stdin.js.map +0 -1
  543. package/dist/store.d.ts.map +0 -1
  544. package/dist/store.js.map +0 -1
  545. package/dist/tenant.d.ts.map +0 -1
  546. package/dist/tenant.js.map +0 -1
  547. package/dist/trace.d.ts.map +0 -1
  548. package/dist/trace.js.map +0 -1
  549. package/dist/version.d.ts.map +0 -1
  550. package/dist/version.js.map +0 -1
  551. package/dist/working-memory.d.ts.map +0 -1
  552. package/dist/working-memory.js.map +0 -1
  553. package/dist/yaml.d.ts.map +0 -1
  554. package/dist/yaml.js.map +0 -1
package/dist/api.js CHANGED
@@ -8,15 +8,17 @@
8
8
  */
9
9
  import { createHash } from 'node:crypto';
10
10
  import { openHippoDb, closeHippoDb } from './db.js';
11
- import { writeEntry, writeEntryDbOnly, stampOriginProject, writeEntryMirrors, readEntry, deleteEntry, loadRecallSearchEntries, loadEntriesByIds, loadChildrenOf, loadFreshRawMemories, loadSessionRawMemories, countSessionRawMemories, DEFAULT_SEARCH_CANDIDATE_LIMIT, removeEntryMirrors, loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, loadLatestHandoff, listSessionEvents, SNAPSHOT_AMBIENT_MAX_AGE_MS, loadIndex, saveIndex, loadAllEntries, loadAmbientCandidates, updateStats, isInitialized, markSummaryDirtyInTx, auditRejectionRefusal, } from './store.js';
11
+ import { writeEntry, writeEntryDbOnly, strengthenRetrieved, stampOriginProject, writeEntryMirrors, readEntry, deleteEntry, loadRecallSearchEntries, loadEntriesByIds, loadChildrenOf, loadFreshRawMemories, loadSessionRawMemories, countSessionRawMemories, DEFAULT_SEARCH_CANDIDATE_LIMIT, removeEntryMirrors, loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, loadLatestHandoff, listSessionEvents, SNAPSHOT_AMBIENT_MAX_AGE_MS, loadIndex, saveIndex, loadAllEntries, loadAmbientCandidates, updateStats, isInitialized, markSummaryDirtyInTx, auditRejectionRefusal, } from './store.js';
12
12
  import { RejectedValueError } from './rejection.js';
13
13
  import { rejectValue, unrejectValue, listRejectionsForTenant } from './reject-flow.js';
14
+ import { listDormantRows, readDormantSnapshot, deleteDormantRow, hasDormantRow, } from './dormant.js';
15
+ import { recordTokenUse, summarizeTokenUse } from './token-ledger.js';
14
16
  import { formatHandoffEvidenceLine } from './handoff.js';
15
17
  import { createMemory, applyOutcome, calculateStrength, Layer, } from './memory.js';
16
18
  import { appendAuditEvent, queryAuditEvents, auditMemories, isContentWorthStoring, } from './audit.js';
17
19
  import { promoteToGlobal, getGlobalRoot, autoShare, searchBothHybrid } from './shared.js';
18
20
  import { writeRecallTrace, writeRecallTraceAtRoot, recordTraceOutcome } from './recall-trace.js';
19
- import { evalNow, isRecallBoostAblated } from './ablation.js';
21
+ import { evalNow } from './ablation.js';
20
22
  import { archiveRawMemory } from './raw-archive.js';
21
23
  import { createApiKey, listApiKeys, revokeApiKey, } from './auth.js';
22
24
  import { applyGoalStackBoost } from './goals.js';
@@ -69,6 +71,13 @@ export class RecallContractError extends Error {
69
71
  this.code = code;
70
72
  }
71
73
  }
74
+ /** The actor's role or identity does not allow the operation. HTTP maps it to 403. */
75
+ export class ForbiddenError extends Error {
76
+ constructor(message) {
77
+ super(message);
78
+ this.name = 'ForbiddenError';
79
+ }
80
+ }
72
81
  // v1.25.0: the recall-side scope predicates (PRIVATE_SCOPE_RE, isPrivateScope,
73
82
  // passesScopeFilterForRecall) live in recall-scope.ts (leaf) so shared.ts can
74
83
  // apply the same default-deny rule to searchBothHybrid's internal loads
@@ -77,9 +86,9 @@ export class RecallContractError extends Error {
77
86
  // back-compat (`api.isPrivateScope`, test imports). NOTE: the import statement
78
87
  // is required — a bare `export { x } from` re-export does not bind the local
79
88
  // names this module's ~9 call sites use.
80
- import { isPrivateScope, passesScopeFilterForRecall } from './recall-scope.js';
89
+ import { isPrivateScope, passesScopeFilterForRecall, assertScopeRequestAllowed } from './recall-scope.js';
81
90
  export { isPrivateScope, passesScopeFilterForRecall };
82
- export { passesCliRecallScopeFilter } from './recall-scope.js';
91
+ export { passesCliRecallScopeFilter, ScopeForbiddenError } from './recall-scope.js';
83
92
  // v39: classifyOriginProject lives in project-identity.ts (leaf) so
84
93
  // shared.ts can use it without an api.ts import cycle. Re-exported here for
85
94
  // callers that already import the api surface.
@@ -137,6 +146,7 @@ export function remember(ctx, opts) {
137
146
  artifact_ref: opts.artifactRef ?? null,
138
147
  tags: opts.tags,
139
148
  tenantId: ctx.tenantId,
149
+ baseHalfLifeDays: loadConfig(ctx.hippoRoot).defaultHalfLifeDays,
140
150
  });
141
151
  // writeEntry threads ctx.actor.subject into its internal audit hook, so exactly
142
152
  // one 'remember' event lands in the log with the supplied actor.
@@ -162,9 +172,8 @@ export function buildSuppressionSummary(counts) {
162
172
  }
163
173
  /**
164
174
  * Domain-level recall. Loads BM25-ranked candidates from SQLite scoped to
165
- * `ctx.tenantId`. The `mode` flag is accepted for forward compatibility (the
166
- * CLI exposes hybrid/physics paths) but Task 2 wires only the BM25 candidate
167
- * loader; later tasks can extend this to call the physics/hybrid scorer.
175
+ * `ctx.tenantId` and keeps that order whatever `mode` says; `retrieve` is the
176
+ * mode-aware, strengthening variant the HTTP route uses.
168
177
  *
169
178
  * **api.recall does NOT mutate `index.last_retrieval_ids`** (v1.11.5 contract
170
179
  * lock). The CLI `cmdRecall` (cli.ts) writes `last_retrieval_ids` because the
@@ -177,7 +186,30 @@ export function buildSuppressionSummary(counts) {
177
186
  * `tests/api-recall-no-side-effects.test.ts`.
178
187
  */
179
188
  export function recall(ctx, opts) {
180
- const limit = opts.limit ?? 10;
189
+ // A member key may not unlock a private or quarantined scope by naming it.
190
+ assertScopeRequestAllowed(ctx.actor.role, opts.scope);
191
+ const windowSize = recallWindowSize(opts);
192
+ return recallFrom(ctx, opts, windowSize, loadRecallSearchEntries(ctx.hippoRoot, opts.query, windowSize, ctx.tenantId, opts.scope, 'exact', false));
193
+ }
194
+ /** Mode-aware recall that strengthens each returned row; never writes last_retrieval_ids (v1.11.5 lock). */
195
+ export async function retrieve(ctx, opts) {
196
+ assertScopeRequestAllowed(ctx.actor.role, opts.scope);
197
+ const windowSize = recallWindowSize(opts);
198
+ let candidates = loadRecallSearchEntries(ctx.hippoRoot, opts.query, windowSize, ctx.tenantId, opts.scope, 'exact', false);
199
+ if (opts.mode === 'hybrid' || opts.mode === 'physics') {
200
+ const searchOpts = { budget: Infinity, hippoRoot: ctx.hippoRoot, scope: opts.scope ?? null };
201
+ const ranked = opts.mode === 'physics'
202
+ ? await physicsSearch(opts.query, candidates, { ...searchOpts, physicsConfig: loadConfig(ctx.hippoRoot).physics })
203
+ : await hybridSearch(opts.query, candidates, searchOpts);
204
+ const rankedIds = new Set(ranked.map((r) => r.entry.id));
205
+ candidates = [...ranked.map((r) => r.entry), ...candidates.filter((e) => !rankedIds.has(e.id))];
206
+ }
207
+ const result = recallFrom(ctx, opts, windowSize, candidates);
208
+ strengthenRetrieved(ctx.hippoRoot, result.results.map((r) => r.id), ctx.tenantId);
209
+ return result;
210
+ }
211
+ /** Contract preflight: throws before any store-touching work. */
212
+ function recallWindowSize(opts) {
181
213
  // F5 (v1.6.5) preflight — codex P1: original guard fired AFTER
182
214
  // loadSearchEntries (which runs initStore, migrating legacy state on first
183
215
  // call). For a true contract preflight we want the throw before any
@@ -207,7 +239,10 @@ export function recall(ctx, opts) {
207
239
  throw new RecallContractError('invalid_scorer_window', `scorerWindow must be a positive integer; got ${opts.scorerWindow}`);
208
240
  }
209
241
  }
210
- const windowSize = opts.scorerWindow ?? DEFAULT_SEARCH_CANDIDATE_LIMIT;
242
+ return opts.scorerWindow ?? DEFAULT_SEARCH_CANDIDATE_LIMIT;
243
+ }
244
+ function recallFrom(ctx, opts, windowSize, all) {
245
+ const limit = opts.limit ?? 10;
211
246
  // v1.7.1 — root-cause fix for the `unknown:legacy` leak. Scope predicate
212
247
  // is now pushed into `loadSearchRows` SQL via `loadRecallSearchEntries`.
213
248
  // - opts.scope undefined / '': SQL excludes `unknown:legacy`.
@@ -233,16 +268,16 @@ export function recall(ctx, opts) {
233
268
  let droppedByBudgetCount = 0;
234
269
  let summarySubstitutionsCount = 0;
235
270
  let freshTailAddedCount = 0;
236
- const all = loadRecallSearchEntries(ctx.hippoRoot, opts.query, windowSize, ctx.tenantId, opts.scope);
237
271
  // v1.12.13 / C5 — WYSIATI totalCandidates counter (post tenant + SQL scope
238
272
  // predicate, pre JS scope filter).
239
273
  totalCandidatesCount = all.length;
274
+ const current = all.filter((e) => !e.superseded_by);
240
275
  let entries;
241
276
  if (opts.scope !== undefined && opts.scope !== '') {
242
277
  // SQL already exact-matched in loadRecallSearchEntries; keep the JS
243
278
  // filter as defense-in-depth so a future SQL-clause regression cannot
244
279
  // silently surface cross-scope rows.
245
- entries = all.filter((e) => e.scope === opts.scope);
280
+ entries = current.filter((e) => e.scope === opts.scope);
246
281
  }
247
282
  else {
248
283
  // SQL already excluded `unknown:legacy` AND (v1.25.0) pre-filtered
@@ -252,7 +287,7 @@ export function recall(ctx, opts) {
252
287
  // anchored `<source>:private:*` rule (v1.2.1 generalization) and
253
288
  // defense-in-depth: connector authors cannot silently surface private
254
289
  // rows to no-scope callers even if the SQL clause regresses.
255
- entries = all.filter((e) => !isPrivateScope(e.scope ?? null));
290
+ entries = current.filter((e) => !isPrivateScope(e.scope ?? null));
256
291
  }
257
292
  // v1.12.13 / C5 — WYSIATI dropped_pre_rank counter (JS scope filter drops
258
293
  // for api.recall; cmdRecall pipeline rolls --outcome/--layer/--as-of/etc.
@@ -326,7 +361,7 @@ export function recall(ctx, opts) {
326
361
  const eligibleParentIds = Array.from(overflowByParent.keys()).filter((pid) => (overflowByParent.get(pid)?.length ?? 0) >= 2 && !baseIds.has(pid));
327
362
  if (eligibleParentIds.length > 0) {
328
363
  const parents = loadEntriesByIds(ctx.hippoRoot, eligibleParentIds, ctx.tenantId);
329
- const eligibleParents = parents.filter((p) => (p.dag_level ?? 0) === 2 && passesScopeFilterForRecall(p.scope ?? null, opts.scope));
364
+ const eligibleParents = parents.filter((p) => (p.dag_level ?? 0) === 2 && !p.superseded_by && passesScopeFilterForRecall(p.scope ?? null, opts.scope));
330
365
  const maxSub = Math.max(1, Math.ceil(limit * 0.3));
331
366
  // Order parents by overflow count descending so the most
332
367
  // information-dense substitutions come first. Overflow count is the
@@ -441,7 +476,7 @@ export function recall(ctx, opts) {
441
476
  // prepended (NOT rows already in baseRanked that got tagged isFreshTail).
442
477
  freshTailAddedCount = freshRanked.length;
443
478
  rankedOut = [...freshRanked, ...baseRanked, ...summaryRanked];
444
- tokensOut = rankedOut.reduce((acc, r) => acc + Math.ceil(r.content.length / 4), 0);
479
+ tokensOut = rankedOut.reduce((acc, r) => acc + estimateTokens(r.content), 0);
445
480
  totalOut = entries.length;
446
481
  // TODO(a1-task-4): emit via the shared audit hook in store.ts so we don't
447
482
  // double-emit. Recall does not currently write through writeEntry, so no
@@ -523,7 +558,7 @@ export function recall(ctx, opts) {
523
558
  sessionHandoff: filteredHandoff,
524
559
  recentSessionEvents: filteredEvents,
525
560
  };
526
- const tokenize = (s) => s ? Math.ceil(s.length / 4) : 0;
561
+ const tokenize = (s) => s ? estimateTokens(s) : 0;
527
562
  continuityTokens =
528
563
  tokenize(filteredSnapshot?.task) +
529
564
  tokenize(filteredSnapshot?.summary) +
@@ -689,6 +724,7 @@ export function recall(ctx, opts) {
689
724
  * - all rows fail the scope/tenant filter
690
725
  */
691
726
  export function assemble(ctx, sessionId, opts = {}) {
727
+ assertScopeRequestAllowed(ctx.actor.role, opts.scope);
692
728
  const budget = opts.budget ?? 4000;
693
729
  const freshTailCount = opts.freshTailCount ?? 10;
694
730
  const summarizeOlder = opts.summarizeOlder ?? true;
@@ -736,7 +772,7 @@ export function assemble(ctx, sessionId, opts = {}) {
736
772
  const eligibleParentIds = Array.from(olderByParent.keys()).filter((pid) => (olderByParent.get(pid)?.length ?? 0) >= 2);
737
773
  const parents = eligibleParentIds.length > 0
738
774
  ? loadEntriesByIds(ctx.hippoRoot, eligibleParentIds, ctx.tenantId)
739
- .filter((p) => (p.dag_level ?? 0) === 2)
775
+ .filter((p) => (p.dag_level ?? 0) === 2 && !p.superseded_by)
740
776
  .filter((p) => passesScopeFilterForRecall(p.scope ?? null, opts.scope))
741
777
  : [];
742
778
  const claimedRawIds = new Set();
@@ -788,7 +824,7 @@ export function assemble(ctx, sessionId, opts = {}) {
788
824
  olderItems.sort((a, b) => cmpIso(a.createdAt, b.createdAt));
789
825
  tailItems.sort((a, b) => cmpIso(a.createdAt, b.createdAt));
790
826
  let items = [...olderItems, ...tailItems];
791
- let tokens = items.reduce((acc, it) => acc + Math.ceil(it.content.length / 4), 0);
827
+ let tokens = items.reduce((acc, it) => acc + estimateTokens(it.content), 0);
792
828
  let evicted = 0;
793
829
  while (tokens > budget && items.length > 0) {
794
830
  let worstIdx = -1;
@@ -803,7 +839,7 @@ export function assemble(ctx, sessionId, opts = {}) {
803
839
  }
804
840
  if (worstIdx === -1)
805
841
  break;
806
- const cost = Math.ceil(items[worstIdx].content.length / 4);
842
+ const cost = estimateTokens(items[worstIdx].content);
807
843
  items = items.filter((_, i) => i !== worstIdx);
808
844
  tokens -= cost;
809
845
  evicted++;
@@ -887,7 +923,7 @@ export function drillDown(ctx, summaryId, opts = {}) {
887
923
  const out = [];
888
924
  let used = 0;
889
925
  for (const c of collected) {
890
- const t = Math.ceil(c.content.length / 4);
926
+ const t = estimateTokens(c.content);
891
927
  if (out.length > 0 && used + t > opts.budget) {
892
928
  truncated = true;
893
929
  break;
@@ -1258,11 +1294,13 @@ export function archiveRaw(ctx, id, reason, opts = {}) {
1258
1294
  * `src/server.ts` POST /v1/auth/keys mirrors this: it ignores any body
1259
1295
  * `tenantId` and uses the resolved Bearer's tenant exclusively.
1260
1296
  *
1261
- * Per A5 v2 follow-ups (TODOS.md), `auth_create` is currently unaudited —
1262
- * we intentionally match that behavior here for consistency. When A5 v2
1263
- * lands and adds the audit op, this function should mirror the cli handler.
1297
+ * Only an admin actor can mint (ForbiddenError otherwise), so a member key
1298
+ * can never create a key, least of all an admin one.
1264
1299
  */
1265
1300
  export function authCreate(ctx, opts) {
1301
+ if (ctx.actor.role !== 'admin') {
1302
+ throw new ForbiddenError('Only an admin key can create API keys');
1303
+ }
1266
1304
  const db = openHippoDb(ctx.hippoRoot);
1267
1305
  try {
1268
1306
  const role = opts.role ?? 'admin';
@@ -1311,6 +1349,9 @@ export function authList(ctx, opts) {
1311
1349
  }
1312
1350
  }
1313
1351
  export function authRevoke(ctx, keyId) {
1352
+ if (ctx.actor.role !== 'admin' && ctx.actor.subject !== `api_key:${keyId}`) {
1353
+ throw new ForbiddenError('A member key can revoke only itself');
1354
+ }
1314
1355
  const db = openHippoDb(ctx.hippoRoot);
1315
1356
  try {
1316
1357
  // SAFETY: row's shape matches the three columns named in the SELECT
@@ -1767,21 +1808,11 @@ export async function getContext(ctx, opts = {}) {
1767
1808
  const toUpdate = selectedItems.map((s) => s.entry);
1768
1809
  const updatedEntries = markRetrieved(toUpdate);
1769
1810
  const localIndex = loadIndex(ctx.hippoRoot);
1770
- // EVAL-ONLY ablation (see ablation.ts): under the recall flag,
1771
- // markRetrieved returns unmutated entries (ids preserved for outcome
1772
- // attribution) and persistence is skipped (identical-row writes still
1773
- // refresh updated_at / mirrors / DAG dirty flags).
1774
- if (!isRecallBoostAblated()) {
1775
- for (const u of updatedEntries) {
1776
- const targetRoot = localIndex.entries[u.id]
1777
- ? ctx.hippoRoot
1778
- : hasGlobal
1779
- ? globalRoot
1780
- : ctx.hippoRoot;
1781
- writeEntry(targetRoot, u);
1782
- }
1783
- }
1784
- localIndex.last_retrieval_ids = updatedEntries.map((u) => u.id);
1811
+ const retrievedIds = updatedEntries.map((u) => u.id);
1812
+ const strengthenedHere = strengthenRetrieved(ctx.hippoRoot, retrievedIds);
1813
+ if (hasGlobal)
1814
+ strengthenRetrieved(globalRoot, retrievedIds.filter((id) => !strengthenedHere.has(id)));
1815
+ localIndex.last_retrieval_ids = retrievedIds;
1785
1816
  // LC1 F1 structural fix (docs/plans/2026-08-02-lc1-recall-trace-persistence.md):
1786
1817
  // write the trace FIRST — post-limit, post-annotation `selectedItems`
1787
1818
  // actually returned, on a fresh short-lived connection (the audit
@@ -1833,6 +1864,174 @@ export async function getContext(ctx, opts = {}) {
1833
1864
  ambientState,
1834
1865
  };
1835
1866
  }
1867
+ /**
1868
+ * Record memory text handed to an agent in the token ledger (ROADMAP TE0).
1869
+ * Best-effort: never throws, because a ledger failure must not fail the
1870
+ * recall or context call that produced the text.
1871
+ */
1872
+ export function recordTokens(ctx, surface, use) {
1873
+ try {
1874
+ const db = openHippoDb(ctx.hippoRoot);
1875
+ try {
1876
+ recordTokenUse(db, {
1877
+ tenantId: ctx.tenantId,
1878
+ sessionId: use.sessionId ?? null,
1879
+ surface,
1880
+ event: 'inject',
1881
+ items: use.items,
1882
+ tokens: use.tokens,
1883
+ });
1884
+ }
1885
+ finally {
1886
+ closeHippoDb(db);
1887
+ }
1888
+ }
1889
+ catch {
1890
+ // Ledger is best-effort.
1891
+ }
1892
+ }
1893
+ /**
1894
+ * Token ledger totals for the tenant over the last `days` days (default 30):
1895
+ * tokens sent per surface, blocks skipped as unchanged and the tokens that
1896
+ * saved, and mean tokens per session.
1897
+ */
1898
+ export function tokenSummary(ctx, opts = {}) {
1899
+ const days = opts.days !== undefined && Number.isFinite(opts.days) && opts.days > 0 ? opts.days : 30;
1900
+ const since = new Date(Date.now() - days * 86_400_000).toISOString();
1901
+ const db = openHippoDb(ctx.hippoRoot);
1902
+ try {
1903
+ return summarizeTokenUse(db, ctx.tenantId, since);
1904
+ }
1905
+ finally {
1906
+ closeHippoDb(db);
1907
+ }
1908
+ }
1909
+ /**
1910
+ * A tenant's dormant memories (src/dormant.ts): what sleep moved out of
1911
+ * active memory instead of deleting, when `dormant.enabled` is on. Newest
1912
+ * first; `opts.query` keeps rows containing every term (case-insensitive).
1913
+ */
1914
+ export function listDormant(ctx, opts = {}) {
1915
+ const db = openHippoDb(ctx.hippoRoot);
1916
+ try {
1917
+ return listDormantRows(db, ctx.tenantId, opts);
1918
+ }
1919
+ finally {
1920
+ closeHippoDb(db);
1921
+ }
1922
+ }
1923
+ /**
1924
+ * Bring a dormant memory back into active memory. It returns as if just
1925
+ * recalled: `last_retrieved` is now, so it gets a full half-life before it
1926
+ * can fade again. Every other field is the snapshot taken when it went
1927
+ * dormant.
1928
+ *
1929
+ * Throws when the tenant has no dormant memory with that id (another
1930
+ * tenant's id reads the same way), when a live memory already holds the id,
1931
+ * and RejectedValueError when the value has been rejected since. On any
1932
+ * throw the dormant copy stays where it is.
1933
+ */
1934
+ export function restoreDormant(ctx, id) {
1935
+ const db = openHippoDb(ctx.hippoRoot);
1936
+ try {
1937
+ let restored;
1938
+ db.exec('BEGIN IMMEDIATE');
1939
+ try {
1940
+ const dormant = readDormantSnapshot(db, ctx.tenantId, id);
1941
+ if (!dormant) {
1942
+ throw new Error(`dormant memory not found: ${id}`);
1943
+ }
1944
+ if (db.prepare(`SELECT 1 FROM memories WHERE id = ?`).get(id) !== undefined) {
1945
+ throw new Error(`memory ${id} is already active; forget it before restoring its dormant copy`);
1946
+ }
1947
+ const now = new Date();
1948
+ // Dormant rows are long-lived, so a snapshot can predate a field added
1949
+ // later: createMemory supplies a default for anything it lacks, then
1950
+ // the snapshot overrides every field it does carry, content included.
1951
+ // (The placeholder only satisfies createMemory's minimum length, so a
1952
+ // legacy row shorter than 3 chars can still be restored.)
1953
+ const revived = {
1954
+ ...createMemory('dormant snapshot defaults'),
1955
+ ...dormant.entry,
1956
+ last_retrieved: now.toISOString(),
1957
+ };
1958
+ restored = stampOriginProject(ctx.hippoRoot, { ...revived, strength: calculateStrength(revived, now) });
1959
+ writeEntryDbOnly(db, restored, { actor: ctx.actor.subject });
1960
+ deleteDormantRow(db, ctx.tenantId, id);
1961
+ // A restore is a labelled "forgot it, then needed it" event: the
1962
+ // signal a learned lifecycle (ROADMAP LC3) trains on. Same transaction
1963
+ // as the restore, so the label exists exactly when the restore does.
1964
+ appendAuditEvent(db, {
1965
+ tenantId: ctx.tenantId,
1966
+ actor: ctx.actor.subject,
1967
+ op: 'dormant_restore',
1968
+ targetId: id,
1969
+ metadata: {
1970
+ reason: dormant.reason,
1971
+ strengthAtDormancy: dormant.strength,
1972
+ dormantAt: dormant.dormantAt,
1973
+ daysDormant: Math.max(0, (now.getTime() - Date.parse(dormant.dormantAt)) / (24 * 60 * 60 * 1000)),
1974
+ },
1975
+ });
1976
+ db.exec('COMMIT');
1977
+ }
1978
+ catch (err) {
1979
+ try {
1980
+ db.exec('ROLLBACK');
1981
+ }
1982
+ catch { /* already rolled back */ }
1983
+ if (err instanceof RejectedValueError) {
1984
+ auditRejectionRefusal(db, err, ctx.actor.subject);
1985
+ }
1986
+ throw err;
1987
+ }
1988
+ writeEntryMirrors(ctx.hippoRoot, db, restored);
1989
+ return restored;
1990
+ }
1991
+ finally {
1992
+ closeHippoDb(db);
1993
+ }
1994
+ }
1995
+ /**
1996
+ * Permanently delete a dormant memory: the explicit "forget it for good"
1997
+ * that dormant storage leaves to the user. Throws when the tenant has no
1998
+ * dormant memory with that id.
1999
+ */
2000
+ export function forgetDormant(ctx, id) {
2001
+ const db = openHippoDb(ctx.hippoRoot);
2002
+ try {
2003
+ if (!deleteDormantRow(db, ctx.tenantId, id)) {
2004
+ throw new Error(`dormant memory not found: ${id}`);
2005
+ }
2006
+ try {
2007
+ appendAuditEvent(db, {
2008
+ tenantId: ctx.tenantId,
2009
+ actor: ctx.actor.subject,
2010
+ op: 'forget',
2011
+ targetId: id,
2012
+ metadata: { dormant: true },
2013
+ });
2014
+ }
2015
+ catch {
2016
+ // Best-effort, like every other forget audit row: the delete stands.
2017
+ }
2018
+ }
2019
+ finally {
2020
+ closeHippoDb(db);
2021
+ }
2022
+ // Counted like every other permanent removal (forget, archiveRaw).
2023
+ updateStats(ctx.hippoRoot, { forgotten: 1 });
2024
+ }
2025
+ /** Whether the tenant holds a dormant memory with this id (for "not found" hints). */
2026
+ export function isDormant(ctx, id) {
2027
+ const db = openHippoDb(ctx.hippoRoot);
2028
+ try {
2029
+ return hasDormantRow(db, ctx.tenantId, id);
2030
+ }
2031
+ finally {
2032
+ closeHippoDb(db);
2033
+ }
2034
+ }
1836
2035
  const DEFAULT_SLEEP_PHASES = {
1837
2036
  consolidate,
1838
2037
  deduplicateStore,
@@ -1896,10 +2095,16 @@ export async function sleep(ctx, opts = {}) {
1896
2095
  dryRun,
1897
2096
  details: consolidateResult.details,
1898
2097
  };
1899
- if (dryRun)
1900
- return result;
2098
+ // Set only when non-zero, so a store without dormant memories gets a
2099
+ // byte-identical result (HTTP /v1/sleep, the CLI render snapshot).
2100
+ if (consolidateResult.dormant > 0) {
2101
+ result.dormant = consolidateResult.dormant;
2102
+ }
2103
+ if (consolidateResult.dormantExpired > 0) {
2104
+ result.dormantExpired = consolidateResult.dormantExpired;
2105
+ }
1901
2106
  // Phase 2: Dedup (post-consolidate near-duplicate cleanup).
1902
- const dedupResult = phases.deduplicateStore(ctx.hippoRoot);
2107
+ const dedupResult = phases.deduplicateStore(ctx.hippoRoot, { dryRun, actor: ctx.actor.subject });
1903
2108
  dedupCount = dedupResult.removed;
1904
2109
  if (dedupResult.removed > 0) {
1905
2110
  const semDups = dedupResult.pairs.filter((p) => p.keptLayer === 'semantic' && p.removedLayer === 'semantic').length;
@@ -1912,25 +2117,29 @@ export async function sleep(ctx, opts = {}) {
1912
2117
  crossDups,
1913
2118
  };
1914
2119
  }
1915
- // Phase 3: Quality audit (remove junk, report warnings).
1916
- const allEntries = phases.loadAllEntries(ctx.hippoRoot);
2120
+ // Phase 3: Quality audit (remove junk, report warnings; a dry run skips rows earlier phases would remove).
2121
+ const planned = new Set(dryRun ? [...(consolidateResult.removedIds ?? []), ...dedupResult.pairs.map((p) => p.removed)] : []);
2122
+ const allEntries = phases.loadAllEntries(ctx.hippoRoot).filter((e) => !planned.has(e.id));
1917
2123
  const auditOut = phases.auditMemories(allEntries);
1918
2124
  if (auditOut.issues.length > 0) {
1919
2125
  const errors = auditOut.issues.filter((i) => i.severity === 'error');
1920
2126
  const warnings = auditOut.issues.filter((i) => i.severity === 'warning');
1921
- if (errors.length > 0) {
1922
- for (const issue of errors) {
1923
- phases.deleteEntry(ctx.hippoRoot, issue.memoryId);
1924
- }
2127
+ let removed = 0;
2128
+ for (const issue of errors) {
2129
+ const reason = `sleep-audit: ${issue.reason}`;
2130
+ if (dryRun || phases.deleteEntry(ctx.hippoRoot, issue.memoryId, { actor: ctx.actor.subject, reason, automatic: true }))
2131
+ removed++;
1925
2132
  }
1926
- auditDeletedCount = errors.length;
1927
- if (errors.length > 0 || warnings.length > 0) {
2133
+ auditDeletedCount = removed;
2134
+ if (removed > 0 || warnings.length > 0) {
1928
2135
  result.audit = {
1929
- errorsRemoved: errors.length,
2136
+ errorsRemoved: removed,
1930
2137
  warningCount: warnings.length,
1931
2138
  };
1932
2139
  }
1933
2140
  }
2141
+ if (dryRun)
2142
+ return result;
1934
2143
  // Phase 4: Auto-share high-transfer-score memories to global.
1935
2144
  if (!opts.noShare) {
1936
2145
  const sleepConfig = phases.loadConfig(ctx.hippoRoot);
package/dist/audit.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { MemoryEntry } from './memory.js';
1
+ import { type MemoryEntry } from './memory.js';
2
2
  import type { DatabaseSyncLike } from './db.js';
3
3
  import type { JsonObject } from './working-memory.js';
4
4
  export type AuditSeverity = 'warning' | 'error';
@@ -16,7 +16,7 @@ export interface AuditResult {
16
16
  export declare function auditMemory(entry: MemoryEntry): AuditIssue | null;
17
17
  export declare function auditMemories(entries: MemoryEntry[]): AuditResult;
18
18
  export declare function isContentWorthStoring(content: string): boolean;
19
- export type AuditOp = 'remember' | 'recall' | 'promote' | 'supersede' | 'forget' | 'archive_raw' | 'auth_revoke' | 'auth_create' | 'outcome' | 'consolidate' | 'audit_prune' | 'summary_marked_dirty' | 'summary_marked_clean' | 'summary_rebuilt' | 'predict_create' | 'predict_close' | 'predict_baserate' | 'recall_autodebias_hint' | 'recall_autodebias_hint_no_class_match' | 'recall_autodebias_hint_tiebreak' | 'recall_anchor_detected_query_repeat' | 'recall_anchor_detected_memory_dominance' | 'recall_anchor_skipped_no_session' | 'recall_availability_detected' | 'decision_create' | 'decision_supersede' | 'decision_close' | 'incident_open' | 'incident_resolve' | 'incident_close' | 'process_create' | 'process_supersede' | 'process_close' | 'policy_create' | 'policy_supersede' | 'policy_close' | 'skill_create' | 'skill_supersede' | 'skill_close' | 'project_brief_create' | 'project_brief_supersede' | 'project_brief_close' | 'customer_note_create' | 'customer_note_supersede' | 'customer_note_close' | 'mv_rescue' | 'reject_value' | 'reject_refusal' | 'unreject_value' | 'conflict_resolve';
19
+ export type AuditOp = 'remember' | 'recall' | 'promote' | 'supersede' | 'forget' | 'archive_raw' | 'auth_revoke' | 'auth_create' | 'outcome' | 'consolidate' | 'audit_prune' | 'summary_marked_dirty' | 'summary_marked_clean' | 'summary_rebuilt' | 'predict_create' | 'predict_close' | 'predict_baserate' | 'recall_autodebias_hint' | 'recall_autodebias_hint_no_class_match' | 'recall_autodebias_hint_tiebreak' | 'recall_anchor_detected_query_repeat' | 'recall_anchor_detected_memory_dominance' | 'recall_anchor_skipped_no_session' | 'recall_availability_detected' | 'decision_create' | 'decision_supersede' | 'decision_close' | 'incident_open' | 'incident_resolve' | 'incident_close' | 'process_create' | 'process_supersede' | 'process_close' | 'policy_create' | 'policy_supersede' | 'policy_close' | 'skill_create' | 'skill_supersede' | 'skill_close' | 'project_brief_create' | 'project_brief_supersede' | 'project_brief_close' | 'customer_note_create' | 'customer_note_supersede' | 'customer_note_close' | 'mv_rescue' | 'reject_value' | 'reject_refusal' | 'unreject_value' | 'half_life_migrate' | 'dormant_restore' | 'conflict_resolve';
20
20
  export interface AppendAuditOpts {
21
21
  tenantId: string;
22
22
  actor: string;
package/dist/audit.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { canAutoDelete } from './memory.js';
1
2
  const STOP_WORDS = new Set([
2
3
  'the', 'a', 'an', 'is', 'was', 'are', 'were', 'be', 'been', 'being',
3
4
  'to', 'of', 'in', 'for', 'on', 'with', 'at', 'by', 'from', 'it',
@@ -109,6 +110,14 @@ function hasNoSpecificity(text) {
109
110
  return words.length < 8 && VAGUE_ONLY.test(text);
110
111
  }
111
112
  export function auditMemory(entry) {
113
+ const issue = classifyMemory(entry);
114
+ // Error means "auto-remove"; a pinned or raw row is never auto-removed, so it can only warn.
115
+ if (issue?.severity === 'error' && !canAutoDelete(entry)) {
116
+ return { ...issue, severity: 'warning', reason: `${issue.reason} (${entry.pinned ? 'pinned' : 'raw'}, kept)` };
117
+ }
118
+ return issue;
119
+ }
120
+ function classifyMemory(entry) {
112
121
  const content = entry.content.trim();
113
122
  if (content.length < 3) {
114
123
  return { memoryId: entry.id, content, severity: 'error', reason: 'too short (< 3 chars)' };
@@ -7,7 +7,7 @@ import { MemoryEntry } from './memory.js';
7
7
  * Create a MemoryEntry capturing a command failure.
8
8
  * Content format: "Command '<cmd>' failed: <truncated stderr>"
9
9
  */
10
- export declare function captureError(exitCode: number, stderr: string, command: string): MemoryEntry;
10
+ export declare function captureError(exitCode: number, stderr: string, command: string, tenantId?: string): MemoryEntry;
11
11
  /**
12
12
  * Parse git log output for actionable lessons.
13
13
  * Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
package/dist/autolearn.js CHANGED
@@ -11,7 +11,7 @@ import { isContentWorthStoring } from './audit.js';
11
11
  * Create a MemoryEntry capturing a command failure.
12
12
  * Content format: "Command '<cmd>' failed: <truncated stderr>"
13
13
  */
14
- export function captureError(exitCode, stderr, command) {
14
+ export function captureError(exitCode, stderr, command, tenantId) {
15
15
  // Truncate to first 500 chars to avoid storing megabytes of build logs
16
16
  const wasTruncated = stderr.length > 500;
17
17
  const truncated = stderr.slice(0, 500).trim();
@@ -29,6 +29,7 @@ export function captureError(exitCode, stderr, command) {
29
29
  tags,
30
30
  source: 'autolearn',
31
31
  confidence: 'observed',
32
+ tenantId,
32
33
  });
33
34
  }
34
35
  /**
@@ -0,0 +1,20 @@
1
+ import type { JsonValue } from './working-memory.js';
2
+ /** Why a failure was not stored, or `stored`. */
3
+ export type CaptureErrorOutcome = 'stored' | 'duplicate' | 'skipped-interrupt' | 'skipped-routine' | 'skipped-invalid';
4
+ /** Normalised form used to spot repeats of the same failure. */
5
+ export declare function failureSignature(text: string): string;
6
+ /**
7
+ * The memory text for a failure payload, or the reason it is not stored.
8
+ * Pure: no store access.
9
+ */
10
+ export declare function lessonFromFailure(payload: JsonValue): {
11
+ text: string;
12
+ } | {
13
+ skip: Exclude<CaptureErrorOutcome, 'stored' | 'duplicate'>;
14
+ };
15
+ /**
16
+ * Store a failure payload as an error memory unless it is routine or a
17
+ * repeat of an auto-captured error already in the store.
18
+ */
19
+ export declare function captureToolFailure(hippoRoot: string, tenantId: string, payload: JsonValue): CaptureErrorOutcome;
20
+ //# sourceMappingURL=capture-error.d.ts.map