hippo-memory 1.71.0 → 2.0.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 (625) hide show
  1. package/README.md +7 -5
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +11 -26
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/copilot.d.ts +1 -3
  7. package/dist/agent-memories/copilot.js +1 -17
  8. package/dist/agent-memories/project-folds.d.ts +10 -0
  9. package/dist/agent-memories/project-folds.js +34 -0
  10. package/dist/agent-memories/sync.js +8 -6
  11. package/dist/api/assemble.js +3 -2
  12. package/dist/api/audit.d.ts +30 -2
  13. package/dist/api/audit.js +48 -7
  14. package/dist/api/auth.d.ts +11 -9
  15. package/dist/api/auth.js +39 -40
  16. package/dist/api/auto-sleep.d.ts +5 -2
  17. package/dist/api/auto-sleep.js +7 -3
  18. package/dist/api/availability.js +2 -3
  19. package/dist/api/cards.d.ts +42 -0
  20. package/dist/api/cards.js +52 -0
  21. package/dist/api/conflicts.d.ts +28 -0
  22. package/dist/api/conflicts.js +61 -0
  23. package/dist/api/context-auto.js +4 -2
  24. package/dist/api/context-render.js +4 -3
  25. package/dist/api/context-select.js +15 -29
  26. package/dist/api/context.js +29 -18
  27. package/dist/api/continuity.d.ts +47 -0
  28. package/dist/api/continuity.js +66 -0
  29. package/dist/api/dormant.js +4 -2
  30. package/dist/api/drill-down.js +3 -2
  31. package/dist/api/embeddings.d.ts +17 -0
  32. package/dist/api/embeddings.js +28 -0
  33. package/dist/api/error-reply.d.ts +8 -0
  34. package/dist/api/error-reply.js +21 -0
  35. package/dist/api/forget.d.ts +7 -3
  36. package/dist/api/forget.js +24 -14
  37. package/dist/api/goals.d.ts +1 -1
  38. package/dist/api/goals.js +5 -9
  39. package/dist/api/graph.js +2 -1
  40. package/dist/api/index.d.ts +4 -2
  41. package/dist/api/index.js +4 -2
  42. package/dist/api/instruction-detect.js +5 -1
  43. package/dist/api/learn.d.ts +5 -1
  44. package/dist/api/learn.js +71 -44
  45. package/dist/api/ledger-db.d.ts +2 -6
  46. package/dist/api/ledger-db.js +4 -36
  47. package/dist/api/memories.d.ts +21 -1
  48. package/dist/api/memories.js +51 -1
  49. package/dist/api/objects.d.ts +1 -1
  50. package/dist/api/objects.js +2 -1
  51. package/dist/api/outcome.d.ts +5 -5
  52. package/dist/api/outcome.js +17 -16
  53. package/dist/api/pilot-arm.d.ts +1 -11
  54. package/dist/api/pilot-arm.js +5 -45
  55. package/dist/api/predictions.d.ts +3 -1
  56. package/dist/api/predictions.js +8 -1
  57. package/dist/api/projects.d.ts +21 -0
  58. package/dist/api/projects.js +24 -0
  59. package/dist/api/promote.d.ts +3 -3
  60. package/dist/api/promote.js +26 -28
  61. package/dist/api/prompt-hook.d.ts +17 -2
  62. package/dist/api/prompt-hook.js +45 -4
  63. package/dist/api/quarantine.js +2 -1
  64. package/dist/api/recall-cli.d.ts +3 -0
  65. package/dist/api/recall-cli.js +13 -4
  66. package/dist/api/recall-core.js +10 -5
  67. package/dist/api/recall-pipeline.js +23 -24
  68. package/dist/api/recall-request.js +1 -1
  69. package/dist/api/recall-types.d.ts +3 -1
  70. package/dist/api/recall.d.ts +0 -3
  71. package/dist/api/recall.js +51 -73
  72. package/dist/api/remember-local.d.ts +5 -2
  73. package/dist/api/remember-local.js +15 -7
  74. package/dist/api/remember.d.ts +7 -3
  75. package/dist/api/remember.js +19 -16
  76. package/dist/api/session-end.d.ts +46 -0
  77. package/dist/api/session-end.js +131 -0
  78. package/dist/api/sleep-run.d.ts +1 -1
  79. package/dist/api/sleep-run.js +16 -11
  80. package/dist/api/sleep.js +4 -3
  81. package/dist/api/status.d.ts +24 -0
  82. package/dist/api/status.js +40 -0
  83. package/dist/api/store-init.d.ts +4 -0
  84. package/dist/api/store-init.js +9 -0
  85. package/dist/api/tokens.js +2 -2
  86. package/dist/api/types.d.ts +3 -7
  87. package/dist/api/types.js +6 -1
  88. package/dist/capture/caller-session.d.ts +0 -3
  89. package/dist/capture/caller-session.js +1 -12
  90. package/dist/capture/capture-error.d.ts +2 -2
  91. package/dist/capture/capture-error.js +23 -18
  92. package/dist/capture/codex-patch.js +3 -1
  93. package/dist/capture/command.js +36 -95
  94. package/dist/capture/compact.js +10 -5
  95. package/dist/capture/compaction-items-caller.js +11 -20
  96. package/dist/capture/compaction-record.d.ts +7 -93
  97. package/dist/capture/compaction-record.js +29 -426
  98. package/dist/capture/compaction-spool.d.ts +7 -7
  99. package/dist/capture/compaction-spool.js +60 -51
  100. package/dist/capture/copilot-transcript.d.ts +2 -1
  101. package/dist/capture/copilot-transcript.js +2 -1
  102. package/dist/capture/extract.d.ts +5 -2
  103. package/dist/capture/extract.js +4 -3
  104. package/dist/capture/failure-caller.d.ts +1 -1
  105. package/dist/capture/failure-caller.js +21 -16
  106. package/dist/capture/failure-reading.d.ts +2 -1
  107. package/dist/capture/failure-reading.js +7 -9
  108. package/dist/capture/pre-compact-caller.js +5 -4
  109. package/dist/capture/session-digest.js +4 -3
  110. package/dist/capture/session-end-caller.js +3 -2
  111. package/dist/capture/session-worker.js +22 -10
  112. package/dist/capture/transcript.d.ts +2 -1
  113. package/dist/capture/transcript.js +6 -3
  114. package/dist/capture/working-state.d.ts +4 -2
  115. package/dist/capture/working-state.js +4 -2
  116. package/dist/cli/audit-prune.d.ts +0 -25
  117. package/dist/cli/audit-prune.js +1 -27
  118. package/dist/cli/audit.js +20 -20
  119. package/dist/cli/auth.d.ts +1 -1
  120. package/dist/cli/auth.js +16 -17
  121. package/dist/cli/briefs.d.ts +1 -4
  122. package/dist/cli/briefs.js +37 -292
  123. package/dist/cli/card.js +41 -33
  124. package/dist/cli/client.d.ts +6 -2
  125. package/dist/cli/client.js +37 -21
  126. package/dist/cli/compact-resume-payload.js +1 -1
  127. package/dist/cli/context.d.ts +1 -1
  128. package/dist/cli/context.js +13 -13
  129. package/dist/cli/continuity.d.ts +1 -1
  130. package/dist/cli/continuity.js +36 -39
  131. package/dist/cli/curate.d.ts +2 -2
  132. package/dist/cli/curate.js +32 -36
  133. package/dist/cli/dag.d.ts +1 -1
  134. package/dist/cli/dag.js +23 -8
  135. package/dist/cli/decisions.d.ts +0 -2
  136. package/dist/cli/decisions.js +7 -285
  137. package/dist/cli/eval.d.ts +1 -1
  138. package/dist/cli/eval.js +12 -13
  139. package/dist/cli/explain.d.ts +1 -1
  140. package/dist/cli/explain.js +21 -25
  141. package/dist/cli/flag-values.js +16 -6
  142. package/dist/cli/flags.d.ts +0 -289
  143. package/dist/cli/flags.js +3 -138
  144. package/dist/cli/graph.d.ts +3 -0
  145. package/dist/cli/graph.js +83 -0
  146. package/dist/cli/hook-runtime.d.ts +6 -6
  147. package/dist/cli/hook-runtime.js +9 -36
  148. package/dist/cli/incidents.d.ts +3 -0
  149. package/dist/cli/incidents.js +112 -0
  150. package/dist/cli/init.d.ts +1 -1
  151. package/dist/cli/init.js +28 -19
  152. package/dist/cli/install-steps.d.ts +2 -1
  153. package/dist/cli/install-steps.js +11 -3
  154. package/dist/cli/last-sleep.js +1 -1
  155. package/dist/cli/maintenance.d.ts +3 -3
  156. package/dist/cli/maintenance.js +29 -30
  157. package/dist/cli/notes.d.ts +2 -0
  158. package/dist/cli/notes.js +41 -0
  159. package/dist/cli/object-verbs.d.ts +2 -2
  160. package/dist/cli/object-verbs.js +4 -4
  161. package/dist/cli/open-browser.d.ts +14 -0
  162. package/dist/cli/open-browser.js +26 -0
  163. package/dist/cli/playbooks.d.ts +3 -4
  164. package/dist/cli/playbooks.js +126 -290
  165. package/dist/cli/predictions.d.ts +3 -0
  166. package/dist/cli/predictions.js +174 -0
  167. package/dist/cli/print.js +2 -1
  168. package/dist/cli/projects.js +30 -22
  169. package/dist/cli/quality-repair-once.d.ts +1 -1
  170. package/dist/cli/quality-repair-once.js +6 -5
  171. package/dist/cli/recall.js +13 -7
  172. package/dist/cli/refine-llm.js +18 -17
  173. package/dist/cli/remember.js +17 -17
  174. package/dist/cli/scheduler.js +2 -1
  175. package/dist/cli/serve.js +11 -6
  176. package/dist/cli/session-hooks.d.ts +1 -5
  177. package/dist/cli/session-hooks.js +89 -168
  178. package/dist/cli/setup.d.ts +1 -1
  179. package/dist/cli/setup.js +17 -10
  180. package/dist/cli/shared.d.ts +2 -6
  181. package/dist/cli/shared.js +9 -29
  182. package/dist/cli/sleep-render.js +6 -3
  183. package/dist/cli/sleep.js +6 -37
  184. package/dist/cli/status.d.ts +3 -3
  185. package/dist/cli/status.js +32 -35
  186. package/dist/cli/transfer.d.ts +3 -3
  187. package/dist/cli/transfer.js +64 -43
  188. package/dist/cli/usage.d.ts +1 -80
  189. package/dist/cli/usage.js +2 -696
  190. package/dist/cli/verb-row.d.ts +34 -0
  191. package/dist/cli/verb-row.js +6 -0
  192. package/dist/cli/verbs/health.d.ts +27 -0
  193. package/dist/cli/verbs/health.js +234 -0
  194. package/dist/cli/verbs/memory.d.ts +16 -0
  195. package/dist/cli/verbs/memory.js +236 -0
  196. package/dist/cli/verbs/objects.d.ts +20 -0
  197. package/dist/cli/verbs/objects.js +257 -0
  198. package/dist/cli/verbs/sessions.d.ts +31 -0
  199. package/dist/cli/verbs/sessions.js +314 -0
  200. package/dist/cli/verbs.d.ts +81 -0
  201. package/dist/cli/verbs.js +7 -0
  202. package/dist/cli/versioned-verbs.d.ts +51 -0
  203. package/dist/cli/versioned-verbs.js +79 -0
  204. package/dist/cli.d.ts +1 -272
  205. package/dist/cli.js +24 -315
  206. package/dist/connectors/dlq.d.ts +39 -3
  207. package/dist/connectors/dlq.js +39 -4
  208. package/dist/connectors/github/backfill.js +12 -3
  209. package/dist/connectors/github/deletion.js +2 -1
  210. package/dist/connectors/github/dlq.js +31 -73
  211. package/dist/connectors/github/ingest.d.ts +2 -6
  212. package/dist/connectors/github/ingest.js +5 -29
  213. package/dist/connectors/github/tenant-routing.js +2 -1
  214. package/dist/connectors/github/webhook.d.ts +2 -1
  215. package/dist/connectors/github/webhook.js +35 -2
  216. package/dist/connectors/ingest.d.ts +10 -0
  217. package/dist/connectors/ingest.js +29 -0
  218. package/dist/connectors/slack/deletion.js +2 -1
  219. package/dist/connectors/slack/dlq.js +49 -71
  220. package/dist/connectors/slack/ingest.d.ts +2 -6
  221. package/dist/connectors/slack/ingest.js +4 -28
  222. package/dist/connectors/slack/tenant-routing.js +2 -1
  223. package/dist/connectors/slack/webhook.d.ts +2 -1
  224. package/dist/connectors/slack/webhook.js +2 -1
  225. package/dist/consolidate/conflicts.js +2 -2
  226. package/dist/consolidate/dag.js +29 -18
  227. package/dist/consolidate/dedupe.d.ts +7 -0
  228. package/dist/consolidate/dedupe.js +6 -4
  229. package/dist/consolidate/llm-passes.js +45 -19
  230. package/dist/consolidate/memory-value.js +3 -2
  231. package/dist/consolidate/merge.js +8 -8
  232. package/dist/consolidate/physics-pass.d.ts +6 -1
  233. package/dist/consolidate/physics-pass.js +26 -6
  234. package/dist/consolidate/replay.js +11 -4
  235. package/dist/consolidate/sleep.js +9 -6
  236. package/dist/consolidate/traces.js +5 -5
  237. package/dist/core/ablation.d.ts +10 -0
  238. package/dist/core/ablation.js +12 -0
  239. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  240. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  241. package/dist/core/ambient.d.ts +4 -0
  242. package/dist/core/ambient.js +39 -18
  243. package/dist/core/api-errors.d.ts +16 -0
  244. package/dist/core/api-errors.js +20 -0
  245. package/dist/core/card.js +3 -1
  246. package/dist/core/compaction-timing.d.ts +7 -0
  247. package/dist/core/compaction-timing.js +9 -0
  248. package/dist/core/config.d.ts +1 -1
  249. package/dist/core/config.js +22 -18
  250. package/dist/core/cosine.d.ts +3 -0
  251. package/dist/core/cosine.js +19 -0
  252. package/dist/{store → core}/markdown.d.ts +1 -1
  253. package/dist/{store → core}/markdown.js +4 -4
  254. package/dist/core/memory-audit.d.ts +17 -0
  255. package/dist/core/memory-audit.js +54 -0
  256. package/dist/core/memory.d.ts +14 -8
  257. package/dist/core/memory.js +35 -23
  258. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  259. package/dist/{consolidate → core}/merged-row.js +1 -1
  260. package/dist/core/physics.d.ts +3 -1
  261. package/dist/core/physics.js +23 -18
  262. package/dist/core/prediction.d.ts +3 -0
  263. package/dist/core/prediction.js +6 -0
  264. package/dist/core/project-identity.d.ts +3 -0
  265. package/dist/core/project-identity.js +12 -2
  266. package/dist/{store → core}/recall-scope.d.ts +1 -10
  267. package/dist/{store → core}/recall-scope.js +2 -19
  268. package/dist/core/search-types.d.ts +1 -1
  269. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  270. package/dist/dashboard/dashboard-actions.js +5 -5
  271. package/dist/dashboard/dashboard-queries.js +2 -7
  272. package/dist/dashboard/dashboard-snapshot.js +1 -3
  273. package/dist/dashboard/dashboard.js +16 -5
  274. package/dist/db/busy.d.ts +2 -7
  275. package/dist/db/busy.js +21 -26
  276. package/dist/db/connect.d.ts +2 -2
  277. package/dist/db/connect.js +7 -7
  278. package/dist/db/index.d.ts +3 -3
  279. package/dist/db/index.js +3 -3
  280. package/dist/db/migrate.js +14 -7
  281. package/dist/db/migrations/index.d.ts +1 -1
  282. package/dist/db/migrations/index.js +3 -1
  283. package/dist/db/migrations/v11.js +1 -0
  284. package/dist/db/migrations/v14.js +1 -0
  285. package/dist/db/migrations/v55.d.ts +3 -0
  286. package/dist/db/migrations/v55.js +17 -0
  287. package/dist/db/open.d.ts +0 -2
  288. package/dist/db/open.js +6 -10
  289. package/dist/db/physics-state.d.ts +0 -4
  290. package/dist/db/physics-state.js +7 -33
  291. package/dist/db/request-stores.d.ts +1 -0
  292. package/dist/db/request-stores.js +2 -1
  293. package/dist/db/tables.d.ts +2 -0
  294. package/dist/db/tables.js +6 -2
  295. package/dist/db/vector-store.js +19 -5
  296. package/dist/db/wal-checkpointer.js +2 -1
  297. package/dist/doctor.d.ts +3 -0
  298. package/dist/doctor.js +18 -15
  299. package/dist/embeddings/local.d.ts +62 -0
  300. package/dist/embeddings/local.js +146 -0
  301. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  302. package/dist/{store/embeddings → embeddings}/provider.js +19 -25
  303. package/dist/embeddings/transformers.d.ts +26 -0
  304. package/dist/embeddings/transformers.js +89 -0
  305. package/dist/entry/session-text.d.ts +1 -1
  306. package/dist/entry/session-text.js +1 -1
  307. package/dist/entry/store-kit.d.ts +37 -0
  308. package/dist/entry/store-kit.js +25 -0
  309. package/dist/entry/testing.d.ts +6 -0
  310. package/dist/entry/testing.js +7 -0
  311. package/dist/eval/eval-suite.js +17 -11
  312. package/dist/eval/eval.js +1 -1
  313. package/dist/eval/judgment.js +12 -5
  314. package/dist/graph/extract.js +3 -3
  315. package/dist/graph/recall.js +1 -1
  316. package/dist/graph/view.js +13 -5
  317. package/dist/graph/write.d.ts +1 -1
  318. package/dist/graph/write.js +9 -9
  319. package/dist/hooks/codex-session.js +3 -2
  320. package/dist/hooks/codex-wrapper.js +2 -1
  321. package/dist/hooks/json-hooks.js +10 -4
  322. package/dist/hooks/opencode.js +8 -5
  323. package/dist/hooks/shared.d.ts +0 -6
  324. package/dist/hooks/shared.js +4 -15
  325. package/dist/importers/core.js +4 -4
  326. package/dist/importers/sources.js +5 -4
  327. package/dist/importers/vault.d.ts +1 -1
  328. package/dist/importers/vault.js +25 -23
  329. package/dist/index.d.ts +5 -4
  330. package/dist/index.js +4 -3
  331. package/dist/learn/autolearn.d.ts +15 -3
  332. package/dist/learn/autolearn.js +38 -16
  333. package/dist/learn/churn-git.js +13 -4
  334. package/dist/learn/extract.d.ts +3 -2
  335. package/dist/learn/extract.js +7 -5
  336. package/dist/learn/forward-claim-detector.js +4 -2
  337. package/dist/learn/invalidation.d.ts +2 -1
  338. package/dist/learn/invalidation.js +18 -9
  339. package/dist/mcp/admin-tools.d.ts +2 -2
  340. package/dist/mcp/admin-tools.js +27 -48
  341. package/dist/mcp/format.js +3 -2
  342. package/dist/mcp/framing.d.ts +1 -0
  343. package/dist/mcp/framing.js +1 -1
  344. package/dist/mcp/memory-tools.d.ts +1 -1
  345. package/dist/mcp/memory-tools.js +8 -9
  346. package/dist/mcp/protocol.d.ts +11 -7
  347. package/dist/mcp/protocol.js +25 -12
  348. package/dist/mcp/recall-tools.js +12 -9
  349. package/dist/mcp/request.js +22 -20
  350. package/dist/mcp/stdio.js +37 -16
  351. package/dist/mcp/tool-args.js +2 -1
  352. package/dist/mcp/tools.js +44 -21
  353. package/dist/objects/customer-notes.d.ts +2 -2
  354. package/dist/objects/decisions.d.ts +2 -2
  355. package/dist/objects/descriptor.d.ts +1 -1
  356. package/dist/objects/incidents.d.ts +2 -2
  357. package/dist/objects/lifecycle.d.ts +1 -1
  358. package/dist/objects/lifecycle.js +2 -1
  359. package/dist/objects/policies.d.ts +2 -2
  360. package/dist/objects/policies.js +2 -1
  361. package/dist/objects/processes.d.ts +2 -2
  362. package/dist/objects/project-briefs.d.ts +2 -2
  363. package/dist/objects/project-briefs.js +2 -3
  364. package/dist/objects/skills.d.ts +2 -2
  365. package/dist/postinstall.js +1 -1
  366. package/dist/rerankers/clef.js +3 -6
  367. package/dist/rerankers/cross-encoder.d.ts +31 -2
  368. package/dist/rerankers/cross-encoder.js +71 -98
  369. package/dist/rerankers/index.js +5 -4
  370. package/dist/rerankers/jev.js +2 -4
  371. package/dist/rerankers/outage-warning.d.ts +3 -1
  372. package/dist/rerankers/outage-warning.js +5 -3
  373. package/dist/search/bm25-search.js +1 -1
  374. package/dist/search/boosts.js +1 -1
  375. package/dist/search/embed-memories.d.ts +12 -0
  376. package/dist/search/embed-memories.js +389 -0
  377. package/dist/search/engine.d.ts +8 -0
  378. package/dist/search/engine.js +10 -0
  379. package/dist/search/goal-boost.d.ts +1 -1
  380. package/dist/search/goal-boost.js +6 -3
  381. package/dist/search/hybrid.d.ts +9 -2
  382. package/dist/search/hybrid.js +9 -4
  383. package/dist/search/physics-search.d.ts +6 -3
  384. package/dist/search/physics-search.js +22 -15
  385. package/dist/search/rerank.js +1 -1
  386. package/dist/search/vector.d.ts +8 -6
  387. package/dist/search/vector.js +14 -17
  388. package/dist/server/auth.d.ts +3 -1
  389. package/dist/server/auth.js +24 -15
  390. package/dist/server/boot.d.ts +2 -1
  391. package/dist/server/boot.js +34 -84
  392. package/dist/server/client-ip.d.ts +9 -6
  393. package/dist/server/client-ip.js +36 -17
  394. package/dist/server/deadline.d.ts +0 -2
  395. package/dist/server/deadline.js +1 -7
  396. package/dist/server/defaults.d.ts +1 -0
  397. package/dist/server/defaults.js +1 -0
  398. package/dist/server/mcp-http.js +16 -11
  399. package/dist/server/request.js +7 -2
  400. package/dist/server/route-checks.d.ts +7 -0
  401. package/dist/server/route-checks.js +42 -0
  402. package/dist/server/route-table.d.ts +9 -8
  403. package/dist/server/route-table.js +127 -133
  404. package/dist/server/routes/admin.d.ts +8 -8
  405. package/dist/server/routes/admin.js +13 -21
  406. package/dist/server/routes/customer-notes.d.ts +6 -6
  407. package/dist/server/routes/customer-notes.js +1 -2
  408. package/dist/server/routes/decisions.d.ts +6 -6
  409. package/dist/server/routes/decisions.js +2 -4
  410. package/dist/server/routes/incidents.d.ts +6 -6
  411. package/dist/server/routes/incidents.js +2 -5
  412. package/dist/server/routes/memories.d.ts +9 -9
  413. package/dist/server/routes/memories.js +19 -40
  414. package/dist/server/routes/object-routes.d.ts +6 -6
  415. package/dist/server/routes/object-routes.js +4 -7
  416. package/dist/server/routes/policies.d.ts +7 -7
  417. package/dist/server/routes/policies.js +2 -4
  418. package/dist/server/routes/predictions.d.ts +6 -6
  419. package/dist/server/routes/predictions.js +9 -13
  420. package/dist/server/routes/processes.d.ts +6 -6
  421. package/dist/server/routes/processes.js +1 -2
  422. package/dist/server/routes/project-briefs.d.ts +7 -7
  423. package/dist/server/routes/project-briefs.js +2 -4
  424. package/dist/server/routes/recall.d.ts +5 -5
  425. package/dist/server/routes/recall.js +6 -10
  426. package/dist/server/routes/skills.d.ts +7 -7
  427. package/dist/server/routes/skills.js +2 -4
  428. package/dist/server/server-detect.d.ts +7 -1
  429. package/dist/server/server-detect.js +36 -11
  430. package/dist/server/sleep-child.js +26 -7
  431. package/dist/server/sleep-offload.d.ts +11 -5
  432. package/dist/server/sleep-offload.js +17 -11
  433. package/dist/server/tls.d.ts +7 -2
  434. package/dist/server/tls.js +17 -5
  435. package/dist/server/types.d.ts +29 -12
  436. package/dist/server/validation.d.ts +1 -2
  437. package/dist/server/validation.js +6 -11
  438. package/dist/server.d.ts +4 -40
  439. package/dist/server.js +3 -29
  440. package/dist/sharing/global-store.d.ts +4 -5
  441. package/dist/sharing/global-store.js +8 -13
  442. package/dist/sharing/global-sync.js +38 -45
  443. package/dist/sharing/project-merge.d.ts +7 -14
  444. package/dist/sharing/project-merge.js +57 -121
  445. package/dist/sharing/search-both.js +10 -3
  446. package/dist/sharing/share.d.ts +2 -0
  447. package/dist/sharing/share.js +39 -38
  448. package/dist/store/ambient.js +7 -7
  449. package/dist/store/audit-event.d.ts +1 -1
  450. package/dist/store/audit.d.ts +0 -16
  451. package/dist/store/audit.js +4 -55
  452. package/dist/store/auth.d.ts +4 -2
  453. package/dist/store/auth.js +7 -3
  454. package/dist/store/candidates.d.ts +3 -2
  455. package/dist/store/candidates.js +59 -30
  456. package/dist/store/capture-write.d.ts +17 -0
  457. package/dist/store/capture-write.js +35 -0
  458. package/dist/store/cards.js +6 -5
  459. package/dist/store/compaction-caller.d.ts +18 -0
  460. package/dist/store/compaction-caller.js +29 -0
  461. package/dist/store/compactions-record.d.ts +115 -0
  462. package/dist/store/compactions-record.js +418 -0
  463. package/dist/store/compactions.js +6 -4
  464. package/dist/store/conflicts.d.ts +7 -1
  465. package/dist/store/conflicts.js +13 -9
  466. package/dist/store/connectors/dlq.d.ts +10 -0
  467. package/dist/store/connectors/dlq.js +33 -0
  468. package/dist/store/connectors/event-log.d.ts +13 -0
  469. package/dist/store/connectors/event-log.js +24 -0
  470. package/dist/store/connectors/github.d.ts +7 -9
  471. package/dist/store/connectors/github.js +35 -60
  472. package/dist/store/connectors/slack.d.ts +2 -11
  473. package/dist/store/connectors/slack.js +24 -57
  474. package/dist/store/dashboard-reads.js +8 -6
  475. package/dist/store/delete-and-batch.d.ts +6 -0
  476. package/dist/store/delete-and-batch.js +40 -6
  477. package/dist/store/delivery-recorder.d.ts +12 -5
  478. package/dist/store/delivery-recorder.js +13 -11
  479. package/dist/store/descendant-page.js +8 -4
  480. package/dist/store/dormant.d.ts +1 -1
  481. package/dist/store/dormant.js +10 -4
  482. package/dist/store/embeddings/index.d.ts +2 -12
  483. package/dist/store/embeddings/index.js +5 -374
  484. package/dist/store/entry-reads.d.ts +35 -4
  485. package/dist/store/entry-reads.js +86 -19
  486. package/dist/store/entry-row.js +9 -2
  487. package/dist/store/entry-writes.d.ts +15 -12
  488. package/dist/store/entry-writes.js +54 -22
  489. package/dist/store/failure-log-at.d.ts +8 -0
  490. package/dist/store/failure-log-at.js +16 -0
  491. package/dist/store/failure-log.d.ts +2 -2
  492. package/dist/store/failure-log.js +5 -3
  493. package/dist/{trust → store}/gated-write.d.ts +3 -1
  494. package/dist/{trust → store}/gated-write.js +7 -5
  495. package/dist/store/goals.js +22 -19
  496. package/dist/store/graph-reads.js +9 -6
  497. package/dist/store/graph-view-rows.js +2 -1
  498. package/dist/store/graph-writes.d.ts +6 -6
  499. package/dist/store/graph-writes.js +48 -71
  500. package/dist/store/half-life.js +2 -2
  501. package/dist/store/handoffs.d.ts +10 -4
  502. package/dist/store/handoffs.js +10 -9
  503. package/dist/store/index-and-stats.js +2 -2
  504. package/dist/store/index.d.ts +2 -2
  505. package/dist/store/index.js +1 -1
  506. package/dist/store/key-writes.js +1 -1
  507. package/dist/store/ledger-turn.d.ts +9 -0
  508. package/dist/store/ledger-turn.js +38 -0
  509. package/dist/store/mirrors.js +19 -10
  510. package/dist/store/open.d.ts +2 -5
  511. package/dist/store/open.js +42 -54
  512. package/dist/store/pilot-arm.d.ts +12 -0
  513. package/dist/store/pilot-arm.js +42 -0
  514. package/dist/store/port.d.ts +68 -6
  515. package/dist/store/port.js +8 -0
  516. package/dist/store/predictions.d.ts +1 -2
  517. package/dist/store/predictions.js +3 -6
  518. package/dist/store/project-tags.d.ts +62 -0
  519. package/dist/store/project-tags.js +67 -0
  520. package/dist/store/quality-repair.js +1 -1
  521. package/dist/store/quarantine.js +2 -1
  522. package/dist/store/recall-trace.d.ts +2 -0
  523. package/dist/store/recall-trace.js +20 -3
  524. package/dist/store/rejected-values.js +16 -10
  525. package/dist/store/rejection-probe.d.ts +4 -0
  526. package/dist/store/rejection-probe.js +19 -0
  527. package/dist/store/rejection.d.ts +0 -17
  528. package/dist/store/rejection.js +1 -21
  529. package/dist/store/rows.js +2 -2
  530. package/dist/store/rule-sql.d.ts +11 -0
  531. package/dist/store/rule-sql.js +31 -6
  532. package/dist/store/search-rows.d.ts +5 -5
  533. package/dist/store/search-rows.js +18 -16
  534. package/dist/store/sessions.js +4 -2
  535. package/dist/store/set-aside.d.ts +14 -0
  536. package/dist/store/set-aside.js +23 -0
  537. package/dist/store/sqlite/busy.d.ts +3 -0
  538. package/dist/store/sqlite/busy.js +8 -0
  539. package/dist/store/sqlite/connector-events-group.js +4 -7
  540. package/dist/store/sqlite/connector-writes-group.js +6 -4
  541. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  542. package/dist/store/sqlite/entry-writes-group.js +3 -3
  543. package/dist/store/sqlite/error-codec.js +4 -3
  544. package/dist/store/sqlite/executor.js +10 -4
  545. package/dist/store/sqlite/graph-reads-group.js +1 -1
  546. package/dist/store/sqlite/held-connection.d.ts +11 -0
  547. package/dist/store/sqlite/held-connection.js +41 -0
  548. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  549. package/dist/store/sqlite/last-recall-group.js +57 -0
  550. package/dist/store/sqlite/local.d.ts +0 -17
  551. package/dist/store/sqlite/local.js +0 -31
  552. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  553. package/dist/store/sqlite/maintenance-groups.js +60 -0
  554. package/dist/store/sqlite/object-rows.d.ts +1 -1
  555. package/dist/store/sqlite/objects-group.d.ts +1 -1
  556. package/dist/store/sqlite/objects-group.js +15 -7
  557. package/dist/store/sqlite/store.d.ts +1 -8
  558. package/dist/store/sqlite/store.js +13 -22
  559. package/dist/store/summaries.d.ts +10 -3
  560. package/dist/store/summaries.js +54 -11
  561. package/dist/store/token-ledger-rows.js +3 -2
  562. package/dist/store/token-ledger.d.ts +0 -7
  563. package/dist/store/token-ledger.js +0 -35
  564. package/dist/store/vector-index.js +8 -4
  565. package/dist/support-bundle.js +2 -3
  566. package/dist/trust/reject-flow.js +2 -2
  567. package/dist/util/agent-homes.d.ts +15 -0
  568. package/dist/util/agent-homes.js +34 -0
  569. package/dist/util/anthropic-messages.d.ts +6 -1
  570. package/dist/util/anthropic-messages.js +26 -7
  571. package/dist/util/atomic-write.d.ts +5 -2
  572. package/dist/util/atomic-write.js +12 -8
  573. package/dist/util/chunked.d.ts +3 -0
  574. package/dist/util/chunked.js +10 -0
  575. package/dist/util/ellipsize.d.ts +3 -0
  576. package/dist/util/ellipsize.js +5 -0
  577. package/dist/util/env.d.ts +12 -2
  578. package/dist/util/env.js +12 -2
  579. package/dist/util/format.d.ts +5 -0
  580. package/dist/util/format.js +10 -0
  581. package/dist/util/hook-payload.d.ts +8 -0
  582. package/dist/util/hook-payload.js +37 -0
  583. package/dist/util/http-retry.d.ts +6 -0
  584. package/dist/util/http-retry.js +43 -5
  585. package/dist/util/http-util.d.ts +0 -8
  586. package/dist/util/http-util.js +10 -21
  587. package/dist/util/limits.d.ts +7 -0
  588. package/dist/util/limits.js +14 -0
  589. package/dist/util/log.d.ts +4 -0
  590. package/dist/util/log.js +9 -0
  591. package/dist/util/request-scope.d.ts +9 -3
  592. package/dist/util/request-scope.js +18 -9
  593. package/dist/util/secret-detect.js +6 -1
  594. package/dist/util/spawn-argv.d.ts +9 -0
  595. package/dist/util/spawn-argv.js +57 -0
  596. package/dist/util/sql.d.ts +3 -0
  597. package/dist/util/sql.js +6 -0
  598. package/dist/util/sqlite-blocked.d.ts +2 -0
  599. package/dist/util/sqlite-blocked.js +5 -0
  600. package/dist/util/stream-tee.d.ts +3 -0
  601. package/dist/util/stream-tee.js +35 -0
  602. package/dist/util/time.d.ts +4 -0
  603. package/dist/util/time.js +4 -0
  604. package/dist/util/vector-codec.d.ts +4 -0
  605. package/dist/util/vector-codec.js +15 -0
  606. package/dist/util/version.d.ts +1 -1
  607. package/dist/util/version.js +1 -1
  608. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  609. package/extensions/openclaw-plugin/package.json +1 -1
  610. package/openclaw.plugin.json +1 -1
  611. package/package.json +4 -2
  612. package/dist/api/on-store.d.ts +0 -16
  613. package/dist/api/on-store.js +0 -38
  614. package/dist/store/embeddings/local.d.ts +0 -15
  615. package/dist/store/embeddings/local.js +0 -175
  616. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  617. /package/dist/{cli → api}/correction-latency.js +0 -0
  618. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  619. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  620. /package/dist/{store → core}/object-types.d.ts +0 -0
  621. /package/dist/{store → core}/object-types.js +0 -0
  622. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  623. /package/dist/{capture → util}/compaction-items.js +0 -0
  624. /package/dist/{store → util}/yaml.d.ts +0 -0
  625. /package/dist/{store → util}/yaml.js +0 -0
