hippo-memory 1.60.0 → 1.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (585) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1262
  53. package/dist/api.js +25 -2727
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +6 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +2 -2
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +71 -120
  123. package/dist/cli.js +170 -8469
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +6 -4
  126. package/dist/connectors/github/backfill.js +94 -87
  127. package/dist/connectors/github/cli-impl.js +4 -3
  128. package/dist/connectors/github/dlq.js +67 -54
  129. package/dist/connectors/github/ingest.js +34 -35
  130. package/dist/connectors/github/tenant-routing.js +3 -2
  131. package/dist/connectors/github/webhook.js +135 -216
  132. package/dist/connectors/slack/dlq.js +49 -61
  133. package/dist/connectors/slack/ingest.js +55 -48
  134. package/dist/connectors/slack/tenant-routing.js +4 -3
  135. package/dist/connectors/slack/webhook.js +72 -74
  136. package/dist/consolidate/conflicts.d.ts +10 -0
  137. package/dist/consolidate/conflicts.js +178 -0
  138. package/dist/consolidate/decay.d.ts +12 -0
  139. package/dist/consolidate/decay.js +145 -0
  140. package/dist/consolidate/llm-passes.d.ts +3 -0
  141. package/dist/consolidate/llm-passes.js +141 -0
  142. package/dist/consolidate/merge.d.ts +7 -0
  143. package/dist/consolidate/merge.js +251 -0
  144. package/dist/consolidate/physics-pass.d.ts +3 -0
  145. package/dist/consolidate/physics-pass.js +60 -0
  146. package/dist/consolidate/run.d.ts +69 -0
  147. package/dist/consolidate/run.js +76 -0
  148. package/dist/consolidate/sleep.d.ts +18 -0
  149. package/dist/consolidate/sleep.js +209 -0
  150. package/dist/consolidate/traces.d.ts +4 -0
  151. package/dist/consolidate/traces.js +178 -0
  152. package/dist/context-auto.js +7 -11
  153. package/dist/context-render.d.ts +1 -1
  154. package/dist/context-render.js +1 -1
  155. package/dist/customer-notes.d.ts +3 -0
  156. package/dist/customer-notes.js +6 -4
  157. package/dist/dag.js +6 -5
  158. package/dist/dashboard-actions.d.ts +20 -0
  159. package/dist/dashboard-actions.js +88 -0
  160. package/dist/dashboard-params.d.ts +45 -0
  161. package/dist/dashboard-params.js +127 -0
  162. package/dist/dashboard-queries.d.ts +15 -0
  163. package/dist/dashboard-queries.js +355 -0
  164. package/dist/dashboard-snapshot.d.ts +138 -0
  165. package/dist/dashboard-snapshot.js +308 -0
  166. package/dist/dashboard-types.d.ts +163 -0
  167. package/dist/dashboard-types.js +3 -0
  168. package/dist/dashboard.d.ts +6 -7
  169. package/dist/dashboard.js +228 -202
  170. package/dist/db/busy.d.ts +5 -0
  171. package/dist/db/busy.js +24 -0
  172. package/dist/db/continuity.d.ts +5 -0
  173. package/dist/db/continuity.js +145 -0
  174. package/dist/db/meta.d.ts +8 -0
  175. package/dist/db/meta.js +35 -0
  176. package/dist/db/migrate.d.ts +9 -0
  177. package/dist/db/migrate.js +138 -0
  178. package/dist/db/migrations/index.d.ts +5 -0
  179. package/dist/db/migrations/index.js +109 -0
  180. package/dist/db/migrations/types.d.ts +14 -0
  181. package/dist/db/migrations/types.js +2 -0
  182. package/dist/db/migrations/v01.d.ts +3 -0
  183. package/dist/db/migrations/v01.js +38 -0
  184. package/dist/db/migrations/v02.d.ts +3 -0
  185. package/dist/db/migrations/v02.js +21 -0
  186. package/dist/db/migrations/v03.d.ts +3 -0
  187. package/dist/db/migrations/v03.js +22 -0
  188. package/dist/db/migrations/v04.d.ts +3 -0
  189. package/dist/db/migrations/v04.js +28 -0
  190. package/dist/db/migrations/v05.d.ts +3 -0
  191. package/dist/db/migrations/v05.js +21 -0
  192. package/dist/db/migrations/v06.d.ts +3 -0
  193. package/dist/db/migrations/v06.js +25 -0
  194. package/dist/db/migrations/v07.d.ts +3 -0
  195. package/dist/db/migrations/v07.js +13 -0
  196. package/dist/db/migrations/v08.d.ts +3 -0
  197. package/dist/db/migrations/v08.js +8 -0
  198. package/dist/db/migrations/v09.d.ts +3 -0
  199. package/dist/db/migrations/v09.js +13 -0
  200. package/dist/db/migrations/v10.d.ts +3 -0
  201. package/dist/db/migrations/v10.js +17 -0
  202. package/dist/db/migrations/v11.d.ts +3 -0
  203. package/dist/db/migrations/v11.js +15 -0
  204. package/dist/db/migrations/v12.d.ts +3 -0
  205. package/dist/db/migrations/v12.js +11 -0
  206. package/dist/db/migrations/v13.d.ts +3 -0
  207. package/dist/db/migrations/v13.js +15 -0
  208. package/dist/db/migrations/v14.d.ts +3 -0
  209. package/dist/db/migrations/v14.js +66 -0
  210. package/dist/db/migrations/v15.d.ts +3 -0
  211. package/dist/db/migrations/v15.js +42 -0
  212. package/dist/db/migrations/v16.d.ts +3 -0
  213. package/dist/db/migrations/v16.js +61 -0
  214. package/dist/db/migrations/v17.d.ts +3 -0
  215. package/dist/db/migrations/v17.js +46 -0
  216. package/dist/db/migrations/v18.d.ts +3 -0
  217. package/dist/db/migrations/v18.js +60 -0
  218. package/dist/db/migrations/v19.d.ts +3 -0
  219. package/dist/db/migrations/v19.js +28 -0
  220. package/dist/db/migrations/v20.d.ts +3 -0
  221. package/dist/db/migrations/v20.js +42 -0
  222. package/dist/db/migrations/v21.d.ts +3 -0
  223. package/dist/db/migrations/v21.js +16 -0
  224. package/dist/db/migrations/v22.d.ts +3 -0
  225. package/dist/db/migrations/v22.js +82 -0
  226. package/dist/db/migrations/v23.d.ts +3 -0
  227. package/dist/db/migrations/v23.js +48 -0
  228. package/dist/db/migrations/v24.d.ts +3 -0
  229. package/dist/db/migrations/v24.js +72 -0
  230. package/dist/db/migrations/v25.d.ts +3 -0
  231. package/dist/db/migrations/v25.js +46 -0
  232. package/dist/db/migrations/v26.d.ts +3 -0
  233. package/dist/db/migrations/v26.js +23 -0
  234. package/dist/db/migrations/v27.d.ts +3 -0
  235. package/dist/db/migrations/v27.js +57 -0
  236. package/dist/db/migrations/v28.d.ts +3 -0
  237. package/dist/db/migrations/v28.js +38 -0
  238. package/dist/db/migrations/v29.d.ts +3 -0
  239. package/dist/db/migrations/v29.js +78 -0
  240. package/dist/db/migrations/v30.d.ts +3 -0
  241. package/dist/db/migrations/v30.js +92 -0
  242. package/dist/db/migrations/v31.d.ts +3 -0
  243. package/dist/db/migrations/v31.js +74 -0
  244. package/dist/db/migrations/v32.d.ts +3 -0
  245. package/dist/db/migrations/v32.js +102 -0
  246. package/dist/db/migrations/v33.d.ts +3 -0
  247. package/dist/db/migrations/v33.js +104 -0
  248. package/dist/db/migrations/v34.d.ts +3 -0
  249. package/dist/db/migrations/v34.js +93 -0
  250. package/dist/db/migrations/v35.d.ts +3 -0
  251. package/dist/db/migrations/v35.js +98 -0
  252. package/dist/db/migrations/v36.d.ts +3 -0
  253. package/dist/db/migrations/v36.js +98 -0
  254. package/dist/db/migrations/v37.d.ts +3 -0
  255. package/dist/db/migrations/v37.js +219 -0
  256. package/dist/db/migrations/v38.d.ts +3 -0
  257. package/dist/db/migrations/v38.js +277 -0
  258. package/dist/db/migrations/v39.d.ts +3 -0
  259. package/dist/db/migrations/v39.js +59 -0
  260. package/dist/db/migrations/v40.d.ts +3 -0
  261. package/dist/db/migrations/v40.js +74 -0
  262. package/dist/db/migrations/v41.d.ts +3 -0
  263. package/dist/db/migrations/v41.js +43 -0
  264. package/dist/db/migrations/v42.d.ts +3 -0
  265. package/dist/db/migrations/v42.js +41 -0
  266. package/dist/db/migrations/v43.d.ts +3 -0
  267. package/dist/db/migrations/v43.js +67 -0
  268. package/dist/db/migrations/v44.d.ts +3 -0
  269. package/dist/db/migrations/v44.js +28 -0
  270. package/dist/db/migrations/v45.d.ts +3 -0
  271. package/dist/db/migrations/v45.js +30 -0
  272. package/dist/db/migrations/v46.d.ts +3 -0
  273. package/dist/db/migrations/v46.js +25 -0
  274. package/dist/db/migrations/v47.d.ts +3 -0
  275. package/dist/db/migrations/v47.js +17 -0
  276. package/dist/db/migrations/v48.d.ts +3 -0
  277. package/dist/db/migrations/v48.js +10 -0
  278. package/dist/db/migrations/v49.d.ts +3 -0
  279. package/dist/db/migrations/v49.js +31 -0
  280. package/dist/db/migrations/v50.d.ts +3 -0
  281. package/dist/db/migrations/v50.js +67 -0
  282. package/dist/db/migrations/v51.d.ts +3 -0
  283. package/dist/db/migrations/v51.js +14 -0
  284. package/dist/db/migrations/v52.d.ts +3 -0
  285. package/dist/db/migrations/v52.js +7 -0
  286. package/dist/db/open.d.ts +23 -0
  287. package/dist/db/open.js +146 -0
  288. package/dist/db/sqlite.d.ts +21 -0
  289. package/dist/db/sqlite.js +8 -0
  290. package/dist/db/tables.d.ts +7 -0
  291. package/dist/db/tables.js +38 -0
  292. package/dist/db.d.ts +6 -46
  293. package/dist/db.js +5 -3049
  294. package/dist/decisions.d.ts +4 -1
  295. package/dist/decisions.js +9 -7
  296. package/dist/dedupe.js +3 -2
  297. package/dist/delivery-recorder.js +4 -1
  298. package/dist/doctor.js +3 -3
  299. package/dist/embedding-provider.d.ts +1 -1
  300. package/dist/embedding-provider.js +4 -3
  301. package/dist/embeddings.d.ts +9 -52
  302. package/dist/embeddings.js +43 -297
  303. package/dist/env.d.ts +75 -0
  304. package/dist/env.js +119 -0
  305. package/dist/eval-suite.js +1 -1
  306. package/dist/eval.js +2 -2
  307. package/dist/extract.js +1 -1
  308. package/dist/gated-write.js +3 -1
  309. package/dist/goals.d.ts +3 -1
  310. package/dist/goals.js +18 -0
  311. package/dist/graph/read.d.ts +73 -0
  312. package/dist/graph/read.js +325 -0
  313. package/dist/graph/rows.d.ts +45 -0
  314. package/dist/graph/rows.js +51 -0
  315. package/dist/graph/types.d.ts +83 -0
  316. package/dist/graph/types.js +11 -0
  317. package/dist/graph/write.d.ts +93 -0
  318. package/dist/{graph.js → graph/write.js} +6 -384
  319. package/dist/graph-extract.js +2 -1
  320. package/dist/graph-recall.d.ts +1 -1
  321. package/dist/graph-recall.js +2 -2
  322. package/dist/graph-stream.js +1 -1
  323. package/dist/graph-view.d.ts +1 -1
  324. package/dist/graph-view.js +1 -1
  325. package/dist/half-life-migration.d.ts +1 -1
  326. package/dist/half-life-migration.js +2 -1
  327. package/dist/hooks/codex-session.d.ts +8 -0
  328. package/dist/hooks/codex-session.js +76 -0
  329. package/dist/hooks/codex-wrapper.d.ts +55 -0
  330. package/dist/hooks/codex-wrapper.js +288 -0
  331. package/dist/hooks/json-hooks.d.ts +63 -0
  332. package/dist/hooks/json-hooks.js +356 -0
  333. package/dist/hooks/opencode.d.ts +50 -0
  334. package/dist/hooks/opencode.js +202 -0
  335. package/dist/hooks/shared.d.ts +54 -0
  336. package/dist/hooks/shared.js +77 -0
  337. package/dist/http-retry.d.ts +2 -0
  338. package/dist/http-retry.js +4 -3
  339. package/dist/http-util.d.ts +3 -0
  340. package/dist/http-util.js +10 -0
  341. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  342. package/dist/importers/core.js +141 -0
  343. package/dist/importers/markdown-parse.d.ts +41 -0
  344. package/dist/importers/markdown-parse.js +132 -0
  345. package/dist/importers/markdown.d.ts +3 -0
  346. package/dist/importers/markdown.js +92 -0
  347. package/dist/importers/sources.d.ts +7 -0
  348. package/dist/importers/sources.js +229 -0
  349. package/dist/importers/vault.d.ts +11 -0
  350. package/dist/importers/vault.js +352 -0
  351. package/dist/incidents.d.ts +3 -0
  352. package/dist/incidents.js +7 -5
  353. package/dist/index.d.ts +25 -6
  354. package/dist/index.js +23 -6
  355. package/dist/invalidation.js +2 -1
  356. package/dist/judgment.js +2 -1
  357. package/dist/keyset.d.ts +13 -0
  358. package/dist/keyset.js +8 -0
  359. package/dist/local-embedding.d.ts +13 -0
  360. package/dist/local-embedding.js +165 -0
  361. package/dist/log.d.ts +7 -0
  362. package/dist/log.js +19 -1
  363. package/dist/mcp/admin-tools.d.ts +8 -0
  364. package/dist/mcp/admin-tools.js +116 -0
  365. package/dist/mcp/format.d.ts +27 -0
  366. package/dist/mcp/format.js +135 -0
  367. package/dist/mcp/memory-tools.d.ts +5 -0
  368. package/dist/mcp/memory-tools.js +83 -0
  369. package/dist/mcp/protocol.d.ts +83 -0
  370. package/dist/mcp/protocol.js +55 -0
  371. package/dist/mcp/recall-tools.d.ts +6 -0
  372. package/dist/mcp/recall-tools.js +320 -0
  373. package/dist/mcp/request.d.ts +10 -0
  374. package/dist/mcp/request.js +163 -0
  375. package/dist/mcp/server.d.ts +4 -75
  376. package/dist/mcp/server.js +7 -1190
  377. package/dist/mcp/session-state.d.ts +11 -0
  378. package/dist/mcp/session-state.js +28 -0
  379. package/dist/mcp/stdio.d.ts +8 -0
  380. package/dist/mcp/stdio.js +79 -0
  381. package/dist/mcp/tools.d.ts +11 -0
  382. package/dist/mcp/tools.js +247 -0
  383. package/dist/memory.d.ts +3 -0
  384. package/dist/memory.js +27 -1
  385. package/dist/multihop.d.ts +1 -1
  386. package/dist/multihop.js +2 -1
  387. package/dist/owner-validation.js +2 -1
  388. package/dist/physics-state.js +10 -7
  389. package/dist/policies.d.ts +3 -0
  390. package/dist/policies.js +8 -6
  391. package/dist/postinstall.js +3 -2
  392. package/dist/predictions/planning-fallacy.d.ts +100 -0
  393. package/dist/predictions/planning-fallacy.js +190 -0
  394. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  395. package/dist/predictions/store.js +434 -0
  396. package/dist/processes.d.ts +3 -0
  397. package/dist/processes.js +7 -5
  398. package/dist/project-briefs.d.ts +3 -0
  399. package/dist/project-briefs.js +7 -5
  400. package/dist/project-identity.js +3 -2
  401. package/dist/project-merge.js +3 -1
  402. package/dist/quarantine.d.ts +2 -1
  403. package/dist/quarantine.js +8 -5
  404. package/dist/raw-archive.js +1 -1
  405. package/dist/recall-history.js +3 -2
  406. package/dist/recall-pipeline.d.ts +2 -2
  407. package/dist/recall-pipeline.js +16 -8
  408. package/dist/recall-scope.js +1 -1
  409. package/dist/recall-trace.d.ts +1 -1
  410. package/dist/refine-llm.js +2 -1
  411. package/dist/reject-flow.js +6 -1
  412. package/dist/rerankers/clef.js +6 -5
  413. package/dist/rerankers/jev.d.ts +1 -1
  414. package/dist/rerankers/jev.js +4 -4
  415. package/dist/rerankers/llm.d.ts +4 -2
  416. package/dist/rerankers/llm.js +58 -38
  417. package/dist/rerankers/types.d.ts +1 -1
  418. package/dist/salience.js +1 -1
  419. package/dist/scheduler.d.ts +1 -0
  420. package/dist/scheduler.js +26 -4
  421. package/dist/scope.js +4 -3
  422. package/dist/search/as-of.d.ts +10 -0
  423. package/dist/search/as-of.js +22 -0
  424. package/dist/search/bm25-search.d.ts +14 -0
  425. package/dist/search/bm25-search.js +43 -0
  426. package/dist/search/bm25.d.ts +15 -0
  427. package/dist/search/bm25.js +54 -0
  428. package/dist/search/boosts.d.ts +54 -0
  429. package/dist/search/boosts.js +94 -0
  430. package/dist/search/breakdown.d.ts +7 -0
  431. package/dist/search/breakdown.js +20 -0
  432. package/dist/search/explain.d.ts +25 -0
  433. package/dist/search/explain.js +31 -0
  434. package/dist/search/finalize.d.ts +8 -0
  435. package/dist/search/finalize.js +52 -0
  436. package/dist/search/fusion.d.ts +27 -0
  437. package/dist/search/fusion.js +42 -0
  438. package/dist/search/hybrid-score.d.ts +20 -0
  439. package/dist/search/hybrid-score.js +73 -0
  440. package/dist/search/hybrid.d.ts +46 -0
  441. package/dist/search/hybrid.js +64 -0
  442. package/dist/search/physics-search.d.ts +29 -0
  443. package/dist/search/physics-search.js +162 -0
  444. package/dist/search/rerank.d.ts +10 -0
  445. package/dist/search/rerank.js +72 -0
  446. package/dist/search/temporal.d.ts +15 -0
  447. package/dist/search/temporal.js +45 -0
  448. package/dist/search/types.d.ts +91 -0
  449. package/dist/search/types.js +2 -0
  450. package/dist/search/vector.d.ts +30 -0
  451. package/dist/search/vector.js +71 -0
  452. package/dist/secret-detect.d.ts +2 -0
  453. package/dist/secret-detect.js +2 -1
  454. package/dist/server/auth.d.ts +52 -0
  455. package/dist/server/auth.js +221 -0
  456. package/dist/server/client-ip.d.ts +25 -0
  457. package/dist/server/client-ip.js +92 -0
  458. package/dist/server/cursor.d.ts +23 -0
  459. package/dist/server/cursor.js +58 -0
  460. package/dist/server/lifecycle.d.ts +7 -0
  461. package/dist/server/lifecycle.js +29 -0
  462. package/dist/server/mcp-http.d.ts +5 -0
  463. package/dist/server/mcp-http.js +199 -0
  464. package/dist/server/request.d.ts +33 -0
  465. package/dist/server/request.js +103 -0
  466. package/dist/server/routes/admin.d.ts +9 -0
  467. package/dist/server/routes/admin.js +158 -0
  468. package/dist/server/routes/customer-notes.d.ts +7 -0
  469. package/dist/server/routes/customer-notes.js +112 -0
  470. package/dist/server/routes/decisions.d.ts +7 -0
  471. package/dist/server/routes/decisions.js +133 -0
  472. package/dist/server/routes/incidents.d.ts +7 -0
  473. package/dist/server/routes/incidents.js +126 -0
  474. package/dist/server/routes/memories.d.ts +10 -0
  475. package/dist/server/routes/memories.js +179 -0
  476. package/dist/server/routes/policies.d.ts +8 -0
  477. package/dist/server/routes/policies.js +151 -0
  478. package/dist/server/routes/predictions.d.ts +7 -0
  479. package/dist/server/routes/predictions.js +164 -0
  480. package/dist/server/routes/processes.d.ts +7 -0
  481. package/dist/server/routes/processes.js +161 -0
  482. package/dist/server/routes/project-briefs.d.ts +8 -0
  483. package/dist/server/routes/project-briefs.js +136 -0
  484. package/dist/server/routes/recall.d.ts +8 -0
  485. package/dist/server/routes/recall.js +340 -0
  486. package/dist/server/routes/skills.d.ts +8 -0
  487. package/dist/server/routes/skills.js +150 -0
  488. package/dist/server/types.d.ts +56 -0
  489. package/dist/server/types.js +2 -0
  490. package/dist/server/validation.d.ts +14 -0
  491. package/dist/server/validation.js +91 -0
  492. package/dist/server.d.ts +7 -61
  493. package/dist/server.js +69 -2362
  494. package/dist/session-digest.d.ts +1 -1
  495. package/dist/session-digest.js +9 -2
  496. package/dist/shared.d.ts +3 -1
  497. package/dist/shared.js +26 -22
  498. package/dist/skills.d.ts +3 -0
  499. package/dist/skills.js +7 -5
  500. package/dist/stdin.js +2 -2
  501. package/dist/store/audit-event.d.ts +19 -0
  502. package/dist/store/audit-event.js +33 -0
  503. package/dist/store/candidates.d.ts +42 -0
  504. package/dist/store/candidates.js +152 -0
  505. package/dist/store/conflicts.d.ts +44 -0
  506. package/dist/store/conflicts.js +444 -0
  507. package/dist/store/delete-and-batch.d.ts +63 -0
  508. package/dist/store/delete-and-batch.js +310 -0
  509. package/dist/store/entry-reads.d.ts +92 -0
  510. package/dist/store/entry-reads.js +255 -0
  511. package/dist/store/entry-row.d.ts +67 -0
  512. package/dist/store/entry-row.js +208 -0
  513. package/dist/store/entry-writes.d.ts +46 -0
  514. package/dist/store/entry-writes.js +148 -0
  515. package/dist/store/handoffs.d.ts +26 -0
  516. package/dist/store/handoffs.js +184 -0
  517. package/dist/store/index-and-stats.d.ts +52 -0
  518. package/dist/store/index-and-stats.js +214 -0
  519. package/dist/store/markdown.d.ts +10 -0
  520. package/dist/store/markdown.js +108 -0
  521. package/dist/store/mirrors.d.ts +49 -0
  522. package/dist/store/mirrors.js +312 -0
  523. package/dist/store/open.d.ts +15 -0
  524. package/dist/store/open.js +223 -0
  525. package/dist/store/rows.d.ts +178 -0
  526. package/dist/store/rows.js +158 -0
  527. package/dist/store/search-rows.d.ts +86 -0
  528. package/dist/store/search-rows.js +254 -0
  529. package/dist/store/sessions.d.ts +83 -0
  530. package/dist/store/sessions.js +272 -0
  531. package/dist/store/summaries.d.ts +94 -0
  532. package/dist/store/summaries.js +377 -0
  533. package/dist/store/tenant-lookup.d.ts +12 -0
  534. package/dist/store/tenant-lookup.js +16 -0
  535. package/dist/store-cards.js +2 -1
  536. package/dist/summary-dirty.d.ts +4 -0
  537. package/dist/summary-dirty.js +32 -0
  538. package/dist/support-bundle.js +4 -3
  539. package/dist/tenant.js +2 -2
  540. package/dist/tokenize.d.ts +2 -0
  541. package/dist/tokenize.js +16 -0
  542. package/dist/transcript-tail.d.ts +7 -0
  543. package/dist/transcript-tail.js +48 -0
  544. package/dist/vector-store.d.ts +27 -0
  545. package/dist/vector-store.js +210 -0
  546. package/dist/version.d.ts +2 -2
  547. package/dist/version.js +2 -2
  548. package/dist/working-memory.js +1 -1
  549. package/dist/yaml.js +36 -11
  550. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  551. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  552. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  553. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  554. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  555. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  556. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  557. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  558. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  559. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  560. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  562. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  563. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  564. package/dist-ui/index.html +3 -25
  565. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  566. package/extensions/openclaw-plugin/package.json +1 -1
  567. package/openclaw.plugin.json +1 -1
  568. package/package.json +1 -1
  569. package/dist/capture.d.ts +0 -155
  570. package/dist/capture.js +0 -1295
  571. package/dist/consolidate.d.ts +0 -58
  572. package/dist/consolidate.js +0 -1124
  573. package/dist/graph.d.ts +0 -245
  574. package/dist/hooks.d.ts +0 -208
  575. package/dist/hooks.js +0 -1076
  576. package/dist/importers.js +0 -900
  577. package/dist/predictions.js +0 -620
  578. package/dist/search.d.ts +0 -320
  579. package/dist/search.js +0 -970
  580. package/dist/store.d.ts +0 -776
  581. package/dist/store.js +0 -3473
  582. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  583. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  584. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  585. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,145 @@
