hippo-memory 1.70.0 → 1.71.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 (629) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-memories/claude-code.d.ts +4 -2
  3. package/dist/agent-memories/claude-code.js +14 -5
  4. package/dist/agent-memories/files.js +23 -12
  5. package/dist/agent-memories/markdown.d.ts +1 -3
  6. package/dist/agent-memories/markdown.js +1 -3
  7. package/dist/agent-memories/report.js +2 -1
  8. package/dist/agent-memories/sync.d.ts +4 -2
  9. package/dist/agent-memories/sync.js +10 -5
  10. package/dist/api/assemble.d.ts +7 -44
  11. package/dist/api/assemble.js +2 -22
  12. package/dist/api/audit.d.ts +5 -1
  13. package/dist/api/audit.js +9 -1
  14. package/dist/api/auth.d.ts +13 -22
  15. package/dist/api/auth.js +34 -24
  16. package/dist/api/auto-sleep.js +2 -2
  17. package/dist/api/availability.d.ts +2 -15
  18. package/dist/api/availability.js +2 -15
  19. package/dist/api/context-select.js +3 -4
  20. package/dist/api/context-types.d.ts +10 -35
  21. package/dist/api/context.d.ts +5 -22
  22. package/dist/api/context.js +21 -38
  23. package/dist/api/dormant.d.ts +5 -21
  24. package/dist/api/dormant.js +7 -26
  25. package/dist/api/drill-down.d.ts +7 -46
  26. package/dist/api/drill-down.js +5 -26
  27. package/dist/api/forget.d.ts +5 -24
  28. package/dist/api/forget.js +5 -28
  29. package/dist/api/graph.d.ts +8 -0
  30. package/dist/api/graph.js +7 -0
  31. package/dist/api/index.d.ts +2 -0
  32. package/dist/api/index.js +2 -0
  33. package/dist/api/instruction-detect.js +16 -5
  34. package/dist/api/ledger-db.d.ts +2 -1
  35. package/dist/api/ledger-db.js +5 -3
  36. package/dist/api/memories.d.ts +5 -0
  37. package/dist/api/memories.js +7 -0
  38. package/dist/api/objects.d.ts +9 -0
  39. package/dist/api/objects.js +11 -0
  40. package/dist/api/on-store.js +5 -3
  41. package/dist/api/predictions.d.ts +9 -0
  42. package/dist/api/predictions.js +18 -0
  43. package/dist/api/promote.d.ts +13 -17
  44. package/dist/api/promote.js +11 -19
  45. package/dist/api/prompt-hook.d.ts +4 -4
  46. package/dist/api/prompt-hook.js +10 -9
  47. package/dist/api/recall-cli.d.ts +55 -0
  48. package/dist/api/recall-cli.js +94 -0
  49. package/dist/api/recall-core.js +14 -6
  50. package/dist/api/recall-finish.d.ts +53 -0
  51. package/dist/api/recall-finish.js +30 -0
  52. package/dist/api/recall-history.d.ts +17 -84
  53. package/dist/api/recall-history.js +15 -88
  54. package/dist/api/recall-pipeline.d.ts +2 -3
  55. package/dist/api/recall-pipeline.js +16 -9
  56. package/dist/api/recall-types.d.ts +64 -304
  57. package/dist/api/recall.d.ts +5 -33
  58. package/dist/api/recall.js +59 -60
  59. package/dist/api/refine.d.ts +7 -0
  60. package/dist/api/refine.js +10 -0
  61. package/dist/api/remember-local.d.ts +57 -0
  62. package/dist/api/remember-local.js +90 -0
  63. package/dist/api/remember.d.ts +18 -1
  64. package/dist/api/remember.js +13 -1
  65. package/dist/api/sleep-run.d.ts +1 -3
  66. package/dist/api/sleep-run.js +17 -21
  67. package/dist/api/sleep.d.ts +9 -28
  68. package/dist/api/tokens.d.ts +3 -10
  69. package/dist/api/tokens.js +3 -10
  70. package/dist/api/types.d.ts +6 -29
  71. package/dist/api/types.js +4 -22
  72. package/dist/capture/command.d.ts +4 -12
  73. package/dist/capture/command.js +6 -22
  74. package/dist/capture/compact.d.ts +4 -15
  75. package/dist/capture/compact.js +16 -25
  76. package/dist/capture/compaction-record.js +101 -69
  77. package/dist/capture/compaction-spool.d.ts +1 -1
  78. package/dist/capture/compaction-spool.js +1 -1
  79. package/dist/capture/session-digest.d.ts +1 -1
  80. package/dist/capture/session-digest.js +13 -7
  81. package/dist/capture/transcript.d.ts +2 -10
  82. package/dist/capture/transcript.js +4 -18
  83. package/dist/cli/api-context.d.ts +3 -0
  84. package/dist/cli/api-context.js +6 -0
  85. package/dist/cli/audit-prune.d.ts +6 -39
  86. package/dist/cli/audit-prune.js +6 -39
  87. package/dist/cli/audit.d.ts +1 -1
  88. package/dist/cli/audit.js +33 -34
  89. package/dist/cli/auth.d.ts +2 -2
  90. package/dist/cli/auth.js +57 -39
  91. package/dist/cli/briefs.d.ts +4 -4
  92. package/dist/cli/briefs.js +18 -22
  93. package/dist/cli/card.d.ts +2 -2
  94. package/dist/cli/card.js +31 -32
  95. package/dist/cli/client.d.ts +7 -27
  96. package/dist/cli/client.js +24 -43
  97. package/dist/cli/compact-resume-payload.js +3 -2
  98. package/dist/cli/context.d.ts +1 -2
  99. package/dist/cli/context.js +12 -8
  100. package/dist/cli/continuity.d.ts +6 -6
  101. package/dist/cli/continuity.js +62 -64
  102. package/dist/cli/correction-latency.d.ts +2 -14
  103. package/dist/cli/correction-latency.js +2 -14
  104. package/dist/cli/curate.d.ts +13 -17
  105. package/dist/cli/curate.js +68 -92
  106. package/dist/cli/dag.d.ts +4 -4
  107. package/dist/cli/dag.js +33 -27
  108. package/dist/cli/decisions.d.ts +4 -4
  109. package/dist/cli/decisions.js +33 -47
  110. package/dist/cli/eval.js +15 -13
  111. package/dist/cli/exit.d.ts +6 -0
  112. package/dist/cli/exit.js +11 -0
  113. package/dist/cli/explain.d.ts +1 -2
  114. package/dist/cli/explain.js +6 -4
  115. package/dist/cli/flag-values.d.ts +6 -1
  116. package/dist/cli/flag-values.js +27 -10
  117. package/dist/cli/flags.d.ts +1 -0
  118. package/dist/cli/flags.js +1 -1
  119. package/dist/cli/github.d.ts +14 -0
  120. package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
  121. package/dist/cli/goals.d.ts +2 -2
  122. package/dist/cli/goals.js +46 -50
  123. package/dist/cli/hook-runtime.d.ts +9 -27
  124. package/dist/cli/hook-runtime.js +15 -31
  125. package/dist/cli/init.d.ts +2 -2
  126. package/dist/cli/init.js +6 -12
  127. package/dist/cli/install-steps.js +3 -12
  128. package/dist/cli/last-sleep.d.ts +2 -1
  129. package/dist/cli/last-sleep.js +3 -0
  130. package/dist/cli/maintenance.d.ts +4 -4
  131. package/dist/cli/maintenance.js +14 -19
  132. package/dist/cli/object-verbs.js +4 -3
  133. package/dist/cli/owner-validation.d.ts +5 -28
  134. package/dist/cli/owner-validation.js +5 -28
  135. package/dist/cli/playbooks.d.ts +4 -4
  136. package/dist/cli/playbooks.js +23 -28
  137. package/dist/cli/print.d.ts +2 -5
  138. package/dist/cli/print.js +1 -4
  139. package/dist/cli/projects.d.ts +2 -2
  140. package/dist/cli/projects.js +1 -3
  141. package/dist/cli/provenance-coverage.d.ts +2 -6
  142. package/dist/cli/provenance-coverage.js +2 -6
  143. package/dist/cli/quality-repair-once.js +2 -2
  144. package/dist/cli/recall.d.ts +2 -4
  145. package/dist/cli/recall.js +55 -131
  146. package/dist/cli/refine-llm.d.ts +5 -31
  147. package/dist/cli/refine-llm.js +9 -36
  148. package/dist/cli/remember.d.ts +3 -3
  149. package/dist/cli/remember.js +122 -180
  150. package/dist/cli/scheduler.d.ts +2 -17
  151. package/dist/cli/scheduler.js +12 -18
  152. package/dist/cli/serve.js +21 -12
  153. package/dist/cli/session-hooks.d.ts +10 -18
  154. package/dist/cli/session-hooks.js +112 -113
  155. package/dist/cli/setup.d.ts +4 -4
  156. package/dist/cli/setup.js +19 -21
  157. package/dist/cli/shared.d.ts +9 -23
  158. package/dist/cli/shared.js +9 -32
  159. package/dist/cli/slack.d.ts +2 -2
  160. package/dist/cli/slack.js +19 -23
  161. package/dist/cli/sleep.d.ts +3 -2
  162. package/dist/cli/sleep.js +15 -16
  163. package/dist/cli/status.d.ts +9 -12
  164. package/dist/cli/status.js +55 -98
  165. package/dist/cli/stdin.d.ts +4 -6
  166. package/dist/cli/stdin.js +2 -3
  167. package/dist/cli/transfer.d.ts +9 -9
  168. package/dist/cli/transfer.js +66 -89
  169. package/dist/cli/usage.js +11 -5
  170. package/dist/cli.d.ts +66 -448
  171. package/dist/cli.js +87 -263
  172. package/dist/connectors/github/backfill.d.ts +5 -25
  173. package/dist/connectors/github/backfill.js +14 -49
  174. package/dist/connectors/github/deletion.d.ts +4 -18
  175. package/dist/connectors/github/deletion.js +2 -15
  176. package/dist/connectors/github/dlq.d.ts +8 -33
  177. package/dist/connectors/github/dlq.js +12 -29
  178. package/dist/connectors/github/ingest.d.ts +2 -6
  179. package/dist/connectors/github/ingest.js +4 -10
  180. package/dist/connectors/github/octokit-client.d.ts +4 -16
  181. package/dist/connectors/github/octokit-client.js +27 -24
  182. package/dist/connectors/github/ratelimit.d.ts +3 -14
  183. package/dist/connectors/github/ratelimit.js +3 -14
  184. package/dist/connectors/github/scope.d.ts +3 -5
  185. package/dist/connectors/github/scope.js +3 -5
  186. package/dist/connectors/github/signature.d.ts +4 -26
  187. package/dist/connectors/github/signature.js +4 -26
  188. package/dist/connectors/github/tenant-routing.d.ts +2 -24
  189. package/dist/connectors/github/tenant-routing.js +4 -26
  190. package/dist/connectors/github/transform.js +2 -16
  191. package/dist/connectors/github/types.d.ts +3 -15
  192. package/dist/connectors/github/types.js +2 -9
  193. package/dist/connectors/github/webhook.d.ts +2 -16
  194. package/dist/connectors/github/webhook.js +6 -22
  195. package/dist/connectors/slack/backfill.d.ts +4 -17
  196. package/dist/connectors/slack/backfill.js +4 -13
  197. package/dist/connectors/slack/dlq.d.ts +2 -19
  198. package/dist/connectors/slack/dlq.js +2 -19
  199. package/dist/connectors/slack/ingest.d.ts +2 -3
  200. package/dist/connectors/slack/ingest.js +2 -3
  201. package/dist/connectors/slack/scope.d.ts +2 -8
  202. package/dist/connectors/slack/scope.js +2 -8
  203. package/dist/connectors/slack/signature.d.ts +1 -6
  204. package/dist/connectors/slack/tenant-routing.d.ts +2 -19
  205. package/dist/connectors/slack/tenant-routing.js +2 -21
  206. package/dist/connectors/slack/transform.d.ts +2 -18
  207. package/dist/connectors/slack/transform.js +2 -18
  208. package/dist/connectors/slack/types.d.ts +3 -9
  209. package/dist/connectors/slack/types.js +2 -4
  210. package/dist/connectors/slack/web-client.js +33 -27
  211. package/dist/connectors/slack/webhook.d.ts +2 -19
  212. package/dist/connectors/slack/webhook.js +5 -26
  213. package/dist/connectors/slack/workspaces.d.ts +4 -24
  214. package/dist/connectors/slack/workspaces.js +4 -24
  215. package/dist/consolidate/conflicts.js +6 -14
  216. package/dist/consolidate/dag-summary.d.ts +8 -0
  217. package/dist/consolidate/dag-summary.js +41 -0
  218. package/dist/consolidate/dag.d.ts +5 -28
  219. package/dist/consolidate/dag.js +14 -75
  220. package/dist/consolidate/decay.js +7 -19
  221. package/dist/consolidate/dedupe.d.ts +6 -52
  222. package/dist/consolidate/dedupe.js +13 -71
  223. package/dist/consolidate/flush-units.d.ts +3 -4
  224. package/dist/consolidate/flush-units.js +3 -3
  225. package/dist/consolidate/half-life-migration.d.ts +3 -26
  226. package/dist/consolidate/half-life-migration.js +11 -28
  227. package/dist/consolidate/llm-passes.js +4 -21
  228. package/dist/consolidate/memory-value-weights.d.ts +2 -13
  229. package/dist/consolidate/memory-value-weights.js +2 -13
  230. package/dist/consolidate/memory-value.d.ts +11 -84
  231. package/dist/consolidate/memory-value.js +16 -104
  232. package/dist/consolidate/merge.js +10 -31
  233. package/dist/consolidate/merged-row.js +2 -1
  234. package/dist/consolidate/physics-pass.js +1 -3
  235. package/dist/consolidate/replay.d.ts +6 -38
  236. package/dist/consolidate/replay.js +14 -52
  237. package/dist/consolidate/run.js +1 -1
  238. package/dist/consolidate/sleep.d.ts +1 -8
  239. package/dist/consolidate/sleep.js +5 -17
  240. package/dist/consolidate/trace.d.ts +3 -18
  241. package/dist/consolidate/trace.js +3 -18
  242. package/dist/consolidate/traces.js +6 -22
  243. package/dist/core/ablation.d.ts +4 -91
  244. package/dist/core/ablation.js +4 -91
  245. package/dist/core/ambient.d.ts +1 -8
  246. package/dist/core/ambient.js +1 -8
  247. package/dist/core/capture-contract.d.ts +4 -2
  248. package/dist/core/capture-contract.js +4 -2
  249. package/dist/core/card.d.ts +4 -1
  250. package/dist/core/card.js +8 -0
  251. package/dist/core/compare.d.ts +11 -67
  252. package/dist/core/compare.js +9 -63
  253. package/dist/core/config.d.ts +10 -24
  254. package/dist/core/config.js +13 -14
  255. package/dist/core/handoff.d.ts +1 -7
  256. package/dist/core/handoff.js +1 -7
  257. package/dist/core/memory-quality.js +1 -1
  258. package/dist/core/memory.d.ts +41 -164
  259. package/dist/core/memory.js +51 -221
  260. package/dist/core/package-root.d.ts +3 -0
  261. package/dist/core/package-root.js +5 -0
  262. package/dist/core/physics-config.d.ts +1 -4
  263. package/dist/core/physics-config.js +3 -8
  264. package/dist/core/physics.d.ts +15 -61
  265. package/dist/core/physics.js +59 -122
  266. package/dist/core/project-identity.d.ts +17 -58
  267. package/dist/core/project-identity.js +17 -38
  268. package/dist/core/project-remote.js +13 -2
  269. package/dist/core/raw-append-only.d.ts +5 -0
  270. package/dist/core/raw-append-only.js +7 -0
  271. package/dist/core/salience.d.ts +1 -7
  272. package/dist/core/salience.js +1 -7
  273. package/dist/dashboard/dashboard-actions.js +2 -2
  274. package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
  275. package/dist/dashboard/dashboard-snapshot.js +11 -2
  276. package/dist/dashboard/dashboard-types.d.ts +2 -1
  277. package/dist/dashboard/dashboard.d.ts +1 -0
  278. package/dist/dashboard/dashboard.js +50 -4
  279. package/dist/db/busy.d.ts +1 -1
  280. package/dist/db/busy.js +17 -8
  281. package/dist/db/connect.d.ts +1 -0
  282. package/dist/db/connect.js +3 -3
  283. package/dist/db/migrate.js +3 -3
  284. package/dist/db/migrations/types.d.ts +2 -5
  285. package/dist/db/migrations/v14.js +2 -3
  286. package/dist/db/migrations/v15.js +2 -8
  287. package/dist/db/migrations/v16.js +2 -3
  288. package/dist/db/migrations/v17.js +2 -3
  289. package/dist/db/migrations/v19.js +2 -5
  290. package/dist/db/migrations/v20.js +2 -7
  291. package/dist/db/migrations/v22.js +4 -17
  292. package/dist/db/migrations/v23.js +3 -14
  293. package/dist/db/migrations/v24.js +2 -4
  294. package/dist/db/migrations/v25.js +3 -8
  295. package/dist/db/migrations/v26.js +2 -13
  296. package/dist/db/migrations/v27.js +3 -11
  297. package/dist/db/migrations/v28.js +2 -14
  298. package/dist/db/migrations/v29.js +4 -18
  299. package/dist/db/migrations/v30.js +4 -16
  300. package/dist/db/migrations/v31.js +2 -15
  301. package/dist/db/migrations/v32.js +4 -22
  302. package/dist/db/migrations/v33.js +2 -15
  303. package/dist/db/migrations/v34.js +2 -11
  304. package/dist/db/migrations/v35.js +2 -11
  305. package/dist/db/migrations/v36.js +2 -11
  306. package/dist/db/migrations/v37.js +8 -33
  307. package/dist/db/migrations/v38.js +5 -38
  308. package/dist/db/migrations/v39.js +9 -20
  309. package/dist/db/migrations/v40.js +2 -9
  310. package/dist/db/migrations/v41.js +2 -24
  311. package/dist/db/migrations/v43.js +1 -1
  312. package/dist/db/migrations/v44.js +2 -8
  313. package/dist/db/migrations/v45.js +2 -7
  314. package/dist/db/migrations/v47.js +2 -3
  315. package/dist/db/migrations/v51.js +1 -1
  316. package/dist/db/open.d.ts +2 -0
  317. package/dist/db/open.js +17 -1
  318. package/dist/db/physics-state.d.ts +6 -22
  319. package/dist/db/physics-state.js +25 -36
  320. package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
  321. package/dist/db/raw-archive-mirror-cleanup.js +2 -17
  322. package/dist/db/vector-store.d.ts +2 -0
  323. package/dist/db/vector-store.js +8 -1
  324. package/dist/doctor.js +74 -19
  325. package/dist/entry/session-text.js +2 -1
  326. package/dist/eval/eval-stats.d.ts +15 -53
  327. package/dist/eval/eval-stats.js +12 -42
  328. package/dist/eval/eval-suite.d.ts +2 -13
  329. package/dist/eval/eval-suite.js +74 -34
  330. package/dist/eval/eval.d.ts +6 -24
  331. package/dist/eval/eval.js +7 -34
  332. package/dist/eval/judgment.d.ts +0 -3
  333. package/dist/eval/judgment.js +19 -11
  334. package/dist/extensions/openclaw-plugin/index.js +1 -1
  335. package/dist/graph/extract.d.ts +5 -27
  336. package/dist/graph/extract.js +7 -33
  337. package/dist/graph/recall.d.ts +7 -20
  338. package/dist/graph/recall.js +14 -76
  339. package/dist/graph/stream.d.ts +7 -39
  340. package/dist/graph/stream.js +11 -34
  341. package/dist/graph/view.d.ts +9 -35
  342. package/dist/graph/view.js +11 -39
  343. package/dist/hooks/codex-wrapper.js +2 -2
  344. package/dist/hooks/copilot.js +2 -1
  345. package/dist/hooks/hook-blocks.d.ts +6 -2
  346. package/dist/hooks/hook-blocks.js +37 -124
  347. package/dist/hooks/json-hooks.d.ts +4 -36
  348. package/dist/hooks/json-hooks.js +18 -57
  349. package/dist/hooks/opencode.d.ts +0 -38
  350. package/dist/hooks/opencode.js +9 -76
  351. package/dist/hooks/shared.d.ts +8 -17
  352. package/dist/hooks/shared.js +29 -20
  353. package/dist/importers/core.d.ts +12 -37
  354. package/dist/importers/core.js +9 -27
  355. package/dist/importers/markdown-parse.d.ts +8 -22
  356. package/dist/importers/markdown-parse.js +8 -25
  357. package/dist/importers/markdown.js +3 -12
  358. package/dist/importers/sources.js +7 -35
  359. package/dist/importers/vault.d.ts +2 -8
  360. package/dist/importers/vault.js +25 -81
  361. package/dist/index.d.ts +6 -2
  362. package/dist/index.js +6 -2
  363. package/dist/learn/autolearn.d.ts +14 -41
  364. package/dist/learn/autolearn.js +14 -41
  365. package/dist/learn/extract.js +2 -4
  366. package/dist/learn/forward-claim-detector.d.ts +6 -30
  367. package/dist/learn/forward-claim-detector.js +14 -66
  368. package/dist/learn/invalidation.d.ts +6 -18
  369. package/dist/learn/invalidation.js +9 -26
  370. package/dist/mcp/admin-tools.js +3 -5
  371. package/dist/mcp/memory-tools.js +4 -9
  372. package/dist/mcp/protocol.d.ts +8 -26
  373. package/dist/mcp/protocol.js +3 -6
  374. package/dist/mcp/recall-tools.js +3 -3
  375. package/dist/mcp/request.d.ts +3 -11
  376. package/dist/mcp/request.js +10 -26
  377. package/dist/mcp/server.d.ts +3 -9
  378. package/dist/mcp/server.js +5 -16
  379. package/dist/mcp/session-state.d.ts +1 -1
  380. package/dist/mcp/session-state.js +5 -11
  381. package/dist/mcp/stdio.d.ts +2 -6
  382. package/dist/mcp/stdio.js +48 -12
  383. package/dist/mcp/tools.js +5 -3
  384. package/dist/objects/customer-notes.d.ts +7 -42
  385. package/dist/objects/customer-notes.js +7 -48
  386. package/dist/objects/decisions.d.ts +12 -50
  387. package/dist/objects/decisions.js +15 -53
  388. package/dist/objects/incidents.d.ts +7 -38
  389. package/dist/objects/incidents.js +7 -41
  390. package/dist/objects/policies.d.ts +11 -89
  391. package/dist/objects/policies.js +11 -98
  392. package/dist/objects/processes.d.ts +7 -52
  393. package/dist/objects/processes.js +7 -61
  394. package/dist/objects/project-briefs.d.ts +11 -55
  395. package/dist/objects/project-briefs.js +14 -75
  396. package/dist/objects/skills.d.ts +7 -42
  397. package/dist/objects/skills.js +8 -54
  398. package/dist/postinstall.js +6 -19
  399. package/dist/predictions/planning-fallacy.d.ts +11 -34
  400. package/dist/rerankers/clef.js +3 -31
  401. package/dist/rerankers/cross-encoder.js +4 -6
  402. package/dist/rerankers/jev.js +9 -6
  403. package/dist/rerankers/llm.d.ts +2 -11
  404. package/dist/rerankers/llm.js +14 -14
  405. package/dist/rerankers/outage-warning.d.ts +2 -1
  406. package/dist/rerankers/outage-warning.js +2 -1
  407. package/dist/rerankers/remote.d.ts +1 -0
  408. package/dist/rerankers/remote.js +2 -0
  409. package/dist/rerankers/types.d.ts +2 -14
  410. package/dist/search/boosts.d.ts +0 -2
  411. package/dist/search/boosts.js +2 -2
  412. package/dist/search/goal-boost.d.ts +23 -0
  413. package/dist/search/goal-boost.js +90 -0
  414. package/dist/search/hybrid.d.ts +2 -0
  415. package/dist/search/multihop.js +2 -3
  416. package/dist/search/path-context.d.ts +5 -18
  417. package/dist/search/path-context.js +5 -18
  418. package/dist/search/physics-search.js +11 -8
  419. package/dist/search/rrf.d.ts +7 -35
  420. package/dist/search/rrf.js +5 -30
  421. package/dist/search/vector.d.ts +7 -0
  422. package/dist/search/vector.js +35 -5
  423. package/dist/server/auth.d.ts +9 -28
  424. package/dist/server/auth.js +32 -25
  425. package/dist/server/boot.d.ts +2 -21
  426. package/dist/server/boot.js +63 -96
  427. package/dist/server/client-ip.d.ts +3 -19
  428. package/dist/server/client-ip.js +5 -28
  429. package/dist/server/defaults.d.ts +3 -0
  430. package/dist/server/defaults.js +4 -0
  431. package/dist/server/key-check-bounds.d.ts +2 -1
  432. package/dist/server/lifecycle.d.ts +5 -4
  433. package/dist/server/lifecycle.js +19 -4
  434. package/dist/server/mcp-http.js +10 -44
  435. package/dist/server/rate-limit.d.ts +5 -18
  436. package/dist/server/rate-limit.js +4 -13
  437. package/dist/server/request.d.ts +4 -8
  438. package/dist/server/request.js +9 -17
  439. package/dist/server/route-table.js +42 -49
  440. package/dist/server/routes/admin.js +22 -28
  441. package/dist/server/routes/customer-notes.js +7 -12
  442. package/dist/server/routes/decisions.js +10 -17
  443. package/dist/server/routes/incidents.js +12 -20
  444. package/dist/server/routes/memories.js +12 -32
  445. package/dist/server/routes/object-routes.d.ts +0 -5
  446. package/dist/server/routes/object-routes.js +7 -15
  447. package/dist/server/routes/policies.js +10 -18
  448. package/dist/server/routes/predictions.js +13 -25
  449. package/dist/server/routes/processes.js +16 -26
  450. package/dist/server/routes/project-briefs.js +9 -16
  451. package/dist/server/routes/recall.js +10 -35
  452. package/dist/server/routes/skills.js +8 -18
  453. package/dist/server/server-detect.d.ts +9 -53
  454. package/dist/server/server-detect.js +24 -90
  455. package/dist/server/sleep-offload.js +4 -1
  456. package/dist/server/types.d.ts +12 -10
  457. package/dist/server/validation.d.ts +3 -1
  458. package/dist/server/validation.js +10 -23
  459. package/dist/server.d.ts +2 -2
  460. package/dist/server.js +3 -2
  461. package/dist/sharing/global-store.d.ts +19 -0
  462. package/dist/sharing/global-store.js +75 -0
  463. package/dist/sharing/global-sync.d.ts +6 -0
  464. package/dist/sharing/global-sync.js +80 -0
  465. package/dist/sharing/project-merge.d.ts +4 -5
  466. package/dist/sharing/project-merge.js +9 -7
  467. package/dist/sharing/scope.d.ts +4 -11
  468. package/dist/sharing/scope.js +4 -11
  469. package/dist/sharing/search-both.d.ts +60 -0
  470. package/dist/sharing/search-both.js +138 -0
  471. package/dist/sharing/share.d.ts +38 -0
  472. package/dist/sharing/share.js +226 -0
  473. package/dist/store/ambient.js +4 -9
  474. package/dist/store/audit-event.d.ts +4 -12
  475. package/dist/store/audit-event.js +4 -12
  476. package/dist/store/audit.d.ts +2 -5
  477. package/dist/store/audit.js +4 -12
  478. package/dist/store/auth.d.ts +6 -6
  479. package/dist/store/auth.js +10 -9
  480. package/dist/store/candidates.d.ts +20 -3
  481. package/dist/store/candidates.js +77 -48
  482. package/dist/store/card-detail.d.ts +2 -1
  483. package/dist/store/card-detail.js +2 -1
  484. package/dist/store/cards.d.ts +14 -9
  485. package/dist/store/cards.js +72 -126
  486. package/dist/store/conflicts.d.ts +4 -21
  487. package/dist/store/conflicts.js +71 -150
  488. package/dist/store/connectors/github.d.ts +10 -10
  489. package/dist/store/connectors/github.js +10 -10
  490. package/dist/store/dashboard-reads.js +4 -8
  491. package/dist/store/delete-and-batch.d.ts +11 -31
  492. package/dist/store/delete-and-batch.js +48 -64
  493. package/dist/store/delivery-recorder.d.ts +8 -4
  494. package/dist/store/delivery-recorder.js +25 -15
  495. package/dist/store/diagnostics.js +6 -13
  496. package/dist/store/dormant.d.ts +7 -29
  497. package/dist/store/dormant.js +15 -56
  498. package/dist/store/embeddings/index.d.ts +11 -80
  499. package/dist/store/embeddings/index.js +71 -207
  500. package/dist/store/embeddings/local.js +15 -32
  501. package/dist/store/embeddings/provider.d.ts +16 -53
  502. package/dist/store/embeddings/provider.js +41 -69
  503. package/dist/store/entry-reads.d.ts +21 -57
  504. package/dist/store/entry-reads.js +65 -126
  505. package/dist/store/entry-row.d.ts +6 -35
  506. package/dist/store/entry-row.js +9 -37
  507. package/dist/store/entry-writes.d.ts +10 -16
  508. package/dist/store/entry-writes.js +17 -35
  509. package/dist/store/goals.d.ts +3 -40
  510. package/dist/store/goals.js +21 -160
  511. package/dist/store/graph-queue.d.ts +6 -22
  512. package/dist/store/graph-queue.js +14 -45
  513. package/dist/store/graph-reads.d.ts +11 -35
  514. package/dist/store/graph-reads.js +20 -58
  515. package/dist/store/graph-rows.d.ts +3 -6
  516. package/dist/store/graph-rows.js +6 -9
  517. package/dist/store/graph-view-rows.d.ts +2 -1
  518. package/dist/store/graph-view-rows.js +2 -1
  519. package/dist/store/graph-writes.d.ts +6 -31
  520. package/dist/store/graph-writes.js +13 -37
  521. package/dist/store/half-life.d.ts +2 -1
  522. package/dist/store/half-life.js +14 -16
  523. package/dist/store/handoffs.d.ts +5 -11
  524. package/dist/store/handoffs.js +16 -34
  525. package/dist/store/index-and-stats.d.ts +6 -19
  526. package/dist/store/index-and-stats.js +34 -82
  527. package/dist/store/markdown.d.ts +2 -6
  528. package/dist/store/markdown.js +21 -20
  529. package/dist/store/mirrors.d.ts +2 -6
  530. package/dist/store/mirrors.js +14 -23
  531. package/dist/store/open.js +6 -13
  532. package/dist/store/planning-fallacy-evidence.d.ts +2 -30
  533. package/dist/store/planning-fallacy-evidence.js +8 -37
  534. package/dist/store/port.d.ts +82 -79
  535. package/dist/store/predictions.d.ts +11 -51
  536. package/dist/store/predictions.js +38 -119
  537. package/dist/{cli → store}/quality-repair.js +15 -31
  538. package/dist/store/raw-archive.d.ts +4 -16
  539. package/dist/store/raw-archive.js +14 -29
  540. package/dist/store/recall-scope.d.ts +19 -79
  541. package/dist/store/recall-scope.js +21 -82
  542. package/dist/store/recall-trace.d.ts +10 -77
  543. package/dist/store/recall-trace.js +19 -95
  544. package/dist/store/rejected-values.js +7 -19
  545. package/dist/store/rejection.d.ts +12 -58
  546. package/dist/store/rejection.js +13 -65
  547. package/dist/store/report-reads.d.ts +6 -0
  548. package/dist/store/report-reads.js +29 -0
  549. package/dist/store/rows.d.ts +9 -19
  550. package/dist/store/rows.js +36 -34
  551. package/dist/store/rule-sql.d.ts +5 -0
  552. package/dist/store/rule-sql.js +37 -0
  553. package/dist/store/search-rows.d.ts +7 -38
  554. package/dist/store/search-rows.js +14 -50
  555. package/dist/store/sessions.d.ts +10 -47
  556. package/dist/store/sessions.js +17 -73
  557. package/dist/store/sqlite/connector-events-group.js +2 -2
  558. package/dist/store/sqlite/entry-writes-group.js +2 -2
  559. package/dist/store/sqlite/error-codec.js +4 -2
  560. package/dist/store/sqlite/executor.d.ts +2 -1
  561. package/dist/store/sqlite/executor.js +2 -1
  562. package/dist/store/sqlite/local.d.ts +3 -3
  563. package/dist/store/sqlite/local.js +1 -0
  564. package/dist/store/sqlite/object-rows.js +6 -3
  565. package/dist/store/sqlite/objects-group.js +4 -2
  566. package/dist/store/sqlite/quarantine-group.js +2 -2
  567. package/dist/store/sqlite/store.d.ts +1 -4
  568. package/dist/store/sqlite/store.js +2 -3
  569. package/dist/store/sqlite/vector-reads-group.js +2 -2
  570. package/dist/store/sqlite/worker-jobs.js +1 -1
  571. package/dist/store/sqlite/worker-ops.d.ts +13 -2
  572. package/dist/store/sqlite/worker-ops.js +13 -2
  573. package/dist/store/sqlite/worker-store.js +5 -2
  574. package/dist/store/summaries.d.ts +10 -62
  575. package/dist/store/summaries.js +34 -146
  576. package/dist/store/summary-dirty.js +1 -1
  577. package/dist/store/tenant-lookup.d.ts +6 -1
  578. package/dist/store/tenant-lookup.js +7 -0
  579. package/dist/store/tenant.d.ts +2 -16
  580. package/dist/store/tenant.js +4 -19
  581. package/dist/store/token-ledger.d.ts +13 -43
  582. package/dist/store/token-ledger.js +19 -50
  583. package/dist/store/usage-reports.js +5 -13
  584. package/dist/store/vector-index.d.ts +46 -0
  585. package/dist/store/vector-index.js +170 -0
  586. package/dist/store/working-memory.d.ts +6 -25
  587. package/dist/store/working-memory.js +18 -52
  588. package/dist/store/yaml.d.ts +1 -5
  589. package/dist/store/yaml.js +2 -6
  590. package/dist/support-bundle.js +7 -5
  591. package/dist/trust/reject-flow.js +1 -3
  592. package/dist/util/anthropic-messages.js +14 -2
  593. package/dist/util/atomic-write.d.ts +2 -1
  594. package/dist/util/atomic-write.js +35 -4
  595. package/dist/util/capped-json.d.ts +6 -0
  596. package/dist/util/capped-json.js +46 -0
  597. package/dist/util/crash-handlers.d.ts +8 -1
  598. package/dist/util/crash-handlers.js +52 -10
  599. package/dist/util/env.d.ts +13 -6
  600. package/dist/util/env.js +14 -7
  601. package/dist/util/home-path.d.ts +2 -1
  602. package/dist/util/home-path.js +4 -2
  603. package/dist/util/http-retry.d.ts +3 -1
  604. package/dist/util/http-retry.js +26 -5
  605. package/dist/util/log.d.ts +3 -2
  606. package/dist/util/log.js +25 -9
  607. package/dist/util/request-scope.d.ts +2 -1
  608. package/dist/util/request-scope.js +2 -1
  609. package/dist/util/secret-detect.d.ts +5 -30
  610. package/dist/util/secret-detect.js +13 -39
  611. package/dist/util/stored-json.d.ts +1 -1
  612. package/dist/util/stored-json.js +1 -1
  613. package/dist/util/token-text.d.ts +1 -4
  614. package/dist/util/token-text.js +1 -4
  615. package/dist/util/transcript-tail.d.ts +2 -0
  616. package/dist/util/transcript-tail.js +24 -23
  617. package/dist/util/version.d.ts +5 -20
  618. package/dist/util/version.js +5 -20
  619. package/extensions/openclaw-plugin/index.ts +1 -1
  620. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  621. package/extensions/openclaw-plugin/package.json +1 -1
  622. package/openclaw.plugin.json +1 -1
  623. package/package.json +1 -1
  624. package/dist/connectors/github/cli-impl.d.ts +0 -25
  625. package/dist/sharing/shared.d.ts +0 -187
  626. package/dist/sharing/shared.js +0 -563
  627. package/dist/store/vector-writes.d.ts +0 -13
  628. package/dist/store/vector-writes.js +0 -89
  629. /package/dist/{cli → store}/quality-repair.d.ts +0 -0
