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
package/README.md CHANGED
@@ -784,7 +784,7 @@ hippo watch "npm run build"
784
784
  | `hippo dashboard` | Open web dashboard at localhost:3333 (memory health by project, and the card board); open the printed URL, which carries a per-start access token |
785
785
  | `hippo dashboard --port <n>` | Use custom port |
786
786
  | `hippo mcp` | Start MCP server (stdio transport) |
787
- | `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`) |
787
+ | `hippo serve` | Start the HTTP API server for this store on `127.0.0.1:6789` (`--port <n>` or `HIPPO_PORT`; `--host <host>`, which off loopback needs `HIPPO_REQUIRE_AUTH=1`). Every request needs an API key (`hippo auth create`, then `Authorization: Bearer <key>`; the hippo CLI reads `HIPPO_API_KEY`). `HIPPO_ALLOW_KEYLESS_LOCAL=1` lets requests from this machine in without one, as host admin; `HIPPO_REQUIRE_AUTH=1` wins over it |
788
788
  | `hippo serve --tls-cert <file> --tls-key <file>` | Serve HTTPS with that PEM certificate and key (or set `HIPPO_TLS_CERT` and `HIPPO_TLS_KEY`). Without them a network bind still starts, and warns once that API keys and memory text travel in cleartext unless a TLS-terminating proxy sits in front |
789
789
 
790
790
  On `heartbeat`, `block`, `review` and `complete`, a given `--run` is checked against the card's live run and the command is refused, unchanged, if the two do not match.
@@ -1,12 +1,14 @@
1
1
  import { type ProjectIdentity } from '../core/project-identity.js';
2
2
  import type { Adapter, AdapterContext, Listing } from './types.js';
3
- /** Claude Code's rule: a linked worktree shares its main checkout's folder, or the git folder's when that sits outside a checkout (a bare repository, or --separate-git-dir); any other checkout, a submodule included, keeps its own. */
3
+ /** Claude Code's rule: a linked worktree shares its main checkout's folder, or the git folder's when that sits outside
4
+ * a checkout (a bare repository, or --separate-git-dir); any other checkout, a submodule included, keeps its own. */
4
5
  export declare function claudeCheckoutRoot(top: string, gitDir: string, common: string): string;
5
6
  /** Claude Code's folder name for a path: non-alphanumerics made '-', and a name over 200 characters cut to 200 plus a base-36 hash of the whole path. */
6
7
  export declare function claudeFolderName(root: string): string;
7
8
  export declare const claudeCodeAdapter: Adapter;
8
9
  /** A session's own notes folder and nothing else, with no git call, so post-compact can read it inside the hook's time limit. */
9
10
  export declare function claudeTranscriptListing(ctx: AdapterContext, transcriptPath: string): Listing;
10
- /** The project a session folder's notes belong to: the one Claude named the folder for, the session's start folder, else cwd or a parent; null when none matches. */
11
+ /** The project a session folder's notes belong to: the one Claude named the folder
12
+ * for, the session's start folder, else cwd or a parent; null when none matches. */
11
13
  export declare function transcriptNotesProject(transcriptPath: string, cwd: string | null, machine: Pick<AdapterContext, 'platform' | 'env'>): ProjectIdentity | null;
12
14
  //# sourceMappingURL=claude-code.d.ts.map
@@ -21,7 +21,8 @@ function claudeMemoryFolderNames(projectRoot, platform) {
21
21
  roots.push(claudeCheckoutRoot(layout.top, layout.gitDir, layout.common));
22
22
  return new Set(roots.map((root) => (platform === 'win32' ? claudeFolderName(root).toLowerCase() : claudeFolderName(root))));
23
23
  }
