hippo-memory 1.60.0 → 1.62.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 (593) hide show
  1. package/README.md +29 -54
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.d.ts +1 -1
  4. package/dist/agent-memories/apply.js +4 -1
  5. package/dist/agent-memories/claude-code.d.ts +3 -1
  6. package/dist/agent-memories/claude-code.js +54 -10
  7. package/dist/agent-memories/codex.js +1 -1
  8. package/dist/agent-memories/gemini.js +1 -1
  9. package/dist/agent-memories/legacy.js +1 -1
  10. package/dist/agent-memories/source.js +1 -1
  11. package/dist/agent-memories/sync.d.ts +3 -3
  12. package/dist/agent-memories/sync.js +22 -9
  13. package/dist/agent-memories/types.d.ts +0 -2
  14. package/dist/ambient-store.d.ts +14 -0
  15. package/dist/ambient-store.js +90 -0
  16. package/dist/ambient.d.ts +23 -0
  17. package/dist/ambient.js +72 -50
  18. package/dist/api/assemble.d.ts +93 -0
  19. package/dist/api/assemble.js +153 -0
  20. package/dist/api/audit.d.ts +17 -0
  21. package/dist/api/audit.js +23 -0
  22. package/dist/api/auth.d.ts +79 -0
  23. package/dist/api/auth.js +178 -0
  24. package/dist/api/context-select.d.ts +49 -0
  25. package/dist/api/context-select.js +344 -0
  26. package/dist/api/context-types.d.ts +105 -0
  27. package/dist/api/context-types.js +3 -0
  28. package/dist/api/context.d.ts +31 -0
  29. package/dist/api/context.js +378 -0
  30. package/dist/api/dormant.d.ts +30 -0
  31. package/dist/api/dormant.js +140 -0
  32. package/dist/api/drill-down.d.ts +84 -0
  33. package/dist/api/drill-down.js +126 -0
  34. package/dist/api/forget.d.ts +57 -0
  35. package/dist/api/forget.js +87 -0
  36. package/dist/api/goals.d.ts +18 -0
  37. package/dist/api/goals.js +33 -0
  38. package/dist/api/learn.d.ts +31 -0
  39. package/dist/api/learn.js +88 -0
  40. package/dist/api/outcome.d.ts +61 -0
  41. package/dist/api/outcome.js +66 -0
  42. package/dist/api/promote.d.ts +54 -0
  43. package/dist/api/promote.js +192 -0
  44. package/dist/api/quarantine.d.ts +24 -0
  45. package/dist/api/quarantine.js +121 -0
  46. package/dist/api/recall-types.d.ts +390 -0
  47. package/dist/api/recall-types.js +3 -0
  48. package/dist/api/recall.d.ts +36 -0
  49. package/dist/api/recall.js +499 -0
  50. package/dist/api/remember.d.ts +35 -0
  51. package/dist/api/remember.js +43 -0
  52. package/dist/api/sleep.d.ts +136 -0
  53. package/dist/api/sleep.js +256 -0
  54. package/dist/api/tokens.d.ts +26 -0
  55. package/dist/api/tokens.js +60 -0
  56. package/dist/api/types.d.ts +56 -0
  57. package/dist/api/types.js +38 -0
  58. package/dist/api.d.ts +20 -1262
  59. package/dist/api.js +25 -2727
  60. package/dist/audit.d.ts +3 -0
  61. package/dist/audit.js +6 -3
  62. package/dist/auth.d.ts +45 -4
  63. package/dist/auth.js +125 -48
  64. package/dist/autolearn.js +2 -2
  65. package/dist/capture/command.d.ts +33 -0
  66. package/dist/capture/command.js +264 -0
  67. package/dist/capture/compact.d.ts +44 -0
  68. package/dist/capture/compact.js +354 -0
  69. package/dist/capture/extract.d.ts +21 -0
  70. package/dist/capture/extract.js +464 -0
  71. package/dist/capture/transcript.d.ts +40 -0
  72. package/dist/capture/transcript.js +193 -0
  73. package/dist/capture-error.js +2 -1
  74. package/dist/churn-git.js +4 -2
  75. package/dist/cli/audit.d.ts +3 -0
  76. package/dist/cli/audit.js +159 -0
  77. package/dist/cli/auth.d.ts +2 -0
  78. package/dist/cli/auth.js +171 -0
  79. package/dist/cli/briefs.d.ts +4 -0
  80. package/dist/cli/briefs.js +453 -0
  81. package/dist/cli/card.d.ts +3 -0
  82. package/dist/cli/card.js +333 -0
  83. package/dist/cli/context.d.ts +15 -0
  84. package/dist/cli/context.js +376 -0
  85. package/dist/cli/continuity.d.ts +6 -0
  86. package/dist/cli/continuity.js +457 -0
  87. package/dist/cli/curate.d.ts +19 -0
  88. package/dist/cli/curate.js +556 -0
  89. package/dist/cli/dag.d.ts +5 -0
  90. package/dist/cli/dag.js +177 -0
  91. package/dist/cli/decisions.d.ts +4 -0
  92. package/dist/cli/decisions.js +528 -0
  93. package/dist/cli/eval.d.ts +5 -0
  94. package/dist/cli/eval.js +213 -0
  95. package/dist/cli/explain.d.ts +4 -0
  96. package/dist/cli/explain.js +156 -0
  97. package/dist/cli/goals.d.ts +2 -0
  98. package/dist/cli/goals.js +196 -0
  99. package/dist/cli/hook-blocks.d.ts +18 -0
  100. package/dist/cli/hook-blocks.js +233 -0
  101. package/dist/cli/init.d.ts +2 -0
  102. package/dist/cli/init.js +305 -0
  103. package/dist/cli/maintenance.d.ts +4 -0
  104. package/dist/cli/maintenance.js +190 -0
  105. package/dist/cli/playbooks.d.ts +4 -0
  106. package/dist/cli/playbooks.js +573 -0
  107. package/dist/cli/projects.js +9 -6
  108. package/dist/cli/recall.d.ts +7 -0
  109. package/dist/cli/recall.js +582 -0
  110. package/dist/cli/remember.d.ts +5 -0
  111. package/dist/cli/remember.js +485 -0
  112. package/dist/cli/serve.d.ts +5 -0
  113. package/dist/cli/serve.js +40 -0
  114. package/dist/cli/session-hooks.d.ts +29 -0
  115. package/dist/cli/session-hooks.js +647 -0
  116. package/dist/cli/setup.d.ts +4 -0
  117. package/dist/cli/setup.js +397 -0
  118. package/dist/cli/shared.d.ts +15 -19
  119. package/dist/cli/shared.js +50 -341
  120. package/dist/cli/slack.d.ts +2 -0
  121. package/dist/cli/slack.js +171 -0
  122. package/dist/cli/status.d.ts +18 -0
  123. package/dist/cli/status.js +409 -0
  124. package/dist/cli/transfer.d.ts +10 -0
  125. package/dist/cli/transfer.js +424 -0
  126. package/dist/cli/usage.d.ts +85 -0
  127. package/dist/cli/usage.js +741 -0
  128. package/dist/cli.d.ts +71 -120
  129. package/dist/cli.js +170 -8469
  130. package/dist/client.js +15 -8
  131. package/dist/compaction-record.d.ts +0 -2
  132. package/dist/compaction-record.js +7 -5
  133. package/dist/connectors/github/backfill.js +94 -87
  134. package/dist/connectors/github/cli-impl.js +4 -3
  135. package/dist/connectors/github/dlq.js +67 -54
  136. package/dist/connectors/github/ingest.js +34 -35
  137. package/dist/connectors/github/tenant-routing.js +3 -2
  138. package/dist/connectors/github/webhook.js +135 -216
  139. package/dist/connectors/slack/dlq.js +49 -61
  140. package/dist/connectors/slack/ingest.js +55 -48
  141. package/dist/connectors/slack/tenant-routing.js +4 -3
  142. package/dist/connectors/slack/webhook.js +72 -74
  143. package/dist/consolidate/conflicts.d.ts +10 -0
  144. package/dist/consolidate/conflicts.js +178 -0
  145. package/dist/consolidate/decay.d.ts +12 -0
  146. package/dist/consolidate/decay.js +145 -0
  147. package/dist/consolidate/llm-passes.d.ts +3 -0
  148. package/dist/consolidate/llm-passes.js +141 -0
  149. package/dist/consolidate/merge.d.ts +7 -0
  150. package/dist/consolidate/merge.js +251 -0
  151. package/dist/consolidate/physics-pass.d.ts +3 -0
  152. package/dist/consolidate/physics-pass.js +60 -0
  153. package/dist/consolidate/run.d.ts +69 -0
  154. package/dist/consolidate/run.js +76 -0
  155. package/dist/consolidate/sleep.d.ts +18 -0
  156. package/dist/consolidate/sleep.js +209 -0
  157. package/dist/consolidate/traces.d.ts +4 -0
  158. package/dist/consolidate/traces.js +178 -0
  159. package/dist/context-auto.js +7 -11
  160. package/dist/context-render.d.ts +1 -1
  161. package/dist/context-render.js +1 -1
  162. package/dist/customer-notes.d.ts +3 -0
  163. package/dist/customer-notes.js +83 -72
  164. package/dist/dag.js +225 -188
  165. package/dist/dashboard-actions.d.ts +20 -0
  166. package/dist/dashboard-actions.js +88 -0
  167. package/dist/dashboard-params.d.ts +45 -0
  168. package/dist/dashboard-params.js +127 -0
  169. package/dist/dashboard-queries.d.ts +15 -0
  170. package/dist/dashboard-queries.js +355 -0
  171. package/dist/dashboard-snapshot.d.ts +138 -0
  172. package/dist/dashboard-snapshot.js +308 -0
  173. package/dist/dashboard-types.d.ts +163 -0
  174. package/dist/dashboard-types.js +3 -0
  175. package/dist/dashboard.d.ts +6 -7
  176. package/dist/dashboard.js +228 -202
  177. package/dist/db/busy.d.ts +5 -0
  178. package/dist/db/busy.js +24 -0
  179. package/dist/db/continuity.d.ts +5 -0
  180. package/dist/db/continuity.js +145 -0
  181. package/dist/db/meta.d.ts +8 -0
  182. package/dist/db/meta.js +35 -0
  183. package/dist/db/migrate.d.ts +9 -0
  184. package/dist/db/migrate.js +138 -0
  185. package/dist/db/migrations/index.d.ts +5 -0
  186. package/dist/db/migrations/index.js +109 -0
  187. package/dist/db/migrations/types.d.ts +14 -0
  188. package/dist/db/migrations/types.js +2 -0
  189. package/dist/db/migrations/v01.d.ts +3 -0
  190. package/dist/db/migrations/v01.js +38 -0
  191. package/dist/db/migrations/v02.d.ts +3 -0
  192. package/dist/db/migrations/v02.js +21 -0
  193. package/dist/db/migrations/v03.d.ts +3 -0
  194. package/dist/db/migrations/v03.js +22 -0
  195. package/dist/db/migrations/v04.d.ts +3 -0
  196. package/dist/db/migrations/v04.js +28 -0
  197. package/dist/db/migrations/v05.d.ts +3 -0
  198. package/dist/db/migrations/v05.js +21 -0
  199. package/dist/db/migrations/v06.d.ts +3 -0
  200. package/dist/db/migrations/v06.js +25 -0
  201. package/dist/db/migrations/v07.d.ts +3 -0
  202. package/dist/db/migrations/v07.js +13 -0
  203. package/dist/db/migrations/v08.d.ts +3 -0
  204. package/dist/db/migrations/v08.js +8 -0
  205. package/dist/db/migrations/v09.d.ts +3 -0
  206. package/dist/db/migrations/v09.js +13 -0
  207. package/dist/db/migrations/v10.d.ts +3 -0
  208. package/dist/db/migrations/v10.js +17 -0
  209. package/dist/db/migrations/v11.d.ts +3 -0
  210. package/dist/db/migrations/v11.js +15 -0
  211. package/dist/db/migrations/v12.d.ts +3 -0
  212. package/dist/db/migrations/v12.js +11 -0
  213. package/dist/db/migrations/v13.d.ts +3 -0
  214. package/dist/db/migrations/v13.js +15 -0
  215. package/dist/db/migrations/v14.d.ts +3 -0
  216. package/dist/db/migrations/v14.js +66 -0
  217. package/dist/db/migrations/v15.d.ts +3 -0
  218. package/dist/db/migrations/v15.js +42 -0
  219. package/dist/db/migrations/v16.d.ts +3 -0
  220. package/dist/db/migrations/v16.js +61 -0
  221. package/dist/db/migrations/v17.d.ts +3 -0
  222. package/dist/db/migrations/v17.js +46 -0
  223. package/dist/db/migrations/v18.d.ts +3 -0
  224. package/dist/db/migrations/v18.js +60 -0
  225. package/dist/db/migrations/v19.d.ts +3 -0
  226. package/dist/db/migrations/v19.js +28 -0
  227. package/dist/db/migrations/v20.d.ts +3 -0
  228. package/dist/db/migrations/v20.js +42 -0
  229. package/dist/db/migrations/v21.d.ts +3 -0
  230. package/dist/db/migrations/v21.js +16 -0
  231. package/dist/db/migrations/v22.d.ts +3 -0
  232. package/dist/db/migrations/v22.js +82 -0
  233. package/dist/db/migrations/v23.d.ts +3 -0
  234. package/dist/db/migrations/v23.js +48 -0
  235. package/dist/db/migrations/v24.d.ts +3 -0
  236. package/dist/db/migrations/v24.js +72 -0
  237. package/dist/db/migrations/v25.d.ts +3 -0
  238. package/dist/db/migrations/v25.js +46 -0
  239. package/dist/db/migrations/v26.d.ts +3 -0
  240. package/dist/db/migrations/v26.js +23 -0
  241. package/dist/db/migrations/v27.d.ts +3 -0
  242. package/dist/db/migrations/v27.js +57 -0
  243. package/dist/db/migrations/v28.d.ts +3 -0
  244. package/dist/db/migrations/v28.js +38 -0
  245. package/dist/db/migrations/v29.d.ts +3 -0
  246. package/dist/db/migrations/v29.js +78 -0
  247. package/dist/db/migrations/v30.d.ts +3 -0
  248. package/dist/db/migrations/v30.js +92 -0
  249. package/dist/db/migrations/v31.d.ts +3 -0
  250. package/dist/db/migrations/v31.js +74 -0
  251. package/dist/db/migrations/v32.d.ts +3 -0
  252. package/dist/db/migrations/v32.js +102 -0
  253. package/dist/db/migrations/v33.d.ts +3 -0
  254. package/dist/db/migrations/v33.js +104 -0
  255. package/dist/db/migrations/v34.d.ts +3 -0
  256. package/dist/db/migrations/v34.js +93 -0
  257. package/dist/db/migrations/v35.d.ts +3 -0
  258. package/dist/db/migrations/v35.js +98 -0
  259. package/dist/db/migrations/v36.d.ts +3 -0
  260. package/dist/db/migrations/v36.js +98 -0
  261. package/dist/db/migrations/v37.d.ts +3 -0
  262. package/dist/db/migrations/v37.js +219 -0
  263. package/dist/db/migrations/v38.d.ts +3 -0
  264. package/dist/db/migrations/v38.js +277 -0
  265. package/dist/db/migrations/v39.d.ts +3 -0
  266. package/dist/db/migrations/v39.js +59 -0
  267. package/dist/db/migrations/v40.d.ts +3 -0
  268. package/dist/db/migrations/v40.js +74 -0
  269. package/dist/db/migrations/v41.d.ts +3 -0
  270. package/dist/db/migrations/v41.js +43 -0
  271. package/dist/db/migrations/v42.d.ts +3 -0
  272. package/dist/db/migrations/v42.js +41 -0
  273. package/dist/db/migrations/v43.d.ts +3 -0
  274. package/dist/db/migrations/v43.js +67 -0
  275. package/dist/db/migrations/v44.d.ts +3 -0
  276. package/dist/db/migrations/v44.js +28 -0
  277. package/dist/db/migrations/v45.d.ts +3 -0
  278. package/dist/db/migrations/v45.js +30 -0
  279. package/dist/db/migrations/v46.d.ts +3 -0
  280. package/dist/db/migrations/v46.js +25 -0
  281. package/dist/db/migrations/v47.d.ts +3 -0
  282. package/dist/db/migrations/v47.js +17 -0
  283. package/dist/db/migrations/v48.d.ts +3 -0
  284. package/dist/db/migrations/v48.js +10 -0
  285. package/dist/db/migrations/v49.d.ts +3 -0
  286. package/dist/db/migrations/v49.js +31 -0
  287. package/dist/db/migrations/v50.d.ts +3 -0
  288. package/dist/db/migrations/v50.js +67 -0
  289. package/dist/db/migrations/v51.d.ts +3 -0
  290. package/dist/db/migrations/v51.js +14 -0
  291. package/dist/db/migrations/v52.d.ts +3 -0
  292. package/dist/db/migrations/v52.js +7 -0
  293. package/dist/db/open.d.ts +23 -0
  294. package/dist/db/open.js +146 -0
  295. package/dist/db/sqlite.d.ts +21 -0
  296. package/dist/db/sqlite.js +8 -0
  297. package/dist/db/tables.d.ts +7 -0
  298. package/dist/db/tables.js +38 -0
  299. package/dist/db.d.ts +6 -46
  300. package/dist/db.js +5 -3049
  301. package/dist/decisions.d.ts +4 -1
  302. package/dist/decisions.js +102 -83
  303. package/dist/dedupe.js +3 -2
  304. package/dist/delivery-recorder.js +4 -1
  305. package/dist/doctor.js +14 -10
  306. package/dist/embedding-provider.d.ts +1 -1
  307. package/dist/embedding-provider.js +4 -3
  308. package/dist/embeddings.d.ts +9 -52
  309. package/dist/embeddings.js +43 -297
  310. package/dist/env.d.ts +75 -0
  311. package/dist/env.js +119 -0
  312. package/dist/eval-suite.js +1 -1
  313. package/dist/eval.js +2 -2
  314. package/dist/extract.js +1 -1
  315. package/dist/gated-write.js +3 -1
  316. package/dist/goals.d.ts +3 -1
  317. package/dist/goals.js +117 -86
  318. package/dist/graph/read.d.ts +73 -0
  319. package/dist/graph/read.js +325 -0
  320. package/dist/graph/rows.d.ts +45 -0
  321. package/dist/graph/rows.js +51 -0
  322. package/dist/graph/types.d.ts +83 -0
  323. package/dist/graph/types.js +11 -0
  324. package/dist/graph/write.d.ts +93 -0
  325. package/dist/{graph.js → graph/write.js} +6 -384
  326. package/dist/graph-extract.js +2 -1
  327. package/dist/graph-recall.d.ts +1 -1
  328. package/dist/graph-recall.js +2 -2
  329. package/dist/graph-stream.js +1 -1
  330. package/dist/graph-view.d.ts +1 -1
  331. package/dist/graph-view.js +1 -1
  332. package/dist/half-life-migration.d.ts +1 -1
  333. package/dist/half-life-migration.js +2 -1
  334. package/dist/hooks/codex-session.d.ts +8 -0
  335. package/dist/hooks/codex-session.js +76 -0
  336. package/dist/hooks/codex-wrapper.d.ts +55 -0
  337. package/dist/hooks/codex-wrapper.js +288 -0
  338. package/dist/hooks/json-hooks.d.ts +63 -0
  339. package/dist/hooks/json-hooks.js +356 -0
  340. package/dist/hooks/opencode.d.ts +50 -0
  341. package/dist/hooks/opencode.js +202 -0
  342. package/dist/hooks/shared.d.ts +54 -0
  343. package/dist/hooks/shared.js +77 -0
  344. package/dist/http-retry.d.ts +2 -0
  345. package/dist/http-retry.js +4 -3
  346. package/dist/http-util.d.ts +3 -0
  347. package/dist/http-util.js +10 -0
  348. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  349. package/dist/importers/core.js +141 -0
  350. package/dist/importers/markdown-parse.d.ts +41 -0
  351. package/dist/importers/markdown-parse.js +132 -0
  352. package/dist/importers/markdown.d.ts +3 -0
  353. package/dist/importers/markdown.js +92 -0
  354. package/dist/importers/sources.d.ts +7 -0
  355. package/dist/importers/sources.js +229 -0
  356. package/dist/importers/vault.d.ts +11 -0
  357. package/dist/importers/vault.js +352 -0
  358. package/dist/incidents.d.ts +3 -0
  359. package/dist/incidents.js +52 -43
  360. package/dist/index.d.ts +25 -6
  361. package/dist/index.js +23 -6
  362. package/dist/invalidation.js +2 -1
  363. package/dist/judgment.js +2 -1
  364. package/dist/keyset.d.ts +13 -0
  365. package/dist/keyset.js +8 -0
  366. package/dist/local-embedding.d.ts +13 -0
  367. package/dist/local-embedding.js +165 -0
  368. package/dist/log.d.ts +7 -0
  369. package/dist/log.js +19 -1
  370. package/dist/mcp/admin-tools.d.ts +8 -0
  371. package/dist/mcp/admin-tools.js +116 -0
  372. package/dist/mcp/format.d.ts +27 -0
  373. package/dist/mcp/format.js +135 -0
  374. package/dist/mcp/memory-tools.d.ts +5 -0
  375. package/dist/mcp/memory-tools.js +83 -0
  376. package/dist/mcp/protocol.d.ts +83 -0
  377. package/dist/mcp/protocol.js +55 -0
  378. package/dist/mcp/recall-tools.d.ts +6 -0
  379. package/dist/mcp/recall-tools.js +320 -0
  380. package/dist/mcp/request.d.ts +10 -0
  381. package/dist/mcp/request.js +163 -0
  382. package/dist/mcp/server.d.ts +4 -75
  383. package/dist/mcp/server.js +7 -1190
  384. package/dist/mcp/session-state.d.ts +11 -0
  385. package/dist/mcp/session-state.js +28 -0
  386. package/dist/mcp/stdio.d.ts +8 -0
  387. package/dist/mcp/stdio.js +79 -0
  388. package/dist/mcp/tools.d.ts +11 -0
  389. package/dist/mcp/tools.js +247 -0
  390. package/dist/memory.d.ts +3 -0
  391. package/dist/memory.js +27 -1
  392. package/dist/multihop.d.ts +1 -1
  393. package/dist/multihop.js +2 -1
  394. package/dist/owner-validation.js +2 -1
  395. package/dist/physics-state.js +10 -7
  396. package/dist/policies.d.ts +3 -0
  397. package/dist/policies.js +93 -74
  398. package/dist/postinstall.js +3 -2
  399. package/dist/predictions/planning-fallacy.d.ts +100 -0
  400. package/dist/predictions/planning-fallacy.js +190 -0
  401. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  402. package/dist/predictions/store.js +434 -0
  403. package/dist/processes.d.ts +3 -0
  404. package/dist/processes.js +94 -76
  405. package/dist/project-briefs.d.ts +3 -0
  406. package/dist/project-briefs.js +142 -113
  407. package/dist/project-identity.js +3 -2
  408. package/dist/project-merge.d.ts +12 -4
  409. package/dist/project-merge.js +132 -45
  410. package/dist/quarantine.d.ts +2 -1
  411. package/dist/quarantine.js +8 -5
  412. package/dist/raw-archive.js +1 -1
  413. package/dist/recall-history.js +3 -2
  414. package/dist/recall-pipeline.d.ts +2 -2
  415. package/dist/recall-pipeline.js +16 -8
  416. package/dist/recall-scope.js +1 -1
  417. package/dist/recall-trace.d.ts +1 -1
  418. package/dist/refine-llm.js +2 -1
  419. package/dist/reject-flow.js +6 -1
  420. package/dist/rerankers/clef.js +6 -5
  421. package/dist/rerankers/jev.d.ts +1 -1
  422. package/dist/rerankers/jev.js +4 -4
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +58 -38
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/scheduler.d.ts +1 -0
  428. package/dist/scheduler.js +26 -4
  429. package/dist/scope.js +4 -3
  430. package/dist/search/as-of.d.ts +10 -0
  431. package/dist/search/as-of.js +22 -0
  432. package/dist/search/bm25-search.d.ts +14 -0
  433. package/dist/search/bm25-search.js +43 -0
  434. package/dist/search/bm25.d.ts +15 -0
  435. package/dist/search/bm25.js +54 -0
  436. package/dist/search/boosts.d.ts +54 -0
  437. package/dist/search/boosts.js +94 -0
  438. package/dist/search/breakdown.d.ts +7 -0
  439. package/dist/search/breakdown.js +20 -0
  440. package/dist/search/explain.d.ts +25 -0
  441. package/dist/search/explain.js +31 -0
  442. package/dist/search/finalize.d.ts +8 -0
  443. package/dist/search/finalize.js +52 -0
  444. package/dist/search/fusion.d.ts +27 -0
  445. package/dist/search/fusion.js +42 -0
  446. package/dist/search/hybrid-score.d.ts +20 -0
  447. package/dist/search/hybrid-score.js +73 -0
  448. package/dist/search/hybrid.d.ts +46 -0
  449. package/dist/search/hybrid.js +64 -0
  450. package/dist/search/physics-search.d.ts +29 -0
  451. package/dist/search/physics-search.js +162 -0
  452. package/dist/search/rerank.d.ts +10 -0
  453. package/dist/search/rerank.js +72 -0
  454. package/dist/search/temporal.d.ts +15 -0
  455. package/dist/search/temporal.js +45 -0
  456. package/dist/search/types.d.ts +91 -0
  457. package/dist/search/types.js +2 -0
  458. package/dist/search/vector.d.ts +30 -0
  459. package/dist/search/vector.js +71 -0
  460. package/dist/secret-detect.d.ts +2 -0
  461. package/dist/secret-detect.js +2 -1
  462. package/dist/server/auth.d.ts +52 -0
  463. package/dist/server/auth.js +221 -0
  464. package/dist/server/client-ip.d.ts +25 -0
  465. package/dist/server/client-ip.js +92 -0
  466. package/dist/server/cursor.d.ts +23 -0
  467. package/dist/server/cursor.js +58 -0
  468. package/dist/server/lifecycle.d.ts +7 -0
  469. package/dist/server/lifecycle.js +29 -0
  470. package/dist/server/mcp-http.d.ts +5 -0
  471. package/dist/server/mcp-http.js +199 -0
  472. package/dist/server/request.d.ts +33 -0
  473. package/dist/server/request.js +103 -0
  474. package/dist/server/routes/admin.d.ts +9 -0
  475. package/dist/server/routes/admin.js +158 -0
  476. package/dist/server/routes/customer-notes.d.ts +7 -0
  477. package/dist/server/routes/customer-notes.js +112 -0
  478. package/dist/server/routes/decisions.d.ts +7 -0
  479. package/dist/server/routes/decisions.js +133 -0
  480. package/dist/server/routes/incidents.d.ts +7 -0
  481. package/dist/server/routes/incidents.js +126 -0
  482. package/dist/server/routes/memories.d.ts +10 -0
  483. package/dist/server/routes/memories.js +179 -0
  484. package/dist/server/routes/policies.d.ts +8 -0
  485. package/dist/server/routes/policies.js +151 -0
  486. package/dist/server/routes/predictions.d.ts +7 -0
  487. package/dist/server/routes/predictions.js +164 -0
  488. package/dist/server/routes/processes.d.ts +7 -0
  489. package/dist/server/routes/processes.js +161 -0
  490. package/dist/server/routes/project-briefs.d.ts +8 -0
  491. package/dist/server/routes/project-briefs.js +136 -0
  492. package/dist/server/routes/recall.d.ts +8 -0
  493. package/dist/server/routes/recall.js +340 -0
  494. package/dist/server/routes/skills.d.ts +8 -0
  495. package/dist/server/routes/skills.js +150 -0
  496. package/dist/server/types.d.ts +56 -0
  497. package/dist/server/types.js +2 -0
  498. package/dist/server/validation.d.ts +14 -0
  499. package/dist/server/validation.js +91 -0
  500. package/dist/server.d.ts +7 -61
  501. package/dist/server.js +69 -2362
  502. package/dist/session-digest.d.ts +1 -1
  503. package/dist/session-digest.js +9 -2
  504. package/dist/shared.d.ts +12 -1
  505. package/dist/shared.js +33 -27
  506. package/dist/skills.d.ts +3 -0
  507. package/dist/skills.js +88 -70
  508. package/dist/stdin.js +2 -2
  509. package/dist/store/audit-event.d.ts +19 -0
  510. package/dist/store/audit-event.js +33 -0
  511. package/dist/store/candidates.d.ts +42 -0
  512. package/dist/store/candidates.js +152 -0
  513. package/dist/store/conflicts.d.ts +44 -0
  514. package/dist/store/conflicts.js +444 -0
  515. package/dist/store/delete-and-batch.d.ts +63 -0
  516. package/dist/store/delete-and-batch.js +310 -0
  517. package/dist/store/entry-reads.d.ts +92 -0
  518. package/dist/store/entry-reads.js +255 -0
  519. package/dist/store/entry-row.d.ts +67 -0
  520. package/dist/store/entry-row.js +208 -0
  521. package/dist/store/entry-writes.d.ts +46 -0
  522. package/dist/store/entry-writes.js +148 -0
  523. package/dist/store/handoffs.d.ts +26 -0
  524. package/dist/store/handoffs.js +184 -0
  525. package/dist/store/index-and-stats.d.ts +52 -0
  526. package/dist/store/index-and-stats.js +214 -0
  527. package/dist/store/markdown.d.ts +10 -0
  528. package/dist/store/markdown.js +108 -0
  529. package/dist/store/mirrors.d.ts +49 -0
  530. package/dist/store/mirrors.js +312 -0
  531. package/dist/store/open.d.ts +15 -0
  532. package/dist/store/open.js +223 -0
  533. package/dist/store/rows.d.ts +178 -0
  534. package/dist/store/rows.js +158 -0
  535. package/dist/store/search-rows.d.ts +86 -0
  536. package/dist/store/search-rows.js +260 -0
  537. package/dist/store/sessions.d.ts +83 -0
  538. package/dist/store/sessions.js +272 -0
  539. package/dist/store/summaries.d.ts +94 -0
  540. package/dist/store/summaries.js +377 -0
  541. package/dist/store/tenant-lookup.d.ts +12 -0
  542. package/dist/store/tenant-lookup.js +16 -0
  543. package/dist/store-cards.js +2 -1
  544. package/dist/summary-dirty.d.ts +4 -0
  545. package/dist/summary-dirty.js +32 -0
  546. package/dist/support-bundle.js +4 -3
  547. package/dist/tenant.js +2 -2
  548. package/dist/tokenize.d.ts +2 -0
  549. package/dist/tokenize.js +16 -0
  550. package/dist/transcript-tail.d.ts +7 -0
  551. package/dist/transcript-tail.js +48 -0
  552. package/dist/vector-store.d.ts +27 -0
  553. package/dist/vector-store.js +210 -0
  554. package/dist/version.d.ts +2 -2
  555. package/dist/version.js +2 -2
  556. package/dist/working-memory.js +1 -1
  557. package/dist/yaml.js +36 -11
  558. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  559. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  560. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  561. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  566. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  570. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  571. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  572. package/dist-ui/index.html +3 -25
  573. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  574. package/extensions/openclaw-plugin/package.json +1 -1
  575. package/openclaw.plugin.json +1 -1
  576. package/package.json +1 -1
  577. package/dist/capture.d.ts +0 -155
  578. package/dist/capture.js +0 -1295
  579. package/dist/consolidate.d.ts +0 -58
  580. package/dist/consolidate.js +0 -1124
  581. package/dist/graph.d.ts +0 -245
  582. package/dist/hooks.d.ts +0 -208
  583. package/dist/hooks.js +0 -1076
  584. package/dist/importers.js +0 -900
  585. package/dist/predictions.js +0 -620
  586. package/dist/search.d.ts +0 -320
  587. package/dist/search.js +0 -970
  588. package/dist/store.d.ts +0 -776
  589. package/dist/store.js +0 -3473
  590. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  591. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  592. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  593. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