@@ -1,7 +1,5 @@
1
- /**
2
- * Slack Events API envelope shapes used by the ingestion connector.
3
- * Spec: https://api.slack.com/events-api
4
- */
1
+ /** Slack Events API envelope shapes used by the ingestion connector.
2
+ * Spec: https://api.slack.com/events-api */
5
3
  import { isJsonString, isJsonObject, isJsonNumber } from '../../util/json.js';
6
4
  export function isSlackEventEnvelope(x) {
7
5
  if (!isJsonObject(x))
@@ -1,15 +1,31 @@
1
1
  import { fetchWithRetry, isRetryableStatus } from '../../util/http-retry.js';
2
- import { isJsonString } from '../../util/json.js';
3
- /**
4
- * Build a SlackHistoryFetcher that pages `conversations.history` over real
5
- * HTTP. Wraps `fetchWithRetry` so 429 and 5xx handling is automatic. The returned
6
- * fetcher is the one `backfillChannel` consumes.
7
- *
8
- * Slack omits `channel` from messages in the history response, so we stamp
9
- * the request channel id onto each parsed message — downstream ingest needs
10
- * it on every event.
11
- */
2
+ import { readCappedJson } from '../../util/capped-json.js';
3
+ import { errorMessage } from '../../util/log.js';
4
+ import { isJsonObject, isJsonString } from '../../util/json.js';
5
+ /** Build a SlackHistoryFetcher that pages `conversations.history` over HTTP via `fetchWithRetry` (429 and 5xx handled).
6
+ * Slack omits `channel` from history messages, so the request channel id is stamped onto each one for ingest. */
12
7
  const SLACK_TIMEOUT_MS = 30_000;
8
+ // A page is at most 200 messages, each up to 40,000 characters at 4 bytes, carried once as text and once as rich-text blocks.
9
+ const SLACK_MAX_REPLY_BYTES = 64 * 1024 * 1024;
10
+ function isSlackMessage(m) {
11
+ return isJsonObject(m) && m.type === 'message' && isJsonString(m.ts);
12
+ }
13
+ /** The reply as a JSON object. The error names the status and the path only, since the query string carries channel ids and cursors. */
14
+ async function readHistoryReply(r, url) {
15
+ const where = `slack: HTTP ${r.status} on ${url.pathname}`;
16
+ let body;
17
+ try {
18
+ body = await readCappedJson(r, SLACK_MAX_REPLY_BYTES);
19
+ }
20
+ catch (err) {
21
+ throw new Error(`${where}: ${errorMessage(err)}`, { cause: err });
22
+ }
23
+ if (!isJsonObject(body))
24
+ throw new Error(`${where}: the reply is not a JSON object`);
25
+ if (body.messages !== undefined && !Array.isArray(body.messages))
26
+ throw new Error(`${where}: \`messages\` is not an array`);
27
+ return body;
28
+ }
13
29
  export function slackHistoryFetcher(token, fetchImpl) {
14
30
  return async ({ channelId, cursor, oldest }) => {
15
31
  const url = new URL('https://slack.com/api/conversations.history');
@@ -25,27 +41,17 @@ export function slackHistoryFetcher(token, fetchImpl) {
25
41
  });
26
42
  if (isRetryableStatus(r.status))
27
43
  throw new Error(`slack: still rate-limited or unavailable (HTTP ${r.status})`);
28
- // SAFETY: body is the Slack `conversations.history` response; per the
29
- // documented shape it's `{ ok, error?, messages?, response_metadata? }`.
30
- const body = (await r.json());
31
- if (!body.ok)
32
- throw new Error(`slack: ${body.error ?? 'unknown error'}`);
33
- const messages = (body.messages ?? [])
34
- .filter((m) => {
35
- if (m === null || Array.isArray(m) || typeof m !== 'object') {
36
- return false;
37
- }
38
- // SAFETY: the check above just confirmed m is a non-null, non-array
39
- // plain object, so it's safe to treat as a JSON-shaped record; the
40
- // `m is SlackMessageEvent` predicate is what validates the fields.
41
- const o = m;
42
- return o.type === 'message' && isJsonString(o.ts);
43
- })
44
+ const body = await readHistoryReply(r, url);
45
+ if (body.ok !== true)
46
+ throw new Error(`slack: ${isJsonString(body.error) ? body.error : 'unknown error'}`);
47
+ const messages = (Array.isArray(body.messages) ? body.messages : [])
48
+ .filter(isSlackMessage)
44
49
  // Slack returns messages without `channel`; stamp it from the request.
45
50
  .map((m) => ({ ...m, channel: channelId }));
51
+ const nextCursor = isJsonObject(body.response_metadata) ? body.response_metadata.next_cursor : undefined;
46
52
  return {
47
53
  messages,
48
- next_cursor: body.response_metadata?.next_cursor ?? null,
54
+ next_cursor: isJsonString(nextCursor) ? nextCursor : null,
49
55
  };
50
56
  };
51
57
  }
