hippo-memory 1.59.0 → 1.61.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 (596) hide show
  1. package/README.md +1 -1
  2. package/dist/ablation.js +9 -27
  3. package/dist/agent-memories/apply.js +4 -1
  4. package/dist/agent-memories/claude-code.js +1 -1
  5. package/dist/agent-memories/codex.js +1 -1
  6. package/dist/agent-memories/gemini.js +1 -1
  7. package/dist/agent-memories/legacy.js +1 -1
  8. package/dist/agent-memories/source.js +1 -1
  9. package/dist/agent-memories/sync.js +8 -3
  10. package/dist/ambient-store.d.ts +14 -0
  11. package/dist/ambient-store.js +90 -0
  12. package/dist/ambient.d.ts +23 -0
  13. package/dist/ambient.js +72 -50
  14. package/dist/api/assemble.d.ts +93 -0
  15. package/dist/api/assemble.js +152 -0
  16. package/dist/api/audit.d.ts +17 -0
  17. package/dist/api/audit.js +23 -0
  18. package/dist/api/auth.d.ts +79 -0
  19. package/dist/api/auth.js +178 -0
  20. package/dist/api/context-types.d.ts +105 -0
  21. package/dist/api/context-types.js +3 -0
  22. package/dist/api/context.d.ts +31 -0
  23. package/dist/api/context.js +705 -0
  24. package/dist/api/dormant.d.ts +30 -0
  25. package/dist/api/dormant.js +140 -0
  26. package/dist/api/drill-down.d.ts +84 -0
  27. package/dist/api/drill-down.js +123 -0
  28. package/dist/api/forget.d.ts +57 -0
  29. package/dist/api/forget.js +87 -0
  30. package/dist/api/goals.d.ts +18 -0
  31. package/dist/api/goals.js +33 -0
  32. package/dist/api/learn.d.ts +31 -0
  33. package/dist/api/learn.js +88 -0
  34. package/dist/api/outcome.d.ts +61 -0
  35. package/dist/api/outcome.js +66 -0
  36. package/dist/api/promote.d.ts +54 -0
  37. package/dist/api/promote.js +203 -0
  38. package/dist/api/quarantine.d.ts +24 -0
  39. package/dist/api/quarantine.js +121 -0
  40. package/dist/api/recall-types.d.ts +390 -0
  41. package/dist/api/recall-types.js +3 -0
  42. package/dist/api/recall.d.ts +36 -0
  43. package/dist/api/recall.js +634 -0
  44. package/dist/api/remember.d.ts +35 -0
  45. package/dist/api/remember.js +43 -0
  46. package/dist/api/sleep.d.ts +136 -0
  47. package/dist/api/sleep.js +271 -0
  48. package/dist/api/tokens.d.ts +26 -0
  49. package/dist/api/tokens.js +60 -0
  50. package/dist/api/types.d.ts +56 -0
  51. package/dist/api/types.js +38 -0
  52. package/dist/api.d.ts +20 -1260
  53. package/dist/api.js +25 -2711
  54. package/dist/audit.d.ts +3 -0
  55. package/dist/audit.js +7 -3
  56. package/dist/auth.d.ts +45 -4
  57. package/dist/auth.js +125 -48
  58. package/dist/autolearn.js +7 -4
  59. package/dist/capture/command.d.ts +33 -0
  60. package/dist/capture/command.js +264 -0
  61. package/dist/capture/compact.d.ts +44 -0
  62. package/dist/capture/compact.js +354 -0
  63. package/dist/capture/extract.d.ts +21 -0
  64. package/dist/capture/extract.js +464 -0
  65. package/dist/capture/transcript.d.ts +40 -0
  66. package/dist/capture/transcript.js +193 -0
  67. package/dist/capture-error.js +2 -1
  68. package/dist/churn-git.js +4 -2
  69. package/dist/cli/audit.d.ts +3 -0
  70. package/dist/cli/audit.js +159 -0
  71. package/dist/cli/auth.d.ts +2 -0
  72. package/dist/cli/auth.js +171 -0
  73. package/dist/cli/briefs.d.ts +4 -0
  74. package/dist/cli/briefs.js +435 -0
  75. package/dist/cli/card.d.ts +3 -0
  76. package/dist/cli/card.js +333 -0
  77. package/dist/cli/context.d.ts +15 -0
  78. package/dist/cli/context.js +366 -0
  79. package/dist/cli/continuity.d.ts +6 -0
  80. package/dist/cli/continuity.js +445 -0
  81. package/dist/cli/curate.d.ts +19 -0
  82. package/dist/cli/curate.js +555 -0
  83. package/dist/cli/dag.d.ts +5 -0
  84. package/dist/cli/dag.js +177 -0
  85. package/dist/cli/decisions.d.ts +4 -0
  86. package/dist/cli/decisions.js +528 -0
  87. package/dist/cli/eval.d.ts +5 -0
  88. package/dist/cli/eval.js +213 -0
  89. package/dist/cli/explain.d.ts +4 -0
  90. package/dist/cli/explain.js +150 -0
  91. package/dist/cli/goals.d.ts +2 -0
  92. package/dist/cli/goals.js +196 -0
  93. package/dist/cli/hook-blocks.d.ts +18 -0
  94. package/dist/cli/hook-blocks.js +233 -0
  95. package/dist/cli/init.d.ts +2 -0
  96. package/dist/cli/init.js +305 -0
  97. package/dist/cli/maintenance.d.ts +4 -0
  98. package/dist/cli/maintenance.js +179 -0
  99. package/dist/cli/playbooks.d.ts +4 -0
  100. package/dist/cli/playbooks.js +556 -0
  101. package/dist/cli/projects.js +1 -1
  102. package/dist/cli/recall.d.ts +7 -0
  103. package/dist/cli/recall.js +597 -0
  104. package/dist/cli/remember.d.ts +5 -0
  105. package/dist/cli/remember.js +442 -0
  106. package/dist/cli/serve.d.ts +5 -0
  107. package/dist/cli/serve.js +40 -0
  108. package/dist/cli/session-hooks.d.ts +29 -0
  109. package/dist/cli/session-hooks.js +637 -0
  110. package/dist/cli/setup.d.ts +4 -0
  111. package/dist/cli/setup.js +376 -0
  112. package/dist/cli/shared.d.ts +15 -19
  113. package/dist/cli/shared.js +50 -341
  114. package/dist/cli/slack.d.ts +2 -0
  115. package/dist/cli/slack.js +171 -0
  116. package/dist/cli/status.d.ts +18 -0
  117. package/dist/cli/status.js +400 -0
  118. package/dist/cli/transfer.d.ts +10 -0
  119. package/dist/cli/transfer.js +438 -0
  120. package/dist/cli/usage.d.ts +85 -0
  121. package/dist/cli/usage.js +741 -0
  122. package/dist/cli.d.ts +319 -13
  123. package/dist/cli.js +436 -8580
  124. package/dist/client.js +15 -8
  125. package/dist/compaction-record.js +12 -9
  126. package/dist/config.js +12 -11
  127. package/dist/connectors/github/backfill.js +94 -87
  128. package/dist/connectors/github/cli-impl.js +5 -3
  129. package/dist/connectors/github/dlq.js +67 -54
  130. package/dist/connectors/github/ingest.js +34 -35
  131. package/dist/connectors/github/tenant-routing.js +3 -2
  132. package/dist/connectors/github/webhook.js +135 -216
  133. package/dist/connectors/slack/dlq.js +49 -61
  134. package/dist/connectors/slack/ingest.js +55 -48
  135. package/dist/connectors/slack/tenant-routing.js +4 -3
  136. package/dist/connectors/slack/webhook.js +72 -74
  137. package/dist/consolidate/conflicts.d.ts +10 -0
  138. package/dist/consolidate/conflicts.js +178 -0
  139. package/dist/consolidate/decay.d.ts +12 -0
  140. package/dist/consolidate/decay.js +145 -0
  141. package/dist/consolidate/llm-passes.d.ts +3 -0
  142. package/dist/consolidate/llm-passes.js +141 -0
  143. package/dist/consolidate/merge.d.ts +7 -0
  144. package/dist/consolidate/merge.js +251 -0
  145. package/dist/consolidate/physics-pass.d.ts +3 -0
  146. package/dist/consolidate/physics-pass.js +60 -0
  147. package/dist/consolidate/run.d.ts +69 -0
  148. package/dist/consolidate/run.js +76 -0
  149. package/dist/consolidate/sleep.d.ts +18 -0
  150. package/dist/consolidate/sleep.js +209 -0
  151. package/dist/consolidate/traces.d.ts +4 -0
  152. package/dist/consolidate/traces.js +178 -0
  153. package/dist/context-auto.js +7 -11
  154. package/dist/context-render.d.ts +1 -1
  155. package/dist/context-render.js +1 -1
  156. package/dist/customer-notes.d.ts +3 -0
  157. package/dist/customer-notes.js +6 -4
  158. package/dist/dag.js +13 -12
  159. package/dist/dashboard-actions.d.ts +20 -0
  160. package/dist/dashboard-actions.js +88 -0
  161. package/dist/dashboard-params.d.ts +45 -0
  162. package/dist/dashboard-params.js +127 -0
  163. package/dist/dashboard-queries.d.ts +15 -0
  164. package/dist/dashboard-queries.js +355 -0
  165. package/dist/dashboard-snapshot.d.ts +138 -0
  166. package/dist/dashboard-snapshot.js +308 -0
  167. package/dist/dashboard-types.d.ts +163 -0
  168. package/dist/dashboard-types.js +3 -0
  169. package/dist/dashboard.d.ts +6 -7
  170. package/dist/dashboard.js +231 -203
  171. package/dist/db/busy.d.ts +5 -0
  172. package/dist/db/busy.js +24 -0
  173. package/dist/db/continuity.d.ts +5 -0
  174. package/dist/db/continuity.js +145 -0
  175. package/dist/db/meta.d.ts +8 -0
  176. package/dist/db/meta.js +35 -0
  177. package/dist/db/migrate.d.ts +9 -0
  178. package/dist/db/migrate.js +138 -0
  179. package/dist/db/migrations/index.d.ts +5 -0
  180. package/dist/db/migrations/index.js +109 -0
  181. package/dist/db/migrations/types.d.ts +14 -0
  182. package/dist/db/migrations/types.js +2 -0
  183. package/dist/db/migrations/v01.d.ts +3 -0
  184. package/dist/db/migrations/v01.js +38 -0
  185. package/dist/db/migrations/v02.d.ts +3 -0
  186. package/dist/db/migrations/v02.js +21 -0
  187. package/dist/db/migrations/v03.d.ts +3 -0
  188. package/dist/db/migrations/v03.js +22 -0
  189. package/dist/db/migrations/v04.d.ts +3 -0
  190. package/dist/db/migrations/v04.js +28 -0
  191. package/dist/db/migrations/v05.d.ts +3 -0
  192. package/dist/db/migrations/v05.js +21 -0
  193. package/dist/db/migrations/v06.d.ts +3 -0
  194. package/dist/db/migrations/v06.js +25 -0
  195. package/dist/db/migrations/v07.d.ts +3 -0
  196. package/dist/db/migrations/v07.js +13 -0
  197. package/dist/db/migrations/v08.d.ts +3 -0
  198. package/dist/db/migrations/v08.js +8 -0
  199. package/dist/db/migrations/v09.d.ts +3 -0
  200. package/dist/db/migrations/v09.js +13 -0
  201. package/dist/db/migrations/v10.d.ts +3 -0
  202. package/dist/db/migrations/v10.js +17 -0
  203. package/dist/db/migrations/v11.d.ts +3 -0
  204. package/dist/db/migrations/v11.js +15 -0
  205. package/dist/db/migrations/v12.d.ts +3 -0
  206. package/dist/db/migrations/v12.js +11 -0
  207. package/dist/db/migrations/v13.d.ts +3 -0
  208. package/dist/db/migrations/v13.js +15 -0
  209. package/dist/db/migrations/v14.d.ts +3 -0
  210. package/dist/db/migrations/v14.js +66 -0
  211. package/dist/db/migrations/v15.d.ts +3 -0
  212. package/dist/db/migrations/v15.js +42 -0
  213. package/dist/db/migrations/v16.d.ts +3 -0
  214. package/dist/db/migrations/v16.js +61 -0
  215. package/dist/db/migrations/v17.d.ts +3 -0
  216. package/dist/db/migrations/v17.js +46 -0
  217. package/dist/db/migrations/v18.d.ts +3 -0
  218. package/dist/db/migrations/v18.js +60 -0
  219. package/dist/db/migrations/v19.d.ts +3 -0
  220. package/dist/db/migrations/v19.js +28 -0
  221. package/dist/db/migrations/v20.d.ts +3 -0
  222. package/dist/db/migrations/v20.js +42 -0
  223. package/dist/db/migrations/v21.d.ts +3 -0
  224. package/dist/db/migrations/v21.js +16 -0
  225. package/dist/db/migrations/v22.d.ts +3 -0
  226. package/dist/db/migrations/v22.js +82 -0
  227. package/dist/db/migrations/v23.d.ts +3 -0
  228. package/dist/db/migrations/v23.js +48 -0
  229. package/dist/db/migrations/v24.d.ts +3 -0
  230. package/dist/db/migrations/v24.js +72 -0
  231. package/dist/db/migrations/v25.d.ts +3 -0
  232. package/dist/db/migrations/v25.js +46 -0
  233. package/dist/db/migrations/v26.d.ts +3 -0
  234. package/dist/db/migrations/v26.js +23 -0
  235. package/dist/db/migrations/v27.d.ts +3 -0
  236. package/dist/db/migrations/v27.js +57 -0
  237. package/dist/db/migrations/v28.d.ts +3 -0
  238. package/dist/db/migrations/v28.js +38 -0
  239. package/dist/db/migrations/v29.d.ts +3 -0
  240. package/dist/db/migrations/v29.js +78 -0
  241. package/dist/db/migrations/v30.d.ts +3 -0
  242. package/dist/db/migrations/v30.js +92 -0
  243. package/dist/db/migrations/v31.d.ts +3 -0
  244. package/dist/db/migrations/v31.js +74 -0
  245. package/dist/db/migrations/v32.d.ts +3 -0
  246. package/dist/db/migrations/v32.js +102 -0
  247. package/dist/db/migrations/v33.d.ts +3 -0
  248. package/dist/db/migrations/v33.js +104 -0
  249. package/dist/db/migrations/v34.d.ts +3 -0
  250. package/dist/db/migrations/v34.js +93 -0
  251. package/dist/db/migrations/v35.d.ts +3 -0
  252. package/dist/db/migrations/v35.js +98 -0
  253. package/dist/db/migrations/v36.d.ts +3 -0
  254. package/dist/db/migrations/v36.js +98 -0
  255. package/dist/db/migrations/v37.d.ts +3 -0
  256. package/dist/db/migrations/v37.js +219 -0
  257. package/dist/db/migrations/v38.d.ts +3 -0
  258. package/dist/db/migrations/v38.js +277 -0
  259. package/dist/db/migrations/v39.d.ts +3 -0
  260. package/dist/db/migrations/v39.js +59 -0
  261. package/dist/db/migrations/v40.d.ts +3 -0
  262. package/dist/db/migrations/v40.js +74 -0
  263. package/dist/db/migrations/v41.d.ts +3 -0
  264. package/dist/db/migrations/v41.js +43 -0
  265. package/dist/db/migrations/v42.d.ts +3 -0
  266. package/dist/db/migrations/v42.js +41 -0
  267. package/dist/db/migrations/v43.d.ts +3 -0
  268. package/dist/db/migrations/v43.js +67 -0
  269. package/dist/db/migrations/v44.d.ts +3 -0
  270. package/dist/db/migrations/v44.js +28 -0
  271. package/dist/db/migrations/v45.d.ts +3 -0
  272. package/dist/db/migrations/v45.js +30 -0
  273. package/dist/db/migrations/v46.d.ts +3 -0
  274. package/dist/db/migrations/v46.js +25 -0
  275. package/dist/db/migrations/v47.d.ts +3 -0
  276. package/dist/db/migrations/v47.js +17 -0
  277. package/dist/db/migrations/v48.d.ts +3 -0
  278. package/dist/db/migrations/v48.js +10 -0
  279. package/dist/db/migrations/v49.d.ts +3 -0
  280. package/dist/db/migrations/v49.js +31 -0
  281. package/dist/db/migrations/v50.d.ts +3 -0
  282. package/dist/db/migrations/v50.js +67 -0
  283. package/dist/db/migrations/v51.d.ts +3 -0
  284. package/dist/db/migrations/v51.js +14 -0
  285. package/dist/db/migrations/v52.d.ts +3 -0
  286. package/dist/db/migrations/v52.js +7 -0
  287. package/dist/db/open.d.ts +23 -0
  288. package/dist/db/open.js +146 -0
  289. package/dist/db/sqlite.d.ts +21 -0
  290. package/dist/db/sqlite.js +8 -0
  291. package/dist/db/tables.d.ts +7 -0
  292. package/dist/db/tables.js +38 -0
  293. package/dist/db.d.ts +6 -46
  294. package/dist/db.js +5 -3036
  295. package/dist/decisions.d.ts +4 -1
  296. package/dist/decisions.js +9 -7
  297. package/dist/dedupe.js +3 -2
  298. package/dist/delivery-recorder.js +5 -1
  299. package/dist/doctor.js +4 -3
  300. package/dist/dormant.js +1 -0
  301. package/dist/embedding-provider.d.ts +1 -1
  302. package/dist/embedding-provider.js +7 -5
  303. package/dist/embeddings.d.ts +9 -52
  304. package/dist/embeddings.js +47 -298
  305. package/dist/env.d.ts +75 -0
  306. package/dist/env.js +119 -0
  307. package/dist/eval-suite.js +1 -1
  308. package/dist/eval.js +2 -2
  309. package/dist/extract.js +5 -4
  310. package/dist/gated-write.js +3 -1
  311. package/dist/goals.d.ts +3 -1
  312. package/dist/goals.js +18 -0
  313. package/dist/graph/read.d.ts +73 -0
  314. package/dist/graph/read.js +325 -0
  315. package/dist/graph/rows.d.ts +45 -0
  316. package/dist/graph/rows.js +51 -0
  317. package/dist/graph/types.d.ts +83 -0
  318. package/dist/graph/types.js +11 -0
  319. package/dist/graph/write.d.ts +93 -0
  320. package/dist/{graph.js → graph/write.js} +8 -391
  321. package/dist/graph-extract.js +2 -1
  322. package/dist/graph-recall.d.ts +1 -1
  323. package/dist/graph-recall.js +2 -2
  324. package/dist/graph-stream.js +1 -1
  325. package/dist/graph-view.d.ts +1 -1
  326. package/dist/graph-view.js +1 -1
  327. package/dist/half-life-migration.d.ts +1 -1
  328. package/dist/half-life-migration.js +2 -1
  329. package/dist/handoff.js +3 -0
  330. package/dist/hooks/codex-session.d.ts +8 -0
  331. package/dist/hooks/codex-session.js +76 -0
  332. package/dist/hooks/codex-wrapper.d.ts +55 -0
  333. package/dist/hooks/codex-wrapper.js +288 -0
  334. package/dist/hooks/json-hooks.d.ts +63 -0
  335. package/dist/hooks/json-hooks.js +356 -0
  336. package/dist/hooks/opencode.d.ts +50 -0
  337. package/dist/hooks/opencode.js +202 -0
  338. package/dist/hooks/shared.d.ts +54 -0
  339. package/dist/hooks/shared.js +77 -0
  340. package/dist/http-retry.d.ts +2 -0
  341. package/dist/http-retry.js +4 -3
  342. package/dist/http-util.d.ts +3 -0
  343. package/dist/http-util.js +10 -0
  344. package/dist/{importers.d.ts → importers/core.d.ts} +13 -17
  345. package/dist/importers/core.js +141 -0
  346. package/dist/importers/markdown-parse.d.ts +41 -0
  347. package/dist/importers/markdown-parse.js +132 -0
  348. package/dist/importers/markdown.d.ts +3 -0
  349. package/dist/importers/markdown.js +92 -0
  350. package/dist/importers/sources.d.ts +7 -0
  351. package/dist/importers/sources.js +229 -0
  352. package/dist/importers/vault.d.ts +11 -0
  353. package/dist/importers/vault.js +352 -0
  354. package/dist/incidents.d.ts +3 -0
  355. package/dist/incidents.js +8 -5
  356. package/dist/index.d.ts +25 -6
  357. package/dist/index.js +23 -6
  358. package/dist/invalidation.js +2 -1
  359. package/dist/judgment.js +7 -3
  360. package/dist/keyset.d.ts +13 -0
  361. package/dist/keyset.js +8 -0
  362. package/dist/local-embedding.d.ts +13 -0
  363. package/dist/local-embedding.js +165 -0
  364. package/dist/log.d.ts +7 -0
  365. package/dist/log.js +19 -1
  366. package/dist/mcp/admin-tools.d.ts +8 -0
  367. package/dist/mcp/admin-tools.js +116 -0
  368. package/dist/mcp/format.d.ts +27 -0
  369. package/dist/mcp/format.js +135 -0
  370. package/dist/mcp/memory-tools.d.ts +5 -0
  371. package/dist/mcp/memory-tools.js +83 -0
  372. package/dist/mcp/protocol.d.ts +83 -0
  373. package/dist/mcp/protocol.js +55 -0
  374. package/dist/mcp/recall-tools.d.ts +6 -0
  375. package/dist/mcp/recall-tools.js +320 -0
  376. package/dist/mcp/request.d.ts +10 -0
  377. package/dist/mcp/request.js +163 -0
  378. package/dist/mcp/server.d.ts +4 -70
  379. package/dist/mcp/server.js +8 -1172
  380. package/dist/mcp/session-state.d.ts +11 -0
  381. package/dist/mcp/session-state.js +28 -0
  382. package/dist/mcp/stdio.d.ts +8 -0
  383. package/dist/mcp/stdio.js +79 -0
  384. package/dist/mcp/tools.d.ts +11 -0
  385. package/dist/mcp/tools.js +247 -0
  386. package/dist/memory.d.ts +8 -3
  387. package/dist/memory.js +27 -1
  388. package/dist/multihop.d.ts +1 -1
  389. package/dist/multihop.js +2 -1
  390. package/dist/owner-validation.js +2 -1
  391. package/dist/physics-state.js +10 -7
  392. package/dist/policies.d.ts +3 -0
  393. package/dist/policies.js +8 -6
  394. package/dist/postinstall.js +3 -2
  395. package/dist/predictions/planning-fallacy.d.ts +100 -0
  396. package/dist/predictions/planning-fallacy.js +190 -0
  397. package/dist/{predictions.d.ts → predictions/store.d.ts} +7 -102
  398. package/dist/predictions/store.js +434 -0
  399. package/dist/processes.d.ts +3 -0
  400. package/dist/processes.js +8 -5
  401. package/dist/project-briefs.d.ts +3 -0
  402. package/dist/project-briefs.js +7 -5
  403. package/dist/project-identity.d.ts +1 -1
  404. package/dist/project-identity.js +12 -6
  405. package/dist/project-merge.js +3 -1
  406. package/dist/quarantine.d.ts +2 -1
  407. package/dist/quarantine.js +8 -5
  408. package/dist/raw-archive-mirror-cleanup.js +2 -1
  409. package/dist/raw-archive.js +1 -1
  410. package/dist/recall-history.js +3 -2
  411. package/dist/recall-pipeline.d.ts +2 -2
  412. package/dist/recall-pipeline.js +16 -8
  413. package/dist/recall-scope.js +1 -1
  414. package/dist/recall-trace.d.ts +3 -3
  415. package/dist/recall-trace.js +10 -14
  416. package/dist/refine-llm.js +20 -11
  417. package/dist/reject-flow.js +6 -1
  418. package/dist/rerankers/clef.d.ts +2 -2
  419. package/dist/rerankers/clef.js +72 -30
  420. package/dist/rerankers/cross-encoder.js +6 -4
  421. package/dist/rerankers/jev.d.ts +4 -2
  422. package/dist/rerankers/jev.js +24 -19
  423. package/dist/rerankers/llm.d.ts +4 -2
  424. package/dist/rerankers/llm.js +61 -41
  425. package/dist/rerankers/types.d.ts +1 -1
  426. package/dist/salience.js +1 -1
  427. package/dist/same-text.d.ts +2 -0
  428. package/dist/same-text.js +4 -0
  429. package/dist/scheduler.d.ts +1 -0
  430. package/dist/scheduler.js +26 -3
  431. package/dist/scope.js +4 -3
  432. package/dist/search/as-of.d.ts +10 -0
  433. package/dist/search/as-of.js +22 -0
  434. package/dist/search/bm25-search.d.ts +14 -0
  435. package/dist/search/bm25-search.js +43 -0
  436. package/dist/search/bm25.d.ts +15 -0
  437. package/dist/search/bm25.js +54 -0
  438. package/dist/search/boosts.d.ts +54 -0
  439. package/dist/search/boosts.js +94 -0
  440. package/dist/search/breakdown.d.ts +7 -0
  441. package/dist/search/breakdown.js +20 -0
  442. package/dist/search/explain.d.ts +25 -0
  443. package/dist/search/explain.js +31 -0
  444. package/dist/search/finalize.d.ts +8 -0
  445. package/dist/search/finalize.js +52 -0
  446. package/dist/search/fusion.d.ts +27 -0
  447. package/dist/search/fusion.js +42 -0
  448. package/dist/search/hybrid-score.d.ts +20 -0
  449. package/dist/search/hybrid-score.js +73 -0
  450. package/dist/search/hybrid.d.ts +46 -0
  451. package/dist/search/hybrid.js +64 -0
  452. package/dist/search/physics-search.d.ts +29 -0
  453. package/dist/search/physics-search.js +162 -0
  454. package/dist/search/rerank.d.ts +10 -0
  455. package/dist/search/rerank.js +72 -0
  456. package/dist/search/temporal.d.ts +15 -0
  457. package/dist/search/temporal.js +45 -0
  458. package/dist/search/types.d.ts +91 -0
  459. package/dist/search/types.js +2 -0
  460. package/dist/search/vector.d.ts +30 -0
  461. package/dist/search/vector.js +71 -0
  462. package/dist/secret-detect.d.ts +2 -0
  463. package/dist/secret-detect.js +3 -1
  464. package/dist/server/auth.d.ts +52 -0
  465. package/dist/server/auth.js +221 -0
  466. package/dist/server/client-ip.d.ts +25 -0
  467. package/dist/server/client-ip.js +92 -0
  468. package/dist/server/cursor.d.ts +23 -0
  469. package/dist/server/cursor.js +58 -0
  470. package/dist/server/lifecycle.d.ts +7 -0
  471. package/dist/server/lifecycle.js +29 -0
  472. package/dist/server/mcp-http.d.ts +5 -0
  473. package/dist/server/mcp-http.js +199 -0
  474. package/dist/server/request.d.ts +33 -0
  475. package/dist/server/request.js +103 -0
  476. package/dist/server/routes/admin.d.ts +9 -0
  477. package/dist/server/routes/admin.js +158 -0
  478. package/dist/server/routes/customer-notes.d.ts +7 -0
  479. package/dist/server/routes/customer-notes.js +112 -0
  480. package/dist/server/routes/decisions.d.ts +7 -0
  481. package/dist/server/routes/decisions.js +133 -0
  482. package/dist/server/routes/incidents.d.ts +7 -0
  483. package/dist/server/routes/incidents.js +126 -0
  484. package/dist/server/routes/memories.d.ts +10 -0
  485. package/dist/server/routes/memories.js +179 -0
  486. package/dist/server/routes/policies.d.ts +8 -0
  487. package/dist/server/routes/policies.js +151 -0
  488. package/dist/server/routes/predictions.d.ts +7 -0
  489. package/dist/server/routes/predictions.js +164 -0
  490. package/dist/server/routes/processes.d.ts +7 -0
  491. package/dist/server/routes/processes.js +161 -0
  492. package/dist/server/routes/project-briefs.d.ts +8 -0
  493. package/dist/server/routes/project-briefs.js +136 -0
  494. package/dist/server/routes/recall.d.ts +8 -0
  495. package/dist/server/routes/recall.js +340 -0
  496. package/dist/server/routes/skills.d.ts +8 -0
  497. package/dist/server/routes/skills.js +150 -0
  498. package/dist/server/types.d.ts +56 -0
  499. package/dist/server/types.js +2 -0
  500. package/dist/server/validation.d.ts +14 -0
  501. package/dist/server/validation.js +91 -0
  502. package/dist/server.d.ts +7 -61
  503. package/dist/server.js +92 -2368
  504. package/dist/session-digest.d.ts +1 -1
  505. package/dist/session-digest.js +9 -2
  506. package/dist/shared.d.ts +3 -1
  507. package/dist/shared.js +46 -40
  508. package/dist/skills.d.ts +3 -0
  509. package/dist/skills.js +7 -5
  510. package/dist/stdin.js +3 -2
  511. package/dist/store/audit-event.d.ts +19 -0
  512. package/dist/store/audit-event.js +33 -0
  513. package/dist/store/candidates.d.ts +42 -0
  514. package/dist/store/candidates.js +152 -0
  515. package/dist/store/conflicts.d.ts +44 -0
  516. package/dist/store/conflicts.js +444 -0
  517. package/dist/store/delete-and-batch.d.ts +63 -0
  518. package/dist/store/delete-and-batch.js +310 -0
  519. package/dist/store/entry-reads.d.ts +92 -0
  520. package/dist/store/entry-reads.js +255 -0
  521. package/dist/store/entry-row.d.ts +67 -0
  522. package/dist/store/entry-row.js +208 -0
  523. package/dist/store/entry-writes.d.ts +46 -0
  524. package/dist/store/entry-writes.js +148 -0
  525. package/dist/store/handoffs.d.ts +26 -0
  526. package/dist/store/handoffs.js +184 -0
  527. package/dist/store/index-and-stats.d.ts +52 -0
  528. package/dist/store/index-and-stats.js +214 -0
  529. package/dist/store/markdown.d.ts +10 -0
  530. package/dist/store/markdown.js +108 -0
  531. package/dist/store/mirrors.d.ts +49 -0
  532. package/dist/store/mirrors.js +312 -0
  533. package/dist/store/open.d.ts +15 -0
  534. package/dist/store/open.js +223 -0
  535. package/dist/store/rows.d.ts +178 -0
  536. package/dist/store/rows.js +158 -0
  537. package/dist/store/search-rows.d.ts +86 -0
  538. package/dist/store/search-rows.js +254 -0
  539. package/dist/store/sessions.d.ts +83 -0
  540. package/dist/store/sessions.js +272 -0
  541. package/dist/store/summaries.d.ts +94 -0
  542. package/dist/store/summaries.js +377 -0
  543. package/dist/store/tenant-lookup.d.ts +12 -0
  544. package/dist/store/tenant-lookup.js +16 -0
  545. package/dist/store-cards.js +2 -1
  546. package/dist/summary-dirty.d.ts +4 -0
  547. package/dist/summary-dirty.js +32 -0
  548. package/dist/support-bundle.js +4 -3
  549. package/dist/tenant.js +2 -2
  550. package/dist/token-ledger.js +1 -0
  551. package/dist/tokenize.d.ts +2 -0
  552. package/dist/tokenize.js +16 -0
  553. package/dist/transcript-tail.d.ts +7 -0
  554. package/dist/transcript-tail.js +48 -0
  555. package/dist/vector-store.d.ts +27 -0
  556. package/dist/vector-store.js +210 -0
  557. package/dist/version.d.ts +2 -2
  558. package/dist/version.js +2 -2
  559. package/dist/working-memory.js +1 -1
  560. package/dist/yaml.js +36 -11
  561. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
  562. package/dist-ui/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  563. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
  564. package/dist-ui/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  565. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  566. package/dist-ui/assets/ibm-plex-mono-latin-600-normal-DWFSQ4vo.woff +0 -0
  567. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 +0 -0
  568. package/dist-ui/assets/ibm-plex-sans-latin-400-normal-CYLoc0-x.woff +0 -0
  569. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 +0 -0
  570. package/dist-ui/assets/ibm-plex-sans-latin-500-normal-BgVn5rGT.woff +0 -0
  571. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-Cu4Hd6ag.woff +0 -0
  572. package/dist-ui/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 +0 -0
  573. package/dist-ui/assets/index-DPN7cP19.js +33 -0
  574. package/dist-ui/assets/index-dFloKRVr.css +1 -0
  575. package/dist-ui/index.html +3 -25
  576. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  577. package/extensions/openclaw-plugin/package.json +1 -1
  578. package/openclaw.plugin.json +1 -1
  579. package/package.json +2 -1
  580. package/dist/capture.d.ts +0 -155
  581. package/dist/capture.js +0 -1293
  582. package/dist/consolidate.d.ts +0 -58
  583. package/dist/consolidate.js +0 -1123
  584. package/dist/graph.d.ts +0 -245
  585. package/dist/hooks.d.ts +0 -208
  586. package/dist/hooks.js +0 -1073
  587. package/dist/importers.js +0 -897
  588. package/dist/predictions.js +0 -620
  589. package/dist/search.d.ts +0 -320
  590. package/dist/search.js +0 -968
  591. package/dist/store.d.ts +0 -744
  592. package/dist/store.js +0 -3372
  593. package/dist-ui/assets/d3-BiWEKnn4.js +0 -1
  594. package/dist-ui/assets/index-BhT8RvO6.js +0 -61
  595. package/dist-ui/assets/index-RoXXJ5dq.css +0 -1
  596. package/dist-ui/assets/three-BDgTxR1l.js +0 -4112
