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/dist/cli/serve.js CHANGED
@@ -1,18 +1,20 @@
1
1
  // Long-running verbs: `hippo dashboard`, `hippo mcp` and `hippo serve`.
2
2
  import { installCrashHandlers } from '../util/crash-handlers.js';
3
- import { envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
3
+ import { envAllowKeylessLocal, envPort, envRequireAuth, envTlsCert, envTlsKey } from '../util/env.js';
4
4
  import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import { printError } from './output.js';
7
7
  import { stringFlagOrExit, stringFlag } from './flag-values.js';
8
8
  import { requireInit } from './shared.js';
9
9
  import { errorMessage } from '../util/log.js';
10
+ import { CliExit } from './exit.js';
11
+ import { DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT } from '../server/defaults.js';
10
12
  export async function handleDashboard({ hippoRoot, flags }) {
11
13
  requireInit(hippoRoot);
12
14
  const port = parseInt(String(flags['port'] ?? '3333'), 10);
13
15
  const { serveDashboard } = await import('../dashboard/dashboard.js');
14
- serveDashboard(hippoRoot, port);
15
- // A busy port or a later throw ends in one log line and exit 1, as it does for serve and mcp.
16
+ serveDashboard(hippoRoot, port, undefined, { handleSignals: true });
17
+ // A later throw ends in one log line and exit 1, as it does for serve and mcp; a busy port is reported by the dashboard itself.
16
18
  installCrashHandlers('dashboard');
17
19
  await new Promise(() => { }); // run until Ctrl+C
18
20
  }
@@ -35,33 +37,40 @@ function readTlsFiles(flags) {
35
37
  return undefined;
36
38
  if (certPath === undefined || keyPath === undefined) {
37
39
  printError('hippo serve: TLS needs both a certificate and a key: --tls-cert and --tls-key, or HIPPO_TLS_CERT and HIPPO_TLS_KEY.');
38
- process.exit(1);
40
+ throw new CliExit(1);
39
41
  }
40
42
  try {
41
43
  return { cert: fs.readFileSync(certPath), key: fs.readFileSync(keyPath) };
42
44
  }
43
45
  catch (err) {
44
46
  printError(`hippo serve: cannot read the TLS files: ${errorMessage(err)}`);
45
- process.exit(1);
47
+ throw new CliExit(1);
46
48
  }
47
49
  }
50
+ /** Said at every start, so the key rule is a choice an operator sees, and an upgrade that changed it explains itself. */
51
+ function keyRuleLine() {
52
+ if (envRequireAuth())
53
+ return 'every request needs an API key (HIPPO_REQUIRE_AUTH=1)';
54
+ if (envAllowKeylessLocal()) {
55
+ return 'requests from this machine need no API key and act as host admin (HIPPO_ALLOW_KEYLESS_LOCAL=1); unset it to require a key on every request';
56
+ }
57
+ return 'every request needs an API key: mint one with `hippo auth create` and send it as "Authorization: Bearer <key>" ' +
58
+ '(the hippo CLI reads HIPPO_API_KEY). To let requests from this machine in without a key, start with HIPPO_ALLOW_KEYLESS_LOCAL=1';
59
+ }
48
60
  export async function handleServe({ hippoRoot, flags }) {
49
61
  requireInit(hippoRoot);
50
- const portRaw = flags['port'] ?? envPort() ?? '6789';
62
+ const portRaw = flags['port'] ?? envPort() ?? DEFAULT_SERVER_PORT;
51
63
  const port = Number(portRaw);
52
64
  if (!Number.isFinite(port) || port < 0) {
53
65
  printError(`Invalid --port: ${String(portRaw)}`);
54
- process.exit(1);
66
+ throw new CliExit(1);
55
67
  }
56
- const host = stringFlag(flags, 'host') ?? '127.0.0.1';
68
+ const host = stringFlag(flags, 'host') ?? DEFAULT_SERVER_HOST;
57
69
  const tls = readTlsFiles(flags);
58
70
  const { serve } = await import('../server.js');
59
71
  const handle = await serve({ hippoRoot, port, host, handleSignals: true, tls });
60
72
  console.log(`hippo serve listening on ${handle.url} (pid ${process.pid})`);
61
- // Said at every start: the no-key local fallback is a default an operator should choose, not discover.
62
- if (!envRequireAuth()) {
63
- console.log('local requests need no API key and act as host admin; set HIPPO_REQUIRE_AUTH=1 to require a key on every request');
64
- }
73
+ console.log(keyRuleLine());
65
74
  console.log(`pidfile: ${path.join(hippoRoot, 'server.pid')}`);
66
75
  console.log('press Ctrl+C to stop');
67
76
  // The SIGINT/SIGTERM handlers stop the server and exit. Hang until then.
@@ -1,26 +1,18 @@
1
1
  import { type CliFlags, type CommandContext } from './flag-values.js';
2
- /**
3
- * SessionEnd entry point. Claude Code / OpenCode fire this on /exit while
4
- * tearing down the TUI, which kills any child that is still running when
5
- * the parent returns. Running sleep + capture synchronously here means both
6
- * get SIGTERM'd mid-consolidation.
7
- *
8
- * So we do the minimum inline (read stdin for transcript_path), then spawn
9
- * a fully detached Node child that runs sleep → capture and exit the parent
10
- * immediately. The child writes to the log file and survives TUI teardown;
11
- * the next SessionStart reads the log via `hippo last-sleep`.
12
- */
13
- export declare function cmdSessionEnd(hippoRoot: string, flags: CliFlags): Promise<void>;
14
- export declare function cmdSessionEndWorker(hippoRoot: string, flags: CliFlags): Promise<void>;
2
+ /** SessionEnd entry: TUI teardown kills children still running, so read stdin inline, spawn a detached child that runs sleep then capture, and exit.
3
+ * The child logs to a file that the next SessionStart reads via `hippo last-sleep`. */
4
+ export declare function handleSessionEnd({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
5
+ export declare function handleSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
15
6
  /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
16
7
  export declare function quoteCmdArg(arg: string): string;
17
8
  /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
18
9
  export declare function cmdShimArgs(shimPath: string, forwardArgs: readonly string[]): string[];
19
- export declare function cmdCodexRun(hippoRoot: string, args: string[]): void;
20
- export declare function cmdCodexSessionEndWorker(hippoRoot: string, flags: CliFlags): Promise<void>;
10
+ export declare function handleCodexRun({ hippoRoot, tenantId, args }: CommandContext): void;
11
+ export declare function cmdCodexSessionEndWorker(hippoRoot: string, tenantId: string, flags: CliFlags): Promise<void>;
12
+ export declare function handleCodexSessionEndWorker({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
21
13
  export declare function handlePreCompact({ hippoRoot, flags }: CommandContext): Promise<void>;
22
14
  export declare function handlePostCompact({ hippoRoot, flags }: CommandContext): Promise<void>;
23
- export declare function handleCaptureError({ hippoRoot, flags }: CommandContext): Promise<void>;
24
- export declare function handleCompactResume({ hippoRoot }: CommandContext): Promise<void>;
25
- export declare function handleCapture({ hippoRoot, flags }: CommandContext): Promise<void>;
15
+ export declare function handleCaptureError({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
16
+ export declare function handleCompactResume({ hippoRoot, tenantId }: CommandContext): Promise<void>;
17
+ export declare function handleCapture({ hippoRoot, tenantId, flags }: CommandContext): Promise<void>;
26
18
  //# sourceMappingURL=session-hooks.d.ts.map
@@ -9,14 +9,13 @@ import { isInitialized } from '../store/open.js';
9
9
  import { loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, closeTaskSnapshotsForSession, listSessionEvents, } from '../store/sessions.js';
10
10
  import { writeSessionEndHandoff } from '../store/handoffs.js';
11
11
  import { readSessionScan, recordSessionDigest } from '../capture/session-digest.js';
12
- import { openHippoDb, closeHippoDb } from '../db/index.js';
13
12
  import { captureToolFailure } from '../capture/capture-error.js';
14
13
  import { readApiCalls, recordRereads, } from '../store/token-ledger.js';
15
14
  import { estimateTokens } from '../util/token-text.js';
16
15
  import { currentMachine, importSessionFolder } from '../agent-memories/sync.js';
17
16
  import { summaryLine } from '../agent-memories/report.js';
18
17
  import { resolveProjectIdentity } from '../core/project-identity.js';
19
- import { getGlobalRoot } from '../sharing/shared.js';
18
+ import { getGlobalRoot } from '../sharing/global-store.js';
20
19
  import { cmdCapture } from '../capture/command.js';
21
20
  import { cmdPreCompact, cmdPostCompact } from '../capture/compact.js';
22
21
  import { transcriptWorkingState } from '../capture/working-state.js';
@@ -30,7 +29,6 @@ import { truncateCodePointSafe } from '../util/transcript-tail.js';
30
29
  import { COMPACTION_DB_WAIT_MS } from '../capture/compaction-record.js';
31
30
  import { COMPACT_RESUME_EVENT_CONTENT_CAP, COMPACT_RESUME_MAX_AGE_MS, compactResumeText } from '../api/context-render.js';
32
31
  import { normaliseHookPayload, readHookStdin, readStdinBounded } from './stdin.js';
33
- import { resolveTenantId } from '../store/tenant.js';
34
32
  import { errorMessage, log } from '../util/log.js';
35
33
  import { bookLedgerTurn } from '../api/ledger-db.js';
36
34
  import { flushDeliveryRecorder } from '../api/prompt-hook.js';
@@ -38,26 +36,17 @@ import { printError } from './output.js';
38
36
  import { cmdLastSleep } from './last-sleep.js';
39
37
  import { readCompactResumePayload } from './compact-resume-payload.js';
40
38
  import { boolFlag, flagIsTrue, stringFlag } from './flag-values.js';
41
- import { logSessionEndImport, appendSessionEndCloseLog, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout, startDeliveryRecorder } from './hook-runtime.js';
42
- /**
43
- * SessionStart(compact) injector. Prints the active task snapshot + recent
44
- * session trail so working state that would otherwise be lost to
45
- * compaction summarisation survives into the new context window. No pinned
46
- * memories here — the UserPromptSubmit hook already re-injects those every
47
- * turn, so duplicating them here would double token cost for nothing.
48
- *
49
- * Same exit-0/crash-safety contract as `hippo pre-compact`: every path
50
- * exits 0. A malformed payload or a store read failure
51
- * degrades to empty stdout, never a thrown error — a failing SessionStart
52
- * hook must not pollute session startup.
53
- */
54
- function cmdCompactResume(hippoRoot, stdinText, stdinTimedOut) {
39
+ import { logSessionEndImport, appendSessionEndCloseLog, reportSessionEndFailure, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout, startDeliveryRecorder, } from './hook-runtime.js';
40
+ import { CliExit } from './exit.js';
41
+ /** SessionStart(compact) injector: prints the task snapshot and session trail lost to compaction; no pinned memories (UserPromptSubmit re-injects them).
42
+ * Every path exits 0: a malformed payload or store read failure degrades to empty stdout, never a throw. */
43
+ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
55
44
  let rec = null;
56
45
  try {
57
46
  // Gate on the non-exiting isInitialized check first: the store reads below call initStore, which would
58
47
  // silently create a store in a project that never ran `hippo init`, and this hook fires globally.
59
48
  if (!isInitialized(hippoRoot)) {
60
- process.exit(0);
49
+ throw new CliExit(0);
61
50
  }
62
51
  const payloadState = readCompactResumePayload(stdinText, stdinTimedOut);
63
52
  let suppressOutput = payloadState.suppressOutput;
@@ -65,23 +54,24 @@ function cmdCompactResume(hippoRoot, stdinText, stdinTimedOut) {
65
54
  if (payloadState.boundary)
66
55
  rec = startDeliveryRecorder(hippoRoot, stdinText, 'claude-code', 'compact-resume');
67
56
  // A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
68
- if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, resolveTenantId({}), payloadSessionId, false)) {
57
+ if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, false)) {
69
58
  suppressOutput = true;
70
59
  rec?.disabled();
71
60
  }
72
61
  if (!suppressOutput)
73
- restoreCompactSnapshot(hippoRoot, payloadSessionId, rec);
62
+ restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec);
74
63
  }
75
64
  catch (err) {
65
+ if (err instanceof CliExit)
66
+ throw err;
76
67
  // Empty stdout on any store error, never a crashed SessionStart; the reason goes to stderr, which the model never sees.
77
68
  log.warn(`hippo compact-resume: skipped: ${errorMessage(err)}`);
78
69
  }
79
70
  // A no-op when the token ledger's handle already wrote the row; exit would drop it otherwise.
80
71
  flushDeliveryRecorder(rec);
81
- process.exit(0);
72
+ throw new CliExit(0);
82
73
  }
83
- function restoreCompactSnapshot(hippoRoot, payloadSessionId, rec) {
84
- const tenantId = resolveTenantId({});
74
+ function restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec) {
85
75
  const snapshot = loadFreshActiveTaskSnapshot(hippoRoot, tenantId, { maxAgeMs: COMPACT_RESUME_MAX_AGE_MS });
86
76
  // Concurrent sessions must not cross-restore. Only suppress when BOTH ids are present and differ;
87
77
  // either side missing, or a manual invocation with no payload session_id, still prints.
@@ -115,18 +105,9 @@ function restoreCompactSnapshot(hippoRoot, payloadSessionId, rec) {
115
105
  delivery: (write) => flushDeliveryRecorder(rec, write),
116
106
  });
117
107
  }
118
- /**
119
- * SessionEnd entry point. Claude Code / OpenCode fire this on /exit while
120
- * tearing down the TUI, which kills any child that is still running when
121
- * the parent returns. Running sleep + capture synchronously here means both
122
- * get SIGTERM'd mid-consolidation.
123
- *
124
- * So we do the minimum inline (read stdin for transcript_path), then spawn
125
- * a fully detached Node child that runs sleep → capture and exit the parent
126
- * immediately. The child writes to the log file and survives TUI teardown;
127
- * the next SessionStart reads the log via `hippo last-sleep`.
128
- */
129
- export async function cmdSessionEnd(hippoRoot, flags) {
108
+ /** SessionEnd entry: TUI teardown kills children still running, so read stdin inline, spawn a detached child that runs sleep then capture, and exit.
109
+ * The child logs to a file that the next SessionStart reads via `hippo last-sleep`. */
110
+ export async function handleSessionEnd({ hippoRoot, tenantId, flags }) {
130
111
  const runtime = hookRuntime(flags);
131
112
  const turn = flagIsTrue(flags, 'turn');
132
113
  // Copilot's hook command carries no path, since one quoted into it would need escaping for each shell; the log goes where the hook table used to point.
@@ -141,6 +122,8 @@ export async function cmdSessionEnd(hippoRoot, flags) {
141
122
  // Before the spawn, since the worker finds its store from the folder it inherits.
142
123
  const root = payloadCwdRoot(hippoRoot, stdinText, runtime);
143
124
  const input = stop ?? sessionEndInput(stdinText, raw.timedOut, runtime);
125
+ // Only a host payload ends a session: a manual run and a reply's end (turn mode) are not boundaries.
126
+ const rec = !turn && input !== null && !input.manual ? startDeliveryRecorder(hookStoreRoot(root), stdinText, runtime, 'session-end') : null;
144
127
  const sessionId = input?.sessionId ?? null;
145
128
  // Resolved here because only this process saw the payload; the worker captures just the path it is handed.
146
129
  // Always a hook, so never scan: an empty stdin here is not a manual run. The Copilot CLI's sessionEnd names no transcript, so its log is found by id.
@@ -159,9 +142,16 @@ export async function cmdSessionEnd(hippoRoot, flags) {
159
142
  flags['transcript'] = transcriptPath;
160
143
  if (sessionId)
161
144
  flags['session-id'] = sessionId;
162
- await cmdSessionEndWorker(root, flags);
145
+ try {
146
+ await cmdSessionEndWorker(root, tenantId, flags);
147
+ }
148
+ finally {
149
+ await runHookWithStores(() => flushDeliveryRecorder(rec));
150
+ }
163
151
  return;
164
152
  }
153
+ // After the spawn, so a locked store delays only the row; the hook's short lock wait bounds it.
154
+ await runHookWithStores(() => flushDeliveryRecorder(rec));
165
155
  }
166
156
  /** What the session-end payload named; null for one hippo refuses or one that never arrived, and the worker then runs with neither value. */
167
157
  function sessionEndInput(stdinText, timedOut, runtime) {
@@ -198,15 +188,18 @@ function vscodeStopInput(raw) {
198
188
  const receipt = readVscodeStop(raw.text, raw.timedOut);
199
189
  return receipt.status === 'received' && receipt.input.sessionId !== null && SESSION_ID_RE.test(receipt.input.sessionId) ? receipt.input : null;
200
190
  }
201
- export async function cmdSessionEndWorker(hippoRoot, flags) {
191
+ async function cmdSessionEndWorker(hippoRoot, tenantId, flags) {
202
192
  const sessionId = flags['session-id'];
203
- await runSessionWorker(isStringValue(sessionId) ? sessionId : null, flagIsTrue(flags, 'turn') ? 'turn' : 'full', (mode) => sessionEndWork(hippoRoot, flags, mode));
193
+ await runSessionWorker(isStringValue(sessionId) ? sessionId : null, flagIsTrue(flags, 'turn') ? 'turn' : 'full', (mode) => sessionEndWork(hippoRoot, tenantId, flags, mode));
194
+ }
195
+ export function handleSessionEndWorker({ hippoRoot, tenantId, flags }) {
196
+ return cmdSessionEndWorker(hippoRoot, tenantId, flags);
204
197
  }
205
- async function sessionEndWork(hippoRoot, flags, mode) {
198
+ async function sessionEndWork(hippoRoot, tenantId, flags, mode) {
206
199
  const transcriptPath = stringFlag(flags, 'transcript');
207
200
  const closeLogFile = stringFlag(flags, 'log-file') ?? null;
208
201
  const closeSessionId = stringFlag(flags, 'session-id') ?? null;
209
- const rereadLog = await bookSessionRereads(hippoRoot, transcriptPath, closeSessionId)
202
+ const rereadLog = await bookSessionRereads(hippoRoot, tenantId, transcriptPath, closeSessionId)
210
203
  .catch((err) => [`re-read count failed: ${errorMessage(err)}`]);
211
204
  // Sleep starts the log file afresh, so the lines go in after it; on exit too, in case sleep exits the process.
212
205
  const flushRereadLog = () => { for (const line of rereadLog.splice(0))
@@ -220,38 +213,37 @@ async function sessionEndWork(hippoRoot, flags, mode) {
220
213
  return;
221
214
  }
222
215
  if (mode === 'turn' && closeSessionId)
223
- await sleepIfDue(hippoRoot, flags, closeLogFile, transcriptPath, closeSessionId);
216
+ await sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, closeSessionId);
224
217
  else
225
- await sleepProjectStore(hippoRoot, flags, closeLogFile, transcriptPath);
218
+ await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
226
219
  flushRereadLog();
227
220
  const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
228
221
  const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
229
- const capture = (turns) => captureEndedSession(hippoRoot, store, flags, transcriptPath, turns);
222
+ const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
230
223
  if (mode === 'turn')
231
224
  captureNewTurns(transcriptPath, closeSessionId, scan, capture, digestLog);
232
225
  else
233
226
  capture(scan?.turns);
234
227
  recordSessionDigest(hippoRoot, scan, {
235
228
  key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
236
- tenantId: resolveTenantId({}),
229
+ tenantId,
237
230
  log: digestLog,
238
231
  });
239
- // Close only this session's snapshot, after sleep+capture: no snapshot producer runs in session-end, and since
240
- // session-end may never fire (crash, kill -9) the freshness bound in loadFreshActiveTaskSnapshot is the backstop.
241
- // The handoff is written first, while the snapshot writeSessionEndHandoff reads is still active.
232
+ // Close only this session's snapshot, after sleep+capture; if session-end never fires (crash, kill -9) the freshness bound in
233
+ // loadFreshActiveTaskSnapshot is the backstop. The handoff is written first, while the snapshot writeSessionEndHandoff reads is active.
242
234
  if (closeSessionId)
243
- writeEndHandoff(store, closeSessionId, transcriptPath, closeLogFile, mode === 'turn');
235
+ writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, mode === 'turn');
244
236
  if (mode === 'turn') {
245
237
  // The chat goes on after a reply, so its snapshot stays for the next compaction to restore.
246
238
  appendSessionEndCloseLog(closeLogFile, 'skip snapshot close: turn mode');
247
239
  return;
248
240
  }
249
- closeEndedSessionSnapshot(store, closeSessionId, closeLogFile);
241
+ closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile);
250
242
  }
251
- function closeEndedSessionSnapshot(store, closeSessionId, closeLogFile) {
243
+ function closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile) {
252
244
  try {
253
245
  if (closeSessionId) {
254
- const closed = closeTaskSnapshotsForSession(store, resolveTenantId({}), closeSessionId);
246
+ const closed = closeTaskSnapshotsForSession(store, tenantId, closeSessionId);
255
247
  appendSessionEndCloseLog(closeLogFile, `closed ${closed} active snapshot(s) for session ${closeSessionId}`);
256
248
  }
257
249
  else {
@@ -262,15 +254,15 @@ function closeEndedSessionSnapshot(store, closeSessionId, closeLogFile) {
262
254
  appendSessionEndCloseLog(closeLogFile, `snapshot close failed: ${errorMessage(err)}`);
263
255
  }
264
256
  }
265
- async function sleepProjectStore(hippoRoot, flags, closeLogFile, transcriptPath) {
257
+ async function sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath) {
266
258
  // Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
267
259
  if (isInitialized(hippoRoot)) {
268
260
  try {
269
- await (await import('./sleep.js')).cmdSleep(hippoRoot, flags);
261
+ await (await import('./sleep.js')).cmdSleep(hippoRoot, tenantId, flags);
270
262
  }
271
263
  catch (err) {
272
- // cmdSleep writes its failure line only when it has a log file, and capture runs regardless.
273
- log.debug(`session-end: sleep failed: ${errorMessage(err)}`);
264
+ // cmdSleep writes its own failure line only once its log tee is open, and capture runs regardless.
265
+ reportSessionEndFailure(closeLogFile, 'session-end: sleep', err);
274
266
  }
275
267
  }
276
268
  else {
@@ -279,18 +271,18 @@ async function sleepProjectStore(hippoRoot, flags, closeLogFile, transcriptPath)
279
271
  }
280
272
  }
281
273
  /** A close after every reply sleeps only at the MCP server's auto-sleep threshold; each line starts the log afresh, as a sleep does. */
282
- async function sleepIfDue(hippoRoot, flags, closeLogFile, transcriptPath, sessionId) {
274
+ async function sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, sessionId) {
283
275
  if (!isInitialized(hippoRoot))
284
- return sleepProjectStore(hippoRoot, flags, closeLogFile, transcriptPath);
276
+ return sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
285
277
  const prefix = `turn close, session ${sessionId}`;
286
278
  try {
287
- const { enabled, count, threshold, due } = autoSleepDue(hippoRoot, resolveTenantId({}), loadConfig(hippoRoot).autoSleep);
279
+ const { enabled, count, threshold, due } = autoSleepDue(hippoRoot, tenantId, loadConfig(hippoRoot).autoSleep);
288
280
  if (!due) {
289
281
  const why = enabled ? `${count} new memories, threshold ${threshold}` : 'auto-sleep is off';
290
282
  appendSessionEndCloseLog(closeLogFile, `${prefix}: skip sleep, ${why}`, { startFresh: true });
291
283
  return;
292
284
  }
293
- await sleepProjectStore(hippoRoot, flags, closeLogFile, transcriptPath);
285
+ await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
294
286
  appendSessionEndCloseLog(closeLogFile, `${prefix}: ran sleep at ${count} new memories (threshold ${threshold})`);
295
287
  }
296
288
  catch (err) {
@@ -312,7 +304,7 @@ function captureNewTurns(transcriptPath, sessionId, scan, capture, log) {
312
304
  saveTurnPosition(sessionId, transcriptPath, scan.turns, log);
313
305
  }
314
306
  /** True when capture ran to the end, so a turn close may move its cursor past these turns. */
315
- function captureEndedSession(hippoRoot, store, flags, transcriptPath, turns) {
307
+ function captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns) {
316
308
  try {
317
309
  const logFile = stringFlag(flags, 'log-file');
318
310
  // With no stdin of its own, capture would read this as a manual run and scan every project.
@@ -326,7 +318,7 @@ function captureEndedSession(hippoRoot, store, flags, transcriptPath, turns) {
326
318
  logFile,
327
319
  dryRun: false,
328
320
  global: false,
329
- tenantId: resolveTenantId({}),
321
+ tenantId,
330
322
  // In the global store, rows would otherwise read as user-global and show up in every project.
331
323
  originProject: store === hippoRoot ? undefined : resolveProjectIdentity(process.cwd()),
332
324
  sessionTurns: turns,
@@ -334,13 +326,12 @@ function captureEndedSession(hippoRoot, store, flags, transcriptPath, turns) {
334
326
  return true;
335
327
  }
336
328
  catch (err) {
337
- log.debug(`session-end: capture failed: ${errorMessage(err)}`);
329
+ reportSessionEndFailure(stringFlag(flags, 'log-file') ?? null, 'session-end: capture', err);
338
330
  return false;
339
331
  }
340
332
  }
341
- function writeEndHandoff(store, closeSessionId, transcriptPath, closeLogFile, inPlace = false) {
333
+ function writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, inPlace = false) {
342
334
  try {
343
- const tenantId = resolveTenantId({});
344
335
  const ownSnapshot = loadActiveTaskSnapshot(store, tenantId)?.session_id === closeSessionId;
345
336
  // A never-compacted session has no snapshot; read even when it has one, as another session's PreCompact can take the slot before the write.
346
337
  const derived = transcriptPath
@@ -361,7 +352,7 @@ function writeEndHandoff(store, closeSessionId, transcriptPath, closeLogFile, in
361
352
  }
362
353
  }
363
354
  /** Books the ending session's re-reads in each store its ledger rows can land in (project and global); returns the log lines. */
364
- async function bookSessionRereads(hippoRoot, transcriptPath, sessionId) {
355
+ async function bookSessionRereads(hippoRoot, tenantId, transcriptPath, sessionId) {
365
356
  if (!transcriptPath || !sessionId)
366
357
  return [];
367
358
  let read;
@@ -376,13 +367,7 @@ async function bookSessionRereads(hippoRoot, transcriptPath, sessionId) {
376
367
  let tokens = 0;
377
368
  for (const root of roots) {
378
369
  try {
379
- const db = openHippoDb(root);
380
- try {
381
- tokens += recordRereads(db, resolveTenantId({}), sessionId, read.calls);
382
- }
383
- finally {
384
- closeHippoDb(db);
385
- }
370
+ tokens += recordRereads(root, tenantId, sessionId, read.calls);
386
371
  }
387
372
  catch (err) {
388
373
  lines.push(`re-read count failed: ${errorMessage(err)}`);
@@ -397,6 +382,7 @@ function loadCodexWrapperMetadata() {
397
382
  if (!fs.existsSync(metadataPath)) {
398
383
  throw new Error('Codex wrapper is not installed. Run `hippo hook install codex` first.');
399
384
  }
385
+ // SAFETY: the file is the one installCodexWrapper wrote; handleCodexRun reads only logFile and realCodexPath from it.
400
386
  return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
401
387
  }
402
388
  /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
@@ -423,7 +409,7 @@ function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
423
409
  }
424
410
  return spawn(realCodexPath, forwardArgs, { cwd, stdio: 'inherit', windowsHide: false });
425
411
  }
426
- export function cmdCodexRun(hippoRoot, args) {
412
+ export function handleCodexRun({ hippoRoot, tenantId, args }) {
427
413
  const metadata = loadCodexWrapperMetadata();
428
414
  const startedAtMs = Date.now();
429
415
  // Codex reads CODEX_HOME at each launch, so resolve it now, not from the install-time metadata.
@@ -441,11 +427,11 @@ export function cmdCodexRun(hippoRoot, args) {
441
427
  process.exit(1);
442
428
  });
443
429
  child.on('exit', async (code, signal) => {
444
- await launchCodexSessionEndWorker(hippoRoot, historyPath, startOffsetBytes, startedAtMs, metadata.logFile);
430
+ await launchCodexSessionEndWorker(hippoRoot, tenantId, historyPath, startOffsetBytes, startedAtMs, metadata.logFile);
445
431
  exitLikeChild(code, signal);
446
432
  });
447
433
  }
448
- async function launchCodexSessionEndWorker(hippoRoot, historyPath, startOffsetBytes, startedAtMs, logFile) {
434
+ async function launchCodexSessionEndWorker(hippoRoot, tenantId, historyPath, startOffsetBytes, startedAtMs, logFile) {
449
435
  const workerArgs = [
450
436
  process.argv[1],
451
437
  '__codex-session-end-worker',
@@ -460,30 +446,40 @@ async function launchCodexSessionEndWorker(hippoRoot, historyPath, startOffsetBy
460
446
  '--log-file',
461
447
  logFile,
462
448
  ];
449
+ if (await detachedWorkerStarted(workerArgs))
450
+ return;
451
+ // Awaited so the sleep write can't be killed by the exit calls below.
463
452
  try {
464
- const worker = spawn(process.execPath, workerArgs, {
465
- detached: true,
466
- stdio: 'ignore',
467
- windowsHide: true,
453
+ await cmdCodexSessionEndWorker(hippoRoot, tenantId, {
454
+ 'codex-home': path.dirname(historyPath),
455
+ 'history-path': historyPath,
456
+ 'start-offset': String(startOffsetBytes),
457
+ 'started-at': String(startedAtMs),
458
+ 'log-file': logFile,
468
459
  });
469
- worker.unref();
470
460
  }
471
- catch (err) {
472
- log.debug(`codex run: the session-end worker did not spawn, running inline: ${errorMessage(err)}`);
473
- // Awaited so the sleep write can't be killed by the exit calls below.
461
+ catch (inlineErr) {
462
+ log.debug(`codex run: the inline session-end failed: ${errorMessage(inlineErr)}`);
463
+ }
464
+ }
465
+ /** Resolves true once the detached worker is running, false when the spawn fails, whether it throws or reports later. */
466
+ function detachedWorkerStarted(workerArgs) {
467
+ return new Promise((resolve) => {
468
+ const failed = (reason) => {
469
+ log.debug(`codex run: the session-end worker did not spawn, running inline: ${reason}`);
470
+ resolve(false);
471
+ };
474
472
  try {
475
- await cmdCodexSessionEndWorker(hippoRoot, {
476
- 'codex-home': path.dirname(historyPath),
477
- 'history-path': historyPath,
478
- 'start-offset': String(startOffsetBytes),
479
- 'started-at': String(startedAtMs),
480
- 'log-file': logFile,
481
- });
473
+ const worker = spawn(process.execPath, workerArgs, { detached: true, stdio: 'ignore', windowsHide: true });
474
+ // An async spawn failure (ENOENT, EAGAIN) arrives as an 'error' event, which a try cannot catch.
475
+ worker.on('error', (err) => failed(err.message));
476
+ worker.once('spawn', () => resolve(true));
477
+ worker.unref();
482
478
  }
483
- catch (inlineErr) {
484
- log.debug(`codex run: the inline session-end failed: ${errorMessage(inlineErr)}`);
479
+ catch (err) {
480
+ failed(errorMessage(err));
485
481
  }
486
- }
482
+ });
487
483
  }
488
484
  function exitLikeChild(code, signal) {
489
485
  if (signal) {
@@ -498,7 +494,7 @@ function exitLikeChild(code, signal) {
498
494
  }
499
495
  process.exit(code ?? 0);
500
496
  }
501
- export async function cmdCodexSessionEndWorker(hippoRoot, flags) {
497
+ export async function cmdCodexSessionEndWorker(hippoRoot, tenantId, flags) {
502
498
  const logFile = stringFlag(flags, 'log-file');
503
499
  // Like the other hooks: project store, else global; a folder with neither must not get one made.
504
500
  const store = hookStoreRoot(hippoRoot);
@@ -506,17 +502,20 @@ export async function cmdCodexSessionEndWorker(hippoRoot, flags) {
506
502
  appendSessionEndCloseLog(logFile ?? null, 'skip: no hippo store for this folder or globally', { startFresh: true });
507
503
  return;
508
504
  }
509
- await sleepCodexProjectStore(hippoRoot, logFile);
510
- captureCodexTranscript(hippoRoot, store, flags, logFile);
505
+ await sleepCodexProjectStore(hippoRoot, tenantId, logFile);
506
+ captureCodexTranscript(hippoRoot, tenantId, store, flags, logFile);
507
+ }
508
+ export function handleCodexSessionEndWorker({ hippoRoot, tenantId, flags }) {
509
+ return cmdCodexSessionEndWorker(hippoRoot, tenantId, flags);
511
510
  }
512
- async function sleepCodexProjectStore(hippoRoot, logFile) {
511
+ async function sleepCodexProjectStore(hippoRoot, tenantId, logFile) {
513
512
  // Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
514
513
  if (isInitialized(hippoRoot)) {
515
514
  try {
516
- await (await import('./sleep.js')).cmdSleep(hippoRoot, logFile ? { 'log-file': logFile } : {});
515
+ await (await import('./sleep.js')).cmdSleep(hippoRoot, tenantId, logFile ? { 'log-file': logFile } : {});
517
516
  }
518
517
  catch (err) {
519
- log.debug(`codex session-end: sleep failed: ${errorMessage(err)}`);
518
+ reportSessionEndFailure(logFile ?? null, 'codex session-end: sleep', err);
520
519
  }
521
520
  }
522
521
  else {
@@ -524,7 +523,7 @@ async function sleepCodexProjectStore(hippoRoot, logFile) {
524
523
  logSessionEndImport(logFile ?? null, undefined);
525
524
  }
526
525
  }
527
- function captureCodexTranscript(hippoRoot, store, flags, logFile) {
526
+ function captureCodexTranscript(hippoRoot, tenantId, store, flags, logFile) {
528
527
  try {
529
528
  const codexHome = stringFlag(flags, 'codex-home') ?? resolveCodexWrapperPaths().codexHome;
530
529
  const historyPath = stringFlag(flags, 'history-path') ?? path.join(codexHome, 'history.jsonl');
@@ -549,7 +548,7 @@ function captureCodexTranscript(hippoRoot, store, flags, logFile) {
549
548
  logFile,
550
549
  dryRun: false,
551
550
  global: false,
552
- tenantId: resolveTenantId({}),
551
+ tenantId,
553
552
  originProject: store === hippoRoot ? undefined : resolveProjectIdentity(process.cwd()),
554
553
  sessionTurns: scan?.turns,
555
554
  };
@@ -557,13 +556,13 @@ function captureCodexTranscript(hippoRoot, store, flags, logFile) {
557
556
  cmdCapture(store, captureOpts);
558
557
  }
559
558
  catch (err) {
560
- log.debug(`codex session-end: capture failed: ${errorMessage(err)}`);
559
+ reportSessionEndFailure(logFile ?? null, 'codex session-end: capture', err);
561
560
  }
562
561
  // The Codex wrapper passes no session id, so the rollout file names the session.
563
- recordSessionDigest(hippoRoot, scan, { key: path.basename(transcriptPath, '.jsonl'), tenantId: resolveTenantId({}), log: digestLog });
562
+ recordSessionDigest(hippoRoot, scan, { key: path.basename(transcriptPath, '.jsonl'), tenantId, log: digestLog });
564
563
  }
565
564
  catch (err) {
566
- log.debug(`codex session-end: transcript scan or digest failed: ${errorMessage(err)}`);
565
+ reportSessionEndFailure(logFile ?? null, 'codex session-end: transcript scan or digest', err);
567
566
  }
568
567
  }
569
568
  export async function handlePreCompact({ hippoRoot, flags }) {
@@ -596,7 +595,7 @@ export async function handlePostCompact({ hippoRoot, flags }) {
596
595
  stdinText: text,
597
596
  stdinTimedOut: timedOut,
598
597
  logFile: logFlag === true || logFlag === false || Array.isArray(logFlag) ? undefined : logFlag,
599
- // Passed in, since capture.ts importing the sync would close an import cycle.
598
+ // Passed in, since src/capture/ importing the sync would close an import cycle.
600
599
  afterSave: (transcriptPath, cwd, log) => {
601
600
  const report = importSessionFolder(store, transcriptPath, cwd, { machine: currentMachine(), busyWaitMs: COMPACTION_DB_WAIT_MS });
602
601
  const summary = summaryLine(report);
@@ -609,7 +608,7 @@ export async function handlePostCompact({ hippoRoot, flags }) {
609
608
  if (line !== null && line !== undefined)
610
609
  console.log(line);
611
610
  }
612
- export async function handleCaptureError({ hippoRoot, flags }) {
611
+ export async function handleCaptureError({ hippoRoot, tenantId, flags }) {
613
612
  // PostToolUseFailure hook: every path exits 0, and nothing is created
614
613
  // when no store exists (the hook fires in every directory).
615
614
  const { text } = await readHookStdin();
@@ -619,7 +618,7 @@ export async function handleCaptureError({ hippoRoot, flags }) {
619
618
  if (isInitialized(root) && payload) {
620
619
  // SAFETY: JSON.parse returns a JSON value by definition.
621
620
  const failure = JSON.parse(payload);
622
- await runHookWithStores(() => captureToolFailure(root, resolveTenantId({}), failure));
621
+ await runHookWithStores(() => captureToolFailure(root, tenantId, failure));
623
622
  }
624
623
  }
625
624
  catch (err) {
@@ -627,14 +626,14 @@ export async function handleCaptureError({ hippoRoot, flags }) {
627
626
  log.warn(`failure capture skipped: ${errorMessage(err)}`);
628
627
  }
629
628
  }
630
- export async function handleCompactResume({ hippoRoot }) {
629
+ export async function handleCompactResume({ hippoRoot, tenantId }) {
631
630
  const { text: stdinText, timedOut: stdinTimedOut } = await readHookStdin();
632
631
  await runHookWithStores(() => {
633
632
  resetHookInjection(hippoRoot, stdinText, 'compact');
634
- cmdCompactResume(hookStoreRoot(hippoRoot), stdinText, stdinTimedOut);
633
+ cmdCompactResume(hookStoreRoot(hippoRoot), tenantId, stdinText, stdinTimedOut);
635
634
  });
636
635
  }
637
- export async function handleCapture({ hippoRoot, flags }) {
636
+ export async function handleCapture({ hippoRoot, tenantId, flags }) {
638
637
  let captureSource = null;
639
638
  let captureFile;
640
639
  let transcriptPath;
@@ -655,10 +654,10 @@ export async function handleCapture({ hippoRoot, flags }) {
655
654
  }
656
655
  if (!captureSource) {
657
656
  printError('Usage: hippo capture --stdin|--file <path>|--last-session [--transcript <path>] [--log-file <path>] [--dry-run] [--global]');
658
- process.exit(1);
657
+ throw new CliExit(1);
659
658
  }
660
659
  // Bounded, and only when last-session has no explicit path: the
661
- // --stdin source keeps its own blocking read in capture.ts by design.
660
+ // --stdin source keeps its own blocking read in src/capture/ by design.
662
661
  const bounded = captureSource === 'last-session' && !transcriptPath
663
662
  ? await readHookStdin()
664
663
  : { text: undefined, timedOut: false };
@@ -671,7 +670,7 @@ export async function handleCapture({ hippoRoot, flags }) {
671
670
  logFile: stringFlag(flags, 'log-file'),
672
671
  dryRun: boolFlag(flags, 'dry-run'),
673
672
  global: boolFlag(flags, 'global'),
674
- tenantId: resolveTenantId({}),
673
+ tenantId,
675
674
  });
676
675
  }
677
676
  //# sourceMappingURL=session-hooks.js.map