@@ -1,23 +1,6 @@
1
1
  import type { HippoStore } from '../../store/index.js';
2
2
  import { type WebhookRequest } from '../../util/http-util.js';
3
- /**
4
- * Slack Events API webhook. Auth is signature-based (HMAC over the raw
5
- * body with SLACK_SIGNING_SECRET); Bearer is NOT required, which is why
6
- * this route is in PUBLIC_ROUTES. The route is responsible for:
7
- * 1. Echoing the one-time url_verification challenge.
8
- * 2. Verifying the HMAC on every other inbound payload.
9
- * 3. Resolving body.team_id → tenantId via slack_workspaces, falling
10
- * back to HIPPO_TENANT then 'default'.
11
- * 4. Dispatching event_callback envelopes to ingestMessage /
12
- * handleMessageDeleted.
13
- * 5. Parking malformed or unhandled payloads in slack_dlq and STILL
14
- * ACKing 200 - Slack retries forever otherwise.
15
- *
16
- * When SLACK_SIGNING_SECRET is unset we return 404, not
17
- * 503, so an external probe cannot distinguish "route gated off by config"
18
- * from "route does not exist on this build".
19
- *
20
- * Bearer auth is skipped on purpose: server.ts checks isPublicRoute before calling this.
21
- */
3
+ /** Slack Events API webhook: HMAC over the raw body with SLACK_SIGNING_SECRET, no Bearer (hence PUBLIC_ROUTES); malformed payloads go to slack_dlq, ACK 200.
4
+ * 404 (not 503) when the secret is unset, so a probe cannot tell a gated-off route from a missing one. */
22
5
  export declare function handleSlackEventsWebhook(request: WebhookRequest, store?: HippoStore): Promise<void>;
