hippo-memory 1.71.0 → 1.72.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 (555) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-memories/apply.d.ts +0 -11
  3. package/dist/agent-memories/apply.js +6 -21
  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 +1 -1
  12. package/dist/api/audit.d.ts +29 -1
  13. package/dist/api/audit.js +44 -5
  14. package/dist/api/auth.d.ts +7 -4
  15. package/dist/api/auth.js +12 -8
  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-render.js +4 -3
  24. package/dist/api/context-select.js +9 -11
  25. package/dist/api/context.js +17 -8
  26. package/dist/api/continuity.d.ts +47 -0
  27. package/dist/api/continuity.js +66 -0
  28. package/dist/api/dormant.js +4 -2
  29. package/dist/api/drill-down.js +1 -1
  30. package/dist/api/embeddings.d.ts +17 -0
  31. package/dist/api/embeddings.js +28 -0
  32. package/dist/api/error-reply.d.ts +8 -0
  33. package/dist/api/error-reply.js +21 -0
  34. package/dist/api/forget.d.ts +6 -2
  35. package/dist/api/forget.js +18 -7
  36. package/dist/api/goals.d.ts +1 -1
  37. package/dist/api/goals.js +5 -9
  38. package/dist/api/index.d.ts +4 -2
  39. package/dist/api/index.js +4 -2
  40. package/dist/api/instruction-detect.js +5 -1
  41. package/dist/api/learn.d.ts +4 -0
  42. package/dist/api/learn.js +53 -27
  43. package/dist/api/ledger-db.d.ts +2 -6
  44. package/dist/api/ledger-db.js +4 -36
  45. package/dist/api/memories.d.ts +19 -1
  46. package/dist/api/memories.js +39 -0
  47. package/dist/api/objects.d.ts +1 -1
  48. package/dist/api/outcome.js +1 -1
  49. package/dist/api/pilot-arm.d.ts +1 -11
  50. package/dist/api/pilot-arm.js +5 -45
  51. package/dist/api/predictions.d.ts +3 -1
  52. package/dist/api/predictions.js +6 -0
  53. package/dist/api/projects.d.ts +21 -0
  54. package/dist/api/projects.js +24 -0
  55. package/dist/api/promote.js +1 -1
  56. package/dist/api/prompt-hook.d.ts +15 -2
  57. package/dist/api/prompt-hook.js +44 -4
  58. package/dist/api/recall-cli.d.ts +3 -0
  59. package/dist/api/recall-cli.js +13 -4
  60. package/dist/api/recall-core.js +3 -3
  61. package/dist/api/recall-pipeline.js +6 -7
  62. package/dist/api/recall-request.js +1 -1
  63. package/dist/api/recall.d.ts +0 -3
  64. package/dist/api/recall.js +19 -44
  65. package/dist/api/remember-local.js +1 -1
  66. package/dist/api/remember.d.ts +2 -1
  67. package/dist/api/remember.js +3 -2
  68. package/dist/api/session-end.d.ts +22 -0
  69. package/dist/api/session-end.js +101 -0
  70. package/dist/api/sleep-run.d.ts +1 -1
  71. package/dist/api/sleep-run.js +13 -9
  72. package/dist/api/status.d.ts +24 -0
  73. package/dist/api/status.js +40 -0
  74. package/dist/api/store-init.d.ts +4 -0
  75. package/dist/api/store-init.js +9 -0
  76. package/dist/api/tokens.js +1 -1
  77. package/dist/api/types.d.ts +2 -0
  78. package/dist/api/types.js +6 -1
  79. package/dist/capture/caller-session.d.ts +0 -3
  80. package/dist/capture/caller-session.js +1 -12
  81. package/dist/capture/capture-error.d.ts +2 -2
  82. package/dist/capture/capture-error.js +23 -18
  83. package/dist/capture/codex-patch.js +3 -1
  84. package/dist/capture/command.js +36 -95
  85. package/dist/capture/compact.js +10 -5
  86. package/dist/capture/compaction-items-caller.js +11 -20
  87. package/dist/capture/compaction-record.d.ts +7 -93
  88. package/dist/capture/compaction-record.js +29 -426
  89. package/dist/capture/compaction-spool.d.ts +4 -2
  90. package/dist/capture/compaction-spool.js +20 -6
  91. package/dist/capture/copilot-transcript.d.ts +2 -1
  92. package/dist/capture/copilot-transcript.js +2 -1
  93. package/dist/capture/extract.d.ts +5 -2
  94. package/dist/capture/extract.js +4 -3
  95. package/dist/capture/failure-caller.d.ts +1 -1
  96. package/dist/capture/failure-caller.js +21 -16
  97. package/dist/capture/failure-reading.d.ts +2 -1
  98. package/dist/capture/failure-reading.js +7 -9
  99. package/dist/capture/pre-compact-caller.js +5 -4
  100. package/dist/capture/session-digest.js +4 -3
  101. package/dist/capture/session-end-caller.js +2 -1
  102. package/dist/capture/session-worker.js +3 -4
  103. package/dist/capture/transcript.d.ts +2 -1
  104. package/dist/capture/transcript.js +6 -3
  105. package/dist/capture/working-state.d.ts +4 -2
  106. package/dist/capture/working-state.js +4 -2
  107. package/dist/cli/audit-prune.d.ts +0 -25
  108. package/dist/cli/audit-prune.js +1 -27
  109. package/dist/cli/audit.js +13 -13
  110. package/dist/cli/auth.d.ts +1 -1
  111. package/dist/cli/auth.js +12 -13
  112. package/dist/cli/briefs.d.ts +1 -4
  113. package/dist/cli/briefs.js +37 -292
  114. package/dist/cli/card.js +41 -33
  115. package/dist/cli/client.d.ts +5 -0
  116. package/dist/cli/client.js +24 -8
  117. package/dist/cli/compact-resume-payload.js +1 -1
  118. package/dist/cli/context.d.ts +1 -1
  119. package/dist/cli/context.js +12 -12
  120. package/dist/cli/continuity.d.ts +1 -1
  121. package/dist/cli/continuity.js +36 -39
  122. package/dist/cli/curate.d.ts +1 -1
  123. package/dist/cli/curate.js +23 -27
  124. package/dist/cli/dag.d.ts +1 -1
  125. package/dist/cli/dag.js +23 -8
  126. package/dist/cli/decisions.d.ts +0 -2
  127. package/dist/cli/decisions.js +4 -281
  128. package/dist/cli/eval.d.ts +1 -1
  129. package/dist/cli/eval.js +12 -13
  130. package/dist/cli/explain.d.ts +1 -1
  131. package/dist/cli/explain.js +21 -25
  132. package/dist/cli/flag-values.js +16 -6
  133. package/dist/cli/flags.d.ts +0 -289
  134. package/dist/cli/flags.js +3 -138
  135. package/dist/cli/graph.d.ts +3 -0
  136. package/dist/cli/graph.js +83 -0
  137. package/dist/cli/hook-runtime.d.ts +3 -5
  138. package/dist/cli/hook-runtime.js +7 -34
  139. package/dist/cli/incidents.d.ts +3 -0
  140. package/dist/cli/incidents.js +112 -0
  141. package/dist/cli/init.d.ts +1 -1
  142. package/dist/cli/init.js +28 -19
  143. package/dist/cli/install-steps.d.ts +2 -1
  144. package/dist/cli/install-steps.js +11 -3
  145. package/dist/cli/last-sleep.js +1 -1
  146. package/dist/cli/lenient-id.d.ts +2 -0
  147. package/dist/cli/lenient-id.js +13 -0
  148. package/dist/cli/maintenance.d.ts +3 -3
  149. package/dist/cli/maintenance.js +29 -30
  150. package/dist/cli/notes.d.ts +2 -0
  151. package/dist/cli/notes.js +41 -0
  152. package/dist/cli/open-browser.d.ts +14 -0
  153. package/dist/cli/open-browser.js +26 -0
  154. package/dist/cli/playbooks.d.ts +3 -4
  155. package/dist/cli/playbooks.js +126 -290
  156. package/dist/cli/predictions.d.ts +3 -0
  157. package/dist/cli/predictions.js +175 -0
  158. package/dist/cli/print.js +2 -1
  159. package/dist/cli/projects.js +30 -22
  160. package/dist/cli/quality-repair-once.d.ts +1 -1
  161. package/dist/cli/quality-repair-once.js +6 -5
  162. package/dist/cli/recall.js +13 -7
  163. package/dist/cli/refine-llm.js +17 -17
  164. package/dist/cli/remember.js +12 -12
  165. package/dist/cli/scheduler.js +2 -1
  166. package/dist/cli/serve.js +3 -3
  167. package/dist/cli/session-hooks.d.ts +1 -1
  168. package/dist/cli/session-hooks.js +45 -115
  169. package/dist/cli/setup.d.ts +1 -1
  170. package/dist/cli/setup.js +17 -10
  171. package/dist/cli/shared.d.ts +2 -6
  172. package/dist/cli/shared.js +9 -29
  173. package/dist/cli/sleep-render.js +6 -3
  174. package/dist/cli/sleep.js +6 -37
  175. package/dist/cli/status.d.ts +3 -3
  176. package/dist/cli/status.js +32 -35
  177. package/dist/cli/transfer.d.ts +1 -1
  178. package/dist/cli/transfer.js +33 -31
  179. package/dist/cli/usage.d.ts +0 -79
  180. package/dist/cli/usage.js +1 -695
  181. package/dist/cli/verb-row.d.ts +32 -0
  182. package/dist/cli/verb-row.js +6 -0
  183. package/dist/cli/verbs/health.d.ts +27 -0
  184. package/dist/cli/verbs/health.js +232 -0
  185. package/dist/cli/verbs/memory.d.ts +16 -0
  186. package/dist/cli/verbs/memory.js +244 -0
  187. package/dist/cli/verbs/objects.d.ts +20 -0
  188. package/dist/cli/verbs/objects.js +254 -0
  189. package/dist/cli/verbs/sessions.d.ts +31 -0
  190. package/dist/cli/verbs/sessions.js +312 -0
  191. package/dist/cli/verbs.d.ts +81 -0
  192. package/dist/cli/verbs.js +7 -0
  193. package/dist/cli/versioned-verbs.d.ts +51 -0
  194. package/dist/cli/versioned-verbs.js +79 -0
  195. package/dist/cli.d.ts +1 -272
  196. package/dist/cli.js +23 -313
  197. package/dist/connectors/dlq.d.ts +39 -3
  198. package/dist/connectors/dlq.js +37 -3
  199. package/dist/connectors/github/backfill.js +12 -3
  200. package/dist/connectors/github/dlq.js +31 -73
  201. package/dist/connectors/github/ingest.d.ts +2 -6
  202. package/dist/connectors/github/ingest.js +3 -28
  203. package/dist/connectors/github/webhook.d.ts +2 -1
  204. package/dist/connectors/github/webhook.js +33 -2
  205. package/dist/connectors/ingest.d.ts +10 -0
  206. package/dist/connectors/ingest.js +28 -0
  207. package/dist/connectors/slack/dlq.js +49 -71
  208. package/dist/connectors/slack/ingest.d.ts +2 -6
  209. package/dist/connectors/slack/ingest.js +2 -27
  210. package/dist/connectors/slack/webhook.d.ts +2 -1
  211. package/dist/connectors/slack/webhook.js +2 -1
  212. package/dist/consolidate/conflicts.js +1 -1
  213. package/dist/consolidate/dag.js +15 -9
  214. package/dist/consolidate/dedupe.d.ts +7 -0
  215. package/dist/consolidate/dedupe.js +5 -3
  216. package/dist/consolidate/llm-passes.js +45 -19
  217. package/dist/consolidate/memory-value.js +2 -1
  218. package/dist/consolidate/merge.js +2 -2
  219. package/dist/consolidate/physics-pass.d.ts +6 -1
  220. package/dist/consolidate/physics-pass.js +26 -6
  221. package/dist/consolidate/replay.js +11 -4
  222. package/dist/consolidate/sleep.js +8 -5
  223. package/dist/consolidate/traces.js +3 -3
  224. package/dist/core/ablation.d.ts +10 -0
  225. package/dist/core/ablation.js +12 -0
  226. package/dist/{sharing/scope.d.ts → core/active-scope.d.ts} +1 -1
  227. package/dist/{sharing/scope.js → core/active-scope.js} +1 -1
  228. package/dist/core/ambient.d.ts +4 -0
  229. package/dist/core/ambient.js +39 -18
  230. package/dist/core/api-errors.d.ts +16 -0
  231. package/dist/core/api-errors.js +20 -0
  232. package/dist/core/card.js +3 -1
  233. package/dist/core/compaction-timing.d.ts +7 -0
  234. package/dist/core/compaction-timing.js +9 -0
  235. package/dist/core/config.d.ts +1 -1
  236. package/dist/core/config.js +7 -2
  237. package/dist/core/cosine.d.ts +3 -0
  238. package/dist/core/cosine.js +19 -0
  239. package/dist/{store → core}/markdown.d.ts +1 -1
  240. package/dist/{store → core}/markdown.js +2 -2
  241. package/dist/core/memory-audit.d.ts +17 -0
  242. package/dist/core/memory-audit.js +54 -0
  243. package/dist/core/memory.d.ts +10 -4
  244. package/dist/core/memory.js +25 -18
  245. package/dist/{consolidate → core}/merged-row.d.ts +1 -1
  246. package/dist/{consolidate → core}/merged-row.js +1 -1
  247. package/dist/core/physics.js +6 -16
  248. package/dist/core/prediction.d.ts +3 -0
  249. package/dist/core/prediction.js +6 -0
  250. package/dist/core/project-identity.d.ts +3 -0
  251. package/dist/core/project-identity.js +10 -1
  252. package/dist/{store → core}/recall-scope.d.ts +1 -10
  253. package/dist/{store → core}/recall-scope.js +2 -19
  254. package/dist/db/busy.d.ts +2 -7
  255. package/dist/db/busy.js +21 -26
  256. package/dist/db/connect.d.ts +0 -1
  257. package/dist/db/connect.js +5 -6
  258. package/dist/db/index.d.ts +3 -3
  259. package/dist/db/index.js +3 -3
  260. package/dist/db/migrations/index.d.ts +1 -1
  261. package/dist/db/migrations/index.js +3 -1
  262. package/dist/db/migrations/v55.d.ts +3 -0
  263. package/dist/db/migrations/v55.js +17 -0
  264. package/dist/db/open.d.ts +0 -2
  265. package/dist/db/open.js +6 -10
  266. package/dist/db/physics-state.js +3 -3
  267. package/dist/db/tables.d.ts +2 -0
  268. package/dist/db/tables.js +6 -2
  269. package/dist/db/vector-store.js +17 -4
  270. package/dist/db/wal-checkpointer.js +2 -1
  271. package/dist/doctor.js +11 -8
  272. package/dist/embeddings/local.d.ts +62 -0
  273. package/dist/embeddings/local.js +146 -0
  274. package/dist/{store/embeddings → embeddings}/provider.d.ts +5 -2
  275. package/dist/{store/embeddings → embeddings}/provider.js +18 -15
  276. package/dist/embeddings/transformers.d.ts +26 -0
  277. package/dist/embeddings/transformers.js +89 -0
  278. package/dist/entry/session-text.d.ts +1 -1
  279. package/dist/entry/session-text.js +1 -1
  280. package/dist/eval/eval-suite.js +17 -11
  281. package/dist/eval/eval.js +1 -1
  282. package/dist/eval/judgment.js +11 -4
  283. package/dist/graph/extract.js +3 -3
  284. package/dist/graph/recall.js +1 -1
  285. package/dist/graph/view.js +13 -5
  286. package/dist/graph/write.d.ts +1 -1
  287. package/dist/graph/write.js +9 -9
  288. package/dist/hooks/codex-session.js +3 -2
  289. package/dist/hooks/codex-wrapper.js +2 -1
  290. package/dist/hooks/json-hooks.js +4 -2
  291. package/dist/hooks/opencode.js +8 -5
  292. package/dist/hooks/shared.d.ts +0 -6
  293. package/dist/hooks/shared.js +4 -15
  294. package/dist/importers/core.js +1 -1
  295. package/dist/importers/sources.js +5 -4
  296. package/dist/importers/vault.js +7 -5
  297. package/dist/index.d.ts +3 -2
  298. package/dist/index.js +3 -2
  299. package/dist/learn/autolearn.d.ts +10 -2
  300. package/dist/learn/autolearn.js +32 -12
  301. package/dist/learn/churn-git.js +13 -4
  302. package/dist/learn/extract.d.ts +3 -2
  303. package/dist/learn/extract.js +6 -4
  304. package/dist/learn/forward-claim-detector.js +4 -2
  305. package/dist/learn/invalidation.js +10 -6
  306. package/dist/mcp/admin-tools.d.ts +2 -2
  307. package/dist/mcp/admin-tools.js +27 -48
  308. package/dist/mcp/format.js +3 -2
  309. package/dist/mcp/framing.d.ts +1 -0
  310. package/dist/mcp/framing.js +1 -1
  311. package/dist/mcp/memory-tools.js +3 -1
  312. package/dist/mcp/protocol.d.ts +11 -7
  313. package/dist/mcp/protocol.js +25 -12
  314. package/dist/mcp/recall-tools.js +12 -9
  315. package/dist/mcp/request.js +2 -1
  316. package/dist/mcp/stdio.js +24 -8
  317. package/dist/mcp/tool-args.js +2 -1
  318. package/dist/mcp/tools.js +44 -21
  319. package/dist/objects/customer-notes.d.ts +2 -2
  320. package/dist/objects/decisions.d.ts +2 -2
  321. package/dist/objects/descriptor.d.ts +1 -1
  322. package/dist/objects/incidents.d.ts +2 -2
  323. package/dist/objects/lifecycle.d.ts +1 -1
  324. package/dist/objects/lifecycle.js +2 -1
  325. package/dist/objects/policies.d.ts +2 -2
  326. package/dist/objects/policies.js +2 -1
  327. package/dist/objects/processes.d.ts +2 -2
  328. package/dist/objects/project-briefs.d.ts +2 -2
  329. package/dist/objects/project-briefs.js +2 -3
  330. package/dist/objects/skills.d.ts +2 -2
  331. package/dist/postinstall.js +1 -1
  332. package/dist/rerankers/clef.js +3 -6
  333. package/dist/rerankers/cross-encoder.d.ts +31 -2
  334. package/dist/rerankers/cross-encoder.js +63 -97
  335. package/dist/rerankers/index.js +5 -4
  336. package/dist/rerankers/jev.js +2 -4
  337. package/dist/rerankers/outage-warning.d.ts +3 -1
  338. package/dist/rerankers/outage-warning.js +5 -3
  339. package/dist/search/bm25-search.js +1 -1
  340. package/dist/search/boosts.js +1 -1
  341. package/dist/search/embed-memories.d.ts +9 -0
  342. package/dist/search/embed-memories.js +377 -0
  343. package/dist/search/goal-boost.d.ts +1 -1
  344. package/dist/search/goal-boost.js +6 -3
  345. package/dist/search/hybrid.d.ts +9 -2
  346. package/dist/search/hybrid.js +9 -4
  347. package/dist/search/physics-search.d.ts +6 -3
  348. package/dist/search/physics-search.js +22 -15
  349. package/dist/search/rerank.js +1 -1
  350. package/dist/search/vector.d.ts +8 -6
  351. package/dist/search/vector.js +10 -13
  352. package/dist/server/auth.d.ts +2 -0
  353. package/dist/server/auth.js +17 -7
  354. package/dist/server/boot.js +7 -66
  355. package/dist/server/client-ip.d.ts +0 -2
  356. package/dist/server/client-ip.js +3 -2
  357. package/dist/server/deadline.d.ts +0 -2
  358. package/dist/server/deadline.js +1 -7
  359. package/dist/server/defaults.d.ts +1 -0
  360. package/dist/server/defaults.js +1 -0
  361. package/dist/server/mcp-http.js +16 -11
  362. package/dist/server/request.js +7 -2
  363. package/dist/server/route-checks.d.ts +7 -0
  364. package/dist/server/route-checks.js +42 -0
  365. package/dist/server/route-table.d.ts +9 -8
  366. package/dist/server/route-table.js +127 -132
  367. package/dist/server/routes/admin.d.ts +8 -8
  368. package/dist/server/routes/admin.js +13 -21
  369. package/dist/server/routes/customer-notes.d.ts +6 -6
  370. package/dist/server/routes/customer-notes.js +1 -2
  371. package/dist/server/routes/decisions.d.ts +6 -6
  372. package/dist/server/routes/decisions.js +2 -4
  373. package/dist/server/routes/incidents.d.ts +6 -6
  374. package/dist/server/routes/incidents.js +2 -5
  375. package/dist/server/routes/memories.d.ts +9 -9
  376. package/dist/server/routes/memories.js +15 -38
  377. package/dist/server/routes/object-routes.d.ts +6 -6
  378. package/dist/server/routes/object-routes.js +4 -7
  379. package/dist/server/routes/policies.d.ts +7 -7
  380. package/dist/server/routes/policies.js +2 -4
  381. package/dist/server/routes/predictions.d.ts +6 -6
  382. package/dist/server/routes/predictions.js +9 -13
  383. package/dist/server/routes/processes.d.ts +6 -6
  384. package/dist/server/routes/processes.js +1 -2
  385. package/dist/server/routes/project-briefs.d.ts +7 -7
  386. package/dist/server/routes/project-briefs.js +2 -4
  387. package/dist/server/routes/recall.d.ts +5 -5
  388. package/dist/server/routes/recall.js +6 -10
  389. package/dist/server/routes/skills.d.ts +7 -7
  390. package/dist/server/routes/skills.js +2 -4
  391. package/dist/server/server-detect.d.ts +7 -1
  392. package/dist/server/server-detect.js +36 -11
  393. package/dist/server/sleep-child.js +26 -7
  394. package/dist/server/sleep-offload.d.ts +11 -5
  395. package/dist/server/sleep-offload.js +17 -11
  396. package/dist/server/types.d.ts +22 -10
  397. package/dist/server/validation.d.ts +1 -2
  398. package/dist/server/validation.js +6 -11
  399. package/dist/server.d.ts +5 -4
  400. package/dist/server.js +5 -4
  401. package/dist/sharing/global-store.js +2 -2
  402. package/dist/sharing/global-sync.js +38 -45
  403. package/dist/sharing/project-merge.d.ts +7 -14
  404. package/dist/sharing/project-merge.js +57 -121
  405. package/dist/sharing/search-both.js +1 -1
  406. package/dist/sharing/share.d.ts +2 -0
  407. package/dist/sharing/share.js +37 -34
  408. package/dist/store/ambient.js +5 -6
  409. package/dist/store/audit-event.d.ts +1 -1
  410. package/dist/store/audit.d.ts +0 -16
  411. package/dist/store/audit.js +4 -55
  412. package/dist/store/auth.d.ts +4 -2
  413. package/dist/store/auth.js +7 -3
  414. package/dist/store/candidates.d.ts +3 -2
  415. package/dist/store/candidates.js +42 -23
  416. package/dist/store/capture-write.d.ts +17 -0
  417. package/dist/store/capture-write.js +35 -0
  418. package/dist/store/cards.js +1 -1
  419. package/dist/store/compaction-caller.d.ts +18 -0
  420. package/dist/store/compaction-caller.js +29 -0
  421. package/dist/store/compactions-record.d.ts +115 -0
  422. package/dist/store/compactions-record.js +417 -0
  423. package/dist/store/compactions.js +6 -4
  424. package/dist/store/conflicts.js +7 -4
  425. package/dist/store/connectors/dlq.d.ts +10 -0
  426. package/dist/store/connectors/dlq.js +32 -0
  427. package/dist/store/connectors/github.d.ts +7 -9
  428. package/dist/store/connectors/github.js +30 -53
  429. package/dist/store/connectors/slack.d.ts +2 -11
  430. package/dist/store/connectors/slack.js +18 -47
  431. package/dist/store/dashboard-reads.js +7 -6
  432. package/dist/store/delete-and-batch.d.ts +6 -0
  433. package/dist/store/delete-and-batch.js +36 -3
  434. package/dist/store/delivery-recorder.d.ts +10 -3
  435. package/dist/store/delivery-recorder.js +12 -5
  436. package/dist/store/descendant-page.js +6 -3
  437. package/dist/store/dormant.d.ts +1 -1
  438. package/dist/store/dormant.js +3 -1
  439. package/dist/store/embeddings/index.d.ts +2 -12
  440. package/dist/store/embeddings/index.js +5 -374
  441. package/dist/store/entry-reads.d.ts +13 -4
  442. package/dist/store/entry-reads.js +47 -11
  443. package/dist/store/entry-writes.d.ts +5 -5
  444. package/dist/store/entry-writes.js +32 -12
  445. package/dist/store/failure-log-at.d.ts +8 -0
  446. package/dist/store/failure-log-at.js +16 -0
  447. package/dist/store/failure-log.d.ts +2 -2
  448. package/dist/store/failure-log.js +5 -3
  449. package/dist/{trust → store}/gated-write.d.ts +3 -1
  450. package/dist/{trust → store}/gated-write.js +7 -5
  451. package/dist/store/goals.js +20 -18
  452. package/dist/store/graph-reads.js +4 -2
  453. package/dist/store/graph-writes.d.ts +6 -6
  454. package/dist/store/graph-writes.js +48 -71
  455. package/dist/store/handoffs.d.ts +1 -1
  456. package/dist/store/handoffs.js +6 -6
  457. package/dist/store/index-and-stats.js +2 -2
  458. package/dist/store/key-writes.js +1 -1
  459. package/dist/store/ledger-turn.d.ts +9 -0
  460. package/dist/store/ledger-turn.js +38 -0
  461. package/dist/store/mirrors.js +10 -6
  462. package/dist/store/open.d.ts +0 -4
  463. package/dist/store/open.js +40 -53
  464. package/dist/store/pilot-arm.d.ts +12 -0
  465. package/dist/store/pilot-arm.js +42 -0
  466. package/dist/store/port.d.ts +9 -3
  467. package/dist/store/port.js +8 -0
  468. package/dist/store/predictions.d.ts +1 -2
  469. package/dist/store/predictions.js +3 -6
  470. package/dist/store/project-tags.d.ts +62 -0
  471. package/dist/store/project-tags.js +67 -0
  472. package/dist/store/quarantine.js +2 -1
  473. package/dist/store/recall-trace.d.ts +2 -0
  474. package/dist/store/recall-trace.js +18 -2
  475. package/dist/store/rejected-values.js +2 -1
  476. package/dist/store/rejection-probe.d.ts +4 -0
  477. package/dist/store/rejection-probe.js +19 -0
  478. package/dist/store/rejection.d.ts +0 -17
  479. package/dist/store/rejection.js +1 -21
  480. package/dist/store/rule-sql.d.ts +9 -0
  481. package/dist/store/rule-sql.js +21 -2
  482. package/dist/store/search-rows.js +9 -4
  483. package/dist/store/sessions.js +4 -2
  484. package/dist/store/set-aside.d.ts +14 -0
  485. package/dist/store/set-aside.js +23 -0
  486. package/dist/store/sqlite/busy.d.ts +3 -0
  487. package/dist/store/sqlite/busy.js +8 -0
  488. package/dist/store/sqlite/connector-events-group.js +4 -7
  489. package/dist/store/sqlite/connector-writes-group.js +3 -3
  490. package/dist/store/sqlite/entry-writes-group.js +2 -2
  491. package/dist/store/sqlite/error-codec.js +4 -3
  492. package/dist/store/sqlite/executor.js +10 -4
  493. package/dist/store/sqlite/graph-reads-group.js +1 -1
  494. package/dist/store/sqlite/held-connection.d.ts +9 -0
  495. package/dist/store/sqlite/held-connection.js +41 -0
  496. package/dist/store/sqlite/object-rows.d.ts +1 -1
  497. package/dist/store/sqlite/objects-group.d.ts +1 -1
  498. package/dist/store/sqlite/objects-group.js +1 -1
  499. package/dist/store/sqlite/store.js +14 -12
  500. package/dist/store/summaries.d.ts +3 -3
  501. package/dist/store/summaries.js +5 -4
  502. package/dist/store/token-ledger.d.ts +0 -7
  503. package/dist/store/token-ledger.js +0 -35
  504. package/dist/store/vector-index.js +3 -2
  505. package/dist/support-bundle.js +2 -3
  506. package/dist/trust/reject-flow.js +2 -2
  507. package/dist/util/agent-homes.d.ts +15 -0
  508. package/dist/util/agent-homes.js +34 -0
  509. package/dist/util/anthropic-messages.d.ts +3 -0
  510. package/dist/util/anthropic-messages.js +22 -5
  511. package/dist/util/chunked.d.ts +3 -0
  512. package/dist/util/chunked.js +10 -0
  513. package/dist/util/ellipsize.d.ts +3 -0
  514. package/dist/util/ellipsize.js +5 -0
  515. package/dist/util/env.d.ts +2 -1
  516. package/dist/util/env.js +2 -1
  517. package/dist/util/format.d.ts +3 -0
  518. package/dist/util/format.js +6 -0
  519. package/dist/util/hook-payload.d.ts +8 -0
  520. package/dist/util/hook-payload.js +37 -0
  521. package/dist/util/http-retry.d.ts +6 -0
  522. package/dist/util/http-retry.js +43 -5
  523. package/dist/util/http-util.d.ts +0 -8
  524. package/dist/util/http-util.js +10 -21
  525. package/dist/util/limits.d.ts +7 -0
  526. package/dist/util/limits.js +14 -0
  527. package/dist/util/log.d.ts +4 -0
  528. package/dist/util/log.js +9 -0
  529. package/dist/util/request-scope.d.ts +3 -1
  530. package/dist/util/request-scope.js +11 -6
  531. package/dist/util/secret-detect.js +6 -1
  532. package/dist/util/sqlite-blocked.d.ts +2 -0
  533. package/dist/util/sqlite-blocked.js +5 -0
  534. package/dist/util/stream-tee.d.ts +3 -0
  535. package/dist/util/stream-tee.js +35 -0
  536. package/dist/util/time.d.ts +4 -0
  537. package/dist/util/time.js +4 -0
  538. package/dist/util/version.d.ts +1 -1
  539. package/dist/util/version.js +1 -1
  540. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  541. package/extensions/openclaw-plugin/package.json +1 -1
  542. package/openclaw.plugin.json +1 -1
  543. package/package.json +2 -2
  544. package/dist/store/embeddings/local.d.ts +0 -15
  545. package/dist/store/embeddings/local.js +0 -175
  546. /package/dist/{cli → api}/correction-latency.d.ts +0 -0
  547. /package/dist/{cli → api}/correction-latency.js +0 -0
  548. /package/dist/{cli → api}/provenance-coverage.d.ts +0 -0
  549. /package/dist/{cli → api}/provenance-coverage.js +0 -0
  550. /package/dist/{store → core}/object-types.d.ts +0 -0
  551. /package/dist/{store → core}/object-types.js +0 -0
  552. /package/dist/{capture → util}/compaction-items.d.ts +0 -0
  553. /package/dist/{capture → util}/compaction-items.js +0 -0
  554. /package/dist/{store → util}/yaml.d.ts +0 -0
  555. /package/dist/{store → util}/yaml.js +0 -0
