hippo-memory 1.71.0 → 2.0.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 (625) hide show
  1. package/README.md +7 -5
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +11 -26
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/copilot.d.ts +1 -3
  7. package/dist/agent-memories/copilot.js +1 -17
  8. package/dist/agent-memories/project-folds.d.ts +10 -0
  9. package/dist/agent-memories/project-folds.js +34 -0
  10. package/dist/agent-memories/sync.js +8 -6
  11. package/dist/api/assemble.js +3 -2
  12. package/dist/api/audit.d.ts +30 -2
  13. package/dist/api/audit.js +48 -7
  14. package/dist/api/auth.d.ts +11 -9
  15. package/dist/api/auth.js +39 -40
  16. package/dist/api/auto-sleep.d.ts +5 -2
  17. package/dist/api/auto-sleep.js +7 -3
  18. package/dist/api/availability.js +2 -3
  19. package/dist/api/cards.d.ts +42 -0
  20. package/dist/api/cards.js +52 -0
  21. package/dist/api/conflicts.d.ts +28 -0
  22. package/dist/api/conflicts.js +61 -0
  23. package/dist/api/context-auto.js +4 -2
  24. package/dist/api/context-render.js +4 -3
  25. package/dist/api/context-select.js +15 -29
  26. package/dist/api/context.js +29 -18
  27. package/dist/api/continuity.d.ts +47 -0
  28. package/dist/api/continuity.js +66 -0
  29. package/dist/api/dormant.js +4 -2
  30. package/dist/api/drill-down.js +3 -2
  31. package/dist/api/embeddings.d.ts +17 -0
  32. package/dist/api/embeddings.js +28 -0
  33. package/dist/api/error-reply.d.ts +8 -0
  34. package/dist/api/error-reply.js +21 -0
  35. package/dist/api/forget.d.ts +7 -3
  36. package/dist/api/forget.js +24 -14
  37. package/dist/api/goals.d.ts +1 -1
  38. package/dist/api/goals.js +5 -9
  39. package/dist/api/graph.js +2 -1
  40. package/dist/api/index.d.ts +4 -2
  41. package/dist/api/index.js +4 -2
  42. package/dist/api/instruction-detect.js +5 -1
  43. package/dist/api/learn.d.ts +5 -1
  44. package/dist/api/learn.js +71 -44
  45. package/dist/api/ledger-db.d.ts +2 -6
  46. package/dist/api/ledger-db.js +4 -36
  47. package/dist/api/memories.d.ts +21 -1
  48. package/dist/api/memories.js +51 -1
  49. package/dist/api/objects.d.ts +1 -1
  50. package/dist/api/objects.js +2 -1
  51. package/dist/api/outcome.d.ts +5 -5
  52. package/dist/api/outcome.js +17 -16
  53. package/dist/api/pilot-arm.d.ts +1 -11
  54. package/dist/api/pilot-arm.js +5 -45
  55. package/dist/api/predictions.d.ts +3 -1
  56. package/dist/api/predictions.js +8 -1
  57. package/dist/api/projects.d.ts +21 -0
  58. package/dist/api/projects.js +24 -0
  59. package/dist/api/promote.d.ts +3 -3
  60. package/dist/api/promote.js +26 -28
  61. package/dist/api/prompt-hook.d.ts +17 -2
  62. package/dist/api/prompt-hook.js +45 -4
  63. package/dist/api/quarantine.js +2 -1
  64. package/dist/api/recall-cli.d.ts +3 -0
  65. package/dist/api/recall-cli.js +13 -4
  66. package/dist/api/recall-core.js +10 -5
  67. package/dist/api/recall-pipeline.js +23 -24
  68. package/dist/api/recall-request.js +1 -1
  69. package/dist/api/recall-types.d.ts +3 -1
  70. package/dist/api/recall.d.ts +0 -3
  71. package/dist/api/recall.js +51 -73
  72. package/dist/api/remember-local.d.ts +5 -2
  73. package/dist/api/remember-local.js +15 -7
  74. package/dist/api/remember.d.ts +7 -3
  75. package/dist/api/remember.js +19 -16
  76. package/dist/api/session-end.d.ts +46 -0
  77. package/dist/api/session-end.js +131 -0
  78. package/dist/api/sleep-run.d.ts +1 -1
  79. package/dist/api/sleep-run.js +16 -11
  80. package/dist/api/sleep.js +4 -3
  81. package/dist/api/status.d.ts +24 -0
  82. package/dist/api/status.js +40 -0
  83. package/dist/api/store-init.d.ts +4 -0
  84. package/dist/api/store-init.js +9 -0
  85. package/dist/api/tokens.js +2 -2
  86. package/dist/api/types.d.ts +3 -7
  87. package/dist/api/types.js +6 -1
  88. package/dist/capture/caller-session.d.ts +0 -3
  89. package/dist/capture/caller-session.js +1 -12
  90. package/dist/capture/capture-error.d.ts +2 -2
  91. package/dist/capture/capture-error.js +23 -18
  92. package/dist/capture/codex-patch.js +3 -1
  93. package/dist/capture/command.js +36 -95
  94. package/dist/capture/compact.js +10 -5
  95. package/dist/capture/compaction-items-caller.js +11 -20
  96. package/dist/capture/compaction-record.d.ts +7 -93
  97. package/dist/capture/compaction-record.js +29 -426
  98. package/dist/capture/compaction-spool.d.ts +7 -7
  99. package/dist/capture/compaction-spool.js +60 -51
  100. package/dist/capture/copilot-transcript.d.ts +2 -1
  101. package/dist/capture/copilot-transcript.js +2 -1
  102. package/dist/capture/extract.d.ts +5 -2
  103. package/dist/capture/extract.js +4 -3
  104. package/dist/capture/failure-caller.d.ts +1 -1
  105. package/dist/capture/failure-caller.js +21 -16
  106. package/dist/capture/failure-reading.d.ts +2 -1
  107. package/dist/capture/failure-reading.js +7 -9
  108. package/dist/capture/pre-compact-caller.js +5 -4
  109. package/dist/capture/session-digest.js +4 -3
  110. package/dist/capture/session-end-caller.js +3 -2
  111. package/dist/capture/session-worker.js +22 -10
  112. package/dist/capture/transcript.d.ts +2 -1
  113. package/dist/capture/transcript.js +6 -3
  114. package/dist/capture/working-state.d.ts +4 -2
  115. package/dist/capture/working-state.js +4 -2
  116. package/dist/cli/audit-prune.d.ts +0 -25
  117. package/dist/cli/audit-prune.js +1 -27
  118. package/dist/cli/audit.js +20 -20
  119. package/dist/cli/auth.d.ts +1 -1
  120. package/dist/cli/auth.js +16 -17
  121. package/dist/cli/briefs.d.ts +1 -4
  122. package/dist/cli/briefs.js +37 -292
  123. package/dist/cli/card.js +41 -33
  124. package/dist/cli/client.d.ts +6 -2
  125. package/dist/cli/client.js +37 -21
  126. package/dist/cli/compact-resume-payload.js +1 -1
  127. package/dist/cli/context.d.ts +1 -1
  128. package/dist/cli/context.js +13 -13
  129. package/dist/cli/continuity.d.ts +1 -1
  130. package/dist/cli/continuity.js +36 -39
  131. package/dist/cli/curate.d.ts +2 -2
  132. package/dist/cli/curate.js +32 -36
  133. package/dist/cli/dag.d.ts +1 -1
  134. package/dist/cli/dag.js +23 -8
  135. package/dist/cli/decisions.d.ts +0 -2
  136. package/dist/cli/decisions.js +7 -285
  137. package/dist/cli/eval.d.ts +1 -1
  138. package/dist/cli/eval.js +12 -13
  139. package/dist/cli/explain.d.ts +1 -1
  140. package/dist/cli/explain.js +21 -25
  141. package/dist/cli/flag-values.js +16 -6
  142. package/dist/cli/flags.d.ts +0 -289
  143. package/dist/cli/flags.js +3 -138
  144. package/dist/cli/graph.d.ts +3 -0
  145. package/dist/cli/graph.js +83 -0
  146. package/dist/cli/hook-runtime.d.ts +6 -6
  147. package/dist/cli/hook-runtime.js +9 -36
  148. package/dist/cli/incidents.d.ts +3 -0
  149. package/dist/cli/incidents.js +112 -0
  150. package/dist/cli/init.d.ts +1 -1
  151. package/dist/cli/init.js +28 -19
  152. package/dist/cli/install-steps.d.ts +2 -1
  153. package/dist/cli/install-steps.js +11 -3
  154. package/dist/cli/last-sleep.js +1 -1
  155. package/dist/cli/maintenance.d.ts +3 -3
  156. package/dist/cli/maintenance.js +29 -30
  157. package/dist/cli/notes.d.ts +2 -0
  158. package/dist/cli/notes.js +41 -0
  159. package/dist/cli/object-verbs.d.ts +2 -2
  160. package/dist/cli/object-verbs.js +4 -4
  161. package/dist/cli/open-browser.d.ts +14 -0
  162. package/dist/cli/open-browser.js +26 -0
  163. package/dist/cli/playbooks.d.ts +3 -4
  164. package/dist/cli/playbooks.js +126 -290
  165. package/dist/cli/predictions.d.ts +3 -0
  166. package/dist/cli/predictions.js +174 -0
  167. package/dist/cli/print.js +2 -1
  168. package/dist/cli/projects.js +30 -22
  169. package/dist/cli/quality-repair-once.d.ts +1 -1
  170. package/dist/cli/quality-repair-once.js +6 -5
  171. package/dist/cli/recall.js +13 -7
  172. package/dist/cli/refine-llm.js +18 -17
  173. package/dist/cli/remember.js +17 -17
  174. package/dist/cli/scheduler.js +2 -1
  175. package/dist/cli/serve.js +11 -6
  176. package/dist/cli/session-hooks.d.ts +1 -5
  177. package/dist/cli/session-hooks.js +89 -168
  178. package/dist/cli/setup.d.ts +1 -1
  179. package/dist/cli/setup.js +17 -10
  180. package/dist/cli/shared.d.ts +2 -6
  181. package/dist/cli/shared.js +9 -29
  182. package/dist/cli/sleep-render.js +6 -3
  183. package/dist/cli/sleep.js +6 -37
  184. package/dist/cli/status.d.ts +3 -3
  185. package/dist/cli/status.js +32 -35
  186. package/dist/cli/transfer.d.ts +3 -3
  187. package/dist/cli/transfer.js +64 -43
  188. package/dist/cli/usage.d.ts +1 -80
  189. package/dist/cli/usage.js +2 -696
  190. package/dist/cli/verb-row.d.ts +34 -0
  191. package/dist/cli/verb-row.js +6 -0
  192. package/dist/cli/verbs/health.d.ts +27 -0
  193. package/dist/cli/verbs/health.js +234 -0
  194. package/dist/cli/verbs/memory.d.ts +16 -0
  195. package/dist/cli/verbs/memory.js +236 -0
  196. package/dist/cli/verbs/objects.d.ts +20 -0
  197. package/dist/cli/verbs/objects.js +257 -0
  198. package/dist/cli/verbs/sessions.d.ts +31 -0
  199. package/dist/cli/verbs/sessions.js +314 -0
  200. package/dist/cli/verbs.d.ts +81 -0
  201. package/dist/cli/verbs.js +7 -0
  202. package/dist/cli/versioned-verbs.d.ts +51 -0
  203. package/dist/cli/versioned-verbs.js +79 -0
  204. package/dist/cli.d.ts +1 -272
  205. package/dist/cli.js +24 -315
  206. package/dist/connectors/dlq.d.ts +39 -3
  207. package/dist/connectors/dlq.js +39 -4
  208. package/dist/connectors/github/backfill.js +12 -3
  209. package/dist/connectors/github/deletion.js +2 -1
  210. package/dist/connectors/github/dlq.js +31 -73
  211. package/dist/connectors/github/ingest.d.ts +2 -6
  212. package/dist/connectors/github/ingest.js +5 -29
  213. package/dist/connectors/github/tenant-routing.js +2 -1
  214. package/dist/connectors/github/webhook.d.ts +2 -1
  215. package/dist/connectors/github/webhook.js +35 -2
  216. package/dist/connectors/ingest.d.ts +10 -0
  217. package/dist/connectors/ingest.js +29 -0
  218. package/dist/connectors/slack/deletion.js +2 -1
  219. package/dist/connectors/slack/dlq.js +49 -71
  220. package/dist/connectors/slack/ingest.d.ts +2 -6
  221. package/dist/connectors/slack/ingest.js +4 -28
  222. package/dist/connectors/slack/tenant-routing.js +2 -1
  223. package/dist/connectors/slack/webhook.d.ts +2 -1
  224. package/dist/connectors/slack/webhook.js +2 -1
  225. package/dist/consolidate/conflicts.js +2 -2
  226. package/dist/consolidate/dag.js +29 -18
  227. package/dist/consolidate/dedupe.d.ts +7 -0
  228. package/dist/consolidate/dedupe.js +6 -4
  229. package/dist/consolidate/llm-passes.js +45 -19
  230. package/dist/consolidate/memory-value.js +3 -2
  231. package/dist/consolidate/merge.js +8 -8
  232. package/dist/consolidate/physics-pass.d.ts +6 -1
  233. package/dist/consolidate/physics-pass.js +26 -6
  234. package/dist/consolidate/replay.js +11 -4
  235. package/dist/consolidate/sleep.js +9 -6
  236. package/dist/consolidate/traces.js +5 -5
  237. package/dist/core/ablation.d.ts +10 -0
  238. package/dist/core/ablation.js +12 -0
  239. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  240. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  241. package/dist/core/ambient.d.ts +4 -0
  242. package/dist/core/ambient.js +39 -18
  243. package/dist/core/api-errors.d.ts +16 -0
  244. package/dist/core/api-errors.js +20 -0
  245. package/dist/core/card.js +3 -1
  246. package/dist/core/compaction-timing.d.ts +7 -0
  247. package/dist/core/compaction-timing.js +9 -0
  248. package/dist/core/config.d.ts +1 -1
  249. package/dist/core/config.js +22 -18
  250. package/dist/core/cosine.d.ts +3 -0
  251. package/dist/core/cosine.js +19 -0
  252. package/dist/{store → core}/markdown.d.ts +1 -1
  253. package/dist/{store → core}/markdown.js +4 -4
  254. package/dist/core/memory-audit.d.ts +17 -0
  255. package/dist/core/memory-audit.js +54 -0
  256. package/dist/core/memory.d.ts +14 -8
  257. package/dist/core/memory.js +35 -23
  258. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  259. package/dist/{consolidate → core}/merged-row.js +1 -1
  260. package/dist/core/physics.d.ts +3 -1
  261. package/dist/core/physics.js +23 -18
  262. package/dist/core/prediction.d.ts +3 -0
  263. package/dist/core/prediction.js +6 -0
  264. package/dist/core/project-identity.d.ts +3 -0
  265. package/dist/core/project-identity.js +12 -2
  266. package/dist/{store → core}/recall-scope.d.ts +1 -10
  267. package/dist/{store → core}/recall-scope.js +2 -19
  268. package/dist/core/search-types.d.ts +1 -1
  269. package/dist/dashboard/dashboard-actions.d.ts +2 -2
  270. package/dist/dashboard/dashboard-actions.js +5 -5
  271. package/dist/dashboard/dashboard-queries.js +2 -7
  272. package/dist/dashboard/dashboard-snapshot.js +1 -3
  273. package/dist/dashboard/dashboard.js +16 -5
  274. package/dist/db/busy.d.ts +2 -7
  275. package/dist/db/busy.js +21 -26
  276. package/dist/db/connect.d.ts +2 -2
  277. package/dist/db/connect.js +7 -7
  278. package/dist/db/index.d.ts +3 -3
  279. package/dist/db/index.js +3 -3
  280. package/dist/db/migrate.js +14 -7
  281. package/dist/db/migrations/index.d.ts +1 -1
  282. package/dist/db/migrations/index.js +3 -1
  283. package/dist/db/migrations/v11.js +1 -0
  284. package/dist/db/migrations/v14.js +1 -0
  285. package/dist/db/migrations/v55.d.ts +3 -0
  286. package/dist/db/migrations/v55.js +17 -0
  287. package/dist/db/open.d.ts +0 -2
  288. package/dist/db/open.js +6 -10
  289. package/dist/db/physics-state.d.ts +0 -4
  290. package/dist/db/physics-state.js +7 -33
  291. package/dist/db/request-stores.d.ts +1 -0
  292. package/dist/db/request-stores.js +2 -1
  293. package/dist/db/tables.d.ts +2 -0
  294. package/dist/db/tables.js +6 -2
  295. package/dist/db/vector-store.js +19 -5
  296. package/dist/db/wal-checkpointer.js +2 -1
  297. package/dist/doctor.d.ts +3 -0
  298. package/dist/doctor.js +18 -15
  299. package/dist/embeddings/local.d.ts +62 -0
  300. package/dist/embeddings/local.js +146 -0
  301. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  302. package/dist/{store/embeddings → embeddings}/provider.js +19 -25
  303. package/dist/embeddings/transformers.d.ts +26 -0
  304. package/dist/embeddings/transformers.js +89 -0
  305. package/dist/entry/session-text.d.ts +1 -1
  306. package/dist/entry/session-text.js +1 -1
  307. package/dist/entry/store-kit.d.ts +37 -0
  308. package/dist/entry/store-kit.js +25 -0
  309. package/dist/entry/testing.d.ts +6 -0
  310. package/dist/entry/testing.js +7 -0
  311. package/dist/eval/eval-suite.js +17 -11
  312. package/dist/eval/eval.js +1 -1
  313. package/dist/eval/judgment.js +12 -5
  314. package/dist/graph/extract.js +3 -3
  315. package/dist/graph/recall.js +1 -1
  316. package/dist/graph/view.js +13 -5
  317. package/dist/graph/write.d.ts +1 -1
  318. package/dist/graph/write.js +9 -9
  319. package/dist/hooks/codex-session.js +3 -2
  320. package/dist/hooks/codex-wrapper.js +2 -1
  321. package/dist/hooks/json-hooks.js +10 -4
  322. package/dist/hooks/opencode.js +8 -5
  323. package/dist/hooks/shared.d.ts +0 -6
  324. package/dist/hooks/shared.js +4 -15
  325. package/dist/importers/core.js +4 -4
  326. package/dist/importers/sources.js +5 -4
  327. package/dist/importers/vault.d.ts +1 -1
  328. package/dist/importers/vault.js +25 -23
  329. package/dist/index.d.ts +5 -4
  330. package/dist/index.js +4 -3
  331. package/dist/learn/autolearn.d.ts +15 -3
  332. package/dist/learn/autolearn.js +38 -16
  333. package/dist/learn/churn-git.js +13 -4
  334. package/dist/learn/extract.d.ts +3 -2
  335. package/dist/learn/extract.js +7 -5
  336. package/dist/learn/forward-claim-detector.js +4 -2
  337. package/dist/learn/invalidation.d.ts +2 -1
  338. package/dist/learn/invalidation.js +18 -9
  339. package/dist/mcp/admin-tools.d.ts +2 -2
  340. package/dist/mcp/admin-tools.js +27 -48
  341. package/dist/mcp/format.js +3 -2
  342. package/dist/mcp/framing.d.ts +1 -0
  343. package/dist/mcp/framing.js +1 -1
  344. package/dist/mcp/memory-tools.d.ts +1 -1
  345. package/dist/mcp/memory-tools.js +8 -9
  346. package/dist/mcp/protocol.d.ts +11 -7
  347. package/dist/mcp/protocol.js +25 -12
  348. package/dist/mcp/recall-tools.js +12 -9
  349. package/dist/mcp/request.js +22 -20
  350. package/dist/mcp/stdio.js +37 -16
  351. package/dist/mcp/tool-args.js +2 -1
  352. package/dist/mcp/tools.js +44 -21
  353. package/dist/objects/customer-notes.d.ts +2 -2
  354. package/dist/objects/decisions.d.ts +2 -2
  355. package/dist/objects/descriptor.d.ts +1 -1
  356. package/dist/objects/incidents.d.ts +2 -2
  357. package/dist/objects/lifecycle.d.ts +1 -1
  358. package/dist/objects/lifecycle.js +2 -1
  359. package/dist/objects/policies.d.ts +2 -2
  360. package/dist/objects/policies.js +2 -1
  361. package/dist/objects/processes.d.ts +2 -2
  362. package/dist/objects/project-briefs.d.ts +2 -2
  363. package/dist/objects/project-briefs.js +2 -3
  364. package/dist/objects/skills.d.ts +2 -2
  365. package/dist/postinstall.js +1 -1
  366. package/dist/rerankers/clef.js +3 -6
  367. package/dist/rerankers/cross-encoder.d.ts +31 -2
  368. package/dist/rerankers/cross-encoder.js +71 -98
  369. package/dist/rerankers/index.js +5 -4
  370. package/dist/rerankers/jev.js +2 -4
  371. package/dist/rerankers/outage-warning.d.ts +3 -1
  372. package/dist/rerankers/outage-warning.js +5 -3
  373. package/dist/search/bm25-search.js +1 -1
  374. package/dist/search/boosts.js +1 -1
  375. package/dist/search/embed-memories.d.ts +12 -0
  376. package/dist/search/embed-memories.js +389 -0
  377. package/dist/search/engine.d.ts +8 -0
  378. package/dist/search/engine.js +10 -0
  379. package/dist/search/goal-boost.d.ts +1 -1
  380. package/dist/search/goal-boost.js +6 -3
  381. package/dist/search/hybrid.d.ts +9 -2
  382. package/dist/search/hybrid.js +9 -4
  383. package/dist/search/physics-search.d.ts +6 -3
  384. package/dist/search/physics-search.js +22 -15
  385. package/dist/search/rerank.js +1 -1
  386. package/dist/search/vector.d.ts +8 -6
  387. package/dist/search/vector.js +14 -17
  388. package/dist/server/auth.d.ts +3 -1
  389. package/dist/server/auth.js +24 -15
  390. package/dist/server/boot.d.ts +2 -1
  391. package/dist/server/boot.js +34 -84
  392. package/dist/server/client-ip.d.ts +9 -6
  393. package/dist/server/client-ip.js +36 -17
  394. package/dist/server/deadline.d.ts +0 -2
  395. package/dist/server/deadline.js +1 -7
  396. package/dist/server/defaults.d.ts +1 -0
  397. package/dist/server/defaults.js +1 -0
  398. package/dist/server/mcp-http.js +16 -11
  399. package/dist/server/request.js +7 -2
  400. package/dist/server/route-checks.d.ts +7 -0
  401. package/dist/server/route-checks.js +42 -0
  402. package/dist/server/route-table.d.ts +9 -8
  403. package/dist/server/route-table.js +127 -133
  404. package/dist/server/routes/admin.d.ts +8 -8
  405. package/dist/server/routes/admin.js +13 -21
  406. package/dist/server/routes/customer-notes.d.ts +6 -6
  407. package/dist/server/routes/customer-notes.js +1 -2
  408. package/dist/server/routes/decisions.d.ts +6 -6
  409. package/dist/server/routes/decisions.js +2 -4
  410. package/dist/server/routes/incidents.d.ts +6 -6
  411. package/dist/server/routes/incidents.js +2 -5
  412. package/dist/server/routes/memories.d.ts +9 -9
  413. package/dist/server/routes/memories.js +19 -40
  414. package/dist/server/routes/object-routes.d.ts +6 -6
  415. package/dist/server/routes/object-routes.js +4 -7
  416. package/dist/server/routes/policies.d.ts +7 -7
  417. package/dist/server/routes/policies.js +2 -4
  418. package/dist/server/routes/predictions.d.ts +6 -6
  419. package/dist/server/routes/predictions.js +9 -13
  420. package/dist/server/routes/processes.d.ts +6 -6
  421. package/dist/server/routes/processes.js +1 -2
  422. package/dist/server/routes/project-briefs.d.ts +7 -7
  423. package/dist/server/routes/project-briefs.js +2 -4
  424. package/dist/server/routes/recall.d.ts +5 -5
  425. package/dist/server/routes/recall.js +6 -10
  426. package/dist/server/routes/skills.d.ts +7 -7
  427. package/dist/server/routes/skills.js +2 -4
  428. package/dist/server/server-detect.d.ts +7 -1
  429. package/dist/server/server-detect.js +36 -11
  430. package/dist/server/sleep-child.js +26 -7
  431. package/dist/server/sleep-offload.d.ts +11 -5
  432. package/dist/server/sleep-offload.js +17 -11
  433. package/dist/server/tls.d.ts +7 -2
  434. package/dist/server/tls.js +17 -5
  435. package/dist/server/types.d.ts +29 -12
  436. package/dist/server/validation.d.ts +1 -2
  437. package/dist/server/validation.js +6 -11
  438. package/dist/server.d.ts +4 -40
  439. package/dist/server.js +3 -29
  440. package/dist/sharing/global-store.d.ts +4 -5
  441. package/dist/sharing/global-store.js +8 -13
  442. package/dist/sharing/global-sync.js +38 -45
  443. package/dist/sharing/project-merge.d.ts +7 -14
  444. package/dist/sharing/project-merge.js +57 -121
  445. package/dist/sharing/search-both.js +10 -3
  446. package/dist/sharing/share.d.ts +2 -0
  447. package/dist/sharing/share.js +39 -38
  448. package/dist/store/ambient.js +7 -7
  449. package/dist/store/audit-event.d.ts +1 -1
  450. package/dist/store/audit.d.ts +0 -16
  451. package/dist/store/audit.js +4 -55
  452. package/dist/store/auth.d.ts +4 -2
  453. package/dist/store/auth.js +7 -3
  454. package/dist/store/candidates.d.ts +3 -2
  455. package/dist/store/candidates.js +59 -30
  456. package/dist/store/capture-write.d.ts +17 -0
  457. package/dist/store/capture-write.js +35 -0
  458. package/dist/store/cards.js +6 -5
  459. package/dist/store/compaction-caller.d.ts +18 -0
  460. package/dist/store/compaction-caller.js +29 -0
  461. package/dist/store/compactions-record.d.ts +115 -0
  462. package/dist/store/compactions-record.js +418 -0
  463. package/dist/store/compactions.js +6 -4
  464. package/dist/store/conflicts.d.ts +7 -1
  465. package/dist/store/conflicts.js +13 -9
  466. package/dist/store/connectors/dlq.d.ts +10 -0
  467. package/dist/store/connectors/dlq.js +33 -0
  468. package/dist/store/connectors/event-log.d.ts +13 -0
  469. package/dist/store/connectors/event-log.js +24 -0
  470. package/dist/store/connectors/github.d.ts +7 -9
  471. package/dist/store/connectors/github.js +35 -60
  472. package/dist/store/connectors/slack.d.ts +2 -11
  473. package/dist/store/connectors/slack.js +24 -57
  474. package/dist/store/dashboard-reads.js +8 -6
  475. package/dist/store/delete-and-batch.d.ts +6 -0
  476. package/dist/store/delete-and-batch.js +40 -6
  477. package/dist/store/delivery-recorder.d.ts +12 -5
  478. package/dist/store/delivery-recorder.js +13 -11
  479. package/dist/store/descendant-page.js +8 -4
  480. package/dist/store/dormant.d.ts +1 -1
  481. package/dist/store/dormant.js +10 -4
  482. package/dist/store/embeddings/index.d.ts +2 -12
  483. package/dist/store/embeddings/index.js +5 -374
  484. package/dist/store/entry-reads.d.ts +35 -4
  485. package/dist/store/entry-reads.js +86 -19
  486. package/dist/store/entry-row.js +9 -2
  487. package/dist/store/entry-writes.d.ts +15 -12
  488. package/dist/store/entry-writes.js +54 -22
  489. package/dist/store/failure-log-at.d.ts +8 -0
  490. package/dist/store/failure-log-at.js +16 -0
  491. package/dist/store/failure-log.d.ts +2 -2
  492. package/dist/store/failure-log.js +5 -3
  493. package/dist/{trust → store}/gated-write.d.ts +3 -1
  494. package/dist/{trust → store}/gated-write.js +7 -5
  495. package/dist/store/goals.js +22 -19
  496. package/dist/store/graph-reads.js +9 -6
  497. package/dist/store/graph-view-rows.js +2 -1
  498. package/dist/store/graph-writes.d.ts +6 -6
  499. package/dist/store/graph-writes.js +48 -71
  500. package/dist/store/half-life.js +2 -2
  501. package/dist/store/handoffs.d.ts +10 -4
  502. package/dist/store/handoffs.js +10 -9
  503. package/dist/store/index-and-stats.js +2 -2
  504. package/dist/store/index.d.ts +2 -2
  505. package/dist/store/index.js +1 -1
  506. package/dist/store/key-writes.js +1 -1
  507. package/dist/store/ledger-turn.d.ts +9 -0
  508. package/dist/store/ledger-turn.js +38 -0
  509. package/dist/store/mirrors.js +19 -10
  510. package/dist/store/open.d.ts +2 -5
  511. package/dist/store/open.js +42 -54
  512. package/dist/store/pilot-arm.d.ts +12 -0
  513. package/dist/store/pilot-arm.js +42 -0
  514. package/dist/store/port.d.ts +68 -6
  515. package/dist/store/port.js +8 -0
  516. package/dist/store/predictions.d.ts +1 -2
  517. package/dist/store/predictions.js +3 -6
  518. package/dist/store/project-tags.d.ts +62 -0
  519. package/dist/store/project-tags.js +67 -0
  520. package/dist/store/quality-repair.js +1 -1
  521. package/dist/store/quarantine.js +2 -1
  522. package/dist/store/recall-trace.d.ts +2 -0
  523. package/dist/store/recall-trace.js +20 -3
  524. package/dist/store/rejected-values.js +16 -10
  525. package/dist/store/rejection-probe.d.ts +4 -0
  526. package/dist/store/rejection-probe.js +19 -0
  527. package/dist/store/rejection.d.ts +0 -17
  528. package/dist/store/rejection.js +1 -21
  529. package/dist/store/rows.js +2 -2
  530. package/dist/store/rule-sql.d.ts +11 -0
  531. package/dist/store/rule-sql.js +31 -6
  532. package/dist/store/search-rows.d.ts +5 -5
  533. package/dist/store/search-rows.js +18 -16
  534. package/dist/store/sessions.js +4 -2
  535. package/dist/store/set-aside.d.ts +14 -0
  536. package/dist/store/set-aside.js +23 -0
  537. package/dist/store/sqlite/busy.d.ts +3 -0
  538. package/dist/store/sqlite/busy.js +8 -0
  539. package/dist/store/sqlite/connector-events-group.js +4 -7
  540. package/dist/store/sqlite/connector-writes-group.js +6 -4
  541. package/dist/store/sqlite/entry-writes-group.d.ts +3 -3
  542. package/dist/store/sqlite/entry-writes-group.js +3 -3
  543. package/dist/store/sqlite/error-codec.js +4 -3
  544. package/dist/store/sqlite/executor.js +10 -4
  545. package/dist/store/sqlite/graph-reads-group.js +1 -1
  546. package/dist/store/sqlite/held-connection.d.ts +11 -0
  547. package/dist/store/sqlite/held-connection.js +41 -0
  548. package/dist/store/sqlite/last-recall-group.d.ts +13 -0
  549. package/dist/store/sqlite/last-recall-group.js +57 -0
  550. package/dist/store/sqlite/local.d.ts +0 -17
  551. package/dist/store/sqlite/local.js +0 -31
  552. package/dist/store/sqlite/maintenance-groups.d.ts +6 -0
  553. package/dist/store/sqlite/maintenance-groups.js +60 -0
  554. package/dist/store/sqlite/object-rows.d.ts +1 -1
  555. package/dist/store/sqlite/objects-group.d.ts +1 -1
  556. package/dist/store/sqlite/objects-group.js +15 -7
  557. package/dist/store/sqlite/store.d.ts +1 -8
  558. package/dist/store/sqlite/store.js +13 -22
  559. package/dist/store/summaries.d.ts +10 -3
  560. package/dist/store/summaries.js +54 -11
  561. package/dist/store/token-ledger-rows.js +3 -2
  562. package/dist/store/token-ledger.d.ts +0 -7
  563. package/dist/store/token-ledger.js +0 -35
  564. package/dist/store/vector-index.js +8 -4
  565. package/dist/support-bundle.js +2 -3
  566. package/dist/trust/reject-flow.js +2 -2
  567. package/dist/util/agent-homes.d.ts +15 -0
  568. package/dist/util/agent-homes.js +34 -0
  569. package/dist/util/anthropic-messages.d.ts +6 -1
  570. package/dist/util/anthropic-messages.js +26 -7
  571. package/dist/util/atomic-write.d.ts +5 -2
  572. package/dist/util/atomic-write.js +12 -8
  573. package/dist/util/chunked.d.ts +3 -0
  574. package/dist/util/chunked.js +10 -0
  575. package/dist/util/ellipsize.d.ts +3 -0
  576. package/dist/util/ellipsize.js +5 -0
  577. package/dist/util/env.d.ts +12 -2
  578. package/dist/util/env.js +12 -2
  579. package/dist/util/format.d.ts +5 -0
  580. package/dist/util/format.js +10 -0
  581. package/dist/util/hook-payload.d.ts +8 -0
  582. package/dist/util/hook-payload.js +37 -0
  583. package/dist/util/http-retry.d.ts +6 -0
  584. package/dist/util/http-retry.js +43 -5
  585. package/dist/util/http-util.d.ts +0 -8
  586. package/dist/util/http-util.js +10 -21
  587. package/dist/util/limits.d.ts +7 -0
  588. package/dist/util/limits.js +14 -0
  589. package/dist/util/log.d.ts +4 -0
  590. package/dist/util/log.js +9 -0
  591. package/dist/util/request-scope.d.ts +9 -3
  592. package/dist/util/request-scope.js +18 -9
  593. package/dist/util/secret-detect.js +6 -1
  594. package/dist/util/spawn-argv.d.ts +9 -0
  595. package/dist/util/spawn-argv.js +57 -0
  596. package/dist/util/sql.d.ts +3 -0
  597. package/dist/util/sql.js +6 -0
  598. package/dist/util/sqlite-blocked.d.ts +2 -0
  599. package/dist/util/sqlite-blocked.js +5 -0
  600. package/dist/util/stream-tee.d.ts +3 -0
  601. package/dist/util/stream-tee.js +35 -0
  602. package/dist/util/time.d.ts +4 -0
  603. package/dist/util/time.js +4 -0
  604. package/dist/util/vector-codec.d.ts +4 -0
  605. package/dist/util/vector-codec.js +15 -0
  606. package/dist/util/version.d.ts +1 -1
  607. package/dist/util/version.js +1 -1
  608. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  609. package/extensions/openclaw-plugin/package.json +1 -1
  610. package/openclaw.plugin.json +1 -1
  611. package/package.json +4 -2
  612. package/dist/api/on-store.d.ts +0 -16
  613. package/dist/api/on-store.js +0 -38
  614. package/dist/store/embeddings/local.d.ts +0 -15
  615. package/dist/store/embeddings/local.js +0 -175
  616. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  617. /package/dist/{cli → api}/correction-latency.js +0 -0
  618. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  619. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  620. /package/dist/{store → core}/object-types.d.ts +0 -0
  621. /package/dist/{store → core}/object-types.js +0 -0
  622. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  623. /package/dist/{capture → util}/compaction-items.js +0 -0
  624. /package/dist/{store → util}/yaml.d.ts +0 -0
  625. /package/dist/{store → util}/yaml.js +0 -0
