@remnic/core 9.18.0 → 9.20.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 (309) hide show
  1. package/dist/access-admin-ops-surface.d.ts +8 -8
  2. package/dist/access-admin-ops-surface.js +8 -8
  3. package/dist/access-boundary.d.ts +8 -8
  4. package/dist/access-boundary.js +8 -8
  5. package/dist/access-cli.js +32 -32
  6. package/dist/access-http.d.ts +8 -8
  7. package/dist/access-http.js +12 -12
  8. package/dist/access-identity-continuity-surface.d.ts +6 -6
  9. package/dist/access-identity-continuity-surface.js +8 -8
  10. package/dist/access-lcm-surface.d.ts +8 -8
  11. package/dist/access-lcm-surface.js +8 -8
  12. package/dist/access-mcp.d.ts +8 -8
  13. package/dist/access-mcp.js +11 -11
  14. package/dist/access-memory-search-fanout.d.ts +2 -2
  15. package/dist/{access-namespace-preflight-IbQ0O8Kf.d.ts → access-namespace-preflight-tmwQgCT6.d.ts} +1 -1
  16. package/dist/access-namespace-preflight.d.ts +3 -3
  17. package/dist/access-namespace-preflight.js +8 -8
  18. package/dist/access-observe-write-surface.d.ts +8 -8
  19. package/dist/access-observe-write-surface.js +8 -8
  20. package/dist/access-operations-batch.js +9 -9
  21. package/dist/access-operations.d.ts +8 -8
  22. package/dist/access-operations.js +10 -10
  23. package/dist/access-recall-concurrency.d.ts +8 -8
  24. package/dist/access-recall-concurrency.js +8 -8
  25. package/dist/access-recall-response.d.ts +8 -8
  26. package/dist/access-recall-response.js +8 -8
  27. package/dist/access-recall-surface.d.ts +8 -8
  28. package/dist/access-recall-surface.js +8 -8
  29. package/dist/{access-service-BqjsJRn_.d.ts → access-service-BqUii7LY.d.ts} +6 -6
  30. package/dist/access-service.d.ts +8 -8
  31. package/dist/access-service.js +8 -8
  32. package/dist/access-surface-catalog.d.ts +8 -8
  33. package/dist/action-confidence.d.ts +1 -1
  34. package/dist/active-memory-bridge.d.ts +1 -1
  35. package/dist/active-recall.d.ts +1 -1
  36. package/dist/active-recall.js +1 -1
  37. package/dist/{auto-sync-IH3G25MT.js → auto-sync-UPTUVE4X.js} +3 -3
  38. package/dist/behavior-learner.d.ts +1 -1
  39. package/dist/behavior-signals.d.ts +1 -1
  40. package/dist/bootstrap.d.ts +6 -6
  41. package/dist/briefing.d.ts +2 -2
  42. package/dist/briefing.js +4 -4
  43. package/dist/buffer-surprise-report.d.ts +1 -1
  44. package/dist/buffer.d.ts +2 -2
  45. package/dist/bulk-import/index.d.ts +3 -3
  46. package/dist/calibration.d.ts +1 -1
  47. package/dist/capabilities.d.ts +1 -1
  48. package/dist/{catalog-D_ToaAZM.d.ts → catalog-iWvWz61I.d.ts} +1 -1
  49. package/dist/causal-behavior.d.ts +1 -1
  50. package/dist/causal-consolidation.d.ts +1 -1
  51. package/dist/causal-consolidation.js +5 -5
  52. package/dist/causal-trajectory-graph.d.ts +1 -1
  53. package/dist/{chunk-52H7OB7Y.js → chunk-275ENJDK.js} +2 -2
  54. package/dist/{chunk-OR3OQHHS.js → chunk-3ZUY2VQF.js} +2 -2
  55. package/dist/{chunk-NEFMSUC2.js → chunk-4F6AANKS.js} +3 -3
  56. package/dist/{chunk-NGO4QKMY.js → chunk-4PYLBXX6.js} +2 -2
  57. package/dist/{chunk-UQXIW7OZ.js → chunk-53WDAG7X.js} +2 -2
  58. package/dist/{chunk-CNNQVI2A.js → chunk-5IXPWEQB.js} +5 -5
  59. package/dist/{chunk-XGYCI23S.js → chunk-5JQLAQUZ.js} +2 -2
  60. package/dist/{chunk-ALPBE5EC.js → chunk-62QM5MKY.js} +7 -7
  61. package/dist/{chunk-KPEIWAZY.js → chunk-6NZ7U4R4.js} +1 -1
  62. package/dist/chunk-6NZ7U4R4.js.map +1 -0
  63. package/dist/{chunk-ZHWEUG7Y.js → chunk-7M6APKJL.js} +333 -8
  64. package/dist/chunk-7M6APKJL.js.map +1 -0
  65. package/dist/{chunk-AKWX5E6R.js → chunk-AT3TDN6O.js} +1017 -296
  66. package/dist/chunk-AT3TDN6O.js.map +1 -0
  67. package/dist/{chunk-LU22QKFA.js → chunk-B7C3TF5H.js} +2 -2
  68. package/dist/{chunk-JHIEQCMG.js → chunk-EILX7SQR.js} +3 -3
  69. package/dist/{chunk-WIP3MQZY.js → chunk-EXU5IQ3S.js} +2 -2
  70. package/dist/{chunk-UL6WTQN4.js → chunk-EZKKHVFY.js} +2 -2
  71. package/dist/{chunk-LTGSOACX.js → chunk-GEUDRENF.js} +2 -2
  72. package/dist/{chunk-B3R5CC35.js → chunk-HJEEAO4O.js} +2 -2
  73. package/dist/{chunk-7NHIHUBW.js → chunk-HPOY2PHQ.js} +3 -3
  74. package/dist/{chunk-VMALXCR5.js → chunk-JFDEYXF7.js} +2 -2
  75. package/dist/{chunk-WMMT6W7C.js → chunk-JN3IUA2Q.js} +2 -2
  76. package/dist/{chunk-A2KGXUOU.js → chunk-JWMYVQAM.js} +2 -2
  77. package/dist/{chunk-6P6ZR6JR.js → chunk-KHRKEELC.js} +17 -17
  78. package/dist/{chunk-UVCY7VDX.js → chunk-LI4ZOFHW.js} +2 -2
  79. package/dist/{chunk-6YJLLDWO.js → chunk-LMHDFOVV.js} +3 -3
  80. package/dist/{chunk-UHOUNNY3.js → chunk-N7EVMKP6.js} +6 -6
  81. package/dist/{chunk-7JXXI3GW.js → chunk-Q3FWRDCP.js} +2 -2
  82. package/dist/{chunk-JEMLK7ED.js → chunk-QO2KODU6.js} +2 -2
  83. package/dist/{chunk-7KXE7KN5.js → chunk-TCZWBJBO.js} +2 -2
  84. package/dist/{chunk-B3ABVQ36.js → chunk-UHVXE24Y.js} +2 -1
  85. package/dist/{chunk-UX3ZXN34.js → chunk-UV72DEZD.js} +2 -2
  86. package/dist/{chunk-FO3WM76R.js → chunk-V5TSUGRB.js} +5 -5
  87. package/dist/{chunk-SGCWBLHN.js → chunk-X5QS5C2O.js} +2 -2
  88. package/dist/{cli-D2g5mRgf.d.ts → cli-DPEhq0Cp.d.ts} +5 -5
  89. package/dist/cli.d.ts +10 -10
  90. package/dist/cli.js +25 -25
  91. package/dist/compounding/engine.d.ts +2 -2
  92. package/dist/compounding/engine.js +4 -4
  93. package/dist/compounding/preference-consolidator.d.ts +1 -1
  94. package/dist/compression-optimizer.d.ts +1 -1
  95. package/dist/config.d.ts +1 -1
  96. package/dist/config.js +1 -1
  97. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  98. package/dist/connectors/codex-materialize-runner.js +4 -4
  99. package/dist/connectors/codex-materialize.d.ts +1 -1
  100. package/dist/connectors/index.d.ts +1 -1
  101. package/dist/connectors/index.js +4 -4
  102. package/dist/consolidation-provenance-check.d.ts +2 -2
  103. package/dist/consolidation-undo.d.ts +2 -2
  104. package/dist/contradiction/index.d.ts +2 -2
  105. package/dist/conversation-index/backend.d.ts +1 -1
  106. package/dist/conversation-index/chunker.d.ts +1 -1
  107. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  108. package/dist/conversation-index/indexer.d.ts +1 -1
  109. package/dist/conversation-index/search.d.ts +1 -1
  110. package/dist/day-summary.d.ts +1 -1
  111. package/dist/delinearize.d.ts +1 -1
  112. package/dist/direct-answer-wiring.d.ts +1 -1
  113. package/dist/direct-answer.d.ts +1 -1
  114. package/dist/embedding-fallback.d.ts +1 -1
  115. package/dist/enrichment/index.d.ts +1 -1
  116. package/dist/entity-retrieval.d.ts +2 -2
  117. package/dist/entity-retrieval.js +4 -4
  118. package/dist/entity-schema.d.ts +1 -1
  119. package/dist/explicit-capture.d.ts +6 -6
  120. package/dist/extraction-faithfulness.d.ts +1 -1
  121. package/dist/extraction-judge-telemetry.d.ts +1 -1
  122. package/dist/extraction-judge-training.d.ts +1 -1
  123. package/dist/extraction-judge.d.ts +1 -1
  124. package/dist/extraction.d.ts +1 -1
  125. package/dist/fallback-llm.d.ts +1 -1
  126. package/dist/graph-dashboard-diff.d.ts +1 -1
  127. package/dist/graph-dashboard-key.d.ts +1 -1
  128. package/dist/graph-dashboard-parser.d.ts +1 -1
  129. package/dist/graph-edge-reinforcement.d.ts +1 -1
  130. package/dist/graph-snapshot.d.ts +1 -1
  131. package/dist/graph.d.ts +1 -1
  132. package/dist/importance.d.ts +1 -1
  133. package/dist/importers/index.d.ts +1 -1
  134. package/dist/in-flight-reads.d.ts +1 -1
  135. package/dist/index.d.ts +470 -90
  136. package/dist/index.js +66 -36
  137. package/dist/intent.d.ts +1 -1
  138. package/dist/lcm/engine.d.ts +1 -1
  139. package/dist/lcm/index.d.ts +1 -1
  140. package/dist/lcm/tools.d.ts +1 -1
  141. package/dist/lifecycle.d.ts +1 -1
  142. package/dist/live-connectors-runner.d.ts +1 -1
  143. package/dist/local-llm.d.ts +1 -1
  144. package/dist/local-model-endpoint.d.ts +1 -1
  145. package/dist/maintenance/memory-governance.d.ts +1 -1
  146. package/dist/maintenance/memory-governance.js +4 -4
  147. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  148. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
  149. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  150. package/dist/maintenance/rebuild-memory-projection.js +5 -5
  151. package/dist/mcp-memory-inspector-app.d.ts +8 -8
  152. package/dist/memory-action-policy.d.ts +1 -1
  153. package/dist/memory-cache.d.ts +1 -1
  154. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  155. package/dist/memory-projection-store.d.ts +1 -1
  156. package/dist/memory-provenance.d.ts +1 -1
  157. package/dist/memory-worth-outcomes.d.ts +2 -2
  158. package/dist/models-json.d.ts +1 -1
  159. package/dist/namespaces/migrate.d.ts +3 -3
  160. package/dist/namespaces/migrate.js +5 -5
  161. package/dist/namespaces/principal.d.ts +1 -1
  162. package/dist/namespaces/search.d.ts +1 -1
  163. package/dist/namespaces/storage.d.ts +3 -3
  164. package/dist/namespaces/storage.js +4 -4
  165. package/dist/native-knowledge.d.ts +1 -1
  166. package/dist/offline-sync-impression-drain.d.ts +1 -1
  167. package/dist/operator-toolkit.d.ts +2 -2
  168. package/dist/operator-toolkit.js +9 -9
  169. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  170. package/dist/orchestration/maintenance.d.ts +3 -3
  171. package/dist/orchestration/maintenance.js +9 -9
  172. package/dist/{orchestrator-DrILRi-n.d.ts → orchestrator-DB93S48I.d.ts} +5 -5
  173. package/dist/orchestrator.d.ts +6 -6
  174. package/dist/orchestrator.js +32 -32
  175. package/dist/patterns-cli.d.ts +1 -1
  176. package/dist/{pipeline-BYo4b_y9.d.ts → pipeline-DmGc-H66.d.ts} +1 -1
  177. package/dist/policy-runtime.d.ts +1 -1
  178. package/dist/proactive-contention.d.ts +1 -1
  179. package/dist/provenance.d.ts +1 -1
  180. package/dist/{qmd-BIrL8e69.d.ts → qmd-cJT0crkF.d.ts} +1 -1
  181. package/dist/qmd-preflight.d.ts +2 -2
  182. package/dist/qmd-recall-cache.d.ts +1 -1
  183. package/dist/qmd.d.ts +2 -2
  184. package/dist/recall-concurrency-config.d.ts +1 -1
  185. package/dist/recall-disclosure-escalation.d.ts +1 -1
  186. package/dist/recall-explain-renderer.d.ts +1 -1
  187. package/dist/recall-explain-renderer.js +3 -3
  188. package/dist/recall-memory-map.d.ts +1 -1
  189. package/dist/recall-planner-llm.d.ts +1 -1
  190. package/dist/recall-state.d.ts +1 -1
  191. package/dist/recall-tag-filter.d.ts +1 -1
  192. package/dist/recall-timings.d.ts +1 -1
  193. package/dist/recall-xray-cli.d.ts +1 -1
  194. package/dist/recall-xray-cli.js +4 -4
  195. package/dist/recall-xray-renderer.d.ts +1 -1
  196. package/dist/recall-xray-renderer.js +3 -3
  197. package/dist/recall-xray.d.ts +1 -1
  198. package/dist/recall-xray.js +2 -2
  199. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  200. package/dist/replay/normalizers/claude.d.ts +1 -1
  201. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  202. package/dist/replay/normalizers/shared.d.ts +1 -1
  203. package/dist/replay/runner.d.ts +1 -1
  204. package/dist/replay/types.d.ts +1 -1
  205. package/dist/resolve-auth-token.d.ts +1 -1
  206. package/dist/resume-bundles.js +2 -2
  207. package/dist/retrieval-agents.d.ts +2 -2
  208. package/dist/retrieval-tiers.d.ts +1 -1
  209. package/dist/routing/engine.d.ts +1 -1
  210. package/dist/routing/store.d.ts +1 -1
  211. package/dist/salvage-envelope.d.ts +1 -1
  212. package/dist/schemas.d.ts +22 -22
  213. package/dist/{scope-profiles-BiQ9yXP4.d.ts → scope-profiles-KG2nODX7.d.ts} +1 -1
  214. package/dist/search/embed-helper.d.ts +1 -1
  215. package/dist/search/factory.d.ts +1 -1
  216. package/dist/search/index.d.ts +1 -1
  217. package/dist/search/lancedb-backend.d.ts +1 -1
  218. package/dist/search/meilisearch-backend.d.ts +1 -1
  219. package/dist/search/noop-backend.d.ts +1 -1
  220. package/dist/search/orama-backend.d.ts +1 -1
  221. package/dist/search/port.d.ts +1 -1
  222. package/dist/search/remote-backend.d.ts +1 -1
  223. package/dist/{semantic-consolidation-C-cSATcR.d.ts → semantic-consolidation-BaZlg0D8.d.ts} +1 -1
  224. package/dist/semantic-consolidation.d.ts +2 -2
  225. package/dist/semantic-consolidation.js +5 -5
  226. package/dist/semantic-rule-promotion.js +4 -4
  227. package/dist/semantic-rule-verifier.d.ts +1 -1
  228. package/dist/semantic-rule-verifier.js +4 -4
  229. package/dist/session-observer-bands.d.ts +1 -1
  230. package/dist/session-observer-state.d.ts +1 -1
  231. package/dist/shared-context/manager.d.ts +1 -1
  232. package/dist/signal.d.ts +1 -1
  233. package/dist/{storage-ByTv05qM.d.ts → storage-BKhHHnRo.d.ts} +2 -221
  234. package/dist/storage.d.ts +2 -2
  235. package/dist/storage.js +3 -3
  236. package/dist/summarizer.d.ts +1 -1
  237. package/dist/summary-snapshot.d.ts +1 -1
  238. package/dist/temporal-supersession.d.ts +2 -2
  239. package/dist/temporal-timeline-recall.d.ts +1 -1
  240. package/dist/temporal-validity.d.ts +1 -1
  241. package/dist/threading.d.ts +1 -1
  242. package/dist/tier-migration.d.ts +2 -2
  243. package/dist/tier-routing.d.ts +1 -1
  244. package/dist/topics.d.ts +1 -1
  245. package/dist/transcript.d.ts +1 -1
  246. package/dist/transfer/types.d.ts +12 -12
  247. package/dist/trust-score-stage.d.ts +1 -1
  248. package/dist/trust-score.d.ts +1 -1
  249. package/dist/{types-e0_MI3Iq.d.ts → types-GBQZuT7l.d.ts} +397 -1
  250. package/dist/types.d.ts +1 -1
  251. package/dist/types.js +1 -1
  252. package/dist/utility-runtime.d.ts +1 -1
  253. package/dist/verified-recall.js +4 -4
  254. package/dist/write-envelope.d.ts +1 -1
  255. package/package.json +2 -2
  256. package/src/config.test.ts +11 -0
  257. package/src/config.ts +5 -6
  258. package/src/meetings/build.test.ts +646 -0
  259. package/src/meetings/build.ts +365 -0
  260. package/src/meetings/cli.test.ts +276 -0
  261. package/src/meetings/cli.ts +242 -0
  262. package/src/meetings/config.test.ts +72 -0
  263. package/src/meetings/config.ts +183 -0
  264. package/src/meetings/errors.ts +13 -0
  265. package/src/meetings/fuse.test.ts +208 -0
  266. package/src/meetings/fuse.ts +297 -0
  267. package/src/meetings/index.ts +11 -1
  268. package/src/meetings/memory-generator.ts +116 -0
  269. package/src/meetings/recall-exclusion.test.ts +88 -0
  270. package/src/meetings/store.test.ts +232 -0
  271. package/src/meetings/store.ts +465 -0
  272. package/src/meetings/types.ts +111 -0
  273. package/src/orchestration/orchestrator-helpers.ts +23 -3
  274. package/src/orchestration/recall-search-pipeline.test.ts +182 -0
  275. package/src/orchestration/recall-search-pipeline.ts +36 -15
  276. package/src/types.ts +8 -0
  277. package/dist/chunk-AKWX5E6R.js.map +0 -1
  278. package/dist/chunk-KPEIWAZY.js.map +0 -1
  279. package/dist/chunk-ZHWEUG7Y.js.map +0 -1
  280. /package/dist/{auto-sync-IH3G25MT.js.map → auto-sync-UPTUVE4X.js.map} +0 -0
  281. /package/dist/{chunk-52H7OB7Y.js.map → chunk-275ENJDK.js.map} +0 -0
  282. /package/dist/{chunk-OR3OQHHS.js.map → chunk-3ZUY2VQF.js.map} +0 -0
  283. /package/dist/{chunk-NEFMSUC2.js.map → chunk-4F6AANKS.js.map} +0 -0
  284. /package/dist/{chunk-NGO4QKMY.js.map → chunk-4PYLBXX6.js.map} +0 -0
  285. /package/dist/{chunk-UQXIW7OZ.js.map → chunk-53WDAG7X.js.map} +0 -0
  286. /package/dist/{chunk-CNNQVI2A.js.map → chunk-5IXPWEQB.js.map} +0 -0
  287. /package/dist/{chunk-XGYCI23S.js.map → chunk-5JQLAQUZ.js.map} +0 -0
  288. /package/dist/{chunk-ALPBE5EC.js.map → chunk-62QM5MKY.js.map} +0 -0
  289. /package/dist/{chunk-LU22QKFA.js.map → chunk-B7C3TF5H.js.map} +0 -0
  290. /package/dist/{chunk-JHIEQCMG.js.map → chunk-EILX7SQR.js.map} +0 -0
  291. /package/dist/{chunk-WIP3MQZY.js.map → chunk-EXU5IQ3S.js.map} +0 -0
  292. /package/dist/{chunk-UL6WTQN4.js.map → chunk-EZKKHVFY.js.map} +0 -0
  293. /package/dist/{chunk-LTGSOACX.js.map → chunk-GEUDRENF.js.map} +0 -0
  294. /package/dist/{chunk-B3R5CC35.js.map → chunk-HJEEAO4O.js.map} +0 -0
  295. /package/dist/{chunk-7NHIHUBW.js.map → chunk-HPOY2PHQ.js.map} +0 -0
  296. /package/dist/{chunk-VMALXCR5.js.map → chunk-JFDEYXF7.js.map} +0 -0
  297. /package/dist/{chunk-WMMT6W7C.js.map → chunk-JN3IUA2Q.js.map} +0 -0
  298. /package/dist/{chunk-A2KGXUOU.js.map → chunk-JWMYVQAM.js.map} +0 -0
  299. /package/dist/{chunk-6P6ZR6JR.js.map → chunk-KHRKEELC.js.map} +0 -0
  300. /package/dist/{chunk-UVCY7VDX.js.map → chunk-LI4ZOFHW.js.map} +0 -0
  301. /package/dist/{chunk-6YJLLDWO.js.map → chunk-LMHDFOVV.js.map} +0 -0
  302. /package/dist/{chunk-UHOUNNY3.js.map → chunk-N7EVMKP6.js.map} +0 -0
  303. /package/dist/{chunk-7JXXI3GW.js.map → chunk-Q3FWRDCP.js.map} +0 -0
  304. /package/dist/{chunk-JEMLK7ED.js.map → chunk-QO2KODU6.js.map} +0 -0
  305. /package/dist/{chunk-7KXE7KN5.js.map → chunk-TCZWBJBO.js.map} +0 -0
  306. /package/dist/{chunk-B3ABVQ36.js.map → chunk-UHVXE24Y.js.map} +0 -0
  307. /package/dist/{chunk-UX3ZXN34.js.map → chunk-UV72DEZD.js.map} +0 -0
  308. /package/dist/{chunk-FO3WM76R.js.map → chunk-V5TSUGRB.js.map} +0 -0
  309. /package/dist/{chunk-SGCWBLHN.js.map → chunk-X5QS5C2O.js.map} +0 -0