package/dist/cli.js CHANGED
@@ -1,39 +1,31 @@
1
1
  #!/usr/bin/env node
2
- // Hippo CLI entry point: parses argv and dispatches each verb through the table below.
2
+ // Hippo CLI entry point: parses argv and dispatches each verb through the table in cli/verbs.ts.
3
3
  // `hippo help` prints the verb list from that table, so no list is kept here.
4
4
  import { envSkipAutoIntegrations } from './util/env.js';
5
5
  import * as path from 'path';
6
6
  import * as fs from 'fs';
7
7
  import { fileURLToPath } from 'node:url';
8
8
  import { repairCodexWrapperIfInstalled } from './hooks/codex-wrapper.js';
9
- import { getHippoRoot } from './store/open.js';
9
+ import { getHippoRoot } from './core/project-identity.js';
10
10
  import { resolveTenantId } from './store/tenant.js';
11
- import { handleGitHub, printGitHubBackfillUsage } from './cli/github.js';
11
+ import { printGitHubBackfillUsage } from './cli/github.js';
12
12
  import { printError } from './cli/output.js';
13
13
  import { errorFields, errorMessage, isLevelEnabled, log } from './util/log.js';
14
- import { isStoreBusy, STORE_BUSY_MESSAGE } from './db/busy.js';
15
- import { boolFlag, flagIsTrue, isBooleanFlag, isStringFlag } from './cli/flag-values.js';
16
- import { VERB_USAGE, USAGE_HEADER, USAGE_EXAMPLES, printAuditPruneUsage, printSlackBackfillUsage, printSlackWorkspacesUsage } from './cli/usage.js';
17
- import { VERB_FLAGS, flagKind, isKnownFlag, undeclaredFlags } from './cli/flags.js';
14
+ import { STORE_BUSY_MESSAGE } from './store/port.js';
15
+ import { isStoreBusy } from './store/sqlite/busy.js';
16
+ import { flagIsTrue, isBooleanFlag, isStringFlag } from './cli/flag-values.js';
17
+ import { USAGE_HEADER, USAGE_EXAMPLES, printAuditPruneUsage, printSlackBackfillUsage, printSlackWorkspacesUsage } from './cli/usage.js';
18
+ import { flagKind, isKnownFlag, undeclaredFlags } from './cli/flags.js';
19
+ import { COMMANDS } from './cli/verbs.js';
18
20
  import { CliExit } from './cli/exit.js';
