@remnic/core 9.22.0 → 9.22.2

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 (402) hide show
  1. package/dist/access-admin-ops-surface.d.ts +15 -12
  2. package/dist/access-admin-ops-surface.js +25 -24
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +13 -10
  5. package/dist/access-boundary.js +25 -24
  6. package/dist/access-cli.js +84 -82
  7. package/dist/access-cli.js.map +1 -1
  8. package/dist/access-http.d.ts +16 -9
  9. package/dist/access-http.js +33 -32
  10. package/dist/access-identity-continuity-surface.d.ts +9 -7
  11. package/dist/access-identity-continuity-surface.js +25 -24
  12. package/dist/access-lcm-surface.d.ts +12 -9
  13. package/dist/access-lcm-surface.js +25 -24
  14. package/dist/access-mcp-output-schemas.js +1 -1
  15. package/dist/access-mcp.d.ts +22 -10
  16. package/dist/access-mcp.js +31 -30
  17. package/dist/access-memory-search-fanout.d.ts +2 -2
  18. package/dist/{access-namespace-preflight-tmwQgCT6.d.ts → access-namespace-preflight-CmErR03h.d.ts} +1 -1
  19. package/dist/access-namespace-preflight.d.ts +3 -3
  20. package/dist/access-namespace-preflight.js +25 -24
  21. package/dist/access-observe-write-surface.d.ts +12 -9
  22. package/dist/access-observe-write-surface.js +25 -24
  23. package/dist/access-operations-batch.js +27 -26
  24. package/dist/access-operations.d.ts +16 -13
  25. package/dist/access-operations.js +28 -27
  26. package/dist/access-recall-concurrency.d.ts +12 -9
  27. package/dist/access-recall-concurrency.js +25 -24
  28. package/dist/access-recall-response.d.ts +12 -9
  29. package/dist/access-recall-response.js +25 -24
  30. package/dist/access-recall-surface.d.ts +14 -11
  31. package/dist/access-recall-surface.js +25 -24
  32. package/dist/access-schema.d.ts +76 -76
  33. package/dist/{access-service-BtxW52vv.d.ts → access-service-CKEROeFP.d.ts} +22 -11
  34. package/dist/access-service.d.ts +13 -10
  35. package/dist/access-service.js +25 -24
  36. package/dist/access-surface-catalog.d.ts +12 -9
  37. package/dist/access-surface-catalog.js +6 -0
  38. package/dist/access-surface-catalog.js.map +1 -1
  39. package/dist/access-wearables-meetings-surface.d.ts +78 -0
  40. package/dist/access-wearables-meetings-surface.js +22 -0
  41. package/dist/access-wearables-meetings-surface.js.map +1 -0
  42. package/dist/action-confidence.d.ts +1 -1
  43. package/dist/active-memory-bridge.d.ts +1 -1
  44. package/dist/active-recall.d.ts +1 -1
  45. package/dist/active-recall.js +2 -2
  46. package/dist/{auto-sync-UPTUVE4X.js → auto-sync-5OE5QOZB.js} +3 -3
  47. package/dist/behavior-learner.d.ts +1 -1
  48. package/dist/behavior-signals.d.ts +1 -1
  49. package/dist/bootstrap.d.ts +9 -7
  50. package/dist/briefing.d.ts +2 -2
  51. package/dist/briefing.js +5 -5
  52. package/dist/buffer-surprise-report.d.ts +1 -1
  53. package/dist/buffer.d.ts +2 -2
  54. package/dist/bulk-import/index.d.ts +3 -3
  55. package/dist/calibration.d.ts +1 -1
  56. package/dist/capabilities.d.ts +1 -1
  57. package/dist/{catalog-iWvWz61I.d.ts → catalog-BFTVo2Ez.d.ts} +1 -1
  58. package/dist/causal-behavior.d.ts +1 -1
  59. package/dist/causal-behavior.js +2 -2
  60. package/dist/causal-chain.js +2 -2
  61. package/dist/causal-consolidation.d.ts +1 -1
  62. package/dist/causal-consolidation.js +9 -9
  63. package/dist/causal-retrieval.js +2 -2
  64. package/dist/causal-trajectory-graph.d.ts +1 -1
  65. package/dist/causal-trajectory.js +1 -1
  66. package/dist/{chunk-GF22HWS2.js → chunk-2PHX3I5C.js} +7 -7
  67. package/dist/{chunk-JFDEYXF7.js → chunk-3NAHZQU3.js} +2 -2
  68. package/dist/{chunk-XBRPEGXF.js → chunk-3UOSVTFR.js} +5 -5
  69. package/dist/{chunk-TTKWTT72.js → chunk-3ZW6ZQO6.js} +3 -3
  70. package/dist/{chunk-UV72DEZD.js → chunk-4B77XSG5.js} +5 -5
  71. package/dist/{chunk-IC2TCZJ2.js → chunk-57QKLRBV.js} +3 -1
  72. package/dist/chunk-57QKLRBV.js.map +1 -0
  73. package/dist/{chunk-LMHDFOVV.js → chunk-5CPI2QWG.js} +3 -3
  74. package/dist/{chunk-P72WZMWQ.js → chunk-5FZQ74K5.js} +2 -2
  75. package/dist/{chunk-BRT7KEXU.js → chunk-6TWXQ4E2.js} +5 -5
  76. package/dist/{chunk-CV6ZYXK3.js → chunk-7I7AYIUQ.js} +3 -3
  77. package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
  78. package/dist/{chunk-MONWCSVL.js → chunk-7RAJ3GXO.js} +2 -1
  79. package/dist/chunk-7RAJ3GXO.js.map +1 -0
  80. package/dist/{chunk-SQEDDWAM.js → chunk-A2RFKL3V.js} +5 -34
  81. package/dist/chunk-A2RFKL3V.js.map +1 -0
  82. package/dist/{chunk-JN57HZCD.js → chunk-ATEAL5EI.js} +6 -6
  83. package/dist/{chunk-4PYLBXX6.js → chunk-AYAROCWD.js} +2 -2
  84. package/dist/chunk-BLDBT6HZ.js +39 -0
  85. package/dist/chunk-BLDBT6HZ.js.map +1 -0
  86. package/dist/{chunk-NB2P47N7.js → chunk-CUUY5CC4.js} +6 -6
  87. package/dist/{chunk-KL5Y6PEV.js → chunk-E3ZMFFQZ.js} +2 -2
  88. package/dist/{chunk-55FDQYPS.js → chunk-ES5IHQ6M.js} +2 -2
  89. package/dist/{chunk-N47ZWQBO.js → chunk-G2NSSQES.js} +2 -2
  90. package/dist/{chunk-GSWPU5CR.js → chunk-GD3QOBMB.js} +2 -2
  91. package/dist/{chunk-6ANPNUVL.js → chunk-IIXLB5E7.js} +58 -36
  92. package/dist/chunk-IIXLB5E7.js.map +1 -0
  93. package/dist/{chunk-SACPRJ7F.js → chunk-JNIJBXVK.js} +2 -2
  94. package/dist/{chunk-W3XT32W7.js → chunk-JVGUY2AU.js} +23 -13
  95. package/dist/chunk-JVGUY2AU.js.map +1 -0
  96. package/dist/{chunk-DGLON3AL.js → chunk-KNRG6ZGJ.js} +6 -6
  97. package/dist/{chunk-GEUDRENF.js → chunk-MMTG3SCJ.js} +2 -2
  98. package/dist/{chunk-WZFAPHIK.js → chunk-MU7ZHSZE.js} +2 -2
  99. package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
  100. package/dist/{chunk-QTO2FGBT.js → chunk-OUW4PAY4.js} +191 -117
  101. package/dist/chunk-OUW4PAY4.js.map +1 -0
  102. package/dist/{chunk-KQ2XCQYN.js → chunk-P2BLHUL2.js} +2 -2
  103. package/dist/{chunk-ACGGTPU4.js → chunk-QCKQEBIY.js} +17 -9
  104. package/dist/chunk-QCKQEBIY.js.map +1 -0
  105. package/dist/{chunk-6L775BUB.js → chunk-QE63OHLB.js} +2 -2
  106. package/dist/{chunk-ONHRRJZM.js → chunk-QJAQNXWI.js} +6 -6
  107. package/dist/{chunk-EQYBHXRR.js → chunk-ROUL7RZU.js} +385 -59
  108. package/dist/chunk-ROUL7RZU.js.map +1 -0
  109. package/dist/{chunk-N6M7MRVN.js → chunk-RT4TSR2C.js} +9034 -8726
  110. package/dist/chunk-RT4TSR2C.js.map +1 -0
  111. package/dist/{chunk-6NZ7U4R4.js → chunk-SCOT5DTA.js} +1 -1
  112. package/dist/chunk-SCOT5DTA.js.map +1 -0
  113. package/dist/{chunk-6RYWNBSA.js → chunk-SVZGA2MK.js} +2 -2
  114. package/dist/chunk-SYOIVK7K.js +63 -0
  115. package/dist/chunk-SYOIVK7K.js.map +1 -0
  116. package/dist/{chunk-DM5A4ZFL.js → chunk-TWCOYET2.js} +11 -1
  117. package/dist/chunk-TWCOYET2.js.map +1 -0
  118. package/dist/{chunk-7S5OMI76.js → chunk-WS32QRLO.js} +109 -44
  119. package/dist/chunk-WS32QRLO.js.map +1 -0
  120. package/dist/{chunk-OCMLGND7.js → chunk-WWZ35GWW.js} +5 -5
  121. package/dist/{chunk-QMGIQUBG.js → chunk-XWPFZX6S.js} +503 -139
  122. package/dist/chunk-XWPFZX6S.js.map +1 -0
  123. package/dist/{chunk-A5N6ISRK.js → chunk-ZN4UZWMT.js} +2 -2
  124. package/dist/{chunk-7M6APKJL.js → chunk-ZYU7ZFLT.js} +2 -2
  125. package/dist/{cli-D9vXgWwM.d.ts → cli-BrwT9YMD.d.ts} +5 -5
  126. package/dist/cli.d.ts +14 -11
  127. package/dist/cli.js +57 -56
  128. package/dist/compounding/engine.d.ts +2 -2
  129. package/dist/compounding/engine.js +5 -5
  130. package/dist/compounding/preference-consolidator.d.ts +1 -1
  131. package/dist/compression-optimizer.d.ts +1 -1
  132. package/dist/config.d.ts +1 -1
  133. package/dist/config.js +2 -2
  134. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  135. package/dist/connectors/codex-materialize-runner.js +5 -5
  136. package/dist/connectors/codex-materialize.d.ts +1 -1
  137. package/dist/connectors/index.d.ts +1 -1
  138. package/dist/connectors/index.js +5 -5
  139. package/dist/consolidation-provenance-check.d.ts +2 -2
  140. package/dist/consolidation-undo.d.ts +2 -2
  141. package/dist/contradiction/index.d.ts +2 -2
  142. package/dist/conversation-index/backend.d.ts +1 -1
  143. package/dist/conversation-index/chunker.d.ts +1 -1
  144. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  145. package/dist/conversation-index/indexer.d.ts +1 -1
  146. package/dist/conversation-index/search.d.ts +1 -1
  147. package/dist/day-summary.d.ts +1 -1
  148. package/dist/delinearize.d.ts +1 -1
  149. package/dist/direct-answer-wiring.d.ts +1 -1
  150. package/dist/direct-answer.d.ts +1 -1
  151. package/dist/embedding-fallback.d.ts +1 -1
  152. package/dist/enrichment/index.d.ts +1 -1
  153. package/dist/entity-retrieval.d.ts +2 -2
  154. package/dist/entity-retrieval.js +5 -5
  155. package/dist/entity-schema.d.ts +1 -1
  156. package/dist/explicit-capture.d.ts +9 -7
  157. package/dist/extraction-error-classification.d.ts +22 -0
  158. package/dist/extraction-error-classification.js +11 -0
  159. package/dist/extraction-error-classification.js.map +1 -0
  160. package/dist/extraction-faithfulness.d.ts +1 -1
  161. package/dist/extraction-judge-telemetry.d.ts +1 -1
  162. package/dist/extraction-judge-training.d.ts +1 -1
  163. package/dist/extraction-judge.d.ts +1 -1
  164. package/dist/extraction.d.ts +3 -17
  165. package/dist/extraction.js +5 -3
  166. package/dist/fallback-llm.d.ts +1 -1
  167. package/dist/{first-start-migration-LEXL3XYL.js → first-start-migration-BKNGOFED.js} +4 -4
  168. package/dist/graph-dashboard-diff.d.ts +1 -1
  169. package/dist/graph-dashboard-key.d.ts +1 -1
  170. package/dist/graph-dashboard-parser.d.ts +1 -1
  171. package/dist/graph-edge-reinforcement.d.ts +1 -1
  172. package/dist/graph-snapshot.d.ts +1 -1
  173. package/dist/graph.d.ts +1 -1
  174. package/dist/importance.d.ts +1 -1
  175. package/dist/importers/index.d.ts +1 -1
  176. package/dist/in-flight-reads.d.ts +1 -1
  177. package/dist/index.d.ts +713 -923
  178. package/dist/index.js +176 -140
  179. package/dist/intent.d.ts +1 -1
  180. package/dist/lcm/engine.d.ts +1 -1
  181. package/dist/lcm/engine.js +3 -3
  182. package/dist/lcm/index.d.ts +1 -1
  183. package/dist/lcm/index.js +11 -11
  184. package/dist/lcm/tools.d.ts +1 -1
  185. package/dist/lifecycle.d.ts +1 -1
  186. package/dist/live-connectors-runner.d.ts +1 -1
  187. package/dist/local-llm.d.ts +1 -1
  188. package/dist/local-model-endpoint.d.ts +1 -1
  189. package/dist/maintenance/memory-governance.d.ts +1 -1
  190. package/dist/maintenance/memory-governance.js +6 -6
  191. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  192. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -5
  193. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  194. package/dist/maintenance/rebuild-memory-projection.js +7 -7
  195. package/dist/maintenance-C98njYb8.d.ts +366 -0
  196. package/dist/mcp-memory-inspector-app.d.ts +12 -9
  197. package/dist/mcp-read-only-tools.js +1 -1
  198. package/dist/memory-action-policy.d.ts +1 -1
  199. package/dist/memory-cache.d.ts +1 -1
  200. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  201. package/dist/memory-projection-store.d.ts +1 -1
  202. package/dist/memory-provenance.d.ts +1 -1
  203. package/dist/memory-worth-outcomes.d.ts +2 -2
  204. package/dist/models-json.d.ts +1 -1
  205. package/dist/namespaces/migrate.d.ts +3 -3
  206. package/dist/namespaces/migrate.js +12 -12
  207. package/dist/namespaces/principal.d.ts +1 -1
  208. package/dist/namespaces/search.d.ts +1 -1
  209. package/dist/namespaces/search.js +6 -6
  210. package/dist/namespaces/storage.d.ts +3 -3
  211. package/dist/namespaces/storage.js +5 -5
  212. package/dist/native-knowledge.d.ts +1 -1
  213. package/dist/offline-sync-impression-drain.d.ts +1 -1
  214. package/dist/operator-toolkit.d.ts +2 -2
  215. package/dist/operator-toolkit.js +18 -18
  216. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  217. package/dist/orchestration/maintenance.d.ts +6 -223
  218. package/dist/orchestration/maintenance.js +12 -12
  219. package/dist/{orchestrator-DB93S48I.d.ts → orchestrator-C9ZVppNh.d.ts} +12 -481
  220. package/dist/orchestrator.d.ts +10 -8
  221. package/dist/orchestrator.js +84 -82
  222. package/dist/patterns-cli.d.ts +1 -1
  223. package/dist/{pipeline-DmGc-H66.d.ts → pipeline-id_-sqYm.d.ts} +1 -1
  224. package/dist/policy-runtime.d.ts +1 -1
  225. package/dist/proactive-contention.d.ts +1 -1
  226. package/dist/provenance.d.ts +1 -1
  227. package/dist/{qmd-cJT0crkF.d.ts → qmd-R6XaQOZK.d.ts} +1 -1
  228. package/dist/qmd-preflight.d.ts +2 -2
  229. package/dist/qmd-recall-cache.d.ts +1 -1
  230. package/dist/qmd.d.ts +2 -2
  231. package/dist/qmd.js +4 -4
  232. package/dist/recall-concurrency-config.d.ts +1 -1
  233. package/dist/recall-disclosure-escalation.d.ts +1 -1
  234. package/dist/recall-explain-renderer.d.ts +1 -1
  235. package/dist/recall-explain-renderer.js +3 -3
  236. package/dist/recall-memory-map.d.ts +1 -1
  237. package/dist/recall-planner-llm.d.ts +1 -1
  238. package/dist/recall-state.d.ts +1 -1
  239. package/dist/recall-tag-filter.d.ts +1 -1
  240. package/dist/recall-timings.d.ts +1 -1
  241. package/dist/recall-xray-cli.d.ts +1 -1
  242. package/dist/recall-xray-cli.js +4 -4
  243. package/dist/recall-xray-renderer.d.ts +1 -1
  244. package/dist/recall-xray-renderer.js +3 -3
  245. package/dist/recall-xray.d.ts +1 -1
  246. package/dist/recall-xray.js +2 -2
  247. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  248. package/dist/replay/normalizers/claude.d.ts +1 -1
  249. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  250. package/dist/replay/normalizers/shared.d.ts +1 -1
  251. package/dist/replay/runner.d.ts +1 -1
  252. package/dist/replay/types.d.ts +1 -1
  253. package/dist/resolve-auth-token.d.ts +1 -1
  254. package/dist/resume-bundles.js +4 -4
  255. package/dist/retrieval-agents.d.ts +2 -2
  256. package/dist/retrieval-tiers.d.ts +1 -1
  257. package/dist/routing/engine.d.ts +1 -1
  258. package/dist/routing/store.d.ts +1 -1
  259. package/dist/salvage-envelope.d.ts +1 -1
  260. package/dist/schemas.d.ts +76 -76
  261. package/dist/{scope-profiles-KG2nODX7.d.ts → scope-profiles-EhyuAKkd.d.ts} +1 -1
  262. package/dist/search/embed-helper.d.ts +1 -1
  263. package/dist/search/factory.d.ts +1 -1
  264. package/dist/search/factory.js +5 -5
  265. package/dist/search/index.d.ts +1 -1
  266. package/dist/search/index.js +9 -9
  267. package/dist/search/lancedb-backend.d.ts +1 -1
  268. package/dist/search/meilisearch-backend.d.ts +1 -1
  269. package/dist/search/noop-backend.d.ts +1 -1
  270. package/dist/search/orama-backend.d.ts +1 -1
  271. package/dist/search/port.d.ts +1 -1
  272. package/dist/search/remote-backend.d.ts +1 -1
  273. package/dist/{semantic-consolidation-BaZlg0D8.d.ts → semantic-consolidation-B2xo26UQ.d.ts} +1 -1
  274. package/dist/semantic-consolidation.d.ts +2 -2
  275. package/dist/semantic-consolidation.js +7 -7
  276. package/dist/semantic-rule-promotion.js +5 -5
  277. package/dist/semantic-rule-verifier.d.ts +1 -1
  278. package/dist/semantic-rule-verifier.js +6 -6
  279. package/dist/service-DgFWlZ-r.d.ts +835 -0
  280. package/dist/session-observer-bands.d.ts +1 -1
  281. package/dist/session-observer-state.d.ts +1 -1
  282. package/dist/shared-context/manager.d.ts +9 -9
  283. package/dist/signal.d.ts +1 -1
  284. package/dist/{storage-BKhHHnRo.d.ts → storage-XGawwqXE.d.ts} +131 -2
  285. package/dist/storage.d.ts +2 -2
  286. package/dist/storage.js +4 -4
  287. package/dist/summarizer.d.ts +1 -1
  288. package/dist/summary-snapshot.d.ts +1 -1
  289. package/dist/temporal-supersession.d.ts +2 -2
  290. package/dist/temporal-timeline-recall.d.ts +1 -1
  291. package/dist/temporal-validity.d.ts +1 -1
  292. package/dist/threading.d.ts +1 -1
  293. package/dist/tier-migration.d.ts +2 -2
  294. package/dist/tier-routing.d.ts +1 -1
  295. package/dist/topics.d.ts +1 -1
  296. package/dist/transcript.d.ts +1 -1
  297. package/dist/transfer/types.d.ts +66 -66
  298. package/dist/trust-score-stage.d.ts +1 -1
  299. package/dist/trust-score.d.ts +1 -1
  300. package/dist/{types-GBQZuT7l.d.ts → types-Bbs0qz6b.d.ts} +2 -3
  301. package/dist/types.d.ts +1 -1
  302. package/dist/types.js +1 -1
  303. package/dist/utility-runtime.d.ts +1 -1
  304. package/dist/verified-recall.js +6 -6
  305. package/dist/write-envelope.d.ts +1 -1
  306. package/package.json +2 -2
  307. package/src/access-boundary.ts +3 -0
  308. package/src/access-http.test.ts +63 -0
  309. package/src/access-http.ts +26 -37
  310. package/src/access-mcp-output-schemas.ts +10 -0
  311. package/src/access-mcp.ts +4 -121
  312. package/src/access-operations-batch.ts +10 -5
  313. package/src/access-service.ts +43 -46
  314. package/src/access-surface-catalog.ts +6 -0
  315. package/src/access-wearables-meetings-surface.ts +139 -0
  316. package/src/activity/digest.ts +1 -1
  317. package/src/activity/runner.test.ts +37 -0
  318. package/src/activity/runner.ts +12 -0
  319. package/src/activity/scheduler.test.ts +1 -0
  320. package/src/activity/sync-registration.ts +13 -0
  321. package/src/cli/meetings-commands.ts +70 -0
  322. package/src/cli.ts +7 -6
  323. package/src/extraction-error-classification.ts +52 -0
  324. package/src/extraction.ts +2 -50
  325. package/src/mcp-read-only-tools.ts +2 -0
  326. package/src/meetings/build-memory.test.ts +364 -0
  327. package/src/meetings/build-scheduler.test.ts +55 -0
  328. package/src/meetings/build-scheduler.ts +96 -0
  329. package/src/meetings/day-source.test.ts +275 -0
  330. package/src/meetings/day-source.ts +352 -0
  331. package/src/meetings/http-glue.ts +126 -0
  332. package/src/meetings/index.ts +5 -4
  333. package/src/meetings/manual-sync-flush.test.ts +72 -0
  334. package/src/meetings/mcp-tools.ts +65 -0
  335. package/src/meetings/memory-gen.test.ts +498 -0
  336. package/src/meetings/memory-gen.ts +549 -0
  337. package/src/meetings/memory-generator.ts +5 -0
  338. package/src/meetings/namespace-isolation.test.ts +159 -0
  339. package/src/meetings/service.test.ts +195 -0
  340. package/src/meetings/service.ts +157 -0
  341. package/src/meetings/summary-extractor.test.ts +287 -0
  342. package/src/meetings/summary-extractor.ts +264 -0
  343. package/src/orchestration/maintenance.ts +8 -0
  344. package/src/orchestration/orchestrator-init.ts +6 -1
  345. package/src/orchestration/workspace-ops.ts +172 -8
  346. package/src/orchestrator.ts +12 -13
  347. package/src/storage.ts +21 -0
  348. package/src/testing/subjects/meetings-namespace-harness.ts +159 -0
  349. package/src/testing/subjects/meetings-namespace.test.ts +93 -0
  350. package/src/types.ts +1 -2
  351. package/src/wearables/cli.ts +2 -1
  352. package/src/wearables/index.ts +1 -0
  353. package/src/wearables/mcp-tools.ts +143 -0
  354. package/src/wearables/registry.test.ts +11 -0
  355. package/src/wearables/registry.ts +13 -0
  356. package/src/wearables/service.test.ts +62 -1
  357. package/src/wearables/service.ts +30 -2
  358. package/src/wearables/transcript-search-namespace-isolation.test.ts +98 -0
  359. package/dist/chunk-6ANPNUVL.js.map +0 -1
  360. package/dist/chunk-6NZ7U4R4.js.map +0 -1
  361. package/dist/chunk-7S5OMI76.js.map +0 -1
  362. package/dist/chunk-ACGGTPU4.js.map +0 -1
  363. package/dist/chunk-DM5A4ZFL.js.map +0 -1
  364. package/dist/chunk-EQYBHXRR.js.map +0 -1
  365. package/dist/chunk-IC2TCZJ2.js.map +0 -1
  366. package/dist/chunk-MONWCSVL.js.map +0 -1
  367. package/dist/chunk-N6M7MRVN.js.map +0 -1
  368. package/dist/chunk-QMGIQUBG.js.map +0 -1
  369. package/dist/chunk-QTO2FGBT.js.map +0 -1
  370. package/dist/chunk-SQEDDWAM.js.map +0 -1
  371. package/dist/chunk-W3XT32W7.js.map +0 -1
  372. /package/dist/{auto-sync-UPTUVE4X.js.map → auto-sync-5OE5QOZB.js.map} +0 -0
  373. /package/dist/{chunk-GF22HWS2.js.map → chunk-2PHX3I5C.js.map} +0 -0
  374. /package/dist/{chunk-JFDEYXF7.js.map → chunk-3NAHZQU3.js.map} +0 -0
  375. /package/dist/{chunk-XBRPEGXF.js.map → chunk-3UOSVTFR.js.map} +0 -0
  376. /package/dist/{chunk-TTKWTT72.js.map → chunk-3ZW6ZQO6.js.map} +0 -0
  377. /package/dist/{chunk-UV72DEZD.js.map → chunk-4B77XSG5.js.map} +0 -0
  378. /package/dist/{chunk-LMHDFOVV.js.map → chunk-5CPI2QWG.js.map} +0 -0
  379. /package/dist/{chunk-P72WZMWQ.js.map → chunk-5FZQ74K5.js.map} +0 -0
  380. /package/dist/{chunk-BRT7KEXU.js.map → chunk-6TWXQ4E2.js.map} +0 -0
  381. /package/dist/{chunk-CV6ZYXK3.js.map → chunk-7I7AYIUQ.js.map} +0 -0
  382. /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
  383. /package/dist/{chunk-JN57HZCD.js.map → chunk-ATEAL5EI.js.map} +0 -0
  384. /package/dist/{chunk-4PYLBXX6.js.map → chunk-AYAROCWD.js.map} +0 -0
  385. /package/dist/{chunk-NB2P47N7.js.map → chunk-CUUY5CC4.js.map} +0 -0
  386. /package/dist/{chunk-KL5Y6PEV.js.map → chunk-E3ZMFFQZ.js.map} +0 -0
  387. /package/dist/{chunk-55FDQYPS.js.map → chunk-ES5IHQ6M.js.map} +0 -0
  388. /package/dist/{chunk-N47ZWQBO.js.map → chunk-G2NSSQES.js.map} +0 -0
  389. /package/dist/{chunk-GSWPU5CR.js.map → chunk-GD3QOBMB.js.map} +0 -0
  390. /package/dist/{chunk-SACPRJ7F.js.map → chunk-JNIJBXVK.js.map} +0 -0
  391. /package/dist/{chunk-DGLON3AL.js.map → chunk-KNRG6ZGJ.js.map} +0 -0
  392. /package/dist/{chunk-GEUDRENF.js.map → chunk-MMTG3SCJ.js.map} +0 -0
  393. /package/dist/{chunk-WZFAPHIK.js.map → chunk-MU7ZHSZE.js.map} +0 -0
  394. /package/dist/{chunk-W4FBGYGK.js.map → chunk-NRV4Y3PM.js.map} +0 -0
  395. /package/dist/{chunk-KQ2XCQYN.js.map → chunk-P2BLHUL2.js.map} +0 -0
  396. /package/dist/{chunk-6L775BUB.js.map → chunk-QE63OHLB.js.map} +0 -0
  397. /package/dist/{chunk-ONHRRJZM.js.map → chunk-QJAQNXWI.js.map} +0 -0
  398. /package/dist/{chunk-6RYWNBSA.js.map → chunk-SVZGA2MK.js.map} +0 -0
  399. /package/dist/{chunk-OCMLGND7.js.map → chunk-WWZ35GWW.js.map} +0 -0
  400. /package/dist/{chunk-A5N6ISRK.js.map → chunk-ZN4UZWMT.js.map} +0 -0
  401. /package/dist/{chunk-7M6APKJL.js.map → chunk-ZYU7ZFLT.js.map} +0 -0
  402. /package/dist/{first-start-migration-LEXL3XYL.js.map → first-start-migration-BKNGOFED.js.map} +0 -0