@@ -5,17 +5,12 @@ import { spawn } from 'child_process';
5
5
  import { resolveCodexSessionTranscript } from '../hooks/codex-session.js';
6
6
  import { resolveCodexWrapperPaths } from '../hooks/codex-wrapper.js';
7
7
  import { resolveJsonHookPaths } from '../hooks/json-hooks.js';
8
- import { isInitialized } from '../store/open.js';
9
- import { loadActiveTaskSnapshot, loadFreshActiveTaskSnapshot, closeTaskSnapshotsForSession, listSessionEvents, } from '../store/sessions.js';
10
- import { writeSessionEndHandoff } from '../store/handoffs.js';
11
8
  import { readSessionScan, recordSessionDigest } from '../capture/session-digest.js';
12
9
  import { captureToolFailure } from '../capture/capture-error.js';
13
- import { readApiCalls, recordRereads, } from '../store/token-ledger.js';
14
10
  import { estimateTokens } from '../util/token-text.js';
15
11
  import { currentMachine, importSessionFolder } from '../agent-memories/sync.js';
16
12
  import { summaryLine } from '../agent-memories/report.js';
17
- import { resolveProjectIdentity } from '../core/project-identity.js';
18
- import { getGlobalRoot } from '../sharing/global-store.js';
13
+ import { resolveProjectIdentity, isInitialized } from '../core/project-identity.js';
19
14
  import { cmdCapture } from '../capture/command.js';