@@ -1,18 +1,24 @@
1
1
  import { createMemory, Layer } from '../core/memory.js';
2
2
  import { writeEntry, writeEntriesTogether } from '../store/entry-writes.js';
3
- import { loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from '../store/summaries.js';
4
- import { RejectedValueError } from '../store/rejection.js';
3
+ import { loadAllDirtySummaries, loadChildrenOfSummary, loadChildrenOfSummaries, childrenKey, applyRebuildResult, clearSummaryDirtyAfterBuild, } from '../store/summaries.js';
4
+ import { RejectedValueError } from '../core/api-errors.js';
5
5
  import { generateDagSummary } from './dag-summary.js';
6
- import { derivationScope, derivationPartitionKey } from '../store/recall-scope.js';
6
+ import { overlapPartners } from './overlap-index.js';
7
+ import { derivationScope, derivationPartitionKey } from '../core/recall-scope.js';
7
8
  import { loadConfig } from '../core/config.js';
8
9
  import { neverAutoShareTags } from '../sharing/share.js';
9
10
  import { errorFields, errorMessage, log } from '../util/log.js';
10
11
  const SUMMARY_FALLBACK_CHARS = 40;
11
12
  const DEFAULT_REBUILD_CAP = 20;
13
+ // Facts join a cluster when their tag sets overlap at least this much.
14
+ const CLUSTER_JACCARD_MIN = 0.5;
12
15
  export function clusterFacts(facts) {
13
16
  if (facts.length === 0)
14
17
  return [];
15
18
  const entityTags = facts.map((f) => f.tags.filter((t) => t.startsWith('speaker:') || t.startsWith('topic:')));
19
+ const tagSets = entityTags.map((tags) => new Set(tags));
20
+ // Every tag indexed, not a prefix: a repeated tag counts twice in `shared`, so the prefix-filter bound would not hold.
21
+ const partnersOf = overlapPartners(tagSets, () => 1);
16
22
  const assigned = new Set();
17
23
  const clusters = [];
18
24
  for (let i = 0; i < facts.length; i++) {
@@ -20,19 +26,18 @@ export function clusterFacts(facts) {
20
26
  continue;
21
27
  const cluster = [i];
22
28
  assigned.add(i);
23
- for (let j = i + 1; j < facts.length; j++) {
29
+ for (const j of partnersOf(i)) {
24
30
  if (assigned.has(j))
25
31
  continue;
26
- const shared = entityTags[i].filter((t) => entityTags[j].includes(t));
27
- const union = new Set([...entityTags[i], ...entityTags[j]]);
28
- const jaccard = union.size > 0 ? shared.length / union.size : 0;
29
- if (jaccard >= 0.5) {
32
+ const shared = entityTags[i].filter((t) => tagSets[j].has(t)).length;
33
+ const inBoth = [...tagSets[i]].filter((t) => tagSets[j].has(t)).length;
34
+ if (shared / (tagSets[i].size + tagSets[j].size - inBoth) >= CLUSTER_JACCARD_MIN) {
30
35
  cluster.push(j);
31
36
  assigned.add(j);
32
37
  }
33
38
  }
34
39
  const members = cluster.map((idx) => facts[idx]);
35
- const sharedTags = entityTags[cluster[0]].filter((t) => cluster.every((idx) => entityTags[idx].includes(t)));
40
+ const sharedTags = entityTags[cluster[0]].filter((t) => cluster.every((idx) => tagSets[idx].has(t)));
36
41
  const label = sharedTags
37
42
  .map((t) => t.split(':')[1])
38
43
  .join(': ') || members[0].content.slice(0, SUMMARY_FALLBACK_CHARS);
@@ -45,7 +50,7 @@ export function clusterFacts(facts) {
45
50
  function partitionFactsByTenant(unparented) {
46
51
  const unparentedByTenant = new Map();
47
52
  for (const fact of unparented) {
48
- const key = derivationPartitionKey(fact.tenantId, fact.scope, fact.origin_project);
53
+ const key = derivationPartitionKey(fact.tenant_id, fact.scope, fact.origin_project);
49
54
  const bucket = unparentedByTenant.get(key);
50
55
  if (bucket)
51
56
  bucket.push(fact);
@@ -98,7 +103,7 @@ async function summarizeCluster(hippoRoot, cluster, home, opts, result) {
98
103
  result.factsLinked += writeEntriesTogether(hippoRoot, cluster.members.map((member) => ({ ...member, dag_parent_id: summaryEntry.id })));
99
104
  // Member writes just marked this fresh summary dirty; clear it, or the same sleep cycle's
100
105
  // rebuild pass would re-rebuild every new summary at twice the LLM cost.
101
- clearSummaryDirtyAfterBuild(hippoRoot, summaryEntry.id, summaryEntry.tenantId, 'buildDag');
106
+ clearSummaryDirtyAfterBuild(hippoRoot, summaryEntry.id, summaryEntry.tenant_id, 'buildDag');
102
107
  }
103
108
  export async function buildDag(hippoRoot, facts, opts) {
104
109
  const result = { candidateClusters: 0, summariesCreated: 0, factsLinked: 0, rejected: 0 };
@@ -106,7 +111,7 @@ export async function buildDag(hippoRoot, facts, opts) {
106
111
  const unparented = facts.filter((f) => f.dag_level === 1 && !f.dag_parent_id && f.tags.includes('extracted'));
107
112
  for (const [, tenantFacts] of partitionFactsByTenant(unparented)) {
108
113
  const home = {
109
- tenantId: tenantFacts[0].tenantId,
114
+ tenantId: tenantFacts[0].tenant_id,
110
115
  scope: derivationScope(tenantFacts[0].scope),
111
116
  originProject: tenantFacts[0].origin_project,
112
117
  baseHalfLifeDays,
@@ -121,8 +126,11 @@ export async function buildDag(hippoRoot, facts, opts) {
121
126
  return result;
122
127
  }
123
128
  /** Regenerate one dirty summary from its children and tally the outcome; throws reach the caller's isolation. */
124
- async function rebuildOneSummary(hippoRoot, summary, opts, result) {
125
- const children = loadChildrenOfSummary(hippoRoot, summary.id, summary.tenantId);
129
+ async function rebuildOneSummary(hippoRoot, summary, opts, result, preloaded, queuedIds) {
130
+ // A queued child may have been rebuilt earlier in this drain, so its preloaded content is stale: reread then.
131
+ const children = preloaded.some((c) => queuedIds.has(c.id))
132
+ ? loadChildrenOfSummary(hippoRoot, summary.id, summary.tenant_id)
133
+ : preloaded;
126
134
  if (children.length === 0) {
127
135
  clearZeroChildSummary(hippoRoot, summary, result);
128
136
  return;
@@ -179,7 +187,8 @@ function summaryLabel(summary) {
179
187
  * A concurrent sleep's second writer gets changed=false (UPDATE requires summary_dirty=1) and is skipped silently; a tombstone hit counts as `refused`. */
180
188
  export async function rebuildDirtySummaries(hippoRoot, opts) {
181
189
  const cap = opts.cap ?? DEFAULT_REBUILD_CAP;
182
- const dirty = loadAllDirtySummaries(hippoRoot);
190
+ // One past the cap tells whether more were waiting without reading the rest.
191
+ const dirty = loadAllDirtySummaries(hippoRoot, cap + 1);
183
192
  const capped = dirty.length > cap;
184
193
  const queue = dirty.slice(0, cap);
185
194
  const result = {
@@ -190,6 +199,8 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
190
199
  failed: 0,
191
200
  capped,
192
201
  };
202
+ const childrenByParent = loadChildrenOfSummaries(hippoRoot, queue);
203
+ const queuedIds = new Set(queue.map((s) => s.id));
193
204
  for (const [index, summary] of queue.entries()) {
194
205
  // Yield the macrotask queue every 25 summaries: each iteration is synchronous SQLite, so a batch of up to 1000
195
206
  // would starve timers and IPC (server keep-alives, Vitest's birpc heartbeat).
@@ -197,13 +208,13 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
197
208
  await new Promise((resolve) => setImmediate(resolve));
198
209
  }
199
210
  try {
200
- await rebuildOneSummary(hippoRoot, summary, opts, result);
211
+ await rebuildOneSummary(hippoRoot, summary, opts, result, childrenByParent.get(childrenKey(summary.tenant_id, summary.id)) ?? [], queuedIds);
201
212
  }
202
213
  catch (err) {
203
214
  // One throw doesn't abort the queue; log enough to triage an exotic
204
215
  // failure (SQLite I/O, prepare), since audit() already catches its own.
205
216
  result.failed++;
206
- log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenantId}) failed: ${errorMessage(err)}`, errorFields(err));
217
+ log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenant_id}) failed: ${errorMessage(err)}`, errorFields(err));
207
218
  }
208
219
  }
209
220
  return result;
@@ -269,7 +280,7 @@ export async function buildEntityProfiles(hippoRoot, l2Summaries, opts) {
269
280
  const unparented = l2Summaries.filter((s) => s.dag_level === 2 && !s.dag_parent_id);
270
281
  for (const [, tenantL2s] of partitionFactsByTenant(unparented)) {
271
282
  const home = {
272
- tenantId: tenantL2s[0].tenantId,
283
+ tenantId: tenantL2s[0].tenant_id,
273
284
  scope: derivationScope(tenantL2s[0].scope),
274
285
  originProject: tenantL2s[0].origin_project,
275
286
  baseHalfLifeDays,
@@ -1,5 +1,6 @@
1
1
  /** Store-level dedup: same text apart from spacing, keeping the stronger copy; split out so `api.sleep` can dedupe without cli -> api imports.
2
2
  * Survivor order is total and tenant-scoped: strength bucket, retrieval_count, then compareEntryIdentity; raw and superseded rows are not candidates. */
3
+ import { type MemoryEntry } from '../core/memory.js';
3
4
  export interface DedupPair {
4
5
  kept: string;
5
6
  keptContent: string;
@@ -19,11 +20,17 @@ export interface DedupResult {
19
20
  /** Quantize strength to an integer bucket so ties are a true equivalence relation (equal iff same multiple of `STRENGTH_TIE_EPSILON`).
20
21
  * Non-finite input maps to 0: a NaN bucket would make the comparator return NaN and break the total order. */
21
22
  export declare function strengthBucket(strength: number | null | undefined): number;
23
+ /** Every row of the store, read once by a caller that also needs them, with the ids of rows backing an object. */
24
+ export interface LoadedStore {
25
+ readonly entries: readonly MemoryEntry[];
26
+ readonly backing: ReadonlySet<string>;
27
+ }
22
28
  /** Remove the weaker copy of same-text (apart from spacing) memories within one tenant; cross-tenant pairs are never duplicates (isolation boundary).
23
29
  * Higher strength wins, then more retrievals; `threshold` is accepted for old callers and ignored. */
24
30
  export declare function deduplicateStore(hippoRoot: string, options?: {
25
31
  threshold?: number;
26
32
  dryRun?: boolean;
27
33
  actor?: string;
34
+ loaded?: LoadedStore;
28
35
  }): DedupResult;
29
36
  //# sourceMappingURL=dedupe.d.ts.map
@@ -5,7 +5,7 @@ import { loadCurrentDistilledEntries } from '../store/entry-reads.js';
5
5
  import { deleteEntriesOneByOne, memoriesBackingObjects } from '../store/delete-and-batch.js';
6
6
  import { compareEntryIdentity } from '../core/compare.js';
7
7
  import { canAutoDelete } from '../core/memory.js';
8
- import { derivationPartitionKey } from '../store/recall-scope.js';
8
+ import { derivationPartitionKey } from '../core/recall-scope.js';
9
9
  import { duplicateKey } from '../util/same-text.js';
10
10
  /** Quantization step for strength-tie comparisons: the 0.01 epsilon applied by rounding instead of an abs-diff threshold, so the tiebreak is transitive. */
11
11
  const STRENGTH_TIE_EPSILON = 0.01;
@@ -34,7 +34,7 @@ function entriesByPartition(entries) {
34
34
  const entriesByTenant = new Map();
35
35
  for (const entry of entries) {
36
36
  // EI2: also split by restricted scope, else a private copy can delete the readable one.
37
- const key = derivationPartitionKey(entry.tenantId, entry.scope, entry.origin_project);
37
+ const key = derivationPartitionKey(entry.tenant_id, entry.scope, entry.origin_project);
38
38
  const bucket = entriesByTenant.get(key);
39
39
  if (bucket)
40
40
  bucket.push(entry);
@@ -73,18 +73,20 @@ function partitionPairs(tenantEntries, removed, backing) {
73
73
  }
74
74
  return [...groups.values()].flatMap((group) => group.pairs);
75
75
  }
76
+ /** The rows loadCurrentDistilledEntries selects, picked from a whole-store read. */
77
+ const isCurrentDistilled = (e) => (e.kind ?? 'distilled') === 'distilled' && !e.superseded_by;
76
78
  /** Remove the weaker copy of same-text (apart from spacing) memories within one tenant; cross-tenant pairs are never duplicates (isolation boundary).
77
79
  * Higher strength wins, then more retrievals; `threshold` is accepted for old callers and ignored. */
78
80
  export function deduplicateStore(hippoRoot, options = {}) {
79
81
  const dryRun = options.dryRun ?? false;
80
82
  // Only current distilled rows compete: raw rows are append-only (the delete
81
83
  // trigger would abort sleep mid-loop) and superseded rows are history.
82
- const entries = loadCurrentDistilledEntries(hippoRoot);
84
+ const entries = options.loaded?.entries.filter(isCurrentDistilled) ?? loadCurrentDistilledEntries(hippoRoot);
83
85
  const entriesByTenant = entriesByPartition(entries);
84
86
  // Shared across tenant groups: ids are globally unique UUIDs, so `removed` cannot collide across tenants and deleteEntry deletes by primary key alone.
85
87
  const removed = new Set();
86
88
  const pairs = [];
87
- const backing = memoriesBackingObjects(hippoRoot);
89
+ const backing = options.loaded?.backing ?? memoriesBackingObjects(hippoRoot);
88
90
  for (const tenantEntries of entriesByTenant.values()) {
89
91
  // The survivor total order (see the file-level docstring), scoped per
90
92
  // tenant group: the total order holds within a tenant only, matching the partition above.
@@ -1,8 +1,11 @@
1
1
  import { envAnthropicApiKey, envDagRebuildCap } from '../util/env.js';
2
2
  import { Layer } from '../core/memory.js';
3
- import { log } from '../util/log.js';
3
+ import { errorFields, errorMessage, log } from '../util/log.js';
4
4
  import { keptAsWritten } from './run.js';
5
5
  import { isReusable } from '../core/memory-quality.js';
6
+ import { isPermanentFailure } from '../util/anthropic-messages.js';
7
+ // Bounds the LLM calls one sleep spends on extraction.
8
+ const EXTRACTION_BATCH_LIMIT = 20;
6
9
  /** The key, model options and once-per-line error reporter every LLM phase shares. */
7
10
  function sleepLlm(run, fetcher) {
8
11
  const { config, result } = run;
@@ -28,21 +31,10 @@ export async function llmPasses(run, fetcher) {
28
31
  run.result.extractionCandidates = extractionCandidates.length;
29
32
  const llm = sleepLlm(run, fetcher);
30
33
  if (llm.apiKey && extractionCandidates.length > 0 && !run.dryRun) {
31
- const { extractFacts, storeExtractedFacts } = await import('../learn/extract.js');
32
- const batchLimit = 20;
33
- let extractedCount = 0;
34
- for (const candidate of extractionCandidates.slice(0, batchLimit)) {
35
- try {
36
- const facts = await extractFacts(candidate.content, { ...llm.llmOpts, onError: llm.llmError('extraction') });
37
- if (facts.length > 0) {
38
- extractedCount += storeExtractedFacts(run.hippoRoot, candidate, facts).length;
39
- }
40
- }
41
- catch (err) {
42
- llm.llmError('extraction')(String(err));
43
- }
44
- }
45
- run.result.extracted = extractedCount;
34
+ const stopped = await extractionPass(run, llm, extractionCandidates.slice(0, EXTRACTION_BATCH_LIMIT));
35
+ // The DAG passes call the same API with the same key and model, so they would fail the same way.
36
+ if (stopped)
37
+ return;
46
38
  }
47
39
  await dagBuildPass(run, llm);
48
40
  if (llm.apiKey && !run.dryRun) {
@@ -50,6 +42,37 @@ export async function llmPasses(run, fetcher) {
50
42
  await entityProfilePass(run, llm);
51
43
  }
52
44
  }
45
+ /** Extracts facts from each candidate; true when it stopped on a failure every later call would repeat (bad key, no credit, unknown model). */
46
+ async function extractionPass(run, llm, batch) {
47
+ const { extractFacts, storeExtractedFacts } = await import('../learn/extract.js');
48
+ const report = llm.llmError('extraction');
49
+ let extractedCount = 0;
50
+ let stopped = false;
51
+ const onError = (msg, failure) => {
52
+ report(msg);
53
+ if (failure && isPermanentFailure(failure))
54
+ stopped = true;
55
+ };
56
+ for (const [index, candidate] of batch.entries()) {
57
+ try {
58
+ const facts = await extractFacts(candidate.content, { ...llm.llmOpts, onError });
59
+ if (facts.length > 0) {
60
+ extractedCount += storeExtractedFacts(run.hippoRoot, candidate, facts).length;
61
+ }
62
+ }
63
+ catch (err) {
64
+ report(errorMessage(err));
65
+ log.warn('consolidate extraction threw', errorFields(err));
66
+ }
67
+ if (stopped) {
68
+ const skipped = batch.length - index - 1;
69
+ report(`stopped after a failure that will not clear on retry; ${skipped} of ${batch.length} candidates skipped, and the DAG passes with them`);
70
+ break;
71
+ }
72
+ }
73
+ run.result.extracted = extractedCount;
74
+ return stopped;
75
+ }
53
76
  // 1.7. DAG summarization — cluster extracted facts and generate summaries
54
77
  async function dagBuildPass(run, { apiKey, llmError, llmOpts }) {
55
78
  const extractedFacts = run.survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1 && !e.superseded_by && isReusable(e));
@@ -65,7 +88,8 @@ async function dagBuildPass(run, { apiKey, llmError, llmOpts }) {
65
88
  }
66
89
  }
67
90
  catch (err) {
68
- llmError('dag')(String(err));
91
+ llmError('dag')(errorMessage(err));
92
+ log.warn('consolidate dag threw', errorFields(err));
69
93
  }
70
94
  }
71
95
  // 1.8. DAG summary rebuild: drain the summary_dirty queue set by child-write hooks; same apiKey/dryRun gate as buildDag.
@@ -99,7 +123,8 @@ async function dagRebuildPass(run, { llmError, llmOpts }) {
99
123
  }
100
124
  }
101
125
  catch (err) {
102
- llmError('dag rebuild')(String(err));
126
+ llmError('dag rebuild')(errorMessage(err));
127
+ log.warn('consolidate dag rebuild threw', errorFields(err));
103
128
  }
104
129
  }
105
130
  // 1.9. DAG entity profiles: cluster L2 summaries into per-entity L3 profiles; runs even when 1.7 was skipped (re-clusters existing L2s every sleep).
@@ -118,7 +143,8 @@ async function entityProfilePass(run, { llmError, llmOpts }) {
118
143
  }
119
144
  }
120
145
  catch (err) {
121
- llmError('dag profiles')(String(err));
146
+ llmError('dag profiles')(errorMessage(err));
147
+ log.warn('consolidate dag profiles threw', errorFields(err));
122
148
  }
123
149
  }
124
150
  //# sourceMappingURL=llm-passes.js.map
@@ -1,6 +1,7 @@
1
1
  /** Learned memory-value scorer, a rescue-only veto in the sleep decay pass (it can only shrink the condemned set); mirrors benchmarks/memory-value/*.mjs.
2
2
  * rescueSet rescues a condemned entry iff it ranks in the top 30% (RESCUE_BUDGET) of its tenant's non-pinned set; memory-value-wiring.test.ts guards parity. */
3
3
  import { DEFAULT_TENANT_ID } from '../util/env.js';
4
+ import { strengthAblation } from '../core/ablation.js';
4
5
  import { calculateStrength } from '../core/memory.js';
5
6
  import { compareEntryIdentity } from '../core/compare.js';
6
7
  import { MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256 } from './memory-value-weights.js';
@@ -31,7 +32,7 @@ export function computeMvFeatures(entry, now) {
31
32
  return {
32
33
  age_days: ageDays,
33
34
  half_life_days: entry.half_life_days,
34
- strength: calculateStrength(entry, now), // clock-basis, never decayOpts — see doc comment above
35
+ strength: calculateStrength(entry, now, { ablation: strengthAblation() }), // clock-basis, never the production decay basis — see doc comment above
35
36
  retrieval_count: entry.retrieval_count,
36
37
  outcome_positive: pos,
37
38
  outcome_negative: neg,
@@ -113,7 +114,7 @@ export function rankNonPinnedByTenant(entries, now, weights = MEMORY_VALUE_WEIGH
113
114
  continue; // pinned entries never compete for rescue (never condemned)
114
115
  // Default an undefined tenantId as dag.ts:341 does: a raw/legacy row can carry one at runtime,
115
116
  // and keying it "undefined" would split it into its own singleton tenant.
116
- const tenantId = e.tenantId ?? DEFAULT_TENANT_ID;
117
+ const tenantId = e.tenant_id ?? DEFAULT_TENANT_ID;
117
118
  const list = byTenant.get(tenantId);
118
119
  if (list)
119
120
  list.push(e);
@@ -3,10 +3,10 @@ import { tokenize } from '../util/tokenize.js';
3
3
  import { jaccardMinShared, overlapPartners } from './overlap-index.js';
4
4
  import { compareEntryIdentity } from '../core/compare.js';
5
5
  import { duplicateKey, mergedText } from '../util/same-text.js';
6
- import { successorAfterRetirement } from './merged-row.js';
6
+ import { successorAfterRetirement } from '../core/merged-row.js';
7
7
  import { rejectionDigest } from '../store/rejection.js';
8
8
  import { reportAuditWriteFailure } from '../store/audit.js';
9
- import { derivationScope, derivationPartitionKey } from '../store/recall-scope.js';
9
+ import { derivationScope, derivationPartitionKey } from '../core/recall-scope.js';
10
10
  import { jaccardSets } from './conflicts.js';
11
11
  import { keptAsWritten } from './run.js';
12
12
  import { isReusable } from '../core/memory-quality.js';
@@ -23,7 +23,7 @@ export function retireHeldTexts(run) {
23
23
  const rejectedIn = (tenantId) => (text) => run.tombstones.find(tenantId, rejectionDigest(text)) !== null;
24
24
  for (let i = survivors.length - 1; i >= 0; i--) {
25
25
  const row = survivors[i];
26
- const successor = run.retirable(row) ? successorAfterRetirement(row, byId, rejectedIn(row.tenantId)) : undefined;
26
+ const successor = run.retirable(row) ? successorAfterRetirement(row, byId, rejectedIn(row.tenant_id)) : undefined;
27
27
  if (successor === undefined)
28
28
  continue;
29
29
  run.result.details.push(` ✂️ ${row.id} held a retired text${successor ? `, ${successor.id} holds the rest` : ''}`);
@@ -51,7 +51,7 @@ function partitionMergeCandidates(survivors) {
51
51
  // Map keeps insertion order, so a single-tenant store gets one partition in the original order.
52
52
  const mergeCandidatesByTenant = new Map();
53
53
  for (const entry of mergeCandidates) {
54
- const key = derivationPartitionKey(entry.tenantId, entry.scope, entry.origin_project);
54
+ const key = derivationPartitionKey(entry.tenant_id, entry.scope, entry.origin_project);
55
55
  const bucket = mergeCandidatesByTenant.get(key);
56
56
  if (bucket)
57
57
  bucket.push(entry);
@@ -70,7 +70,7 @@ export function mergePass(run) {
70
70
  let mergesSkippedRejected = 0;
71
71
  for (const [, tenantCandidates] of mergeCandidatesByTenant) {
72
72
  const partition = {
73
- tenantId: tenantCandidates[0].tenantId,
73
+ tenantId: tenantCandidates[0].tenant_id,
74
74
  scope: derivationScope(tenantCandidates[0].scope),
75
75
  origin: tenantCandidates[0].origin_project,
76
76
  };
@@ -156,8 +156,8 @@ function mergeRejected(run, semantic, cluster, related, used) {
156
156
  const { tombstones } = run;
157
157
  const newDigest = rejectionDigest(semantic.content);
158
158
  const oldDigest = rejectionDigest(legacyMergeContents(related)); // tombstones from older releases hold this format's digest
159
- const newHit = tombstones.find(semantic.tenantId, newDigest);
160
- const tombstone = newHit ?? tombstones.find(semantic.tenantId, oldDigest);
159
+ const newHit = tombstones.find(semantic.tenant_id, newDigest);
160
+ const tombstone = newHit ?? tombstones.find(semantic.tenant_id, oldDigest);
161
161
  const mergeDigest = newHit ? newDigest : oldDigest;
162
162
  if (!tombstone)
163
163
  return false;
@@ -167,7 +167,7 @@ function mergeRejected(run, semantic, cluster, related, used) {
167
167
  used.add(e.id);
168
168
  try {
169
169
  tombstones.audit({
170
- tenantId: semantic.tenantId,
170
+ tenantId: semantic.tenant_id,
171
171
  actor: 'sleep',
172
172
  op: 'reject_refusal',
173
173
  metadata: {
@@ -1,3 +1,8 @@
1
+ import { type PhysicsParticle } from '../core/physics.js';
2
+ import type { MemoryEntry } from '../core/memory.js';
1
3
  import type { SleepRun } from './run.js';
2
- export declare function physicsPass(run: SleepRun): void;
4
+ export declare function physicsPass(run: SleepRun, maxParticles?: number): void;
5
+ /** Every stored particle in load order up to the cap; past it, the most recently recalled survivors (memory id breaks ties),
6
+ * then particles with no survivor. */
7
+ export declare function particlesToSimulate(stored: PhysicsParticle[], entries: ReadonlyMap<string, MemoryEntry>, max?: number): PhysicsParticle[];
3
8
  //# sourceMappingURL=physics-pass.d.ts.map
@@ -3,8 +3,10 @@ import { loadStoredParticles, saveStoredParticles } from '../store/vector-index.
3
3
  import { simulate } from '../core/physics.js';
4
4
  import { errorMessage } from '../util/log.js';
5
5
  const STATS_DECIMALS = 4;
6
+ // Every substep is all-pairs, so one sleep moves at most this many particles; the rest keep their stored state until they are recalled.
7
+ const SLEEP_PHYSICS_MAX_PARTICLES = 1000;
6
8
  // 2. Physics simulation pass
7
- export function physicsPass(run) {
9
+ export function physicsPass(run, maxParticles = SLEEP_PHYSICS_MAX_PARTICLES) {
8
10
  if (run.dryRun)
9
11
  return;
10
12
  const { config, result } = run;
@@ -12,27 +14,45 @@ export function physicsPass(run) {
12
14
  const physicsEnabled = config.physics.enabled === true
13
15
  || (config.physics.enabled === 'auto');
14
16
  if (physicsEnabled)
15
- simulateStoredParticles(run);
17
+ simulateStoredParticles(run, maxParticles);
16
18
  }
17
19
  catch (error) {
18
20
  result.details.push(` ⚠️ physics simulation skipped: ${errorMessage(error)}`);
19
21
  }
20
22
  }
21
- function simulateStoredParticles(run) {
23
+ function simulateStoredParticles(run, maxParticles) {
22
24
  const { result, survivors } = run;
23
- const particles = loadStoredParticles(run.hippoRoot);
24
- if (particles.length === 0)
25
+ const stored = loadStoredParticles(run.hippoRoot);
26
+ if (stored.length === 0)
25
27
  return;
26
28
  // Build entry lookup for property refresh
27
29
  const entryMap = new Map(survivors.map(e => [e.id, e]));
30
+ const particles = particlesToSimulate(stored, entryMap, maxParticles);
28
31
  refreshParticleProperties(particles, entryMap, run.now);
29
32
  const stats = simulate(particles, survivorForces(run));
30
33
  saveStoredParticles(run.hippoRoot, particles);
31
34
  result.physicsSimulated = stats.particleCount;
32
- result.details.push(` ⚛️ physics: ${stats.particleCount} particles, ` +
35
+ const capped = particles.length < stored.length ? ` (the ${particles.length} most recently recalled of ${stored.length})` : '';
36
+ result.details.push(` ⚛️ physics: ${stats.particleCount} particles${capped}, ` +
33
37
  `avg vel ${stats.avgVelocityMagnitude.toFixed(STATS_DECIMALS)}, ` +
34
38
  `energy ${stats.energy.total.toFixed(STATS_DECIMALS)}`);
35
39
  }
40
+ /** Every stored particle in load order up to the cap; past it, the most recently recalled survivors (memory id breaks ties),
41
+ * then particles with no survivor. */
42
+ export function particlesToSimulate(stored, entries, max = SLEEP_PHYSICS_MAX_PARTICLES) {
43
+ if (stored.length <= max)
44
+ return stored;
45
+ const recalled = (p) => entries.get(p.memoryId)?.last_retrieved ?? '';
46
+ const ranked = [...stored].sort((a, b) => {
47
+ const [ra, rb] = [recalled(a), recalled(b)];
48
+ if (ra !== rb)
49
+ return ra < rb ? 1 : -1;
50
+ return a.memoryId < b.memoryId ? -1 : a.memoryId > b.memoryId ? 1 : 0;
51
+ });
52
+ const kept = new Set(ranked.slice(0, max));
53
+ // Load order, not rank order: the force sums run in this order, so a capped run matches an uncapped one over the same set.
54
+ return stored.filter((p) => kept.has(p));
55
+ }
36
56
  function survivorForces(run) {
37
57
  // Build conflict pairs from survivors
38
58
  const conflictPairs = new Map();
@@ -1,5 +1,6 @@
1
1
  /** Replay: during `hippo sleep`, sample N survivors weighted by reward, valence, under-rehearsal and age, then apply the `markRetrieved` strengthening.
2
2
  * A lightweight deterministic analog of hippocampal replay, so important memories stay strong without being queried; distinct from decay, physics and merge. */
3
+ import { HOUR_MS } from '../util/time.js';
3
4
  import { isOutcomeSlowAblated } from '../core/ablation.js';
4
5
  import { resolveConfidence } from '../core/memory.js';
5
6
  const VALENCE_WEIGHT = {
@@ -8,6 +9,12 @@ const VALENCE_WEIGHT = {
8
9
  negative: 1.5,
9
10
  critical: 2.0,
10
11
  };
12
+ // Floor keeps every weight positive for sampleForReplay; the rest scale reward and idle boosts.
13
+ const REWARD_FLOOR = 0.1;
14
+ const REWARD_POSITIVE_GAIN = 0.5;
15
+ const REWARD_NET_GAIN = 0.25;
16
+ const IDLE_BOOST_GAIN = 0.1;
17
+ const STRENGTH_FLOOR = 0.1;
11
18
  /** Priority score for ranking survivors for replay (higher = more likely sampled); pure in the entry and current time. */
12
19
  export function replayPriority(entry, now, outcomeAblated) {
13
20
  const pos = entry.outcome_positive ?? 0;
@@ -16,18 +23,18 @@ export function replayPriority(entry, now, outcomeAblated) {
16
23
  // The clamp is required because sampleForReplay needs all weights positive.
17
24
  const rewardSignal = outcomeAblated
18
25
  ? 1.0 // EVAL-ONLY ablation (see ablation.ts): outcome-off also silences replay's reward bias
19
- : Math.max(0.1, 1 + pos * 0.5 + (pos - neg) * 0.25);
26
+ : Math.max(REWARD_FLOOR, 1 + pos * REWARD_POSITIVE_GAIN + (pos - neg) * REWARD_NET_GAIN);
20
27
  const valence = VALENCE_WEIGHT[entry.emotional_valence] ?? 1.0;
21
28
  // Under-rehearsed memories benefit most from replay.
22
29
  const underRehearsed = 1 / (1 + (entry.retrieval_count ?? 0));
23
30
  // Idle-time boost: memories that haven't been touched recently need rehearsal more.
24
31
  const lastRetrieved = new Date(entry.last_retrieved);
25
32
  const deltaMs = now.getTime() - lastRetrieved.getTime();
26
- const ageHours = Number.isFinite(deltaMs) ? Math.max(0, deltaMs / 3_600_000) : 0;
27
- const idleBoost = 1 + Math.log1p(ageHours) * 0.1;
33
+ const ageHours = Number.isFinite(deltaMs) ? Math.max(0, deltaMs / HOUR_MS) : 0;
34
+ const idleBoost = 1 + Math.log1p(ageHours) * IDLE_BOOST_GAIN;
28
35
  // Weight by current strength so dead-and-decaying memories don't waste replay slots.
29
36
  const rawStrength = Number.isFinite(entry.strength) ? entry.strength : 0;
30
- const strengthFloor = Math.max(0.1, rawStrength);
37
+ const strengthFloor = Math.max(STRENGTH_FLOOR, rawStrength);
31
38
  return rewardSignal * valence * underRehearsed * idleBoost * strengthFloor;
32
39
  }
33
40
  /** Deterministic 32-bit RNG (Mulberry32): same seed, same sequence, so replay is reproducible without a random-number dependency. */
@@ -1,5 +1,5 @@
1
1
  /** Consolidation engine ("Sleep"): decay pass (drop entries below the strength threshold), merge pass (semantic summaries of overlapping episodics), stats. */
2
- import { evalNow } from '../core/ablation.js';
2
+ import { evalNow, strengthAblation } from '../core/ablation.js';
3
3
  import { canAutoDelete } from '../core/memory.js';
4
4
  import { loadAllEntriesWithBase } from '../store/entry-reads.js';
5
5
  import { commitInChunks, memoriesBackingObjects } from '../store/delete-and-batch.js';
@@ -11,7 +11,7 @@ import { loadConfig } from '../core/config.js';
11
11
  import { recordAuditEventsRowByRow, reportAuditWriteFailure } from '../store/audit.js';
12
12
  import { lazyTombstoneChecks } from '../store/tombstone-checks.js';
13
13
  import { migrateDefaultHalfLife, LEGACY_TYPED_HALF_LIFE } from './half-life-migration.js';
14
- import { errorMessage, log } from '../util/log.js';
14
+ import { errorFields, errorMessage, log } from '../util/log.js';
15
15
  import { WRITE_BUDGET } from '../util/write-budget.js';
16
16
  import { decayPass } from './decay.js';
17
17
  import { familyUnits, groupFlush } from './flush-units.js';
@@ -68,6 +68,7 @@ function sessionDecayOptions(hippoRoot, config) {
68
68
  decayBasis: config.decayBasis,
69
69
  avgSessionIntervalDays: sessionCtx.avgSessionIntervalDays,
70
70
  sleepCount: sessionCtx.sleepCount,
71
+ ablation: strengthAblation(),
71
72
  };
72
73
  }
73
74
  /** Every pass between decay and the flush; the tombstone-check handle closes whichever of them throws. */
@@ -96,7 +97,8 @@ function migrateHalfLives(hippoRoot, dryRun, result) {
96
97
  result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.rescaled} memories from the ${halfLife.from}-day to the ${halfLife.to}-day half-life`);
97
98
  }
98
99
  if (halfLife.typed > 0) {
99
- result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects from the ${LEGACY_TYPED_HALF_LIFE}-day to the ${halfLife.to}-day half-life`);
100
+ result.details.push(` ⏳ ${dryRun ? 'would move' : 'moved'} ${halfLife.typed} memories of decisions, incidents and other objects ` +
101
+ `from the ${LEGACY_TYPED_HALF_LIFE}-day to the ${halfLife.to}-day half-life`);
100
102
  }
101
103
  return halfLife;
102
104
  }
@@ -126,7 +128,8 @@ async function expireDormant(run, budget) {
126
128
  const cutoff = new Date(run.now.getTime() - config.dormant.retentionDays * DAY_MS).toISOString();
127
129
  result.dormantExpired = await expireDormantBefore(run.hippoRoot, cutoff, { dryRun, budget, busyWaitMs: SLEEP_DB_WAIT_MS });
128
130
  if (result.dormantExpired > 0) {
129
- result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} older than ${config.dormant.retentionDays} days`);
131
+ result.details.push(` ⌛ ${dryRun ? 'would expire' : 'expired'} ${result.dormantExpired} dormant memor${result.dormantExpired === 1 ? 'y' : 'ies'} ` +
132
+ `older than ${config.dormant.retentionDays} days`);
130
133
  }
131
134
  }
132
135
  // 4. Log run
@@ -153,7 +156,7 @@ function auditRescues(run, { rescuedEntries, rankById }) {
153
156
  const rescueEvent = (entry) => {
154
157
  const rank = rankById.get(entry.id);
155
158
  return {
156
- tenantId: entry.tenantId,
159
+ tenantId: entry.tenant_id,
157
160
  actor: 'sleep',
158
161
  op: 'mv_rescue',
159
162
  targetId: entry.id,
@@ -175,7 +178,7 @@ function auditRescues(run, { rescuedEntries, rankById }) {
175
178
  }
176
179
  catch (err) {
177
180
  // An audit store that will not open must never crash the mutation it records.
178
- log.debug(`mv_rescue audit unavailable: ${errorMessage(err)}`);
181
+ log.warn(`mv_rescue audit unavailable: ${errorMessage(err)}`, { errorClass: errorFields(err).errorClass });
179
182
  result.details.push(` ⚠️ memory-value: mv_rescue audit unavailable this cycle ` +
180
183
  `(${rescuedEntries.length} rescue${rescuedEntries.length === 1 ? '' : 's'} not audited)`);
181
184
  }
@@ -1,4 +1,4 @@
1
- import { isRecallBoostAblated } from '../core/ablation.js';
1
+ import { isRecallBoostAblated, strengthAblation } from '../core/ablation.js';
2
2
  import { Layer, createMemory, markRetrieved } from '../core/memory.js';
3
3
  import { findPromotableSessions, traceExistsForSession, listSessionEvents } from '../store/sessions.js';
4
4
  import { rejectionDigest } from '../store/rejection.js';
@@ -6,7 +6,7 @@ import { sampleForReplay } from './replay.js';
6
6
  import { renderTraceContent } from './trace.js';
7
7
  import { resolveTenantId } from '../store/tenant.js';
8
8
  import { reportAuditWriteFailure } from '../store/audit.js';
9
- import { commonDerivationScope } from '../store/recall-scope.js';
9
+ import { commonDerivationScope } from '../core/recall-scope.js';
10
10
  import { log } from '../util/log.js';
11
11
  import { REPLAY_COUNT_DEFAULT } from './run.js';
12
12
  import { isJsonString } from '../util/json.js';
@@ -103,12 +103,12 @@ function sessionEnding(events) {
103
103
  // sleep; check the tombstone under the entry's own stamped tenantId, never a guessed one.
104
104
  function traceRejected(run, trace, sessionId) {
105
105
  const traceDigest = rejectionDigest(trace.content);
106
- const tombstone = run.tombstones.find(trace.tenantId, traceDigest);
106
+ const tombstone = run.tombstones.find(trace.tenant_id, traceDigest);
107
107
  if (!tombstone)
108
108
  return false;
109
109
  try {
110
110
  run.tombstones.audit({
111
- tenantId: trace.tenantId,
111
+ tenantId: trace.tenant_id,
112
112
  actor: 'sleep',
113
113
  op: 'reject_refusal',
114
114
  metadata: {
@@ -136,7 +136,7 @@ export function replayPass(run) {
136
136
  const picked = sampleForReplay(survivors, replayCount, now, seed);
137
137
  if (picked.length === 0)
138
138
  return;
139
- const rehearsed = markRetrieved(picked, now);
139
+ const rehearsed = markRetrieved(picked, now, { ablation: strengthAblation() });
140
140
  const rehearsedById = new Map(rehearsed.map((e) => [e.id, e]));
141
141
  // Update survivors in place so downstream passes see rehearsed state.
142
142
  for (let i = 0; i < survivors.length; i++) {
@@ -1,6 +1,16 @@
1
1
  /** EVAL-ONLY ablation switches (HIPPO_ABLATE_*, HIPPO_EVAL_RECENCY_DAYS, HIPPO_FAKE_NOW): each cuts ONE mechanism (outcome also replayPriority bias).
2
2
  * Not a production surface. Env is read once per process; tests that mutate these vars MUST call _resetAblationCacheForTests() in beforeEach AND afterEach. See
3
3
  * docs/ARCHITECTURE.md#srccoreablationts. */
4
+ /** The three switches strength scoring honours, resolved by the entry layer and handed to core in DecayOptions. */
5
+ export interface StrengthAblation {
6
+ readonly decay: boolean;
7
+ readonly recallBoost: boolean;
8
+ readonly outcomeSlow: boolean;
9
+ }
10
+ /** Production scoring: nothing ablated. Core falls back to this, so it never reads the environment. */
11
+ export declare const NO_STRENGTH_ABLATION: StrengthAblation;
12
+ /** The frozen strength switches for this process; entry-layer callers pass them as `DecayOptions.ablation`. */
13
+ export declare function strengthAblation(): StrengthAblation;
4
14
  export declare function isDecayAblated(): boolean;
5
15
  export declare function isRecallBoostAblated(): boolean;
6
16
  export declare function isOutcomeSlowAblated(): boolean;