1
+ import { calculateStrength } from '../memory.js';
2
+ import { detectSecret } from '../secret-detect.js';
3
+ import { rescueSet, rankNonPinnedByTenant, validateWeights } from '../memory-value.js';
4
+ import { MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256 } from '../memory-value-weights.js';
5
+ export const DECAY_THRESHOLD = 0.05;
6
+ // A faded, unpinned, unrescued memory leaves active memory one of three
7
+ // ways. A raw receipt is append-only: trg_memories_raw_append_only aborts
8
+ // a DELETE, and with it this whole cycle's batch and every later sleep,
9
+ // so it stays where it is (stored strength refreshed) but sits out the
10
+ // rest of this cycle the way a deleted row would. Anything else goes
11
+ // dormant when config.dormant is on, and is deleted otherwise.
12
+ // Only called for rows `retirable` allows (never pinned, raw, kept for good or backing a first-class object).
13
+ function retireFaded(run, entry, strength) {
14
+ const { result } = run;
15
+ const why = `(strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})`;
16
+ // A faded secret is deleted, never kept dormant: keeping it would hold a
17
+ // credential on disk that the user reasonably expects forgetting removed.
18
+ if (run.config.dormant.enabled && !detectSecret(entry).flagged) {
19
+ result.dormant++;
20
+ result.details.push(` 💤 dormant ${entry.id} ${why}`);
21
+ run.pendingDormant.push({ entry: { ...entry, strength }, strength, reason: 'decay', dormantAt: run.now.toISOString() });
22
+ return;
23
+ }
24
+ result.removed++;
25
+ result.details.push(` 🗑 removed ${entry.id} ${why}`);
26
+ run.pendingDeletes.push(entry.id);
27
+ }
28
+ /** Keeps an entry with its live strength cached; only strength is a cached computation, confidence stays as stored. */
29
+ function keepSurvivor(run, entry, strength) {
30
+ const updated = { ...entry, strength };
31
+ run.survivors.push(updated);
32
+ if (!run.dryRun && strength !== entry.strength) {
33
+ run.pendingWrites.push(updated);
34
+ }
35
+ run.result.decayed++;
36
+ return updated;
37
+ }
38
+ // -------------------------------------------------------------------------
39
+ // 1. Decay pass
40
+ // -------------------------------------------------------------------------
41
+ // LC2-E3 (opt-in, default off; docs/plans/2026-08-10-lc2-e3-mv-wiring.md):
42
+ // flag OFF keeps the single-phase loop below byte-identical to pre-E3
43
+ // behavior (pre-registered gate G2). Flag ON restructures into two phases:
44
+ // phase 1 classifies every entry (condemned vs survivor) with ZERO
45
+ // commits; phase 2 runs rescueSet over the per-tenant candidate groups,
46
+ // then commits — rescued entries get the standard survivor bookkeeping
47
+ // refresh (stored strength + effective confidence; no half-life edits, no
48
+ // rank-derived writes) and are pushed to survivors so they fully
49
+ // participate in this cycle's merge/physics/conflict passes; non-rescued
50
+ // condemned entries follow the existing pendingDeletes/result.removed/
51
+ // details path.
52
+ export function decayPass(run) {
53
+ if (run.config.memoryValue.enabled)
54
+ return decayWithMemoryValue(run);
55
+ for (const entry of run.all) {
56
+ const strength = calculateStrength(entry, run.now, run.decayOpts);
57
+ if (run.retirable(entry) && strength < DECAY_THRESHOLD) {
58
+ retireFaded(run, entry, strength);
59
+ }
60
+ else {
61
+ keepSurvivor(run, entry, strength);
62
+ }
63
+ }
64
+ return { rescuedIds: new Set(), rescuedEntries: [], rankById: new Map() };
65
+ }
66
+ // A non-finite feature (e.g. a malformed `created`) scores -Infinity and can never be
67
+ // rescued, so name those entries in one warning rather than leave it a silent NaN detail.
68
+ function reportNonFiniteScores(result, rankById) {
69
+ const nonFiniteIds = [...rankById.entries()]
70
+ .filter(([, info]) => !Number.isFinite(info.score))
71
+ .map(([id]) => id);
72
+ if (nonFiniteIds.length > 0) {
73
+ result.details.push(` ⚠️ memory-value: skipped ${nonFiniteIds.length} entr${nonFiniteIds.length === 1 ? 'y' : 'ies'} ` +
74
+ `with non-finite computed features (never rescued): ${nonFiniteIds.join(', ')}`);
75
+ }
76
+ }
77
+ function decayWithMemoryValue(run) {
78
+ const { all, now, result } = run;
79
+ // Carried forward to logRun, where the mv_rescue audit rows are actually
80
+ // written (code-review fix: writing them here, before batchWriteAndDelete,
81
+ // would assert rescues for a cycle whose effects might never land if a
82
+ // later phase throws).
83
+ const rescuedEntries = [];
84
+ let rescuedIds = new Set();
85
+ let rankById = new Map();
86
+ // --- Phase 1: classify (zero commits) ---
87
+ const condemned = [];
88
+ const strengthById = new Map();
89
+ for (const entry of all) {
90
+ const strength = calculateStrength(entry, now, run.decayOpts);
91
+ strengthById.set(entry.id, strength);
92
+ if (run.retirable(entry) && strength < DECAY_THRESHOLD) {
93
+ condemned.push(entry);
94
+ }
95
+ }
96
+ // --- Phase 2a: rescue decision (pure compute) ---
97
+ // Runs under --dry-run too (only the pendingDeletes flush and the audit write in
98
+ // logRun stay !dryRun-gated), so the preview matches what a
99
+ // real run would decide.
100
+ const condemnedIds = new Set(condemned.map((e) => e.id));
101
+ // Fail-loud must not depend on condemnation traffic (round-2 code-review
102
+ // P2-2): validate the frozen weights constant unconditionally, even on a
103
+ // sleep with nothing condemned.
104
+ validateWeights();
105
+ if (condemnedIds.size > 0) {
106
+ // Compute the per-tenant ranking ONCE (round-2 code-review P2-2):
107
+ // rankById feeds both rescueSet's decision (via precomputedRanks,
108
+ // skipping its own internal rankNonPinnedByTenant call) and the
109
+ // detail/audit rank context below, so the whole-store ranking pass
110
+ // runs a single time per sleep instead of twice, and only when there
111
+ // is actually something condemned to rank against.
112
+ rankById = rankNonPinnedByTenant(all, now);
113
+ rescuedIds = rescueSet(all, condemnedIds, now, MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256, rankById);
114
+ reportNonFiniteScores(result, rankById);
115
+ }
116
+ // --- Phase 2b: commit, one pass over `all` in ITS ORIGINAL ORDER ---
117
+ // (review-round F4: rescued entries used to be appended at the tail of
118
+ // survivors, systematically starving them in downstream order-sensitive
119
+ // passes like extraction's slice(0,20) — a single pass over `all`
120
+ // preserves flag-off's ordering semantics exactly.)
121
+ for (const entry of all) {
122
+ const strength = strengthById.get(entry.id);
123
+ if (run.retirable(entry) && strength < DECAY_THRESHOLD) {
124
+ if (rescuedIds.has(entry.id)) {
125
+ // Rescued (D1): standard survivor stored-strength refresh (P2-1).
126
+ // Confidence is left alone here: it is an epistemic tier, not a
127
+ // cached computation, so resolveConfidence derives it on read.
128
+ rescuedEntries.push(keepSurvivor(run, entry, strength));
129
+ const rank = rankById.get(entry.id);
130
+ const rankNote = rank
131
+ ? ` - rescued (rank ${rank.rank}/${rank.totalNonPinned} in tenant ${rank.tenantId}, top ${rank.keepN})`
132
+ : ' - rescued';
133
+ result.details.push(` 🛟 ${entry.id} (strength ${strength.toFixed(4)} < ${DECAY_THRESHOLD})${rankNote}`);
134
+ }
135
+ else {
136
+ retireFaded(run, entry, strength);
137
+ }
138
+ }
139
+ else {
140
+ keepSurvivor(run, entry, strength);
141
+ }
142
+ }
143
+ return { rescuedIds, rescuedEntries, rankById };
144
+ }
145
+ //# sourceMappingURL=decay.js.map
@@ -0,0 +1,3 @@
1
+ import { type SleepRun } from './run.js';
2
+ export declare function llmPasses(run: SleepRun, fetcher: typeof fetch | undefined): Promise<void>;
3
+ //# sourceMappingURL=llm-passes.d.ts.map
@@ -0,0 +1,141 @@
1
+ import { envAnthropicApiKey, envDagRebuildCap } from '../env.js';
2
+ import { Layer } from '../memory.js';
3
+ import { log } from '../log.js';
4
+ import { keptAsWritten } from './run.js';
5
+ /** The key, model options and once-per-line error reporter every LLM phase shares. */
6
+ function sleepLlm(run, fetcher) {
7
+ const { config, result } = run;
8
+ // extraction.enabled=false is the opt-out for every LLM phase below, key or no key.
9
+ const apiKey = config.extraction.enabled !== false ? (envAnthropicApiKey() ?? '') : '';
10
+ const llmErrorsSeen = new Set();
11
+ const llmError = (phase) => (msg) => {
12
+ const line = ` ⚠️ ${phase}: ${msg}`;
13
+ if (llmErrorsSeen.has(line))
14
+ return;
15
+ llmErrorsSeen.add(line);
16
+ result.details.push(line);
17
+ log.warn(`consolidate ${phase}: ${msg}`);
18
+ };
19
+ const llmOpts = { apiKey, model: config.extraction.model, fetcher };
20
+ return { apiKey, llmError, llmOpts };
21
+ }
22
+ export async function llmPasses(run, fetcher) {
23
+ // -------------------------------------------------------------------------
24
+ // 1.6. Batch extraction — extract facts from episodic memories missing them
25
+ // -------------------------------------------------------------------------
26
+ const extractedFromIds = new Set(run.survivors.filter((e) => e.extracted_from).map((e) => e.extracted_from));
27
+ const extractionCandidates = run.survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !extractedFromIds.has(e.id) && !keptAsWritten(e));
28
+ run.result.extractionCandidates = extractionCandidates.length;
29
+ const llm = sleepLlm(run, fetcher);
30
+ if (llm.apiKey && extractionCandidates.length > 0 && !run.dryRun) {
31
+ const { extractFacts, storeExtractedFacts } = await import('../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
+ storeExtractedFacts(run.hippoRoot, candidate, facts);
39
+ extractedCount += facts.length;
40
+ }
41
+ }
42
+ catch (err) {
43
+ llm.llmError('extraction')(String(err));
44
+ }
45
+ }
46
+ run.result.extracted = extractedCount;
47
+ }
48
+ await dagBuildPass(run, llm);
49
+ if (llm.apiKey && !run.dryRun) {
50
+ await dagRebuildPass(run, llm);
51
+ await entityProfilePass(run, llm);
52
+ }
53
+ }
54
+ // -------------------------------------------------------------------------
55
+ // 1.7. DAG summarization — cluster extracted facts and generate summaries
56
+ // -------------------------------------------------------------------------
57
+ async function dagBuildPass(run, { apiKey, llmError, llmOpts }) {
58
+ const extractedFacts = run.survivors.filter((e) => e.tags.includes('extracted') && e.dag_level === 1 && !e.superseded_by);
59
+ if (!(apiKey && extractedFacts.length >= 3 && !run.dryRun))
60
+ return;
61
+ try {
62
+ const { buildDag } = await import('../dag.js');
63
+ const dagResult = await buildDag(run.hippoRoot, extractedFacts, { ...llmOpts, onError: llmError('dag') });
64
+ run.result.dagCandidateClusters = dagResult.candidateClusters;
65
+ run.result.dagSummariesCreated = dagResult.summariesCreated;
66
+ if (dagResult.summariesCreated > 0) {
67
+ run.result.details.push(` 🌳 DAG: ${dagResult.summariesCreated} summaries created, ${dagResult.factsLinked} facts linked`);
68
+ }
69
+ }
70
+ catch (err) {
71
+ llmError('dag')(String(err));
72
+ }
73
+ }
74
+ // -------------------------------------------------------------------------
75
+ // 1.8. DAG summary rebuild — drain dirty queue from E2's child-write hooks
76
+ // -------------------------------------------------------------------------
77
+ // Consumer of E2's summary_dirty flag. Walks dirty L2 summaries, regenerates
78
+ // each via generateDagSummary, atomically refreshes content + 6 metadata
79
+ // columns + clears summary_dirty (with FTS sync). Same apiKey/dryRun gate
80
+ // as buildDag above. Cap HIPPO_DAG_REBUILD_CAP (default 20, hard ceiling
81
+ // 1000) prevents runaway LLM cost.
82
+ async function dagRebuildPass(run, { llmError, llmOpts }) {
83
+ const { result } = run;
84
+ try {
85
+ const { rebuildDirtySummaries } = await import('../dag.js');
86
+ const rawCap = envDagRebuildCap();
87
+ // R1 MED must-fix: hard ceiling so misconfigured env can't burn
88
+ // unbounded LLM cost.
89
+ const cap = rawCap !== undefined ? Math.min(rawCap, 1000) : 20;
90
+ const rebuildResult = await rebuildDirtySummaries(run.hippoRoot, { ...llmOpts, onError: llmError('dag rebuild'), cap });
91
+ result.summariesRebuilt = rebuildResult.rebuilt;
92
+ result.summariesRebuildFailed = rebuildResult.failed;
93
+ result.summariesZeroChildSkipped = rebuildResult.zeroChildSkipped;
94
+ result.summariesRebuildRefused = rebuildResult.refused;
95
+ result.summariesRebuildCapped = rebuildResult.capped;
96
+ if (rebuildResult.rebuilt > 0 || rebuildResult.zeroChildSkipped > 0 || rebuildResult.failed > 0 || rebuildResult.refused > 0) {
97
+ const parts = [];
98
+ if (rebuildResult.rebuilt > 0)
99
+ parts.push(`${rebuildResult.rebuilt} rebuilt`);
100
+ if (rebuildResult.refused > 0)
101
+ parts.push(`${rebuildResult.refused} refused`);
102
+ if (rebuildResult.zeroChildSkipped > 0)
103
+ parts.push(`${rebuildResult.zeroChildSkipped} zero-child-skipped`);
104
+ if (rebuildResult.failed > 0)
105
+ parts.push(`${rebuildResult.failed} failed`);
106
+ if (rebuildResult.capped)
107
+ parts.push(`CAPPED@${cap}`);
108
+ result.details.push(` 🌳 DAG rebuild: ${parts.join(', ')}`);
109
+ }
110
+ }
111
+ catch (err) {
112
+ llmError('dag rebuild')(String(err));
113
+ }
114
+ }
115
+ // -------------------------------------------------------------------------
116
+ // 1.9. DAG entity profiles — cluster L2 topic summaries into L3 profiles
117
+ // -------------------------------------------------------------------------
118
+ // E5 phase: aggregate per-entity L2 summaries (e.g. all the speaker:Alice
119
+ // topic summaries) into a single L3 entity profile. Runs even when phase
120
+ // 1.7 buildDag was skipped (re-clusters existing L2s every sleep).
121
+ //
122
+ // Uses loadAllL2Summaries (not `survivors`) because phase 1.7 wrote new
123
+ // L2s directly via writeEntry without pushing back into survivors.
124
+ async function entityProfilePass(run, { llmError, llmOpts }) {
125
+ try {
126
+ const { buildEntityProfiles } = await import('../dag.js');
127
+ const { loadAllL2Summaries } = await import('../store/summaries.js');
128
+ const l2Summaries = loadAllL2Summaries(run.hippoRoot);
129
+ if (l2Summaries.length >= 2) {
130
+ const profileResult = await buildEntityProfiles(run.hippoRoot, l2Summaries, { ...llmOpts, onError: llmError('dag profiles') });
131
+ run.result.entityProfilesCreated = profileResult.profilesCreated;
132
+ if (profileResult.profilesCreated > 0) {
133
+ run.result.details.push(` 🌲 DAG L3: ${profileResult.profilesCreated} entity profiles, ${profileResult.l2sLinked} L2s linked`);
134
+ }
135
+ }
136
+ }
137
+ catch (err) {
138
+ llmError('dag profiles')(String(err));
139
+ }
140
+ }
141
+ //# sourceMappingURL=llm-passes.js.map
@@ -0,0 +1,7 @@
1
+ import { type SleepRun } from './run.js';
2
+ export declare function retireHeldTexts(run: SleepRun): void;
3
+ /** Returns how many clusters were skipped because their merged text matches a rejected value. */
4
+ export declare function mergePass(run: SleepRun): number;
5
+ /** Maps i to each j > i, ascending, whose text overlap with i reaches the merge threshold; every text needs at least one token. */
6
+ export declare function mergePartners(contents: readonly string[]): (i: number) => number[];
7
+ //# sourceMappingURL=merge.d.ts.map
@@ -0,0 +1,251 @@
1
+ import { Layer, calculateStrength, createMemory } from '../memory.js';
2
+ import { tokenize } from '../tokenize.js';
3
+ import { jaccardMinShared, overlapPartners } from '../overlap-index.js';
4
+ import { compareEntryIdentity } from '../compare.js';
5
+ import { duplicateKey, mergedText } from '../same-text.js';
6
+ import { successorAfterRetirement } from '../merged-row.js';
7
+ import { rejectionDigest, findRejectedValue } from '../rejection.js';
8
+ import { appendAuditEvent, reportAuditWriteFailure } from '../audit.js';
9
+ import { derivationScope, derivationPartitionKey } from '../recall-scope.js';
10
+ import { jaccardSets } from './conflicts.js';
11
+ import { keptAsWritten } from './run.js';
12
+ const MERGE_OVERLAP_THRESHOLD = 0.35; // Jaccard similarity for "related"
13
+ const MERGE_MIN_CLUSTER = 2; // minimum cluster size to merge
14
+ const MERGE_MAX_SOURCES = 5; // with MERGE_MAX_CHARS, keeps a merged row near 500 tokens, a third of the 1,500-token context budget
15
+ const MERGE_MAX_CHARS = 2000; // total source text; sources past either cap stay unmerged and keep their half-life
16
+ // Half-life scale for merged source episodics. Demotion must go through
17
+ // half_life_days: calculateStrength() recomputes live strength from
18
+ // last_retrieved/half_life and never reads the stored strength field, so a
19
+ // stored-strength write is inert for ranking and gets overwritten by the
20
+ // next sleep's decay pass anyway.
21
+ const MERGE_SOURCE_HALF_LIFE_FACTOR = 0.3;
22
+ export function retireHeldTexts(run) {
23
+ const { survivors } = run;
24
+ const byId = new Map(run.all.map((e) => [e.id, e]));
25
+ const rejectedIn = (tenantId) => (text) => {
26
+ const db = run.getConsolidateDb();
27
+ return db !== null && findRejectedValue(db, tenantId, rejectionDigest(text)) !== null;
28
+ };
29
+ for (let i = survivors.length - 1; i >= 0; i--) {
30
+ const row = survivors[i];
31
+ const successor = run.retirable(row) ? successorAfterRetirement(row, byId, rejectedIn(row.tenantId)) : undefined;
32
+ if (successor === undefined)
33
+ continue;
34
+ run.result.details.push(` ✂️ ${row.id} held a retired text${successor ? `, ${successor.id} holds the rest` : ''}`);
35
+ if (run.dryRun)
36
+ continue;
37
+ run.pendingDeletes.push(row.id);
38
+ if (successor) {
39
+ run.pendingWrites.push(successor);
40
+ survivors[i] = successor;
41
+ }
42
+ else {
43
+ survivors.splice(i, 1);
44
+ }
45
+ }
46
+ }
47
+ // -------------------------------------------------------------------------
48
+ // 3. Merge pass - episodic entries only
49
+ // -------------------------------------------------------------------------
50
+ /** Returns how many clusters were skipped because their merged text matches a rejected value. */
51
+ export function mergePass(run) {
52
+ const alreadyMergedIds = new Set(run.survivors.flatMap((e) => e.parents));
53
+ const mergeCandidates = run.survivors.filter((e) => e.layer === Layer.Episodic && !e.superseded_by && !keptAsWritten(e) && !alreadyMergedIds.has(e.id)
54
+ && !e.pinned // a pin merged with a look-alike would read as one of two values
55
+ && tokenize(e.content).length > 0);
56
+ const used = new Set();
57
+ // T1 fix (2026-08-15 hardening pass): partition by tenantId BEFORE the
58
+ // overlap loop so a cluster can never span tenants. Previously textOverlap
59
+ // clustered across the whole host-wide `survivors` list with no tenant
60
+ // boundary, and mergeContents concatenated cross-tenant content into one
61
+ // row. Map preserves insertion order, so single-tenant stores (every row
62
+ // 'default') get exactly one partition and iterate in the same order as
63
+ // before this fix — byte-identical behavior there.
64
+ const mergeCandidatesByTenant = new Map();
65
+ for (const entry of mergeCandidates) {
66
+ const key = derivationPartitionKey(entry.tenantId, entry.scope, entry.origin_project);
67
+ const bucket = mergeCandidatesByTenant.get(key);
68
+ if (bucket)
69
+ bucket.push(entry);
70
+ else
71
+ mergeCandidatesByTenant.set(key, [entry]);
72
+ }
73
+ // AT1 consolidation-loop fix (docs/plans/2026-08-15-at1-rejected-value-tombstone.md):
74
+ // reuses the single consolidateDb handle opened lazily in consolidate()
75
+ // for the whole non-dry-run consolidate — see that
76
+ // declaration's comment. Only needed for real writes — a dry-run preview
77
+ // never reaches batchWriteAndDelete's guard bypass, so there is nothing
78
+ // here for it to protect against.
79
+ let mergesSkippedRejected = 0;
80
+ for (const [, tenantCandidates] of mergeCandidatesByTenant) {
81
+ const partition = {
82
+ tenantId: tenantCandidates[0].tenantId,
83
+ scope: derivationScope(tenantCandidates[0].scope),
84
+ origin: tenantCandidates[0].origin_project,
85
+ };
86
+ const partnersOf = mergePartners(tenantCandidates.map((e) => e.content));
87
+ for (let i = 0; i < tenantCandidates.length; i++) {
88
+ if (used.has(tenantCandidates[i].id) || tenantCandidates[i].content.length > MERGE_MAX_CHARS)
89
+ continue;
90
+ const related = [tenantCandidates[i]];
91
+ for (const j of partnersOf(i)) {
92
+ if (!used.has(tenantCandidates[j].id))
93
+ related.push(tenantCandidates[j]);
94
+ }
95
+ const cluster = [];
96
+ let clusterChars = 0;
97
+ for (const e of related) {
98
+ if (cluster.length === MERGE_MAX_SOURCES || clusterChars + e.content.length > MERGE_MAX_CHARS)
99
+ continue;
100
+ cluster.push(e);
101
+ clusterChars += e.content.length;
102
+ }
103
+ if (cluster.length < MERGE_MIN_CLUSTER)
104
+ continue;
105
+ if (!mergeCluster(run, partition, cluster, related, used))
106
+ mergesSkippedRejected++;
107
+ }
108
+ }
109
+ return mergesSkippedRejected;
110
+ }
111
+ /** Merges one cluster into a semantic row; returns false when a tombstone refuses the merged text. */
112
+ function mergeCluster(run, partition, cluster, related, used) {
113
+ const { result, dryRun } = run;
114
+ // Create a semantic summary
115
+ const mergedContent = mergeContents(cluster);
116
+ const allTags = Array.from(new Set(cluster.flatMap((e) => e.tags))).sort();
117
+ const maxValence = pickStrongestValence(cluster);
118
+ // AT1 P2 fix: build the semantic entry FIRST — createMemory is cheap
119
+ // and pure — so the tombstone check below runs under the tenant the
120
+ // row will ACTUALLY land in.
121
+ // T1 fix: createMemory now receives tenantId: mergeTenant (the
122
+ // partition's tenant — every member of `cluster` shares it by
123
+ // construction), so the row lands in its source tenant instead of
124
+ // always 'default'.
125
+ let semantic = null;
126
+ if (!dryRun) {
127
+ semantic = {
128
+ ...createMemory(mergedContent, {
129
+ layer: Layer.Semantic,
130
+ tags: allTags,
131
+ emotional_valence: maxValence,
132
+ schema_fit: 0.7,
133
+ source: 'consolidation',
134
+ confidence: 'inferred',
135
+ tenantId: partition.tenantId,
136
+ scope: partition.scope,
137
+ baseHalfLifeDays: run.config.defaultHalfLifeDays,
138
+ }),
139
+ origin_project: partition.origin,
140
+ parents: cluster.map((e) => e.id),
141
+ };
142
+ }
143
+ if (semantic && mergeRejected(run, semantic, cluster, related, used))
144
+ return false;
145
+ // Mark cluster members as used
146
+ for (const e of cluster)
147
+ used.add(e.id);
148
+ result.merged += cluster.length;
149
+ result.details.push(` 🔀 merged ${cluster.length} episodic entries into semantic: "${mergedContent.slice(0, 60)}..."`);
150
+ if (!dryRun && semantic) {
151
+ run.pendingWrites.push(semantic);
152
+ result.semanticCreated++;
153
+ // Demote source episodics (they've been compressed into neocortex):
154
+ // scale half_life_days so they decay sooner while staying recoverable.
155
+ // Immediate ranking is deliberately unchanged: the 2026-06-10 DAG
156
+ // slice-1 eval measured that dropping children below a worse-retrieving
157
+ // summary regresses budget-bounded QA (docs/evals/). The stored
158
+ // strength is refreshed to the live value so inspect, replay sampling,
159
+ // and strength-sorted assembly see the truth instead of a fake 0.3.
160
+ // Mutate in place (not a copy): `cluster` holds the same object
161
+ // references as `survivors`, and the later detectConflicts(survivors)
162
+ // pass in this same run must see the post-demotion half-life, or it
163
+ // can persist conflicts for entries the just-written state excludes.
164
+ for (const e of cluster) {
165
+ e.half_life_days = Math.max(1, Math.floor(e.half_life_days * MERGE_SOURCE_HALF_LIFE_FACTOR));
166
+ e.strength = calculateStrength(e, run.now, run.decayOpts);
167
+ run.pendingWrites.push(e);
168
+ }
169
+ }
170
+ return true;
171
+ }
172
+ // mergeContents is DETERMINISTIC CONCATENATION (not an LLM paraphrase)
173
+ // — if a human rejected exactly this byte-identical rollup before, an
174
+ // unguarded sleep would regenerate it every cycle and
175
+ // batchWriteAndDelete's guard bypass (store.ts) would silently
176
+ // re-assert it forever. This producer-side check is what makes that
177
+ // bypass safe. A hit skips the WHOLE cluster: sources stay unmerged —
178
+ // not demoted, not deleted — so a later sleep gets another chance if
179
+ // the tombstone is lifted.
180
+ function mergeRejected(run, semantic, cluster, related, used) {
181
+ const consolidateDb = run.getConsolidateDb();
182
+ if (!consolidateDb)
183
+ return false;
184
+ const newDigest = rejectionDigest(semantic.content);
185
+ const oldDigest = rejectionDigest(legacyMergeContents(related)); // tombstones from older releases hold this format's digest
186
+ const newHit = findRejectedValue(consolidateDb, semantic.tenantId, newDigest);
187
+ const tombstone = newHit ?? findRejectedValue(consolidateDb, semantic.tenantId, oldDigest);
188
+ const mergeDigest = newHit ? newDigest : oldDigest;
189
+ if (!tombstone)
190
+ return false;
191
+ // Still mark used — these members are not re-tried against a
192
+ // DIFFERENT cluster within this same pass; next sleep re-clusters
193
+ // them fresh.
194
+ const rejected = newHit ? cluster : related; // the old format digested the uncapped list, so rows past the cap were rejected too
195
+ for (const e of rejected)
196
+ used.add(e.id);
197
+ try {
198
+ appendAuditEvent(consolidateDb, {
199
+ tenantId: semantic.tenantId,
200
+ actor: 'sleep',
201
+ op: 'reject_refusal',
202
+ metadata: {
203
+ digest: mergeDigest,
204
+ reason: tombstone.reason,
205
+ sourceIds: rejected.map((e) => e.id),
206
+ },
207
+ });
208
+ }
209
+ catch (error) {
210
+ reportAuditWriteFailure('reject_refusal', String(error));
211
+ }
212
+ return true;
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // Helpers
216
+ // ---------------------------------------------------------------------------
217
+ function mergeContents(entries) {
218
+ // Each distinct text goes in once and in full (the merge demotes every source), one bullet with its lines indented, so heldTextKeys can read it back.
219
+ // Newest first says which version is current; compareEntryIdentity settles ties, so the row and its rejection digest depend only on the sources.
220
+ const sorted = [...entries].sort((a, b) => (Date.parse(b.created) - Date.parse(a.created)) || compareEntryIdentity(a, b));
221
+ const texts = new Map();
222
+ for (const e of sorted) {
223
+ if (!texts.has(duplicateKey(e.content)))
224
+ texts.set(duplicateKey(e.content), e.content);
225
+ }
226
+ const header = entries.length === 2 ? '[Consolidated from 2 related memories, newest first]' : `[Consolidated pattern from ${entries.length} related memories, newest first]`;
227
+ return mergedText(header, [...texts.values()]);
228
+ }
229
+ function legacyMergeContents(entries) {
230
+ // The old format dropped text, so it is only ever digested to match rejections recorded against it, never written.
231
+ const sorted = [...entries].sort((a, b) => (b.content.length - a.content.length) || compareEntryIdentity(a, b));
232
+ if (entries.length === 2)
233
+ return `[Consolidated from ${entries.length} related memories]\n\n${sorted[0].content}`;
234
+ const bullets = sorted.map((e) => `- ${e.content.split('\n')[0].slice(0, 120)}`).join('\n');
235
+ return `[Consolidated pattern from ${entries.length} related memories]\n\n${bullets}`;
236
+ }
237
+ function pickStrongestValence(entries) {
238
+ const order = ['critical', 'negative', 'positive', 'neutral'];
239
+ for (const v of order) {
240
+ if (entries.some((e) => e.emotional_valence === v))
241
+ return v;
242
+ }
243
+ return 'neutral';
244
+ }
245
+ /** Maps i to each j > i, ascending, whose text overlap with i reaches the merge threshold; every text needs at least one token. */
246
+ export function mergePartners(contents) {
247
+ const sets = contents.map((text) => new Set(tokenize(text)));
248
+ const candidatesOf = overlapPartners(sets, jaccardMinShared(MERGE_OVERLAP_THRESHOLD));
249
+ return (i) => candidatesOf(i).filter((j) => jaccardSets(sets[i], sets[j]) >= MERGE_OVERLAP_THRESHOLD);
250
+ }
251
+ //# sourceMappingURL=merge.js.map
@@ -0,0 +1,3 @@
1
+ import type { SleepRun } from './run.js';
2
+ export declare function physicsPass(run: SleepRun): void;
3
+ //# sourceMappingURL=physics-pass.d.ts.map
@@ -0,0 +1,60 @@
1
+ import { openHippoDb, closeHippoDb } from '../db.js';
2
+ import { loadPhysicsState, savePhysicsState, refreshParticleProperties } from '../physics-state.js';
3
+ import { simulate } from '../physics.js';
4
+ // -------------------------------------------------------------------------
5
+ // 2. Physics simulation pass
6
+ // -------------------------------------------------------------------------
7
+ export function physicsPass(run) {
8
+ if (run.dryRun)
9
+ return;
10
+ const { config, result, survivors } = run;
11
+ try {
12
+ const physicsEnabled = config.physics.enabled === true
13
+ || (config.physics.enabled === 'auto');
14
+ if (physicsEnabled) {
15
+ const db = openHippoDb(run.hippoRoot);
16
+ try {
17
+ const physicsMap = loadPhysicsState(db);
18
+ const particles = Array.from(physicsMap.values());
19
+ if (particles.length > 0) {
20
+ // Build entry lookup for property refresh
21
+ const entryMap = new Map(survivors.map(e => [e.id, e]));
22
+ refreshParticleProperties(particles, entryMap, run.now);
23
+ // Build conflict pairs from survivors
24
+ const conflictPairs = new Map();
25
+ for (const entry of survivors) {
26
+ if (entry.conflicts_with.length > 0) {
27
+ const set = conflictPairs.get(entry.id) ?? new Set();
28
+ for (const cid of entry.conflicts_with)
29
+ set.add(cid);
30
+ conflictPairs.set(entry.id, set);
31
+ }
32
+ }
33
+ // Build half-life lookup
34
+ const halfLives = new Map();
35
+ for (const entry of survivors) {
36
+ halfLives.set(entry.id, entry.half_life_days);
37
+ }
38
+ const ctx = {
39
+ conflictPairs,
40
+ halfLives,
41
+ config: config.physics,
42
+ };
43
+ const stats = simulate(particles, ctx);
44
+ savePhysicsState(db, particles);
45
+ result.physicsSimulated = stats.particleCount;
46
+ result.details.push(` ⚛️ physics: ${stats.particleCount} particles, ` +
47
+ `avg vel ${stats.avgVelocityMagnitude.toFixed(4)}, ` +
48
+ `energy ${stats.energy.total.toFixed(4)}`);
49
+ }
50
+ }
51
+ finally {
52
+ closeHippoDb(db);
53
+ }
54
+ }
55
+ }
56
+ catch (error) {
57
+ result.details.push(` ⚠️ physics simulation skipped: ${error instanceof Error ? error.message : 'unknown error'}`);
58
+ }
59
+ }
60
+ //# sourceMappingURL=physics-pass.js.map