@@ -2895,3 +2895,66 @@ test("HTTP namespace/writable preflight admits write-scoped tokens and rejects r
2895
2895
  await server.stop();
2896
2896
  }
2897
2897
  });
2898
+
2899
+ test("HTTP meetings build enforces the per-principal write rate limit (issue #1937)", async () => {
2900
+ let builds = 0;
2901
+ const service = {
2902
+ meetingsBuild: async (date: string) => {
2903
+ builds += 1;
2904
+ return { enabled: true, date, meetings: [] };
2905
+ },
2906
+ } as unknown as EngramAccessService;
2907
+ const server = new EngramAccessHttpServer({
2908
+ service,
2909
+ port: 0,
2910
+ authToken: "test-token",
2911
+ adminConsoleEnabled: false,
2912
+ writeRateLimitMaxRequests: 1,
2913
+ });
2914
+ const status = await server.start();
2915
+ try {
2916
+ const build = () =>
2917
+ fetch(`http://127.0.0.1:${status.port}/engram/v1/meetings/build`, {
2918
+ method: "POST",
2919
+ headers: { authorization: "Bearer test-token", "content-type": "application/json" },
2920
+ body: JSON.stringify({ date: "2026-03-10" }),
2921
+ });
2922
+ const first = await build();
2923
+ assert.equal(first.status, 200, "the first build is within the write quota");
2924
+ const second = await build();
2925
+ assert.equal(second.status, 429, "the second build exceeds the per-principal write quota");
2926
+ const rateLimited = await second.json() as { code?: string };
2927
+ assert.equal(rateLimited.code, "write_rate_limited");
2928
+ assert.equal(builds, 1, "the rate-limited build never reached the service (no persist/reindex)");
2929
+ } finally {
2930
+ await server.stop();
2931
+ }
2932
+ });
2933
+
2934
+ test("HTTP meetings get returns 400 (not 500) for a malformed percent-encoded id (issue #1900)", async () => {
2935
+ let called = 0;
2936
+ const service = {
2937
+ meetingsGet: async () => {
2938
+ called += 1;
2939
+ return { enabled: true, found: false, id: "x", record: null };
2940
+ },
2941
+ } as unknown as EngramAccessService;
2942
+ const server = new EngramAccessHttpServer({
2943
+ service,
2944
+ port: 0,
2945
+ authToken: "test-token",
2946
+ adminConsoleEnabled: false,
2947
+ });
2948
+ const status = await server.start();
2949
+ try {
2950
+ const response = await fetch(`http://127.0.0.1:${status.port}/engram/v1/meetings/%E0%A4%A`, {
2951
+ headers: { authorization: "Bearer test-token" },
2952
+ });
2953
+ assert.equal(response.status, 400, "a malformed id is a client error, not an internal 500");
2954
+ const errorBody = await response.json() as { code?: string };
2955
+ assert.equal(errorBody.code, "invalid_request");
2956
+ assert.equal(called, 0, "the malformed id never reached the service");
2957
+ } finally {
2958
+ await server.stop();
2959
+ }
2960
+ });
@@ -13,11 +13,12 @@ import { EngramAccessForbiddenError } from "./access-errors.js";
13
13
  import {
14
14
  EngramAccessInputError,
15
15
  type EngramAccessService,
16
+ type WearablesMeetingsScope,
16
17
  type EngramAccessMemoryResponse,
17
18
  type EngramAccessWriteResponse,
18
19
  } from "./access-service.js";