19
21
  // Helpers
20
- // Commands that delete or hide memories: an unknown flag here stops the run instead of being ignored.
21
- const DESTRUCTIVE_COMMANDS = new Set([
22
- 'audit', 'dedup', 'forget', 'invalidate', 'projects', 'reject', 'resolve', 'sleep', 'supersede',
23
- ]);
24
- // Commands that honour --dry-run. Any other command would ignore it and run for real.
25
- const DRY_RUN_COMMANDS = new Set([
26
- 'audit', 'capture', 'dedup', 'forget', 'import', 'invalidate', 'refine', 'setup', 'sleep',
27
- ]);
28
- // share and brief honour --dry-run in one form only; their other forms write for real.
29
- function dryRunRefusal(command, args, flags) {
30
- const isBrief = command === 'brief' || command === 'project-brief';
31
- const onlyForm = command === 'share' ? 'share --auto' : isBrief ? `${command} refresh` : null;
32
- const honoured = command === 'share' ? args[0] === '--auto' || boolFlag(flags, 'auto')
33
- : isBrief ? args[0] === 'refresh' : DRY_RUN_COMMANDS.has(command);
22
+ // A command that does not honour --dry-run would ignore it and run for real.
23
+ function dryRunRefusal(command, spec, args, flags) {
24
+ const only = spec?.dryRun;
25
+ const honoured = only === undefined ? spec?.flags.switches?.includes('dry-run') : only !== false && only.honoured(args, flags);
34
26
  if (honoured)
35
27
  return null;
36
- const where = onlyForm ? ` outside \`hippo ${onlyForm}\`` : '';
28
+ const where = only ? ` outside \`hippo ${command} ${only.form}\`` : '';
37
29
  return `hippo ${command} has no --dry-run${where}, so it would run for real. Nothing was changed.`;
38
30
  }
39
31
  function pushRepeatableFlag(flags, key, value) {
@@ -134,294 +126,10 @@ function maybeRepairCodexWrapper(currentCommand, flags) {
134
126
  log.debug(`codex wrapper not repaired: ${errorMessage(err)}`);
135
127
  }
136
128
  }
137
- // A verb's entry is handle<Verb>(ctx); cmd<Name> is a typed function below an entry, never called from this table.
138
- /** Every verb main() dispatches, keyed by name; a verb without a VERB_FLAGS entry, or the reverse, fails to compile. */
139
- export const VERB_HANDLERS = {
140
- init: {
141
- run: async (c) => { (await import('./cli/init.js')).handleInit(c); },
142
- },
143
- remember: {
144
- run: async (c) => { await (await import('./cli/remember.js')).handleRemember(c); },
145
- },
146
- recall: {
147
- run: async (c) => { await (await import('./cli/recall.js')).handleRecall(c); },
148
- scoped: true,
149
- },
150
- drill: {
151
- run: async (c) => { await (await import('./cli/dag.js')).handleDrill(c); },
152
- scoped: true,
153
- },
154
- assemble: {
155
- run: async (c) => { await (await import('./cli/dag.js')).handleAssemble(c); },
156
- scoped: true,
157
- },
158
- supersede: {
159
- run: async (c) => { await (await import('./cli/remember.js')).handleSupersede(c); },
160
- },
161
- explain: {
162
- run: async (c) => { await (await import('./cli/explain.js')).handleExplain(c); },
163
- scoped: true,
164
- },
165
- eval: {
166
- run: async (c) => { await (await import('./cli/eval.js')).handleEval(c); },
167
- },
168
- trace: {
169
- run: async (c) => { await (await import('./cli/remember.js')).handleTrace(c); },
170
- },
171
- refine: {
172
- run: async (c) => { await (await import('./cli/maintenance.js')).handleRefine(c); },
173
- },
174
- sleep: {
175
- run: async (c) => { await (await import('./cli/sleep.js')).handleSleep(c); },
176
- scoped: true,
177
- },
178
- 'last-sleep': {
179
- run: async (c) => { (await import('./cli/last-sleep.js')).handleLastSleep(c); },
180
- },
181
- 'session-end': {
182
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleSessionEnd(c); },
183
- },
184
- '__session-end-worker': {
185
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleSessionEndWorker(c); },
186
- },
187
- 'pre-compact': {
188
- run: async (c) => { await (await import('./cli/session-hooks.js')).handlePreCompact(c); },
189
- },
190
- 'post-compact': {
191
- run: async (c) => { await (await import('./cli/session-hooks.js')).handlePostCompact(c); },
192
- },
193
- 'capture-error': {
194
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleCaptureError(c); },
195
- },
196
- 'compact-resume': {
197
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleCompactResume(c); },
198
- },
199
- 'codex-run': {
200
- run: async (c) => { (await import('./cli/session-hooks.js')).handleCodexRun(c); },
201
- },
202
- '__codex-session-end-worker': {
203
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleCodexSessionEndWorker(c); },
204
- },
205
- dedup: {
206
- run: async (c) => { (await import('./cli/maintenance.js')).handleDedup(c); },
207
- },
208
- dag: {
209
- run: async (c) => { (await import('./cli/dag.js')).handleDag(c); },
210
- },
211
- auth: {
212
- run: async (c) => { (await import('./cli/auth.js')).handleAuth(c); },
213
- scoped: true,
214
- },
215
- goal: {
216
- run: async (c) => { (await import('./cli/goals.js')).handleGoal(c); },
217
- scoped: true,
218
- },
219
- slack: {
220
- run: async (c) => { await (await import('./cli/slack.js')).handleSlack(c); },
221
- },
222
- github: {
223
- run: async (c) => { await handleGitHub(c); },
224
- },
225
- audit: {
226
- run: async (c) => { await (await import('./cli/audit.js')).handleAudit(c); },
227
- scoped: true,
228
- },
229
- 'correction-latency': {
230
- run: async (c) => { await (await import('./cli/status.js')).handleCorrectionLatency(c); },
231
- },
232
- provenance: {
233
- run: async (c) => { await (await import('./cli/status.js')).handleProvenance(c); },
234
- },
235
- status: {
236
- run: async (c) => { (await import('./cli/status.js')).handleStatus(c); },
237
- },
238
- outcome: {
239
- run: async (c) => { (await import('./cli/curate.js')).handleOutcome(c); },
240
- scoped: true,
241
- },
242
- conflicts: {
243
- run: async (c) => { (await import('./cli/curate.js')).handleConflicts(c); },
244
- },
245
- resolve: {
246
- run: async (c) => { await (await import('./cli/curate.js')).handleResolve(c); },
247
- },
248
- reject: {
249
- run: async (c) => { (await import('./cli/curate.js')).handleReject(c); },
250
- },
251
- rejections: {
252
- run: async (c) => { (await import('./cli/curate.js')).handleRejections(c); },
253
- },
254
- unreject: {
255
- run: async (c) => { (await import('./cli/curate.js')).handleUnreject(c); },
256
- },
257
- dormant: {
258
- run: async (c) => { (await import('./cli/curate.js')).handleDormant(c); },
259
- scoped: true,
260
- },
261
- projects: {
262
- run: async (c) => { (await import('./cli/projects.js')).handleProjects(c); },
263
- },
264
- quarantine: {
265
- run: async (c) => { await (await import('./cli/curate.js')).handleQuarantine(c); },
266
- scoped: true,
267
- },
268
- tokens: {
269
- run: async (c) => { (await import('./cli/status.js')).handleTokens(c); },
270
- scoped: true,
271
- },
272
- failures: {
273
- run: async (c) => { (await import('./cli/status.js')).handleFailures(c); },
274
- scoped: true,
275
- },
276
- doctor: {
277
- run: async (c) => { await (await import('./cli/status.js')).handleDoctor(c); },
278
- },
279
- 'support-bundle': {
280
- run: async (c) => { await (await import('./cli/status.js')).handleSupportBundle(c); },
281
- },
282
- snapshot: {
283
- run: async (c) => { (await import('./cli/continuity.js')).handleSnapshot(c); },
284
- },
285
- session: {
286
- run: async (c) => { (await import('./cli/continuity.js')).handleSession(c); },
287
- },
288
- handoff: {
289
- run: async (c) => { (await import('./cli/continuity.js')).handleHandoff(c); },
290
- },
291
- card: {
292
- run: async (c) => { (await import('./cli/card.js')).handleCard(c); },
293
- },
294
- predict: {
295
- run: async (c) => { (await import('./cli/decisions.js')).handlePredict(c); },
296
- },
297
- current: {
298
- run: async (c) => { (await import('./cli/continuity.js')).handleCurrent(c); },
299
- },
300
- forget: {
301
- run: async (c) => { await (await import('./cli/curate.js')).handleForget(c); },
302
- scoped: true,
303
- },
304
- inspect: {
305
- run: async (c) => { await (await import('./cli/status.js')).handleInspect(c); },
306
- },
307
- context: {
308
- run: async (c) => { await (await import('./cli/context.js')).handleContext(c); },
309
- },
310
- hook: {
311
- run: async (c) => { (await import('./cli/setup.js')).handleHook(c); },
312
- },
313
- setup: {
314
- run: async (c) => { (await import('./cli/setup.js')).handleSetup(c); },
315
- },
316
- 'daily-runner': {
317
- run: async (c) => { (await import('./cli/setup.js')).handleDailyRunner(c); },
318
- },
319
- embed: {
320
- run: async (c) => { await (await import('./cli/maintenance.js')).handleEmbed(c); },
321
- },
322
- watch: {
323
- run: async (c) => { await (await import('./cli/transfer.js')).handleWatch(c); },
324
- },
325
- learn: {
326
- run: async (c) => { (await import('./cli/transfer.js')).handleLearn(c); },
327
- scoped: true,
328
- },
329
- promote: {
330
- run: async (c) => { await (await import('./cli/transfer.js')).handlePromote(c); },
331
- scoped: true,
332
- },
333
- sync: {
334
- run: async (c) => { (await import('./cli/transfer.js')).handleSync(c); },
335
- },
336
- share: {
337
- run: async (c) => { await (await import('./cli/transfer.js')).handleShare(c); },
338
- },
339
- peers: {
340
- run: async (c) => { await (await import('./cli/transfer.js')).handlePeers(c); },
341
- },
342
- import: {
343
- run: async (c) => { (await import('./cli/transfer.js')).handleImport(c); },
344
- },
345
- export: {
346
- run: async (c) => { await (await import('./cli/transfer.js')).handleExport(c); },
347
- },
348
- capture: {
349
- run: async (c) => { await (await import('./cli/session-hooks.js')).handleCapture(c); },
350
- },
351
- dashboard: {
352
- run: async (c) => { await (await import('./cli/serve.js')).handleDashboard(c); },
353
- },
354
- wm: {
355
- run: async (c) => { (await import('./cli/continuity.js')).handleWm(c); },
356
- },
357
- mcp: {
358
- run: async () => { await (await import('./cli/serve.js')).handleMcp(); },
359
- },
360
- serve: {
361
- run: async (c) => { await (await import('./cli/serve.js')).handleServe(c); },
362
- },
363
- invalidate: {
364
- run: async (c) => { await (await import('./cli/curate.js')).handleInvalidate(c); },
365
- },
366
- decide: {
367
- run: async (c) => { await (await import('./cli/decisions.js')).handleDecide(c); },
368
- },
369
- incident: {
370
- run: async (c) => { (await import('./cli/decisions.js')).handleIncident(c); },
371
- },
372
- process: {
373
- run: async (c) => { (await import('./cli/playbooks.js')).handleProcess(c); },
374
- },
375
- policy: {
376
- run: async (c) => { (await import('./cli/playbooks.js')).handlePolicy(c); },
377
- },
378
- skill: {
379
- run: async (c) => { (await import('./cli/playbooks.js')).handleSkill(c); },
380
- },
381
- brief: {
382
- run: async (c) => { (await import('./cli/briefs.js')).handleProjectBrief(c); },
383
- aliases: ['project-brief'],
384
- },
385
- note: {
386
- run: async (c) => { (await import('./cli/briefs.js')).handleCustomerNote(c); },
387
- aliases: ['customer-note'],
388
- },
389
- graph: {
390
- run: async (c) => { (await import('./cli/briefs.js')).handleGraph(c); },
391
- },
392
- };
393
- const USAGE_BLOCKS = VERB_USAGE;
394
- const FLAGS_BY_VERB = VERB_FLAGS;
395
- function buildCommands() {
396
- const specs = Object.entries(VERB_HANDLERS).map(([verb, handler]) => {
397
- const spec = { ...handler, usage: USAGE_BLOCKS[verb] ?? [], flags: FLAGS_BY_VERB[verb] };
398
- return [verb, spec];
399
- });
400
- // SAFETY: VERB_HANDLERS is checked above to have exactly the VerbName keys, so every key is present.
401
- return Object.fromEntries(specs);
402
- }
403
- /** Every verb's handler, aliases, help blocks and flags, keyed by name. */
404
- export const COMMANDS = buildCommands();
129
+ const ROWS = Object.values(COMMANDS);
405
130
  const COMMAND_INDEX = new Map(Object.entries(COMMANDS).flatMap(([verb, spec]) => [verb, ...(spec.aliases ?? [])].map((name) => [name, spec])));
