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,46 +1,28 @@
1
1
  import { existsSync, readFileSync, writeFileSync, unlinkSync, renameSync } from 'node:fs';
2
2
  import { join } from 'node:path';
3
3
  import { envHealthProbeMs } from '../util/env.js';
4
- // Pidfile sits directly inside hippoRoot. `hippoRoot` is the `.hippo`
5
- // directory itself (the same convention used by api.ts / store.ts /
6
- // openHippoDb), so this resolves to `${hippoRoot}/server.pid`.
4
+ // Pidfile sits directly inside hippoRoot (the `.hippo` directory itself, as for openHippoDb), i.e. `${hippoRoot}/server.pid`.
7
5
  const PIDFILE = 'server.pid';
8
- /**
9
- * How long detectServer waits for the `/health` liveness probe before
10
- * treating the pidfile as stale. Short by design: the probe only fires on
11
- * the rare path where a pidfile exists and its pid is live, and the target
12
- * is always loopback, so a healthy server answers well within this bound. HIPPO_HEALTH_PROBE_MS overrides it.
13
- */
6
+ /** How long detectServer waits for the `/health` probe before treating the pidfile as stale; short because it fires only when a pidfile exists with a live
7
+ * pid on loopback. HIPPO_HEALTH_PROBE_MS overrides it. */
14
8
  const HEALTH_PROBE_TIMEOUT_MS = 300;
15
- /**
16
- * Hard cap on the /health response body detectServer will buffer. A real
17
- * hippo /health payload is well under 1 KB; a larger body means the process
18
- * answering on the recorded port is not hippo, so the pidfile is stale.
19
- */
9
+ /** Hard cap on the /health body detectServer buffers: a real payload is well under 1 KB, so a larger body means the process on the recorded port is not
10
+ * hippo. */
20
11
  const HEALTH_BODY_MAX_BYTES = 64 * 1024;
21
- /**
22
- * Loopback hosts the recorded pidfile url is allowed to point at. serve()
23
- * only binds these (it mirrors LOOPBACK_HOSTS in server.ts); a pidfile url
24
- * with any other host is malformed or forged and must not be probed.
25
- */
12
+ /** Loopback hosts a recorded pidfile url may point at (serve() only binds these); any other host is malformed or forged and is not probed. */
26
13
  const PIDFILE_LOOPBACK_HOSTS = new Set(['127.0.0.1', '::1', 'localhost']);
27
14
  /** False when the pidfile's pid is dead or its url could not be one serve() wrote. */