19
20
  import { CorrectionContractError } from "./correction/correction-contract.js";
20
- import { WearablesInputError } from "./wearables/errors.js";
21
+ import { WearablesInputError } from "./wearables/errors.js"; import { respondMeetingsList, respondMeetingsGet, respondMeetingsBuild } from "./meetings/http-glue.js";
21
22
  import { EngramMcpServer, MCP_SUPPORTED_PROTOCOL_VERSIONS } from "./access-mcp.js";
22
23
  import { validateRequest, type SchemaName, type SchemaTypeFor } from "./access-schema.js";
23
24
  import {
@@ -349,9 +350,7 @@ function decodeRelayMissionIdSegment(raw: string): string {
349
350
  try {
350
351
  return decodeURIComponent(raw);
351
352
  } catch {
352
- throw new EngramAccessInputError(
353
- "missionId path segment is not valid percent-encoded input",
354
- );
353
+ throw new EngramAccessInputError("missionId path segment is not valid percent-encoded input");
355
354
  }
356
355
  }
357
356
 
@@ -713,6 +712,13 @@ export class EngramAccessHttpServer {
713
712
  return this.resolveRequestIdentity(req).principal;
714
713
  }
715
714
 
715
+ /** Caller scope for wearables/meetings ops (issue #2123): request principal +
716
+ * gated namespace + optional sessionKey, so reads/writes resolve to the caller
717
+ * namespace instead of the machine default. */
718
+ private wearablesScope(req: IncomingMessage, namespace?: string, sessionKey?: string): WearablesMeetingsScope {
719
+ return { authenticatedPrincipal: this.resolveRequestPrincipal(req), namespace: this.resolveNamespace(req, namespace), ...(sessionKey ? { sessionKey } : {}) };
720
+ }
721
+
716
722
  /** Resolve namespace: only use the explicit body value. Adapter-inferred namespace
717
723
  * is intentionally NOT used as a fallback for REST requests — omitting namespace
718
724
  * should default to the server's global namespace, not silently scope to an adapter. */
@@ -725,11 +731,7 @@ export class EngramAccessHttpServer {
725
731
  // and the id-loaded contradiction routes — one rule, every surface. The
726
732
  // effective namespace (explicit OR server default) must be a member; fail
727
733
  // closed. No-op for unrestricted tokens (no namespaces allow-list).
728
- enforceNamespaceAllowList(
729
- tokenCapabilityStore.getStore(),
730
- namespace,
731
- this.service.configRef?.defaultNamespace,
732
- );
734
+ enforceNamespaceAllowList(tokenCapabilityStore.getStore(), namespace, this.service.configRef?.defaultNamespace);
733
735
  return namespace;
734
736
  }
735
737
 
@@ -1351,11 +1353,7 @@ export class EngramAccessHttpServer {
1351
1353
  req,
1352
1354
  namespaceParam && namespaceParam.length > 0 ? namespaceParam : undefined,
1353
1355
  );
1354
- const payload = await this.service.recallTierExplain(
1355
- sessionKey,
1356
- namespace,
1357
- this.resolveRequestPrincipal(req),
1358
- );
1356
+ const payload = await this.service.recallTierExplain(sessionKey, namespace, this.resolveRequestPrincipal(req));
1359
1357
  this.respondJson(res, 200, payload);
1360
1358
  return;
1361
1359
  }