406
- // The full listing order; a verb listed twice prints its next help block.
407
- const USAGE_ORDER = [
408
- 'init', 'remember', 'supersede', 'recall', 'explain', 'trace', 'refine', 'eval', 'context', 'sleep',
409
- 'daily-runner', 'dedup', 'status', 'audit', 'github', 'slack', 'provenance', 'dag', 'drill', 'assemble',
410
- 'correction-latency', 'outcome', 'conflicts', 'resolve', 'reject', 'rejections', 'unreject', 'dormant',
411
- 'projects', 'quarantine', 'capture-error', 'doctor', 'support-bundle', 'tokens', 'failures', 'snapshot',
412
- 'session', 'handoff', 'card', 'current', 'forget', 'inspect', 'embed', 'watch', 'learn', 'promote',
413
- 'share', 'peers', 'sync', 'import', 'export', 'capture', 'setup', 'last-sleep', 'session-end',
414
- 'pre-compact', 'compact-resume', 'post-compact', 'codex-run', 'hook', 'predict', 'decide', 'incident',
415
- 'process', 'policy', 'skill', 'brief', 'note', 'graph', 'invalidate', 'wm', 'dashboard', 'mcp', 'serve',
416
- 'goal', 'auth', 'audit',
417
- ];
418
131
  export function usageText() {
419
- const printed = new Map();
420
- const blocks = USAGE_ORDER.map((verb) => {
421
- const index = printed.get(verb) ?? 0;
422
- printed.set(verb, index + 1);
423
- return COMMANDS[verb].usage[index];
424
- });
132
+ const blocks = [...ROWS.flatMap((row) => row.usage ?? []), ...ROWS.flatMap((row) => row.listedLast ?? [])];
425
133
  return USAGE_HEADER + blocks.join('') + USAGE_EXAMPLES;
426
134
  }