23
6
  //# sourceMappingURL=webhook.d.ts.map
@@ -9,25 +9,8 @@ import { resolveTenantForSlackTeam } from './tenant-routing.js';
9
9
  import { resolveTenantId } from '../../store/tenant.js';
10
10
  import { HttpError, JSON_HEADERS, isHeaderString, closeIfBodyUnread, readWebhookBody, sendJson } from '../../util/http-util.js';
11
11
  import { isJsonObject } from '../../util/json.js';
12
- /**
13
- * Slack Events API webhook. Auth is signature-based (HMAC over the raw
14
- * body with SLACK_SIGNING_SECRET); Bearer is NOT required, which is why
15
- * this route is in PUBLIC_ROUTES. The route is responsible for:
16
- * 1. Echoing the one-time url_verification challenge.
17
- * 2. Verifying the HMAC on every other inbound payload.
18
- * 3. Resolving body.team_id → tenantId via slack_workspaces, falling
19
- * back to HIPPO_TENANT then 'default'.
20
- * 4. Dispatching event_callback envelopes to ingestMessage /
21
- * handleMessageDeleted.
22
- * 5. Parking malformed or unhandled payloads in slack_dlq and STILL
23
- * ACKing 200 - Slack retries forever otherwise.
24
- *
25
- * When SLACK_SIGNING_SECRET is unset we return 404, not
26
- * 503, so an external probe cannot distinguish "route gated off by config"
27
- * from "route does not exist on this build".
28
- *
29
- * Bearer auth is skipped on purpose: server.ts checks isPublicRoute before calling this.
30
- */
12
+ /** Slack Events API webhook: HMAC over the raw body with SLACK_SIGNING_SECRET, no Bearer (hence PUBLIC_ROUTES); malformed payloads go to slack_dlq, ACK 200.
13
+ * 404 (not 503) when the secret is unset, so a probe cannot tell a gated-off route from a missing one. */
31
14
  export async function handleSlackEventsWebhook(request, store) {
32
15
  const { req, res, opts } = request;
33
16
  // Secret and headers before the body, so a caller with neither cannot make the server buffer one.
@@ -104,10 +87,8 @@ async function routeSignedSlackPayload(d) {
104
87
  }
105
88
  if (answerUrlVerification(res, body))
106
89
  return;
107
- // Resolve tenant, failing closed: when slack_workspaces is non-empty
108
- // and the team_id is unknown, resolveTenantForTeam returns null and we
109
- // park the envelope in slack_dlq with bucket='unroutable'. Mandatory ACK
110
- // 200 so Slack stops retrying; do NOT call ingest.
90
+ // Fail closed: resolveTenantForSlackTeam returns null for an unknown team on a non-empty slack_workspaces; park it in slack_dlq (bucket='unroutable')
91
+ // and still ACKs 200 so Slack stops retrying; never call ingest.
111
92
  let resolvedTenant = null;
112
93
  if (body !== undefined && isSlackEventEnvelope(body)) {
113
94
  resolvedTenant = await resolveTenantForSlackTeam(d.hippoRoot, body.team_id, d.store);
@@ -169,9 +150,7 @@ async function dispatchSlackEvent(d, ctx, body) {
169
150
  }
170
151
  const r = await ingestMessage(ctx, {
171
152
  teamId: body.team_id,
172
- // channel privacy isn't on the inner event; use channel_type as a
173
- // proxy. 'group'|'im'|'mpim' → private. 'channel' → public. Unknown
174
- // → private (fail closed).
153
+ // Channel privacy is not on the inner event, so channel_type is the proxy: 'group'|'im'|'mpim' private, 'channel' public, unknown private.
175
154
  channel: {
176
155
  id: inner.channel,
177
156
  is_private: inner.channel_type !== 'channel',
@@ -1,23 +1,5 @@
1
- /**
2
- * Slack workspace registration helpers.
3
- *
4
- * The `slack_workspaces` table maps Slack `team_id` → hippo `tenant_id`.
5
- * Empty table = single-tenant install (HIPPO_TENANT fallback).
6
- * Non-empty = multi-workspace install (fail-closed routing via
7
- * `resolveTenantForTeam`).
8
- *
9
- * These helpers give the CLI (`hippo slack workspaces add|list|remove`) a
10
- * surface, so operators with multiple workspaces need no direct SQL.
11
- *
12
- * Design choices:
13
- * - `add` is an upsert (ON CONFLICT UPDATE). Re-registering an
14
- * existing team_id with a different tenant_id intentionally
15
- * overwrites — operators move workspaces between tenants and the
16
- * CLI shouldn't require a delete+add dance.
17
- * - `list` sorts by team_id for stable output.
18
- * - `remove` returns a boolean for the CLI to distinguish "removed"
19
- * from "not found" without an extra SELECT.
20
- */
1
+ /** Slack workspace registration helpers: the `slack_workspaces` table maps `team_id` to `tenant_id` (empty = single-tenant, non-empty = fail-closed routing).
2
+ * `add` is an upsert that overwrites an existing team_id's tenant on purpose, so moving a workspace needs no delete+add. */
21
3
  import { type SlackWorkspace } from '../../store/connectors/slack.js';
22
4
  export type { SlackWorkspace };
23
5
  export { listSlackWorkspaces as listWorkspaces, removeSlackWorkspace as removeWorkspace } from '../../store/connectors/slack.js';
@@ -25,9 +7,7 @@ export interface AddWorkspaceOpts {
25
7
  teamId: string;
26
8
  tenantId: string;
27
9
  }
28
- /**
29
- * Register or re-register a Slack team → tenant mapping. Upserts on
30
- * team_id conflict (operators move workspaces between tenants).
31
- */
10
+ /** Register or re-register a Slack team → tenant mapping. Upserts on
11
+ * team_id conflict (operators move workspaces between tenants). */
32
12
  export declare function addWorkspace(hippoRoot: string, opts: AddWorkspaceOpts): SlackWorkspace;
33
13
  //# sourceMappingURL=workspaces.d.ts.map
@@ -1,29 +1,9 @@
1
- /**
2
- * Slack workspace registration helpers.
3
- *
4
- * The `slack_workspaces` table maps Slack `team_id` → hippo `tenant_id`.
5
- * Empty table = single-tenant install (HIPPO_TENANT fallback).
6
- * Non-empty = multi-workspace install (fail-closed routing via
7
- * `resolveTenantForTeam`).
8
- *
9
- * These helpers give the CLI (`hippo slack workspaces add|list|remove`) a
10
- * surface, so operators with multiple workspaces need no direct SQL.
11
- *
12
- * Design choices:
13
- * - `add` is an upsert (ON CONFLICT UPDATE). Re-registering an
14
- * existing team_id with a different tenant_id intentionally
15
- * overwrites — operators move workspaces between tenants and the
16
- * CLI shouldn't require a delete+add dance.
17
- * - `list` sorts by team_id for stable output.
18
- * - `remove` returns a boolean for the CLI to distinguish "removed"
19
- * from "not found" without an extra SELECT.
20
- */
1
+ /** Slack workspace registration helpers: the `slack_workspaces` table maps `team_id` to `tenant_id` (empty = single-tenant, non-empty = fail-closed routing).
2
+ * `add` is an upsert that overwrites an existing team_id's tenant on purpose, so moving a workspace needs no delete+add. */
21
3
  import { upsertSlackWorkspace } from '../../store/connectors/slack.js';
22
4
  export { listSlackWorkspaces as listWorkspaces, removeSlackWorkspace as removeWorkspace } from '../../store/connectors/slack.js';
23
- /**
24
- * Register or re-register a Slack team → tenant mapping. Upserts on
25
- * team_id conflict (operators move workspaces between tenants).
26
- */
5
+ /** Register or re-register a Slack team → tenant mapping. Upserts on
6
+ * team_id conflict (operators move workspaces between tenants). */
27
7
  export function addWorkspace(hippoRoot, opts) {
28
8
  return upsertSlackWorkspace(hippoRoot, opts.teamId, opts.tenantId);
29
9
  }
@@ -3,12 +3,8 @@ import { jaccardMinShared, overlapPartners } from './overlap-index.js';
3
3
  import { isQuarantineScope } from '../trust/quarantine.js';
4
4
  import { isPersonalScope } from '../store/recall-scope.js';
5
5
  import { DECAY_THRESHOLD } from './decay.js';
6
- // Contradictions should be gated by content overlap, not shared tags. Tags like
7
- // `feedback` / `policy` are too coarse and can make unrelated rules look like
8
- // conflicts before the polarity heuristics run.
9
- // Jaccard threshold on stopword-filtered tokens. Only applied after a polarity
10
- // signal has already been detected (explicit pair or inferred negation), so
11
- // this just filters out drive-by topic similarity, not semantic drift.
6
+ // Gate contradictions on content overlap, not shared tags (`feedback`/`policy` are too coarse). The Jaccard threshold on stopword-filtered tokens
7
+ // only applies after a polarity signal, so it filters drive-by topic similarity, not semantic drift.
12
8
  const CONFLICT_OVERLAP_THRESHOLD = 0.5;
13
9
  // Minimum distinctive shared tokens before we trust an overlap score. Filters
14
10
  // out cases where two memories share only common English + a project name.
@@ -41,9 +37,8 @@ rescuedIds = new Set()) {
41
37
  const partnersOf = overlapPartners(profiles.map((p) => p.distinct), jaccardMinShared(CONFLICT_OVERLAP_THRESHOLD, CONFLICT_MIN_RARE_SHARED));
42
38
  for (let i = 0; i < survivors.length; i++) {
43
39
  for (const j of partnersOf(i)) {
44
- // Traces are variants of each other, not contradictions. Two
45
- // strategies for the same task can both be valid; conflict detection
46
- // exists for stated-rule disagreement, not strategy diversity.
40
+ // Traces are variants of each other, not contradictions: two strategies for the same task can both be valid,
41
+ // and conflict detection is for stated-rule disagreement, not strategy diversity.
47
42
  if (survivors[i].layer === Layer.Trace && survivors[j].layer === Layer.Trace)
48
43
  continue;
49
44
  if (survivors[i].superseded_by || survivors[j].superseded_by)
@@ -77,8 +72,7 @@ function recalledTogether(a, b) {
77
72
  }
78
73
  function conflictProfile(text) {
79
74
  const opening = openingWindow(text);
80
- // Polarity is measured only in the first POLARITY_WINDOW_WORDS, so a stray
81
- // negation deep in a prose memory doesn't flip the intent.
75
+ // Polarity is measured only in the first POLARITY_WINDOW_WORDS, so a stray negation deep in a prose memory doesn't flip the intent.
82
76
  // Pad with spaces so space-delimited patterns match words at the start/end.
83
77
  return { distinct: distinctiveTokens(text), polarity: inferConflictPolarity(opening), window: ' ' + opening.toLowerCase() + ' ' };
84
78
  }
@@ -128,9 +122,7 @@ function openingWindow(text) {
128
122
  }
129
123
  // Takes opening windows only, so " on " and " off " as prepositions deep in long prose don't read as enabled/disabled.
130
124
  function classifyConflictType(a, b, aPolarity, bPolarity) {
131
- // Tightened tokens: require whole-word boundaries so " on " alone doesn't
132
- // match "on/off". Pair only `enabled` ↔ `disabled` and explicit on/off in
133
- // imperative context.
125
+ // Whole-word boundaries so " on " alone doesn't match "on/off"; pair only `enabled` <-> `disabled` and explicit on/off in imperative context.
134
126
  const enabledDisabled = (containsAny(a, [' enabled ', ' enable ']) && containsAny(b, [' disabled ', ' disable ']))
135
127
  || (containsAny(b, [' enabled ', ' enable ']) && containsAny(a, [' disabled ', ' disable ']));
136
128
  if (enabledDisabled)
@@ -0,0 +1,8 @@
1
+ export interface DagSummaryOptions {
2
+ apiKey: string;
3
+ model?: string;
4
+ fetcher?: typeof fetch;
5
+ onError?: (msg: string) => void;
6
+ }
7
+ export declare function generateDagSummary(label: string, factContents: string[], opts: DagSummaryOptions): Promise<string | null>;
8
+ //# sourceMappingURL=dag-summary.d.ts.map
@@ -0,0 +1,41 @@
1
+ // The one LLM call behind every DAG summary, kept apart from the graph writes so its request bytes are tested on their own.
2
+ import { redactSecretsStrict } from '../util/secret-detect.js';
3
+ import { describeMessageFailure, sendAnthropicMessage } from '../util/anthropic-messages.js';
4
+ import { certainDefect } from '../core/memory-quality.js';
5
+ const DAG_SUMMARY_PROMPT = `You are summarizing a cluster of facts about a specific topic/entity for a memory system.
6
+
7
+ Topic: {label}
8
+ Facts:
9
+ {facts}
10
+
11
+ ` +
12
+ 'Write a single concise paragraph (2-4 sentences) that captures all the key information from these facts. ' +
13
+ 'This summary will be used to quickly determine if this cluster is relevant to a future query, ' +
14
+ 'so include specific names, dates, numbers, and key details. Output ONLY the summary paragraph, no preamble.';
15
+ // Output budget for one summary paragraph, and the shortest reply kept as a summary.
16
+ const SUMMARY_MAX_TOKENS = 400;
17
+ const SUMMARY_MIN_CHARS = 20;
18
+ export async function generateDagSummary(label, factContents, opts) {
19
+ const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecretsStrict(f)}`).join('\n');
20
+ const prompt = DAG_SUMMARY_PROMPT
21
+ .replace('{label}', redactSecretsStrict(label))
22
+ .replace('{facts}', factsBlock);
23
+ const reply = await sendAnthropicMessage({
24
+ apiKey: opts.apiKey,
25
+ model: opts.model,
26
+ maxTokens: SUMMARY_MAX_TOKENS,
27
+ prompt,
28
+ fetcher: opts.fetcher,
29
+ });
30
+ if (!reply.ok) {
31
+ opts.onError?.(describeMessageFailure(reply.failure));
32
+ return null;
33
+ }
34
+ const defect = certainDefect(reply.text);
35
+ if (defect !== null) {
36
+ opts.onError?.(`summary quality refused: ${defect}`);
37
+ return null;
38
+ }
39
+ return reply.text.length >= SUMMARY_MIN_CHARS ? reply.text : null;
40
+ }
41
+ //# sourceMappingURL=dag-summary.js.map
@@ -1,17 +1,11 @@
1
1
  import { type MemoryEntry } from '../core/memory.js';
2
+ import { type DagSummaryOptions } from './dag-summary.js';
2
3
  export interface FactCluster {
3
4
  label: string;
4
5
  members: MemoryEntry[];
5
6
  entityTags: string[];
6
7
  }
7
8
  export declare function clusterFacts(facts: MemoryEntry[]): FactCluster[];
8
- export interface DagSummaryOptions {
9
- apiKey: string;
10
- model?: string;
11
- fetcher?: typeof fetch;
12
- onError?: (msg: string) => void;
13
- }
14
- export declare function generateDagSummary(label: string, factContents: string[], opts: DagSummaryOptions): Promise<string | null>;
15
9
  export interface DagBuildResult {
16
10
  candidateClusters: number;
17
11
  summariesCreated: number;
@@ -29,19 +23,8 @@ export interface DagRebuildResult {
29
23
  failed: number;
30
24
  capped: boolean;
31
25
  }
32
- /**
33
- * Sleep-cycle phase that drains the dirty L2 summary queue.
34
- * Thin orchestrator; the heavy lifting lives in store.ts (load + apply)
35
- * and dag.ts:generateDagSummary (LLM call).
36
- *
37
- * Per-summary try/catch: one throwing rebuild does NOT abort the rest of the queue.
38
- *
39
- * Race-loser handling: applyRebuildResult's UPDATE WHERE includes
40
- * AND summary_dirty=1, so concurrent sleep's second writer returns
41
- * changed=false. Silent skip (neither rebuilt++ nor refused++ nor failed++).
42
- *
43
- * A tombstone hit counts as `refused`, not `rebuilt`; dirty clears either way.
44
- */
26
+ /** Sleep-cycle phase draining the dirty L2 summary queue; one throwing rebuild does not abort the rest.
27
+ * A concurrent sleep's second writer gets changed=false (UPDATE requires summary_dirty=1) and is skipped silently; a tombstone hit counts as `refused`. */
45
28
  export declare function rebuildDirtySummaries(hippoRoot: string, opts: DagSummaryOptions & {
46
29
  cap?: number;
47
30
  }): Promise<DagRebuildResult>;
@@ -54,13 +37,7 @@ export interface EntityProfilesBuildResult {
54
37
  * `failed`: a tombstone hit is a deliberate refusal, not an error. */
55
38
  rejected: number;
56
39
  }
57
- /**
58
- * Build L3 entity profiles by clustering L2 summaries with
59
- * shared entity tags. Threshold 2+ L2s per entity. Mirrors buildDag L1->L2
60
- * pattern, one level up.
61
- *
62
- * Born-dirty cancellation: each L2 link write marks the new L3 dirty, so clear it
63
- * or the same sleep cycle's rebuild re-rebuilds the freshly built L3.
64
- */
40
+ /** Build L3 entity profiles by clustering L2 summaries sharing entity tags (2+ L2s per entity).
41
+ * Each L2 link write marks the new L3 dirty, so clear it or the same cycle re-rebuilds it. */
65
42
  export declare function buildEntityProfiles(hippoRoot: string, l2Summaries: MemoryEntry[], opts: DagSummaryOptions): Promise<EntityProfilesBuildResult>;
66
43
  //# sourceMappingURL=dag.d.ts.map
@@ -2,13 +2,11 @@ import { createMemory, Layer } from '../core/memory.js';
2
2
  import { writeEntry, writeEntriesTogether } from '../store/entry-writes.js';
3
3
  import { loadAllDirtySummaries, loadChildrenOfSummary, applyRebuildResult, clearSummaryDirtyAfterBuild, } from '../store/summaries.js';
4
4
  import { RejectedValueError } from '../store/rejection.js';
5
- import { redactSecretsStrict } from '../util/secret-detect.js';
6
- import { describeMessageFailure, sendAnthropicMessage } from '../util/anthropic-messages.js';
5
+ import { generateDagSummary } from './dag-summary.js';
7
6
  import { derivationScope, derivationPartitionKey } from '../store/recall-scope.js';
8
7
  import { loadConfig } from '../core/config.js';
9
- import { neverAutoShareTags } from '../sharing/shared.js';
10
- import { errorMessage, log } from '../util/log.js';
11
- import { certainDefect } from '../core/memory-quality.js';
8
+ import { neverAutoShareTags } from '../sharing/share.js';
9
+ import { errorFields, errorMessage, log } from '../util/log.js';
12
10
  const SUMMARY_FALLBACK_CHARS = 40;
13
11
  const DEFAULT_REBUILD_CAP = 20;
14
12
  export function clusterFacts(facts) {
@@ -42,41 +40,7 @@ export function clusterFacts(facts) {
42
40
  }
43
41
  return clusters;
44
42
  }
45
- const DAG_SUMMARY_PROMPT = `You are summarizing a cluster of facts about a specific topic/entity for a memory system.
46
-
47
- Topic: {label}
48
- Facts:
49
- {facts}
50
-
51
- Write a single concise paragraph (2-4 sentences) that captures all the key information from these facts. This summary will be used to quickly determine if this cluster is relevant to a future query, so include specific names, dates, numbers, and key details. Output ONLY the summary paragraph, no preamble.`;
52
- // Output budget for one summary paragraph, and the shortest reply kept as a summary.
53
- const SUMMARY_MAX_TOKENS = 400;
54
- const SUMMARY_MIN_CHARS = 20;
55
- export async function generateDagSummary(label, factContents, opts) {
56
- const factsBlock = factContents.map((f, i) => `${i + 1}. ${redactSecretsStrict(f)}`).join('\n');
57
- const prompt = DAG_SUMMARY_PROMPT
58
- .replace('{label}', redactSecretsStrict(label))
59
- .replace('{facts}', factsBlock);
60
- const reply = await sendAnthropicMessage({
61
- apiKey: opts.apiKey,
62
- model: opts.model,
63
- maxTokens: SUMMARY_MAX_TOKENS,
64
- prompt,
65
- fetcher: opts.fetcher,
66
- });
67
- if (!reply.ok) {
68
- opts.onError?.(describeMessageFailure(reply.failure));
69
- return null;
70
- }
71
- const defect = certainDefect(reply.text);
72
- if (defect !== null) {
73
- opts.onError?.(`summary quality refused: ${defect}`);
74
- return null;
75
- }
76
- return reply.text.length >= SUMMARY_MIN_CHARS ? reply.text : null;
77
- }
78
- // Partition BEFORE clustering so one LLM summary never mixes facts from different tenants.
79
- // Map keeps insertion order, so a single-tenant store iterates in its original order.
43
+ // Partition before clustering so one LLM summary never mixes tenants; Map keeps insertion order, so a single-tenant store iterates as before.
80
44
  // buildEntityProfiles partitions its L2s with this same key.
81
45
  function partitionFactsByTenant(unparented) {
82
46
  const unparentedByTenant = new Map();
@@ -93,10 +57,7 @@ function partitionFactsByTenant(unparented) {
93
57
  /** The L2 summary entry for one cluster, landing in the facts' own tenant and scope. */
94
58
  function createClusterSummaryEntry(summary, cluster, home) {
95
59
  const memberCreatedAts = cluster.members.map((m) => m.created).sort();
96
- // Every member of `cluster` shares home.tenantId by construction (the
97
- // tenant partition above), so the summary lands in the same tenant
98
- // as the facts it summarizes instead of always 'default'
99
- // (memory.ts:535 defaults tenantId when the option is omitted).
60
+ // Every cluster member shares home.tenantId (tenant partition above), so the summary lands in the facts' tenant, not 'default'.
100
61
  const summaryEntry = createMemory(summary, {
101
62
  layer: Layer.Semantic,
102
63
  tags: [...cluster.entityTags, ...neverAutoShareTags(cluster.members), 'dag-summary'],
@@ -204,9 +165,8 @@ function clearZeroChildSummary(hippoRoot, summary, result) {
204
165
  });
205
166
  if (changed)
206
167
  result.zeroChildSkipped++;
207
- // changed=false → race lost / row vanished; silently skip. `refused`
208
- // is always false here — applyRebuildResult only checks the
209
- // tombstone when bumpRebuildCount is true (store/summaries.ts).
168
+ // changed=false means race lost or row vanished: skip silently. `refused` is always false here, as applyRebuildResult
169
+ // checks the tombstone only when bumpRebuildCount is true.
210
170
  }
211
171
  // Derive label from summary's existing entity tags (mirrors clusterFacts)
212
172
  function summaryLabel(summary) {
@@ -215,19 +175,8 @@ function summaryLabel(summary) {
215
175
  ? entityTags.map((t) => t.split(':')[1]).join(': ')
216
176
  : summary.content.slice(0, SUMMARY_FALLBACK_CHARS);
217
177
  }
218
- /**
219
- * Sleep-cycle phase that drains the dirty L2 summary queue.
220
- * Thin orchestrator; the heavy lifting lives in store.ts (load + apply)
221
- * and dag.ts:generateDagSummary (LLM call).
222
- *
223
- * Per-summary try/catch: one throwing rebuild does NOT abort the rest of the queue.
224
- *
225
- * Race-loser handling: applyRebuildResult's UPDATE WHERE includes
226
- * AND summary_dirty=1, so concurrent sleep's second writer returns
227
- * changed=false. Silent skip (neither rebuilt++ nor refused++ nor failed++).
228
- *
229
- * A tombstone hit counts as `refused`, not `rebuilt`; dirty clears either way.
230
- */
178
+ /** Sleep-cycle phase draining the dirty L2 summary queue; one throwing rebuild does not abort the rest.
179
+ * A concurrent sleep's second writer gets changed=false (UPDATE requires summary_dirty=1) and is skipped silently; a tombstone hit counts as `refused`. */
231
180
  export async function rebuildDirtySummaries(hippoRoot, opts) {
232
181
  const cap = opts.cap ?? DEFAULT_REBUILD_CAP;
233
182
  const dirty = loadAllDirtySummaries(hippoRoot);
@@ -242,12 +191,8 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
242
191
  capped,
243
192
  };
244
193
  for (const [index, summary] of queue.entries()) {
245
- // Yield the macrotask queue every 25 summaries. The cap can reach 1000,
246
- // and each iteration is synchronous SQLite (the LLM await resolves as a
247
- // microtask when the response is cached/mocked), so a large batch would
248
- // otherwise starve timers and IPC for the whole rebuild: server
249
- // keep-alive pings in production, Vitest's birpc heartbeat in tests
250
- // (hardcoded 60s upstream, vitest-dev/vitest#8164).
194
+ // Yield the macrotask queue every 25 summaries: each iteration is synchronous SQLite, so a batch of up to 1000
195
+ // would starve timers and IPC (server keep-alives, Vitest's birpc heartbeat).
251
196
  if (index > 0 && index % 25 === 0) {
252
197
  await new Promise((resolve) => setImmediate(resolve));
253
198
  }
@@ -258,7 +203,7 @@ export async function rebuildDirtySummaries(hippoRoot, opts) {
258
203
  // One throw doesn't abort the queue; log enough to triage an exotic
259
204
  // failure (SQLite I/O, prepare), since audit() already catches its own.
260
205
  result.failed++;
261
- log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenantId}) failed: ${errorMessage(err)}`);
206
+ log.error(`rebuildDirtySummaries: summary ${summary.id} (tenant ${summary.tenantId}) failed: ${errorMessage(err)}`, errorFields(err));
262
207
  }
263
208
  }
264
209
  return result;
@@ -309,14 +254,8 @@ async function profileCluster(hippoRoot, cluster, home, opts, result) {
309
254
  // The distinct source tags the audit row.
310
255
  clearSummaryDirtyAfterBuild(hippoRoot, profileEntry.id, home.tenantId, 'buildEntityProfiles', 'buildEntityProfiles-clean');
311
256
  }
312
- /**
313
- * Build L3 entity profiles by clustering L2 summaries with
314
- * shared entity tags. Threshold 2+ L2s per entity. Mirrors buildDag L1->L2
315
- * pattern, one level up.
316
- *
317
- * Born-dirty cancellation: each L2 link write marks the new L3 dirty, so clear it
318
- * or the same sleep cycle's rebuild re-rebuilds the freshly built L3.
319
- */
257
+ /** Build L3 entity profiles by clustering L2 summaries sharing entity tags (2+ L2s per entity).
258
+ * Each L2 link write marks the new L3 dirty, so clear it or the same cycle re-rebuilds it. */
320
259
  export async function buildEntityProfiles(hippoRoot, l2Summaries, opts) {
321
260
  const result = {
322
261
  candidateClusters: 0,
@@ -4,13 +4,8 @@ import { rescueSet, rankNonPinnedByTenant, validateWeights } from './memory-valu
4
4
  import { MEMORY_VALUE_WEIGHTS, SOURCE_ARTIFACT_SHA256 } from './memory-value-weights.js';
5
5
  const STRENGTH_DECIMALS = 4;
6
6
  export const DECAY_THRESHOLD = 0.05;
7
- // A faded, unpinned, unrescued memory leaves active memory one of three
8
- // ways. A raw receipt is append-only: trg_memories_raw_append_only aborts
9
- // a DELETE, and with it this whole cycle's batch and every later sleep,
10
- // so it stays where it is (stored strength refreshed) but sits out the
11
- // rest of this cycle the way a deleted row would. Anything else goes
12
- // dormant when config.dormant is on, and is deleted otherwise.
13
- // Only called for rows `retirable` allows (never pinned, raw, kept for good or backing a first-class object).
7
+ // Leaving active memory: a raw receipt stays (the append-only trigger aborts DELETE for the whole batch; stored strength refreshed) but sits out this cycle;
8
+ // others go dormant when config.dormant is on, else are deleted. Only called for rows `retirable` allows.
14
9
  function retireFaded(run, entry, strength) {
15
10
  const { result } = run;
16
11
  const why = `(strength ${strength.toFixed(STRENGTH_DECIMALS)} < ${DECAY_THRESHOLD})`;
@@ -36,11 +31,8 @@ function keepSurvivor(run, entry, strength) {
36
31
  run.result.decayed++;
37
32
  return updated;
38
33
  }
39
- // -------------------------------------------------------------------------
40
- // 1. Decay pass
41
- // -------------------------------------------------------------------------
42
- // Memory-value flag OFF runs the single-phase loop below. Flag ON classifies every entry with ZERO commits,
43
- // runs rescueSet per tenant, then commits; rescued entries stay full survivors for this cycle's later passes.
34
+ // 1. Decay pass. Memory-value flag OFF runs the single-phase loop below; ON classifies every entry with zero commits, runs rescueSet per tenant, then commits.
35
+ // Rescued entries stay full survivors for this cycle's later passes.
44
36
  export function decayPass(run) {
45
37
  if (run.config.memoryValue.enabled)
46
38
  return decayWithMemoryValue(run);
@@ -93,10 +85,7 @@ function decayWithMemoryValue(run) {
93
85
  let rescuedIds = new Set();
94
86
  let rankById = new Map();
95
87
  const { strengthById, condemnedIds } = classifyByStrength(run);
96
- // --- Phase 2a: rescue decision (pure compute) ---
97
- // Runs under --dry-run too (only the pendingDeletes flush and the audit write in
98
- // logRun stay !dryRun-gated), so the preview matches what a
99
- // real run would decide.
88
+ // Phase 2a: rescue decision (pure compute); runs under --dry-run too (only the pendingDeletes flush and the logRun audit write are !dryRun-gated).
100
89
  // Fail-loud must not depend on condemnation traffic: validate the frozen weights even when nothing is condemned.
101
90
  validateWeights();
102
91
  if (condemnedIds.size > 0) {
@@ -112,9 +101,8 @@ function decayWithMemoryValue(run) {
112
101
  const strength = strengthById.get(entry.id);
113
102
  if (run.retirable(entry) && strength < DECAY_THRESHOLD) {
114
103
  if (rescuedIds.has(entry.id)) {
115
- // Rescued: standard survivor stored-strength refresh.
116
- // Confidence is left alone here: it is an epistemic tier, not a
117
- // cached computation, so resolveConfidence derives it on read.
104
+ // Rescued: standard survivor stored-strength refresh. Confidence is left alone: it is an epistemic tier, not a cached
105
+ // computation, so resolveConfidence derives it on read.
118
106
  rescuedEntries.push(keepSurvivor(run, entry, strength));
119
107
  reportRescue(result, entry, strength, rankById.get(entry.id));
120
108
  }