hippo-memory 1.70.0 → 1.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (629) hide show
  1. package/README.md +1 -1
  2. package/dist/agent-memories/claude-code.d.ts +4 -2
  3. package/dist/agent-memories/claude-code.js +14 -5
  4. package/dist/agent-memories/files.js +23 -12
  5. package/dist/agent-memories/markdown.d.ts +1 -3
  6. package/dist/agent-memories/markdown.js +1 -3
  7. package/dist/agent-memories/report.js +2 -1
  8. package/dist/agent-memories/sync.d.ts +4 -2
  9. package/dist/agent-memories/sync.js +10 -5
  10. package/dist/api/assemble.d.ts +7 -44
  11. package/dist/api/assemble.js +2 -22
  12. package/dist/api/audit.d.ts +5 -1
  13. package/dist/api/audit.js +9 -1
  14. package/dist/api/auth.d.ts +13 -22
  15. package/dist/api/auth.js +34 -24
  16. package/dist/api/auto-sleep.js +2 -2
  17. package/dist/api/availability.d.ts +2 -15
  18. package/dist/api/availability.js +2 -15
  19. package/dist/api/context-select.js +3 -4
  20. package/dist/api/context-types.d.ts +10 -35
  21. package/dist/api/context.d.ts +5 -22
  22. package/dist/api/context.js +21 -38
  23. package/dist/api/dormant.d.ts +5 -21
  24. package/dist/api/dormant.js +7 -26
  25. package/dist/api/drill-down.d.ts +7 -46
  26. package/dist/api/drill-down.js +5 -26
  27. package/dist/api/forget.d.ts +5 -24
  28. package/dist/api/forget.js +5 -28
  29. package/dist/api/graph.d.ts +8 -0
  30. package/dist/api/graph.js +7 -0
  31. package/dist/api/index.d.ts +2 -0
  32. package/dist/api/index.js +2 -0
  33. package/dist/api/instruction-detect.js +16 -5
  34. package/dist/api/ledger-db.d.ts +2 -1
  35. package/dist/api/ledger-db.js +5 -3
  36. package/dist/api/memories.d.ts +5 -0
  37. package/dist/api/memories.js +7 -0
  38. package/dist/api/objects.d.ts +9 -0
  39. package/dist/api/objects.js +11 -0
  40. package/dist/api/on-store.js +5 -3
  41. package/dist/api/predictions.d.ts +9 -0
  42. package/dist/api/predictions.js +18 -0
  43. package/dist/api/promote.d.ts +13 -17
  44. package/dist/api/promote.js +11 -19
  45. package/dist/api/prompt-hook.d.ts +4 -4
  46. package/dist/api/prompt-hook.js +10 -9
  47. package/dist/api/recall-cli.d.ts +55 -0
  48. package/dist/api/recall-cli.js +94 -0
  49. package/dist/api/recall-core.js +14 -6
  50. package/dist/api/recall-finish.d.ts +53 -0
  51. package/dist/api/recall-finish.js +30 -0
  52. package/dist/api/recall-history.d.ts +17 -84
  53. package/dist/api/recall-history.js +15 -88
  54. package/dist/api/recall-pipeline.d.ts +2 -3
  55. package/dist/api/recall-pipeline.js +16 -9
  56. package/dist/api/recall-types.d.ts +64 -304
  57. package/dist/api/recall.d.ts +5 -33
  58. package/dist/api/recall.js +59 -60
  59. package/dist/api/refine.d.ts +7 -0
  60. package/dist/api/refine.js +10 -0
  61. package/dist/api/remember-local.d.ts +57 -0
  62. package/dist/api/remember-local.js +90 -0
  63. package/dist/api/remember.d.ts +18 -1
  64. package/dist/api/remember.js +13 -1
  65. package/dist/api/sleep-run.d.ts +1 -3
  66. package/dist/api/sleep-run.js +17 -21
  67. package/dist/api/sleep.d.ts +9 -28
  68. package/dist/api/tokens.d.ts +3 -10
  69. package/dist/api/tokens.js +3 -10
  70. package/dist/api/types.d.ts +6 -29
  71. package/dist/api/types.js +4 -22
  72. package/dist/capture/command.d.ts +4 -12
  73. package/dist/capture/command.js +6 -22
  74. package/dist/capture/compact.d.ts +4 -15
  75. package/dist/capture/compact.js +16 -25
  76. package/dist/capture/compaction-record.js +101 -69
  77. package/dist/capture/compaction-spool.d.ts +1 -1
  78. package/dist/capture/compaction-spool.js +1 -1
  79. package/dist/capture/session-digest.d.ts +1 -1
  80. package/dist/capture/session-digest.js +13 -7
  81. package/dist/capture/transcript.d.ts +2 -10
  82. package/dist/capture/transcript.js +4 -18
  83. package/dist/cli/api-context.d.ts +3 -0
  84. package/dist/cli/api-context.js +6 -0
  85. package/dist/cli/audit-prune.d.ts +6 -39
  86. package/dist/cli/audit-prune.js +6 -39
  87. package/dist/cli/audit.d.ts +1 -1
  88. package/dist/cli/audit.js +33 -34
  89. package/dist/cli/auth.d.ts +2 -2
  90. package/dist/cli/auth.js +57 -39
  91. package/dist/cli/briefs.d.ts +4 -4
  92. package/dist/cli/briefs.js +18 -22
  93. package/dist/cli/card.d.ts +2 -2
  94. package/dist/cli/card.js +31 -32
  95. package/dist/cli/client.d.ts +7 -27
  96. package/dist/cli/client.js +24 -43
  97. package/dist/cli/compact-resume-payload.js +3 -2
  98. package/dist/cli/context.d.ts +1 -2
  99. package/dist/cli/context.js +12 -8
  100. package/dist/cli/continuity.d.ts +6 -6
  101. package/dist/cli/continuity.js +62 -64
  102. package/dist/cli/correction-latency.d.ts +2 -14
  103. package/dist/cli/correction-latency.js +2 -14
  104. package/dist/cli/curate.d.ts +13 -17
  105. package/dist/cli/curate.js +68 -92
  106. package/dist/cli/dag.d.ts +4 -4
  107. package/dist/cli/dag.js +33 -27
  108. package/dist/cli/decisions.d.ts +4 -4
  109. package/dist/cli/decisions.js +33 -47
  110. package/dist/cli/eval.js +15 -13
  111. package/dist/cli/exit.d.ts +6 -0
  112. package/dist/cli/exit.js +11 -0
  113. package/dist/cli/explain.d.ts +1 -2
  114. package/dist/cli/explain.js +6 -4
  115. package/dist/cli/flag-values.d.ts +6 -1
  116. package/dist/cli/flag-values.js +27 -10
  117. package/dist/cli/flags.d.ts +1 -0
  118. package/dist/cli/flags.js +1 -1
  119. package/dist/cli/github.d.ts +14 -0
  120. package/dist/{connectors/github/cli-impl.js → cli/github.js} +43 -71
  121. package/dist/cli/goals.d.ts +2 -2
  122. package/dist/cli/goals.js +46 -50
  123. package/dist/cli/hook-runtime.d.ts +9 -27
  124. package/dist/cli/hook-runtime.js +15 -31
  125. package/dist/cli/init.d.ts +2 -2
  126. package/dist/cli/init.js +6 -12
  127. package/dist/cli/install-steps.js +3 -12
  128. package/dist/cli/last-sleep.d.ts +2 -1
  129. package/dist/cli/last-sleep.js +3 -0
  130. package/dist/cli/maintenance.d.ts +4 -4
  131. package/dist/cli/maintenance.js +14 -19
  132. package/dist/cli/object-verbs.js +4 -3
  133. package/dist/cli/owner-validation.d.ts +5 -28
  134. package/dist/cli/owner-validation.js +5 -28
  135. package/dist/cli/playbooks.d.ts +4 -4
  136. package/dist/cli/playbooks.js +23 -28
  137. package/dist/cli/print.d.ts +2 -5
  138. package/dist/cli/print.js +1 -4
  139. package/dist/cli/projects.d.ts +2 -2
  140. package/dist/cli/projects.js +1 -3
  141. package/dist/cli/provenance-coverage.d.ts +2 -6
  142. package/dist/cli/provenance-coverage.js +2 -6
  143. package/dist/cli/quality-repair-once.js +2 -2
  144. package/dist/cli/recall.d.ts +2 -4
  145. package/dist/cli/recall.js +55 -131
  146. package/dist/cli/refine-llm.d.ts +5 -31
  147. package/dist/cli/refine-llm.js +9 -36
  148. package/dist/cli/remember.d.ts +3 -3
  149. package/dist/cli/remember.js +122 -180
  150. package/dist/cli/scheduler.d.ts +2 -17
  151. package/dist/cli/scheduler.js +12 -18
  152. package/dist/cli/serve.js +21 -12
  153. package/dist/cli/session-hooks.d.ts +10 -18
  154. package/dist/cli/session-hooks.js +112 -113
  155. package/dist/cli/setup.d.ts +4 -4
  156. package/dist/cli/setup.js +19 -21
  157. package/dist/cli/shared.d.ts +9 -23
  158. package/dist/cli/shared.js +9 -32
  159. package/dist/cli/slack.d.ts +2 -2
  160. package/dist/cli/slack.js +19 -23
  161. package/dist/cli/sleep.d.ts +3 -2
  162. package/dist/cli/sleep.js +15 -16
  163. package/dist/cli/status.d.ts +9 -12
  164. package/dist/cli/status.js +55 -98
  165. package/dist/cli/stdin.d.ts +4 -6
  166. package/dist/cli/stdin.js +2 -3
  167. package/dist/cli/transfer.d.ts +9 -9
  168. package/dist/cli/transfer.js +66 -89
  169. package/dist/cli/usage.js +11 -5
  170. package/dist/cli.d.ts +66 -448
  171. package/dist/cli.js +87 -263
  172. package/dist/connectors/github/backfill.d.ts +5 -25
  173. package/dist/connectors/github/backfill.js +14 -49
  174. package/dist/connectors/github/deletion.d.ts +4 -18
  175. package/dist/connectors/github/deletion.js +2 -15
  176. package/dist/connectors/github/dlq.d.ts +8 -33
  177. package/dist/connectors/github/dlq.js +12 -29
  178. package/dist/connectors/github/ingest.d.ts +2 -6
  179. package/dist/connectors/github/ingest.js +4 -10
  180. package/dist/connectors/github/octokit-client.d.ts +4 -16
  181. package/dist/connectors/github/octokit-client.js +27 -24
  182. package/dist/connectors/github/ratelimit.d.ts +3 -14
  183. package/dist/connectors/github/ratelimit.js +3 -14
  184. package/dist/connectors/github/scope.d.ts +3 -5
  185. package/dist/connectors/github/scope.js +3 -5
  186. package/dist/connectors/github/signature.d.ts +4 -26
  187. package/dist/connectors/github/signature.js +4 -26
  188. package/dist/connectors/github/tenant-routing.d.ts +2 -24
  189. package/dist/connectors/github/tenant-routing.js +4 -26
  190. package/dist/connectors/github/transform.js +2 -16
  191. package/dist/connectors/github/types.d.ts +3 -15
  192. package/dist/connectors/github/types.js +2 -9
  193. package/dist/connectors/github/webhook.d.ts +2 -16
  194. package/dist/connectors/github/webhook.js +6 -22
  195. package/dist/connectors/slack/backfill.d.ts +4 -17
  196. package/dist/connectors/slack/backfill.js +4 -13
  197. package/dist/connectors/slack/dlq.d.ts +2 -19
  198. package/dist/connectors/slack/dlq.js +2 -19
  199. package/dist/connectors/slack/ingest.d.ts +2 -3
  200. package/dist/connectors/slack/ingest.js +2 -3
  201. package/dist/connectors/slack/scope.d.ts +2 -8
  202. package/dist/connectors/slack/scope.js +2 -8
  203. package/dist/connectors/slack/signature.d.ts +1 -6
  204. package/dist/connectors/slack/tenant-routing.d.ts +2 -19
  205. package/dist/connectors/slack/tenant-routing.js +2 -21
  206. package/dist/connectors/slack/transform.d.ts +2 -18
  207. package/dist/connectors/slack/transform.js +2 -18
  208. package/dist/connectors/slack/types.d.ts +3 -9
  209. package/dist/connectors/slack/types.js +2 -4
  210. package/dist/connectors/slack/web-client.js +33 -27
  211. package/dist/connectors/slack/webhook.d.ts +2 -19
  212. package/dist/connectors/slack/webhook.js +5 -26
  213. package/dist/connectors/slack/workspaces.d.ts +4 -24
  214. package/dist/connectors/slack/workspaces.js +4 -24
  215. package/dist/consolidate/conflicts.js +6 -14
  216. package/dist/consolidate/dag-summary.d.ts +8 -0
  217. package/dist/consolidate/dag-summary.js +41 -0
  218. package/dist/consolidate/dag.d.ts +5 -28
  219. package/dist/consolidate/dag.js +14 -75
  220. package/dist/consolidate/decay.js +7 -19
  221. package/dist/consolidate/dedupe.d.ts +6 -52
  222. package/dist/consolidate/dedupe.js +13 -71
  223. package/dist/consolidate/flush-units.d.ts +3 -4
  224. package/dist/consolidate/flush-units.js +3 -3
  225. package/dist/consolidate/half-life-migration.d.ts +3 -26
  226. package/dist/consolidate/half-life-migration.js +11 -28
  227. package/dist/consolidate/llm-passes.js +4 -21
  228. package/dist/consolidate/memory-value-weights.d.ts +2 -13
  229. package/dist/consolidate/memory-value-weights.js +2 -13
  230. package/dist/consolidate/memory-value.d.ts +11 -84
  231. package/dist/consolidate/memory-value.js +16 -104
  232. package/dist/consolidate/merge.js +10 -31
  233. package/dist/consolidate/merged-row.js +2 -1
  234. package/dist/consolidate/physics-pass.js +1 -3
  235. package/dist/consolidate/replay.d.ts +6 -38
  236. package/dist/consolidate/replay.js +14 -52
  237. package/dist/consolidate/run.js +1 -1
  238. package/dist/consolidate/sleep.d.ts +1 -8
  239. package/dist/consolidate/sleep.js +5 -17
  240. package/dist/consolidate/trace.d.ts +3 -18
  241. package/dist/consolidate/trace.js +3 -18
  242. package/dist/consolidate/traces.js +6 -22
  243. package/dist/core/ablation.d.ts +4 -91
  244. package/dist/core/ablation.js +4 -91
  245. package/dist/core/ambient.d.ts +1 -8
  246. package/dist/core/ambient.js +1 -8
  247. package/dist/core/capture-contract.d.ts +4 -2
  248. package/dist/core/capture-contract.js +4 -2
  249. package/dist/core/card.d.ts +4 -1
  250. package/dist/core/card.js +8 -0
  251. package/dist/core/compare.d.ts +11 -67
  252. package/dist/core/compare.js +9 -63
  253. package/dist/core/config.d.ts +10 -24
  254. package/dist/core/config.js +13 -14
  255. package/dist/core/handoff.d.ts +1 -7
  256. package/dist/core/handoff.js +1 -7
  257. package/dist/core/memory-quality.js +1 -1
  258. package/dist/core/memory.d.ts +41 -164
  259. package/dist/core/memory.js +51 -221
  260. package/dist/core/package-root.d.ts +3 -0
  261. package/dist/core/package-root.js +5 -0
  262. package/dist/core/physics-config.d.ts +1 -4
  263. package/dist/core/physics-config.js +3 -8
  264. package/dist/core/physics.d.ts +15 -61
  265. package/dist/core/physics.js +59 -122
  266. package/dist/core/project-identity.d.ts +17 -58
  267. package/dist/core/project-identity.js +17 -38
  268. package/dist/core/project-remote.js +13 -2
  269. package/dist/core/raw-append-only.d.ts +5 -0
  270. package/dist/core/raw-append-only.js +7 -0
  271. package/dist/core/salience.d.ts +1 -7
  272. package/dist/core/salience.js +1 -7
  273. package/dist/dashboard/dashboard-actions.js +2 -2
  274. package/dist/dashboard/dashboard-snapshot.d.ts +2 -1
  275. package/dist/dashboard/dashboard-snapshot.js +11 -2
  276. package/dist/dashboard/dashboard-types.d.ts +2 -1
  277. package/dist/dashboard/dashboard.d.ts +1 -0
  278. package/dist/dashboard/dashboard.js +50 -4
  279. package/dist/db/busy.d.ts +1 -1
  280. package/dist/db/busy.js +17 -8
  281. package/dist/db/connect.d.ts +1 -0
  282. package/dist/db/connect.js +3 -3
  283. package/dist/db/migrate.js +3 -3
  284. package/dist/db/migrations/types.d.ts +2 -5
  285. package/dist/db/migrations/v14.js +2 -3
  286. package/dist/db/migrations/v15.js +2 -8
  287. package/dist/db/migrations/v16.js +2 -3
  288. package/dist/db/migrations/v17.js +2 -3
  289. package/dist/db/migrations/v19.js +2 -5
  290. package/dist/db/migrations/v20.js +2 -7
  291. package/dist/db/migrations/v22.js +4 -17
  292. package/dist/db/migrations/v23.js +3 -14
  293. package/dist/db/migrations/v24.js +2 -4
  294. package/dist/db/migrations/v25.js +3 -8
  295. package/dist/db/migrations/v26.js +2 -13
  296. package/dist/db/migrations/v27.js +3 -11
  297. package/dist/db/migrations/v28.js +2 -14
  298. package/dist/db/migrations/v29.js +4 -18
  299. package/dist/db/migrations/v30.js +4 -16
  300. package/dist/db/migrations/v31.js +2 -15
  301. package/dist/db/migrations/v32.js +4 -22
  302. package/dist/db/migrations/v33.js +2 -15
  303. package/dist/db/migrations/v34.js +2 -11
  304. package/dist/db/migrations/v35.js +2 -11
  305. package/dist/db/migrations/v36.js +2 -11
  306. package/dist/db/migrations/v37.js +8 -33
  307. package/dist/db/migrations/v38.js +5 -38
  308. package/dist/db/migrations/v39.js +9 -20
  309. package/dist/db/migrations/v40.js +2 -9
  310. package/dist/db/migrations/v41.js +2 -24
  311. package/dist/db/migrations/v43.js +1 -1
  312. package/dist/db/migrations/v44.js +2 -8
  313. package/dist/db/migrations/v45.js +2 -7
  314. package/dist/db/migrations/v47.js +2 -3
  315. package/dist/db/migrations/v51.js +1 -1
  316. package/dist/db/open.d.ts +2 -0
  317. package/dist/db/open.js +17 -1
  318. package/dist/db/physics-state.d.ts +6 -22
  319. package/dist/db/physics-state.js +25 -36
  320. package/dist/db/raw-archive-mirror-cleanup.d.ts +2 -17
  321. package/dist/db/raw-archive-mirror-cleanup.js +2 -17
  322. package/dist/db/vector-store.d.ts +2 -0
  323. package/dist/db/vector-store.js +8 -1
  324. package/dist/doctor.js +74 -19
  325. package/dist/entry/session-text.js +2 -1
  326. package/dist/eval/eval-stats.d.ts +15 -53
  327. package/dist/eval/eval-stats.js +12 -42
  328. package/dist/eval/eval-suite.d.ts +2 -13
  329. package/dist/eval/eval-suite.js +74 -34
  330. package/dist/eval/eval.d.ts +6 -24
  331. package/dist/eval/eval.js +7 -34
  332. package/dist/eval/judgment.d.ts +0 -3
  333. package/dist/eval/judgment.js +19 -11
  334. package/dist/extensions/openclaw-plugin/index.js +1 -1
  335. package/dist/graph/extract.d.ts +5 -27
  336. package/dist/graph/extract.js +7 -33
  337. package/dist/graph/recall.d.ts +7 -20
  338. package/dist/graph/recall.js +14 -76
  339. package/dist/graph/stream.d.ts +7 -39
  340. package/dist/graph/stream.js +11 -34
  341. package/dist/graph/view.d.ts +9 -35
  342. package/dist/graph/view.js +11 -39
  343. package/dist/hooks/codex-wrapper.js +2 -2
  344. package/dist/hooks/copilot.js +2 -1
  345. package/dist/hooks/hook-blocks.d.ts +6 -2
  346. package/dist/hooks/hook-blocks.js +37 -124
  347. package/dist/hooks/json-hooks.d.ts +4 -36
  348. package/dist/hooks/json-hooks.js +18 -57
  349. package/dist/hooks/opencode.d.ts +0 -38
  350. package/dist/hooks/opencode.js +9 -76
  351. package/dist/hooks/shared.d.ts +8 -17
  352. package/dist/hooks/shared.js +29 -20
  353. package/dist/importers/core.d.ts +12 -37
  354. package/dist/importers/core.js +9 -27
  355. package/dist/importers/markdown-parse.d.ts +8 -22
  356. package/dist/importers/markdown-parse.js +8 -25
  357. package/dist/importers/markdown.js +3 -12
  358. package/dist/importers/sources.js +7 -35
  359. package/dist/importers/vault.d.ts +2 -8
  360. package/dist/importers/vault.js +25 -81
  361. package/dist/index.d.ts +6 -2
  362. package/dist/index.js +6 -2
  363. package/dist/learn/autolearn.d.ts +14 -41
  364. package/dist/learn/autolearn.js +14 -41
  365. package/dist/learn/extract.js +2 -4
  366. package/dist/learn/forward-claim-detector.d.ts +6 -30
  367. package/dist/learn/forward-claim-detector.js +14 -66
  368. package/dist/learn/invalidation.d.ts +6 -18
  369. package/dist/learn/invalidation.js +9 -26
  370. package/dist/mcp/admin-tools.js +3 -5
  371. package/dist/mcp/memory-tools.js +4 -9
  372. package/dist/mcp/protocol.d.ts +8 -26
  373. package/dist/mcp/protocol.js +3 -6
  374. package/dist/mcp/recall-tools.js +3 -3
  375. package/dist/mcp/request.d.ts +3 -11
  376. package/dist/mcp/request.js +10 -26
  377. package/dist/mcp/server.d.ts +3 -9
  378. package/dist/mcp/server.js +5 -16
  379. package/dist/mcp/session-state.d.ts +1 -1
  380. package/dist/mcp/session-state.js +5 -11
  381. package/dist/mcp/stdio.d.ts +2 -6
  382. package/dist/mcp/stdio.js +48 -12
  383. package/dist/mcp/tools.js +5 -3
  384. package/dist/objects/customer-notes.d.ts +7 -42
  385. package/dist/objects/customer-notes.js +7 -48
  386. package/dist/objects/decisions.d.ts +12 -50
  387. package/dist/objects/decisions.js +15 -53
  388. package/dist/objects/incidents.d.ts +7 -38
  389. package/dist/objects/incidents.js +7 -41
  390. package/dist/objects/policies.d.ts +11 -89
  391. package/dist/objects/policies.js +11 -98
  392. package/dist/objects/processes.d.ts +7 -52
  393. package/dist/objects/processes.js +7 -61
  394. package/dist/objects/project-briefs.d.ts +11 -55
  395. package/dist/objects/project-briefs.js +14 -75
  396. package/dist/objects/skills.d.ts +7 -42
  397. package/dist/objects/skills.js +8 -54
  398. package/dist/postinstall.js +6 -19
  399. package/dist/predictions/planning-fallacy.d.ts +11 -34
  400. package/dist/rerankers/clef.js +3 -31
  401. package/dist/rerankers/cross-encoder.js +4 -6
  402. package/dist/rerankers/jev.js +9 -6
  403. package/dist/rerankers/llm.d.ts +2 -11
  404. package/dist/rerankers/llm.js +14 -14
  405. package/dist/rerankers/outage-warning.d.ts +2 -1
  406. package/dist/rerankers/outage-warning.js +2 -1
  407. package/dist/rerankers/remote.d.ts +1 -0
  408. package/dist/rerankers/remote.js +2 -0
  409. package/dist/rerankers/types.d.ts +2 -14
  410. package/dist/search/boosts.d.ts +0 -2
  411. package/dist/search/boosts.js +2 -2
  412. package/dist/search/goal-boost.d.ts +23 -0
  413. package/dist/search/goal-boost.js +90 -0
  414. package/dist/search/hybrid.d.ts +2 -0
  415. package/dist/search/multihop.js +2 -3
  416. package/dist/search/path-context.d.ts +5 -18
  417. package/dist/search/path-context.js +5 -18
  418. package/dist/search/physics-search.js +11 -8
  419. package/dist/search/rrf.d.ts +7 -35
  420. package/dist/search/rrf.js +5 -30
  421. package/dist/search/vector.d.ts +7 -0
  422. package/dist/search/vector.js +35 -5
  423. package/dist/server/auth.d.ts +9 -28
  424. package/dist/server/auth.js +32 -25
  425. package/dist/server/boot.d.ts +2 -21
  426. package/dist/server/boot.js +63 -96
  427. package/dist/server/client-ip.d.ts +3 -19
  428. package/dist/server/client-ip.js +5 -28
  429. package/dist/server/defaults.d.ts +3 -0
  430. package/dist/server/defaults.js +4 -0
  431. package/dist/server/key-check-bounds.d.ts +2 -1
  432. package/dist/server/lifecycle.d.ts +5 -4
  433. package/dist/server/lifecycle.js +19 -4
  434. package/dist/server/mcp-http.js +10 -44
  435. package/dist/server/rate-limit.d.ts +5 -18
  436. package/dist/server/rate-limit.js +4 -13
  437. package/dist/server/request.d.ts +4 -8
  438. package/dist/server/request.js +9 -17
  439. package/dist/server/route-table.js +42 -49
  440. package/dist/server/routes/admin.js +22 -28
  441. package/dist/server/routes/customer-notes.js +7 -12
  442. package/dist/server/routes/decisions.js +10 -17
  443. package/dist/server/routes/incidents.js +12 -20
  444. package/dist/server/routes/memories.js +12 -32
  445. package/dist/server/routes/object-routes.d.ts +0 -5
  446. package/dist/server/routes/object-routes.js +7 -15
  447. package/dist/server/routes/policies.js +10 -18
  448. package/dist/server/routes/predictions.js +13 -25
  449. package/dist/server/routes/processes.js +16 -26
  450. package/dist/server/routes/project-briefs.js +9 -16
  451. package/dist/server/routes/recall.js +10 -35
  452. package/dist/server/routes/skills.js +8 -18
  453. package/dist/server/server-detect.d.ts +9 -53
  454. package/dist/server/server-detect.js +24 -90
  455. package/dist/server/sleep-offload.js +4 -1
  456. package/dist/server/types.d.ts +12 -10
  457. package/dist/server/validation.d.ts +3 -1
  458. package/dist/server/validation.js +10 -23
  459. package/dist/server.d.ts +2 -2
  460. package/dist/server.js +3 -2
  461. package/dist/sharing/global-store.d.ts +19 -0
  462. package/dist/sharing/global-store.js +75 -0
  463. package/dist/sharing/global-sync.d.ts +6 -0
  464. package/dist/sharing/global-sync.js +80 -0
  465. package/dist/sharing/project-merge.d.ts +4 -5
  466. package/dist/sharing/project-merge.js +9 -7
  467. package/dist/sharing/scope.d.ts +4 -11
  468. package/dist/sharing/scope.js +4 -11
  469. package/dist/sharing/search-both.d.ts +60 -0
  470. package/dist/sharing/search-both.js +138 -0
  471. package/dist/sharing/share.d.ts +38 -0
  472. package/dist/sharing/share.js +226 -0
  473. package/dist/store/ambient.js +4 -9
  474. package/dist/store/audit-event.d.ts +4 -12
  475. package/dist/store/audit-event.js +4 -12
  476. package/dist/store/audit.d.ts +2 -5
  477. package/dist/store/audit.js +4 -12
  478. package/dist/store/auth.d.ts +6 -6
  479. package/dist/store/auth.js +10 -9
  480. package/dist/store/candidates.d.ts +20 -3
  481. package/dist/store/candidates.js +77 -48
  482. package/dist/store/card-detail.d.ts +2 -1
  483. package/dist/store/card-detail.js +2 -1
  484. package/dist/store/cards.d.ts +14 -9
  485. package/dist/store/cards.js +72 -126
  486. package/dist/store/conflicts.d.ts +4 -21
  487. package/dist/store/conflicts.js +71 -150
  488. package/dist/store/connectors/github.d.ts +10 -10
  489. package/dist/store/connectors/github.js +10 -10
  490. package/dist/store/dashboard-reads.js +4 -8
  491. package/dist/store/delete-and-batch.d.ts +11 -31
  492. package/dist/store/delete-and-batch.js +48 -64
  493. package/dist/store/delivery-recorder.d.ts +8 -4
  494. package/dist/store/delivery-recorder.js +25 -15
  495. package/dist/store/diagnostics.js +6 -13
  496. package/dist/store/dormant.d.ts +7 -29
  497. package/dist/store/dormant.js +15 -56
  498. package/dist/store/embeddings/index.d.ts +11 -80
  499. package/dist/store/embeddings/index.js +71 -207
  500. package/dist/store/embeddings/local.js +15 -32
  501. package/dist/store/embeddings/provider.d.ts +16 -53
  502. package/dist/store/embeddings/provider.js +41 -69
  503. package/dist/store/entry-reads.d.ts +21 -57
  504. package/dist/store/entry-reads.js +65 -126
  505. package/dist/store/entry-row.d.ts +6 -35
  506. package/dist/store/entry-row.js +9 -37
  507. package/dist/store/entry-writes.d.ts +10 -16
  508. package/dist/store/entry-writes.js +17 -35
  509. package/dist/store/goals.d.ts +3 -40
  510. package/dist/store/goals.js +21 -160
  511. package/dist/store/graph-queue.d.ts +6 -22
  512. package/dist/store/graph-queue.js +14 -45
  513. package/dist/store/graph-reads.d.ts +11 -35
  514. package/dist/store/graph-reads.js +20 -58
  515. package/dist/store/graph-rows.d.ts +3 -6
  516. package/dist/store/graph-rows.js +6 -9
  517. package/dist/store/graph-view-rows.d.ts +2 -1
  518. package/dist/store/graph-view-rows.js +2 -1
  519. package/dist/store/graph-writes.d.ts +6 -31
  520. package/dist/store/graph-writes.js +13 -37
  521. package/dist/store/half-life.d.ts +2 -1
  522. package/dist/store/half-life.js +14 -16
  523. package/dist/store/handoffs.d.ts +5 -11
  524. package/dist/store/handoffs.js +16 -34
  525. package/dist/store/index-and-stats.d.ts +6 -19
  526. package/dist/store/index-and-stats.js +34 -82
  527. package/dist/store/markdown.d.ts +2 -6
  528. package/dist/store/markdown.js +21 -20
  529. package/dist/store/mirrors.d.ts +2 -6
  530. package/dist/store/mirrors.js +14 -23
  531. package/dist/store/open.js +6 -13
  532. package/dist/store/planning-fallacy-evidence.d.ts +2 -30
  533. package/dist/store/planning-fallacy-evidence.js +8 -37
  534. package/dist/store/port.d.ts +82 -79
  535. package/dist/store/predictions.d.ts +11 -51
  536. package/dist/store/predictions.js +38 -119
  537. package/dist/{cli → store}/quality-repair.js +15 -31
  538. package/dist/store/raw-archive.d.ts +4 -16
  539. package/dist/store/raw-archive.js +14 -29
  540. package/dist/store/recall-scope.d.ts +19 -79
  541. package/dist/store/recall-scope.js +21 -82
  542. package/dist/store/recall-trace.d.ts +10 -77
  543. package/dist/store/recall-trace.js +19 -95
  544. package/dist/store/rejected-values.js +7 -19
  545. package/dist/store/rejection.d.ts +12 -58
  546. package/dist/store/rejection.js +13 -65
  547. package/dist/store/report-reads.d.ts +6 -0
  548. package/dist/store/report-reads.js +29 -0
  549. package/dist/store/rows.d.ts +9 -19
  550. package/dist/store/rows.js +36 -34
  551. package/dist/store/rule-sql.d.ts +5 -0
  552. package/dist/store/rule-sql.js +37 -0
  553. package/dist/store/search-rows.d.ts +7 -38
  554. package/dist/store/search-rows.js +14 -50
  555. package/dist/store/sessions.d.ts +10 -47
  556. package/dist/store/sessions.js +17 -73
  557. package/dist/store/sqlite/connector-events-group.js +2 -2
  558. package/dist/store/sqlite/entry-writes-group.js +2 -2
  559. package/dist/store/sqlite/error-codec.js +4 -2
  560. package/dist/store/sqlite/executor.d.ts +2 -1
  561. package/dist/store/sqlite/executor.js +2 -1
  562. package/dist/store/sqlite/local.d.ts +3 -3
  563. package/dist/store/sqlite/local.js +1 -0
  564. package/dist/store/sqlite/object-rows.js +6 -3
  565. package/dist/store/sqlite/objects-group.js +4 -2
  566. package/dist/store/sqlite/quarantine-group.js +2 -2
  567. package/dist/store/sqlite/store.d.ts +1 -4
  568. package/dist/store/sqlite/store.js +2 -3
  569. package/dist/store/sqlite/vector-reads-group.js +2 -2
  570. package/dist/store/sqlite/worker-jobs.js +1 -1
  571. package/dist/store/sqlite/worker-ops.d.ts +13 -2
  572. package/dist/store/sqlite/worker-ops.js +13 -2
  573. package/dist/store/sqlite/worker-store.js +5 -2
  574. package/dist/store/summaries.d.ts +10 -62
  575. package/dist/store/summaries.js +34 -146
  576. package/dist/store/summary-dirty.js +1 -1
  577. package/dist/store/tenant-lookup.d.ts +6 -1
  578. package/dist/store/tenant-lookup.js +7 -0
  579. package/dist/store/tenant.d.ts +2 -16
  580. package/dist/store/tenant.js +4 -19
  581. package/dist/store/token-ledger.d.ts +13 -43
  582. package/dist/store/token-ledger.js +19 -50
  583. package/dist/store/usage-reports.js +5 -13
  584. package/dist/store/vector-index.d.ts +46 -0
  585. package/dist/store/vector-index.js +170 -0
  586. package/dist/store/working-memory.d.ts +6 -25
  587. package/dist/store/working-memory.js +18 -52
  588. package/dist/store/yaml.d.ts +1 -5
  589. package/dist/store/yaml.js +2 -6
  590. package/dist/support-bundle.js +7 -5
  591. package/dist/trust/reject-flow.js +1 -3
  592. package/dist/util/anthropic-messages.js +14 -2
  593. package/dist/util/atomic-write.d.ts +2 -1
  594. package/dist/util/atomic-write.js +35 -4
  595. package/dist/util/capped-json.d.ts +6 -0
  596. package/dist/util/capped-json.js +46 -0
  597. package/dist/util/crash-handlers.d.ts +8 -1
  598. package/dist/util/crash-handlers.js +52 -10
  599. package/dist/util/env.d.ts +13 -6
  600. package/dist/util/env.js +14 -7
  601. package/dist/util/home-path.d.ts +2 -1
  602. package/dist/util/home-path.js +4 -2
  603. package/dist/util/http-retry.d.ts +3 -1
  604. package/dist/util/http-retry.js +26 -5
  605. package/dist/util/log.d.ts +3 -2
  606. package/dist/util/log.js +25 -9
  607. package/dist/util/request-scope.d.ts +2 -1
  608. package/dist/util/request-scope.js +2 -1
  609. package/dist/util/secret-detect.d.ts +5 -30
  610. package/dist/util/secret-detect.js +13 -39
  611. package/dist/util/stored-json.d.ts +1 -1
  612. package/dist/util/stored-json.js +1 -1
  613. package/dist/util/token-text.d.ts +1 -4
  614. package/dist/util/token-text.js +1 -4
  615. package/dist/util/transcript-tail.d.ts +2 -0
  616. package/dist/util/transcript-tail.js +24 -23
  617. package/dist/util/version.d.ts +5 -20
  618. package/dist/util/version.js +5 -20
  619. package/extensions/openclaw-plugin/index.ts +1 -1
  620. package/extensions/openclaw-plugin/openclaw.plugin.json +1 -1
  621. package/extensions/openclaw-plugin/package.json +1 -1
  622. package/openclaw.plugin.json +1 -1
  623. package/package.json +1 -1
  624. package/dist/connectors/github/cli-impl.d.ts +0 -25
  625. package/dist/sharing/shared.d.ts +0 -187
  626. package/dist/sharing/shared.js +0 -563
  627. package/dist/store/vector-writes.d.ts +0 -13
  628. package/dist/store/vector-writes.js +0 -89
  629. /package/dist/{cli → store}/quality-repair.d.ts +0 -0