20
15
  import { cmdPreCompact, cmdPostCompact } from '../capture/compact.js';
21
16
  import { transcriptWorkingState } from '../capture/working-state.js';
@@ -25,18 +20,19 @@ import { loadTurnPosition, runSessionWorker, saveTurnPosition, turnsAfter } from
25
20
  import { isStringValue, readSessionEnd, readVscodeStop } from '../core/capture-contract.js';
26
21
  import { loadConfig } from '../core/config.js';
27
22
  import { autoSleepDue } from '../api/auto-sleep.js';
28
- import { truncateCodePointSafe } from '../util/transcript-tail.js';
29
- import { COMPACTION_DB_WAIT_MS } from '../capture/compaction-record.js';
30
- import { COMPACT_RESUME_EVENT_CONTENT_CAP, COMPACT_RESUME_MAX_AGE_MS, compactResumeText } from '../api/context-render.js';
23
+ import { COMPACTION_DB_WAIT_MS } from '../core/compaction-timing.js';
24
+ import { compactResumeBlock, sessionEndWork as runSessionEnd } from '../api/session-end.js';
31
25
  import { normaliseHookPayload, readHookStdin, readStdinBounded } from './stdin.js';
32
26
  import { errorMessage, log } from '../util/log.js';
27
+ import { cmdShimArgs } from '../util/spawn-argv.js';
33
28
  import { bookLedgerTurn } from '../api/ledger-db.js';