427
135
  function printUsage() {
@@ -429,7 +137,8 @@ function printUsage() {
429
137
  }
430
138
  /** One verb's help blocks as `hippo <verb> --help` prints them, or null for a verb with none. */
431
139
  export function verbUsage(verb) {
432
- const usage = COMMAND_INDEX.get(verb)?.usage ?? [];
140
+ const spec = COMMAND_INDEX.get(verb);
141
+ const usage = [...(spec?.usage ?? []), ...(spec?.listedLast ?? [])];
433
142
  return usage.length > 0 ? usage.join('').slice(1) : null;
434
143
  }
435
144
  // These sub-commands have fuller usage text than their lines in usageText().
@@ -486,13 +195,14 @@ function rejectValuedSwitches(flags, declared) {
486
195
  }
487
196
  }
488
197
  }
489
- function checkUnknownFlags(command, flags, declared) {
198
+ function checkUnknownFlags(command, flags, spec) {
199
+ const declared = spec?.flags;
490
200
  // card checks its flags per subcommand, with a stricter message.
491
201
  if (command === 'card')
492
202
  return;
493
203
  const flagNames = (keys) => keys.map((key) => `--${key}`).join(', ');
494
204
  const unknown = Object.keys(flags).filter((key) => !isKnownFlag(key));
495
- if (unknown.length > 0 && DESTRUCTIVE_COMMANDS.has(command)) {
205
+ if (unknown.length > 0 && spec?.destructive) {
496
206
  printError(`Unknown flag ${flagNames(unknown)} for hippo ${command}. Nothing was changed.`);
497
207
  throw new CliExit(2);
498
208
  }
@@ -518,8 +228,8 @@ async function main(command, args, flags, hippoRoot) {
518
228
  rejectEmptyScope(flags);
519
229
  rejectNonNumericFlags(flags, spec?.flags);
520
230
  rejectValuedSwitches(flags, spec?.flags);
521
- checkUnknownFlags(command, flags, spec?.flags);
522
- const refusal = Object.hasOwn(flags, 'dry-run') ? dryRunRefusal(command, args, flags) : null;
231
+ checkUnknownFlags(command, flags, spec);
232
+ const refusal = Object.hasOwn(flags, 'dry-run') ? dryRunRefusal(command, spec, args, flags) : null;
523
233
  if (refusal) {
524
234
  printError(refusal);
525
235
  throw new CliExit(2);
@@ -1,5 +1,6 @@
1
1
  import { type HippoStore } from '../store/index.js';
2
2
  import type { ConnectorDeadLetter } from '../store/port.js';
3
+ import type { JsonValue } from '../util/json.js';
3
4
  declare const DEFAULT_BUCKET = "parse_error";
4
5
  /** What a caller hands over to park one payload, whatever the connector. */
5
6
  export interface ParkOpts<Bucket extends string> {
@@ -18,10 +19,14 @@ export interface ParkedRow<Bucket extends string> {
18
19
  bucket: Bucket | typeof DEFAULT_BUCKET;
19
20
  signature: string | null;
20
21
  }
21
- /** What one connector supplies: the tag that names its table to the store, and its list. `Own` is the columns only its table has. */
22
+ /** What one connector supplies: the tag that names its table to the store, its list, its one-row read and its retry bump.
23
+ * `Own` is the columns only its table has. */
22
24
  export interface ConnectorDlq<Own, Bucket extends string, Item> {
23
25
  readonly letter: (row: ParkedRow<Bucket> & Own) => ConnectorDeadLetter;
24
26
  readonly list: (hippoRoot: string, tenantId: string, limit: number) => Item[];
27
+ readonly entry: (hippoRoot: string, id: number) => Item | null;
28
+ /** Adds one to `retry_count` and stamps `retried_at`. */
29
+ readonly bump: (hippoRoot: string, id: number) => void;
25
30
  }
26
31
  /** Parks on `store`, else on hippo.db under `hippoRoot`. */
27
32
  export declare function parkInDlq<Own, Bucket extends string>(dlq: ConnectorDlq<Own, Bucket, unknown>, hippoRoot: string, opts: ParkOpts<Bucket> & NoInfer<Own>, store?: HippoStore): Promise<number>;
@@ -38,7 +43,38 @@ export interface ReplayResult {
38
43
  retryCount: number;
39
44
  reason?: string;
40
45
  }
41
- /** A replay that did not go through; `retryCount` is the row's count after any bump the caller made. */
42
- export declare function replayFailed(status: ReplayStatus, retryCount: number, reason: string): ReplayResult;
46
+ /** The columns a replay reads from any connector's row. */
47
+ interface ParkedEntry {
48
+ readonly id: number;
49
+ readonly retryCount: number;
50
+ readonly rawPayload: string;
51
+ }
52
+ /** A row that cannot pass the signature gate: 'sig_missing' is not counted, since only --force can get it through. */
53
+ export interface SignatureRefusal {
54
+ readonly status: 'sig_missing' | 'sig_fail';
55
+ readonly reason: string;
56
+ }
57
+ /** What a connector's re-ingest of a parsed envelope reports. */
58
+ export type Reingest = {
59
+ readonly ok: true;
60
+ readonly status: ReplayStatus;
61
+ readonly memoryId: string | null;
62
+ readonly reason?: string;
63
+ } | {
64
+ readonly ok: false;
65
+ readonly status: ReplayStatus;
66
+ readonly reason: string;
67
+ };
68
+ /** The parts of a replay only the connector knows. */
69
+ export interface ReplaySteps<Item, Envelope extends JsonValue> {
70
+ readonly dlq: ConnectorDlq<never, never, Item>;
71
+ /** Skipped under --force. */
72
+ readonly refuseSignature: (row: Item) => SignatureRefusal | null;
73
+ readonly isEnvelope: (parsed: JsonValue) => parsed is Envelope;
74
+ readonly notEnvelope: string;
75
+ readonly reingest: (row: Item, envelope: Envelope) => Promise<Reingest>;
76
+ }
77
+ /** Re-runs a parked row under today's secret and routing; every attempt past the read is counted once, except a missing signature. */
78
+ export declare function replayParked<Item extends ParkedEntry, Envelope extends JsonValue>(steps: ReplaySteps<Item, Envelope>, hippoRoot: string, id: number, force: boolean): Promise<ReplayResult>;
43
79
  export {};
44
80
  //# sourceMappingURL=dlq.d.ts.map
@@ -1,10 +1,11 @@
1
1
  // The dead-letter queue every webhook connector parks into: one redaction, one unroutable sentinel, one set of defaults, one replay result.
2
+ import { DEFAULT_LIST_LIMIT } from '../util/limits.js';
2
3
  import { DLQ_REDACTED_NOTE, redactPayload } from '../util/secret-detect.js';
3
4
  import { requireGroup, storeFor } from '../store/index.js';
5
+ import { errorMessage } from '../util/log.js';
4
6
  /** The tenant stored on a row no tenant was resolved for; the column is NOT NULL. */
5
7
  const UNROUTABLE_TENANT = '__unroutable__';
6
8
  const DEFAULT_BUCKET = 'parse_error';
7
- const DEFAULT_LIST_LIMIT = 100;
8
9
  /** Parks on `store`, else on hippo.db under `hippoRoot`. */
9
10
  export async function parkInDlq(dlq, hippoRoot, opts, store) {
10
11
  const rawPayload = redactPayload(opts.rawPayload);
@@ -23,8 +24,41 @@ export async function parkInDlq(dlq, hippoRoot, opts, store) {
23
24
  export function listDlq(dlq, hippoRoot, opts) {
24
25
  return dlq.list(hippoRoot, opts.tenantId, opts.limit ?? DEFAULT_LIST_LIMIT);
25
26
  }
26
- /** A replay that did not go through; `retryCount` is the row's count after any bump the caller made. */
27
- export function replayFailed(status, retryCount, reason) {
27
+ /** A replay that did not go through; `retryCount` is the row's count after any bump made. */
28
+ function replayFailed(status, retryCount, reason) {
28
29
  return { ok: false, status, memoryId: null, retryCount, reason };
29
30
  }
31
+ /** A replay that failed after the row was read: counts it exactly once, then reports the new count. */
32
+ function failAndBump(dlq, hippoRoot, row, status, reason) {
33
+ dlq.bump(hippoRoot, row.id);
34
+ return replayFailed(status, row.retryCount + 1, reason);
35
+ }
36
+ /** Re-runs a parked row under today's secret and routing; every attempt past the read is counted once, except a missing signature. */
37
+ export async function replayParked(steps, hippoRoot, id, force) {
38
+ const row = steps.dlq.entry(hippoRoot, id);
39
+ if (!row)
40
+ return replayFailed('not_found', 0, `dlq id ${id} not found`);
41
+ const refusal = force ? null : steps.refuseSignature(row);
42
+ if (refusal?.status === 'sig_missing')
43
+ return replayFailed(refusal.status, row.retryCount, refusal.reason);
44
+ if (refusal)
45
+ return failAndBump(steps.dlq, hippoRoot, row, refusal.status, refusal.reason);
46
+ let parsed;
47
+ try {
48
+ parsed = JSON.parse(row.rawPayload);
49
+ }
50
+ catch (e) {
51
+ return failAndBump(steps.dlq, hippoRoot, row, 'parse_error', `still unparseable: ${errorMessage(e)}`);
52
+ }
53
+ if (!steps.isEnvelope(parsed))
54
+ return failAndBump(steps.dlq, hippoRoot, row, 'unhandled', steps.notEnvelope);
55
+ const outcome = await steps.reingest(row, parsed);
56
+ if (!outcome.ok)
57
+ return failAndBump(steps.dlq, hippoRoot, row, outcome.status, outcome.reason);
58
+ steps.dlq.bump(hippoRoot, row.id);
59
+ const result = { ok: true, status: outcome.status, memoryId: outcome.memoryId, retryCount: row.retryCount + 1 };
60
+ if (outcome.reason !== undefined)
61
+ result.reason = outcome.reason;
62
+ return result;
63
+ }
30
64
  //# sourceMappingURL=dlq.js.map
@@ -82,14 +82,23 @@ async function drainStream(ctx, url0, options) {
82
82
  }
83
83
  return { ingested, pages, maxUpdatedAt, drained: true };
84
84
  }
85
+ // A reset hours away must fail the run for a later rerun; sleeping through it would hold the process for the whole window.
86
+ const MAX_RATE_LIMIT_ATTEMPTS = 5;
87
+ const MAX_RATE_LIMIT_WAIT_MS = 10 * 60 * 1000;
85
88
  async function fetchPagePastRateLimit(options, url) {
86
89
  const { fetcher, token, sleep } = options;
87
- // Fetch with rate-limit retry loop.
88
- while (true) {
90
+ let waitedMs = 0;
91
+ for (let attempt = 1;; attempt++) {
89
92
  const page = await fetcher({ url, token });
90
93
  if (page.rateLimit.reason === 'none')
91
94
  return page;
92
- await sleep(page.rateLimit.sleepSeconds * 1000);
95
+ const waitMs = page.rateLimit.sleepSeconds * 1000;
96
+ if (attempt >= MAX_RATE_LIMIT_ATTEMPTS || waitedMs + waitMs > MAX_RATE_LIMIT_WAIT_MS) {
97
+ const resetAt = new Date(Date.now() + waitMs).toISOString();
98
+ throw new Error(`GitHub rate limit still active after ${attempt} attempts and ${Math.round(waitedMs / 1000)}s waited; resets at ${resetAt}`);
99
+ }
100
+ await sleep(waitMs);
101
+ waitedMs += waitMs;
93
102
  }
94
103
  }
95
104
  function issueItemToEvent(item, repository) {
@@ -1,88 +1,46 @@
1
- import { bumpGitHubDlqRetryCount, githubDlqEntry, listGitHubDlq, } from '../../store/connectors/github.js';
2
- import { replayFailed } from '../dlq.js';
1
+ import { githubDlqEntry, markGitHubDlqRetried, listGitHubDlq, } from '../../store/connectors/github.js';
2
+ import { replayParked } from '../dlq.js';
3
3
  import { verifyGitHubSignature } from './signature.js';
4
4
  import { isGitHubWebhookEnvelope } from './types.js';
5
5
  /** GitHub's dead-letter table; the event, delivery, installation and repo columns let an operator triage a row without re-reading the payload. */
6
6
  export const githubDlq = {
7
7
  letter: (row) => ({ connector: 'github', ...row }),
8
8
  list: listGitHubDlq,
9
+ entry: githubDlqEntry,
10
+ bump: markGitHubDlqRetried,
9
11
  };
10
12
  /** Replay a DLQ row through the normal ingest path; a failed signature, parse or envelope check bumps retry_count.
11
13
  * Without an `ingestHook` (dry-run) it bumps retry_count and returns `replayed` with memoryId=null; replays use today's routing, not the original's. */
12
14
  export async function replayDlqEntry(ctx, id, opts = {}) {
13
- const row = githubDlqEntry(ctx.hippoRoot, id);
14
- if (!row)
15
- return replayFailed('not_found', 0, `dlq id ${id} not found`);
16
- // Signature verification (current secret, not the one in effect when DLQed).
17
- if (!opts.force && opts.webhookSecret) {
18
- const sigFailure = checkReplaySignature(ctx.hippoRoot, id, row, opts.webhookSecret, opts.previousSecret);
19
- if (sigFailure)
20
- return sigFailure;
21
- }
22
- const envelopeFailure = checkReplayEnvelope(ctx.hippoRoot, id, row);
23
- if (envelopeFailure)
24
- return envelopeFailure;
25
- // Without an ingest hook this is a dry-run validation. Bump and report.
26
- if (!opts.ingestHook) {
27
- bumpGitHubDlqRetryCount(ctx.hippoRoot, id);
28
- return {
29
- ok: true,
30
- status: 'replayed',
31
- memoryId: null,
32
- retryCount: row.retryCount + 1,
33
- reason: 'dry-run: no ingest hook supplied',
34
- };
35
- }
36
- // Real replay path: the route's IngestHook owns routing, idempotency and the memory write; this module only validates and bumps the retry counter.
37
- // No idempotencyKey arg: the hook re-derives it from the parsed event (artifact_ref + updated_at).
38
- const eventName = row.eventName ?? '';
39
- const deliveryId = row.deliveryId ?? '';
40
- const { memoryId } = await opts.ingestHook(ctx, {
41
- rawPayload: row.rawPayload,
42
- eventName,
43
- deliveryId,
44
- });
45
- bumpGitHubDlqRetryCount(ctx.hippoRoot, id);
46
- return {
47
- ok: true,
48
- status: 'replayed',
49
- memoryId,
50
- retryCount: row.retryCount + 1,
51
- };
15
+ const { webhookSecret, previousSecret, ingestHook } = opts;
16
+ return replayParked({
17
+ dlq: githubDlq,
18
+ // The secret in effect now, not the one in effect when the row was parked.
19
+ refuseSignature: (row) => (webhookSecret ? refuseSignature(row, webhookSecret, previousSecret) : null),
20
+ isEnvelope: isGitHubWebhookEnvelope,
21
+ notEnvelope: 'not a GitHub webhook envelope',
22
+ reingest: async (row) => {
23
+ if (!ingestHook)
24
+ return { ok: true, status: 'replayed', memoryId: null, reason: 'dry-run: no ingest hook supplied' };
25
+ // The hook owns routing, idempotency and the memory write, and re-derives the key from the parsed event.
26
+ const { memoryId } = await ingestHook(ctx, {
27
+ rawPayload: row.rawPayload,
28
+ eventName: row.eventName ?? '',
29
+ deliveryId: row.deliveryId ?? '',
30
+ });
31
+ return { ok: true, status: 'replayed', memoryId };
32
+ },
33
+ }, ctx.hippoRoot, id, opts.force === true);
52
34
  }
53
- /** The failure result when the row cannot pass the signature gate, else null. */
54
- function checkReplaySignature(hippoRoot, id, row, webhookSecret, previousSecret) {
35
+ function refuseSignature(row, webhookSecret, previousSecret) {
55
36
  if (!row.signature) {
56
- return replayFailed('sig_missing', row.retryCount, 'row has no signature (legacy, or redacted before storing); pass --force to replay');
57
- }
58
- const sigOk = verifyGitHubSignature({
59
- rawBody: row.rawPayload,
60
- signature: row.signature,
61
- webhookSecret,
62
- previousSecret,
63
- });
64
- if (!sigOk) {
65
- bumpGitHubDlqRetryCount(hippoRoot, id);
66
- return replayFailed('sig_fail', row.retryCount + 1, 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway');
37
+ return { status: 'sig_missing', reason: 'row has no signature (legacy, or redacted before storing); pass --force to replay' };
67
38
  }
68
- return null;
69
- }
70
- /** Parse + envelope guard; the failure result after bumping the count, else null. */
71
- function checkReplayEnvelope(hippoRoot, id, row) {
72
- let parsed;
73
- try {
74
- parsed = JSON.parse(row.rawPayload);
75
- }
76
- catch (e) {
77
- bumpGitHubDlqRetryCount(hippoRoot, id);
78
- // SAFETY: best-effort error message only; property access on any JS value is safe, even for a non-Error throw.
79
- const message = e.message;
80
- return replayFailed('parse_error', row.retryCount + 1, `still unparseable: ${message}`);
81
- }
82
- if (!isGitHubWebhookEnvelope(parsed)) {
83
- bumpGitHubDlqRetryCount(hippoRoot, id);
84
- return replayFailed('unhandled', row.retryCount + 1, 'not a GitHub webhook envelope');
85
- }
86
- return null;
39
+ if (verifyGitHubSignature({ rawBody: row.rawPayload, signature: row.signature, webhookSecret, previousSecret }))
40
+ return null;
41
+ return {
42
+ status: 'sig_fail',
43
+ reason: 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway',
44
+ };
87
45
  }
88
46
  //# sourceMappingURL=dlq.js.map