28
15
  function isLiveLoopbackTarget(info) {
29
- // Probe the process. Sending signal 0 throws if the pid is dead or owned
30
- // by another user we cannot signal. Either way, treat as stale.
31
- // Node's process.kill(pid, 0) is implemented on Windows via OpenProcess +
32
- // GetExitCodeProcess, so this works cross-platform for the dead-pid case.
16
+ // Signal 0 throws if the pid is dead or owned by another user we cannot signal; either way, treat as stale.
17
+ // process.kill(pid, 0) works cross-platform for the dead-pid case (OpenProcess + GetExitCodeProcess on Windows).
33
18
  try {
34
19
  process.kill(info.pid, 0);
35
20
  }
36
21
  catch {
37
22
  return false;
38
23
  }
39
- // The pid is live, but it may have been reused by an unrelated process, and
40
- // the recorded url is read from a file anyone could forge. serve() only ever
41
- // binds a loopback host, so a url that is not http on a loopback host and the
42
- // recorded port is malformed or forged. Reject it before probing: the probe,
43
- // and the routed request that may follow, can carry HIPPO_API_KEY.
24
+ // The pid may have been reused and the recorded url is read from a forgeable file; serve() only binds loopback, so a url that is not http on a loopback
25
+ // host and the recorded port is malformed or forged. Reject it before probing, since the probe and any routed request can carry HIPPO_API_KEY.
44
26
  let probeUrl;
45
27
  try {
46
28
  probeUrl = new URL(info.url);
@@ -54,9 +36,8 @@ function isLiveLoopbackTarget(info) {
54
36
  }
55
37
  /** The whole body as text, or null once it passes HEALTH_BODY_MAX_BYTES (the stream is then cancelled). */
56
38
  async function readCappedBody(body) {
57
- // Read the body under a hard byte cap. The process answering on info.url
58
- // may not be hippo (pid reuse is the case this probe guards against), so
59
- // its response is untrusted: never hand an unbounded stream to a parser.
39
+ // Read the body under a hard byte cap: the process on info.url may not be hippo (pid reuse), so its response is untrusted and never goes unbounded into a
40
+ // parser.
60
41
  const reader = body.getReader();
61
42
  const decoder = new TextDecoder();
62
43
  let raw = '';
@@ -77,12 +58,8 @@ async function readCappedBody(body) {
77
58
  }
78
59
  /** True when /health on info.url reports the pidfile's started_at; unlinks the pidfile on any definitive mismatch. */
79
60
  async function healthMatchesPidfile(hippoRoot, info) {
80
- // Confirm the process answering on info.url is this hippo server by matching
81
- // the /health `started_at` against the pidfile. A connection refusal, a
82
- // non-200, or a malformed body unlink the pidfile as stale. A probe timeout
83
- // is deliberately left ambiguous: a live but momentarily-busy server (e.g.
84
- // blocked on a synchronous query) can miss the 300ms window, so a timeout
85
- // returns null WITHOUT unlinking. The pidfile survives for the next probe.
61
+ // Confirm the answering process is this server by matching /health `started_at` against the pidfile; refusal, non-200 or a malformed body unlink the
62
+ // pidfile as stale. A probe timeout is ambiguous (a live but busy server can miss the 300ms window), so it returns null WITHOUT unlinking.
86
63
  try {
87
64
  const res = await fetch(`${info.url}/health`, {
88
65
  signal: AbortSignal.timeout(envHealthProbeMs() ?? HEALTH_PROBE_TIMEOUT_MS),
@@ -104,32 +81,16 @@ async function healthMatchesPidfile(hippoRoot, info) {
104
81
  return true;
105
82
  }
106
83
  catch (err) {
107
- // A timeout is ambiguous (the server may be alive but busy), so keep the
108
- // pidfile. Any other failure (connection refused, malformed body) is
109
- // definitive: unlink it as stale.
110
- // SAFETY: err's shape is unknown (catch clause); reading an optional
111
- // .name property structurally is safe regardless of the object's actual type.
84
+ // A timeout is ambiguous (the server may be busy), so keep the pidfile; any other failure (refused, malformed body) is definitive: unlink as stale.
85
+ // SAFETY: err's shape is unknown (catch clause); reading an optional .name property structurally is safe regardless of the actual type.
112
86
  if (err?.name !== 'TimeoutError') {
113
87
  removePidfile(hippoRoot);
114
88
  }
115
89
  return false;
116
90
  }
117
91
  }
118
- /**
119
- * Read .hippo/server.pid and return the embedded ServerInfo if a live hippo
120
- * server is genuinely answering on the recorded url. Returns null on missing,
121
- * malformed, or stale pidfiles, and best-effort unlinks the file in the
122
- * stale/malformed cases.
123
- *
124
- * Liveness is proven in two steps. `process.kill(pid, 0)` rules out dead
125
- * pids. But a pid can be reused by an unrelated process, so a GET /health
126
- * then confirms the process that answers is *this* hippo server: its
127
- * `started_at` must equal the pidfile's. A mismatch, non-200, malformed
128
- * body, or timeout all mean the pidfile is stale.
129
- *
130
- * The /health probe runs only when a pidfile exists and the pid is live, so
131
- * the common no-server path stays a single fast file existence check.
132
- */
92
+ /** Returns the pidfile's ServerInfo if a live hippo server answers on the recorded url, else null (best-effort unlinking of missing/stale/malformed pidfiles).
93
+ * `process.kill(pid, 0)` rules out dead pids; GET /health must then return the pidfile's `started_at` (pids get reused). Probes only if the pid is live. */
133
94
  export async function detectServer(hippoRoot) {
134
95
  const path = join(hippoRoot, PIDFILE);
135
96
  if (!existsSync(path))
@@ -148,14 +109,8 @@ export async function detectServer(hippoRoot) {
148
109
  }
149
110
  return (await healthMatchesPidfile(hippoRoot, info)) ? info : null;
150
111
  }
151
- /**
152
- * Atomically write the pidfile. Writes to a process-scoped temp file then
153
- * renames into place, which is atomic on POSIX and on NTFS via MoveFileEx.
154
- *
155
- * `startedAt` is supplied by the caller (`serve()`) rather than generated
156
- * here, so the pidfile and the server's GET /health response carry the same
157
- * timestamp — detectServer's liveness probe compares the two for equality.
158
- */
112
+ /** Atomically writes the pidfile (process-scoped temp file, then rename; atomic on POSIX and NTFS). `startedAt` comes from the caller (`serve()`) so the
113
+ * pidfile and GET /health carry the same timestamp, which detectServer's liveness probe compares. */
159
114
  export function writePidfile(hippoRoot, opts) {
160
115
  const path = join(hippoRoot, PIDFILE);
161
116
  const tmp = `${path}.tmp.${process.pid}`;
@@ -169,13 +124,8 @@ export function writePidfile(hippoRoot, opts) {
169
124
  writeFileSync(tmp, JSON.stringify(info));
170
125
  renameSync(tmp, path);
171
126
  }
172
- /**
173
- * Best-effort pidfile removal. Silent on ENOENT or any other error so the
174
- * caller can use this in shutdown paths without fear of throwing.
175
- *
176
- * Identity-blind: deletes whatever pidfile is on disk. A shutdown path that
177
- * must not clobber a newer server's pidfile should use removePidfileIfOwned.
178
- */
127
+ /** Best-effort pidfile removal, silent on any error so shutdown paths can call it. Identity-blind: a shutdown that must not clobber a newer server's pidfile
128
+ * uses removePidfileIfOwned. */
179
129
  export function removePidfile(hippoRoot) {
180
130
  const path = join(hippoRoot, PIDFILE);
181
131
  try {
@@ -183,24 +133,8 @@ export function removePidfile(hippoRoot) {
183
133
  }
184
134
  catch { /* already gone or undeletable; the next detectServer probe re-checks */ }
185
135
  }
186
- /**
187
- * Remove the pidfile only if it still describes the caller's own server.
188
- * Reads and parses the pidfile and unlinks it ONLY when both `pid` and
189
- * `started_at` match `owner`. A pidfile rewritten by a newer server is left
190
- * intact, so a shutting-down older server cannot orphan the newer one by
191
- * deleting its pidfile out from under it.
192
- *
193
- * Best-effort and never throws: a missing, unreadable, malformed, or
194
- * non-object pidfile (including a literal JSON `null`) is "not provably mine"
195
- * and left alone — detectServer unlinks a malformed pidfile on its next
196
- * probe, so it does not leak. Returns true iff a matching pidfile was removed.
197
- *
198
- * Residual TOCTOU: the pidfile could be rewritten between the read and the
199
- * unlink. The window is microseconds and the shape is the same read-check-
200
- * unlink detectServer already uses; this narrows the clobber from an
201
- * unbounded window (any time between writePidfile and stop) to a negligible
202
- * one.
203
- */
136
+ /** Removes the pidfile ONLY when both `pid` and `started_at` match `owner`, so an older shutting-down server cannot orphan a newer one; never throws.
137
+ * Anything unreadable or malformed is "not provably mine" and left alone (detectServer unlinks it). Returns true iff removed. */
204
138
  export function removePidfileIfOwned(hippoRoot, owner) {
205
139
  const path = join(hippoRoot, PIDFILE);
206
140
  try {
@@ -23,7 +23,10 @@ function runInChild(job) {
23
23
  const deadlineMs = envSleepTimeoutMs() ?? DEFAULT_SLEEP_DEADLINE_MS;
24
24
  return new Promise((resolve, reject) => {
25
25
  // The child's stderr is the server's log, so Node's SQLite notice would repeat there on every sleep.
26
- const child = spawn(process.execPath, ['--disable-warning=ExperimentalWarning', CHILD_ENTRY], { stdio: ['ignore', 'inherit', 'inherit', 'ipc'], windowsHide: true });
26
+ const child = spawn(process.execPath, ['--disable-warning=ExperimentalWarning', CHILD_ENTRY], {
27
+ stdio: ['ignore', 'inherit', 'inherit', 'ipc'],
28
+ windowsHide: true
29
+ });
27
30
  let reply;
28
31
  let timedOut = false;
29
32
  // SIGKILL because the child is inside synchronous SQLite work and cannot run a handler; the OS drops its write lock.
@@ -7,17 +7,16 @@ export interface ServerHandle {
7
7
  port: number;
8
8
  url: string;
9
9
  stop: () => Promise<void>;
10
- /** Introspection-only: the underlying node:http Server, exposed so
11
- * tests can assert keep-alive/headers timeout hardening without reaching
12
- * into serve()'s closure. Additive field — do not depend on it for control
13
- * flow outside tests. */
10
+ /** Introspection-only: the underlying node:http Server, so tests can assert keep-alive/headers timeout hardening without reaching into serve()'s closure.
11
+ * Do not use for control flow. */
14
12
  server?: import('node:http').Server;
15
13
  }
16
14
  /** Identity an {@link AuthResolver} vouches for. The core sanitises it before use. */
17
15
  export interface ResolvedBearer {
18
16
  tenantId: string;
19
17
  subject: string;
20
- /** Not 'admin' means 'member'. Admin is tenant-only, yet can mint member API keys (POST /v1/auth/keys); an add-on revokes them through the exported authRevoke when the IdP deprovisions the minter. */
18
+ /** Not 'admin' means 'member'. Admin is tenant-only, yet can mint member API keys (POST /v1/auth/keys);
19
+ * an add-on revokes them through the exported authRevoke when the IdP deprovisions the minter. */
21
20
  role: 'admin' | 'member';
22
21
  scopes?: readonly string[];
23
22
  }
@@ -28,7 +27,8 @@ export interface AddonCall {
28
27
  readonly ctx: Context;
29
28
  readonly body: Readonly<Record<string, JsonValue>>;
30
29
  }
31
- /** A POST /v1 route an add-on mounts through serve(): core authenticates and parses first, then sends the returned value as 200 JSON. Under another store it runs only when that store has its `storeReady` group. */
30
+ /** A POST /v1 route an add-on mounts through serve(): core authenticates and parses first, then sends the
31
+ * returned value as 200 JSON. Under another store it runs only when that store has its `storeReady` group. */
32
32
  export interface AddonRoute {
33
33
  readonly path: string;
34
34
  readonly handler: (call: AddonCall) => Promise<JsonValue>;
@@ -46,7 +46,8 @@ export interface ServeOpts {
46
46
  authResolverTimeoutMs?: number;
47
47
  port?: number;
48
48
  host?: string;
49
- /** Stop and exit on SIGINT/SIGTERM, and drain then exit 1 on an uncaught exception or unhandled rejection. Only `hippo serve` owns the process, so only it sets this. */
49
+ /** Stop and exit on SIGINT/SIGTERM, and drain then exit 1 on an uncaught exception or unhandled rejection. A stop still running
50
+ * 10 s past `shutdownDrainMs` ends the process with a failure exit. Only `hippo serve` owns the process, so only it sets this. */
50
51
  handleSignals?: boolean;
51
52
  /** How long stop() lets in-flight requests finish before closing their sockets; defaults to 5000 ms. */
52
53
  shutdownDrainMs?: number;
@@ -59,7 +60,8 @@ export interface ServeOpts {
59
60
  mintBodyDeadlineMs?: number;
60
61
  /** Tests only: shortens the wait for a signed webhook's body, which defaults to 10 s. */
61
62
  webhookBodyDeadlineMs?: number;
62
- /** PEM certificate and key: serve() then answers HTTPS only. Unset means cleartext HTTP, which needs a TLS-terminating proxy in front on any non-loopback bind. */
63
+ /** PEM certificate and key: serve() then answers HTTPS only. Unset means cleartext
64
+ * HTTP, which needs a TLS-terminating proxy in front on any non-loopback bind. */
63
65
  tls?: {
64
66
  cert: string | Buffer;
65
67
  key: string | Buffer;
@@ -94,8 +96,8 @@ type StoreStatus = {
94
96
  sqliteOnly: string;
95
97
  storeReady?: never;
96
98
  };
97
- /** One /v1 route: an exact path, a matchPath pattern, or a regex, each paired with the handler for one method. Under another store it runs only when that store has its `storeReady` group; a `sqliteOnly` route never does.
98
- * `loop: 'off'` declares that the route's SQLite work runs on a worker thread, so its handler opens no hippo.db on the server thread. */
99
+ /** One /v1 route: an exact path, a matchPath pattern, or a regex, each paired with one method's handler. Under another store it runs only with its
100
+ * store's `storeReady` group; `loop: 'off'` runs its SQLite work on a worker thread, so the handler opens no hippo.db on the server thread. */
99
101
  export type Route = {
100
102
  method: string;
101
103
  loop?: 'off';
@@ -2,9 +2,11 @@ import type { IncomingMessage } from 'node:http';
2
2
  import type { Context, RememberOpts } from '../api/index.js';
3
3
  import { type JsonValue } from '../util/json.js';
4
4
  export declare function isSetMember<T extends string>(set: ReadonlySet<T>, value: string): value is T;
5
+ export declare const MAX_SHORT_FIELD_LEN = 4096;
5
6
  export declare const MAX_LIST_LIMIT = 1000;
6
7
  export declare function parseListLimit(limitRaw: string | null, defaultLimit?: number, maxLimit?: number): number;
7
- /** `_authed` is proof the caller passed auth, so a full-size body is read only for an authenticated caller; the key mint reads first under its own small cap. */
8
+ /** `_authed` is proof the caller passed auth, so a full-size body is read only for
9
+ * an authenticated caller; the key mint reads first under its own small cap. */
8
10
  export declare function parseJsonBody(req: IncomingMessage, _authed: Context): Promise<Record<string, JsonValue>>;
9
11
  export declare function parseJsonObjectText(raw: string): Record<string, JsonValue>;
10
12
  export declare function getString(obj: Record<string, JsonValue>, key: string): string | undefined;
@@ -1,18 +1,13 @@
1
1
  import { HttpError, MAX_ID_LEN, readBody } from '../util/http-util.js';
2
2
  import { isJsonString, isJsonObject } from '../util/json.js';
3
- // Runtime membership check for a `ReadonlySet<T>` of string-literal union
4
- // members, used at every `body` field validated against a VALID_* set below.
5
- // Set<T>.has(value: T) itself gives no narrowing (its parameter type is T,
6
- // not a type predicate) so callers previously needed a separate `as T` cast
7
- // at both the check and the later usage; this helper is the one place that
8
- // assertion lives, so downstream call sites narrow via the `value is T`
9
- // return instead of re-asserting.
3
+ // Runtime membership check for a `ReadonlySet<T>` of string-literal members: Set<T>.has gives no narrowing, so this is the one place the `as T` assertion lives
4
+ // and callers narrow via the `value is T` return.
10
5
  export function isSetMember(set, value) {
11
- // SAFETY: `value as T` is discarded unless `set.has` (the real runtime
12
- // check) confirms membership; the `value is T` return type is what
13
- // performs the actual narrowing for callers.
6
+ // SAFETY: `value as T` is discarded unless `set.has` (the real runtime check) confirms membership; the `value is T` return type does the narrowing.
14
7
  return set.has(value);
15
8
  }
9
+ // Cap for short free-text HTTP fields (names, text, context, change summaries) on the object routes.
10
+ export const MAX_SHORT_FIELD_LEN = 4096;
16
11
  // Number.isInteger, not isFinite: SQLite `LIMIT ?` rejects "1.5" with a 500.
17
12
  // Shared by every first-class-object list route so the guard cannot drift.
18
13
  export const MAX_LIST_LIMIT = 1000;
@@ -25,7 +20,8 @@ export function parseListLimit(limitRaw, defaultLimit = 100, maxLimit = MAX_LIST
25
20
  }
26
21
  return limit;
27
22
  }
28
- /** `_authed` is proof the caller passed auth, so a full-size body is read only for an authenticated caller; the key mint reads first under its own small cap. */
23
+ /** `_authed` is proof the caller passed auth, so a full-size body is read only for
24
+ * an authenticated caller; the key mint reads first under its own small cap. */
29
25
  export async function parseJsonBody(req, _authed) {
30
26
  return parseJsonObjectText(await readBody(req));
31
27
  }
@@ -72,18 +68,9 @@ export function getCallerProject(body) {
72
68
  }
73
69
  return { name: v.name, aliases: v.aliases };
74
70
  }
75
- /**
76
- * Charset + length validation for `:id` route captures. Routes call
77
- * this immediately after `matchPath` to reject empty / overlong / illegal
78
- * ids with a useful 400 instead of silently falling through to "not found".
79
- *
80
- * Allowed charset matches all production id shapes Hippo emits: `mem_<hex>`,
81
- * `sum_<hex>`, `sess-<id>`, Slack bot ids like `B01ABCD`, etc. The `:` and
82
- * `.` are allowed for forward-compat. The `/` is intentionally absent —
83
- * Hippo never emits ids with slashes, and `rejectEncodedSlash` already
84
- * stops `%2F`-smuggled ones at the front door.
85
- */
86
- const ID_SEGMENT_RE = /^[A-Za-z0-9_:.\-]+$/;
71
+ /** Charset + length validation for `:id` captures, called right after `matchPath` so empty/overlong/illegal ids get a 400, not "not found".
72
+ * Allows every production id shape (`mem_<hex>`, `sess-<id>`, Slack ids) plus `:` and `.`; no `/`, since `rejectEncodedSlash` stops `%2F` smuggling. */
73
+ const ID_SEGMENT_RE = /^[A-Za-z0-9_:.-]+$/;
87
74
  export function validateIdSegment(id, fieldName) {
88
75
  if (id.length === 0)
89
76
  throw new HttpError(400, `${fieldName} is required`);
package/dist/server.d.ts CHANGED
@@ -35,12 +35,12 @@ export type { AmbientLoadResult, AmbientRecallRequest, ContextCandidateFilter, R
35
35
  export type { AmbientStoreFilter } from './store/ambient.js';
36
36
  export type { AmbientTallies } from './core/ambient.js';
37
37
  export type { TokenUse } from './store/token-ledger.js';
38
- export type { EmbeddingIndexState } from './store/embeddings/index.js';
38
+ export type { EmbeddingIndexState } from './store/vector-index.js';
39
39
  export type { PhysicsParticle } from './core/physics.js';
40
40
  export { StoreBusyError } from './db/index.js';
41
41
  export { decodeVector, EMBEDDING_MODEL_META_KEY, encodeVector, rankVectorRows, type VectorMatch, type VectorRow } from './db/vector-store.js';
42
42
  export { bufferToFloat32, float32ToBuffer } from './db/physics-state.js';
43
- export { replacesIndex } from './store/embeddings/index.js';
43
+ export { replacesIndex } from './store/vector-index.js';
44
44
  export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './store/recall-scope.js';
45
45
  export { SECRET_TAGS } from './util/secret-detect.js';
46
46
  export { tallyAmbientEntries } from './core/ambient.js';
package/dist/server.js CHANGED
@@ -9,7 +9,8 @@ export { isCrossSite, LOOPBACK_HOST_HEADER } from './util/http-util.js';
9
9
  export { __resetSessionRecallHistoryHttp } from './server/routes/recall.js';
10
10
  export { clientIpForRateLimit } from './server/client-ip.js';
11
11
  export { isLoopback, isReservedActor } from './server/auth.js';
12
- // What an add-on route handler needs: HttpError for its 4xx replies, promptHookContext for a caller that renders the prompt hook elsewhere, JsonValue for its body.
12
+ // What an add-on route handler needs: HttpError for its 4xx replies, promptHookContext
13
+ // for a caller that renders the prompt hook elsewhere, JsonValue for its body.
13
14
  export { HttpError } from './util/http-util.js';
14
15
  export { promptHookContext } from './api/prompt-hook.js';
15
16
  // A session-end route stores the turns its caller read from a transcript on the caller's own machine.
@@ -26,7 +27,7 @@ export { StoreBusyError } from './db/index.js';
26
27
  // so both stores keep the same bytes and return the same ids in the same order.
27
28
  export { decodeVector, EMBEDDING_MODEL_META_KEY, encodeVector, rankVectorRows } from './db/vector-store.js';
28
29
  export { bufferToFloat32, float32ToBuffer } from './db/physics-state.js';
29
- export { replacesIndex } from './store/embeddings/index.js';
30
+ export { replacesIndex } from './store/vector-index.js';
30
31
  // An add-on's ContextReads applies hippo.db's scope, secret, tally and rarest-term rules with the same code.
31
32
  export { passesScopeFilterForRecall, RECALL_DEFAULT_DENY_SCOPES } from './store/recall-scope.js';
32
33
  export { SECRET_TAGS } from './util/secret-detect.js';
@@ -0,0 +1,19 @@
1
+ import { MemoryEntry } from '../core/memory.js';
2
+ import type { DatabaseSyncLike } from '../db/index.js';
3
+ /** Returns the path to the global Hippo store.
4
+ * Resolution order: $HIPPO_HOME > $XDG_DATA_HOME/hippo > ~/.hippo/ */
5
+ export declare function getGlobalRoot(): string;
6
+ /** Ensure the global store exists. */
7
+ export declare function initGlobal(): void;
8
+ /** Copies a local memory to the global store and returns the copy, which gets a new `g_` id so it cannot collide. */
9
+ export declare function promoteToGlobal(localRoot: string, id: string, opts?: {
10
+ actor?: string;
11
+ tenantId?: string;
12
+ afterWrite?: (db: DatabaseSyncLike, globalId: string) => void;
13
+ /** Also writes one `promote` audit row for the copy ({sourceId}), in the copy's own transaction. */
14
+ auditAs?: {
15
+ tenantId: string;
16
+ actor: string;
17
+ };
18
+ }): MemoryEntry;
19
+ //# sourceMappingURL=global-store.d.ts.map
@@ -0,0 +1,75 @@
1
+ // The global store: where it lives, creating it, and copying a local memory into it.
2
+ import { BadRequestError, NotFoundError } from '../core/api-errors.js';
3
+ import * as fs from 'fs';
4
+ import { generateId } from '../core/memory.js';
5
+ import { initStore } from '../store/open.js';
6
+ import { writeEntry } from '../store/entry-writes.js';
7
+ import { readEntry } from '../store/entry-reads.js';
8
+ import { isPersonalScope } from '../store/recall-scope.js';
9
+ import { fallbackOrigin, resolveGlobalRootDir } from '../core/project-identity.js';
10
+ import { isSharedStore } from '../core/config.js';
11
+ import { detectSecret } from '../util/secret-detect.js';
12
+ import { isQuarantineScope } from '../trust/quarantine.js';
13
+ import { embedMemory } from '../store/embeddings/index.js';
14
+ import { appendAuditEvent } from '../store/audit.js';
15
+ /** Returns the path to the global Hippo store.
16
+ * Resolution order: $HIPPO_HOME > $XDG_DATA_HOME/hippo > ~/.hippo/ */
17
+ export function getGlobalRoot() {
18
+ // Single source of truth lives in project-identity.ts (leaf) so db migrations
19
+ // can resolve the same path without a shared.ts import cycle.
20
+ return resolveGlobalRootDir();
21
+ }
22
+ /** Ensure the global store exists. */
23
+ export function initGlobal() {
24
+ const globalRoot = getGlobalRoot();
25
+ if (!fs.existsSync(globalRoot)) {
26
+ initStore(globalRoot);
27
+ }
28
+ else {
29
+ // Ensure subdirectories exist in case partially initialized
30
+ initStore(globalRoot);
31
+ }
32
+ }
33
+ /** The copy's write hook: the `promote` row when asked for, then the caller's own hook, both in the copy's transaction. */
34
+ function promoteHook(sourceId, auditAs, afterWrite) {
35
+ if (!auditAs)
36
+ return afterWrite;
37
+ return (db, globalId) => {
38
+ appendAuditEvent(db, { tenantId: auditAs.tenantId, actor: auditAs.actor, op: 'promote', targetId: globalId, metadata: { sourceId } });
39
+ afterWrite?.(db, globalId);
40
+ };
41
+ }
42
+ /** Copies a local memory to the global store and returns the copy, which gets a new `g_` id so it cannot collide. */
43
+ export function promoteToGlobal(localRoot, id, opts) {
44
+ const entry = readEntry(localRoot, id, opts?.tenantId);
45
+ if (!entry)
46
+ throw new NotFoundError(`Memory not found: ${id}`);
47
+ // Same quarantine veto as shareMemory; a promoted copy would have no quarantine record to review.
48
+ if (isQuarantineScope(entry.scope)) {
49
+ throw new BadRequestError(`Refusing to promote ${id}: it is quarantined pending review. Approve it first via 'hippo quarantine approve ${id}'.`);
50
+ }
51
+ if (isPersonalScope(entry.scope ?? null)) {
52
+ throw new BadRequestError(`Refusing to promote ${id}: it is a personal memory and stays with its owner on this server.`);
53
+ }
54
+ // Secret producer veto: promote is a producer path to the global store
55
+ // exactly like shareMemory - same hard rule.
56
+ const promoteSecret = detectSecret(entry);
57
+ if (promoteSecret.flagged) {
58
+ throw new BadRequestError(`Refusing to promote ${id} to the global store: content matches secret material (${promoteSecret.reason}). ` +
59
+ `Secrets stay in their owning project's store.`);
60
+ }
61
+ initGlobal();
62
+ const globalRoot = getGlobalRoot();
63
+ // A project store's NULL row gets its folder back; a shared store's folder is no caller's project, so NULL stays and the label names no path.
64
+ const globalEntry = {
65
+ ...entry,
66
+ id: generateId('g'),
67
+ source: isSharedStore(localRoot) ? `shared::${new Date().toISOString()}` : `promoted:${localRoot}`,
68
+ origin_project: entry.origin_project ?? fallbackOrigin(localRoot),
69
+ };
70
+ writeEntry(globalRoot, globalEntry, { actor: opts?.actor, afterWrite: promoteHook(id, opts?.auditAs, opts?.afterWrite) });
71
+ // Fire-and-forget: embedMemory gates on availability and never rejects.
72
+ void embedMemory(globalRoot, globalEntry);
73
+ return globalEntry;
74
+ }
75
+ //# sourceMappingURL=global-store.js.map
@@ -0,0 +1,6 @@
1
+ /** Copy all global memories into the local store, skipping entries that already exist locally by ID or text (promote and share copy under a new ID).
2
+ * Returns the count of newly copied entries. */
3
+ export declare function syncGlobalToLocal(localRoot: string, globalRoot: string, opts?: {
4
+ includeCrossProject?: boolean;
5
+ }): number;
6
+ //# sourceMappingURL=global-sync.d.ts.map
@@ -0,0 +1,80 @@
1
+ // Copying the global store's memories down into a local store.
2
+ import { BadRequestError } from '../core/api-errors.js';
3
+ import * as fs from 'fs';
4
+ import * as path from 'path';
5
+ import { AGENT_MEMORY_SOURCE_PREFIX } from '../core/agent-memory-tools.js';
6
+ import { writeEntry } from '../store/entry-writes.js';
7
+ import { loadAllEntries } from '../store/entry-reads.js';
8
+ import { classifyOriginProject, resolveProjectIdentity } from '../core/project-identity.js';
9
+ import { isSharedStore } from '../core/config.js';
10
+ import { detectSecret } from '../util/secret-detect.js';
11
+ import { RejectedValueError } from '../store/rejection.js';
12
+ import { embedAll } from '../store/embeddings/index.js';
13
+ import { log } from '../util/log.js';
14
+ import { logEmbedAllFailure } from './search-both.js';
15
+ /** Copy all global memories into the local store, skipping entries that already exist locally by ID or text (promote and share copy under a new ID).
16
+ * Returns the count of newly copied entries. */
17
+ export function syncGlobalToLocal(localRoot, globalRoot, opts = {}) {
18
+ if (isSharedStore(localRoot)) {
19
+ throw new BadRequestError(`Refusing to sync into ${localRoot}: a shared store takes no copies of a personal global store, whose rows would reach every member.`);
20
+ }
21
+ if (!fs.existsSync(globalRoot))
22
+ return 0;
23
+ // Host-wide read: the global union is copied into a tenant-scoped local store, and writeEntry carries the tenant if the local-root context has one.
24
+ const globalEntries = loadAllEntries(globalRoot);
25
+ const textKey = (e) => `${e.tenantId}\n${e.content}`;
26
+ const localEntries = loadAllEntries(localRoot);
27
+ const localIds = new Set(localEntries.map((e) => e.id));
28
+ const localText = new Set(localEntries.map(textKey));
29
+ // Syncing down must not re-import what ambient context excludes: other-project rows are skipped by default and secret rows never copied.
30
+ // origin_project is preserved on the copy (writeEntry stamps it only when missing).
31
+ const currentProject = resolveProjectIdentity(path.dirname(path.resolve(localRoot)));
32
+ let count = 0;
33
+ // A locally rejected value must not come back through sync down: caught per item, printed as one line.
34
+ let rejected = 0;
35
+ for (const entry of globalEntries) {
36
+ // Skip if already present by ID
37
+ if (localIds.has(entry.id))
38
+ continue;
39
+ // Only the global store's user pass sets an imported note's row aside, so a copy would outlive the note.
40
+ if (entry.source.startsWith(AGENT_MEMORY_SOURCE_PREFIX))
41
+ continue;
42
+ if (localText.has(textKey(entry)))
43
+ continue;
44
+ if (detectSecret(entry).flagged)
45
+ continue;
46
+ if (!opts.includeCrossProject && classifyOriginProject(entry.origin_project, currentProject) === 'cross-project')
47
+ continue;
48
+ if (!writeUnlessRejected(localRoot, entry)) {
49
+ rejected++;
50
+ continue;
51
+ }
52
+ localText.add(textKey(entry));
53
+ count++;
54
+ }
55
+ finishSyncDown(localRoot, count, rejected);
56
+ return count;
57
+ }
58
+ /** False when the local store rejects the value; any other failure still throws. */
59
+ function writeUnlessRejected(localRoot, entry) {
60
+ try {
61
+ writeEntry(localRoot, entry);
62
+ return true;
63
+ }
64
+ catch (err) {
65
+ if (err instanceof RejectedValueError)
66
+ return false;
67
+ throw err;
68
+ }
69
+ }
70
+ function finishSyncDown(localRoot, count, rejected) {
71
+ if (rejected > 0) {
72
+ log.warn(`syncGlobalToLocal: skipped ${rejected} rejected value(s) (run \`hippo unreject\` on the local store to allow).`);
73
+ }
74
+ // Batch producer: one embedAll() on the destination rather than an
75
+ // embedMemory() per copied row (same batching invariant as autoShare).
76
+ if (count > 0) {
77
+ void embedAll(localRoot).catch((err) => logEmbedAllFailure('syncGlobalToLocal', err));
78
+ }
79
+ }
80
+ //# sourceMappingURL=global-sync.js.map
@@ -59,15 +59,14 @@ export declare function mergeProjects(db: DatabaseSyncLike, hippoRoot: string, o
59
59
  export declare function namesFoldedInto(db: DatabaseSyncLike, tenantId: string, names: readonly string[]): string[];
60
60
  /** Reads only, so doctor and a dry run take no write lock; merged rows are planned before any fold, so a few may re-tag differently once folds apply. */
61
61
  export declare function planProjectRepair(db: DatabaseSyncLike, hippoRoot: string, tenantId: string, globalFolds?: boolean): Omit<RepairResult, 'backup'>;
62
- /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then re-tags sleep's user-global merges by their parents; a dry run only plans. */
62
+ /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
63
+ * re-tags sleep's user-global merges by their parents; a dry run only plans. */
63
64
  export declare function repairProjects(db: DatabaseSyncLike, hippoRoot: string, opts: {
64
65
  tenantId: string;
65
66
  dryRun: boolean;
66
67
  globalFolds?: boolean;
67
68
  }): RepairResult;
68
- /**
69
- * Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
70
- * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted.
71
- */
69
+ /** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
70
+ * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
72
71
  export declare function repairOnceOnSleep(db: DatabaseSyncLike, hippoRoot: string, tenantId: string): RepairResult | null;
73
72
  //# sourceMappingURL=project-merge.d.ts.map
@@ -115,7 +115,8 @@ function importCopies(db, tenantId) {
115
115
  const userGlobal = new Set(live.filter((e) => e.origin_project === '').map((e) => duplicateKey(e.content)));
116
116
  return live.filter((e) => e.origin_project && e.kind !== 'raw' && !e.pinned && toolTag(e.source) !== null && userGlobal.has(duplicateKey(e.content)));
117
117
  }
118
- /** Imports to set aside. The global store also checks each Claude session folder a compaction recorded: its notes under any other project are misfiled, edited or not, and a text copy in the right folder is kept. */
118
+ /** Imports to set aside. The global store also checks each Claude session folder a compaction recorded: its
119
+ * notes under any other project are misfiled, edited or not, and a text copy in the right folder is kept. */
119
120
  function strayImports(db, hippoRoot, tenantId) {
120
121
  const copies = importCopies(db, tenantId);
121
122
  if (!isGlobalStoreRoot(hippoRoot))
@@ -187,7 +188,9 @@ function ownLegacyFold(db, hippoRoot, tenantId) {
187
188
  const { name, legacyName } = resolveProjectIdentity(path.dirname(path.resolve(hippoRoot)));
188
189
  if (legacyName === '' || legacyName === name)
189
190
  return [];
190
- const held = holdsOrigin(db, 'memories', tenantId, legacyName) || holdsOrigin(db, 'compactions', tenantId, legacyName) || listDormantSnapshots(db, tenantId).some((s) => s.entry.origin_project === legacyName);
191
+ const held = holdsOrigin(db, 'memories', tenantId, legacyName)
192
+ || holdsOrigin(db, 'compactions', tenantId, legacyName)
193
+ || listDormantSnapshots(db, tenantId).some((s) => s.entry.origin_project === legacyName);
191
194
  return held ? [{ from: legacyName, into: name }] : [];
192
195
  }
193
196
  function foldOf(value) {
@@ -253,7 +256,8 @@ function planUserGlobalRepair(db, tenantId, folds) {
253
256
  }
254
257
  return { toProject, setAside, untraced };
255
258
  }
256
- /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then re-tags sleep's user-global merges by their parents; a dry run only plans. */
259
+ /** Sets aside stray imports, folds the names the resolver now maps elsewhere, then
260
+ * re-tags sleep's user-global merges by their parents; a dry run only plans. */
257
261
  export function repairProjects(db, hippoRoot, opts) {
258
262
  const { tenantId, dryRun, globalFolds = true } = opts;
259
263
  if (dryRun)
@@ -290,10 +294,8 @@ const AUTO_REPAIR_META_KEY = 'project_repair_auto';
290
294
  function repairIsEmpty(r) {
291
295
  return r.copies.length + r.folds.length + r.toProject.length + r.setAside.length === 0;
292
296
  }
293
- /**
294
- * Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
295
- * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted.
296
- */
297
+ /** Sleep runs repair once per store, so an upgrade needs no command. Global-store folds stay
298
+ * with `hippo projects repair`: their evidence is compaction folders, blind to a same-named repo that never compacted. */
297
299
  export function repairOnceOnSleep(db, hippoRoot, tenantId) {
298
300
  if (getMeta(db, AUTO_REPAIR_META_KEY) === '1')
299
301
  return null;