34
- import { flushDeliveryRecorder } from '../api/prompt-hook.js';
29
+ import { flushDeliveryRecorder, startDeliveryRecorder, startToolFailureRecorder } from '../api/prompt-hook.js';
35
30
  import { printError } from './output.js';
36
31
  import { cmdLastSleep } from './last-sleep.js';
37
32
  import { readCompactResumePayload } from './compact-resume-payload.js';
33
+ import { cliApiContext } from './api-context.js';
38
34
  import { boolFlag, flagIsTrue, stringFlag } from './flag-values.js';
39
- import { logSessionEndImport, appendSessionEndCloseLog, reportSessionEndFailure, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout, startDeliveryRecorder, } from './hook-runtime.js';
35
+ import { logSessionEndImport, appendSessionEndCloseLog, reportSessionEndFailure, resetHookInjection, hookStoreRoot, hookRuntime, payloadCwdRoot, runHookWithStores, inPilotHoldout, hostSessionId, } from './hook-runtime.js';
40
36
  import { CliExit } from './exit.js';
41
37
  /** SessionStart(compact) injector: prints the task snapshot and session trail lost to compaction; no pinned memories (UserPromptSubmit re-injects them).
42
38
  * Every path exits 0: a malformed payload or store read failure degrades to empty stdout, never a throw. */