@@ -0,0 +1,312 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import { Layer } from '../memory.js';
4
+ import { dumpFrontmatter } from '../yaml.js';
5
+ import { getMeta } from '../db.js';
6
+ import { log } from '../log.js';
7
+ import { parseJsonArray, INDEX_VERSION, parseLastTraceId, MEMORY_SELECT_COLUMNS, rowToEntry, rowToMemoryConflict, } from './rows.js';
8
+ import { serializeEntry } from './markdown.js';
9
+ export function layerDir(root, layer) {
10
+ return path.join(root, layer);
11
+ }
12
+ export function ensureMirrorDirectories(hippoRoot) {
13
+ const dirs = [
14
+ hippoRoot,
15
+ path.join(hippoRoot, 'buffer'),
16
+ path.join(hippoRoot, 'episodic'),
17
+ path.join(hippoRoot, 'semantic'),
18
+ path.join(hippoRoot, 'conflicts'),
19
+ ];
20
+ for (const dir of dirs) {
21
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
22
+ }
23
+ }
24
+ // Tenant-scoped mirror file paths. The single-tenant 'default' deployment
25
+ // keeps the original `active-task.md` / `recent-session.md` filenames for
26
+ // on-disk back-compat; multi-tenant deployments get a `.<tenantId>` suffix
27
+ // so tenant B saving cannot overwrite tenant A's mirror file.
28
+ function activeTaskMirrorPath(hippoRoot, tenantId) {
29
+ const file = tenantId === 'default' ? 'active-task.md' : `active-task.${tenantId}.md`;
30
+ return path.join(hippoRoot, 'buffer', file);
31
+ }
32
+ function recentSessionMirrorPath(hippoRoot, tenantId) {
33
+ const file = tenantId === 'default' ? 'recent-session.md' : `recent-session.${tenantId}.md`;
34
+ return path.join(hippoRoot, 'buffer', file);
35
+ }
36
+ export function writeActiveTaskMirror(hippoRoot, tenantId, snapshot) {
37
+ const filePath = activeTaskMirrorPath(hippoRoot, tenantId);
38
+ const fm = dumpFrontmatter({
39
+ id: snapshot.id,
40
+ task: snapshot.task,
41
+ status: snapshot.status,
42
+ source: snapshot.source,
43
+ session_id: snapshot.session_id,
44
+ created_at: snapshot.created_at,
45
+ updated_at: snapshot.updated_at,
46
+ next_step: snapshot.next_step,
47
+ });
48
+ const body = [
49
+ `# Active Task Snapshot`,
50
+ '',
51
+ `## Summary`,
52
+ snapshot.summary,
53
+ '',
54
+ `## Next step`,
55
+ snapshot.next_step,
56
+ '',
57
+ `## Task`,
58
+ snapshot.task,
59
+ '',
60
+ ];
61
+ if (snapshot.session_id) {
62
+ body.push(`## Session`, snapshot.session_id, '');
63
+ }
64
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
65
+ fs.writeFileSync(filePath, `${fm}\n\n${body.join('\n')}`, 'utf8');
66
+ }
67
+ export function removeActiveTaskMirror(hippoRoot, tenantId) {
68
+ const filePath = activeTaskMirrorPath(hippoRoot, tenantId);
69
+ if (fs.existsSync(filePath)) {
70
+ fs.unlinkSync(filePath);
71
+ }
72
+ }
73
+ export function writeRecentSessionMirror(hippoRoot, tenantId, events) {
74
+ const filePath = recentSessionMirrorPath(hippoRoot, tenantId);
75
+ if (events.length === 0) {
76
+ if (fs.existsSync(filePath)) {
77
+ fs.unlinkSync(filePath);
78
+ }
79
+ return;
80
+ }
81
+ const latest = events[events.length - 1];
82
+ const fm = dumpFrontmatter({
83
+ session_id: latest.session_id,
84
+ task: latest.task,
85
+ event_count: events.length,
86
+ updated_at: latest.created_at,
87
+ });
88
+ const lines = [
89
+ '# Recent Session Trail',
90
+ '',
91
+ `- Session: ${latest.session_id}`,
92
+ `- Task: ${latest.task ?? 'n/a'}`,
93
+ `- Updated: ${latest.created_at}`,
94
+ '',
95
+ '## Events',
96
+ '',
97
+ ];
98
+ for (const event of events) {
99
+ lines.push(`- [${event.created_at}] (${event.event_type}) ${event.content}`);
100
+ }
101
+ lines.push('');
102
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
103
+ fs.writeFileSync(filePath, `${fm}\n\n${lines.join('\n')}`, 'utf8');
104
+ }
105
+ function writeConflictMirrors(hippoRoot, conflicts) {
106
+ const conflictDir = path.join(hippoRoot, 'conflicts');
107
+ fs.mkdirSync(conflictDir, { recursive: true });
108
+ const keep = new Set();
109
+ for (const conflict of conflicts) {
110
+ const filename = `conflict_${conflict.id}.md`;
111
+ keep.add(filename);
112
+ const fm = dumpFrontmatter({
113
+ id: conflict.id,
114
+ memory_a_id: conflict.memory_a_id,
115
+ memory_b_id: conflict.memory_b_id,
116
+ reason: conflict.reason,
117
+ score: Math.round(conflict.score * 10000) / 10000,
118
+ status: conflict.status,
119
+ detected_at: conflict.detected_at,
120
+ updated_at: conflict.updated_at,
121
+ });
122
+ const body = [
123
+ '# Memory Conflict',
124
+ '',
125
+ `- Memory A: ${conflict.memory_a_id}`,
126
+ `- Memory B: ${conflict.memory_b_id}`,
127
+ `- Reason: ${conflict.reason}`,
128
+ `- Score: ${conflict.score.toFixed(3)}`,
129
+ `- Status: ${conflict.status}`,
130
+ '',
131
+ ].join('\n');
132
+ fs.writeFileSync(path.join(conflictDir, filename), `${fm}\n\n${body}`, 'utf8');
133
+ }
134
+ for (const existing of fs.readdirSync(conflictDir)) {
135
+ if (existing === '.gitkeep')
136
+ continue;
137
+ if (!keep.has(existing)) {
138
+ fs.unlinkSync(path.join(conflictDir, existing));
139
+ }
140
+ }
141
+ }
142
+ export function writeMarkdownMirror(hippoRoot, entry) {
143
+ removeEntryMirrors(hippoRoot, entry.id);
144
+ const dir = layerDir(hippoRoot, entry.layer);
145
+ fs.mkdirSync(dir, { recursive: true });
146
+ fs.writeFileSync(path.join(dir, `${entry.id}.md`), serializeEntry(entry), 'utf8');
147
+ }
148
+ // AT1 P1 fix (codex): `writeMarkdownMirror` writes ANY layer's mirror,
149
+ // including `trace/<id>.md` for Layer.Trace rows (auto-promoted traces,
150
+ // consolidate.ts) — but this enumeration only walked
151
+ // Buffer/Episodic/Semantic. A rejected/forgotten trace row's markdown
152
+ // content survived on disk while the purge (and `hippo reject`/plain
153
+ // `forget`) reported success, and a stale trace mirror is exactly the
154
+ // resurrection channel bootstrapLegacyStore/rebuildIndex guard against.
155
+ // Fixes BOTH the AT1 reject-flow purge and the pre-existing plain-`forget`
156
+ // gap for trace rows (deleteEntry has always called this same function).
157
+ export function removeEntryMirrors(hippoRoot, id) {
158
+ for (const layer of [Layer.Buffer, Layer.Episodic, Layer.Semantic, Layer.Trace]) {
159
+ const file = path.join(layerDir(hippoRoot, layer), `${id}.md`);
160
+ if (fs.existsSync(file)) {
161
+ fs.unlinkSync(file);
162
+ }
163
+ }
164
+ }
165
+ /**
166
+ * AT1 mirror-purge honesty fix (docs/plans/2026-08-15-at1-rejected-value-tombstone.md):
167
+ * the candidate markdown mirror paths still on disk for `id`, computed the
168
+ * same way `removeEntryMirrors` walks them (one per layer: buffer/episodic/
169
+ * semantic), filtered to the ones that still `fs.existsSync`. Used to report
170
+ * an EXPLICIT path when a best-effort purge fails and no reaper exists to
171
+ * retry it — plain `removeEntryMirrors` returns void, giving no way to name
172
+ * which file is stuck.
173
+ */
174
+ export function getExistingEntryMirrorPaths(hippoRoot, id) {
175
+ // AT1 P1 fix (codex): same missing Layer.Trace as removeEntryMirrors above
176
+ // — kept in lockstep with it since this function's whole purpose is
177
+ // walking the mirror paths "the same way removeEntryMirrors walks them"
178
+ // (see its own doc comment).
179
+ return [Layer.Buffer, Layer.Episodic, Layer.Semantic, Layer.Trace]
180
+ .map((layer) => path.join(layerDir(hippoRoot, layer), `${id}.md`))
181
+ .filter((file) => fs.existsSync(file));
182
+ }
183
+ /**
184
+ * AT1 fix: best-effort markdown-mirror purge shared by `reject-flow.ts`'s
185
+ * `rejectValue` and `resolveConflict`'s post-commit purge. Both used to log
186
+ * "will retry via reaper on next open" for EVERY failure, but the reaper
187
+ * (`cleanupArchivedMirrors`, raw-archive-mirror-cleanup.ts) only scans
188
+ * `raw_archive` — that message was false for a non-raw id, which has no
189
+ * reaper at all.
190
+ *
191
+ * Retries the unlink once synchronously (the common real-world failure is a
192
+ * transient lock/AV-scanner false positive, not a permanent one). On a
193
+ * second failure: raw ids still get the honest reaper message (true); non-raw
194
+ * ids get the EXPLICIT leftover file path(s) and a manual-delete instruction,
195
+ * since nothing will ever retry them automatically.
196
+ *
197
+ * Returns true if the mirror ended up purged (first or second attempt).
198
+ */
199
+ export function purgeMirrorBestEffort(hippoRoot, id, isRaw, logPrefix) {
200
+ try {
201
+ removeEntryMirrors(hippoRoot, id);
202
+ return true;
203
+ }
204
+ catch {
205
+ try {
206
+ removeEntryMirrors(hippoRoot, id);
207
+ return true;
208
+ }
209
+ catch (secondErr) {
210
+ const msg = secondErr instanceof Error ? secondErr.message : String(secondErr);
211
+ if (isRaw) {
212
+ log.error(`${logPrefix}: mirror cleanup failed for ${id} (will retry via reaper on next open): ${msg}`);
213
+ }
214
+ else {
215
+ const leftover = getExistingEntryMirrorPaths(hippoRoot, id);
216
+ const pathsNote = leftover.length > 0 ? leftover.join(', ') : `${id}.md (path unresolved)`;
217
+ log.error(`${logPrefix}: mirror cleanup failed for ${id} - no automatic retry exists for this file, ` +
218
+ `delete it manually: ${pathsNote} (${msg})`);
219
+ }
220
+ return false;
221
+ }
222
+ }
223
+ }
224
+ /** Derive the current `HippoIndex` from SQLite. Exported for `rebuildIndex`
225
+ * (the only index.json writer) and the longmemeval benchmark. */
226
+ export function buildIndexFromDb(db) {
227
+ // SAFETY: rows' shape matches the seven columns named in the SELECT below.
228
+ const rows = db.prepare(`SELECT id, created, last_retrieved, strength, layer, tags_json, pinned FROM memories ORDER BY created ASC, id ASC`).all();
229
+ const entries = {};
230
+ for (const row of rows) {
231
+ // SAFETY: layer is only ever written from the Layer enum by this
232
+ // module's own INSERT/UPDATE paths.
233
+ const layer = row.layer;
234
+ entries[row.id] = {
235
+ id: row.id,
236
+ file: path.join(layer, `${row.id}.md`),
237
+ layer,
238
+ strength: Number(row.strength ?? 0),
239
+ tags: parseJsonArray(row.tags_json),
240
+ created: row.created,
241
+ last_retrieved: row.last_retrieved,
242
+ pinned: Boolean(row.pinned),
243
+ };
244
+ }
245
+ // LC1 codex round-2 med: the two lockstep keys must be read in ONE
246
+ // statement. Two autocommit SELECTs leave a window where a concurrent
247
+ // saveIndex (which commits both keys in one transaction) lands between
248
+ // them, handing the reader mismatched last_retrieval_ids / last_trace_id
249
+ // and re-opening the mislinkage hole saveIndex's BEGIN/COMMIT closed on
250
+ // the write side. One SELECT = one SQLite read snapshot.
251
+ // SAFETY: lockstepRows' shape matches the key/value columns named above.
252
+ const lockstepRows = db.prepare(`SELECT key, value FROM meta WHERE key IN ('last_retrieval_ids', 'last_trace_id')`).all();
253
+ const lockstep = new Map(lockstepRows.map((r) => [r.key, r.value]));
254
+ return {
255
+ version: INDEX_VERSION,
256
+ entries,
257
+ last_retrieval_ids: parseJsonArray(lockstep.get('last_retrieval_ids') ?? '[]'),
258
+ last_trace_id: parseLastTraceId(lockstep.get('last_trace_id') ?? ''),
259
+ };
260
+ }
261
+ export function buildStatsFromDb(db) {
262
+ // SAFETY: runs' shape matches the four columns named in the SELECT above.
263
+ const runs = db.prepare(`SELECT timestamp, decayed, merged, removed FROM consolidation_runs ORDER BY timestamp ASC, id ASC`).all();
264
+ return {
265
+ total_remembered: Number(getMeta(db, 'total_remembered', '0')),
266
+ total_recalled: Number(getMeta(db, 'total_recalled', '0')),
267
+ total_forgotten: Number(getMeta(db, 'total_forgotten', '0')),
268
+ consolidation_runs: runs.map((run) => ({
269
+ timestamp: run.timestamp,
270
+ decayed: run.decayed,
271
+ merged: run.merged,
272
+ removed: run.removed,
273
+ })),
274
+ };
275
+ }
276
+ /** Write the `index.json` mirror file for an already-derived index. Exported for
277
+ * `rebuildIndex` (the only index.json writer) and the longmemeval benchmark. */
278
+ export function writeIndexMirror(hippoRoot, index) {
279
+ mirrorBestEffort('index.json', () => fs.writeFileSync(path.join(hippoRoot, 'index.json'), JSON.stringify(index, null, 2), 'utf8'));
280
+ }
281
+ export function writeStatsMirror(hippoRoot, stats) {
282
+ mirrorBestEffort('stats.json', () => fs.writeFileSync(path.join(hippoRoot, 'stats.json'), JSON.stringify(stats, null, 2), 'utf8'));
283
+ }
284
+ /** Mirrors are derived from SQLite and written after COMMIT, so a failed write warns instead of failing a committed change. */
285
+ export function mirrorBestEffort(what, write) {
286
+ try {
287
+ write();
288
+ }
289
+ catch (err) {
290
+ log.warn(`${what} not refreshed (${err instanceof Error ? err.message : String(err)}); the database write succeeded`);
291
+ }
292
+ }
293
+ export function syncMirrorFiles(hippoRoot, db) {
294
+ // SAFETY: this query selects exactly MEMORY_SELECT_COLUMNS, matching
295
+ // MemoryRow's field set.
296
+ const entries = db.prepare(`SELECT ${MEMORY_SELECT_COLUMNS} FROM memories ORDER BY created ASC, id ASC`).all();
297
+ mirrorBestEffort('markdown mirrors', () => {
298
+ for (const entry of entries.map(rowToEntry))
299
+ writeMarkdownMirror(hippoRoot, entry);
300
+ });
301
+ // SAFETY: conflicts' shape matches the eight columns named in the SELECT
302
+ // above.
303
+ const conflicts = db.prepare(`
304
+ SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
305
+ FROM memory_conflicts
306
+ WHERE status = 'open'
307
+ ORDER BY updated_at DESC, id DESC
308
+ `).all();
309
+ mirrorBestEffort('conflict mirrors', () => writeConflictMirrors(hippoRoot, conflicts.map(rowToMemoryConflict)));
310
+ writeStatsMirror(hippoRoot, buildStatsFromDb(db));
311
+ }
312
+ //# sourceMappingURL=mirrors.js.map
@@ -0,0 +1,15 @@
1
+ import { type MemoryEntry } from '../memory.js';
2
+ import { type DatabaseSyncLike } from '../db.js';
3
+ import { type ResolveProjectIdentityOpts } from '../project-identity.js';
4
+ /** Nearest ancestor store like git; the strict join is the fallback so `hippo init` still creates `<cwd>/.hippo`. */
5
+ export declare function getHippoRoot(cwd?: string, opts?: ResolveProjectIdentityOpts): string;
6
+ export declare function isInitialized(hippoRoot: string): boolean;
7
+ export declare function initStore(hippoRoot: string): void;
8
+ /** One open connection with init done on it, for callers who used to pay for `initStore` + a second `openHippoDb`. */
9
+ export declare function openStore(hippoRoot: string): DatabaseSyncLike;
10
+ /** `meta` key holding the default half-life base a store's memories are on (src/half-life-migration.ts). */
11
+ export declare const HALF_LIFE_BASE_META_KEY = "default_half_life_base";
12
+ /** `meta` key set once no memory of a decision, incident or other object sits on the old flat 90 days. */
13
+ export declare const TYPED_HALF_LIFE_META_KEY = "typed_half_life_on_default";
14
+ export declare function loadLegacyEntriesFromMarkdown(hippoRoot: string): MemoryEntry[];
15
+ //# sourceMappingURL=open.d.ts.map
@@ -0,0 +1,223 @@
1
+ // Opens the SQLite store, the source of truth; Markdown and JSON files are human-readable mirrors of it.
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { DEFAULT_HALF_LIFE_DAYS, Layer } from '../memory.js';
5
+ import { closeHippoDb, openHippoDb, getMeta, setMeta } from '../db.js';
6
+ import { findHippoStoreDir, realpathOrResolve } from '../project-identity.js';
7
+ import { RejectedValueError } from '../rejection.js';
8
+ import { log } from '../log.js';
9
+ import { isPlainJsonObject } from './rows.js';
10
+ import { audit } from './audit-event.js';
11
+ import { deserializeEntry } from './markdown.js';
12
+ import { stampOriginProjectForImport, upsertEntryRow } from './entry-row.js';
13
+ import { ensureMirrorDirectories, syncMirrorFiles, layerDir } from './mirrors.js';
14
+ /** Nearest ancestor store like git; the strict join is the fallback so `hippo init` still creates `<cwd>/.hippo`. */
15
+ export function getHippoRoot(cwd = process.cwd(), opts) {
16
+ return findHippoStoreDir(cwd, opts) ?? path.join(realpathOrResolve(cwd), '.hippo');
17
+ }
18
+ export function isInitialized(hippoRoot) {
19
+ // A bare .hippo directory is not enough — autoInstallHooks /
20
+ // setupDailySchedule can create it without ever calling initStore,
21
+ // leaving a partial directory (integrations/, logs/, runs/) with no
22
+ // hippo.db. Returning true in that state caused `hippo init` to skip
23
+ // initStore and `hippo recall` to silently fall back to an empty store
24
+ // (incident 2026-04-26: ingest_direct.py against a bare .hippo).
25
+ // Treat the store as initialized only if hippo.db actually exists.
26
+ return fs.existsSync(path.join(hippoRoot, 'hippo.db'));
27
+ }
28
+ export function initStore(hippoRoot) {
29
+ closeHippoDb(openStore(hippoRoot));
30
+ }
31
+ /** One open connection with init done on it, for callers who used to pay for `initStore` + a second `openHippoDb`. */
32
+ export function openStore(hippoRoot) {
33
+ ensureMirrorDirectories(hippoRoot);
34
+ const db = openHippoDb(hippoRoot);
35
+ try {
36
+ const bootstrapped = bootstrapLegacyStore(db, hippoRoot);
37
+ if (bootstrapped) {
38
+ syncMirrorFiles(hippoRoot, db);
39
+ }
40
+ recordHalfLifeBaseForNewStore(db);
41
+ return db;
42
+ }
43
+ catch (error) {
44
+ try {
45
+ closeHippoDb(db);
46
+ }
47
+ catch {
48
+ // Best effort only; surface the original init error.
49
+ }
50
+ throw error;
51
+ }
52
+ }
53
+ /** `meta` key holding the default half-life base a store's memories are on (src/half-life-migration.ts). */
54
+ export const HALF_LIFE_BASE_META_KEY = 'default_half_life_base';
55
+ /** `meta` key set once no memory of a decision, incident or other object sits on the old flat 90 days. */
56
+ export const TYPED_HALF_LIFE_META_KEY = 'typed_half_life_on_default';
57
+ /**
58
+ * A store with no memories starts on the current default half-life base, so
59
+ * `hippo sleep` never migrates it. A store that already holds memories and
60
+ * no recorded base predates the record, and keeps reading as the legacy
61
+ * 7-day base until sleep migrates it.
62
+ */
63
+ function recordHalfLifeBaseForNewStore(db) {
64
+ if (getMeta(db, HALF_LIFE_BASE_META_KEY, '') !== '')
65
+ return;
66
+ if (db.prepare(`SELECT 1 AS x FROM memories LIMIT 1`).get() !== undefined)
67
+ return;
68
+ setMeta(db, HALF_LIFE_BASE_META_KEY, String(DEFAULT_HALF_LIFE_DAYS));
69
+ setMeta(db, TYPED_HALF_LIFE_META_KEY, '1');
70
+ }
71
+ function bootstrapLegacyStore(db, hippoRoot) {
72
+ // SAFETY: countRow's shape matches the single `COUNT(*) AS count` column
73
+ // selected above; `.get()` returns undefined only when no row exists.
74
+ const countRow = db.prepare(`SELECT COUNT(*) AS count FROM memories`).get();
75
+ const memoryCount = Number(countRow?.count ?? 0);
76
+ if (memoryCount > 0)
77
+ return false;
78
+ // AT1 P2 fix: memoryCount alone is not a reliable "already bootstrapped"
79
+ // signal once the rejection guard exists. If EVERY legacy mirror row is
80
+ // rejected, memories stays at 0 rows even after a successful bootstrap
81
+ // pass, so the memoryCount>0 gate above never trips — every subsequent
82
+ // initStore() call would re-run this whole function: re-scan the legacy
83
+ // mirrors, re-attempt (and re-refuse, re-auditing) every row, and
84
+ // re-INSERT the legacy consolidation_runs rows with no dedup, duplicating
85
+ // them on each open. A dedicated meta flag marks bootstrap as
86
+ // attempted-and-settled regardless of how many rows actually landed.
87
+ if (getMeta(db, 'legacy_bootstrap_completed', '0') === '1')
88
+ return false;
89
+ const legacyEntries = loadLegacyEntriesFromMarkdown(hippoRoot);
90
+ if (legacyEntries.length === 0)
91
+ return false;
92
+ db.exec('BEGIN');
93
+ try {
94
+ importLegacyEntries(db, hippoRoot, legacyEntries);
95
+ importLegacyIndexAndStats(db, hippoRoot);
96
+ // AT1 P2 fix: stamp completion regardless of how many rows actually
97
+ // landed (all-rejected included) — see the gate comment above.
98
+ setMeta(db, 'legacy_bootstrap_completed', '1');
99
+ db.exec('COMMIT');
100
+ }
101
+ catch (error) {
102
+ try {
103
+ db.exec('ROLLBACK');
104
+ }
105
+ catch { /* already rolled back; keep the original error */ }
106
+ throw error;
107
+ }
108
+ return true;
109
+ }
110
+ function importLegacyEntries(db, hippoRoot, legacyEntries) {
111
+ // AT1 (plan §3, round-3 redesign): run the guard LIVE per row rather
112
+ // than bypassing it. bootstrapLegacyStore is exactly the channel through
113
+ // which a stale/never-purged markdown mirror could resurrect a rejected
114
+ // value; a skip-and-count here closes that structurally, independent of
115
+ // mirror state. The refusal audit is written INLINE inside this
116
+ // still-open loop transaction (plain audit() — nothing is rolled back
117
+ // on a per-row skip, so the post-rollback auditRejectionRefusal helper
118
+ // is the wrong tool here).
119
+ let rejectedCount = 0;
120
+ for (const entry of legacyEntries) {
121
+ // v39: legacy markdown carries no origin_project; stamp from the store
122
+ // location so bootstrapped rows stay visible to ambient context.
123
+ const stamped = stampOriginProjectForImport(hippoRoot, entry);
124
+ try {
125
+ upsertEntryRow(db, stamped);
126
+ }
127
+ catch (err) {
128
+ if (err instanceof RejectedValueError) {
129
+ rejectedCount++;
130
+ audit(db, 'reject_refusal', err.entryId, { digest: err.digest, reason: err.reason }, 'cli', err.tenantId);
131
+ continue;
132
+ }
133
+ throw err;
134
+ }
135
+ }
136
+ if (rejectedCount > 0) {
137
+ log.warn(`bootstrapLegacyStore: skipped ${rejectedCount} rejected value(s) found in legacy mirrors`);
138
+ }
139
+ }
140
+ function importLegacyIndexAndStats(db, hippoRoot) {
141
+ const legacyIndex = loadLegacyIndexFile(hippoRoot);
142
+ setMeta(db, 'last_retrieval_ids', JSON.stringify(legacyIndex.last_retrieval_ids ?? []));
143
+ // LC1: legacy index.json predates last_trace_id, so this is '' for every
144
+ // pre-v40 store — harmless, matches the ensureMetaDefaults default.
145
+ // Coerce like its neighbors below coerce theirs (independent-review-critic
146
+ // LOW finding): accept only a clean digit string, else fall back to ''
147
+ // rather than trusting whatever a hand-edited/corrupt index.json carries.
148
+ const legacyTraceId = String(legacyIndex.last_trace_id ?? '');
149
+ setMeta(db, 'last_trace_id', /^\d+$/.test(legacyTraceId) ? legacyTraceId : '');
150
+ const legacyStats = loadLegacyStatsFile(hippoRoot);
151
+ setMeta(db, 'total_remembered', String(Number(legacyStats.total_remembered ?? 0)));
152
+ setMeta(db, 'total_recalled', String(Number(legacyStats.total_recalled ?? 0)));
153
+ setMeta(db, 'total_forgotten', String(Number(legacyStats.total_forgotten ?? 0)));
154
+ const runs = Array.isArray(legacyStats.consolidation_runs) ? legacyStats.consolidation_runs : [];
155
+ const insertRun = db.prepare(`INSERT INTO consolidation_runs(timestamp, decayed, merged, removed) VALUES (?, ?, ?, ?)`);
156
+ for (const run of runs) {
157
+ if (!isPlainJsonObject(run))
158
+ continue;
159
+ const row = run;
160
+ insertRun.run(String(row.timestamp ?? new Date().toISOString()), Number(row.decayed ?? 0), Number(row.merged ?? 0), Number(row.removed ?? 0));
161
+ }
162
+ }
163
+ export function loadLegacyEntriesFromMarkdown(hippoRoot) {
164
+ const entries = [];
165
+ for (const layer of [Layer.Buffer, Layer.Episodic, Layer.Semantic]) {
166
+ const dir = layerDir(hippoRoot, layer);
167
+ if (!fs.existsSync(dir))
168
+ continue;
169
+ for (const file of fs.readdirSync(dir)) {
170
+ if (!file.endsWith('.md'))
171
+ continue;
172
+ const raw = fs.readFileSync(path.join(dir, file), 'utf8');
173
+ const entry = deserializeEntry(raw);
174
+ if (entry)
175
+ entries.push(entry);
176
+ }
177
+ }
178
+ return entries;
179
+ }
180
+ function loadLegacyIndexFile(hippoRoot) {
181
+ const indexPath = path.join(hippoRoot, 'index.json');
182
+ if (!fs.existsSync(indexPath)) {
183
+ return { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
184
+ }
185
+ try {
186
+ // SAFETY: index.json is only ever written by writeIndexMirror below,
187
+ // which always serializes a HippoIndex; a hand-edited or corrupted file
188
+ // that violates the shape falls through to the catch block's fallback.
189
+ return JSON.parse(fs.readFileSync(indexPath, 'utf8'));
190
+ }
191
+ catch (err) {
192
+ log.debug(`store: unreadable index.json read as empty: ${err instanceof Error ? err.message : String(err)}`);
193
+ return { version: 1, entries: {}, last_retrieval_ids: [], last_trace_id: null };
194
+ }
195
+ }
196
+ function loadLegacyStatsFile(hippoRoot) {
197
+ const statsPath = path.join(hippoRoot, 'stats.json');
198
+ if (!fs.existsSync(statsPath)) {
199
+ return {
200
+ total_remembered: 0,
201
+ total_recalled: 0,
202
+ total_forgotten: 0,
203
+ consolidation_runs: [],
204
+ };
205
+ }
206
+ try {
207
+ // SAFETY: stats.json is only ever written by writeStatsMirror below,
208
+ // which always emits exactly these four fields; callers additionally
209
+ // guard every read with `?? 0` / `Array.isArray`, tolerating a
210
+ // hand-edited or corrupted file even if this optimistic cast is wrong.
211
+ return JSON.parse(fs.readFileSync(statsPath, 'utf8'));
212
+ }
213
+ catch (err) {
214
+ log.debug(`store: unreadable stats.json read as zero: ${err instanceof Error ? err.message : String(err)}`);
215
+ return {
216
+ total_remembered: 0,
217
+ total_recalled: 0,
218
+ total_forgotten: 0,
219
+ consolidation_runs: [],
220
+ };
221
+ }
222
+ }
223
+ //# sourceMappingURL=open.js.map