@@ -9,6 +9,7 @@ import { RecallSearchPipelineCoordinator } from "./recall-search-pipeline.js";
9
9
  import type { RecallSearchPipelineDeps } from "./recall-search-pipeline.js";
10
10
  import type { MemoryFile, QmdSearchResult } from "../types.js";
11
11
  import type { StorageManager } from "../index.js";
12
+ import type { QueryAwarePrefilter } from "../orchestrator.js";
12
13
 
13
14
  function result(namespace: string, path: string): QmdSearchResult {
14
15
  return { docid: `${namespace}:${path}`, namespace, path, score: 1, snippet: path };
@@ -68,3 +69,184 @@ test("recall safety keeps same relative path distinct across namespaces", async
68
69
  await rm(memoryDir, { recursive: true, force: true });
69
70
  }
70
71
  });
72
+
73
+ function scopedCandidatesStub(
74
+ seed: QmdSearchResult[],
75
+ ): RecallSearchPipelineDeps["searchScopedMemoryCandidates"] {
76
+ // Faithful to production: return only the requested candidates, capped to limit.
77
+ return async (candidatePaths, _query, limit) =>
78
+ seed.filter((r) => candidatePaths.has(r.path)).slice(0, Math.max(0, limit));
79
+ }
80
+
81
+ function fallbackCoordinator(seed: QmdSearchResult[], archived: MemoryFile[]): RecallSearchPipelineCoordinator {
82
+ const readArchivedMemoriesForNamespaces: RecallSearchPipelineDeps["readArchivedMemoriesForNamespaces"] =
83
+ async () => archived;
84
+ const namespaceFromPath: RecallSearchPipelineDeps["namespaceFromPath"] = () => "default";
85
+ const deps = {
86
+ searchScopedMemoryCandidates: scopedCandidatesStub(seed),
87
+ readArchivedMemoriesForNamespaces,
88
+ namespaceFromPath,
89
+ config: { memoryDir: "/mem" },
90
+ } as unknown as RecallSearchPipelineDeps;
91
+ return new RecallSearchPipelineCoordinator(deps);
92
+ }
93
+
94
+ function prefilter(paths: string[]): QueryAwarePrefilter {
95
+ return {
96
+ candidatePaths: new Set(paths),
97
+ temporalFromDate: null,
98
+ matchedTags: [],
99
+ expandedTags: [],
100
+ combination: "none",
101
+ filteredToFullSearch: false,
102
+ };
103
+ }
104
+
105
+ const MEETING_RECORD = "meetings/2026-03-10/mtg-2026-03-10-abcdef01.md";
106
+ const SEED_PATHS = [MEETING_RECORD, "facts/a.md", "artifacts/y.md"];
107
+ const SEED_WITH_NON_RECALLABLE = SEED_PATHS.map((p) => result("default", p));
108
+ const PREFILTER = prefilter(SEED_PATHS);
109
+
110
+ test("archive fallback excludes non-recallable seeds on the archived-empty early return", async () => {
111
+ const coordinator = fallbackCoordinator(SEED_WITH_NON_RECALLABLE, []);
112
+ // limit 10 > filtered seed count, tokens non-empty, archived empty → the
113
+ // `return scopedSeedResults` early path at the archived-empty guard.
114
+ const out = await coordinator.searchLongTermArchiveFallback("quarterly report", ["default"], 10, PREFILTER);
115
+ assert.deepEqual(
116
+ out.map((r) => r.path),
117
+ ["facts/a.md"],
118
+ "meeting record + artifact must not leak through the direct-caller early return",
119
+ );
120
+ });
121
+
122
+ test("archive fallback excludes non-recallable seeds on the empty-tokens early return", async () => {
123
+ const coordinator = fallbackCoordinator(SEED_WITH_NON_RECALLABLE, [memory("facts/z.md", "archived")]);
124
+ // Empty prompt → zero tokens → the `return scopedSeedResults` early path
125
+ // before archive scoring is even attempted.
126
+ const out = await coordinator.searchLongTermArchiveFallback("", ["default"], 10, PREFILTER);
127
+ assert.deepEqual(out.map((r) => r.path), ["facts/a.md"]);
128
+ });
129
+
130
+ test("archive fallback applies the cap to FILTERED seeds, not raw non-recallable hits", async () => {
131
+ // The scoped search returns a single non-recallable hit that would fill a cap
132
+ // of 1 if counted raw; the method must count only recallable seeds, so it does
133
+ // not early-return that hit and (archive empty) yields nothing.
134
+ const coordinator = fallbackCoordinator([result("default", MEETING_RECORD)], []);
135
+ const out = await coordinator.searchLongTermArchiveFallback("quarterly", ["default"], 1, prefilter([MEETING_RECORD]));
136
+ assert.deepEqual(out.map((r) => r.path), []);
137
+ });
138
+
139
+ test("finding 1 — overfetches scoped seeds before exclusion so a capped fetch still yields recallable hits", async () => {
140
+ // The scoped candidate order puts the NON-recallable meeting record FIRST;
141
+ // capping the scoped fetch to the caller's limit (1) BEFORE the generic-recall
142
+ // exclusion would return only the meeting record, which is then filtered out —
143
+ // dropping facts/a.md with no refill. Overfetching the full candidate set first
144
+ // and excluding afterward must still surface the recallable hit at the cap.
145
+ const coordinator = fallbackCoordinator(
146
+ [result("default", MEETING_RECORD), result("default", "facts/a.md")],
147
+ [],
148
+ );
149
+ const out = await coordinator.searchLongTermArchiveFallback(
150
+ "quarterly",
151
+ ["default"],
152
+ 1,
153
+ prefilter([MEETING_RECORD, "facts/a.md"]),
154
+ );
155
+ assert.deepEqual(
156
+ out.map((r) => r.path),
157
+ ["facts/a.md"],
158
+ "an excluded-first seed must not starve the result of a recallable hit at the cap",
159
+ );
160
+ });
161
+
162
+ function hotSeedCoordinator(seed: QmdSearchResult[]): RecallSearchPipelineCoordinator {
163
+ const deps = {
164
+ config: { memoryDir: "/mem", qmdSearchStrategy: "lex", searchBackend: "qmd" },
165
+ qmd: {},
166
+ searchScopedMemoryCandidates: scopedCandidatesStub(seed),
167
+ searchAcrossNamespaces: async () => [],
168
+ namespaceFromPath: () => "default",
169
+ } as unknown as RecallSearchPipelineDeps;
170
+ return new RecallSearchPipelineCoordinator(deps);
171
+ }
172
+
173
+ test("finding 1 (round-4) — hot QMD seed path overfetches scoped seeds before exclusion", async () => {
174
+ // The query-aware candidate order puts the NON-recallable meeting record FIRST.
175
+ // The hot seed fetch previously capped the scoped fetch to qmdFetchLimit (1)
176
+ // BEFORE the generic-recall exclusion, so the sole fetched seed was the meeting
177
+ // record — filtered out, dropping facts/a.md with no refill. Overfetching the
178
+ // full candidate set and excluding afterward must still surface the recallable
179
+ // hit at the cap.
180
+ const coordinator = hotSeedCoordinator([
181
+ result("default", MEETING_RECORD),
182
+ result("default", "facts/a.md"),
183
+ ]);
184
+ const out = await coordinator.fetchQmdMemoryResultsWithArtifactTopUp("quarterly", 1, 1, {
185
+ namespacesEnabled: false,
186
+ recallNamespaces: ["default"],
187
+ resolveNamespace: () => "default",
188
+ queryAwarePrefilter: prefilter([MEETING_RECORD, "facts/a.md"]),
189
+ });
190
+ assert.deepEqual(
191
+ out.map((r) => r.path),
192
+ ["facts/a.md"],
193
+ "an excluded-first candidate must not starve the hot seed of a recallable hit at the cap",
194
+ );
195
+ });
196
+
197
+ function resultScored(namespace: string, path: string, score: number): QmdSearchResult {
198
+ return { docid: `${namespace}:${path}`, namespace, path, score, snippet: path };
199
+ }
200
+
201
+ function meetingRecordPath(hash: string): string {
202
+ return `meetings/2026-03-10/mtg-2026-03-10-${hash}.md`;
203
+ }
204
+
205
+ function starvedPrimaryCoordinator(
206
+ seed: QmdSearchResult[],
207
+ primary: QmdSearchResult[],
208
+ ): RecallSearchPipelineCoordinator {
209
+ const deps = {
210
+ config: { memoryDir: "/mem", qmdSearchStrategy: "lex", searchBackend: "qmd" },
211
+ qmd: {},
212
+ searchScopedMemoryCandidates: scopedCandidatesStub(seed),
213
+ // Faithful to the QMD backend: cap the primary hits to the requested budget.
214
+ searchAcrossNamespaces: async ({ maxResults }: { maxResults: number }) =>
215
+ [...primary].sort((a, b) => b.score - a.score).slice(0, Math.max(0, maxResults)),
216
+ namespaceFromPath: () => "default",
217
+ } as unknown as RecallSearchPipelineDeps;
218
+ return new RecallSearchPipelineCoordinator(deps);
219
+ }
220
+
221
+ test("finding 1 (round-5) — excluded seeds must not fill the merge cap and starve a primary hit", async () => {
222
+ // Excluded meeting records dominate the query-aware SEED set (higher score),
223
+ // while the sole recallable memory arrives from the PRIMARY QMD search — so the
224
+ // scoped-seed overfetch fix and the seed-derived `bestFiltered` fallback cannot
225
+ // rescue it. The seed MERGE `[...seeds, ...primary]` capped to fetchLimit BEFORE
226
+ // filterRecallCandidates ran, so every cap slot (even after the two-attempt
227
+ // fetchLimit growth) went to meeting records later filtered out — dropping
228
+ // facts/a.md with no refill. Excluding non-recallable paths BEFORE the cap must
229
+ // let the primary hit survive at qmdFetchLimit=1.
230
+ const meetings = [
231
+ "aaaaaaaa",
232
+ "bbbbbbbb",
233
+ "cccccccc",
234
+ "dddddddd",
235
+ "eeeeeeee",
236
+ "ffffffff",
237
+ ].map((h) => resultScored("default", meetingRecordPath(h), 2));
238
+ const coordinator = starvedPrimaryCoordinator(meetings, [
239
+ resultScored("default", "facts/a.md", 1),
240
+ ]);
241
+ const out = await coordinator.fetchQmdMemoryResultsWithArtifactTopUp("quarterly", 1, 1, {
242
+ namespacesEnabled: false,
243
+ recallNamespaces: ["default"],
244
+ resolveNamespace: () => "default",
245
+ queryAwarePrefilter: prefilter(meetings.map((m) => m.path)),
246
+ });
247
+ assert.deepEqual(
248
+ out.map((r) => r.path),
249
+ ["facts/a.md"],
250
+ "excluded seeds ranked ahead must not fill the fetchLimit cap and starve the recallable primary hit",
251
+ );
252
+ });
@@ -422,10 +422,19 @@ export class RecallSearchPipelineCoordinator {
422
422
  ? await this.deps.searchScopedMemoryCandidates(
423
423
  queryAwarePrefilter.candidatePaths,
424
424
  prompt,
425
- qmdFetchLimit,
425
+ // Overfetch the FULL scoped candidate set BEFORE the generic-recall
426
+ // exclusion `filterRecallCandidates` applies below (L464). Capping to
427
+ // `qmdFetchLimit` here lets excluded paths (artifacts, activity digests,
428
+ // meeting records) consume the caller's budget and drop legitimate hits
429
+ // with no refill — the hot-path mirror of the archive-fallback fix. The
430
+ // candidate set is an already-bounded prefilter, so its size is the
431
+ // natural ceiling; the post-exclusion cap is applied by filterRecallCandidates.
432
+ queryAwarePrefilter.candidatePaths.size,
426
433
  { allowArchived: options.collection !== undefined },
427
434
  )
428
435
  : [];
436
+ // Drop generic-recall-excluded records before the fetchLimit cap so they can't starve valid memories (#1995).
437
+ const recallable = (r: QmdSearchResult) => !isGenericRecallExcludedPath(r.path, this.deps.config.memoryDir);
429
438
 
430
439
  let fetchLimit = Math.max(qmdFetchLimit, qmdHybridFetchLimit);
431
440
  const maxFetchLimit = Math.min(
@@ -586,13 +595,12 @@ export class RecallSearchPipelineCoordinator {
586
595
  lastHybridResultCount = hybridResults.length;
587
596
  lastHybridTopUpUsed = hybridResults.length > 0;
588
597
  if (hybridResults.length > 0) {
589
- // Dedup by composite (namespace, path) so a fanout hit and a
590
- // seed/hybrid hit for the same memory never inject twice (#2020).
598
+ // Dedup by composite (namespace, path) so a hit never injects twice (#2020).
591
599
  mergedResults = dedupeResultsByNamespace(
592
600
  [...primaryResults, ...hybridResults],
593
601
  this.deps.namespaceFromPath,
594
602
  fetchLimit,
595
- { transportFallback: "hybrid" },
603
+ { transportFallback: "hybrid", filter: recallable },
596
604
  );
597
605
  }
598
606
  }
@@ -603,6 +611,7 @@ export class RecallSearchPipelineCoordinator {
603
611
  [...scopedSeedResults, ...mergedResults],
604
612
  this.deps.namespaceFromPath,
605
613
  fetchLimit,
614
+ { filter: recallable },
606
615
  );
607
616
  }
608
617
 
@@ -685,18 +694,30 @@ export class RecallSearchPipelineCoordinator {
685
694
  if (cappedLimit === 0) return [];
686
695
  if (queryAwarePrefilter?.candidatePaths?.size === 0) return [];
687
696
 
688
- const scopedSeedResults = queryAwarePrefilter?.candidatePaths?.size
689
- ? await this.deps.searchScopedMemoryCandidates(
690
- queryAwarePrefilter.candidatePaths,
691
- prompt,
692
- cappedLimit,
693
- { allowArchived: true },
694
- )
695
- : [];
697
+ const candidatePaths = queryAwarePrefilter?.candidatePaths;
698
+ const scopedSeedResults = (
699
+ candidatePaths?.size
700
+ ? await this.deps.searchScopedMemoryCandidates(
701
+ candidatePaths,
702
+ prompt,
703
+ // Overfetch the FULL scoped candidate set BEFORE the generic-recall
704
+ // exclusion below. Capping to `cappedLimit` first lets excluded paths
705
+ // (artifacts, activity digests, meeting records) consume the caller's
706
+ // budget and drop legitimate hits with no refill — e.g. a prefilter of
707
+ // [meetingRecord, facts/a.md] at limit 1 would return nothing. The
708
+ // candidate set is an already-bounded prefilter, so its size is the
709
+ // natural ceiling; the post-exclusion cap is applied below.
710
+ candidatePaths.size,
711
+ { allowArchived: true },
712
+ )
713
+ : []
714
+ ).filter((result) => !isGenericRecallExcludedPath(result.path, this.deps.config.memoryDir));
715
+ // Non-recallable seed paths (artifacts, activity digests, meeting records) are
716
+ // excluded above AFTER an unconstrained candidate fetch, so the cap here counts
717
+ // only recallable seeds — and EVERY early-return / direct-caller path below
718
+ // returns already-filtered, budget-honoring seeds.
696
719
  if (scopedSeedResults.length >= cappedLimit) {
697
- return scopedSeedResults
698
- .filter((result) => !isGenericRecallExcludedPath(result.path, this.deps.config.memoryDir))
699
- .slice(0, cappedLimit);
720
+ return scopedSeedResults.slice(0, cappedLimit);
700
721
  }
701
722
 
702
723
  const tokens = Array.from(new Set(tokenizeRecallQuery(prompt)));
package/src/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { BoundedJsonlStateConfig } from "./bounded-jsonl-state.js";
2
+ import type { MeetingsConfig } from "./meetings/types.js";
2
3
  import type { ActivityConfig } from "./activity/types.js";
3
4
  import type { WearablesConfig } from "./wearables/types.js";
4
5
 
@@ -1217,6 +1218,11 @@ export interface PluginConfig extends BoundedJsonlStateConfig {
1217
1218
  */
1218
1219
  wearables: WearablesConfig;
1219
1220
  activity: ActivityConfig;
1221
+ /**
1222
+ * Retrospective meeting intelligence (issue #1900): detect + fuse meetings
1223
+ * from already-ingested audio + screen activity. Disabled by default.
1224
+ */
1225
+ meetings: MeetingsConfig;
1220
1226
  /**
1221
1227
  * At-rest encryption configuration (issue #690 PR 3/4).
1222
1228
  *
@@ -1243,6 +1249,8 @@ export interface PluginConfig extends BoundedJsonlStateConfig {
1243
1249
  // default — byte-identical pre-feature when enabled === false (rule 39).
1244
1250
  chat: ChatConfig;
1245
1251
  slotBehavior: SlotBehaviorConfig;
1252
+ /** OpenClaw bridge mode (#2120): `"embedded"` (default) or `"delegate"`. */
1253
+ bridgeMode: string;
1246
1254
  codexCompat: CodexCompatConfig;
1247
1255
  /**
1248
1256
  * When true (default), the extraction prompt instructs the LLM to classify