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,444 @@
1
+ import { closeHippoDb } from '../db.js';
2
+ import { rejectionDigest, insertRejectedValue, normalizeValueForRejection } from '../rejection.js';
3
+ import { archiveRawMemory } from '../raw-archive.js';
4
+ import { rowToMemoryConflict } from './rows.js';
5
+ import { audit } from './audit-event.js';
6
+ import { syncMirrorFiles, purgeMirrorBestEffort } from './mirrors.js';
7
+ import { openStore } from './open.js';
8
+ import { deleteEntryCore } from './delete-and-batch.js';
9
+ function canonicalConflictPair(aId, bId) {
10
+ return aId < bId
11
+ ? { memory_a_id: aId, memory_b_id: bId }
12
+ : { memory_a_id: bId, memory_b_id: aId };
13
+ }
14
+ export function listMemoryConflicts(hippoRoot, status = 'open', tenantId) {
15
+ const db = openStore(hippoRoot);
16
+ try {
17
+ // v0.28 — '*' is a sentinel meaning "no status filter, return all rows".
18
+ // Pre-v0.28 callers (cli/mcp/dashboard) always passed 'open' or default,
19
+ // so this sentinel is purely additive. The 4 SQL branches below cover
20
+ // {tenanted | unscoped} × {all-statuses | specific-status}.
21
+ const allStatuses = status === '*';
22
+ let rows;
23
+ if (tenantId !== undefined) {
24
+ // Tenanted query — JOIN to memories on both conflict members and require
25
+ // each in-tenant, so neither a normal cross-tenant pair nor a stale
26
+ // pre-fix row surfaces (consistent with resolveConflict).
27
+ // SAFETY: both branches select the same eight mc.* columns (aliased
28
+ // to MemoryConflictRow's field names) from memory_conflicts.
29
+ rows = allStatuses
30
+ ? db.prepare(`
31
+ SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score,
32
+ mc.status, mc.detected_at, mc.updated_at
33
+ FROM memory_conflicts mc
34
+ JOIN memories ma ON ma.id = mc.memory_a_id
35
+ JOIN memories mb ON mb.id = mc.memory_b_id
36
+ WHERE ma.tenant_id = ? AND mb.tenant_id = ?
37
+ ORDER BY mc.updated_at DESC, mc.id DESC
38
+ `).all(tenantId, tenantId)
39
+ : db.prepare(`
40
+ SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score,
41
+ mc.status, mc.detected_at, mc.updated_at
42
+ FROM memory_conflicts mc
43
+ JOIN memories ma ON ma.id = mc.memory_a_id
44
+ JOIN memories mb ON mb.id = mc.memory_b_id
45
+ WHERE mc.status = ? AND ma.tenant_id = ? AND mb.tenant_id = ?
46
+ ORDER BY mc.updated_at DESC, mc.id DESC
47
+ `).all(status, tenantId, tenantId);
48
+ }
49
+ else {
50
+ // Unscoped query — legacy direct-mode (CLI, tests, consolidate).
51
+ // SAFETY: both branches select the same eight columns matching
52
+ // MemoryConflictRow's field set.
53
+ rows = allStatuses
54
+ ? db.prepare(`
55
+ SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
56
+ FROM memory_conflicts
57
+ ORDER BY updated_at DESC, id DESC
58
+ `).all()
59
+ : db.prepare(`
60
+ SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
61
+ FROM memory_conflicts
62
+ WHERE status = ?
63
+ ORDER BY updated_at DESC, id DESC
64
+ `).all(status);
65
+ }
66
+ return rows.map(rowToMemoryConflict);
67
+ }
68
+ finally {
69
+ closeHippoDb(db);
70
+ }
71
+ }
72
+ export function replaceDetectedConflicts(hippoRoot, detected, detectedAt = new Date().toISOString()) {
73
+ const db = openStore(hippoRoot);
74
+ try {
75
+ db.exec('BEGIN');
76
+ const sameTenant = loadSameTenantCheck(db);
77
+ const canonicalDetected = detected.map((conflict) => ({
78
+ ...canonicalConflictPair(conflict.memory_a_id, conflict.memory_b_id),
79
+ reason: conflict.reason,
80
+ score: conflict.score,
81
+ }));
82
+ resolveStaleOpenConflicts(db, canonicalDetected, sameTenant, detectedAt);
83
+ upsertDetectedConflicts(db, canonicalDetected, sameTenant, detectedAt);
84
+ rebuildConflictsWithJson(db, sameTenant);
85
+ db.exec('COMMIT');
86
+ syncMirrorFiles(hippoRoot, db);
87
+ }
88
+ catch (error) {
89
+ try {
90
+ db.exec('ROLLBACK');
91
+ }
92
+ catch {
93
+ // Ignore nested rollback failures.
94
+ }
95
+ throw error;
96
+ }
97
+ finally {
98
+ closeHippoDb(db);
99
+ }
100
+ }
101
+ function loadSameTenantCheck(db) {
102
+ // Tenant guard (E2): a conflict is meaningful only within one tenant.
103
+ // Build id -> tenant_id once and skip cross-tenant pairs both when
104
+ // inserting rows and when rebuilding conflicts_with_json, so a stale
105
+ // cross-tenant row can neither persist nor leak a foreign id.
106
+ const tenantById = new Map();
107
+ // SAFETY: rows' shape matches the two columns named in the SELECT below.
108
+ for (const r of db.prepare(`SELECT id, tenant_id FROM memories`).all()) {
109
+ tenantById.set(r.id, r.tenant_id);
110
+ }
111
+ return (a, b) => {
112
+ const ta = tenantById.get(a);
113
+ const tb = tenantById.get(b);
114
+ return ta !== undefined && tb !== undefined && ta === tb;
115
+ };
116
+ }
117
+ function resolveStaleOpenConflicts(db, canonicalDetected, sameTenant, detectedAt) {
118
+ const detectedKeys = new Set(canonicalDetected.map((conflict) => `${conflict.memory_a_id}::${conflict.memory_b_id}`));
119
+ // SAFETY: openRows' shape matches the eight columns named in the SELECT
120
+ // above.
121
+ const openRows = db.prepare(`
122
+ SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
123
+ FROM memory_conflicts
124
+ WHERE status = 'open'
125
+ `).all();
126
+ for (const row of openRows) {
127
+ const key = `${row.memory_a_id}::${row.memory_b_id}`;
128
+ const stale = !detectedKeys.has(key);
129
+ // v1.11.0 residue: auto-resolve any open cross-tenant row. The insert
130
+ // loop below (line 2089) and the refMap rebuild (line 2117) skip
131
+ // cross-tenant pairs, but the resolve-stale loop previously left
132
+ // re-detected cross-tenant rows lingering status='open'. The
133
+ // sameTenant() helper is already built one block up; no extra query.
134
+ const crossTenant = !sameTenant(row.memory_a_id, row.memory_b_id);
135
+ if (stale || crossTenant) {
136
+ db.prepare(`UPDATE memory_conflicts SET status = 'resolved', updated_at = ? WHERE id = ?`).run(detectedAt, row.id);
137
+ }
138
+ }
139
+ }
140
+ function upsertDetectedConflicts(db, canonicalDetected, sameTenant, detectedAt) {
141
+ for (const conflict of canonicalDetected) {
142
+ // Skip cross-tenant pairs — never persist a conflict spanning tenants.
143
+ if (!sameTenant(conflict.memory_a_id, conflict.memory_b_id))
144
+ continue;
145
+ db.prepare(`
146
+ INSERT INTO memory_conflicts(memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at)
147
+ VALUES (?, ?, ?, ?, 'open', ?, ?)
148
+ ON CONFLICT(memory_a_id, memory_b_id) DO UPDATE SET
149
+ reason = excluded.reason,
150
+ score = excluded.score,
151
+ status = 'open',
152
+ updated_at = excluded.updated_at
153
+ `).run(conflict.memory_a_id, conflict.memory_b_id, conflict.reason, conflict.score, detectedAt, detectedAt);
154
+ }
155
+ }
156
+ function rebuildConflictsWithJson(db, sameTenant) {
157
+ // SAFETY: openConflicts' shape matches the two columns named above.
158
+ const openConflicts = db.prepare(`
159
+ SELECT memory_a_id, memory_b_id
160
+ FROM memory_conflicts
161
+ WHERE status = 'open'
162
+ `).all();
163
+ const refMap = new Map();
164
+ for (const row of openConflicts) {
165
+ // Skip cross-tenant pairs so a stale row never seeds a foreign id
166
+ // into conflicts_with_json.
167
+ if (!sameTenant(row.memory_a_id, row.memory_b_id))
168
+ continue;
169
+ if (!refMap.has(row.memory_a_id))
170
+ refMap.set(row.memory_a_id, new Set());
171
+ if (!refMap.has(row.memory_b_id))
172
+ refMap.set(row.memory_b_id, new Set());
173
+ refMap.get(row.memory_a_id).add(row.memory_b_id);
174
+ refMap.get(row.memory_b_id).add(row.memory_a_id);
175
+ }
176
+ // SAFETY: memoryRows' shape matches the single `id` column selected
177
+ // above.
178
+ const memoryRows = db.prepare(`SELECT id FROM memories`).all();
179
+ for (const memory of memoryRows) {
180
+ const refs = Array.from(refMap.get(memory.id) ?? []).sort();
181
+ db.prepare(`UPDATE memories SET conflicts_with_json = ?, updated_at = datetime('now') WHERE id = ?`).run(JSON.stringify(refs), memory.id);
182
+ }
183
+ }
184
+ /**
185
+ * Resolve a conflict by keeping one memory and weakening the other.
186
+ * Sets conflict status to 'resolved' and halves the loser's half-life.
187
+ * If --forget is used, the loser is removed entirely (kind-aware: raw rows
188
+ * are archived via archiveRawMemory, others deleted via deleteEntryCore —
189
+ * AT1 fix for the pre-existing crash where a raw loser aborted the whole
190
+ * resolve transaction against the append-only trigger). `opts.rejectLoserValue`
191
+ * additionally tombstones the loser's normalized digest so it cannot be
192
+ * re-asserted later.
193
+ *
194
+ * Every resolution path (weaken / forget / reject) emits a `conflict_resolve`
195
+ * audit row (AT1 — previously resolveConflict wrote zero audit rows on any path).
196
+ *
197
+ * Returns the resolved conflict, or null if not found.
198
+ */
199
+ export function resolveConflict(hippoRoot, conflictId, keepId, forgetLoser = false, tenantId, opts) {
200
+ const db = openStore(hippoRoot);
201
+ // When tenantId is set, the conflict lookup requires BOTH members in-tenant
202
+ // and every memories mutation carries AND tenant_id = ?. A cross-tenant probe
203
+ // then returns null, indistinguishable from a bad id. Omitted tenantId =
204
+ // legacy unscoped behaviour (CLI direct mode, tests, consolidate.ts).
205
+ const scope = {
206
+ memScope: tenantId !== undefined ? ' AND tenant_id = ?' : '',
207
+ memArgs: tenantId !== undefined ? [tenantId] : [],
208
+ };
209
+ try {
210
+ const row = selectConflictRow(db, conflictId, tenantId);
211
+ if (!row)
212
+ return null;
213
+ const conflict = rowToMemoryConflict(row);
214
+ if (conflict.status !== 'open')
215
+ return null;
216
+ const loserId = keepId === conflict.memory_a_id
217
+ ? conflict.memory_b_id
218
+ : keepId === conflict.memory_b_id
219
+ ? conflict.memory_a_id
220
+ : null;
221
+ if (!loserId)
222
+ return null;
223
+ db.exec('BEGIN');
224
+ // Mark conflict as resolved
225
+ db.prepare(`UPDATE memory_conflicts SET status = 'resolved', updated_at = datetime('now') WHERE id = ?`)
226
+ .run(conflictId);
227
+ const target = { conflictId, keepId, loserId, scope, opts };
228
+ const removeLoser = forgetLoser || opts?.rejectLoserValue === true;
229
+ const removal = removeLoser ? removeConflictLoser(db, target) : weakenConflictLoser(db, target);
230
+ stripConflictRefs(db, target, removal.loserRemoved);
231
+ auditConflictResolve(db, target, removal, tenantId);
232
+ db.exec('COMMIT');
233
+ syncMirrorFiles(hippoRoot, db);
234
+ if (removal.loserRemoved)
235
+ purgeRemovedLoserMirrors(hippoRoot, db, loserId, removal);
236
+ return { conflict: { ...conflict, status: 'resolved' }, loserId };
237
+ }
238
+ catch (error) {
239
+ try {
240
+ db.exec('ROLLBACK');
241
+ }
242
+ catch { /* ignore */ }
243
+ throw error;
244
+ }
245
+ finally {
246
+ closeHippoDb(db);
247
+ }
248
+ }
249
+ function selectConflictRow(db, conflictId, tenantId) {
250
+ // SAFETY: both branches select the same eight columns (aliased in the
251
+ // tenanted branch) matching MemoryConflictRow's field set.
252
+ return (tenantId !== undefined
253
+ ? db.prepare(`
254
+ SELECT mc.id, mc.memory_a_id, mc.memory_b_id, mc.reason, mc.score,
255
+ mc.status, mc.detected_at, mc.updated_at
256
+ FROM memory_conflicts mc
257
+ JOIN memories ma ON ma.id = mc.memory_a_id
258
+ JOIN memories mb ON mb.id = mc.memory_b_id
259
+ WHERE mc.id = ? AND ma.tenant_id = ? AND mb.tenant_id = ?
260
+ `).get(conflictId, tenantId, tenantId)
261
+ : db.prepare(`
262
+ SELECT id, memory_a_id, memory_b_id, reason, score, status, detected_at, updated_at
263
+ FROM memory_conflicts WHERE id = ?
264
+ `).get(conflictId));
265
+ }
266
+ function weakenConflictLoser(db, t) {
267
+ // Halve the loser's half-life (weakens it over time)
268
+ db.prepare(`UPDATE memories SET half_life_days = MAX(1, half_life_days / 2), updated_at = datetime('now') WHERE id = ?${t.scope.memScope}`)
269
+ .run(t.loserId, ...t.scope.memArgs);
270
+ return { loserRemoved: false, loserWasRaw: false, rejectedDigest: undefined, extraRemovedIds: [], extraRemovedRawIds: [] };
271
+ }
272
+ function removeConflictLoser(db, t) {
273
+ // AT1 (plan §5): removal (forgetLoser OR rejectLoserValue — a tombstoned
274
+ // value cannot be left live) is now kind-aware. The old bare
275
+ // `DELETE FROM memories WHERE id = ?` aborted the whole transaction when
276
+ // the loser was kind='raw' (append-only trigger fires); route through
277
+ // the same helpers the reject verb uses (both db-scoped, both compose
278
+ // inside this BEGIN/COMMIT). loserRemoved / loserWasRaw drive both the
279
+ // conflicts_with_json skip below and the post-commit mirror purge.
280
+ const removal = {
281
+ loserRemoved: false,
282
+ loserWasRaw: false,
283
+ rejectedDigest: undefined,
284
+ // AT1 P1 fix (codex): same-tenant duplicates of the loser's content that
285
+ // rejectLoserValue also removes (see below) — separate from loserId so
286
+ // the audit + post-commit mirror purge can cover ALL of them, not just
287
+ // loserId.
288
+ extraRemovedIds: [],
289
+ extraRemovedRawIds: [],
290
+ };
291
+ const { loserId, opts } = t;
292
+ // SAFETY: loserRow's shape matches the three columns named in the
293
+ // SELECT above.
294
+ const loserRow = db
295
+ .prepare(`SELECT kind, content, tenant_id FROM memories WHERE id = ?${t.scope.memScope}`)
296
+ .get(loserId, ...t.scope.memArgs);
297
+ if (loserRow) {
298
+ const actor = opts?.rejectedBy ?? 'cli';
299
+ const reason = opts?.reason ?? `resolveConflict ${t.conflictId}: kept ${t.keepId}`;
300
+ if (opts?.rejectLoserValue) {
301
+ removal.rejectedDigest = tombstoneLoserValue(db, t, loserRow, { actor, reason }, removal);
302
+ }
303
+ if (loserRow.kind === 'raw') {
304
+ archiveRawMemory(db, loserId, { reason, who: actor });
305
+ removal.loserWasRaw = true;
306
+ }
307
+ else {
308
+ deleteEntryCore(db, loserId, { actor, suppressForgetAudit: true });
309
+ }
310
+ removal.loserRemoved = true;
311
+ }
312
+ // loserRow undefined = tenant-scope mismatch (or already gone); matches
313
+ // the old tenant-scoped DELETE's silent 0-rows-affected behavior.
314
+ return removal;
315
+ }
316
+ /** Tombstones the loser's digest and removes its same-tenant duplicates into `removal`; returns the digest. */
317
+ function tombstoneLoserValue(db, t, loserRow, who, removal) {
318
+ const { actor, reason } = who;
319
+ const rejectedDigest = rejectionDigest(loserRow.content);
320
+ insertRejectedValue(db, {
321
+ tenantId: loserRow.tenant_id ?? 'default',
322
+ digest: rejectedDigest,
323
+ reason,
324
+ rejectedBy: actor,
325
+ rejectedAt: new Date().toISOString(),
326
+ sourceMemoryId: t.loserId,
327
+ normalizedChars: normalizeValueForRejection(loserRow.content).length,
328
+ });
329
+ // AT1 P1 fix (codex): reject-flow.ts's `rejectValue` removes ALL
330
+ // live same-tenant rows whose normalized digest matches, not just
331
+ // the one id passed — but this branch only ever removed loserId,
332
+ // leaving same-TENANT duplicates live while their shared content
333
+ // was tombstoned. Same O(N) scan pattern as reject-flow.ts (human-
334
+ // triggered command, tenant's row count is human-scale). CRITICAL
335
+ // BOUNDARY: tenant-scoped ONLY — tombstones are tenant-scoped by
336
+ // design, so a same-content row in ANOTHER tenant is legitimately
337
+ // live and must NOT be touched here. `keepId` is excluded even if
338
+ // its content coincidentally matches: the human explicitly chose
339
+ // to keep it in this same resolution, and this branch must not
340
+ // undo that choice in the same transaction.
341
+ const loserTenantId = loserRow.tenant_id ?? 'default';
342
+ // SAFETY: dupRows' shape matches the three columns named in the
343
+ // SELECT above.
344
+ const dupRows = db
345
+ .prepare(`SELECT id, kind, content FROM memories WHERE tenant_id = ? AND id != ? AND id != ?`)
346
+ .all(loserTenantId, t.loserId, t.keepId);
347
+ for (const dup of dupRows) {
348
+ if (rejectionDigest(dup.content) !== rejectedDigest)
349
+ continue;
350
+ if (dup.kind === 'raw') {
351
+ archiveRawMemory(db, dup.id, { reason, who: actor });
352
+ removal.extraRemovedRawIds.push(dup.id);
353
+ }
354
+ else {
355
+ deleteEntryCore(db, dup.id, { actor, suppressForgetAudit: true });
356
+ }
357
+ removal.extraRemovedIds.push(dup.id);
358
+ }
359
+ return rejectedDigest;
360
+ }
361
+ function stripConflictRefs(db, t, loserRemoved) {
362
+ const { memScope, memArgs } = t.scope;
363
+ const { keepId, loserId } = t;
364
+ // Clean up conflicts_with references
365
+ // SAFETY: keepRow's shape matches the single `conflicts_with_json`
366
+ // column selected above.
367
+ const keepRow = db.prepare(`SELECT conflicts_with_json FROM memories WHERE id = ?${memScope}`).get(keepId, ...memArgs);
368
+ if (keepRow) {
369
+ const refs = JSON.parse(keepRow.conflicts_with_json || '[]');
370
+ const cleaned = refs.filter((r) => r !== loserId);
371
+ db.prepare(`UPDATE memories SET conflicts_with_json = ?, updated_at = datetime('now') WHERE id = ?${memScope}`)
372
+ .run(JSON.stringify(cleaned), keepId, ...memArgs);
373
+ }
374
+ if (!loserRemoved) {
375
+ // SAFETY: loserRow's shape matches the single `conflicts_with_json`
376
+ // column named in the SELECT below.
377
+ const loserRow = db.prepare(`SELECT conflicts_with_json FROM memories WHERE id = ?${memScope}`).get(loserId, ...memArgs);
378
+ if (loserRow) {
379
+ const refs = JSON.parse(loserRow.conflicts_with_json || '[]');
380
+ const cleaned = refs.filter((r) => r !== keepId);
381
+ db.prepare(`UPDATE memories SET conflicts_with_json = ?, updated_at = datetime('now') WHERE id = ?${memScope}`)
382
+ .run(JSON.stringify(cleaned), loserId, ...memArgs);
383
+ }
384
+ }
385
+ }
386
+ function auditConflictResolve(db, t, removal, tenantId) {
387
+ const { loserRemoved, loserWasRaw, rejectedDigest, extraRemovedIds } = removal;
388
+ // AT1: the missing audit (plan §5 — resolveConflict wrote ZERO audit_log
389
+ // rows on any path before this). Every path — weaken, forget, reject —
390
+ // lands exactly one conflict_resolve row.
391
+ const conflictResolveMeta = {
392
+ conflictId: t.conflictId,
393
+ keepId: t.keepId,
394
+ loserId: t.loserId,
395
+ disposition: loserRemoved ? (loserWasRaw ? 'archived_raw' : 'deleted') : 'weakened',
396
+ rejected: Boolean(t.opts?.rejectLoserValue),
397
+ // AT1 P1 fix: every row this call removed, not just loserId — the
398
+ // same-tenant duplicate sweep above (extraRemovedIds) needs an
399
+ // audit trail too.
400
+ removedIds: loserRemoved ? [t.loserId, ...extraRemovedIds] : [],
401
+ };
402
+ // Assigned only when present so the serialized audit payload keeps
403
+ // omitting the key, exactly as the pre-migration object literal did.
404
+ if (rejectedDigest !== undefined)
405
+ conflictResolveMeta.rejectedDigest = rejectedDigest;
406
+ // Fresh spread literal: ConflictResolveMeta is a closed interface (no
407
+ // index signature) and isn't directly assignable to audit()'s
408
+ // Record<string, JsonValue> metadata param; a spread into a fresh
409
+ // object literal satisfies it without widening the declared type above.
410
+ audit(db, 'conflict_resolve', t.keepId, { ...conflictResolveMeta }, t.opts?.rejectedBy ?? 'cli', tenantId);
411
+ }
412
+ function purgeRemovedLoserMirrors(hippoRoot, db, loserId, removal) {
413
+ // AT1 P1b fix: mirror purge + reaper stamp for EVERY removed loser, not
414
+ // just the rejectLoserValue path. Pre-AT1, the plain forgetLoser path on
415
+ // a raw loser crashed outright (bare DELETE FROM memories hit the
416
+ // append-only trigger) — there is no legacy "successful forget, no
417
+ // purge" behavior to preserve for that case. Post-AT1's kind-aware
418
+ // removal (archiveRawMemory / deleteEntryCore above) makes plain
419
+ // --forget succeed on every kind, but until this fix the mirror was
420
+ // only purged when rejectLoserValue was ALSO set: a plain raw --forget
421
+ // left its markdown mirror orphaned (the reaper still catches it
422
+ // eventually, since archiveRawMemory's own raw_archive insert leaves
423
+ // mirror_cleaned_at NULL) and a plain non-raw --forget left its mirror
424
+ // orphaned FOREVER (no reaper exists for non-raw rows). Same post-commit
425
+ // purge+reaper pattern as the reject verb (src/reject-flow.ts) and
426
+ // api.archiveRaw — reusing removeEntryMirrors + raw_archive bookkeeping.
427
+ // AT1 P1 fix: loop over loserId AND every same-tenant duplicate the
428
+ // rejectLoserValue sweep above removed (extraRemovedIds) — previously
429
+ // only loserId's mirror was purged, leaving duplicate mirrors orphaned
430
+ // despite their rows being gone.
431
+ for (const removedId of [loserId, ...removal.extraRemovedIds]) {
432
+ const isRaw = removedId === loserId ? removal.loserWasRaw : removal.extraRemovedRawIds.includes(removedId);
433
+ // AT1 fix: purgeMirrorBestEffort retries once, then — for non-raw ids,
434
+ // which cleanupArchivedMirrors' reaper never scans — reports the
435
+ // EXPLICIT leftover path(s) instead of the false "will retry via
436
+ // reaper" claim. See its own doc comment (store.ts, near
437
+ // removeEntryMirrors) for the full rationale.
438
+ const mirrorOk = purgeMirrorBestEffort(hippoRoot, removedId, isRaw, 'resolveConflict');
439
+ if (mirrorOk && isRaw) {
440
+ db.prepare(`UPDATE raw_archive SET mirror_cleaned_at = ? WHERE memory_id = ?`).run(new Date().toISOString(), removedId);
441
+ }
442
+ }
443
+ }
444
+ //# sourceMappingURL=conflicts.js.map
@@ -0,0 +1,63 @@
1
+ import { type MemoryEntry } from '../memory.js';
2
+ import { openHippoDb } from '../db.js';
3
+ import { type DormantMove } from '../dormant.js';
4
+ /** Tables whose rows keep a first-class object's backing memory in `memory_id` (ON DELETE SET NULL); tests/dormant-memories.test.ts pins it to the schema. */
5
+ export declare const MEMORY_BACKED_TABLES: readonly ["predictions", "decisions", "incidents", "processes", "policies", "skills", "project_briefs", "customer_notes"];
6
+ /** Ids of memories that back a first-class object, for passes that plan deletes before making them. A table missing from an older schema is skipped. */
7
+ export declare function memoriesBackingObjects(hippoRoot: string): Set<string>;
8
+ /**
9
+ * AT1 (plan §4, round-2 fix, designed from source): db-scoped delete core.
10
+ * `deleteEntry` used to open+close its OWN connection, which meant it could
11
+ * never compose inside a caller's transaction (unlike writeEntry/
12
+ * writeEntryDbOnly, which already split this way). Split identically: row-
13
+ * meta SELECT, `DELETE FROM memories`, FTS delete, `forget` audit, DAG
14
+ * dirty-mark. NO filesystem I/O — the caller's own transaction may still be
15
+ * rolled back, and mirror writes must only happen post-commit.
16
+ *
17
+ * `opts.suppressForgetAudit` (default false, off): two AT1 callers set this
18
+ * so a removed non-raw row does NOT ALSO emit a `forget` row, because each
19
+ * already writes its own aggregate audit trail — `src/reject-flow.ts`'s
20
+ * `rejectValue` (single `reject_value` row covering every same-digest row
21
+ * removed) and `resolveConflict` (`conflict_resolve` row per resolution).
22
+ * Default keeps `deleteEntry` byte-identical to its pre-split behavior.
23
+ *
24
+ * Returns `{tenantId, dagParentId}` for the removed row, or `null` if no row with `id`
25
+ * existed or `automatic` refused it (pinned, raw, kept for good or backing an object at DELETE time, so a late pin wins).
26
+ */
27
+ export declare function deleteEntryCore(db: ReturnType<typeof openHippoDb>, id: string, opts?: {
28
+ actor?: string;
29
+ suppressForgetAudit?: boolean;
30
+ reason?: string;
31
+ automatic?: boolean;
32
+ }): {
33
+ tenantId: string;
34
+ dagParentId: string | null;
35
+ } | null;
36
+ /**
37
+ * Delete an entry from SQLite and mirrors.
38
+ *
39
+ * `opts.actor` defaults to 'cli'. The api.* layer threads `ctx.actor` so HTTP
40
+ * callers land with `api_key:<key_id>` in the audit log without a duplicate
41
+ * emit from the api wrapper.
42
+ *
43
+ * Thin wrapper over `deleteEntryCore` (open → core → mirrors → close);
44
+ * behavior is byte-identical to the pre-split implementation for every
45
+ * existing caller.
46
+ */
47
+ export declare function deleteEntry(hippoRoot: string, id: string, opts?: {
48
+ actor?: string;
49
+ reason?: string;
50
+ automatic?: boolean;
51
+ }): boolean;
52
+ /** Consolidation's flush, one transaction. With `snapshot` (rows as the caller loaded them), a write keeps only
53
+ * the fields the caller changed, takes the rest from the live row, and never resurrects a row that is gone.
54
+ *
55
+ * `dormant` (src/dormant.ts): each move's snapshot is inserted into `dormant_memories` and its `memories` row
56
+ * leaves exactly like a delete (FTS row, DAG parent dirty-mark, mirrors), in the same transaction, so a memory
57
+ * is never in both places or in neither. Deletes and moves both skip rows that are no longer auto-deletable
58
+ * (pinned, raw, kept for good or backing an object since the caller decided). Returns the ids that left `memories`, deleted or moved. */
59
+ export declare function batchWriteAndDelete(hippoRoot: string, toWrite: MemoryEntry[], toDeleteIds: string[], opts?: {
60
+ snapshot?: ReadonlyMap<string, MemoryEntry>;
61
+ dormant?: DormantMove[];
62
+ }): string[];
63
+ //# sourceMappingURL=delete-and-batch.d.ts.map