package/dist/client.js CHANGED
@@ -13,8 +13,19 @@
13
13
  * Network errors (ECONNREFUSED on a stale pidfile, etc.) propagate as the
14
14
  * native fetch failure so the caller can detect them and self-heal.
15
15
  */
16
+ import { fetchWithRetry } from './http-retry.js';
16
17
  /** A write the local server has not answered in this long is stuck; the caller treats it as delivery-unknown. */
17
18
  const SERVER_TIMEOUT_MS = 30_000;
19
+ /** Five tries at the server's 1 s Retry-After keeps the roughly 5 s wait the CLI had before the server answered busy with 503. */
20
+ const STORE_BUSY_ATTEMPTS = 5;
21
+ /** The server sets Retry-After on a 503 only for a held write lock (server.ts replyFor); the auth-provider 503 has none. */
22
+ function isStoreBusy(res) {
23
+ return res.status === 503 && res.headers.has('retry-after');
24
+ }
25
+ /** Replaying is safe because each routed write commits in one transaction and anything after it is best-effort, so a busy 503 means nothing landed. */
26
+ function sendWrite(url, init) {
27
+ return fetchWithRetry(url, init, { timeoutMs: SERVER_TIMEOUT_MS, attempts: STORE_BUSY_ATTEMPTS, retryOn: isStoreBusy });
28
+ }
18
29
  function buildHeaders(apiKey, withBody) {
19
30
  const headers = {};
20
31
  if (withBody)
@@ -57,10 +68,9 @@ async function throwForStatus(res) {
57
68
  throw new HttpResponseError(message, res.status);
58
69
  }
59
70
  export async function remember(serverUrl, apiKey, opts) {
60
- const res = await fetch(`${serverUrl}/v1/memories`, {
71
+ const res = await sendWrite(`${serverUrl}/v1/memories`, {
61
72
  method: 'POST',
62
73
  headers: buildHeaders(apiKey, true),
63
- signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
64
74
  body: JSON.stringify(opts),
65
75
  });
66
76
  if (!res.ok)
@@ -69,10 +79,9 @@ export async function remember(serverUrl, apiKey, opts) {
69
79
  return result;
70
80
  }
71
81
  export async function forget(serverUrl, apiKey, id) {
72
- const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(id)}`, {
82
+ const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}`, {
73
83
  method: 'DELETE',
74
84
  headers: buildHeaders(apiKey, false),
75
- signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
76
85
  });
77
86
  if (!res.ok)
78
87
  await throwForStatus(res);
@@ -80,10 +89,9 @@ export async function forget(serverUrl, apiKey, id) {
80
89
  return result;
81
90
  }
82
91
  export async function promote(serverUrl, apiKey, id) {
83
- const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/promote`, {
92
+ const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/promote`, {
84
93
  method: 'POST',
85
94
  headers: buildHeaders(apiKey, false),
86
- signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
87
95
  });
88
96
  if (!res.ok)
89
97
  await throwForStatus(res);
@@ -91,10 +99,9 @@ export async function promote(serverUrl, apiKey, id) {
91
99
  return result;
92
100
  }
93
101
  export async function archiveRaw(serverUrl, apiKey, id, reason) {
94
- const res = await fetch(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/archive`, {
102
+ const res = await sendWrite(`${serverUrl}/v1/memories/${encodeURIComponent(id)}/archive`, {
95
103
  method: 'POST',
96
104
  headers: buildHeaders(apiKey, true),
97
- signal: AbortSignal.timeout(SERVER_TIMEOUT_MS),
98
105
  body: JSON.stringify({ reason }),
99
106
  });
100
107
  if (!res.ok)
@@ -1,7 +1,6 @@
1
1
  // One record per Claude Code compaction, and what turns its summary into kept memories.
2
2
  import * as fs from 'fs';
3
3
  import * as path from 'path';
4
- import { errorMessage, readTranscriptTail, truncateCodePointSafe } from './capture.js';
5
4
  import { isObjectLike, isStringValue } from './capture-contract.js';
6
5
  import { compactSummaryBody, parseCompactionItems, selectItemRows } from './compaction-items.js';
7
6
  import { loadConfig } from './config.js';
@@ -10,8 +9,12 @@ import { gatedWrite } from './gated-write.js';
10
9
  import { COMPACTION_MEMORY_TAG, COMPACTION_SOURCE_PREFIX, Layer, createMemory, generateId } from './memory.js';
11
10
  import { deriveOriginProject, isGlobalStoreRoot } from './project-identity.js';
12
11
  import { maskEmails, redactSecretsStrict } from './secret-detect.js';
13
- import { strengthenRetrievedOn, updateStats, writeEntryMirrors } from './store.js';
12
+ import { strengthenRetrievedOn, writeEntryMirrors } from './store/entry-writes.js';
13
+ import { isRecallBoostAblated } from './ablation.js';
14
+ import { updateStats } from './store/index-and-stats.js';
14
15
  import { resolveTenantId } from './tenant.js';
16
+ import { errorMessage, log as logger } from './log.js';
17
+ import { readTranscriptTail, truncateCodePointSafe } from './transcript-tail.js';
15
18
  /** PostCompact has 10 s in all (PreCompact 30 s), so a locked store must be given up on early. */
16
19
  export const COMPACTION_DB_WAIT_MS = 2000;
17
20
  /** Tested verbatim: Claude Code hands PreCompact stdout to the summariser as instructions. */
@@ -225,7 +228,7 @@ export function saveItems(db, hippoRoot, ctx, log) {
225
228
  }
226
229
  }
227
230
  // Said again by another session is the same signal as being recalled; the same session carrying it forward is not.
228
- strengthenRetrievedOn(db, [...restated], ctx.tenantId);
231
+ strengthenRetrievedOn(db, [...restated], { tenantId: ctx.tenantId, recallBoostAblated: isRecallBoostAblated() });
229
232
  if (ctx.recordId !== null) {
230
233
  db.prepare(`UPDATE compactions SET items_written = ?, status = 'done' WHERE tenant_id = ? AND id = ?`).run(written.length, ctx.tenantId, ctx.recordId);
231
234
  }
@@ -262,7 +265,7 @@ export function parsePostCompactPayload(stdinText) {
262
265
  raw = JSON.parse((stdinText ?? '').trim());
263
266
  }
264
267
  catch {
265
- return null;
268
+ return null; // non-JSON stdin is not a PostCompact payload; the caller skips it
266
269
  }
267
270
  if (!isObjectLike(raw) || !('session_id' in raw) || !isStringValue(raw.session_id) || raw.session_id === '')
268
271
  return null;
@@ -309,7 +312,7 @@ export function saveCompaction(hippoRoot, payload, log) {
309
312
  if (isSqliteBusy(err))
310
313
  throw err;
311
314
  log(`record step failed: ${errorMessage(err)}`);
312
- console.error(`hippo post-compact: record step failed: ${errorMessage(err)}`);
315
+ logger.error(`post-compact: record step failed: ${errorMessage(err)}`);
313
316
  }
314
317
  try {
315
318
  result.written = saveItems(db, hippoRoot, {
@@ -337,12 +340,12 @@ export function saveCompaction(hippoRoot, payload, log) {
337
340
  }
338
341
  catch (spoolErr) {
339
342
  log(`spool failed: ${errorMessage(spoolErr)}`);
340
- console.error(`hippo post-compact: spool failed: ${errorMessage(spoolErr)}`);
343
+ logger.error(`post-compact: spool failed: ${errorMessage(spoolErr)}`);
341
344
  }
342
345
  }
343
346
  else {
344
347
  log(`items step failed: ${errorMessage(err)}`);
345
- console.error(`hippo post-compact: items step failed: ${errorMessage(err)}`);
348
+ logger.error(`post-compact: items step failed: ${errorMessage(err)}`);
346
349
  }
347
350
  }
348
351
  finally {
@@ -380,7 +383,7 @@ function transcriptSummary(transcriptPath, afterMs, beforeMs) {
380
383
  lines.push(JSON.parse(raw));
381
384
  }
382
385
  catch {
383
- continue;
386
+ continue; // the tail can start mid-line; a torn line holds no summary
384
387
  }
385
388
  }
386
389
  const stamp = (line) => (isStringValue(line.timestamp) ? Date.parse(line.timestamp) : Number.NaN);
@@ -409,7 +412,7 @@ function readSpooled(file, fallbackTenantId) {
409
412
  raw = JSON.parse(fs.readFileSync(file, 'utf8'));
410
413
  }
411
414
  catch {
412
- return null;
415
+ return null; // a half-written or vanished spool file is skipped; the caller treats null as unreadable
413
416
  }
414
417
  if (!isObjectLike(raw) || !('sessionId' in raw) || !isStringValue(raw.sessionId) || !('summary' in raw) || !isStringValue(raw.summary))
415
418
  return null;
package/dist/config.js CHANGED
@@ -5,6 +5,7 @@ import * as fs from 'fs';
5
5
  import * as path from 'path';
6
6
  import { DEFAULT_PHYSICS_CONFIG, mergePhysicsConfig } from './physics-config.js';
7
7
  import { DEFAULT_HALF_LIFE_DAYS } from './memory.js';
8
+ import { log } from './log.js';
8
9
  const DEFAULT_CONFIG = {
9
10
  defaultHalfLifeDays: DEFAULT_HALF_LIFE_DAYS,
10
11
  defaultBudget: 4000,
@@ -114,7 +115,7 @@ function deliveryLedgerEnabled(value) {
114
115
  return enabled;
115
116
  if (isObject && enabled === undefined)
116
117
  return false;
117
- console.error(`Warning: config.json's "deliveryLedger" must be an object like {"enabled": true} ` +
118
+ log.warn(`config.json's "deliveryLedger" must be an object like {"enabled": true} ` +
118
119
  `(got ${JSON.stringify(value)}) - using false.`);
119
120
  return false;
120
121
  }
@@ -127,7 +128,7 @@ function pilotHoldoutRate(value) {
127
128
  return 0;
128
129
  if (Number.isInteger(rate) && rate >= 0 && rate <= 10000)
129
130
  return rate;
130
- console.error(`Warning: config.json's "pilot" must be an object like {"holdoutRateBp": 2000}, an integer from 0 to 10000 ` +
131
+ log.warn(`config.json's "pilot" must be an object like {"holdoutRateBp": 2000}, an integer from 0 to 10000 ` +
131
132
  `(got ${JSON.stringify(value)}) - using 0 (pilot off).`);
132
133
  return 0;
133
134
  }
@@ -136,7 +137,7 @@ function agentMemoryTools(value) {
136
137
  return null;
137
138
  if (Array.isArray(value) && value.every((t) => String(t) === t))
138
139
  return value;
139
- console.error(`Warning: config.json's "agentMemories.tools" must be a list of tool ids like ["claude-code", "codex"] ` +
140
+ log.warn(`config.json's "agentMemories.tools" must be a list of tool ids like ["claude-code", "codex"] ` +
140
141
  `(got ${JSON.stringify(value)}) - importing none.`);
141
142
  return [];
142
143
  }
@@ -158,7 +159,7 @@ export function loadConfig(hippoRoot) {
158
159
  const memoryValueRaw = raw.memoryValue;
159
160
  const validMemoryValueConfig = memoryValueRaw === undefined || isMemoryValueConfig(memoryValueRaw);
160
161
  if (!validMemoryValueConfig) {
161
- console.error(`Warning: config.json's "memoryValue" must be an object like {"enabled": true} ` +
162
+ log.warn(`config.json's "memoryValue" must be an object like {"enabled": true} ` +
162
163
  `(got ${JSON.stringify(memoryValueRaw)}) - using defaults.`);
163
164
  }
164
165
  const memoryValueOverride = memoryValueRaw !== undefined && isMemoryValueConfig(memoryValueRaw) ? memoryValueRaw : {};
@@ -167,20 +168,20 @@ export function loadConfig(hippoRoot) {
167
168
  // warns and falls back to the default, which keeps faded memories.
168
169
  const dormantRaw = raw.dormant;
169
170
  if (dormantRaw !== undefined && !isDormantConfig(dormantRaw)) {
170
- console.error(`Warning: config.json's "dormant" must be an object like {"enabled": false} ` +
171
+ log.warn(`config.json's "dormant" must be an object like {"enabled": false} ` +
171
172
  `(got ${JSON.stringify(dormantRaw)}) - using the default (faded memories kept dormant).`);
172
173
  }
173
174
  const dormantOverride = dormantRaw !== undefined && isDormantConfig(dormantRaw) ? dormantRaw : {};
174
175
  // Only a real boolean counts: {"enabled": "false"} is a truthy string.
175
176
  let dormantEnabled = dormantOverride.enabled ?? DEFAULT_CONFIG.dormant.enabled;
176
177
  if (dormantEnabled !== true && dormantEnabled !== false) {
177
- console.error(`Warning: config.json's "dormant.enabled" must be true or false ` +
178
+ log.warn(`config.json's "dormant.enabled" must be true or false ` +
178
179
  `(got ${JSON.stringify(dormantEnabled)}) - using the default (faded memories kept dormant).`);
179
180
  dormantEnabled = DEFAULT_CONFIG.dormant.enabled;
180
181
  }
181
182
  let dormantRetentionDays = dormantOverride.retentionDays ?? DEFAULT_CONFIG.dormant.retentionDays;
182
183
  if (!Number.isFinite(dormantRetentionDays) || dormantRetentionDays < 0) {
183
- console.error(`Warning: config.json's "dormant.retentionDays" must be a number of days, 0 or more ` +
184
+ log.warn(`config.json's "dormant.retentionDays" must be a number of days, 0 or more ` +
184
185
  `(got ${JSON.stringify(dormantRetentionDays)}) - using ${DEFAULT_CONFIG.dormant.retentionDays}.`);
185
186
  dormantRetentionDays = DEFAULT_CONFIG.dormant.retentionDays;
186
187
  }
@@ -188,21 +189,21 @@ export function loadConfig(hippoRoot) {
188
189
  const churnStalenessRaw = raw.churnStaleness;
189
190
  const validChurnStalenessConfig = churnStalenessRaw === undefined || isChurnStalenessConfig(churnStalenessRaw);
190
191
  if (!validChurnStalenessConfig) {
191
- console.error(`Warning: config.json's "churnStaleness" must be an object like {"enabled": true} ` +
192
+ log.warn(`config.json's "churnStaleness" must be an object like {"enabled": true} ` +
192
193
  `(got ${JSON.stringify(churnStalenessRaw)}) - using defaults.`);
193
194
  }
194
195
  let churnStalenessEnabled = churnStalenessRaw !== undefined && isChurnStalenessConfig(churnStalenessRaw)
195
196
  ? churnStalenessRaw.enabled
196
197
  : DEFAULT_CONFIG.churnStaleness.enabled;
197
198
  if (churnStalenessEnabled !== true && churnStalenessEnabled !== false) {
198
- console.error(`Warning: config.json's "churnStaleness.enabled" must be true or false ` +
199
+ log.warn(`config.json's "churnStaleness.enabled" must be true or false ` +
199
200
  `(got ${JSON.stringify(churnStalenessEnabled)}) - using false.`);
200
201
  churnStalenessEnabled = false;
201
202
  }
202
203
  // Every writer starts a memory on this, and a zero or negative half-life scores zero strength, so sleep would retire it.
203
204
  let defaultHalfLifeDays = raw.defaultHalfLifeDays ?? DEFAULT_CONFIG.defaultHalfLifeDays;
204
205
  if (!Number.isFinite(defaultHalfLifeDays) || defaultHalfLifeDays <= 0) {
205
- console.error(`Warning: config.json's "defaultHalfLifeDays" must be a number of days above 0 ` +
206
+ log.warn(`config.json's "defaultHalfLifeDays" must be a number of days above 0 ` +
206
207
  `(got ${JSON.stringify(defaultHalfLifeDays)}) - using ${DEFAULT_CONFIG.defaultHalfLifeDays}.`);
207
208
  defaultHalfLifeDays = DEFAULT_CONFIG.defaultHalfLifeDays;
208
209
  }
@@ -247,7 +248,7 @@ export function loadConfig(hippoRoot) {
247
248
  }
248
249
  catch (err) {
249
250
  if (fs.existsSync(configPath)) {
250
- console.error(`Warning: failed to parse ${configPath}: ${err instanceof Error ? err.message : err}`);
251
+ log.warn(`failed to parse ${configPath}: ${err instanceof Error ? err.message : err}`);
251
252
  }
252
253
  return { ...DEFAULT_CONFIG };
253
254
  }
@@ -172,6 +172,82 @@ async function drainStream(ctx, url0, toIngestEvent, fetcher, token, sleep, maxI
172
172
  }
173
173
  return { ingested, pages, maxUpdatedAt, drained: true };
174
174
  }
175
+ function issueItemToEvent(item, repository) {
176
+ if (!isIssuesItem(item))
177
+ return null;
178
+ // Codex P1 #2: /issues returns PRs too — skip them.
179
+ if (item.pull_request)
180
+ return null;
181
+ const payload = {
182
+ action: 'opened',
183
+ repository,
184
+ issue: {
185
+ number: item.number,
186
+ title: item.title,
187
+ body: item.body ?? null,
188
+ user: { login: item.user.login, id: item.user.id },
189
+ updated_at: item.updated_at,
190
+ },
191
+ };
192
+ return { eventName: 'issues', payload };
193
+ }
194
+ function issueCommentItemToEvent(item, repository) {
195
+ if (!isCommentItem(item))
196
+ return null;
197
+ // SAFETY: this closure only runs against the /issues/comments stream,
198
+ // so every item isCommentItem validates here is genuinely an
199
+ // IssueCommentItem; a missing issue_url is handled defensively below.
200
+ const c = item;
201
+ const issueNumber = parseTrailingNumber(c.issue_url);
202
+ if (issueNumber === null)
203
+ return null;
204
+ const payload = {
205
+ action: 'created',
206
+ repository,
207
+ issue: { number: issueNumber },
208
+ comment: {
209
+ id: c.id,
210
+ body: c.body ?? null,
211
+ user: { login: c.user.login, id: c.user.id },
212
+ updated_at: c.updated_at,
213
+ },
214
+ };
215
+ return { eventName: 'issue_comment', payload };
216
+ }
217
+ function prReviewCommentItemToEvent(item, repository) {
218
+ if (!isCommentItem(item))
219
+ return null;
220
+ // SAFETY: this closure only runs against the /pulls/comments stream,
221
+ // so every item isCommentItem validates here is genuinely a
222
+ // PrReviewCommentItem; a missing pull_request_url is handled below.
223
+ const c = item;
224
+ const prNumber = parseTrailingNumber(c.pull_request_url);
225
+ if (prNumber === null)
226
+ return null;
227
+ const payload = {
228
+ action: 'created',
229
+ repository,
230
+ pull_request: { number: prNumber },
231
+ comment: {
232
+ id: c.id,
233
+ body: c.body ?? null,
234
+ user: { login: c.user.login, id: c.user.id },
235
+ updated_at: c.updated_at,
236
+ },
237
+ };
238
+ return { eventName: 'pull_request_review_comment', payload };
239
+ }
240
+ /** Drains one stream, then persists its HWM only when the stream ran to the end. */
241
+ async function backfillStream(ctx, opts, sleep, stream) {
242
+ const res = await drainStream(ctx, stream.url, stream.toIngestEvent, opts.fetcher, opts.token, sleep, opts.maxPerStream);
243
+ // v1.3.1: only advance HWM when the stream actually drained. A capped run
244
+ // (--max) must leave the HWM at its previous value so the next invocation
245
+ // re-fetches the unprocessed tail.
246
+ if (res.drained && res.maxUpdatedAt) {
247
+ writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, stream.column, res.maxUpdatedAt);
248
+ }
249
+ return { ingested: res.ingested, pages: res.pages };
250
+ }
175
251
  export async function backfillRepo(ctx, opts) {
176
252
  const sleep = opts.sleepMs ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
177
253
  const cursors = readCursor(ctx.hippoRoot, ctx.tenantId, opts.repoFullName);
@@ -181,101 +257,32 @@ export async function backfillRepo(ctx, opts) {
181
257
  pages: { issues: 0, issueComments: 0, prReviewComments: 0 },
182
258
  };
183
259
  // ---------- Stream 1: issues (skip PRs) ----------
184
- const issuesUrl = `${API}/repos/${opts.repoFullName}/issues?state=all&per_page=100` +
185
- (cursors.issues ? `&since=${encodeURIComponent(cursors.issues)}` : '');
186
- const issuesRes = await drainStream(ctx, issuesUrl, (item) => {
187
- if (!isIssuesItem(item))
188
- return null;
189
- // Codex P1 #2: /issues returns PRs too — skip them.
190
- if (item.pull_request)
191
- return null;
192
- const payload = {
193
- action: 'opened',
194
- repository,
195
- issue: {
196
- number: item.number,
197
- title: item.title,
198
- body: item.body ?? null,
199
- user: { login: item.user.login, id: item.user.id },
200
- updated_at: item.updated_at,
201
- },
202
- };
203
- return { eventName: 'issues', payload };
204
- }, opts.fetcher, opts.token, sleep, opts.maxPerStream);
260
+ const issuesRes = await backfillStream(ctx, opts, sleep, {
261
+ url: `${API}/repos/${opts.repoFullName}/issues?state=all&per_page=100` +
262
+ (cursors.issues ? `&since=${encodeURIComponent(cursors.issues)}` : ''),
263
+ column: 'issues_hwm',
264
+ toIngestEvent: (item) => issueItemToEvent(item, repository),
265
+ });
205
266
  result.ingested.issues = issuesRes.ingested;
206
267
  result.pages.issues = issuesRes.pages;
207
- // v1.3.1: only advance HWM when the stream actually drained. A capped run
208
- // (--max) must leave the HWM at its previous value so the next invocation
209
- // re-fetches the unprocessed tail.
210
- if (issuesRes.drained && issuesRes.maxUpdatedAt) {
211
- writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issues_hwm', issuesRes.maxUpdatedAt);
212
- }
213
268
  // ---------- Stream 2: repo-level issue comments ----------
214
- const commentsUrl = `${API}/repos/${opts.repoFullName}/issues/comments?per_page=100` +
215
- (cursors.issueComments
216
- ? `&since=${encodeURIComponent(cursors.issueComments)}`
217
- : '');
218
- const commentsRes = await drainStream(ctx, commentsUrl, (item) => {
219
- if (!isCommentItem(item))
220
- return null;
221
- // SAFETY: this closure only runs against the /issues/comments stream,
222
- // so every item isCommentItem validates here is genuinely an
223
- // IssueCommentItem; a missing issue_url is handled defensively below.
224
- const c = item;
225
- const issueNumber = parseTrailingNumber(c.issue_url);
226
- if (issueNumber === null)
227
- return null;
228
- const payload = {
229
- action: 'created',
230
- repository,
231
- issue: { number: issueNumber },
232
- comment: {
233
- id: c.id,
234
- body: c.body ?? null,
235
- user: { login: c.user.login, id: c.user.id },
236
- updated_at: c.updated_at,
237
- },
238
- };
239
- return { eventName: 'issue_comment', payload };
240
- }, opts.fetcher, opts.token, sleep, opts.maxPerStream);
269
+ const commentsRes = await backfillStream(ctx, opts, sleep, {
270
+ url: `${API}/repos/${opts.repoFullName}/issues/comments?per_page=100` +
271
+ (cursors.issueComments ? `&since=${encodeURIComponent(cursors.issueComments)}` : ''),
272
+ column: 'issue_comments_hwm',
273
+ toIngestEvent: (item) => issueCommentItemToEvent(item, repository),
274
+ });
241
275
  result.ingested.issueComments = commentsRes.ingested;
242
276
  result.pages.issueComments = commentsRes.pages;
243
- if (commentsRes.drained && commentsRes.maxUpdatedAt) {
244
- writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'issue_comments_hwm', commentsRes.maxUpdatedAt);
245
- }
246
277
  // ---------- Stream 3: repo-level PR review comments ----------
247
- const prCommentsUrl = `${API}/repos/${opts.repoFullName}/pulls/comments?per_page=100` +
248
- (cursors.prReviewComments
249
- ? `&since=${encodeURIComponent(cursors.prReviewComments)}`
250
- : '');
251
- const prCommentsRes = await drainStream(ctx, prCommentsUrl, (item) => {
252
- if (!isCommentItem(item))
253
- return null;
254
- // SAFETY: this closure only runs against the /pulls/comments stream,
255
- // so every item isCommentItem validates here is genuinely a
256
- // PrReviewCommentItem; a missing pull_request_url is handled below.
257
- const c = item;
258
- const prNumber = parseTrailingNumber(c.pull_request_url);
259
- if (prNumber === null)
260
- return null;
261
- const payload = {
262
- action: 'created',
263
- repository,
264
- pull_request: { number: prNumber },
265
- comment: {
266
- id: c.id,
267
- body: c.body ?? null,
268
- user: { login: c.user.login, id: c.user.id },
269
- updated_at: c.updated_at,
270
- },
271
- };
272
- return { eventName: 'pull_request_review_comment', payload };
273
- }, opts.fetcher, opts.token, sleep, opts.maxPerStream);
278
+ const prCommentsRes = await backfillStream(ctx, opts, sleep, {
279
+ url: `${API}/repos/${opts.repoFullName}/pulls/comments?per_page=100` +
280
+ (cursors.prReviewComments ? `&since=${encodeURIComponent(cursors.prReviewComments)}` : ''),
281
+ column: 'pr_review_comments_hwm',
282
+ toIngestEvent: (item) => prReviewCommentItemToEvent(item, repository),
283
+ });
274
284
  result.ingested.prReviewComments = prCommentsRes.ingested;
275
285
  result.pages.prReviewComments = prCommentsRes.pages;
276
- if (prCommentsRes.drained && prCommentsRes.maxUpdatedAt) {
277
- writeOneHwm(ctx.hippoRoot, ctx.tenantId, opts.repoFullName, 'pr_review_comments_hwm', prCommentsRes.maxUpdatedAt);
278
- }
279
286
  return result;
280
287
  }
281
288
  //# sourceMappingURL=backfill.js.map
@@ -9,6 +9,7 @@
9
9
  * - hippo github dlq list
10
10
  * - hippo github dlq replay <id> [--force]
11
11
  */
12
+ import { envGithubToken, envGithubWebhookSecret, envGithubWebhookSecretPrevious } from '../../env.js';
12
13
  import { adminActor } from '../../api.js';
13
14
  import { openHippoDb, closeHippoDb } from '../../db.js';
14
15
  import { resolveTenantId } from '../../tenant.js';
@@ -52,6 +53,7 @@ function parsedToIngestEvent(parsed, eventName) {
52
53
  }
53
54
  return null;
54
55
  }
56
+ // Console lines below are the `hippo github` command's printed result and usage text, so they stay off the logger.
55
57
  export function printGithubBackfillUsage() {
56
58
  console.log('hippo github backfill --repo <owner/name> [--since ISO] [--max <N>]');
57
59
  console.log(' --repo GitHub repository in owner/name format (required, e.g. acme/widgets)');
@@ -69,7 +71,7 @@ export async function cmdGithubBackfill(hippoRoot, flags, fetcher = realGitHubFe
69
71
  printGithubBackfillUsage();
70
72
  process.exit(2);
71
73
  }
72
- const token = process.env.GITHUB_TOKEN;
74
+ const token = envGithubToken();
73
75
  if (!token) {
74
76
  console.error('GITHUB_TOKEN is not set. Backfill requires a personal access token with repo read scope.');
75
77
  process.exit(2);
@@ -165,8 +167,8 @@ export async function cmdGithubDlqReplay(hippoRoot, args, flags) {
165
167
  // real hook so `replay` actually re-runs the ingest path.
166
168
  const result = await replayDlqEntry(ctx, id, {
167
169
  force,
168
- webhookSecret: process.env.GITHUB_WEBHOOK_SECRET,
169
- previousSecret: process.env.GITHUB_WEBHOOK_SECRET_PREVIOUS,
170
+ webhookSecret: envGithubWebhookSecret(),
171
+ previousSecret: envGithubWebhookSecretPrevious(),
170
172
  ingestHook: async (innerCtx, args) => {
171
173
  const parsed = JSON.parse(args.rawPayload);
172
174
  const event = parsedToIngestEvent(parsed, args.eventName);
@@ -104,61 +104,13 @@ export async function replayDlqEntry(ctx, id, opts = {}) {
104
104
  }
105
105
  // Signature verification (current secret, not the one in effect when DLQed).
106
106
  if (!opts.force && opts.webhookSecret) {
107
- if (!row.signature) {
108
- return {
109
- ok: false,
110
- status: 'sig_missing',
111
- memoryId: null,
112
- retryCount: row.retryCount,
113
- reason: 'row has no signature (legacy, or redacted before storing); pass --force to replay',
114
- };
115
- }
116
- const sigOk = verifyGitHubSignature({
117
- rawBody: row.rawPayload,
118
- signature: row.signature,
119
- webhookSecret: opts.webhookSecret,
120
- previousSecret: opts.previousSecret,
121
- });
122
- if (!sigOk) {
123
- bumpRetryCount(ctx.hippoRoot, id);
124
- return {
125
- ok: false,
126
- status: 'sig_fail',
127
- memoryId: null,
128
- retryCount: row.retryCount + 1,
129
- reason: 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway',
130
- };
131
- }
132
- }
133
- // Parse + envelope guard.
134
- let parsed;
135
- try {
136
- parsed = JSON.parse(row.rawPayload);
137
- }
138
- catch (e) {
139
- bumpRetryCount(ctx.hippoRoot, id);
140
- // SAFETY: this is a best-effort error message only; property access on
141
- // any JS value is safe (undefined if absent), preserving the existing
142
- // lenient formatting even when something non-Error was thrown.
143
- const message = e.message;
144
- return {
145
- ok: false,
146
- status: 'parse_error',
147
- memoryId: null,
148
- retryCount: row.retryCount + 1,
149
- reason: `still unparseable: ${message}`,
150
- };
151
- }
152
- if (!isGitHubWebhookEnvelope(parsed)) {
153
- bumpRetryCount(ctx.hippoRoot, id);
154
- return {
155
- ok: false,
156
- status: 'unhandled',
157
- memoryId: null,
158
- retryCount: row.retryCount + 1,
159
- reason: 'not a GitHub webhook envelope',
160
- };
107
+ const sigFailure = checkReplaySignature(ctx.hippoRoot, id, row, opts.webhookSecret, opts.previousSecret);
108
+ if (sigFailure)
109
+ return sigFailure;
161
110
  }
111
+ const envelopeFailure = checkReplayEnvelope(ctx.hippoRoot, id, row);
112
+ if (envelopeFailure)
113
+ return envelopeFailure;
162
114
  // Without an ingest hook this is a dry-run validation. Bump and report.
163
115
  if (!opts.ingestHook) {
164
116
  bumpRetryCount(ctx.hippoRoot, id);
@@ -190,4 +142,65 @@ export async function replayDlqEntry(ctx, id, opts = {}) {
190
142
  retryCount: row.retryCount + 1,
191
143
  };
192
144
  }
145
+ /** The failure result when the row cannot pass the signature gate, else null. */
146
+ function checkReplaySignature(hippoRoot, id, row, webhookSecret, previousSecret) {
147
+ if (!row.signature) {
148
+ return {
149
+ ok: false,
150
+ status: 'sig_missing',
151
+ memoryId: null,
152
+ retryCount: row.retryCount,
153
+ reason: 'row has no signature (legacy, or redacted before storing); pass --force to replay',
154
+ };
155
+ }
156
+ const sigOk = verifyGitHubSignature({
157
+ rawBody: row.rawPayload,
158
+ signature: row.signature,
159
+ webhookSecret,
160
+ previousSecret,
161
+ });
162
+ if (!sigOk) {
163
+ bumpRetryCount(hippoRoot, id);
164
+ return {
165
+ ok: false,
166
+ status: 'sig_fail',
167
+ memoryId: null,
168
+ retryCount: row.retryCount + 1,
169
+ reason: 'signature did not verify against current GITHUB_WEBHOOK_SECRET; pass --force to replay anyway',
170
+ };
171
+ }
172
+ return null;
173
+ }
174
+ /** Parse + envelope guard; the failure result after bumping the count, else null. */
175
+ function checkReplayEnvelope(hippoRoot, id, row) {
176
+ let parsed;
177
+ try {
178
+ parsed = JSON.parse(row.rawPayload);
179
+ }
180
+ catch (e) {
181
+ bumpRetryCount(hippoRoot, id);
182
+ // SAFETY: this is a best-effort error message only; property access on
183
+ // any JS value is safe (undefined if absent), preserving the existing
184
+ // lenient formatting even when something non-Error was thrown.
185
+ const message = e.message;
186
+ return {
187
+ ok: false,
188
+ status: 'parse_error',
189
+ memoryId: null,
190
+ retryCount: row.retryCount + 1,
191
+ reason: `still unparseable: ${message}`,
192
+ };
193
+ }
194
+ if (!isGitHubWebhookEnvelope(parsed)) {
195
+ bumpRetryCount(hippoRoot, id);
196
+ return {
197
+ ok: false,
198
+ status: 'unhandled',
199
+ memoryId: null,
200
+ retryCount: row.retryCount + 1,
201
+ reason: 'not a GitHub webhook envelope',
202
+ };
203
+ }
204
+ return null;
205
+ }
193
206
  //# sourceMappingURL=dlq.js.map