@@ -51,10 +47,13 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
51
47
  const payloadState = readCompactResumePayload(stdinText, stdinTimedOut);
52
48
  let suppressOutput = payloadState.suppressOutput;
53
49
  const payloadSessionId = payloadState.payloadSessionId;
54
- if (payloadState.boundary)
55
- rec = startDeliveryRecorder(hippoRoot, stdinText, 'claude-code', 'compact-resume');
50
+ if (payloadState.boundary) {
51
+ rec = startDeliveryRecorder(cliApiContext(hippoRoot, tenantId), {
52
+ stdinText, runtime: 'claude-code', eventType: 'compact-resume', envSessionId: hostSessionId(),
53
+ });
54
+ }
56
55
  // A compaction follows a prompt or SessionStart that booked the arm, so this only reads it.
57
- if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, false)) {
56
+ if (!suppressOutput && payloadSessionId !== null && inPilotHoldout(hippoRoot, tenantId, payloadSessionId, { write: false })) {
58
57
  suppressOutput = true;
59
58
  rec?.disabled();
60
59
  }
@@ -72,30 +71,10 @@ function cmdCompactResume(hippoRoot, tenantId, stdinText, stdinTimedOut) {
72
71
  throw new CliExit(0);
73
72
  }
74
73
  function restoreCompactSnapshot(hippoRoot, tenantId, payloadSessionId, rec) {
75
- const snapshot = loadFreshActiveTaskSnapshot(hippoRoot, tenantId, { maxAgeMs: COMPACT_RESUME_MAX_AGE_MS });
76
- // Concurrent sessions must not cross-restore. Only suppress when BOTH ids are present and differ;
77
- // either side missing, or a manual invocation with no payload session_id, still prints.
78
- const sessionMismatch = !!snapshot &&
79
- payloadSessionId !== null &&
80
- snapshot.session_id !== null &&
81
- payloadSessionId !== snapshot.session_id;
82
- if (!snapshot || sessionMismatch)
74
+ const text = compactResumeBlock(cliApiContext(hippoRoot, tenantId), payloadSessionId);
75
+ if (text === null)
83
76
  return;
84
- // Loaded before the print so a bad trail row costs the trail, not the snapshot; stderr stays out of the model's context.
85
- let events = [];
86
- try {
87
- if (snapshot.session_id) {
88
- events = listSessionEvents(hippoRoot, tenantId, { session_id: snapshot.session_id }).map((e) => ({
89
- ...e,
90
- content: truncateCodePointSafe(e.content, COMPACT_RESUME_EVENT_CONTENT_CAP),
91
- }));
92
- }
93
- }
94
- catch (err) {
95
- log.warn(`hippo compact-resume: trail skipped: ${errorMessage(err)}`);
96
- }
97
77
  // Printed in one write so the ledger books exactly the text the model is handed.
98
- const text = compactResumeText(snapshot, events);
99
78
  console.log(text);
100
79
  rec?.delivered({ state: 'sent', emittedText: `${text}\n` });
101
80
  bookLedgerTurn(hippoRoot, {
@@ -123,27 +102,24 @@ export async function handleSessionEnd({ hippoRoot, tenantId, flags }) {
123
102
  const root = payloadCwdRoot(hippoRoot, stdinText, runtime);
124
103
  const input = stop ?? sessionEndInput(stdinText, raw.timedOut, runtime);
125
104
  // 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;
105
+ const rec = !turn && input !== null && !input.manual
106
+ ? startDeliveryRecorder(cliApiContext(hookStoreRoot(root), tenantId), { stdinText, runtime, eventType: 'session-end', envSessionId: hostSessionId() })
107
+ : null;
127
108
  const sessionId = input?.sessionId ?? null;
128
109
  // Resolved here because only this process saw the payload; the worker captures just the path it is handed.
129
110
  // 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.
130
111
  const named = input?.transcriptPath ?? null;
131
112
  const transcriptPath = (named !== null && fs.existsSync(named) ? named : null)
132
113
  ?? (runtime === 'copilot' && sessionId ? copilotTranscriptFor(sessionId) : null);
114
+ const worker = { logFile, transcriptPath, sessionId, turn };
133
115
  try {
134
- spawnSessionEndWorker(sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn));
116
+ spawnSessionEndWorker(sessionEndWorkerArgs(worker));
135
117
  }
136
118
  catch (err) {
137
119
  log.debug(`session-end: the worker did not spawn, running inline: ${errorMessage(err)}`);
138
120
  // Inline is the last resort, handed what the child's argv would have carried.
139
- if (logFile)
140
- flags['log-file'] = logFile;
141
- if (transcriptPath)
142
- flags['transcript'] = transcriptPath;
143
- if (sessionId)
144
- flags['session-id'] = sessionId;
145
121
  try {
146
- await cmdSessionEndWorker(root, tenantId, flags);
122
+ await cmdSessionEndWorker(root, tenantId, inlineWorkerFlags(flags, worker));
147
123
  }
148
124
  finally {
149
125
  await runHookWithStores(() => flushDeliveryRecorder(rec));
@@ -161,7 +137,8 @@ function sessionEndInput(stdinText, timedOut, runtime) {
161
137
  log.debug(`session-end: ${receipt.reason}`);
162
138
  return null;
163
139
  }
164
- function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
140
+ function sessionEndWorkerArgs(o) {
141
+ const { logFile, transcriptPath, sessionId, turn } = o;
165
142
  const workerArgs = [process.argv[1], '__session-end-worker'];
166
143
  if (logFile)
167
144
  workerArgs.push('--log-file', logFile);
@@ -173,6 +150,26 @@ function sessionEndWorkerArgs(logFile, transcriptPath, sessionId, turn) {
173
150
  workerArgs.push('--turn');
174
151
  return workerArgs;
175
152
  }
153
+ /** The flags the detached worker would parse from its argv, so the inline run sees what the child would have; the hook's own flags fill the gaps. */
154
+ function inlineWorkerFlags(flags, w) {
155
+ const out = {};
156
+ const keep = (name, value) => {
157
+ if (value)
158
+ out[name] = value;
159
+ };
160
+ keep('log-file', w.logFile ?? flags['log-file']);
161
+ keep('transcript', w.transcriptPath ?? flags['transcript']);
162
+ keep('session-id', w.sessionId ?? flags['session-id']);
163
+ if (flagIsTrue(flags, 'turn'))
164
+ out['turn'] = true;
165
+ if (flagIsTrue(flags, 'dry-run'))
166
+ out['dry-run'] = true;
167
+ if (flagIsTrue(flags, 'no-learn'))
168
+ out['no-learn'] = true;
169
+ if (flagIsTrue(flags, 'no-share'))
170
+ out['no-share'] = true;
171
+ return out;
172
+ }
176
173
  function spawnSessionEndWorker(workerArgs) {
177
174
  const child = spawn(process.execPath, workerArgs, {
178
175
  detached: true,
@@ -195,64 +192,38 @@ async function cmdSessionEndWorker(hippoRoot, tenantId, flags) {
195
192
  export function handleSessionEndWorker({ hippoRoot, tenantId, flags }) {
196
193
  return cmdSessionEndWorker(hippoRoot, tenantId, flags);
197
194
  }
198
- async function sessionEndWork(hippoRoot, tenantId, flags, mode) {
195
+ function sessionEndWork(hippoRoot, tenantId, flags, mode) {
199
196
  const transcriptPath = stringFlag(flags, 'transcript');
200
- const closeLogFile = stringFlag(flags, 'log-file') ?? null;
201
- const closeSessionId = stringFlag(flags, 'session-id') ?? null;
202
- const rereadLog = await bookSessionRereads(hippoRoot, tenantId, transcriptPath, closeSessionId)
203
- .catch((err) => [`re-read count failed: ${errorMessage(err)}`]);
204
- // Sleep starts the log file afresh, so the lines go in after it; on exit too, in case sleep exits the process.
205
- const flushRereadLog = () => { for (const line of rereadLog.splice(0))
206
- appendSessionEndCloseLog(closeLogFile, line); };
207
- process.once('exit', flushRereadLog);
208
- // Like the other hooks: project store, else global; a folder with neither must not get one made.
209
- const store = hookStoreRoot(hippoRoot);
210
- if (!isInitialized(store)) {
211
- appendSessionEndCloseLog(closeLogFile, 'skip: no hippo store for this folder or globally', { startFresh: true });
212
- flushRereadLog();
213
- return;
214
- }
215
- if (mode === 'turn' && closeSessionId)
216
- await sleepIfDue(hippoRoot, tenantId, flags, closeLogFile, transcriptPath, closeSessionId);
217
- else
218
- await sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath);
219
- flushRereadLog();
220
- const digestLog = (message) => appendSessionEndCloseLog(closeLogFile, message);
221
- const scan = transcriptPath ? readSessionScan(transcriptPath, digestLog) : null;
222
- const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
223
- if (mode === 'turn')
224
- captureNewTurns(transcriptPath, closeSessionId, scan, capture, digestLog);
225
- else
226
- capture(scan?.turns);
227
- recordSessionDigest(hippoRoot, scan, {
228
- key: closeSessionId || path.basename(transcriptPath ?? '', '.jsonl'),
197
+ const logFile = stringFlag(flags, 'log-file') ?? null;
198
+ const sessionId = stringFlag(flags, 'session-id') ?? null;
199
+ return runSessionEnd({
200
+ mode,
201
+ hippoRoot,
229
202
  tenantId,
230
- log: digestLog,
203
+ sessionId,
204
+ transcriptPath,
205
+ contextFor: (root) => cliApiContext(root, tenantId),
206
+ storeRoot: () => hookStoreRoot(hippoRoot),
207
+ log: (line, opts) => appendSessionEndCloseLog(logFile, line, opts),
208
+ sleep: () => (mode === 'turn' && sessionId
209
+ ? sleepIfDue(hippoRoot, tenantId, flags, logFile, transcriptPath, sessionId)
210
+ : sleepProjectStore(hippoRoot, tenantId, flags, logFile, transcriptPath)),
211
+ readScan: (log) => (transcriptPath ? readSessionScan(transcriptPath, log) : null),
212
+ capture: (store, scan) => {
213
+ const capture = (turns) => captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath, turns);
214
+ if (mode === 'turn')
215
+ captureNewTurns(transcriptPath, sessionId, scan, capture, (line) => appendSessionEndCloseLog(logFile, line));
216
+ else
217
+ capture(scan?.turns);
218
+ },
219
+ digest: (scan, log) => recordSessionDigest(hippoRoot, scan, {
220
+ key: sessionId || path.basename(transcriptPath ?? '', '.jsonl'),
221
+ tenantId,
222
+ log,
223
+ }),
224
+ workingState: (log) => (transcriptPath ? transcriptWorkingState(transcriptPath, log) : null),
225
+ evidence: () => collectHandoffEvidence(process.cwd(), 'unknown'),
231
226
  });
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.
234
- if (closeSessionId)
235
- writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, mode === 'turn');
236
- if (mode === 'turn') {
237
- // The chat goes on after a reply, so its snapshot stays for the next compaction to restore.
238
- appendSessionEndCloseLog(closeLogFile, 'skip snapshot close: turn mode');
239
- return;
240
- }
241
- closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile);
242
- }
243
- function closeEndedSessionSnapshot(store, tenantId, closeSessionId, closeLogFile) {
244
- try {
245
- if (closeSessionId) {
246
- const closed = closeTaskSnapshotsForSession(store, tenantId, closeSessionId);
247
- appendSessionEndCloseLog(closeLogFile, `closed ${closed} active snapshot(s) for session ${closeSessionId}`);
248
- }
249
- else {
250
- appendSessionEndCloseLog(closeLogFile, 'skip: no session_id in SessionEnd payload, active snapshot left untouched');
251
- }
252
- }
253
- catch (err) {
254
- appendSessionEndCloseLog(closeLogFile, `snapshot close failed: ${errorMessage(err)}`);
255
- }
256
227
  }
257
228
  async function sleepProjectStore(hippoRoot, tenantId, flags, closeLogFile, transcriptPath) {
258
229
  // Sleeping the global store from here would learn this folder's git commits into it; it has its own daily sleep.
@@ -330,53 +301,6 @@ function captureEndedSession(hippoRoot, tenantId, store, flags, transcriptPath,
330
301
  return false;
331
302
  }
332
303
  }
333
- function writeEndHandoff(store, tenantId, closeSessionId, transcriptPath, closeLogFile, inPlace = false) {
334
- try {
335
- const ownSnapshot = loadActiveTaskSnapshot(store, tenantId)?.session_id === closeSessionId;
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.
337
- const derived = transcriptPath
338
- ? transcriptWorkingState(transcriptPath, (message) => appendSessionEndCloseLog(closeLogFile, message))
339
- : null;
340
- if (!ownSnapshot && !derived) {
341
- appendSessionEndCloseLog(closeLogFile, 'skip: no snapshot or transcript for session');
342
- }
343
- else {
344
- const evidence = collectHandoffEvidence(process.cwd(), 'unknown');
345
- const handoff = writeSessionEndHandoff(store, tenantId, closeSessionId, evidence, derived, undefined, { inPlace });
346
- appendSessionEndCloseLog(closeLogFile, handoff ? `wrote handoff for session ${closeSessionId}` : `skip: kept the existing handoff for session ${closeSessionId}`);
347
- }
348
- }
349
- catch (err) {
350
- // SAFETY: catch clauses bind unknown, but Node/V8 always throws an Error here.
351
- appendSessionEndCloseLog(closeLogFile, `handoff write failed: ${errorMessage(err)}`);
352
- }
353
- }
354
- /** Books the ending session's re-reads in each store its ledger rows can land in (project and global); returns the log lines. */
355
- async function bookSessionRereads(hippoRoot, tenantId, transcriptPath, sessionId) {
356
- if (!transcriptPath || !sessionId)
357
- return [];
358
- let read;
359
- try {
360
- read = await readApiCalls(transcriptPath);
361
- }
362
- catch (err) {
363
- return [`skip re-read count: cannot read the transcript: ${errorMessage(err)}`];
364
- }
365
- const roots = new Set([hippoRoot, getGlobalRoot()].filter((root) => isInitialized(root)).map((root) => path.resolve(root)));
366
- const lines = [];
367
- let tokens = 0;
368
- for (const root of roots) {
369
- try {
370
- tokens += recordRereads(root, tenantId, sessionId, read.calls);
371
- }
372
- catch (err) {
373
- lines.push(`re-read count failed: ${errorMessage(err)}`);
374
- }
375
- }
376
- const skipped = read.malformed > 0 ? `, ${read.malformed} unparsable transcript lines skipped` : '';
377
- lines.push(`re-read ${tokens} tokens over ${read.calls.length} model calls for session ${sessionId}${skipped}`);
378
- return lines;
379
- }
380
304
  function loadCodexWrapperMetadata() {
381
305
  const { metadataPath } = resolveCodexWrapperPaths();
382
306
  if (!fs.existsSync(metadataPath)) {
@@ -385,20 +309,6 @@ function loadCodexWrapperMetadata() {
385
309
  // SAFETY: the file is the one installCodexWrapper wrote; handleCodexRun reads only logFile and realCodexPath from it.
386
310
  return JSON.parse(fs.readFileSync(metadataPath, 'utf8'));
387
311
  }
388
- /** Quotes one cmd.exe argument; each `%` leaves the quotes as `^%`, so no %NAME% pair can expand. */
389
- export function quoteCmdArg(arg) {
390
- if (arg.length === 0)
391
- return '""';
392
- if (!/[ \t"&()^<>|%!]/.test(arg))
393
- return arg;
394
- return `"${arg.replace(/"/g, '""').replace(/%/g, '"^%"')}"`;
395
- }
396
- /** cmd.exe arguments that run a .cmd or .bat shim with every forwarded argument delivered verbatim. */
397
- export function cmdShimArgs(shimPath, forwardArgs) {
398
- const command = `"${shimPath}"${forwardArgs.length > 0 ? ` ${forwardArgs.map(quoteCmdArg).join(' ')}` : ''}`;
399
- // The line is already quoted for cmd.exe, so Node must not quote it again; /s strips the outer pair.
400
- return ['/d', '/v:off', '/s', '/c', `"${command}"`];
401
- }
402
312
  function spawnRealCodex(realCodexPath, forwardArgs, cwd) {
403
313
  const ext = path.extname(realCodexPath).toLowerCase();
404
314
  if (process.platform === 'win32' && ext === '.ps1') {
@@ -565,15 +475,17 @@ function captureCodexTranscript(hippoRoot, tenantId, store, flags, logFile) {
565
475
  reportSessionEndFailure(logFile ?? null, 'codex session-end: transcript scan or digest', err);
566
476
  }
567
477
  }
568
- export async function handlePreCompact({ hippoRoot, flags }) {
478
+ export async function handlePreCompact({ hippoRoot, tenantId, flags }) {
569
479
  // Bounded wait, not a TTY guard: an idle non-TTY pipe must not hang.
570
480
  const { text: stdinText, timedOut: stdinTimedOut } = await readHookStdin();
571
481
  const runtime = hookRuntime(flags);
572
482
  const root = payloadCwdRoot(hippoRoot, stdinText, runtime);
573
483
  await runHookWithStores(async () => {
574
484
  // Started before any store wait, so two fires of one hook carry timestamps close enough to match as duplicates.
575
- const rec = startDeliveryRecorder(hookStoreRoot(root), stdinText, runtime, 'pre-compact');
576
- resetHookInjection(root, stdinText, null);
485
+ const rec = startDeliveryRecorder(cliApiContext(hookStoreRoot(root), tenantId), {
486
+ stdinText, runtime, eventType: 'pre-compact', envSessionId: hostSessionId(),
487
+ });
488
+ resetHookInjection(root, tenantId, stdinText, null);
577
489
  await cmdPreCompact(hookStoreRoot(root), {
578
490
  stdinText,
579
491
  stdinTimedOut,
@@ -587,7 +499,8 @@ export async function handlePreCompact({ hippoRoot, flags }) {
587
499
  });
588
500
  }
589
501
  export async function handlePostCompact({ hippoRoot, flags }) {
590
- // PostCompact hook: saves the compaction summary and its memories, then prints one plain line, because Claude Code shows this hook's stdout as-is. Always exits 0.
502
+ // PostCompact hook: saves the compaction summary and its memories, then prints one plain line, because Claude Code shows this hook's
503
+ // stdout as-is. Always exits 0.
591
504
  const { text, timedOut } = await readHookStdin();
592
505
  const logFlag = flags['log-file'];
593
506
  const store = hookStoreRoot(hippoRoot);
@@ -618,7 +531,15 @@ export async function handleCaptureError({ hippoRoot, tenantId, flags }) {
618
531
  if (isInitialized(root) && payload) {
619
532
  // SAFETY: JSON.parse returns a JSON value by definition.
620
533
  const failure = JSON.parse(payload);
621
- await runHookWithStores(() => captureToolFailure(root, tenantId, failure));
534
+ const rec = startToolFailureRecorder(cliApiContext(root, tenantId), { stdinText: text, runtime: hookRuntime(flags), envSessionId: hostSessionId() });
535
+ await runHookWithStores(() => {
536
+ try {
537
+ return captureToolFailure(root, tenantId, failure, (id) => rec?.logged(id));
538
+ }
539
+ finally {
540
+ flushDeliveryRecorder(rec);
541
+ }
542
+ });
622
543
  }
623
544
  }
624
545
  catch (err) {
@@ -629,7 +550,7 @@ export async function handleCaptureError({ hippoRoot, tenantId, flags }) {
629
550
  export async function handleCompactResume({ hippoRoot, tenantId }) {
630
551
  const { text: stdinText, timedOut: stdinTimedOut } = await readHookStdin();
631
552
  await runHookWithStores(() => {
632
- resetHookInjection(hippoRoot, stdinText, 'compact');
553
+ resetHookInjection(hippoRoot, tenantId, stdinText, 'compact');
633
554
  cmdCompactResume(hookStoreRoot(hippoRoot), tenantId, stdinText, stdinTimedOut);
634
555
  });
635
556
  }
@@ -1,5 +1,5 @@
1
1
  import { type CommandContext } from './flag-values.js';
2
2
  export declare function handleHook({ args }: CommandContext): void;
3
3
  export declare function handleSetup({ flags }: CommandContext): void;
4
- export declare function handleDailyRunner(_ctx: CommandContext): void;
4
+ export declare function handleDailyRunner({ tenantId }: CommandContext): Promise<void>;
5
5
  //# sourceMappingURL=setup.d.ts.map
package/dist/cli/setup.js CHANGED
@@ -1,4 +1,5 @@
1
1
  // `hippo hook`, `hippo setup` and `hippo daily-runner`: install and run the agent and machine integrations.
2
+ import { MINUTE_MS } from '../util/time.js';
2
3
  import * as path from 'path';
3
4
  import * as fs from 'fs';
4
5
  import { execFileSync } from 'child_process';
@@ -7,7 +8,7 @@ import { detectInstalledTools } from '../hooks/shared.js';
7
8
  import { ensureCodexWrapperInstalled, installCodexWrapper, detectRealCodexPath, uninstallCodexWrapper, } from '../hooks/codex-wrapper.js';
8
9
  import { installOpencodePlugin, uninstallOpencodePlugin, resolveOpencodePluginPath } from '../hooks/opencode.js';
9
10
  import { COPILOT_CLI_MCP, VSCODE_MCP, copilotMcpSnippet, copilotPaths, installCopilot, isCopilotCliPresent, isMcpFailure, uninstallCopilot, } from '../hooks/copilot.js';
10
- import { isInitialized } from '../store/open.js';
11
+ import { isInitialized } from '../core/project-identity.js';
11
12
  import { currentMachine, importUserMemories } from '../agent-memories/sync.js';
12
13
  import { getGlobalRoot } from '../sharing/global-store.js';
13
14
  import { listRegisteredWorkspaces, runDailyMaintenance } from './scheduler.js';
@@ -188,7 +189,8 @@ const VSCODE_INSTRUCTIONS_REMOVE_LINES = {
188
189
  absent: () => '',
189
190
  kept: (file) => `Left ${file}: it is not the text hippo wrote. Delete it by hand if no agent needs it.`,
190
191
  };
191
- const VSCODE_HOOKS_LINE = 'VS Code: hooks need VS Code 1.109.3 or later with chat.useHooks on (the default); older versions get the MCP server and the instructions file only.';
192
+ const VSCODE_HOOKS_LINE = 'VS Code: hooks need VS Code 1.109.3 or later with chat.useHooks on (the default); older versions get the MCP server and the ' +
193
+ 'instructions file only.';
192
194
  function mcpInstallLine(file, mcp, host) {
193
195
  return isMcpFailure(mcp) ? mcpFailureLine(file, mcp, addByHand(host)) : MCP_MERGE_LINES[mcp](file, host);
194
196
  }
@@ -198,7 +200,8 @@ function printVscodeInstall(result, indent) {
198
200
  console.log(`${indent}${VSCODE_INSTRUCTIONS_INSTALL_LINES[result.instructions](paths.instructions)}`);
199
201
  if (paths.profiles.length > 0) {
200
202
  const names = paths.profiles.map((dir) => path.basename(dir)).join(', ');
201
- console.log(`${indent}Found VS Code profiles (${names}) under ${path.join(paths.userDir, 'profiles')}: hippo set up the default profile only; copy the "hippo" server and prompts/hippo.instructions.md into a profile to use hippo there.`);
203
+ console.log(`${indent}Found VS Code profiles (${names}) under ${path.join(paths.userDir, 'profiles')}: ` +
204
+ 'hippo set up the default profile only; copy the "hippo" server and prompts/hippo.instructions.md into a profile to use hippo there.');
202
205
  }
203
206
  }
204
207
  function printCopilotInstall(result, indent) {
@@ -206,7 +209,8 @@ function printCopilotInstall(result, indent) {
206
209
  const hooks = result.hooks ? `Installed hippo's Copilot hooks (${copilotHookEvents().join(', ')}) ->` : "hippo's Copilot hooks are already in";
207
210
  console.log(`${indent}${hooks} ${paths.hooks}`);
208
211
  if (result.mcp === null || result.instructions === null) {
209
- console.log(`${indent}No Copilot CLI files in ${path.dirname(paths.mcpConfig)}, so hippo skipped mcp-config.json and copilot-instructions.md, which only the Copilot CLI reads`);
212
+ console.log(`${indent}No Copilot CLI files in ${path.dirname(paths.mcpConfig)}, ` +
213
+ 'so hippo skipped mcp-config.json and copilot-instructions.md, which only the Copilot CLI reads');
210
214
  }
211
215
  else {
212
216
  console.log(`${indent}${mcpInstallLine(paths.mcpConfig, result.mcp, COPILOT_CLI_MCP)}`);
@@ -226,8 +230,10 @@ function mcpRemoveLines(file, mcp) {
226
230
  return [`Removed the "hippo" MCP server from ${file}`];
227
231
  if (mcp === 'user-owned')
228
232
  return [`Left the "hippo" MCP server in ${file}: hippo did not write it`];
229
- if (mcp === 'unreadable')
230
- return [`WARNING: ${file} has comments or is not a JSON object hippo can edit, so it was left unchanged; remove the "hippo" server by hand if hippo added it`];
233
+ if (mcp === 'unreadable') {
234
+ return [`WARNING: ${file} has comments or is not a JSON object hippo can edit, so it was left unchanged; ` +
235
+ 'remove the "hippo" server by hand if hippo added it'];
236
+ }
231
237
  return [];
232
238
  }
233
239
  function printCopilotUninstall(result) {
@@ -473,21 +479,21 @@ function setupPluginTool(tool, dryRun) {
473
479
  }
474
480
  }
475
481
  // Three times the 10 minutes POST /v1/sleep allows a consolidation, so a slow real sleep fits and a hung child cannot stall every later workspace.
476
- const DAILY_STEP_TIMEOUT_MS = 30 * 60_000;
482
+ const DAILY_STEP_TIMEOUT_MS = 30 * MINUTE_MS;
477
483
  /** Why a child step failed; a child killed at the deadline says so, since its own message is only the spawn error code. */
478
484
  function dailyStepFailure(err, timeoutMs) {
479
485
  if (err instanceof Error && 'code' in err && err.code === 'ETIMEDOUT')
480
486
  return `timed out after ${timeoutMs} ms and was stopped`;
481
487
  return errorMessage(err);
482
488
  }
483
- export function handleDailyRunner(_ctx) {
489
+ export async function handleDailyRunner({ tenantId }) {
484
490
  const globalRoot = getGlobalRoot();
485
491
  // No workspace sleep ever opens the global store, yet hooks in folders without a store compact into it.
486
492
  if (isInitialized(globalRoot)) {
487
493
  const finished = replayCompactionsAt(globalRoot, (message) => log.warn(`compaction replay: ${message}`));
488
494
  if (finished > 0)
489
495
  console.log(`Finished saving ${finished} compaction${finished === 1 ? '' : 's'} left over in the global store.`);
490
- repairQualityOnceAt(globalRoot);
496
+ await repairQualityOnceAt(globalRoot, tenantId);
491
497
  }
492
498
  printAgentImport(importUserMemories(globalRoot, { machine: currentMachine() }), '');
493
499
  const workspaces = listRegisteredWorkspaces(globalRoot);
@@ -516,7 +522,8 @@ export function handleDailyRunner(_ctx) {
516
522
  log.error(`daily-runner failed in ${cwd} during \`${action}\`: ${dailyStepFailure(err, timeout)}`, { workspace: cwd, ...errorFields(err) });
517
523
  }
518
524
  });
519
- console.log(`Daily maintenance complete: ${processed} workspace${processed === 1 ? '' : 's'} processed, ${failed} command failure${failed === 1 ? '' : 's'}.`);
525
+ console.log(`Daily maintenance complete: ${processed} workspace${processed === 1 ? '' : 's'} processed, ` +
526
+ `${failed} command failure${failed === 1 ? '' : 's'}.`);
520
527
  // The scheduler that runs this only sees the exit code, so a failed workspace must not read as a clean run.
521
528
  if (failed > 0)
522
529
  process.exitCode = 1;
@@ -1,13 +1,9 @@
1
1
  import { type ChurnStaleResult } from '../learn/invalidation.js';
2
- import { type AuditOp } from '../store/audit.js';
3
2
  import { type ServerInfo } from '../server/server-detect.js';
4
- import type { JsonObject } from '../store/working-memory.js';
5
3
  import type { CliFlags } from './flag-values.js';
6
- /** Emit an audit event on its own short-lived connection to `hippoRoot`'s db; swallows all errors, since audit must never crash a CLI command. */
7
- export declare function emitCliAudit(hippoRoot: string, op: AuditOp, targetId?: string, metadata?: JsonObject): void;
8
4
  export declare function requireInit(hippoRoot: string): void;
9
5
  /** Runs detectChurnStale against every store this repo's memories can live in. */
10
- export declare function runChurnStaleForRepo(hippoRoot: string, dryRun: boolean): {
6
+ export declare function runChurnStaleForRepo(hippoRoot: string, tenantId: string, dryRun: boolean): {
11
7
  root: string;
12
8
  result: ChurnStaleResult;
13
9
  }[];
@@ -21,7 +17,7 @@ interface LearnFromRepoResult {
21
17
  skipped: number;
22
18
  lowInfo: number;
23
19
  }
24
- export declare function learnFromRepo(hippoRoot: string, repoPath: string, days: number, label?: string): LearnFromRepoResult;
20
+ export declare function learnFromRepo(hippoRoot: string, tenantId: string, repoPath: string, days: number, label?: string): Promise<LearnFromRepoResult>;
25
21
  export declare function resolveAuthRoot(hippoRoot: string, flags: CliFlags): string;
26
22
  export {};
27
23
  //# sourceMappingURL=shared.d.ts.map
@@ -1,36 +1,17 @@
1
- // Store and server helpers the CLI verbs share: audit events, init checks, server routing, git learning and the auth root.
1
+ // Store and server helpers the CLI verbs share: init checks, server routing, git learning and the auth root.
2
2
  // This module must never import cli.ts.
3
3
  import { envApiKey, envRequireServer } from '../util/env.js';
4
4
  import { execFileSync } from 'child_process';
5
5
  import { isSharedStore } from '../core/config.js';
6
- import { isInitialized } from '../store/open.js';
7
6
  import { detectChurnStale } from '../learn/invalidation.js';
8
- import { resolveProjectIdentity } from '../core/project-identity.js';
7
+ import { resolveProjectIdentity, isInitialized } from '../core/project-identity.js';
9
8
  import { getGlobalRoot, initGlobal } from '../sharing/global-store.js';
10
- import { reportAuditWriteFailure } from '../store/audit.js';
11
- import { sqliteSyncStore } from '../store/sqlite/store.js';
12
9
  import * as client from './client.js';
13
10
  import { detectServer, removePidfileIfOwned } from '../server/server-detect.js';
14
- import { resolveTenantId } from '../store/tenant.js';
15
- import { adminActor, learn, CLI_LEARN } from '../api/index.js';
11
+ import { learn, CLI_LEARN } from '../api/index.js';
12
+ import { cliApiContext } from './api-context.js';
16
13
  import { errorMessage, log } from '../util/log.js';
17
14
  import { printError } from './output.js';
18
- /** Emit an audit event on its own short-lived connection to `hippoRoot`'s db; swallows all errors, since audit must never crash a CLI command. */
19
- export function emitCliAudit(hippoRoot, op, targetId, metadata) {
20
- try {
21
- sqliteSyncStore(hippoRoot).appendAuditEvents([{
22
- tenantId: resolveTenantId({}),
23
- actor: 'cli',
24
- op,
25
- targetId,
26
- metadata,
27
- }]);
28
- }
29
- catch (error) {
30
- // Best effort: the command already did its work.
31
- reportAuditWriteFailure(op, String(error), targetId);
32
- }
33
- }
34
15
  export function requireInit(hippoRoot) {
35
16
  if (!isInitialized(hippoRoot)) {
36
17
  printError(`No hippo store at ${hippoRoot} (searched ${process.cwd()} and its parents up to your home directory). Run \`hippo init\` first.`);
@@ -38,12 +19,11 @@ export function requireInit(hippoRoot) {
38
19
  }
39
20
  }
40
21
  /** Runs detectChurnStale against every store this repo's memories can live in. */
41
- export function runChurnStaleForRepo(hippoRoot, dryRun) {
22
+ export function runChurnStaleForRepo(hippoRoot, tenantId, dryRun) {
42
23
  const repoRoot = execFileSync('git', ['rev-parse', '--show-toplevel'], { cwd: process.cwd(), encoding: 'utf8', timeout: 10_000, windowsHide: true }).trim();
43
24
  const { name: projectName, legacyName } = resolveProjectIdentity(process.cwd());
44
25
  const globalRoot = getGlobalRoot();
45
26
  const roots = globalRoot !== hippoRoot && isInitialized(globalRoot) ? [hippoRoot, globalRoot] : [hippoRoot];
46
- const tenantId = resolveTenantId({});
47
27
  return roots.map((root) => {
48
28
  // One store failing must not abort sleep's later phases or skip the other store.
49
29
  try {
@@ -89,7 +69,8 @@ export async function runViaServerIfAvailable(hippoRoot, httpFn) {
89
69
  if (failure === 'delivery-unknown') {
90
70
  // Every caller is a non-idempotent write, so replaying on the direct path would store a row the server may already have committed;
91
71
  // leave the pidfile alone: the next command's connect-phase failure heals it.
92
- printError(`hippo: the connection to ${info.url} dropped or timed out mid-request, so the write may already have been applied. Not retrying locally. Check with \`hippo recall\` before running this again.`);
72
+ printError(`hippo: the connection to ${info.url} dropped or timed out mid-request, so the write may already have been applied. ` +
73
+ 'Not retrying locally. Check with `hippo recall` before running this again.');
93
74
  process.exit(1);
94
75
  }
95
76
  throw err;
@@ -102,10 +83,9 @@ export function skipLearnOnSharedStore(hippoRoot) {
102
83
  console.log("Shared store: skipped learning from this account's git commits and coding agents' own memories.");
103
84
  return true;
104
85
  }
105
- export function learnFromRepo(hippoRoot, repoPath, days, label) {
86
+ export async function learnFromRepo(hippoRoot, tenantId, repoPath, days, label) {
106
87
  const prefix = label ? `[${label}] ` : '';
107
- const ctx = { hippoRoot, tenantId: resolveTenantId({}), actor: adminActor('cli') };
108
- const result = learn(ctx, { repoPath, days, profile: CLI_LEARN });
88
+ const result = await learn(cliApiContext(hippoRoot, tenantId), { repoPath, days, profile: CLI_LEARN });
109
89
  if (result.status === 'not-a-repo') {
110
90
  console.log(`${prefix}No git history found (or not a git repository).`);
111
91
  return { added: 0, skipped: 0, lowInfo: 0 };
@@ -2,10 +2,12 @@
2
2
  import { renderAmbientSummary } from '../core/ambient.js';
3
3
  /** The lines `hippo sleep` prints for an api.sleep result; pure, so the snapshot tests read them without a console spy. */
4
4
  export function sleepResultLines(result) {
5
- return [...sleepCountLines(result), ...(result.dryRun ? ['\n(dry run - nothing written)'] : []), ...sleepDedupeAndAuditLines(result), ...sleepShareAndGraphLines(result)];
5
+ return [...sleepCountLines(result), ...(result.dryRun ? ['\n(dry run - nothing ' +
6
+ 'written)'] : []), ...sleepDedupeAndAuditLines(result), ...sleepShareAndGraphLines(result)];
6
7
  }
7
8
  function sleepCountLines(result) {
8
- const lines = [`Running consolidation${result.dryRun ? ' (dry run)' : ''}...`, `\nResults:`, ` Active memories: ${result.active}`, ` Removed (decayed): ${result.removed}`];
9
+ const lines = [`Running consolidation${result.dryRun ? ' (dry ' +
10
+ 'run)' : ''}...`, `\nResults:`, ` Active memories: ${result.active}`, ` Removed (decayed): ${result.removed}`];
9
11
  // Only when dormant.enabled moved something, so every other render stays byte-identical.
10
12
  if (result.dormant !== undefined && result.dormant > 0) {
11
13
  lines.push(` Kept dormant: ${result.dormant} (hippo dormant to list)`);
@@ -29,7 +31,8 @@ function sleepDedupeAndAuditLines(result) {
29
31
  parts.push(`${epiDups} duplicate episodic lessons`);
30
32
  if (crossDups > 0)
31
33
  parts.push(`${crossDups} cross-layer duplicates`);
32
- lines.push(`\n${result.dryRun ? 'Would dedupe' : 'Deduped'} ${removed} duplicates (${parts.join(', ')}). ${result.dryRun ? 'Would keep' : 'Kept'} stronger copies.`);
34
+ lines.push(`\n${result.dryRun ? 'Would ' +
35
+ 'dedupe' : 'Deduped'} ${removed} duplicates (${parts.join(', ')}). ${result.dryRun ? 'Would keep' : 'Kept'} stronger copies.`);
33
36
  }
34
37
  if (result.audit) {
35
38
  if (result.audit.errorsRemoved > 0) {