24
- /** Claude Code's rule: a linked worktree shares its main checkout's folder, or the git folder's when that sits outside a checkout (a bare repository, or --separate-git-dir); any other checkout, a submodule included, keeps its own. */
24
+ /** Claude Code's rule: a linked worktree shares its main checkout's folder, or the git folder's when that sits outside
25
+ * a checkout (a bare repository, or --separate-git-dir); any other checkout, a submodule included, keeps its own. */
25
26
  export function claudeCheckoutRoot(top, gitDir, common) {
26
27
  if (gitDir === common)
27
28
  return top;
@@ -55,7 +56,8 @@ export function claudeTranscriptListing(ctx, transcriptPath) {
55
56
  const folder = path.join(path.dirname(transcriptPath), 'memory');
56
57
  return { tool: 'claude-code', home: config, containers: readFolders([folder], 'project', ctx.platform), warnings: [] };
57
58
  }
58
- /** The project a session folder's notes belong to: the one Claude named the folder for, the session's start folder, else cwd or a parent; null when none matches. */
59
+ /** The project a session folder's notes belong to: the one Claude named the folder
60
+ * for, the session's start folder, else cwd or a parent; null when none matches. */
59
61
  export function transcriptNotesProject(transcriptPath, cwd, machine) {
60
62
  const fold = (name) => (machine.platform === 'win32' ? name.toLowerCase() : name);
61
63
  const folder = fold(path.basename(path.dirname(transcriptPath)));
@@ -79,9 +81,16 @@ export function transcriptNotesProject(transcriptPath, cwd, machine) {
79
81
  const START_SCAN_BYTES = 64 * 1024;
80
82
  /** The cwd on the transcript's first line that has one: the folder Claude named the session folder for, which a folder name alone cannot give back. */
81
83
  function transcriptStartCwd(transcriptPath) {
82
- if (!fs.existsSync(transcriptPath))
83
- return null;
84
- const fd = fs.openSync(transcriptPath, 'r');
84
+ let fd;
85
+ try {
86
+ fd = fs.openSync(transcriptPath, 'r');
87
+ }
88
+ catch (err) {
89
+ // A transcript that is not there names no start folder; any other failure is the caller's to see.
90
+ if (err instanceof Error && 'code' in err && (err.code === 'ENOENT' || err.code === 'ENOTDIR'))
91
+ return null;
92
+ throw err;
93
+ }
85
94
  try {
86
95
  const buf = Buffer.alloc(START_SCAN_BYTES);
87
96
  const lines = buf.subarray(0, fs.readSync(fd, buf, 0, buf.length, 0)).toString('utf8').split('\n');
@@ -7,23 +7,34 @@ const MAX_DEPTH = 8;
7
7
  /** A file's text, or why it was skipped: empty, too big, holds a NUL byte (not text), or unreadable. */
8
8
  export function readTextFile(file) {
9
9
  try {
10
- const stat = fs.statSync(file);
11
- if (!stat.isFile())
12
- return { ok: false, reason: `${file}: not a file` };
13
- // A tool rewriting a file truncates it first; read as holding no notes, every row would be set aside.
14
- if (stat.size === 0)
15
- return { ok: false, reason: `${file}: empty` };
16
- if (stat.size > MAX_ITEM_BYTES)
17
- return { ok: false, reason: `${file}: over ${MAX_ITEM_BYTES} bytes` };
18
- const buf = fs.readFileSync(file);
19
- if (buf.includes(0))
20
- return { ok: false, reason: `${file}: not text` };
21
- return { ok: true, text: buf.toString('utf8'), mtimeMs: stat.mtimeMs };
10
+ // O_NONBLOCK opens a FIFO at once, for the file check to turn away; Windows has no such flag and the OR adds nothing.
11
+ const fd = fs.openSync(file, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);
12
+ try {
13
+ return readOpenTextFile(file, fd);
14
+ }
15
+ finally {
16
+ fs.closeSync(fd);
17
+ }
22
18
  }
23
19
  catch (err) {
24
20
  return { ok: false, reason: `${file}: ${errorMessage(err)}` };
25
21
  }
26
22
  }
23
+ /** The checks and the read on one descriptor, so the file measured is the file read. */
24
+ function readOpenTextFile(file, fd) {
25
+ const stat = fs.fstatSync(fd);
26
+ if (!stat.isFile())
27
+ return { ok: false, reason: `${file}: not a file` };
28
+ // A tool rewriting a file truncates it first; read as holding no notes, every row would be set aside.
29
+ if (stat.size === 0)
30
+ return { ok: false, reason: `${file}: empty` };
31
+ if (stat.size > MAX_ITEM_BYTES)
32
+ return { ok: false, reason: `${file}: over ${MAX_ITEM_BYTES} bytes` };
33
+ const buf = fs.readFileSync(fd);
34
+ if (buf.includes(0))
35
+ return { ok: false, reason: `${file}: not text` };
36
+ return { ok: true, text: buf.toString('utf8'), mtimeMs: stat.mtimeMs };
37
+ }
27
38
  /** Files in a folder as '/'-separated relative paths, sorted; dot entries skipped, symlinked folders not followed. */
28
39
  export function listFiles(dir, opts) {
29
40
  if (!fs.existsSync(dir))
@@ -1,6 +1,4 @@
1
- /**
2
- * Splits one markdown memory file into items (a top-level bullet or a paragraph), each tagged with its heading. Pure.
3
- */
1
+ /** Splits one markdown memory file into items (a top-level bullet or a paragraph), each tagged with its heading. Pure. */
4
2
  export interface MarkdownItem {
5
3
  readonly heading: string;
6
4
  readonly headingSlug: string;
@@ -1,6 +1,4 @@
1
- /**
2
- * Splits one markdown memory file into items (a top-level bullet or a paragraph), each tagged with its heading. Pure.
3
- */
1
+ /** Splits one markdown memory file into items (a top-level bullet or a paragraph), each tagged with its heading. Pure. */
4
2
  const HEADING = /^#{1,6}\s+/;
5
3
  // Column 0 only: an indented marker is a sub-bullet and stays inside its item.
6
4
  const BULLET = /^(?:[-*+]|\d+[.)]) /;
@@ -47,7 +47,8 @@ export function totalTally(report) {
47
47
  const plural = (n, one, many) => `${n} ${n === 1 ? one : many}`;
48
48
  const TALLY_WORDS = {
49
49
  imported: 'new', replaced: 'replaced', restored: 'brought back', setAside: 'set aside', untagged: 'pinned and kept',
50
- unchanged: 'unchanged', adopted: 'taken over from the old Claude import', renamed: 'moved to the project id', collapsed: 'duplicates folded', retagged: 'retagged',
50
+ unchanged: 'unchanged', adopted: 'taken over from the old Claude import', renamed: 'moved to the project id', collapsed: 'duplicates folded',
51
+ retagged: 'retagged',
51
52
  handedOver: 'handed over from the global store', duplicate: 'already stored', secret: 'skipped for a secret', short: 'too short',
52
53
  rejected: 'skipped as rejected', unread: 'files skipped', unreadable: 'unreadable folders', busy: 'busy folders',
53
54
  };
@@ -24,9 +24,11 @@ export declare function importForStore(hippoRoot: string, opts: SyncOptions): Im
24
24
  export declare function importProjectMemories(hippoRoot: string, opts: SyncOptions): ImportReport;
25
25
  /** Every tool's user-level memory into the global store, created on demand, with no origin. */
26
26
  export declare function importUserMemories(invokingRoot: string, opts: SyncOptions): ImportReport;
27
- /** Session end in a folder with no store of its own: the session's project into the global store with its origin, the session folder's notes, then the user pass. */
27
+ /** Session end in a folder with no store of its own: the session's project into the
28
+ * global store with its origin, the session folder's notes, then the user pass. */
28
29
  export declare function importAtSessionEnd(cwd: string, transcriptPath: string | undefined, opts: SyncOptions): ImportReport;
29
- /** The session folder's notes under the project Claude filed them for, never cwd's: a session begun at home keeps its home notes user-global wherever it ends. No git call, so post-compact can run it. */
30
+ /** The session folder's notes under the project Claude filed them for, never cwd's: a session begun at
31
+ * home keeps its home notes user-global wherever it ends. No git call, so post-compact can run it. */
30
32
  export declare function importSessionFolder(hippoRoot: string, transcriptPath: string, cwd: string | null, opts: SyncOptions): ImportReport;
31
33
  /** The variable when set (empty or `none` is off); else the tools both the invoking and the target store's config allow. */
32
34
  export declare function allowedTools(env: Machine['env'], invoking: string, target: string, warnings: string[]): Set<ToolId>;
@@ -44,29 +44,34 @@ export function importForStore(hippoRoot, opts) {
44
44
  export function importProjectMemories(hippoRoot, opts) {
45
45
  const ctx = context(opts.machine, { projectRoot: path.dirname(hippoRoot) });
46
46
  return runPass({
47
- scope: 'project', target: hippoRoot, invoking: hippoRoot, list: (a) => a.list(ctx, 'project'), legacy: true, originProject: undefined, legacyOrigins: [], handover: true,
47
+ scope: 'project', target: hippoRoot, invoking: hippoRoot, list: (a) => a.list(ctx, 'project'), legacy: true, originProject: undefined,
48
+ legacyOrigins: [], handover: true,
48
49
  }, opts);
49
50
  }
50
51
  /** Every tool's user-level memory into the global store, created on demand, with no origin. */
51
52
  export function importUserMemories(invokingRoot, opts) {
52
53
  const ctx = context(opts.machine, {});
53
54
  return runPass({
54
- scope: 'user', target: resolveGlobalRootDir(), invoking: invokingRoot, list: (a) => a.list(ctx, 'user'), legacy: false, originProject: '', legacyOrigins: [], handover: false,
55
+ scope: 'user', target: resolveGlobalRootDir(), invoking: invokingRoot, list: (a) => a.list(ctx, 'user'), legacy: false, originProject: '',
56
+ legacyOrigins: [], handover: false,
55
57
  }, opts);
56
58
  }
57
- /** Session end in a folder with no store of its own: the session's project into the global store with its origin, the session folder's notes, then the user pass. */
59
+ /** Session end in a folder with no store of its own: the session's project into the
60
+ * global store with its origin, the session folder's notes, then the user pass. */
58
61
  export function importAtSessionEnd(cwd, transcriptPath, opts) {
59
62
  const globalRoot = resolveGlobalRootDir();
60
63
  const ctx = context(opts.machine, { projectRoot: cwd });
61
64
  const report = runPass({
62
- scope: 'project', target: globalRoot, invoking: globalRoot, list: (a) => a.list(ctx, 'project'), legacy: false, ...projectOrigins(resolveProjectIdentity(cwd)), handover: false,
65
+ scope: 'project', target: globalRoot, invoking: globalRoot, list: (a) => a.list(ctx, 'project'), legacy: false,
66
+ ...projectOrigins(resolveProjectIdentity(cwd)), handover: false,
63
67
  }, opts);
64
68
  if (transcriptPath !== undefined)
65
69
  mergeReports(report, importSessionFolder(globalRoot, transcriptPath, cwd, opts));
66
70
  mergeReports(report, importUserMemories(globalRoot, opts));
67
71
  return report;
68
72
  }
69
- /** The session folder's notes under the project Claude filed them for, never cwd's: a session begun at home keeps its home notes user-global wherever it ends. No git call, so post-compact can run it. */
73
+ /** The session folder's notes under the project Claude filed them for, never cwd's: a session begun at
74
+ * home keeps its home notes user-global wherever it ends. No git call, so post-compact can run it. */
70
75
  export function importSessionFolder(hippoRoot, transcriptPath, cwd, opts) {
71
76
  const project = transcriptNotesProject(transcriptPath, cwd, opts.machine);
72
77
  if (project === null)
@@ -9,19 +9,10 @@ export interface AssembleOpts {
9
9
  /** Substitute parent summaries for older raws when ≥2 share a level-2
10
10
  * ancestor. Default true. */
11
11
  summarizeOlder?: boolean;
12
- /**
13
- * Restrict to a specific scope, same rule as
14
- * `recall`: when set, exact match required (so an authorised caller can
15
- * assemble a `slack:private:CSEC` session by passing scope explicitly).
16
- * When undefined, default-deny applies to ANY `<source>:private:*` and
17
- * `unknown:legacy` rows.
18
- */
12
+ /** Exact scope match when set, so an authorised caller can assemble a private session.
13
+ * When undefined, default-deny applies to every `<source>:private:*` and `unknown:legacy` row. */
19
14
  scope?: string;
20
- /**
21
- * Hard row cap on the SELECT that loads session raws. Default 5000 to
22
- * protect against degenerate sessions. When the cap is hit, `truncated`
23
- * is set on the result so the caller knows to widen.
24
- */
15
+ /** Hard row cap on the SELECT that loads session raws (default 5000); `truncated` is set when it is hit. */
25
16
  rowCap?: number;
26
17
  cost?: AssembleCost;
27
18
  project?: CallerProject;
@@ -51,42 +42,14 @@ export interface AssembleResult {
51
42
  sessionId: string;
52
43
  items: AssembledContextItem[];
53
44
  tokens: number;
54
- /**
55
- * Tenant + scope-filtered raw row count for the session, uncapped by `rowCap`, so
56
- * "session has N msgs" stays accurate when items[] is the windowed view.
57
- */
45
+ /** Tenant + scope-filtered raw row count, uncapped by `rowCap`, so "session has N msgs" stays accurate for a windowed items[]. */
58
46
  totalRaw: number;
59
47
  summarized: number;
60
48
  evicted: number;
61
- /**
62
- * True when `rowCap` truncated the loaded window. The cap keeps the NEWEST
63
- * rows, so the items[] array represents the freshest tail of the session;
64
- * older rows beyond the cap are silently absent. Use `totalRaw - items.length
65
- * - summarized + ...` to estimate how much you didn't see, or widen `rowCap`.
66
- */
49
+ /** True when `rowCap` truncated the window; the cap keeps the NEWEST rows, so older rows beyond it are absent. */
67
50
  truncated: boolean;
68
51
  }
69
- /**
70
- * Build a chronologically-ordered context window for a session. Adapts the
71
- * lossless-claw context-engine pattern to Hippo's score-ranked memory store.
72
- *
73
- * Algorithm:
74
- * 1. Load all kind='raw' rows for the session, tenant + scope filtered.
75
- * 2. Split: newest `freshTailCount` are protected (fresh tail).
76
- * 3. For older rows, when ≥2 share a level-2 parent, substitute the
77
- * summary; everything else passes through as raw.
78
- * 4. Hippo-additive eviction: when over-budget, drop the lowest-strength
79
- * non-fresh-tail item first. Fresh-tail rows are never evicted.
80
- *
81
- * Strength-weighted eviction is the differentiator from lossless-claw,
82
- * which evicts oldest-first. A high-strength older row (high retrieval
83
- * count, slow decay) survives; a low-strength recent row (newer but
84
- * unimportant) goes first.
85
- *
86
- * Returns `items: []` cleanly when:
87
- * - sessionId is empty
88
- * - no raws exist for the session
89
- * - all rows fail the scope/tenant filter
90
- */
52
+ /** Chronological context window for a session; over budget, evicts the lowest-strength non-fresh-tail item first (fresh tail is never evicted).
53
+ * Returns `items: []` for an empty sessionId, no raws, or when every row fails the scope/tenant filter. */
91
54
  export declare function assemble(ctx: Context, sessionId: string, opts?: AssembleOpts): Promise<AssembleResult>;
92
55
  //# sourceMappingURL=assemble.d.ts.map
@@ -6,28 +6,8 @@ import { classifyOriginProject, projectNames } from '../core/project-identity.js
6
6
  const DEFAULT_FRESH_TAIL_COUNT = 10;
7
7
  const DEFAULT_ROW_CAP = 5000;
8
8
  export const DEFAULT_ASSEMBLE_BUDGET = 4000;
9
- /**
10
- * Build a chronologically-ordered context window for a session. Adapts the
11
- * lossless-claw context-engine pattern to Hippo's score-ranked memory store.
12
- *
13
- * Algorithm:
14
- * 1. Load all kind='raw' rows for the session, tenant + scope filtered.
15
- * 2. Split: newest `freshTailCount` are protected (fresh tail).
16
- * 3. For older rows, when ≥2 share a level-2 parent, substitute the
17
- * summary; everything else passes through as raw.
18
- * 4. Hippo-additive eviction: when over-budget, drop the lowest-strength
19
- * non-fresh-tail item first. Fresh-tail rows are never evicted.
20
- *
21
- * Strength-weighted eviction is the differentiator from lossless-claw,
22
- * which evicts oldest-first. A high-strength older row (high retrieval
23
- * count, slow decay) survives; a low-strength recent row (newer but
24
- * unimportant) goes first.
25
- *
26
- * Returns `items: []` cleanly when:
27
- * - sessionId is empty
28
- * - no raws exist for the session
29
- * - all rows fail the scope/tenant filter
30
- */
9
+ /** Chronological context window for a session; over budget, evicts the lowest-strength non-fresh-tail item first (fresh tail is never evicted).
10
+ * Returns `items: []` for an empty sessionId, no raws, or when every row fails the scope/tenant filter. */
31
11
  export async function assemble(ctx, sessionId, opts = {}) {
32
12
  assertScopeRequestAllowed(ctx.actor, opts.scope);
33
13
  const budget = opts.budget ?? DEFAULT_ASSEMBLE_BUDGET;
@@ -1,4 +1,4 @@
1
- import type { AuditEvent, AuditOp } from '../store/audit.js';
1
+ import type { AuditEvent, AuditIssue, AuditOp } from '../store/audit.js';
2
2
  import type { KeysetPosition } from '../util/keyset.js';
3
3
  import type { Context } from './types.js';
4
4
  export interface AuditListOpts {
@@ -11,4 +11,8 @@ export interface AuditListOpts {
11
11
  }
12
12
  /** Read audit events scoped to `ctx.tenantId` on the store the request runs on. Read-only, no audit emit. */
13
13
  export declare function auditList(ctx: Context, opts: AuditListOpts): Promise<AuditEvent[]>;
14
+ /** The pass that removes audit errors; it leads the reason on each forget row. */
15
+ export type AuditPass = 'audit --fix' | 'sleep-audit';
16
+ /** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
17
+ export declare function removeAuditErrors(ctx: Context, pass: AuditPass, issues: readonly AuditIssue[]): string[];
14
18
  //# sourceMappingURL=audit.d.ts.map
package/dist/api/audit.js CHANGED
@@ -1,4 +1,5 @@
1
- // Audit log queries.
1
+ // Audit log queries, and the removal of the memories a quality audit marks as errors.
2
+ import { deleteEntry } from '../store/delete-and-batch.js';
2
3
  import { requireGroup, storeFor } from '../store/index.js';
3
4
  /** Read audit events scoped to `ctx.tenantId` on the store the request runs on. Read-only, no audit emit. */
4
5
  export async function auditList(ctx, opts) {
@@ -6,4 +7,11 @@ export async function auditList(ctx, opts) {
6
7
  tenantId: ctx.tenantId, op: opts.op, since: opts.since, limit: opts.limit, after: opts.after,
7
8
  });
8
9
  }
10
+ /** Delete the memories an audit marked as errors, each with its own forget row, and answer the ids that went: a pinned or raw row stays. */
11
+ export function removeAuditErrors(ctx, pass, issues) {
12
+ return issues
13
+ .filter((issue) => issue.severity === 'error')
14
+ .filter((issue) => deleteEntry(ctx.hippoRoot, issue.memoryId, { actor: ctx.actor.subject, reason: `${pass}: ${issue.reason}`, automatic: true }))
15
+ .map((issue) => issue.memoryId);
16
+ }
9
17
  //# sourceMappingURL=audit.js.map
@@ -3,13 +3,12 @@ import type { KeysetPosition } from '../util/keyset.js';
3
3
  import type { Context, StoreReply } from './types.js';
4
4
  export interface AuthCreateOpts {
5
5
  label?: string;
6
- /**
7
- * Authorization role for the new key. Defaults to `'admin'` for
8
- * back-compat with keys minted before roles existed (the api_keys.role column DEFAULT also
9
- * resolves to 'admin' if omitted from the INSERT). Member keys are
10
- * 403-blocked from admin-gated routes (e.g. `POST /v1/sleep`).
11
- */
6
+ /** Defaults to `'member'`, which admin-gated routes such as `POST /v1/sleep` refuse; an admin key has to be asked for by name. */
12
7
  role?: 'admin' | 'member';
8
+ /** Days until the key expires: above 0 and at most 3650. Defaults to 90. */
9
+ ttlDays?: number;
10
+ /** True mints a key that never expires, which has to be asked for by name; refused together with `ttlDays`. */
11
+ noExpiry?: boolean;
13
12
  }
14
13
  export interface AuthCreateResult {
15
14
  keyId: string;
@@ -17,18 +16,11 @@ export interface AuthCreateResult {
17
16
  tenantId: string;
18
17
  /** The role bound to the new key (admin | member). */
19
18
  role: 'admin' | 'member';
19
+ /** ISO time the key stops working; null for a key that never expires. */
20
+ expiresAt: string | null;
20
21
  }
21
- /**
22
- * Mint a new API key. The new key is ALWAYS bound to `ctx.tenantId`. Callers
23
- * cannot override the tenant via the opts bag — a previous `tenantId` field
24
- * was removed because the HTTP layer would happily forward `body.tenantId`,
25
- * letting tenant A mint a key for tenant B. The HTTP route handler at
26
- * `src/server.ts` POST /v1/auth/keys mirrors this: it ignores any body
27
- * `tenantId` and uses the resolved Bearer's tenant exclusively.
28
- *
29
- * Only an admin actor can mint (ForbiddenError otherwise), and a key never
30
- * outranks its minter: a resolver admin is tenant-only, so it mints members.
31
- */
22
+ /** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
23
+ * Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
32
24
  export declare function authCreate<C extends Context>(ctx: C, opts: AuthCreateOpts): StoreReply<C, AuthCreateResult>;
33
25
  export interface AuthCreateSelfOpts {
34
26
  label?: string;
@@ -41,7 +33,8 @@ export interface AuthCreateSelfResult extends AuthCreateResult {
41
33
  /** ISO time the key stops working. */
42
34
  expiresAt: string;
43
35
  }
44
- /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
36
+ /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
37
+ * binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
45
38
  export declare function authCreateSelf<C extends Context>(ctx: C, opts: AuthCreateSelfOpts): StoreReply<C, AuthCreateSelfResult>;
46
39
  type KeyListOpts = {
47
40
  active: boolean;
@@ -58,10 +51,8 @@ export type AuthRevokeReply<C extends Context> = StoreReply<C, AuthRevokeResult>
58
51
  /** Revoke a key in the caller's tenant: a member API key may revoke only itself, a resolver member only the keys it minted.
59
52
  * The revoke and its auth_revoke row commit together on either store, so a failed audit write leaves the key live. */
60
53
  export declare function authRevoke<C extends Context>(ctx: C, keyId: string): AuthRevokeReply<C>;
61
- /**
62
- * The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
63
- * so the local CLI can run revoke and grant in the key's own tenant.
64
- */
54
+ /** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
55
+ * so the local CLI can run revoke and grant in the key's own tenant. */
65
56
  export declare function authKeyTenant(ctx: Context, keyId: string): string | undefined;
66
57
  /** Shared result shape for authGrant/authUngrant, named per the file's oxlint anti-slop rule. */
67
58
  export interface AuthGrantResult {
package/dist/api/auth.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // API key management: create, list, revoke, and grant or ungrant restricted scopes.
2
- import { ForbiddenError, NotFoundError } from '../core/api-errors.js';
2
+ import { BadRequestError, ForbiddenError, NotFoundError } from '../core/api-errors.js';
3
3
  import { mintApiKey, } from '../store/auth.js';
4
4
  import { changeScopeGrant } from '../store/sqlite/local.js';
5
5
  import { sqliteSyncStore } from '../store/sqlite/store.js';
@@ -10,17 +10,8 @@ const API_KEY_SUBJECT = 'api_key:';
10
10
  function keyIdOfSubject(subject) {
11
11
  return subject.startsWith(API_KEY_SUBJECT) ? subject.slice(API_KEY_SUBJECT.length) : null;
12
12
  }
13
- /**
14
- * Mint a new API key. The new key is ALWAYS bound to `ctx.tenantId`. Callers
15
- * cannot override the tenant via the opts bag — a previous `tenantId` field
16
- * was removed because the HTTP layer would happily forward `body.tenantId`,
17
- * letting tenant A mint a key for tenant B. The HTTP route handler at
18
- * `src/server.ts` POST /v1/auth/keys mirrors this: it ignores any body
19
- * `tenantId` and uses the resolved Bearer's tenant exclusively.
20
- *
21
- * Only an admin actor can mint (ForbiddenError otherwise), and a key never
22
- * outranks its minter: a resolver admin is tenant-only, so it mints members.
23
- */
13
+ /** Mints a key always bound to `ctx.tenantId`; opts cannot override the tenant, or tenant A could mint a key for tenant B.
14
+ * Admin only (ForbiddenError otherwise), and a key never outranks its minter: a resolver admin is tenant-only, so it mints members. */
24
15
  export function authCreate(ctx, opts) {
25
16
  // The key and its auth_create row commit together on either store, so a failed audit write leaves no key.
26
17
  return onStore(ctx, (port) => {
@@ -34,6 +25,23 @@ function newKey(ctx, fields) {
34
25
  const { keyId, plaintext, keyHash } = mintApiKey();
35
26
  return { plaintext, key: { ...fields, keyId, keyHash, tenantId: ctx.tenantId, createdAt: new Date().toISOString() } };
36
27
  }
28
+ /** Days a key lives when its mint names no expiry, so a key nobody remembers stops working by itself. */
29
+ const DEFAULT_KEY_TTL_DAYS = 90;
30
+ // The ceiling keeps toISOString in range.
31
+ const MAX_TTL_DAYS = 3650;
32
+ /** A 400, not a RangeError, since the caller of the mint chose these. */
33
+ function mintExpiry({ ttlDays, noExpiry }) {
34
+ if (noExpiry && ttlDays !== undefined) {
35
+ throw new BadRequestError('send ttlDays or noExpiry, not both');
36
+ }
37
+ if (noExpiry)
38
+ return null;
39
+ const days = ttlDays ?? DEFAULT_KEY_TTL_DAYS;
40
+ if (!Number.isFinite(days) || days <= 0 || days > MAX_TTL_DAYS) {
41
+ throw new BadRequestError(`ttlDays must be above 0 and at most ${MAX_TTL_DAYS}`);
42
+ }
43
+ return new Date(Date.now() + days * DAY_MS).toISOString();
44
+ }
37
45
  function adminKeyMint(ctx, opts) {
38
46
  if (ctx.actor.role !== 'admin') {
39
47
  throw new ForbiddenError('Only an admin key can create API keys');
@@ -41,16 +49,16 @@ function adminKeyMint(ctx, opts) {
41
49
  if (ctx.actor.viaAuthResolver && opts.role === 'admin') {
42
50
  throw new ForbiddenError('A key minted through the auth resolver can only be a member key');
43
51
  }
44
- const role = opts.role ?? (ctx.actor.viaAuthResolver ? 'member' : 'admin');
52
+ const role = opts.role ?? 'member';
45
53
  const label = opts.label ?? null;
46
- const { plaintext, key } = newKey(ctx, { label, role, ownerSubject: null, expiresAt: null });
47
- // The plaintext is NEVER logged; metadata carries label + role, keyId is non-secret.
48
- return { plaintext, mint: { key, actor: ctx.actor.subject, metadata: { label, role } } };
54
+ const expiresAt = mintExpiry(opts);
55
+ const { plaintext, key } = newKey(ctx, { label, role, ownerSubject: null, expiresAt });
56
+ // The plaintext is NEVER logged; the audit row carries what the key can do and for how long, keyId is non-secret.
57
+ return { plaintext, mint: { key, actor: ctx.actor.subject, metadata: { label, role, expiresAt } } };
49
58
  }
50
59
  function createResult({ key }, plaintext) {
51
- return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: key.role };
60
+ return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: key.role, expiresAt: key.expiresAt };
52
61
  }
53
- const MAX_TTL_DAYS = 3650;
54
62
  /** A RangeError, not a 4xx, since the operator's config sets these; the ttl ceiling keeps toISOString in range and a departed user's key short-lived. */
55
63
  function assertSelfMintOpts({ ttlDays, perSubject }) {
56
64
  if (!Number.isFinite(ttlDays) || ttlDays <= 0 || ttlDays > MAX_TTL_DAYS) {
@@ -60,7 +68,8 @@ function assertSelfMintOpts({ ttlDays, perSubject }) {
60
68
  throw new RangeError(`authCreateSelf: perSubject must be a whole number of at least 1, got ${String(perSubject)}`);
61
69
  }
62
70
  }
63
- /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
71
+ /** Mint a member key for the caller an auth resolver vouched for, whatever its role; the
72
+ * binary floor, the cap's revokes, the mint and its audit rows commit or fail together. */
64
73
  export function authCreateSelf(ctx, opts) {
65
74
  return onStore(ctx, (port) => {
66
75
  const keyWrites = port.keyWrites ?? notPorted(port, 'keyWrites');
@@ -79,7 +88,10 @@ function selfKeyMint(ctx, opts) {
79
88
  // Not destructured: a binding pattern makes TypeScript infer F as KeyFields and lose ownerSubject's string type.
80
89
  const made = newKey(ctx, { label, role: 'member', ownerSubject: subject, expiresAt });
81
90
  // Same op and actor as an admin mint, so a lookup by audit row finds this key too.
82
- return { plaintext: made.plaintext, mint: { key: made.key, actor: subject, metadata: { label, role: 'member', self: true, expiresAt }, perSubject: opts.perSubject } };
91
+ return {
92
+ plaintext: made.plaintext,
93
+ mint: { key: made.key, actor: subject, metadata: { label, role: 'member', self: true, expiresAt }, perSubject: opts.perSubject }
94
+ };
83
95
  }
84
96
  function selfResult({ key }, plaintext) {
85
97
  return { keyId: key.keyId, plaintext, tenantId: key.tenantId, role: 'member', expiresAt: key.expiresAt };
@@ -146,10 +158,8 @@ function assertMemberKeyRevokesSelf(ctx, keyId) {
146
158
  function keyOwnerOf(record) {
147
159
  return record ? { tenantId: record.tenantId, revokedAt: record.revokedAt, role: record.role, ownerSubject: record.ownerSubject ?? null } : undefined;
148
160
  }
149
- /**
150
- * The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
151
- * so the local CLI can run revoke and grant in the key's own tenant.
152
- */
161
+ /** The tenant that owns `keyId`, or undefined for an unknown key. Host admin only: it reads across tenants,
162
+ * so the local CLI can run revoke and grant in the key's own tenant. */
153
163
  export function authKeyTenant(ctx, keyId) {
154
164
  if (!ctx.actor.hostAdmin) {
155
165
  throw new ForbiddenError('Only the host admin can look up a key across tenants');
@@ -1,5 +1,5 @@
1
1
  // When a write starts a background sleep; the MCP remember tool and the session-close hook share it.
2
- import { errorMessage, log } from '../util/log.js';
2
+ import { errorFields, errorMessage, log } from '../util/log.js';
3
3
  import { countCreatedSinceLastSleep } from '../store/index-and-stats.js';
4
4
  import { consolidate } from '../consolidate/sleep.js';
5
5
  import { outsideRequestStores, runWithRequestStores, scopedBusyWait } from '../db/index.js';
@@ -25,7 +25,7 @@ export function startAutoSleepIfDue(hippoRoot, tenantId, config, allowed) {
25
25
  const busyWaitMs = scopedBusyWait();
26
26
  outsideRequestStores(() => runWithRequestStores(() => consolidate(hippoRoot), { busyWaitMs }))
27
27
  .catch((err) => {
28
- log.error(`auto-sleep consolidate failed (tenant ${tenantId}): ${errorMessage(err)}`);
28
+ log.error(`auto-sleep consolidate failed (tenant ${tenantId}): ${errorMessage(err)}`, errorFields(err));
29
29
  })
30
30
  .finally(() => autoSleepInFlight.delete(hippoRoot));
31
31
  }
@@ -46,20 +46,7 @@ export declare const DEFAULT_RECENT_FRACTION_THRESHOLD = 0.7;
46
46
  export declare const DEFAULT_MIN_RETURNED = 3;
47
47
  export declare const DEFAULT_MIN_POOL = 10;
48
48
  export declare const DEFAULT_MIN_OLDER_PASSED_OVER = 3;
49
- /**
50
- * Detect availability/recency bias in a recall result.
51
- *
52
- * Returns an AvailabilityHint when ALL of the following hold:
53
- * 1. topK.length >= minReturned AND pool.length >= minPool (enough signal);
54
- * 2. recentFraction > recentFractionThreshold (returned slice is recency-dominated);
55
- * 3. poolMedianAgeDays > topKMedianAgeDays (the pool genuinely skews older,
56
- * so recency is not just the corpus being young);
57
- * 4. olderCandidatesPassedOver >= minOlderPassedOver (older matched memories
58
- * actually existed and were not returned).
59
- * Otherwise returns null.
60
- *
61
- * Entries with an unparseable `created` are dropped defensively so a malformed
62
- * row cannot poison the medians with NaN.
63
- */
49
+ /** Returns an AvailabilityHint when the returned slice is recency-dominated, the pool skews older and older matches were passed over; else null.
50
+ * Entries with an unparseable `created` are dropped so a malformed row cannot poison the medians with NaN. */
64
51
  export declare function detectAvailabilityBias(opts: DetectAvailabilityBiasOpts): AvailabilityHint | null;
65
52
  //# sourceMappingURL=availability.d.ts.map
@@ -17,21 +17,8 @@ function parseTimestamps(refs) {
17
17
  .map((e) => ({ id: e.id, ts: Date.parse(e.created) }))
18
18
  .filter((e) => Number.isFinite(e.ts));
19
19
  }
20
- /**
21
- * Detect availability/recency bias in a recall result.
22
- *
23
- * Returns an AvailabilityHint when ALL of the following hold:
24
- * 1. topK.length >= minReturned AND pool.length >= minPool (enough signal);
25
- * 2. recentFraction > recentFractionThreshold (returned slice is recency-dominated);
26
- * 3. poolMedianAgeDays > topKMedianAgeDays (the pool genuinely skews older,
27
- * so recency is not just the corpus being young);
28
- * 4. olderCandidatesPassedOver >= minOlderPassedOver (older matched memories
29
- * actually existed and were not returned).
30
- * Otherwise returns null.
31
- *
32
- * Entries with an unparseable `created` are dropped defensively so a malformed
33
- * row cannot poison the medians with NaN.
34
- */
20
+ /** Returns an AvailabilityHint when the returned slice is recency-dominated, the pool skews older and older matches were passed over; else null.
21
+ * Entries with an unparseable `created` are dropped so a malformed row cannot poison the medians with NaN. */
35
22
  export function detectAvailabilityBias(opts) {
36
23
  const now = opts.now ?? Date.now();
37
24
  const recencyWindowMs = opts.recencyWindowMs ?? DEFAULT_RECENCY_WINDOW_MS;
@@ -4,7 +4,7 @@ import { heldIdLookup } from '../store/entry-reads.js';
4
4
  import { calculateStrength } from '../core/memory.js';
5
5
  import { auditQueryFields, recordAuditEvent } from '../store/audit.js';
6
6
  import { isWorthSurfacing } from '../core/memory-quality.js';
7
- import { rankBothStores } from '../sharing/shared.js';
7
+ import { rankBothStores } from '../sharing/search-both.js';
8
8
  import { evalNow } from '../core/ablation.js';
9
9
  import { hybridSearch } from '../search/hybrid.js';
10
10
  import { physicsSearch } from '../search/physics-search.js';
@@ -51,9 +51,8 @@ export function selectPinned(opts, plan, left, pools, admission) {
51
51
  const [localPool, globalPool] = oneCopyPerMemory(localEntries, globalEntries, nowP);
52
52
  obs?.dropMissing([...localEntries, ...globalEntries], [...localPool, ...globalPool], 'load', 'duplicate');
53
53
  const picked = { items: [], ids: new Set(), used: 0 };
54
- // Pinned entries are explicit user intent, the recent-N list an automatic
55
- // backfill. Both loops share ONE budget and the recent loop runs first, so
56
- // pins are ranked here and reserve their share before it can spend.
54
+ // Pinned entries are explicit intent, the recent-N list an automatic backfill; both share ONE budget and the recent loop runs first,
55
+ // so pins are ranked here and reserve their share before it can spend.
57
56
  const pinnedLocal = localPool.filter((e) => e.pinned);
58
57
  const pinnedGlobal = globalPool.filter((e) => e.pinned);
59
58
  const rankedPinned = rankPinned(plan, pinnedLocal, pinnedGlobal, nowP);