@@ -1493,7 +1491,7 @@ export class EngramAccessHttpServer {
1493
1491
  (pathname === "/engram/v1/wearables/status" || pathname === "/remnic/v1/wearables/status")
1494
1492
  ) {
1495
1493
  this.enforceTokenOp("wearables_status"); // boundary dispatch (issue #1525)
1496
- this.respondJson(res, 200, await this.service.wearablesStatus());
1494
+ this.respondJson(res, 200, await this.service.wearablesStatus(this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined)));
1497
1495
  return;
1498
1496
  }
1499
1497
 
@@ -1524,12 +1522,7 @@ export class EngramAccessHttpServer {
1524
1522
  );
1525
1523
  }
1526
1524
  try {
1527
- const summaries = await this.service.wearablesSync({
1528
- source,
1529
- date,
1530
- days,
1531
- forceMemories: body.forceMemories === true,
1532
- });
1525
+ const summaries = await this.service.wearablesSync({ source, date, days, forceMemories: body.forceMemories === true, ...this.wearablesScope(req, optionalQueryString(body.namespace, "namespace"), optionalQueryString(body.sessionKey, "sessionKey")) });
1533
1526
  this.respondJson(res, 200, { summaries });
1534
1527
  } catch (err) {
1535
1528
  if (this.respondWearablesError(res, err)) return;
@@ -1551,10 +1544,7 @@ export class EngramAccessHttpServer {
1551
1544
  }
1552
1545
  const sourceParam = parsed.searchParams.get("source");
1553
1546
  try {
1554
- const transcripts = await this.service.wearablesTranscriptDay({
1555
- date,
1556
- source: sourceParam && sourceParam.length > 0 ? sourceParam : undefined,
1557
- });
1547
+ const transcripts = await this.service.wearablesTranscriptDay({ date, source: sourceParam && sourceParam.length > 0 ? sourceParam : undefined, ...this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined) });
1558
1548
  this.respondJson(res, 200, { transcripts });
1559
1549
  } catch (err) {
1560
1550
  if (this.respondWearablesError(res, err)) return;
@@ -1576,13 +1566,7 @@ export class EngramAccessHttpServer {
1576
1566
  );
1577
1567
  }
