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,184 @@
1
+ import { closeHippoDb, openHippoDb } from '../db.js';
2
+ import { rowToSessionHandoff, isHandoffOutcome, } from '../handoff.js';
3
+ import { RECALL_DEFAULT_DENY_SCOPES } from '../recall-scope.js';
4
+ import { assertTenantId } from '../tenant.js';
5
+ import { openStore } from './open.js';
6
+ import { loadActiveTaskSnapshot } from './sessions.js';
7
+ // W1: the nine-column SELECT was cloned four times (plan rule 8); one
8
+ // definition so a sixth caller can't drift from the other five.
9
+ /** Column list shared by every session_handoffs SELECT; store-cards.ts reuses it for the card handoff lookup. */
10
+ export const HANDOFF_COLUMNS = 'id, session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, created_at, constraints_json, evidence_json, outcome, target_runtime, card_id';
11
+ /**
12
+ * Save a session handoff record. Returns the persisted handoff.
13
+ */
14
+ export function saveSessionHandoff(hippoRoot, tenantId, handoff) {
15
+ assertTenantId('saveSessionHandoff', tenantId);
16
+ const db = openStore(hippoRoot);
17
+ const now = new Date().toISOString();
18
+ // v1.2: scope is wired through. Read-side default-deny in api.recall +
19
+ // cmdRecall continuity excludes slack:private:* and 'unknown:legacy'.
20
+ try {
21
+ const result = db.prepare(`
22
+ INSERT INTO session_handoffs(session_id, repo_root, task_id, summary, next_action, artifacts_json, scope, tenant_id, created_at, constraints_json, evidence_json, outcome, target_runtime, card_id)
23
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
24
+ `).run(handoff.sessionId, handoff.repoRoot ?? null, handoff.taskId ?? null, handoff.summary, handoff.nextAction ?? null, JSON.stringify(handoff.artifacts ?? []), handoff.scope ?? null, tenantId, now, JSON.stringify(handoff.constraints ?? []), handoff.evidence ? JSON.stringify(handoff.evidence) : null, handoff.outcome ?? null, handoff.targetRuntime ?? null, handoff.cardId ?? null);
25
+ const id = Number(result.lastInsertRowid ?? 0);
26
+ // SAFETY: row's shape matches HANDOFF_COLUMNS.
27
+ const row = db.prepare(`
28
+ SELECT ${HANDOFF_COLUMNS}
29
+ FROM session_handoffs
30
+ WHERE id = ?
31
+ `).get(id);
32
+ if (!row) {
33
+ throw new Error('Failed to reload saved session handoff');
34
+ }
35
+ return rowToSessionHandoff(row);
36
+ }
37
+ finally {
38
+ closeHippoDb(db);
39
+ }
40
+ }
41
+ /** Load the most recent handoff, optionally filtered by session ID. */
42
+ export function loadLatestHandoff(hippoRoot, tenantId, sessionId, opts = {}) {
43
+ assertTenantId('loadLatestHandoff', tenantId);
44
+ const db = openStore(hippoRoot);
45
+ try {
46
+ const conditions = ['tenant_id = ?'];
47
+ const params = [tenantId];
48
+ if (sessionId) {
49
+ conditions.push('session_id = ?');
50
+ params.push(sessionId);
51
+ }
52
+ if (opts.excludeSessionId) {
53
+ conditions.push('session_id != ?');
54
+ params.push(opts.excludeSessionId);
55
+ }
56
+ if (opts.unfinishedOnly) {
57
+ // codex P2: restrict to each session's newest revision first — stampHandoffOutcome
58
+ // only stamps the newest row, so an older null-outcome revision must not resurrect.
59
+ conditions.push(`id IN (SELECT MAX(id) FROM session_handoffs WHERE tenant_id = ? GROUP BY session_id)`);
60
+ params.push(tenantId);
61
+ conditions.push(`(outcome IS NULL OR outcome IN ('partial','failure'))`);
62
+ }
63
+ if (opts.maxAgeMs != null) {
64
+ conditions.push('created_at >= ?');
65
+ params.push(new Date(Date.now() - opts.maxAgeMs).toISOString());
66
+ }
67
+ if (opts.scopeFilter === 'default-deny') {
68
+ // codex P2: admit scope before LIMIT 1, else a newer denied row hides an older eligible one.
69
+ const placeholders = RECALL_DEFAULT_DENY_SCOPES.map(() => '?').join(', ');
70
+ conditions.push(`(scope IS NULL OR (scope NOT IN (${placeholders}) AND scope NOT LIKE '%:private:%'))`);
71
+ params.push(...RECALL_DEFAULT_DENY_SCOPES);
72
+ }
73
+ // SAFETY: row's shape matches HANDOFF_COLUMNS.
74
+ const row = db.prepare(`
75
+ SELECT ${HANDOFF_COLUMNS}
76
+ FROM session_handoffs
77
+ WHERE ${conditions.join(' AND ')}
78
+ ORDER BY created_at DESC, id DESC
79
+ LIMIT 1
80
+ `).get(...params);
81
+ return row ? rowToSessionHandoff(row) : null;
82
+ }
83
+ finally {
84
+ closeHippoDb(db);
85
+ }
86
+ }
87
+ /**
88
+ * Load a specific handoff by its row ID.
89
+ */
90
+ export function loadHandoffById(hippoRoot, tenantId, id) {
91
+ assertTenantId('loadHandoffById', tenantId);
92
+ const db = openStore(hippoRoot);
93
+ try {
94
+ // SAFETY: row's shape matches HANDOFF_COLUMNS.
95
+ const row = db.prepare(`
96
+ SELECT ${HANDOFF_COLUMNS}
97
+ FROM session_handoffs
98
+ WHERE id = ? AND tenant_id = ?
99
+ `).get(id, tenantId);
100
+ return row ? rowToSessionHandoff(row) : null;
101
+ }
102
+ finally {
103
+ closeHippoDb(db);
104
+ }
105
+ }
106
+ /** Stamp the outcome on a session's newest handoff, only if it has none yet. Returns rows changed. */
107
+ export function stampHandoffOutcome(hippoRoot, tenantId, sessionId, outcome) {
108
+ assertTenantId('stampHandoffOutcome', tenantId);
109
+ const db = openStore(hippoRoot);
110
+ try {
111
+ const result = db.prepare(`
112
+ UPDATE session_handoffs SET outcome = ?
113
+ WHERE tenant_id = ? AND session_id = ? AND outcome IS NULL
114
+ AND id = (
115
+ SELECT id FROM session_handoffs
116
+ WHERE tenant_id = ? AND session_id = ?
117
+ ORDER BY created_at DESC, id DESC LIMIT 1
118
+ )
119
+ `).run(outcome, tenantId, sessionId, tenantId, sessionId);
120
+ return Number(result.changes ?? 0);
121
+ }
122
+ finally {
123
+ closeHippoDb(db);
124
+ }
125
+ }
126
+ /** Auto-write a handoff at session-end (DF1 T3) from the session's active snapshot, else from `derived`, its transcript state.
127
+ * @param evidence best-effort git state; outcome comes from the newest session_complete event.
128
+ * @returns null when neither source is the session's, a newer handoff covers the snapshot, or the session's latest handoff was not read off its transcript. */
129
+ export function writeSessionEndHandoff(hippoRoot, tenantId, sessionId, evidence, derived = null) {
130
+ assertTenantId('writeSessionEndHandoff', tenantId);
131
+ const active = loadActiveTaskSnapshot(hippoRoot, tenantId);
132
+ const existing = loadLatestHandoff(hippoRoot, tenantId, sessionId);
133
+ let snapshot;
134
+ let handoffEvidence = evidence;
135
+ if (active && active.session_id === sessionId) {
136
+ // Strict '>': a same-millisecond tie must not swallow the session's only write (test 6e).
137
+ if (existing && existing.updatedAt > active.updated_at)
138
+ return null;
139
+ snapshot = active;
140
+ }
141
+ else {
142
+ // Only an earlier transcript read gives way; `hippo handoff create` and unmarked older handoffs keep winning.
143
+ if (!derived || (existing && existing.evidence?.derivedFrom !== 'transcript'))
144
+ return null;
145
+ snapshot = { ...derived, scope: null };
146
+ handoffEvidence = { ...evidence, derivedFrom: 'transcript' };
147
+ }
148
+ const db = openHippoDb(hippoRoot);
149
+ let outcome = null;
150
+ try {
151
+ // SAFETY: row's shape matches the single `content` column below.
152
+ const completeEvent = db.prepare(`
153
+ SELECT content FROM session_events
154
+ WHERE tenant_id = ? AND session_id = ? AND event_type = 'session_complete'
155
+ ORDER BY created_at DESC, id DESC LIMIT 1
156
+ `).get(tenantId, sessionId);
157
+ if (isHandoffOutcome(completeEvent?.content))
158
+ outcome = completeEvent.content;
159
+ }
160
+ finally {
161
+ closeHippoDb(db);
162
+ }
163
+ // codex P2: same-task refresh carries forward envelope fields nobody cleared,
164
+ // rather than dropping them when the snapshot rewrite has no opinion on them.
165
+ // codex P1: a scope mismatch must not leak private metadata into an unscoped envelope.
166
+ const carryForward = existing != null && existing.taskId === snapshot.task
167
+ && (existing.scope ?? null) === (snapshot.scope ?? null);
168
+ return saveSessionHandoff(hippoRoot, tenantId, {
169
+ version: 1,
170
+ sessionId,
171
+ repoRoot: carryForward ? existing.repoRoot : undefined,
172
+ taskId: snapshot.task,
173
+ summary: snapshot.summary,
174
+ nextAction: snapshot.next_step,
175
+ artifacts: carryForward ? existing.artifacts : [],
176
+ scope: snapshot.scope,
177
+ evidence: handoffEvidence,
178
+ outcome,
179
+ constraints: carryForward ? existing.constraints : undefined,
180
+ targetRuntime: carryForward ? existing.targetRuntime : undefined,
181
+ cardId: carryForward ? existing.cardId : undefined,
182
+ });
183
+ }
184
+ //# sourceMappingURL=handoffs.js.map
@@ -0,0 +1,52 @@
1
+ import type { HippoIndex, LegacyStats } from './rows.js';
2
+ /** Load the derived index from SQLite. Read-only: index.json is only ever written by `rebuildIndex`. */
3
+ export declare function loadIndex(hippoRoot: string): HippoIndex;
4
+ /**
5
+ * Persist mutable index metadata. Entry rows themselves are derived from SQLite.
6
+ *
7
+ * LC1 F1(c) structural fix: `last_retrieval_ids` and `last_trace_id` must
8
+ * land atomically — callers (getContext, cmdRecall) fold a freshly-written
9
+ * trace id into `index.last_trace_id` before calling this, relying on BOTH
10
+ * meta keys committing together. Wrapped in BEGIN/COMMIT so a crash or a
11
+ * mid-write failure can never advance one key without the other. index.json
12
+ * is left untouched; only `rebuildIndex` writes it.
13
+ */
14
+ export declare function saveIndex(hippoRoot: string, index: HippoIndex): void;
15
+ /**
16
+ * Rebuild mirrors from SQLite, importing any legacy markdown files not already present.
17
+ */
18
+ export declare function rebuildIndex(hippoRoot: string): HippoIndex;
19
+ export declare function updateStats(hippoRoot: string, delta: {
20
+ remembered?: number;
21
+ recalled?: number;
22
+ forgotten?: number;
23
+ }): void;
24
+ export declare function updateStatsUnlessBusy(hippoRoot: string, delta: Parameters<typeof updateStats>[1], committed: string): void;
25
+ export declare function loadStats(hippoRoot: string): LegacyStats;
26
+ export declare function appendConsolidationRun(hippoRoot: string, run: {
27
+ timestamp: string;
28
+ decayed: number;
29
+ merged: number;
30
+ removed: number;
31
+ }): void;
32
+ /** Rows a tenant created since the last sleep (runs are host-wide), looking back at most 24 hours. */
33
+ export declare function countCreatedSinceLastSleep(hippoRoot: string, tenantId: string, now?: Date): number;
34
+ /**
35
+ * Session decay context: provides the data needed for session-based and adaptive decay.
36
+ */
37
+ export interface SessionDecayContext {
38
+ /** Total number of sleep (consolidation) cycles completed. */
39
+ sleepCount: number;
40
+ /** Average interval between recent sleep cycles, in days. 0 if < 2 cycles. */
41
+ avgSessionIntervalDays: number;
42
+ }
43
+ /**
44
+ * Load the session decay context from the store.
45
+ * Uses consolidation_runs timestamps to compute session intervals.
46
+ */
47
+ export declare function loadSessionDecayContext(hippoRoot: string): SessionDecayContext;
48
+ /**
49
+ * Increment the sleep counter. Called after each consolidation run.
50
+ */
51
+ export declare function incrementSleepCount(hippoRoot: string): void;
52
+ //# sourceMappingURL=index-and-stats.d.ts.map
@@ -0,0 +1,214 @@
1
+ import { closeHippoDb, setMeta, isSqliteBusy, pruneConsolidationRuns, getMeta } from '../db.js';
2
+ import { RejectedValueError } from '../rejection.js';
3
+ import { log } from '../log.js';
4
+ import { audit } from './audit-event.js';
5
+ import { stampOriginProjectForImport, upsertEntryRow } from './entry-row.js';
6
+ import { buildIndexFromDb, syncMirrorFiles, writeIndexMirror, writeStatsMirror, buildStatsFromDb } from './mirrors.js';
7
+ import { openStore, loadLegacyEntriesFromMarkdown } from './open.js';
8
+ /** Load the derived index from SQLite. Read-only: index.json is only ever written by `rebuildIndex`. */
9
+ export function loadIndex(hippoRoot) {
10
+ const db = openStore(hippoRoot);
11
+ try {
12
+ return buildIndexFromDb(db);
13
+ }
14
+ finally {
15
+ closeHippoDb(db);
16
+ }
17
+ }
18
+ /**
19
+ * Persist mutable index metadata. Entry rows themselves are derived from SQLite.
20
+ *
21
+ * LC1 F1(c) structural fix: `last_retrieval_ids` and `last_trace_id` must
22
+ * land atomically — callers (getContext, cmdRecall) fold a freshly-written
23
+ * trace id into `index.last_trace_id` before calling this, relying on BOTH
24
+ * meta keys committing together. Wrapped in BEGIN/COMMIT so a crash or a
25
+ * mid-write failure can never advance one key without the other. index.json
26
+ * is left untouched; only `rebuildIndex` writes it.
27
+ */
28
+ export function saveIndex(hippoRoot, index) {
29
+ const db = openStore(hippoRoot);
30
+ try {
31
+ db.exec('BEGIN');
32
+ try {
33
+ setMeta(db, 'last_retrieval_ids', JSON.stringify(index.last_retrieval_ids ?? []));
34
+ setMeta(db, 'last_trace_id', index.last_trace_id ?? '');
35
+ db.exec('COMMIT');
36
+ }
37
+ catch (error) {
38
+ try {
39
+ db.exec('ROLLBACK');
40
+ }
41
+ catch { /* already rolled back; keep the original error */ }
42
+ throw error;
43
+ }
44
+ }
45
+ finally {
46
+ closeHippoDb(db);
47
+ }
48
+ }
49
+ /**
50
+ * Rebuild mirrors from SQLite, importing any legacy markdown files not already present.
51
+ */
52
+ export function rebuildIndex(hippoRoot) {
53
+ const db = openStore(hippoRoot);
54
+ try {
55
+ // SAFETY: rows' shape matches the single `id` column selected above.
56
+ const existingIds = new Set(db.prepare(`SELECT id FROM memories`).all().map((row) => row.id));
57
+ const legacyEntries = loadLegacyEntriesFromMarkdown(hippoRoot).filter((entry) => !existingIds.has(entry.id));
58
+ if (legacyEntries.length > 0) {
59
+ db.exec('BEGIN');
60
+ try {
61
+ // AT1 (plan §3, round-3 redesign): same guard-with-per-row-skip as
62
+ // bootstrapLegacyStore — rebuildIndex is the other channel through
63
+ // which a stale markdown mirror could resurrect a rejected value.
64
+ // Refusal audit written INLINE (nothing rolls back on a skip).
65
+ let rejectedCount = 0;
66
+ for (const entry of legacyEntries) {
67
+ // v39: same store-derived origin stamp as bootstrapLegacyStore.
68
+ const stamped = stampOriginProjectForImport(hippoRoot, entry);
69
+ try {
70
+ upsertEntryRow(db, stamped);
71
+ }
72
+ catch (err) {
73
+ if (err instanceof RejectedValueError) {
74
+ rejectedCount++;
75
+ audit(db, 'reject_refusal', err.entryId, { digest: err.digest, reason: err.reason }, 'cli', err.tenantId);
76
+ continue;
77
+ }
78
+ throw err;
79
+ }
80
+ }
81
+ if (rejectedCount > 0) {
82
+ log.warn(`rebuildIndex: skipped ${rejectedCount} rejected value(s) found in legacy mirrors`);
83
+ }
84
+ db.exec('COMMIT');
85
+ }
86
+ catch (err) {
87
+ try {
88
+ db.exec('ROLLBACK');
89
+ }
90
+ catch { /* ignore if no active txn */ }
91
+ throw err;
92
+ }
93
+ }
94
+ syncMirrorFiles(hippoRoot, db);
95
+ const index = buildIndexFromDb(db);
96
+ writeIndexMirror(hippoRoot, index);
97
+ return index;
98
+ }
99
+ finally {
100
+ closeHippoDb(db);
101
+ }
102
+ }
103
+ export function updateStats(hippoRoot, delta) {
104
+ const db = openStore(hippoRoot);
105
+ try {
106
+ // One atomic statement per counter, and only for counters the caller
107
+ // named: the read-modify-write this replaces both lost increments to a
108
+ // concurrent writer and stamped stale values over the untouched two.
109
+ const increments = [
110
+ ['total_remembered', delta.remembered ?? 0],
111
+ ['total_recalled', delta.recalled ?? 0],
112
+ ['total_forgotten', delta.forgotten ?? 0],
113
+ ];
114
+ for (const [key, amount] of increments) {
115
+ if (amount === 0)
116
+ continue;
117
+ // Both binds are the same string: node:sqlite binds a JS number as REAL,
118
+ // which would store "1.0" into this TEXT column instead of "1".
119
+ db.prepare(`
120
+ INSERT INTO meta(key, value) VALUES(?, ?)
121
+ ON CONFLICT(key) DO UPDATE SET value = CAST(meta.value AS INTEGER) + CAST(? AS INTEGER)
122
+ `).run(key, String(amount), String(amount));
123
+ }
124
+ writeStatsMirror(hippoRoot, buildStatsFromDb(db));
125
+ }
126
+ finally {
127
+ closeHippoDb(db);
128
+ }
129
+ }
130
+ export function updateStatsUnlessBusy(hippoRoot, delta, committed) {
131
+ try {
132
+ updateStats(hippoRoot, delta);
133
+ }
134
+ catch (err) {
135
+ if (!isSqliteBusy(err))
136
+ throw err;
137
+ log.warnThenDebug('stats-busy', `${committed}, but the store was busy, so the stats counters were not updated`);
138
+ }
139
+ }
140
+ export function loadStats(hippoRoot) {
141
+ const db = openStore(hippoRoot);
142
+ try {
143
+ return buildStatsFromDb(db);
144
+ }
145
+ finally {
146
+ closeHippoDb(db);
147
+ }
148
+ }
149
+ export function appendConsolidationRun(hippoRoot, run) {
150
+ const db = openStore(hippoRoot);
151
+ try {
152
+ db.prepare(`INSERT INTO consolidation_runs(timestamp, decayed, merged, removed) VALUES (?, ?, ?, ?)`).run(run.timestamp, run.decayed, run.merged, run.removed);
153
+ pruneConsolidationRuns(db, 50);
154
+ writeStatsMirror(hippoRoot, buildStatsFromDb(db));
155
+ }
156
+ finally {
157
+ closeHippoDb(db);
158
+ }
159
+ }
160
+ /** Rows a tenant created since the last sleep (runs are host-wide), looking back at most 24 hours. */
161
+ export function countCreatedSinceLastSleep(hippoRoot, tenantId, now = new Date()) {
162
+ const db = openStore(hippoRoot);
163
+ try {
164
+ const dayAgo = new Date(now.getTime() - 86_400_000).toISOString();
165
+ const row = db.prepare(`SELECT COUNT(*) AS n FROM memories WHERE tenant_id = ?
166
+ AND created > MAX(?, COALESCE((SELECT MAX(timestamp) FROM consolidation_runs), ''))`).get(tenantId, dayAgo);
167
+ return row.n;
168
+ }
169
+ finally {
170
+ closeHippoDb(db);
171
+ }
172
+ }
173
+ /**
174
+ * Load the session decay context from the store.
175
+ * Uses consolidation_runs timestamps to compute session intervals.
176
+ */
177
+ export function loadSessionDecayContext(hippoRoot) {
178
+ const db = openStore(hippoRoot);
179
+ try {
180
+ // Get recent consolidation timestamps (last 20)
181
+ // SAFETY: rows' shape matches the single `timestamp` column above.
182
+ const rows = db.prepare(`SELECT timestamp FROM consolidation_runs ORDER BY timestamp DESC, id DESC LIMIT 20`).all();
183
+ const sleepCount = Number(getMeta(db, 'sleep_count', '0')) || rows.length;
184
+ if (rows.length < 2) {
185
+ return { sleepCount, avgSessionIntervalDays: 0 };
186
+ }
187
+ // Compute average interval between consecutive sessions
188
+ const timestamps = rows.map((r) => new Date(r.timestamp).getTime()).reverse();
189
+ let totalInterval = 0;
190
+ for (let i = 1; i < timestamps.length; i++) {
191
+ totalInterval += timestamps[i] - timestamps[i - 1];
192
+ }
193
+ const avgMs = totalInterval / (timestamps.length - 1);
194
+ const avgDays = avgMs / (1000 * 60 * 60 * 24);
195
+ return { sleepCount, avgSessionIntervalDays: Math.max(0, avgDays) };
196
+ }
197
+ finally {
198
+ closeHippoDb(db);
199
+ }
200
+ }
201
+ /**
202
+ * Increment the sleep counter. Called after each consolidation run.
203
+ */
204
+ export function incrementSleepCount(hippoRoot) {
205
+ const db = openStore(hippoRoot);
206
+ try {
207
+ const current = Number(getMeta(db, 'sleep_count', '0')) || 0;
208
+ setMeta(db, 'sleep_count', String(current + 1));
209
+ }
210
+ finally {
211
+ closeHippoDb(db);
212
+ }
213
+ }
214
+ //# sourceMappingURL=index-and-stats.js.map
@@ -0,0 +1,10 @@
1
+ import { type MemoryEntry } from '../memory.js';
2
+ /**
3
+ * Serialize a MemoryEntry to markdown with YAML frontmatter.
4
+ */
5
+ export declare function serializeEntry(entry: MemoryEntry): string;
6
+ /**
7
+ * Deserialize a markdown file to a MemoryEntry.
8
+ */
9
+ export declare function deserializeEntry(raw: string): MemoryEntry | null;
10
+ //# sourceMappingURL=markdown.d.ts.map
@@ -0,0 +1,108 @@
1
+ import { dumpFrontmatter, parseFrontmatter } from '../yaml.js';
2
+ /**
3
+ * Serialize a MemoryEntry to markdown with YAML frontmatter.
4
+ */
5
+ export function serializeEntry(entry) {
6
+ const frontmatter = {
7
+ id: entry.id,
8
+ created: entry.created,
9
+ last_retrieved: entry.last_retrieved,
10
+ retrieval_count: entry.retrieval_count,
11
+ strength: Math.round(entry.strength * 10000) / 10000,
12
+ half_life_days: entry.half_life_days,
13
+ layer: entry.layer,
14
+ tags: entry.tags,
15
+ emotional_valence: entry.emotional_valence,
16
+ schema_fit: entry.schema_fit,
17
+ source: entry.source,
18
+ outcome_score: entry.outcome_score,
19
+ outcome_positive: entry.outcome_positive,
20
+ outcome_negative: entry.outcome_negative,
21
+ conflicts_with: entry.conflicts_with,
22
+ pinned: entry.pinned,
23
+ confidence: entry.confidence ?? 'observed',
24
+ parents: entry.parents ?? [],
25
+ starred: entry.starred ?? false,
26
+ trace_outcome: entry.trace_outcome ?? null,
27
+ source_session_id: entry.source_session_id ?? null,
28
+ kind: entry.kind ?? 'distilled',
29
+ scope: entry.scope ?? null,
30
+ owner: entry.owner ?? null,
31
+ artifact_ref: entry.artifact_ref ?? null,
32
+ };
33
+ // Emit tenant_id only when not 'default' to keep diffs clean for the dominant
34
+ // single-tenant case (mirrors the plan's task 7 guidance).
35
+ const tenantId = entry.tenantId ?? 'default';
36
+ if (tenantId !== 'default') {
37
+ frontmatter['tenant_id'] = tenantId;
38
+ }
39
+ // v39: '' (user-global) and null (unknown, hidden by default) must both round-trip;
40
+ // only undefined (unstamped) is omitted, so a rebuild stamps nothing it can read.
41
+ if (entry.origin_project !== undefined) {
42
+ frontmatter['origin_project'] = entry.origin_project;
43
+ }
44
+ // Spread into a fresh object literal: dumpFrontmatter's Record<string,
45
+ // YamlValue> parameter needs an index signature, which a named interface
46
+ // reference (EntryFrontmatterFields) doesn't structurally provide even
47
+ // though every property's value type already matches.
48
+ const fm = dumpFrontmatter({ ...frontmatter });
49
+ return `${fm}\n\n${entry.content}\n`;
50
+ }
51
+ /**
52
+ * Deserialize a markdown file to a MemoryEntry.
53
+ */
54
+ export function deserializeEntry(raw) {
55
+ const { data, content } = parseFrontmatter(raw);
56
+ if (!data['id'] || !data['layer'])
57
+ return null;
58
+ // SAFETY: every `as X` below narrows a raw YAML frontmatter field to an
59
+ // enum/union member of MemoryEntry; frontmatter is only ever written by
60
+ // serializeEntry (whose own fields are typed), so out-of-range values here
61
+ // would indicate hand-edited files, which this parser is not required to
62
+ // reject — matches the pre-existing permissive-parse behavior.
63
+ return {
64
+ id: String(data['id']),
65
+ created: String(data['created'] ?? new Date().toISOString()),
66
+ last_retrieved: String(data['last_retrieved'] ?? new Date().toISOString()),
67
+ retrieval_count: Number(data['retrieval_count'] ?? 0),
68
+ strength: Number(data['strength'] ?? 1.0),
69
+ half_life_days: Number(data['half_life_days'] ?? 7),
70
+ layer: data['layer'],
71
+ tags: normalizeStringArray(data['tags']),
72
+ emotional_valence: data['emotional_valence'] ?? 'neutral',
73
+ schema_fit: Number(data['schema_fit'] ?? 0.5),
74
+ source: String(data['source'] ?? 'cli'),
75
+ outcome_score: data['outcome_score'] === null || data['outcome_score'] === undefined ? null : Number(data['outcome_score']),
76
+ outcome_positive: Number(data['outcome_positive'] ?? 0),
77
+ outcome_negative: Number(data['outcome_negative'] ?? 0),
78
+ conflicts_with: normalizeStringArray(data['conflicts_with']),
79
+ pinned: Boolean(data['pinned'] ?? false),
80
+ confidence: data['confidence'] ?? 'observed',
81
+ content: content.trim(),
82
+ parents: normalizeStringArray(data['parents']),
83
+ starred: Boolean(data['starred'] ?? false),
84
+ trace_outcome: data['trace_outcome'] ?? null,
85
+ source_session_id: data['source_session_id'] === null || data['source_session_id'] === undefined
86
+ ? null
87
+ : String(data['source_session_id']),
88
+ valid_from: data['valid_from'] ? String(data['valid_from']) : String(data['created'] ?? new Date().toISOString()),
89
+ superseded_by: data['superseded_by'] === null || data['superseded_by'] === undefined
90
+ ? null
91
+ : String(data['superseded_by']),
92
+ extracted_from: data['extracted_from'] ?? null,
93
+ dag_level: Number(data['dag_level'] ?? 0),
94
+ dag_parent_id: data['dag_parent_id'] ?? null,
95
+ kind: (data['kind'] ?? 'distilled'),
96
+ scope: data['scope'] === null || data['scope'] === undefined ? null : String(data['scope']),
97
+ owner: data['owner'] === null || data['owner'] === undefined ? null : String(data['owner']),
98
+ artifact_ref: data['artifact_ref'] === null || data['artifact_ref'] === undefined ? null : String(data['artifact_ref']),
99
+ tenantId: data['tenant_id'] === null || data['tenant_id'] === undefined ? 'default' : String(data['tenant_id']),
100
+ origin_project: !('origin_project' in data) ? undefined : data['origin_project'] === null ? null : String(data['origin_project']),
101
+ };
102
+ }
103
+ function normalizeStringArray(value) {
104
+ if (!Array.isArray(value))
105
+ return [];
106
+ return value.map((item) => String(item));
107
+ }
108
+ //# sourceMappingURL=markdown.js.map
@@ -0,0 +1,49 @@
1
+ import { Layer, type MemoryEntry } from '../memory.js';
2
+ import { openHippoDb } from '../db.js';
3
+ import { type TaskSnapshot, type SessionEvent, type HippoIndex, type LegacyStats } from './rows.js';
4
+ export declare function layerDir(root: string, layer: Layer): string;
5
+ export declare function ensureMirrorDirectories(hippoRoot: string): void;
6
+ export declare function writeActiveTaskMirror(hippoRoot: string, tenantId: string, snapshot: TaskSnapshot): void;
7
+ export declare function removeActiveTaskMirror(hippoRoot: string, tenantId: string): void;
8
+ export declare function writeRecentSessionMirror(hippoRoot: string, tenantId: string, events: SessionEvent[]): void;
9
+ export declare function writeMarkdownMirror(hippoRoot: string, entry: MemoryEntry): void;
10
+ export declare function removeEntryMirrors(hippoRoot: string, id: string): void;
11
+ /**
12
+ * AT1 mirror-purge honesty fix (docs/plans/2026-08-15-at1-rejected-value-tombstone.md):
13
+ * the candidate markdown mirror paths still on disk for `id`, computed the
14
+ * same way `removeEntryMirrors` walks them (one per layer: buffer/episodic/
15
+ * semantic), filtered to the ones that still `fs.existsSync`. Used to report
16
+ * an EXPLICIT path when a best-effort purge fails and no reaper exists to
17
+ * retry it — plain `removeEntryMirrors` returns void, giving no way to name
18
+ * which file is stuck.
19
+ */
20
+ export declare function getExistingEntryMirrorPaths(hippoRoot: string, id: string): string[];
21
+ /**
22
+ * AT1 fix: best-effort markdown-mirror purge shared by `reject-flow.ts`'s
23
+ * `rejectValue` and `resolveConflict`'s post-commit purge. Both used to log
24
+ * "will retry via reaper on next open" for EVERY failure, but the reaper
25
+ * (`cleanupArchivedMirrors`, raw-archive-mirror-cleanup.ts) only scans
26
+ * `raw_archive` — that message was false for a non-raw id, which has no
27
+ * reaper at all.
28
+ *
29
+ * Retries the unlink once synchronously (the common real-world failure is a
30
+ * transient lock/AV-scanner false positive, not a permanent one). On a
31
+ * second failure: raw ids still get the honest reaper message (true); non-raw
32
+ * ids get the EXPLICIT leftover file path(s) and a manual-delete instruction,
33
+ * since nothing will ever retry them automatically.
34
+ *
35
+ * Returns true if the mirror ended up purged (first or second attempt).
36
+ */
37
+ export declare function purgeMirrorBestEffort(hippoRoot: string, id: string, isRaw: boolean, logPrefix: string): boolean;
38
+ /** Derive the current `HippoIndex` from SQLite. Exported for `rebuildIndex`
39
+ * (the only index.json writer) and the longmemeval benchmark. */
40
+ export declare function buildIndexFromDb(db: ReturnType<typeof openHippoDb>): HippoIndex;
41
+ export declare function buildStatsFromDb(db: ReturnType<typeof openHippoDb>): LegacyStats;
42
+ /** Write the `index.json` mirror file for an already-derived index. Exported for
43
+ * `rebuildIndex` (the only index.json writer) and the longmemeval benchmark. */
44
+ export declare function writeIndexMirror(hippoRoot: string, index: HippoIndex): void;
45
+ export declare function writeStatsMirror(hippoRoot: string, stats: LegacyStats): void;
46
+ /** Mirrors are derived from SQLite and written after COMMIT, so a failed write warns instead of failing a committed change. */
47
+ export declare function mirrorBestEffort(what: string, write: () => void): void;
48
+ export declare function syncMirrorFiles(hippoRoot: string, db: ReturnType<typeof openHippoDb>): void;
49
+ //# sourceMappingURL=mirrors.d.ts.map