@@ -1,3 +1,4 @@
1
+ import { DEFAULT_TENANT_ID } from '../util/env.js';
1
2
  import * as fs from 'fs';
2
3
  import * as path from 'path';
3
4
  import { createHash } from 'node:crypto';
@@ -15,33 +16,17 @@ import { splitMarkdownFrontmatter, frontmatterList, parseWikilinks, collectMarkd
15
16
  import { realpathOrResolve } from '../util/real-path.js';
16
17
  import { isJsonString } from '../util/json.js';
17
18
  import { escapeLike } from '../util/escape.js';
18
- /**
19
- * Import a markdown vault FOLDER as `kind='raw'` memories.
20
- *
21
- * NOT re-entrant: idempotency rests on the in-memory `existing` Map loaded once
22
- * at the top. Two concurrent importVault runs over the same vault could both see
23
- * a note as absent and double-insert (the connector pattern relies on a single
24
- * sequential writer; same caveat applies here).
25
- */
19
+ /** Import a markdown vault FOLDER as `kind='raw'` memories.
20
+ * NOT re-entrant: idempotency rests on the in-memory `existing` Map loaded once, so two concurrent runs over one vault can double-insert. */
26
21
  export function importVault(folderPath, options) {
27
22
  const hippoRoot = options.hippoRoot;
28
23
  const identity = vaultIdentityOrThrow(options);
29
24
  if (options.global) {
30
- // The raw-archive path is tenant-local; global mode would put raw vault rows
31
- // in the wrong store. Reject for SDK callers too (the CLI also rejects
32
- // --global) rather than silently writing local (codex P2).
25
+ // The raw-archive path is tenant-local, so global mode would put raw vault rows in the wrong store; reject for SDK callers too, not only the CLI.
33
26
  throw new Error('importVault does not support global mode (raw rows are tenant-local).');
34
27
  }
35
- // Self-store no-op guard (codex R8 P1). MUST run BEFORE the existing-rows load
36
- // and the deletion-sync pass below. If the vault folder IS the store (or lives
37
- // inside it), there are no real vault notes - only the store's own markdown
38
- // mirror files. Letting collectMarkdownFiles return [] for this case is NOT
39
- // safe: an empty scan is indistinguishable from "every note was deleted", so
40
- // deletion-sync would archive every live vault:<name>:* row, and raw-archive
41
- // content redaction makes that loss IRREVERSIBLE. The only safe reading of
42
- // "import the store into itself" is "do nothing". Canonicalize both paths
43
- // (realpath: dereference junctions/symlinks + normalize Windows case) so an
44
- // aliased path to the store is still caught (codex R9 P2).
28
+ // Self-store no-op guard: MUST run before the existing-rows load and the deletion-sync. If the vault IS (or sits inside) the store, an empty scan looks like
29
+ // "every note deleted" and deletion-sync would irreversibly archive every live row, so do nothing. Canonicalize both paths (realpath) to catch aliased paths.
45
30
  const resolvedStore = realpathOrResolve(hippoRoot);
46
31
  const resolvedFolder = realpathOrResolve(folderPath);
47
32
  if (resolvedFolder === resolvedStore || resolvedFolder.startsWith(resolvedStore + path.sep)) {
@@ -51,7 +36,7 @@ export function importVault(folderPath, options) {
51
36
  }
52
37
  function syncVaultFolder(folderPath, options, { vaultName, scope }) {
53
38
  const hippoRoot = options.hippoRoot;
54
- const tenantId = options.tenantId ?? 'default';
39
+ const tenantId = options.tenantId ?? DEFAULT_TENANT_ID;
55
40
  const extraTags = options.extraTags ?? [];
56
41
  const dryRun = options.dryRun ?? false;
57
42
  const ctx = {
@@ -78,10 +63,8 @@ function syncVaultFolder(folderPath, options, { vaultName, scope }) {
78
63
  withRequestStoresSync(importNotes);
79
64
  else
80
65
  importNotes();
81
- // Deletion-sync: any artifactRef present in the Map but NOT seen this run is a
82
- // note that vanished from the source folder → archive its raw row. Per-file
83
- // archiveRaw (own handle); no outer SAVEPOINT (no cross-file idempotency row
84
- // to commit atomically, unlike github's multi-row case).
66
+ // Deletion-sync: an artifactRef in the Map but not seen this run vanished from the source, so archive its raw row.
67
+ // Per-file archiveRaw, no outer SAVEPOINT: there is no cross-file idempotency row to commit atomically.
85
68
  for (const [artifactRef, rows] of existing) {
86
69
  if (seen.has(artifactRef))
87
70
  continue;
@@ -95,32 +78,19 @@ function syncVaultFolder(folderPath, options, { vaultName, scope }) {
95
78
  return { total, imported, skipped, rejected, archived, redacted, entries };
96
79
  }
97
80
  function vaultIdentityOrThrow(options) {
98
- // Vault NAME is the identity key for the destructive deletion-sync below, so it
99
- // must be explicit. Defaulting to the folder basename meant two unrelated vaults
100
- // sharing a basename (e.g. work/notes and personal/notes) collided on the same
101
- // `vault:<name>:*` prefix - importing the second loaded the first's rows and the
102
- // deletion-sync archived them (codex R10 P2). Require a deliberate name instead
103
- // of inferring a path-unstable one.
81
+ // The vault NAME keys the destructive deletion-sync, so it must be explicit: defaulting to the folder basename made two vaults
82
+ // sharing a basename collide on the same `vault:<name>:*` prefix and the sync archived the first one's rows.
104
83
  const vaultName = options.name?.trim();
105
84
  if (!vaultName) {
106
85
  throw new Error('importVault requires an explicit vault name (options.name): it is the identity key for source-deletion sync and must not be inferred from the folder basename.');
107
86
  }
108
87
  if (vaultName.includes(':')) {
109
- // ':' is the artifactRef delimiter (vault:<name>:<relpath>); a name
110
- // containing it lets a different vault's prefix scan over-match and archive
111
- // its rows (codex P2). Reject rather than silently corrupt the keys.
88
+ // ':' delimits the artifactRef (vault:<name>:<relpath>); a name containing it lets another vault's prefix scan over-match and archive its rows.
112
89
  throw new Error(`vault name must not contain ':' (artifactRef delimiter): ${vaultName}`);
113
90
  }
114
91
  const scope = options.scope ?? null;
115
- // Privacy footgun guard (codex R13 P2): hippo's recall filter only default-denies
116
- // scopes shaped `<source>:private:*` (see isPrivateScope / PRIVATE_SCOPE_RE in
117
- // scope.ts). A bare `private` (or `private:<x>`) first segment is NOT recognized
118
- // as private, so notes a user believes are private would still be returned to
119
- // no-scope recall callers. Reject the alias and point at the source-prefixed form
120
- // rather than silently storing public-visible "private" notes. Use recall's own
121
- // isPrivateScope as the single source of truth: reject a scope that names a
122
- // `private` segment yet is NOT a valid `<source>:private:*` (catches `private`,
123
- // `private:x`, and `vault:private` with a missing trailing segment).
92
+ // Privacy guard: recall only default-denies scopes shaped `<source>:private:*` (isPrivateScope in src/store/recall-scope.ts), so a bare `private`
93
+ // alias would be returned to no-scope callers. Reject any scope naming a `private` segment that is not a valid `<source>:private:*`.
124
94
  assertClientScope(scope);
125
95
  if (scope !== null && scope.split(':').includes('private') && !isPrivateScope(scope)) {
126
96
  throw new Error(`vault scope '${scope}' is not recognized as private by recall (only '<source>:private:*' scopes are default-denied). Use a source-prefixed scope such as 'vault:private:${vaultName}'.`);
@@ -153,27 +123,17 @@ function importVaultNote(run, relpath) {
153
123
  tally.total++;
154
124
  const artifactRef = `vault:${run.vaultName}:${relpath}`;
155
125
  run.seen.add(artifactRef);
156
- // Content-hash is computed from the RAW file bytes (deterministic; no
157
- // Date/random in the content path) so idempotency survives frontmatter
158
- // edits identically to body edits.
126
+ // The content hash covers the RAW file bytes (deterministic, no Date/random) so frontmatter edits are idempotent like body edits.
159
127
  const rawFileContent = readVaultNote(run, relpath);
160
128
  if (rawFileContent === null)
161
129
  return;
162
130
  const hash = createHash('sha256').update(rawFileContent).digest('hex');
163
131
  const hashTag = `content-hash:${hash}`;
164
- // Load every live raw row for this ref (>1 only after a concurrent double-
165
- // insert). The idempotency decision happens below, AFTER the full tag set is
166
- // built, so it can compare the complete envelope rather than a subset.
132
+ // Load every live raw row for this ref (>1 only after a concurrent double-insert); decide idempotency below, once the full tag set is built.
167
133
  const priors = run.existing.get(artifactRef) ?? [];
168
134
  const { fm, body } = splitMarkdownFrontmatter(rawFileContent);
169
- // Empty / frontmatter-only note: nothing storable (createMemory enforces a
170
- // min content length). The note's CONTENT was deleted at source, so this is a
171
- // content-deletion: archive any prior row(s) - the old body must not stay live
172
- // and searchable after the source no longer holds it (codex R12 P2) - then
173
- // skip the write. Archiving here is safe precisely because we then skip
174
- // remember() entirely: there is no archive-then-throw-on-empty-body hazard
175
- // (the original reason this branch did not archive). The note stays in `seen`
176
- // so deletion-sync does not double-process it.
135
+ // Empty or frontmatter-only note: nothing storable, and the content was deleted at source, so archive prior rows (the old body must not stay searchable)
136
+ // and skip the write. Safe because remember() is skipped, so there is no archive-then-throw hazard; the note stays in `seen` so deletion-sync skips it.
177
137
  if (body.trim().length < 3) {
178
138
  archivePriors(run, priors, `emptied:${artifactRef}`);
179
139
  tally.skipped++;
@@ -189,15 +149,10 @@ function importVaultNote(run, relpath) {
189
149
  }
190
150
  function writeChangedNote(run, artifactRef, priors, body, tags) {
191
151
  const { ctx, tally } = run;
192
- // Changed file → archive EVERY old raw row for this ref (normally one; >1
193
- // only after a concurrent double-insert), then append the new one. NEVER
194
- // supersede (would yield kind='distilled'). archiveRaw commits + closes its
195
- // handle before remember() runs, so there is no double-live row; a crash
196
- // between them self-heals (file re-imported as fresh raw next run).
152
+ // Changed file: archive EVERY old raw row for this ref (>1 only after a concurrent double-insert), then append the new one; NEVER supersede.
153
+ // archiveRaw commits before remember() runs, so no double-live row; a crash between them self-heals on the next import.
197
154
  archivePriors(run, priors, `changed:${artifactRef}`);
198
- // remember() owns the actual write. We build an `echo` of the SAME content +
199
- // tags via createMemory purely for the ImportResult, then reconcile its id to
200
- // remember()'s real row id so entries[] reflects the row that landed.
155
+ // remember() owns the write; the `echo` from createMemory only fills the ImportResult, with its id reconciled to the row that landed.
201
156
  const content = vetSecrets(body, tags, true).content;
202
157
  const echo = createMemory(content, {
203
158
  kind: 'raw',
@@ -236,10 +191,7 @@ function archivePriors(run, priors, reason) {
236
191
  }
237
192
  }
238
193
  function vaultNoteTags(run, hashTag, fm, body) {
239
- // Build the FULL tag envelope this import would write, BEFORE the idempotency
240
- // decision. De-duplicate (createMemory stores tags verbatim, so a collision
241
- // between, e.g., a frontmatter tag and an extraTag would otherwise produce a
242
- // duplicate). Order-preserving.
194
+ // Build the FULL tag envelope before the idempotency decision, de-duplicated and order-preserving (createMemory stores tags verbatim).
243
195
  const frontmatterTags = [
244
196
  ...frontmatterList(fm['tags']),
245
197
  ...frontmatterList(fm['aliases']).map((a) => `alias:${a}`),
@@ -255,14 +207,8 @@ function vaultNoteTags(run, hashTag, fm, body) {
255
207
  ]));
256
208
  }
257
209
  function vaultEnvelopeUnchanged(priors, tags, scope) {
258
- // Unchanged iff EVERY live raw row carries the EXACT same tag set AND scope.
259
- // Comparing the COMPLETE set (not the content-hash + a subset of extra tags)
260
- // means every envelope change registers: content (via the content-hash tag),
261
- // frontmatter, wikilinks, an ADDED extra tag, or a REMOVED one - the earlier
262
- // piecemeal checks missed scope (R10 P2) then tag removal (R11 P2). Set
263
- // equality is order-independent and both sides are deduped. (`length > 0`
264
- // guard: a never-seen file must import, not skip; archiving ALL priors on a
265
- // mismatch also clears any concurrent-double-insert duplicates.)
210
+ // Unchanged iff EVERY live raw row carries the EXACT same tag set AND scope; comparing the complete envelope (not hash plus a subset) catches
211
+ // scope, added and removed tags. `length > 0` guards a never-seen file; archiving all priors on a mismatch also clears concurrent double-inserts.
266
212
  const wantTags = new Set(tags);
267
213
  return (priors.length > 0 &&
268
214
  priors.every((p) => {
@@ -297,9 +243,7 @@ function storeVaultNote(run, echo, content, tags, artifactRef) {
297
243
  throw err;
298
244
  }
299
245
  }
300
- /** Local tolerant JSON-array parse for the loader's `tags_json` column. The
301
- * store's own `parseJsonArray` is not exported; this matches its contract
302
- * (returns [] on null/garbage). */
246
+ /** Tolerant JSON-array parse for the loader's `tags_json` column (the store's `parseJsonArray` is not exported); returns [] on null or garbage. */
303
247
  function parseJsonArrayLoose(value) {
304
248
  if (!value)
305
249
  return [];
package/dist/index.d.ts CHANGED
@@ -33,9 +33,13 @@ export { ConsolidationResult } from './consolidate/run.js';
33
33
  export { sleep, type SleepOpts, type SleepResult } from './api/sleep.js';
34
34
  export { strengthBucket } from './consolidate/dedupe.js';
35
35
  export { isEmbeddingAvailable, getEmbedding } from './store/embeddings/local.js';
36
- export { cosineSimilarity, loadEmbeddingIndex, saveEmbeddingIndex, embedMemory, embedAll, } from './store/embeddings/index.js';
36
+ export { cosineSimilarity, embedMemory, embedAll, } from './store/embeddings/index.js';
37
+ export { loadEmbeddingIndex, saveEmbeddingIndex } from './store/vector-index.js';
37
38
  export { captureError, extractLessons, partitionLessons, deduplicateLesson, runWatched, fetchGitLog, } from './learn/autolearn.js';
38
- export { getGlobalRoot, initGlobal, promoteToGlobal, searchBoth, searchBothHybrid, syncGlobalToLocal, HybridSearchOptions, transferScore, shareMemory, listPeers, autoShare, } from './sharing/shared.js';
39
+ export { getGlobalRoot, initGlobal, promoteToGlobal } from './sharing/global-store.js';
40
+ export { searchBoth, searchBothHybrid, HybridSearchOptions } from './sharing/search-both.js';
41
+ export { syncGlobalToLocal } from './sharing/global-sync.js';
42
+ export { transferScore, shareMemory, listPeers, autoShare } from './sharing/share.js';
39
43
  export { wmPush, wmRead, wmClear, wmFlush, WorkingMemoryItem, WM_MAX_ENTRIES, } from './store/working-memory.js';
40
44
  export { importChatGPT, importClaude, importCursor, importGenericFile, } from './importers/sources.js';
41
45
  export { importMarkdown } from './importers/markdown.js';
package/dist/index.js CHANGED
@@ -37,11 +37,15 @@ export { sleep } from './api/sleep.js';
37
37
  export { strengthBucket } from './consolidate/dedupe.js';
38
38
  // Feature 1: Embedding search
39
39
  export { isEmbeddingAvailable, getEmbedding } from './store/embeddings/local.js';
40
- export { cosineSimilarity, loadEmbeddingIndex, saveEmbeddingIndex, embedMemory, embedAll, } from './store/embeddings/index.js';
40
+ export { cosineSimilarity, embedMemory, embedAll, } from './store/embeddings/index.js';
41
+ export { loadEmbeddingIndex, saveEmbeddingIndex } from './store/vector-index.js';
41
42
  // Feature 2: Auto-learn from errors
42
43
  export { captureError, extractLessons, partitionLessons, deduplicateLesson, runWatched, fetchGitLog, } from './learn/autolearn.js';
43
44
  // Feature 3: Cross-agent shared memory
44
- export { getGlobalRoot, initGlobal, promoteToGlobal, searchBoth, searchBothHybrid, syncGlobalToLocal, transferScore, shareMemory, listPeers, autoShare, } from './sharing/shared.js';
45
+ export { getGlobalRoot, initGlobal, promoteToGlobal } from './sharing/global-store.js';
46
+ export { searchBoth, searchBothHybrid } from './sharing/search-both.js';
47
+ export { syncGlobalToLocal } from './sharing/global-sync.js';
48
+ export { transferScore, shareMemory, listPeers, autoShare } from './sharing/share.js';
45
49
  // Feature 5: Working memory
46
50
  export { wmPush, wmRead, wmClear, wmFlush, WM_MAX_ENTRIES, } from './store/working-memory.js';
47
51
  // Feature 4: Memory importers
@@ -1,56 +1,29 @@
1
- /**
2
- * Auto-learn from errors and git history.
3
- * Agents learn from failures without explicit hippo remember calls.
4
- */
1
+ /** Auto-learn from errors and git history.
2
+ * Agents learn from failures without explicit hippo remember calls. */
5
3
  import { MemoryEntry } from '../core/memory.js';
6
- /** A memory of a failed command, "Command '<cmd>' failed: <truncated stderr>"; no store is in reach, so `hippo watch` re-derives its half-life from the store's config. */
4
+ /** A memory of a failed command, "Command '<cmd>' failed: <truncated stderr>"; `hippo watch` stores its text and tags through remember. */
7
5
  export declare function captureError(exitCode: number, stderr: string, command: string, tenantId?: string): MemoryEntry;
8
- /**
9
- * Parse git log output for actionable lessons.
10
- * Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
11
- */
6
+ /** Parse git log output for actionable lessons.
7
+ * Looks for fix:, revert:, bug:, error:, hotfix: commit messages. */
12
8
  export declare function extractLessons(gitLog: string, customPatterns?: string[]): string[];
13
- /**
14
- * Split parsed lessons into ones worth storing and low-information ones.
15
- *
16
- * `extractLessons` is a published API surface (exported from src/index.ts)
17
- * and does one job: parse a git log into candidate lesson strings. Adding a
18
- * quality check inside it would break that contract and silently change
19
- * what external callers get back. So parsing and admission are separate
20
- * steps: this function is the write-path gate, called by each caller that
21
- * actually stores a lesson, not by the parser itself.
22
- *
23
- * Order is preserved in both output arrays; both hold lessons with secret shapes redacted.
24
- */
9
+ /** Split parsed lessons into ones worth storing and low-information ones; kept out of `extractLessons` so that published parser's output cannot change.
10
+ * Order is preserved in both arrays, and both hold lessons with secret shapes redacted. */
25
11
  export declare function partitionLessons(lessons: string[]): {
26
12
  kept: string[];
27
13
  dropped: string[];
28
14
  };
29
- /**
30
- * Check if a substantially similar memory already exists.
31
- * Returns true if overlap > threshold (default 0.7).
32
- *
33
- * `tenantId` is opt-in. Only takes effect when the first argument is a
34
- * root string (string-overload path). When the first argument is a
35
- * pre-loaded MemoryEntry[], the caller has already scoped — tenantId is
36
- * ignored on that path.
37
- */
15
+ /** Check if a substantially similar memory already exists: true if overlap > threshold (default 0.7).
16
+ * `tenantId` applies only on the root-string overload; a pre-loaded MemoryEntry[] is already scoped, so it is ignored there. */
38
17
  export declare function deduplicateLesson(hippoRootOrEntries: string | MemoryEntry[], lesson: string, threshold?: number, tenantId?: string): boolean;
39
- /**
40
- * Run a command in a shell, streaming stderr live; never pass text the caller did not write.
41
- * Returns: { exitCode, stderr }.
42
- */
18
+ /** Run a command in a shell, streaming stderr live; never pass text the caller did not write.
19
+ * Returns: { exitCode, stderr }. */
43
20
  export declare function runWatched(command: string): Promise<{
44
21
  exitCode: number;
45
22
  stderr: string;
46
23
  }>;
47
- /**
48
- * Check whether a directory is a git work tree.
49
- */
24
+ /** Check whether a directory is a git work tree. */
50
25
  export declare function isGitRepo(cwd: string): boolean;
51
- /**
52
- * Fetch recent git log lines (subject lines only).
53
- * days: how many days of history to include.
54
- */
26
+ /** Fetch recent git log lines (subject lines only).
27
+ * days: how many days of history to include. */
55
28
  export declare function fetchGitLog(cwd: string, days: number): string;
56
29
  //# sourceMappingURL=autolearn.d.ts.map
@@ -1,7 +1,5 @@
1
- /**
2
- * Auto-learn from errors and git history.
3
- * Agents learn from failures without explicit hippo remember calls.
4
- */
1
+ /** Auto-learn from errors and git history.
2
+ * Agents learn from failures without explicit hippo remember calls. */
5
3
  import { execSync, execFileSync, spawn } from 'child_process';
6
4
  import { createMemory, Layer, DEFAULT_HALF_LIFE_DAYS } from '../core/memory.js';
7
5
  import { loadAllEntries } from '../store/entry-reads.js';
@@ -11,7 +9,7 @@ import { redactSecretsStrict } from '../util/secret-detect.js';
11
9
  import { errorMessage, log } from '../util/log.js';
12
10
  const AUTOLEARN_TEXT_CHARS = 500;
13
11
  const AUTOLEARN_TAG_CHARS = 30;
14
- /** A memory of a failed command, "Command '<cmd>' failed: <truncated stderr>"; no store is in reach, so `hippo watch` re-derives its half-life from the store's config. */
12
+ /** A memory of a failed command, "Command '<cmd>' failed: <truncated stderr>"; `hippo watch` stores its text and tags through remember. */
15
13
  export function captureError(exitCode, stderr, command, tenantId) {
16
14
  // Truncate to first 500 chars to avoid storing megabytes of build logs
17
15
  const clean = redactSecretsStrict(stderr);
@@ -35,10 +33,8 @@ export function captureError(exitCode, stderr, command, tenantId) {
35
33
  baseHalfLifeDays: DEFAULT_HALF_LIFE_DAYS,
36
34
  });
37
35
  }
38
- /**
39
- * Parse git log output for actionable lessons.
40
- * Looks for fix:, revert:, bug:, error:, hotfix: commit messages.
41
- */
36
+ /** Parse git log output for actionable lessons.
37
+ * Looks for fix:, revert:, bug:, error:, hotfix: commit messages. */
42
38
  export function extractLessons(gitLog, customPatterns) {
43
39
  const lessons = [];
44
40
  const lines = gitLog.split('\n');
@@ -73,18 +69,8 @@ export function extractLessons(gitLog, customPatterns) {
73
69
  // Deduplicate exact matches at extraction time
74
70
  return [...new Set(lessons)];
75
71
  }
76
- /**
77
- * Split parsed lessons into ones worth storing and low-information ones.
78
- *
79
- * `extractLessons` is a published API surface (exported from src/index.ts)
80
- * and does one job: parse a git log into candidate lesson strings. Adding a
81
- * quality check inside it would break that contract and silently change
82
- * what external callers get back. So parsing and admission are separate
83
- * steps: this function is the write-path gate, called by each caller that
84
- * actually stores a lesson, not by the parser itself.
85
- *
86
- * Order is preserved in both output arrays; both hold lessons with secret shapes redacted.
87
- */
72
+ /** Split parsed lessons into ones worth storing and low-information ones; kept out of `extractLessons` so that published parser's output cannot change.
73
+ * Order is preserved in both arrays, and both hold lessons with secret shapes redacted. */
88
74
  export function partitionLessons(lessons) {
89
75
  const kept = [];
90
76
  const dropped = [];
@@ -98,15 +84,8 @@ export function partitionLessons(lessons) {
98
84
  }
99
85
  return { kept, dropped };
100
86
  }
101
- /**
102
- * Check if a substantially similar memory already exists.
103
- * Returns true if overlap > threshold (default 0.7).
104
- *
105
- * `tenantId` is opt-in. Only takes effect when the first argument is a
106
- * root string (string-overload path). When the first argument is a
107
- * pre-loaded MemoryEntry[], the caller has already scoped — tenantId is
108
- * ignored on that path.
109
- */
87
+ /** Check if a substantially similar memory already exists: true if overlap > threshold (default 0.7).
88
+ * `tenantId` applies only on the root-string overload; a pre-loaded MemoryEntry[] is already scoped, so it is ignored there. */
110
89
  export function deduplicateLesson(hippoRootOrEntries, lesson, threshold = 0.7, tenantId) {
111
90
  const entries = Array.isArray(hippoRootOrEntries)
112
91
  ? hippoRootOrEntries
@@ -118,10 +97,8 @@ export function deduplicateLesson(hippoRootOrEntries, lesson, threshold = 0.7, t
118
97
  }
119
98
  return false;
120
99
  }
121
- /**
122
- * Run a command in a shell, streaming stderr live; never pass text the caller did not write.
123
- * Returns: { exitCode, stderr }.
124
- */
100
+ /** Run a command in a shell, streaming stderr live; never pass text the caller did not write.
101
+ * Returns: { exitCode, stderr }. */
125
102
  export function runWatched(command) {
126
103
  return new Promise((resolve) => {
127
104
  // Use shell: true so the command string is handled by the shell as-is
@@ -143,9 +120,7 @@ export function runWatched(command) {
143
120
  });
144
121
  });
145
122
  }
146
- /**
147
- * Check whether a directory is a git work tree.
148
- */
123
+ /** Check whether a directory is a git work tree. */
149
124
  export function isGitRepo(cwd) {
150
125
  try {
151
126
  const raw = execSync('git rev-parse --is-inside-work-tree', {
@@ -162,10 +137,8 @@ export function isGitRepo(cwd) {
162
137
  return false;
163
138
  }
164
139
  }
165
- /**
166
- * Fetch recent git log lines (subject lines only).
167
- * days: how many days of history to include.
168
- */
140
+ /** Fetch recent git log lines (subject lines only).
141
+ * days: how many days of history to include. */
169
142
  export function fetchGitLog(cwd, days) {
170
143
  try {
171
144
  const raw = execFileSync('git', [
@@ -4,7 +4,7 @@ import { loadConfig } from '../core/config.js';
4
4
  import { RejectedValueError } from '../store/rejection.js';
5
5
  import { redactSecretsStrict } from '../util/secret-detect.js';
6
6
  import { describeMessageFailure, sendAnthropicMessage } from '../util/anthropic-messages.js';
7
- import { neverAutoShareTags } from '../sharing/shared.js';
7
+ import { neverAutoShareTags } from '../sharing/share.js';
8
8
  import { errorMessage, log } from '../util/log.js';
9
9
  import { isJsonString } from '../util/json.js';
10
10
  import { certainDefect } from '../core/memory-quality.js';
@@ -86,9 +86,7 @@ export function storeExtractedFacts(hippoRoot, source, facts) {
86
86
  continue;
87
87
  }
88
88
  const entry = buildExtractedEntry(fact, source, inheritedTags, baseHalfLifeDays);
89
- // A refusal is per-VALUE: one rejected fact must not
90
- // drop the rest of this batch. writeEntry has already audited the
91
- // refusal (reject_refusal) before rethrowing, so skip-and-count here.
89
+ // A refusal is per-VALUE: one rejected fact must not drop the rest of the batch; writeEntry already audited it (reject_refusal), so skip and count.
92
90
  try {
93
91
  writeEntry(hippoRoot, entry);
94
92
  }
@@ -1,36 +1,12 @@
1
- /**
2
- * Forward-claim detector: pure-function regex set + token extraction.
3
- *
4
- * No DB. No state. No dependencies beyond stdlib regex + String.
5
- *
6
- * The detector's job is to decide whether a recall query carries a
7
- * forward-prediction phrase ("will take ~3 days", "ship by Friday",
8
- * "ETA in 2 weeks"). Calibration is intentionally HIGH-PRECISION /
9
- * LOW-RECALL: better to fire on 20% of real forward-claims than 80% with
10
- * 40% noise. Cry-wolf failure dominates planning-fallacy hint UX (Lovallo-
11
- * Kahneman 2003 inside-vs-outside view).
12
- *
13
- * Iteration signal: the `recall_autodebias_hint_no_class_match` audit op
14
- * (emitted by recall when a phrase matches but no class
15
- * resolves) is the telemetry channel for deciding whether to add an
16
- * embedding-based detector.
17
- */
1
+ /** Forward-claim detector: a pure regex set plus token extraction deciding whether a recall query carries a forward-prediction phrase.
2
+ * Calibration is HIGH-PRECISION / LOW-RECALL, since cry-wolf noise dominates hint UX; `recall_autodebias_hint_no_class_match` audits are the telemetry. */
18
3
  export interface ForwardClaimMatch {
19
- /** The regex match snippet, e.g. "will take" or "~3 days". Surfaced
20
- * to the calling agent in `PlanningFallacyHint.detectedPhrase` so they
21
- * see WHY the hint appeared. */
4
+ /** The regex match snippet (e.g. "will take"), surfaced in `PlanningFallacyHint.detectedPhrase` so the agent sees WHY the hint appeared. */
22
5
  phrase: string;
23
- /** Lower-cased non-stop-word tokens (len >= 3, alpha or alphanumeric)
24
- * extracted from the FULL query, NOT just the match. Used by the
25
- * orchestrator's class resolver to score overlap with class_tag tokens. */
6
+ /** Lower-cased non-stop-word tokens (len >= 3) from the FULL query, not just the match; the class resolver scores them against class_tag tokens. */
26
7
  classQueryTokens: string[];
27
8
  }
28
- /**
29
- * Detect whether a recall query carries a forward-prediction phrase.
30
- *
31
- * @returns first-match phrase + extracted class-resolution tokens when
32
- * any pattern matches; null otherwise. Token extraction runs only on a
33
- * match — non-forward queries pay zero work beyond the regex gate.
34
- */
9
+ /** Detect whether a recall query carries a forward-prediction phrase; returns the first-match phrase plus class-resolution tokens, else null.
10
+ * Token extraction runs only on a match, so non-forward queries pay nothing beyond the regex gate. */
35
11
  export declare function detectForwardClaim(queryText: string): ForwardClaimMatch | null;
36
12
  //# sourceMappingURL=forward-claim-detector.d.ts.map
@@ -1,91 +1,41 @@
1
- /**
2
- * Forward-claim detector: pure-function regex set + token extraction.
3
- *
4
- * No DB. No state. No dependencies beyond stdlib regex + String.
5
- *
6
- * The detector's job is to decide whether a recall query carries a
7
- * forward-prediction phrase ("will take ~3 days", "ship by Friday",
8
- * "ETA in 2 weeks"). Calibration is intentionally HIGH-PRECISION /
9
- * LOW-RECALL: better to fire on 20% of real forward-claims than 80% with
10
- * 40% noise. Cry-wolf failure dominates planning-fallacy hint UX (Lovallo-
11
- * Kahneman 2003 inside-vs-outside view).
12
- *
13
- * Iteration signal: the `recall_autodebias_hint_no_class_match` audit op
14
- * (emitted by recall when a phrase matches but no class
15
- * resolves) is the telemetry channel for deciding whether to add an
16
- * embedding-based detector.
17
- */
18
- /**
19
- * Each pattern is intentionally narrow:
20
- * adding a pattern should require evidence from the
21
- * `recall_autodebias_hint_no_class_match` audit channel that real forward-
22
- * claims are slipping through, NOT speculative "this might match more".
23
- *
24
- * Word boundaries (`\b`) are mandatory: prevent `~5 days` inside
25
- * `~5 days_ago` from matching, and prevent `ETA` substring matches inside
26
- * a longer token (e.g. `BETAtesting`).
27
- */
28
- // Reused fragment for ALL duration-suffix patterns. Requires a digit + unit
29
- // so 'will take ownership' / 'ship in Docker' (no time component) don't
30
- // match: verb-only patterns fire on everyday non-estimate queries that share a class-token.
31
- // Accepts `<N> unit` (3 days), `a/an unit` (a week — implicit 1), and
32
- // `one unit` so natural English forward-claims aren't lost.
1
+ /** Forward-claim detector: a pure regex set plus token extraction deciding whether a recall query carries a forward-prediction phrase.
2
+ * Calibration is HIGH-PRECISION / LOW-RECALL, since cry-wolf noise dominates hint UX; `recall_autodebias_hint_no_class_match` audits are the telemetry. */
3
+ /** Each pattern is deliberately narrow (add one only on audit evidence); word boundaries are mandatory so `ETA` never matches inside `BETAtesting`. */
4
+ // Shared duration suffix: needs a digit + unit (`<N> unit`, `a/an unit`, `one unit`) so 'will take ownership' and 'ship in Docker' do not match.
33
5
  const DURATION_TAIL = String.raw `(?:about|around|~|≈)?\s*(?:\d+|a|an|one)\s*(?:day|week|month|hour|hr|min(?:ute)?|sec(?:ond)?)s?\b`;
34
6
  const FORWARD_CLAIM_PATTERNS = [
35
- // Verb + duration tail. Old pattern `/\b(?:will|should...) take\b/i`
36
- // matched `who will take ownership of auth?` because there was no
37
- // quantifier requirement. Now requires `<verb> take <N> <unit>`.
7
+ // Verb + duration tail: requires `<verb> take <N> <unit>`, because a bare `will take` matched `who will take ownership of auth?`.
38
8
  new RegExp(String.raw `\b(?:will|should|gonna|going\s+to)\s+take\s+${DURATION_TAIL}`, 'i'),
39
- // Ship + by/in + duration-or-day. Old pattern `/\bship(?:ping)?\s+(?:by|in)\b/i`
40
- // matched `how does this ship in Docker?`. Now requires either a
41
- // duration tail OR a literal day-of-week reference.
9
+ // Ship + by/in + duration-or-day: a bare `ship in` matched `how does this ship in Docker?`, so a duration tail or literal day-of-week is required.
42
10
  new RegExp(String.raw `\bship(?:ping|s)?\s+(?:by|in)\s+(?:(?:about|around)\s+)?(?:next\s+)?(?:${DURATION_TAIL}|(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b`, 'i'),
43
11
  /\bestimate(?:d)?\s+(?:at\s+)?(?:~|≈|about|around)?\s*\d+/i,
44
12
  /\b(?:by|in|within)\s+(?:about|around|~)?\s*\d+\s*(?:day|week|month|hour)s?\b/i,
45
13
  /\bETA\s*(?:is|:)?\s*\d+/i,
46
14
  /\b(?:by|before)\s+next\s+(?:week|month|sprint|monday|tuesday|wednesday|thursday|friday|saturday|sunday)\b/i,
47
- // Standalone tilde duration: '~3 days for migration', 'estimate ~3 days'.
48
- // Lookbehind asserts start-of-string OR whitespace before the tilde
49
- // because \b before ~ requires a word char immediately preceding (~ is
50
- // not a word character), so /\b~/ would only match in 'foo~3 days'
51
- // (malformed) and silently miss the legitimate cases.
15
+ // Standalone tilde duration ('~3 days for migration'): the lookbehind asserts start-of-string or whitespace because `\b` before `~` needs a word char
16
+ // and /\b~/ would only match 'foo~3 days', silently missing the real cases.
52
17
  /(?<=^|\s)~\s*\d+\s*(?:day|week|month|hour)s?\b/i,
53
18
  // Should + verb + duration tail. Same tightening as the leading 'will
54
19
  // take' rule: 'should ship by EOD' must include a quantifier.
55
20
  new RegExp(String.raw `\bshould\s+(?:be|ship|finish|complete|land)\s+(?:by|in|within)\s+(?:(?:about|around)\s+)?(?:next\s+)?(?:${DURATION_TAIL}|(?:monday|tuesday|wednesday|thursday|friday|saturday|sunday))\b`, 'i'),
56
21
  ];
57
- /**
58
- * Pronouns + function words + modal verbs the regex set already gates on.
59
- * Dropped before class-resolution so the overlap signal comes from
60
- * domain tokens ("migration", "auth", "refactor") rather than connectives.
61
- */
22
+ /** Pronouns, function words and modal verbs the regex set already gates on; dropped before class resolution so overlap comes from domain tokens. */
62
23
  const STOP_WORDS = new Set([
63
24
  'the', 'a', 'an', 'and', 'or', 'but', 'for', 'to', 'in', 'on', 'at', 'of',
64
25
  'by', 'with', 'my', 'your', 'our', 'their', 'its', 'it', 'this', 'that',
65
26
  'these', 'those', 'will', 'should', 'can', 'i', 'we', 'they', 'he', 'she',
66
27
  'is', 'be', 'was', 'are', 'were', 'has', 'have', 'had', 'do', 'does', 'did',
67
28
  'from', 'as', 'so', 'than', 'then',
68
- // Verbs that appear inside FORWARD_CLAIM_PATTERNS themselves — they're
69
- // signal for the regex gate but NOT signal for class resolution (you
70
- // wouldn't name a prediction class "take" or "ship"). Listing here so
71
- // they don't pollute the classQueryTokens overlap score.
29
+ // Verbs inside FORWARD_CLAIM_PATTERNS gate the regex but are no signal for class resolution; listing them keeps them out of the classQueryTokens overlap.
72
30
  'take', 'taken', 'takes', 'ship', 'ships', 'finish', 'complete', 'land',
73
31
  'eta', 'estimate', 'estimated', 'next', 'about', 'around',
74
- // Duration units appear in every forward-claim phrase by design (the
75
- // regex set REQUIRES a `<N> <unit>` quantifier after the verb). Letting
76
- // them through to class resolution lets a class tag containing 'days'
77
- // win or tie on the unit token instead of the domain token.
32
+ // Every forward-claim phrase contains a duration unit by design; letting it through would let a class tag containing 'days' win or tie on the unit.
78
33
  'day', 'days', 'week', 'weeks', 'month', 'months',
79
34
  'hour', 'hours', 'hr', 'hrs',
80
35
  'min', 'mins', 'minute', 'minutes', 'sec', 'secs', 'second', 'seconds',
81
36
  ]);
82
- /**
83
- * Detect whether a recall query carries a forward-prediction phrase.
84
- *
85
- * @returns first-match phrase + extracted class-resolution tokens when
86
- * any pattern matches; null otherwise. Token extraction runs only on a
87
- * match — non-forward queries pay zero work beyond the regex gate.
88
- */
37
+ /** Detect whether a recall query carries a forward-prediction phrase; returns the first-match phrase plus class-resolution tokens, else null.
38
+ * Token extraction runs only on a match, so non-forward queries pay nothing beyond the regex gate. */
89
39
  export function detectForwardClaim(queryText) {
90
40
  if (!queryText)
91
41
  return null;
@@ -103,9 +53,7 @@ function extractClassQueryTokens(queryText) {
103
53
  .toLowerCase()
104
54
  // Strip everything that's not alphanum or whitespace or hyphen / underscore.
105
55
  .replace(/[^a-z0-9\s_-]/g, ' ')
106
- // Split on whitespace AND hyphen AND underscore so `migration-effort`
107
- // produces ['migration', 'effort'] — matching the class-tag split
108
- // pattern in resolveClassFromTokens (split on /[-_\s]+/).
56
+ // Split on whitespace, hyphen and underscore so `migration-effort` yields ['migration', 'effort'], matching the class-tag split in resolveClassFromTokens.
109
57
  .split(/[\s_-]+/)
110
58
  .filter((t) => t.length >= 3 && !STOP_WORDS.has(t) && !/^\d+$/.test(t));
111
59
  }