1578
1568
  try {
1579
- const results = await this.service.wearablesTranscriptSearch({
1580
- query: queryParam,
1581
- source: nonEmptyQueryParam(parsed.searchParams.get("source")),
1582
- from: nonEmptyQueryParam(parsed.searchParams.get("from")),
1583
- to: nonEmptyQueryParam(parsed.searchParams.get("to")),
1584
- limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"),
1585
- });
1569
+ const results = await this.service.wearablesTranscriptSearch({ query: queryParam, source: nonEmptyQueryParam(parsed.searchParams.get("source")), from: nonEmptyQueryParam(parsed.searchParams.get("from")), to: nonEmptyQueryParam(parsed.searchParams.get("to")), limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"), ...this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined) });
1586
1570
  this.respondJson(res, 200, { results });
1587
1571
  } catch (err) {
1588
1572
  if (this.respondWearablesError(res, err)) return;
@@ -1597,11 +1581,7 @@ export class EngramAccessHttpServer {
1597
1581
  ) {
1598
1582
  this.enforceTokenOp("transcript_memories"); // boundary dispatch (issue #1525)
1599
1583
  try {
1600
- const memories = await this.service.wearablesTranscriptMemories({
1601
- source: nonEmptyQueryParam(parsed.searchParams.get("source")),
1602
- date: nonEmptyQueryParam(parsed.searchParams.get("date")),
1603
- limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"),
1604
- });
1584
+ const memories = await this.service.wearablesTranscriptMemories({ source: nonEmptyQueryParam(parsed.searchParams.get("source")), date: nonEmptyQueryParam(parsed.searchParams.get("date")), limit: positiveIntQueryParam(parsed.searchParams.get("limit"), "limit"), ...this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined) });
1605
1585
  this.respondJson(res, 200, { memories });
1606
1586
  } catch (err) {
1607
1587
  if (this.respondWearablesError(res, err)) return;
@@ -1610,6 +1590,15 @@ export class EngramAccessHttpServer {
1610
1590
  return;
1611
1591
  }
1612
1592
 
1593
+ if (req.method === "GET" && (pathname === "/engram/v1/meetings" || pathname === "/remnic/v1/meetings")) {
1594
+ this.enforceTokenOp("meetings_list"); await respondMeetingsList(res, this.respondJson.bind(this), this.service, nonEmptyQueryParam(parsed.searchParams.get("date")), this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined)); return; }
1595
+ if (req.method === "POST" && (pathname === "/engram/v1/meetings/build" || pathname === "/remnic/v1/meetings/build")) {
1596
+ this.enforceTokenOp("meetings_build"); await respondMeetingsBuild(req, res, this.respondJson.bind(this), this.readJsonBody.bind(this), this.service, { enforceQuota: () => this.ensureWriteRateLimitAvailable(req), recordHit: () => this.recordWriteRateLimitHit(req) }, (ns, sk) => this.wearablesScope(req, ns, sk)); return; }
1597
+ const meetingGetEngram = /^\/engram\/v1\/meetings\/([^/]+)$/.exec(pathname);
1598
+ if (req.method === "GET" && meetingGetEngram) { this.enforceTokenOp("meetings_get"); await respondMeetingsGet(res, this.respondJson.bind(this), this.service, meetingGetEngram[1] ?? "", this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined)); return; }
1599
+ const meetingGetRemnic = /^\/remnic\/v1\/meetings\/([^/]+)$/.exec(pathname);
1600
+ if (req.method === "GET" && meetingGetRemnic) { this.enforceTokenOp("meetings_get"); await respondMeetingsGet(res, this.respondJson.bind(this), this.service, meetingGetRemnic[1] ?? "", this.wearablesScope(req, parsed.searchParams.get("namespace") ?? undefined, parsed.searchParams.get("sessionKey") ?? undefined)); return; }
1601
+
1613
1602
  if (req.method === "POST" && pathname === "/engram/v1/observe") {
1614
1603
  this.enforceTokenOp("observe"); // boundary dispatch (issue #1525)
1615
1604
  const body = await this.readValidatedBody(req, "observe");
@@ -56,6 +56,16 @@ const TOOL_OUTPUT_SCHEMAS: Readonly<Record<string, Record<string, unknown>>> = {
56
56
  transcript_day: T_ARRAY,
57
57
  transcript_search: T_ARRAY,
58
58
  transcript_memories: T_ARRAY,
59
+ meetings_list: objectSchema({ enabled: T_BOOLEAN, days: T_ARRAY }),
60
+ meetings_get: objectSchema({ enabled: T_BOOLEAN, found: T_BOOLEAN, id: T_STRING, record: T_NULLABLE_STRING }),
61
+ meetings_build: objectSchema({
62
+ date: T_STRING,
63
+ enabled: T_BOOLEAN,
64
+ meetings: T_ARRAY,
65
+ built: T_NUMBER,
66
+ skipped: T_NUMBER,
67
+ removed: T_ARRAY,
68
+ }),
59
69
  action_confidence: objectSchema({
60
70
  schemaVersion: T_NUMBER,
61
71
  decision: T_STRING,
package/src/access-mcp.ts CHANGED
@@ -43,7 +43,7 @@ import type { RecallDisclosure, RecallPlanMode } from "./types.js";
43
43
  import { expandTildePath } from "./utils/path.js";
44
44
 
45
45
  import { applyToolOutputSchemas } from "./access-mcp-output-schemas.js";
46
- import { MCP_READ_ONLY_TOOL_SUFFIXES } from "./mcp-read-only-tools.js";
46
+ import { MCP_READ_ONLY_TOOL_SUFFIXES } from "./mcp-read-only-tools.js";import { MEETINGS_MCP_TOOLS } from "./meetings/mcp-tools.js";import { WEARABLES_MCP_TOOLS } from "./wearables/mcp-tools.js";
47
47
  import { abortError, isAbortError } from "./abort-error.js";
48
48
  type JsonRpcId = string | number | null;
49
49
 
@@ -82,7 +82,7 @@ type McpRequestOptions = {
82
82
  abortSignal?: AbortSignal;
83
83
  };
84
84
 
85
- type McpTool = {
85
+ export type McpTool = {
86
86
  name: string;
87
87
  title?: string;
88
88
  description: string;
@@ -188,7 +188,7 @@ const MCP_MIGRATED_OPERATIONS: Readonly<Record<string, OperationName>> = {
188
188
  "engram.wearables_sync": "wearables_sync",
189
189
  "engram.transcript_day": "transcript_day",
190
190
  "engram.transcript_search": "transcript_search",
191
- "engram.transcript_memories": "transcript_memories",
191
+ "engram.transcript_memories": "transcript_memories", "engram.meetings_list": "meetings_list", "engram.meetings_get": "meetings_get", "engram.meetings_build": "meetings_build",
192
192
  "engram.action_confidence": "action_confidence",
193
193
  "engram.chatgpt_memory_inspector": "chatgpt_memory_inspector",
194
194
  "engram.day_summary": "day_summary",
@@ -682,124 +682,7 @@ export class EngramMcpServer {
682
682
  additionalProperties: false,
683
683
  },
684
684
  },
685
- {
686
- name: "engram.wearables_status",
687
- description:
688
- "Status of wearable transcript sources (Limitless / Bee / Omi): configured sources, connector availability, last sync, stored transcript days.",
689
- inputSchema: {
690
- type: "object",
691
- properties: {},
692
- additionalProperties: false,
693
- },
694
- },
695
- {
696
- name: "engram.wearables_sync",
697
- description:
698
- "Pull, clean, and store wearable transcripts for one source or all enabled sources; optionally creates trust-gated memories per the source's memoryMode.",
699
- inputSchema: {
700
- type: "object",
701
- properties: {
702
- source: {
703
- type: "string",
704
- description: "Source id (e.g. limitless, bee, omi). Omit to sync every enabled source.",
705
- },
706
- date: {
707
- type: "string",
708
- description: "Sync exactly this day (YYYY-MM-DD). Overrides days.",
709
- },
710
- days: {
711
- type: "integer",
712
- minimum: 1,
713
- maximum: 90,
714
- description: "Lookback window in days ending today (default 2).",
715
- },
716
- forceMemories: {
717
- type: "boolean",
718
- description: "Re-run memory extraction even for unchanged days.",
719
- },
720
- },
721
- additionalProperties: false,
722
- },
723
- },
724
- {
725
- name: "engram.transcript_day",
726
- description:
727
- "Return the full stored wearable transcript(s) for a day, across all sources or one source, with cross-source overlap hints.",
728
- inputSchema: {
729
- type: "object",
730
- properties: {
731
- date: {
732
- type: "string",
733
- description: "Day to read (YYYY-MM-DD). Required.",
734
- },
735
- source: {
736
- type: "string",
737
- description: "Optional source id to scope to (e.g. limitless).",
738
- },
739
- },
740
- required: ["date"],
741
- additionalProperties: false,
742
- },
743
- },
744
- {
745
- name: "engram.transcript_search",
746
- description:
747
- "Search stored wearable transcripts. Results carry source + date so callers can pull the full day via engram.transcript_day.",
748
- inputSchema: {
749
- type: "object",
750
- properties: {
751
- query: {
752
- type: "string",
753
- description: "Search query. Required; non-empty.",
754
- },
755
- source: {
756
- type: "string",
757
- description: "Optional source id filter.",
758
- },
759
- from: {
760
- type: "string",
761
- description: "Optional inclusive start date (YYYY-MM-DD).",
762
- },
763
- to: {
764
- type: "string",
765
- description: "Optional inclusive end date (YYYY-MM-DD).",
766
- },
767
- limit: {
768
- type: "integer",
769
- minimum: 1,
770
- maximum: 50,
771
- description: "Maximum results (default 10).",
772
- },
773
- },
774
- required: ["query"],
775
- additionalProperties: false,
776
- },
777
- },
778
- {
779
- name: "engram.transcript_memories",
780
- description:
781
- "List memories created from wearable transcripts, filterable by source and/or day. Includes pending_review candidates awaiting approval.",
782
- inputSchema: {
783
- type: "object",
784
- properties: {
785
- source: {
786
- type: "string",
787
- description: "Optional source id filter (e.g. limitless).",
788
- },
789
- date: {
790
- type: "string",
791
- description: "Optional transcript day filter (YYYY-MM-DD).",
792
- },
793
- limit: {
794
- type: "integer",
795
- minimum: 1,
796
- maximum: 200,
797
- description: "Maximum results (default 50).",
798
- },
799
- },
800
- additionalProperties: false,
801
- },
802
- },
685
+ ...WEARABLES_MCP_TOOLS, ...MEETINGS_MCP_TOOLS,
803
686
  {
804
687
  name: "engram.action_confidence",
805
688
  description:
@@ -140,11 +140,16 @@ defineOperation({ name: "namespace_writable", description: "Read-only preflight:
140
140
  } });
141
141
 
142
142
  // === WEARABLES ===
143
- defineOperation({ name: "wearables_status", description: "Wearables status.", schema: strictSchema({}), handler: async (_i, ctx) => ({ result: await ctx.service.wearablesStatus() }) });
144
- defineOperation({ name: "wearables_sync", description: "Sync wearables.", schema: strictSchema({ source: S.str, date: S.str, days: S.flexNum, forceMemories: S.bool }), handler: async (input, ctx) => ({ result: await ctx.service.wearablesSync({ source: optStr(input.source), date: optStr(input.date), days: typeof input.days === "number" ? input.days : typeof input.days === "string" && Number.isFinite(Number(input.days)) ? Number(input.days) : undefined, forceMemories: optBool(input.forceMemories) }) }) });
145
- defineOperation({ name: "transcript_day", description: "Transcript for a day.", schema: strictSchema({ date: S.str, source: S.str }), handler: async (input, ctx) => { const d = defStr(input.date, ""); if (d.trim().length === 0) throw new EngramAccessInputError("transcript_day: date is required (YYYY-MM-DD)"); return { result: await ctx.service.wearablesTranscriptDay({ date: d, source: optStr(input.source) }) }; } });
146
- defineOperation({ name: "transcript_search", description: "Search transcripts.", schema: strictSchema({ query: S.str, source: S.str, from: S.str, to: S.str, limit: S.flexNum }), handler: async (input, ctx) => { const q = defStr(input.query, ""); if (q.trim().length === 0) throw new EngramAccessInputError("transcript_search: query is required"); return { result: await ctx.service.wearablesTranscriptSearch({ query: q, source: optStr(input.source), from: optStr(input.from), to: optStr(input.to), limit: typeof input.limit === "number" ? input.limit : typeof input.limit === "string" && Number.isFinite(Number(input.limit)) ? Number(input.limit) : undefined }) }; } });
147
- defineOperation({ name: "transcript_memories", description: "Transcript memories.", schema: strictSchema({ source: S.str, date: S.str, limit: S.flexNum }), handler: async (input, ctx) => ({ result: await ctx.service.wearablesTranscriptMemories({ source: optStr(input.source), date: optStr(input.date), limit: typeof input.limit === "number" ? input.limit : typeof input.limit === "string" && Number.isFinite(Number(input.limit)) ? Number(input.limit) : undefined }) }) });
143
+ defineOperation({ name: "wearables_status", description: "Wearables status.", schema: strictSchema({ namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.wearablesStatus({ authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }) });
144
+ defineOperation({ name: "wearables_sync", description: "Sync wearables.", schema: strictSchema({ source: S.str, date: S.str, days: S.flexNum, forceMemories: S.bool, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.wearablesSync({ source: optStr(input.source), date: optStr(input.date), days: typeof input.days === "number" ? input.days : typeof input.days === "string" && Number.isFinite(Number(input.days)) ? Number(input.days) : undefined, forceMemories: optBool(input.forceMemories), authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }) });
145
+ defineOperation({ name: "transcript_day", description: "Transcript for a day.", schema: strictSchema({ date: S.str, source: S.str, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => { const d = defStr(input.date, ""); if (d.trim().length === 0) throw new EngramAccessInputError("transcript_day: date is required (YYYY-MM-DD)"); return { result: await ctx.service.wearablesTranscriptDay({ date: d, source: optStr(input.source), authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }; } });
146
+ defineOperation({ name: "transcript_search", description: "Search transcripts.", schema: strictSchema({ query: S.str, source: S.str, from: S.str, to: S.str, limit: S.flexNum, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => { const q = defStr(input.query, ""); if (q.trim().length === 0) throw new EngramAccessInputError("transcript_search: query is required"); return { result: await ctx.service.wearablesTranscriptSearch({ query: q, source: optStr(input.source), from: optStr(input.from), to: optStr(input.to), limit: typeof input.limit === "number" ? input.limit : typeof input.limit === "string" && Number.isFinite(Number(input.limit)) ? Number(input.limit) : undefined, authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }; } });
147
+ defineOperation({ name: "transcript_memories", description: "Transcript memories.", schema: strictSchema({ source: S.str, date: S.str, limit: S.flexNum, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.wearablesTranscriptMemories({ source: optStr(input.source), date: optStr(input.date), limit: typeof input.limit === "number" ? input.limit : typeof input.limit === "string" && Number.isFinite(Number(input.limit)) ? Number(input.limit) : undefined, authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }) });
148
+
149
+ // === MEETINGS (issue #1900) ===
150
+ defineOperation({ name: "meetings_list", description: "List stored meeting records (all days, or one day).", schema: strictSchema({ date: S.str, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => { const d = optStr(input.date); return { result: await ctx.service.meetingsList(d && d.length > 0 ? d : undefined, { authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }; } });
151
+ defineOperation({ name: "meetings_get", description: "Get a stored meeting record by id.", schema: strictSchema({ id: S.str, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.meetingsGet(reqStr(input.id, "id"), { authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }) });
152
+ defineOperation({ name: "meetings_build", description: "Detect + fuse + store a day's meetings.", schema: strictSchema({ date: S.str, namespace: S.str, sessionKey: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.meetingsBuild(reqStr(input.date, "date"), { authenticatedPrincipal: ctx.authenticatedPrincipal, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey) }) }) });
148
153
 
149
154
  // === ACTION CONFIDENCE + INSPECTOR + CAPSULE ===
150
155
  defineOperation({ name: "action_confidence", description: "Action confidence.", schema: strictSchema({ intendedAction: S.str, confidence: S.num, risk: S.str, contextReadiness: S.str, currentContextScopes: S.strArr, userRules: z.array(z.unknown()).optional(), retrievedMemories: z.array(z.unknown()).optional() }), handler: async (input, ctx) => { const req: Record<string, unknown> = {}; if (input.intendedAction !== undefined) req.intendedAction = optStr(input.intendedAction); if (input.confidence !== undefined) req.confidence = optNum(input.confidence); if (input.risk !== undefined) req.risk = optStr(input.risk) as "low" | "medium" | "high" | "irreversible" | "restricted" | undefined; if (input.contextReadiness !== undefined) req.contextReadiness = optStr(input.contextReadiness) as "none" | "partial" | "sufficient" | undefined; if (input.currentContextScopes !== undefined) req.currentContextScopes = optStrArr(input.currentContextScopes); if (input.userRules !== undefined) req.userRules = input.userRules; if (input.retrievedMemories !== undefined) req.retrievedMemories = input.retrievedMemories; return { result: await ctx.service.actionConfidence(req) }; } });
@@ -107,6 +107,12 @@ import { displayErrorDetail } from "./runtime/better-sqlite.js";
107
107
  import type { PatternReinforcementResult } from "./maintenance/pattern-reinforcement.js";
108
108
  import type { LiveConnectorsRunSummary } from "./live-connectors-runner.js";
109
109
  import type { WearablesService } from "./wearables/service.js";
110
+ import type { MeetingsGetResult, MeetingsListResult } from "./meetings/service.js";
111
+ import type { MeetingsDayBuildSummary } from "./meetings/build.js";
112
+
113
+ import * as wearablesMeetings from "./access-wearables-meetings-surface.js";
114
+ import type { WearablesMeetingsHost, WearablesMeetingsScope } from "./access-wearables-meetings-surface.js";
115
+ export type { WearablesMeetingsScope };
110
116
  import {
111
117
  computeProcedureStats,
112
118
  type ProcedureStatsReport,
@@ -5745,60 +5751,51 @@ export class EngramAccessService {
5745
5751
  // behavior and validation (renderer-sharing rule).
5746
5752
  // ---------------------------------------------------------------------------
5747
5753
 
5748
- async wearablesStatus(): Promise<
5749
- Awaited<ReturnType<WearablesService["status"]>>
5750
- > {
5751
- return this.orchestrator.getWearablesService().status();
5754
+ /**
5755
+ * Structural host bound per call so the wearables + meetings ops (issue
5756
+ * #2123) delegate to the pure surface module while the namespace/principal
5757
+ * resolvers stay private.
5758
+ */
5759
+ private get wmHost(): WearablesMeetingsHost {
5760
+ return {
5761
+ orchestrator: this.orchestrator,
5762
+ resolveReadableNamespace: this.resolveReadableNamespace.bind(this),
5763
+ writableNamespaceFor: this.writableNamespaceFor.bind(this),
5764
+ resolveRequestPrincipal: this.resolveRequestPrincipal.bind(this),
5765
+ };
5752
5766
  }
5753
5767
 
5754
- async wearablesSync(request: {
5755
- source?: string;
5756
- date?: string;
5757
- days?: number;
5758
- forceMemories?: boolean;
5759
- }): Promise<Awaited<ReturnType<WearablesService["sync"]>>> {
5760
- return this.orchestrator.getWearablesService().sync({
5761
- source: request.source,
5762
- date: request.date,
5763
- days: request.days,
5764
- forceMemories: request.forceMemories,
5765
- });
5768
+ async wearablesStatus(scope?: WearablesMeetingsScope): Promise<Awaited<ReturnType<WearablesService["status"]>>> {
5769
+ return wearablesMeetings.wearablesStatus(this.wmHost, scope);
5766
5770
  }
5767
5771
 
5768
- async wearablesTranscriptDay(request: {
5769
- date: string;
5770
- source?: string;
5771
- }): Promise<Awaited<ReturnType<WearablesService["dayTranscript"]>>> {
5772
- return this.orchestrator
5773
- .getWearablesService()
5774
- .dayTranscript(request.date, request.source);
5772
+ async wearablesSync(request: { source?: string; date?: string; days?: number; forceMemories?: boolean } & WearablesMeetingsScope): Promise<Awaited<ReturnType<WearablesService["sync"]>>> {
5773
+ return wearablesMeetings.wearablesSync(this.wmHost, request);
5775
5774
  }
5776
5775
 
5777
- async wearablesTranscriptSearch(request: {
5778
- query: string;
5779
- source?: string;
5780
- from?: string;
5781
- to?: string;
5782
- limit?: number;
5783
- }): Promise<Awaited<ReturnType<WearablesService["searchTranscripts"]>>> {
5784
- return this.orchestrator.getWearablesService().searchTranscripts(request.query, {
5785
- source: request.source,
5786
- from: request.from,
5787
- to: request.to,
5788
- limit: request.limit,
5789
- });
5776
+ async wearablesTranscriptDay(request: { date: string; source?: string } & WearablesMeetingsScope): Promise<Awaited<ReturnType<WearablesService["dayTranscript"]>>> {
5777
+ return wearablesMeetings.wearablesTranscriptDay(this.wmHost, request);
5790
5778
  }
5791
5779
 
5792
- async wearablesTranscriptMemories(request: {
5793
- source?: string;
5794
- date?: string;
5795
- limit?: number;
5796
- }): Promise<Awaited<ReturnType<WearablesService["transcriptMemories"]>>> {
5797
- return this.orchestrator.getWearablesService().transcriptMemories({
5798
- source: request.source,
5799
- date: request.date,
5800
- limit: request.limit,
5801
- });
5780
+ async wearablesTranscriptSearch(request: { query: string; source?: string; from?: string; to?: string; limit?: number } & WearablesMeetingsScope): Promise<Awaited<ReturnType<WearablesService["searchTranscripts"]>>> {
5781
+ return wearablesMeetings.wearablesTranscriptSearch(this.wmHost, request);
5782
+ }
5783
+
5784
+ async wearablesTranscriptMemories(request: { source?: string; date?: string; limit?: number } & WearablesMeetingsScope): Promise<Awaited<ReturnType<WearablesService["transcriptMemories"]>>> {
5785
+ return wearablesMeetings.wearablesTranscriptMemories(this.wmHost, request);
5786
+ }
5787
+
5788
+ // Meetings (issue #1900): thin delegations to the caller-ns MeetingsService.
5789
+ async meetingsList(date?: string, scope?: WearablesMeetingsScope): Promise<MeetingsListResult> {
5790
+ return wearablesMeetings.meetingsList(this.wmHost, date, scope);
5791
+ }
5792
+
5793
+ async meetingsGet(id: string, scope?: WearablesMeetingsScope): Promise<MeetingsGetResult> {
5794
+ return wearablesMeetings.meetingsGet(this.wmHost, id, scope);
5795
+ }
5796
+
5797
+ async meetingsBuild(date: string, scope?: WearablesMeetingsScope): Promise<MeetingsDayBuildSummary> {
5798
+ return wearablesMeetings.meetingsBuild(this.wmHost, date, scope);
5802
5799
  }
5803
5800
 
5804
5801
  // ── Admin console surfaces (issue #1502) ────────────────────────────────
@@ -59,6 +59,9 @@ export const MCP_TOOLS: readonly McpToolEntry[] = [
59
59
  { tool: "transcript_day", operation: "transcript_day" },
60
60
  { tool: "transcript_search", operation: "transcript_search" },
61
61
  { tool: "transcript_memories", operation: "transcript_memories" },
62
+ { tool: "meetings_list", operation: "meetings_list" },
63
+ { tool: "meetings_get", operation: "meetings_get" },
64
+ { tool: "meetings_build", operation: "meetings_build" },
62
65
  { tool: "action_confidence", operation: "action_confidence" },
63
66
  { tool: "chatgpt_memory_inspector", operation: "chatgpt_memory_inspector" },
64
67
  { tool: "day_summary", operation: "day_summary" },
@@ -190,6 +193,9 @@ export const HTTP_ROUTES: readonly HttpRouteEntry[] = [
190
193
  { method: "GET", pathname: "/engram/v1/wearables/transcript", operation: "transcript_day" },
191
194
  { method: "GET", pathname: "/engram/v1/wearables/transcripts/search", operation: "transcript_search" },
192
195
  { method: "GET", pathname: "/engram/v1/wearables/memories", operation: "transcript_memories" },
196
+ { method: "GET", pathname: "/engram/v1/meetings", operation: "meetings_list" },
197
+ { method: "POST", pathname: "/engram/v1/meetings/build", operation: "meetings_build" },
198
+ { method: "GET", pathname: "/engram/v1/meetings/:id", operation: "meetings_get" },
193
199
  { method: "POST", pathname: "/engram/v1/observe", operation: "observe" },
194
200
  { method: "POST", pathname: "/engram/v1/lcm/search", operation: "lcm_search" },
195
201
  { method: "POST", pathname: "/engram/v1/lcm/compaction/flush", operation: "lcm_compaction_flush" },