@remnic/core 9.45.4 → 9.46.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 (460) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +30 -29
  3. package/dist/access-authorization-probe.d.ts +10 -10
  4. package/dist/access-authorization-probe.js +31 -30
  5. package/dist/access-boundary.d.ts +10 -10
  6. package/dist/access-boundary.js +30 -29
  7. package/dist/access-cli.js +91 -87
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +10 -10
  11. package/dist/access-extraction-force-flush.js +30 -29
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +10 -10
  14. package/dist/access-http-lifecycle-flush.d.ts +10 -10
  15. package/dist/access-http-offline-stream.d.ts +10 -10
  16. package/dist/access-http-offline-stream.js +1 -1
  17. package/dist/access-http-query.js +30 -29
  18. package/dist/access-http.d.ts +10 -11
  19. package/dist/access-http.js +42 -41
  20. package/dist/access-identity-continuity-surface.d.ts +8 -8
  21. package/dist/access-identity-continuity-surface.js +30 -29
  22. package/dist/access-lcm-surface.d.ts +10 -10
  23. package/dist/access-lcm-surface.js +30 -29
  24. package/dist/access-mcp.d.ts +10 -10
  25. package/dist/access-mcp.js +36 -35
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-CWUDwB4M.d.ts → access-namespace-preflight--H6HwN85.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +30 -29
  30. package/dist/access-observe-write-surface.d.ts +10 -10
  31. package/dist/access-observe-write-surface.js +30 -29
  32. package/dist/access-offline-manifest.d.ts +8 -8
  33. package/dist/access-operations-batch.js +31 -30
  34. package/dist/access-operations.d.ts +13 -13
  35. package/dist/access-operations.js +35 -34
  36. package/dist/access-recall-concurrency.d.ts +10 -10
  37. package/dist/access-recall-concurrency.js +30 -29
  38. package/dist/access-recall-response.d.ts +10 -10
  39. package/dist/access-recall-response.js +30 -29
  40. package/dist/access-recall-surface.d.ts +10 -10
  41. package/dist/access-recall-surface.js +30 -29
  42. package/dist/access-schema.d.ts +84 -84
  43. package/dist/access-service-helpers.d.ts +10 -10
  44. package/dist/{access-service-CsU-ljFD.d.ts → access-service-loJadYd7.d.ts} +7 -7
  45. package/dist/access-service.d.ts +10 -10
  46. package/dist/access-service.js +30 -29
  47. package/dist/access-surface-catalog.d.ts +10 -10
  48. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  49. package/dist/action-confidence.d.ts +1 -1
  50. package/dist/active-memory-bridge.d.ts +1 -1
  51. package/dist/active-recall.d.ts +1 -1
  52. package/dist/adapters/index.js +4 -4
  53. package/dist/adapters/registry.js +2 -2
  54. package/dist/ambient-provenance.d.ts +109 -0
  55. package/dist/ambient-provenance.js +22 -0
  56. package/dist/ambient-provenance.js.map +1 -0
  57. package/dist/{auto-sync-UPTUVE4X.js → auto-sync-7O6RP2RT.js} +3 -2
  58. package/dist/{auto-sync-UPTUVE4X.js.map → auto-sync-7O6RP2RT.js.map} +1 -1
  59. package/dist/behavior-learner.d.ts +1 -1
  60. package/dist/behavior-signals.d.ts +1 -1
  61. package/dist/bootstrap.d.ts +8 -8
  62. package/dist/briefing.d.ts +2 -2
  63. package/dist/briefing.js +6 -5
  64. package/dist/buffer-surprise-report.d.ts +1 -1
  65. package/dist/buffer-turn-helpers.d.ts +1 -1
  66. package/dist/buffer-turn-helpers.js +1 -1
  67. package/dist/buffer.d.ts +2 -2
  68. package/dist/buffer.js +5 -5
  69. package/dist/bulk-import/index.d.ts +3 -3
  70. package/dist/calibration.d.ts +1 -1
  71. package/dist/capabilities.d.ts +1 -1
  72. package/dist/{catalog-bctMURhN.d.ts → catalog-Iwbk9h5E.d.ts} +1 -1
  73. package/dist/causal-behavior.d.ts +1 -1
  74. package/dist/causal-consolidation.d.ts +1 -1
  75. package/dist/causal-consolidation.js +7 -6
  76. package/dist/causal-consolidation.js.map +1 -1
  77. package/dist/causal-trajectory-graph.d.ts +1 -1
  78. package/dist/{chunk-7RZJWZ46.js → chunk-227UFSEQ.js} +5 -5
  79. package/dist/{chunk-ER7W6H4T.js → chunk-2AD5SXO4.js} +5 -2
  80. package/dist/chunk-2AD5SXO4.js.map +1 -0
  81. package/dist/{chunk-XSFHWBQO.js → chunk-2DSUT7DZ.js} +10 -64
  82. package/dist/{chunk-XSFHWBQO.js.map → chunk-2DSUT7DZ.js.map} +1 -1
  83. package/dist/{chunk-DZPFMQZ7.js → chunk-3S63QIFQ.js} +1 -1
  84. package/dist/chunk-3S63QIFQ.js.map +1 -0
  85. package/dist/{chunk-UQWIKLQK.js → chunk-47J4EDGR.js} +9 -9
  86. package/dist/{chunk-5SNZSWWR.js → chunk-5LRDM4R7.js} +42 -42
  87. package/dist/{chunk-7YERSTN7.js → chunk-5R6S4DJZ.js} +7 -7
  88. package/dist/{chunk-C26TE27X.js → chunk-5VQPZ4GV.js} +3 -3
  89. package/dist/{chunk-U2VLVBBH.js → chunk-64BHFFKZ.js} +3 -3
  90. package/dist/{chunk-AJQ57VV3.js → chunk-6H744ZBH.js} +4 -4
  91. package/dist/chunk-6H744ZBH.js.map +1 -0
  92. package/dist/{chunk-7CITSYSH.js → chunk-7T4TOGMS.js} +2 -2
  93. package/dist/{chunk-ZMAYKGPN.js → chunk-7YQ6ESEA.js} +12 -41
  94. package/dist/chunk-7YQ6ESEA.js.map +1 -0
  95. package/dist/{chunk-YMAQDHQM.js → chunk-BDNL34CT.js} +2 -2
  96. package/dist/{chunk-GQL52GQ5.js → chunk-CDKHKZL5.js} +15 -12
  97. package/dist/chunk-CDKHKZL5.js.map +1 -0
  98. package/dist/{chunk-WGP57SR3.js → chunk-CK5KOVHW.js} +3 -2
  99. package/dist/{chunk-WGP57SR3.js.map → chunk-CK5KOVHW.js.map} +1 -1
  100. package/dist/{chunk-JH6BPLOP.js → chunk-E4FOAENZ.js} +4 -4
  101. package/dist/{chunk-ZFGZ6PZ2.js → chunk-FULKGK7P.js} +2 -2
  102. package/dist/{chunk-BGHFOD5A.js → chunk-HJ3SVHUW.js} +3 -3
  103. package/dist/{chunk-TYISDI6B.js → chunk-HXXTXLKA.js} +2 -2
  104. package/dist/{chunk-FZP32336.js → chunk-IDE5AR5W.js} +53 -31
  105. package/dist/chunk-IDE5AR5W.js.map +1 -0
  106. package/dist/{chunk-7SHJHPTY.js → chunk-ILBLZ5Y5.js} +2 -2
  107. package/dist/chunk-J7T4MX7P.js +131 -0
  108. package/dist/chunk-J7T4MX7P.js.map +1 -0
  109. package/dist/{chunk-DSUAAZZX.js → chunk-JFO5QZ7N.js} +2 -2
  110. package/dist/{chunk-EJHEWCGQ.js → chunk-KA47C7BF.js} +2 -2
  111. package/dist/{chunk-NUEQKLNB.js → chunk-KMWYZTIE.js} +2 -2
  112. package/dist/{chunk-TQ4GD737.js → chunk-L7G72WY4.js} +2 -2
  113. package/dist/{chunk-CLB32OHM.js → chunk-LI7OE7G6.js} +2 -2
  114. package/dist/{chunk-TN76AKO3.js → chunk-M2INOSTA.js} +2 -2
  115. package/dist/{chunk-DYVMXPCF.js → chunk-M32URQXV.js} +665 -614
  116. package/dist/chunk-M32URQXV.js.map +1 -0
  117. package/dist/{chunk-WQIHRA5F.js → chunk-N3LL5NEU.js} +2 -2
  118. package/dist/{chunk-HFPASSFV.js → chunk-P2OTGMTR.js} +2 -2
  119. package/dist/{chunk-Y7HRYCNW.js → chunk-PFJXPOD4.js} +2 -2
  120. package/dist/{chunk-MDISBSYA.js → chunk-PKCLQ7KM.js} +43 -143
  121. package/dist/chunk-PKCLQ7KM.js.map +1 -0
  122. package/dist/chunk-QW27DOHG.js +84 -0
  123. package/dist/chunk-QW27DOHG.js.map +1 -0
  124. package/dist/{chunk-ZI32MKDW.js → chunk-RCU25Z66.js} +32 -35
  125. package/dist/chunk-RCU25Z66.js.map +1 -0
  126. package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
  127. package/dist/{chunk-QCECHYZL.js → chunk-RVO6TCTU.js} +6 -6
  128. package/dist/{chunk-D3I2MCN7.js → chunk-RVPTS4U5.js} +3 -3
  129. package/dist/{chunk-W3IC7QOY.js → chunk-RVYVMQK4.js} +3 -3
  130. package/dist/chunk-S2HLHAZ4.js +16 -0
  131. package/dist/chunk-S2HLHAZ4.js.map +1 -0
  132. package/dist/{chunk-2MRHJNWL.js → chunk-ST5IEK3H.js} +2 -2
  133. package/dist/{chunk-O4KMGRXE.js → chunk-SXWHN7GC.js} +2 -2
  134. package/dist/{chunk-KXEFRMCF.js → chunk-T6JRMVOV.js} +2 -2
  135. package/dist/{chunk-R5RFK3CB.js → chunk-U6JGQ37L.js} +2 -2
  136. package/dist/{chunk-UV72DEZD.js → chunk-UYUYZ4WY.js} +36 -10
  137. package/dist/chunk-UYUYZ4WY.js.map +1 -0
  138. package/dist/{chunk-EITZHSX6.js → chunk-V5FE3UAI.js} +2 -2
  139. package/dist/chunk-VL35ZFSZ.js +102 -0
  140. package/dist/chunk-VL35ZFSZ.js.map +1 -0
  141. package/dist/{chunk-NTOIP2E6.js → chunk-W2ZSNIBP.js} +2 -2
  142. package/dist/{chunk-QVSBTCVP.js → chunk-WHWDBTCJ.js} +2 -2
  143. package/dist/{chunk-5CEECY6P.js → chunk-WOC6DXP5.js} +3 -3
  144. package/dist/{chunk-XTAUXTDO.js → chunk-XBMJ35IP.js} +2 -2
  145. package/dist/{chunk-VOUOLGIP.js → chunk-YRFAYOFQ.js} +11 -13
  146. package/dist/chunk-YRFAYOFQ.js.map +1 -0
  147. package/dist/{chunk-P7NGM24P.js → chunk-YWCOJOUI.js} +2 -2
  148. package/dist/{chunk-6NNNURLK.js → chunk-Z54EM5YZ.js} +4 -4
  149. package/dist/{chunk-ULVR5KG7.js → chunk-ZDAYWJV6.js} +2 -2
  150. package/dist/chunk-ZDAYWJV6.js.map +1 -0
  151. package/dist/{cli-BBHDtG36.d.ts → cli-D_RcqXfZ.d.ts} +5 -5
  152. package/dist/cli.d.ts +12 -12
  153. package/dist/cli.js +61 -60
  154. package/dist/compat/checks.js +1 -1
  155. package/dist/compounding/engine.d.ts +2 -2
  156. package/dist/compounding/engine.js +6 -5
  157. package/dist/compounding/preference-consolidator.d.ts +1 -1
  158. package/dist/compression-optimizer.d.ts +1 -1
  159. package/dist/config.d.ts +1 -1
  160. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  161. package/dist/connectors/codex-materialize-runner.js +6 -5
  162. package/dist/connectors/codex-materialize.d.ts +1 -1
  163. package/dist/connectors/index.d.ts +1 -1
  164. package/dist/connectors/index.js +6 -5
  165. package/dist/consolidation-provenance-check.d.ts +2 -2
  166. package/dist/consolidation-undo.d.ts +2 -2
  167. package/dist/contradiction/index.d.ts +2 -2
  168. package/dist/converge-config.d.ts +1 -1
  169. package/dist/convergence-refresh.d.ts +2 -2
  170. package/dist/convergence-refresh.js +8 -7
  171. package/dist/conversation-index/backend.d.ts +1 -1
  172. package/dist/conversation-index/backend.js +2 -2
  173. package/dist/conversation-index/chunker.d.ts +1 -1
  174. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  175. package/dist/conversation-index/indexer.d.ts +1 -1
  176. package/dist/conversation-index/search.d.ts +1 -1
  177. package/dist/corpus-watermark.d.ts +1 -1
  178. package/dist/corpus-watermark.js +17 -16
  179. package/dist/day-summary.d.ts +1 -1
  180. package/dist/delinearize.d.ts +1 -1
  181. package/dist/direct-answer-wiring.d.ts +1 -1
  182. package/dist/direct-answer.d.ts +1 -1
  183. package/dist/embedding-fallback.d.ts +1 -1
  184. package/dist/enrichment/index.d.ts +1 -1
  185. package/dist/entity-retrieval.d.ts +2 -2
  186. package/dist/entity-retrieval.js +6 -5
  187. package/dist/entity-schema.d.ts +1 -1
  188. package/dist/explicit-capture.d.ts +8 -8
  189. package/dist/external-wiki-access.d.ts +10 -10
  190. package/dist/external-wiki-access.js +33 -32
  191. package/dist/external-wiki-cli.js +4 -90
  192. package/dist/external-wiki-cli.js.map +1 -1
  193. package/dist/external-wiki-collection-registration.d.ts +1 -1
  194. package/dist/external-wiki-collection.d.ts +1 -1
  195. package/dist/external-wiki-mcp-tools.d.ts +10 -10
  196. package/dist/external-wiki-search.js +2 -2
  197. package/dist/external-wiki.d.ts +1 -5
  198. package/dist/external-wiki.js +1 -3
  199. package/dist/extraction-error-classification.d.ts +1 -1
  200. package/dist/extraction-faithfulness.d.ts +1 -1
  201. package/dist/extraction-judge-telemetry.d.ts +1 -1
  202. package/dist/extraction-judge-training.d.ts +1 -1
  203. package/dist/extraction-judge.d.ts +1 -1
  204. package/dist/extraction-liveness.d.ts +1 -1
  205. package/dist/extraction-prompt.d.ts +36 -0
  206. package/dist/extraction-prompt.js +16 -0
  207. package/dist/extraction-prompt.js.map +1 -0
  208. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  209. package/dist/extraction-source-grounding.d.ts +1 -1
  210. package/dist/extraction.d.ts +6 -14
  211. package/dist/extraction.js +13 -10
  212. package/dist/fallback-llm.d.ts +1 -1
  213. package/dist/{first-start-migration-F2QJD66E.js → first-start-migration-ZSHEFEI3.js} +10 -12
  214. package/dist/{first-start-migration-F2QJD66E.js.map → first-start-migration-ZSHEFEI3.js.map} +1 -1
  215. package/dist/graph-dashboard-diff.d.ts +1 -1
  216. package/dist/graph-dashboard-key.d.ts +1 -1
  217. package/dist/graph-dashboard-parser.d.ts +1 -1
  218. package/dist/graph-edge-reinforcement.d.ts +1 -1
  219. package/dist/graph-snapshot.d.ts +1 -1
  220. package/dist/graph.d.ts +1 -1
  221. package/dist/importance.d.ts +1 -1
  222. package/dist/importers/index.d.ts +1 -1
  223. package/dist/in-flight-reads.d.ts +1 -1
  224. package/dist/index.d.ts +701 -697
  225. package/dist/index.js +133 -128
  226. package/dist/intent.d.ts +1 -1
  227. package/dist/lcm/engine.d.ts +1 -1
  228. package/dist/lcm/engine.js +2 -2
  229. package/dist/lcm/index.d.ts +1 -1
  230. package/dist/lcm/index.js +2 -2
  231. package/dist/lcm/tools.d.ts +1 -1
  232. package/dist/lifecycle.d.ts +1 -1
  233. package/dist/live-connectors-runner.d.ts +1 -1
  234. package/dist/local-llm.d.ts +1 -1
  235. package/dist/local-model-endpoint.d.ts +1 -1
  236. package/dist/maintenance/memory-governance.d.ts +1 -1
  237. package/dist/maintenance/memory-governance.js +6 -5
  238. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  239. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +6 -5
  240. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  241. package/dist/maintenance/rebuild-memory-projection.js +7 -6
  242. package/dist/{maintenance-D2mveyCd.d.ts → maintenance-DQrL93Uu.d.ts} +3 -3
  243. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  244. package/dist/memory-action-policy.d.ts +1 -1
  245. package/dist/memory-cache.d.ts +1 -1
  246. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  247. package/dist/memory-projection-store.d.ts +1 -1
  248. package/dist/memory-provenance.d.ts +1 -1
  249. package/dist/memory-snapshot.d.ts +10 -0
  250. package/dist/memory-snapshot.js +8 -0
  251. package/dist/memory-snapshot.js.map +1 -0
  252. package/dist/memory-worth-outcomes.d.ts +2 -2
  253. package/dist/models-json.d.ts +1 -1
  254. package/dist/namespaces/migrate.d.ts +3 -3
  255. package/dist/namespaces/migrate.js +16 -15
  256. package/dist/namespaces/principal.d.ts +1 -1
  257. package/dist/namespaces/search.d.ts +1 -1
  258. package/dist/namespaces/search.js +9 -9
  259. package/dist/namespaces/storage.d.ts +3 -3
  260. package/dist/namespaces/storage.js +6 -5
  261. package/dist/native-knowledge.d.ts +1 -1
  262. package/dist/offline-sync-impression-drain.d.ts +1 -1
  263. package/dist/operator-doctor-corpus.d.ts +1 -1
  264. package/dist/operator-doctor-corpus.js +18 -17
  265. package/dist/operator-doctor-replica.d.ts +1 -1
  266. package/dist/operator-toolkit.d.ts +3 -3
  267. package/dist/operator-toolkit.js +22 -21
  268. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  269. package/dist/orchestration/maintenance.d.ts +4 -4
  270. package/dist/orchestration/maintenance.js +11 -10
  271. package/dist/{orchestrator-DJYlwiUv.d.ts → orchestrator-LPGegii3.d.ts} +8 -8
  272. package/dist/orchestrator.d.ts +8 -8
  273. package/dist/orchestrator.js +93 -89
  274. package/dist/patterns-cli.d.ts +1 -1
  275. package/dist/{pipeline-CNjY4wk3.d.ts → pipeline-1h2GpiHP.d.ts} +1 -1
  276. package/dist/policy-runtime.d.ts +1 -1
  277. package/dist/proactive-contention.d.ts +1 -1
  278. package/dist/provenance.d.ts +1 -1
  279. package/dist/{qmd-C0UDZidt.d.ts → qmd-UdwoF71D.d.ts} +1 -1
  280. package/dist/qmd-preflight.d.ts +2 -2
  281. package/dist/qmd-recall-cache.d.ts +1 -1
  282. package/dist/qmd.d.ts +2 -2
  283. package/dist/qmd.js +4 -4
  284. package/dist/recall-concurrency-config.d.ts +1 -1
  285. package/dist/recall-disclosure-escalation.d.ts +1 -1
  286. package/dist/recall-explain-renderer.d.ts +1 -1
  287. package/dist/recall-explain-renderer.js +3 -3
  288. package/dist/recall-memory-map.d.ts +1 -1
  289. package/dist/recall-planner-llm.d.ts +1 -1
  290. package/dist/recall-state.d.ts +1 -1
  291. package/dist/recall-tag-filter.d.ts +1 -1
  292. package/dist/recall-timings.d.ts +1 -1
  293. package/dist/recall-xray-cli.d.ts +1 -1
  294. package/dist/recall-xray-cli.js +4 -4
  295. package/dist/recall-xray-renderer.d.ts +1 -1
  296. package/dist/recall-xray-renderer.js +3 -3
  297. package/dist/recall-xray.d.ts +1 -1
  298. package/dist/recall-xray.js +2 -2
  299. package/dist/reconcile/cursor.d.ts +1 -1
  300. package/dist/reconcile/manifest.d.ts +1 -1
  301. package/dist/reconcile/plan.d.ts +1 -1
  302. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  303. package/dist/replay/normalizers/claude.d.ts +1 -1
  304. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  305. package/dist/replay/normalizers/shared.d.ts +1 -1
  306. package/dist/replay/runner.d.ts +1 -1
  307. package/dist/replay/types.d.ts +1 -1
  308. package/dist/replica-divergence.d.ts +1 -1
  309. package/dist/replica-peers-config.d.ts +1 -1
  310. package/dist/resolve-auth-token.d.ts +1 -1
  311. package/dist/retrieval-agents.d.ts +2 -2
  312. package/dist/retrieval-tiers.d.ts +1 -1
  313. package/dist/routing/engine.d.ts +1 -1
  314. package/dist/routing/store.d.ts +1 -1
  315. package/dist/salvage-envelope.d.ts +1 -1
  316. package/dist/schemas.d.ts +76 -76
  317. package/dist/{scope-profiles-BJzp2F5A.d.ts → scope-profiles-APjhSe-w.d.ts} +1 -1
  318. package/dist/sdk-compat.js.map +1 -1
  319. package/dist/search/embed-helper.d.ts +1 -1
  320. package/dist/search/factory.d.ts +1 -1
  321. package/dist/search/factory.js +8 -8
  322. package/dist/search/index.d.ts +1 -1
  323. package/dist/search/index.js +14 -14
  324. package/dist/search/lancedb-backend.d.ts +1 -1
  325. package/dist/search/meilisearch-backend.d.ts +1 -1
  326. package/dist/search/noop-backend.d.ts +1 -1
  327. package/dist/search/orama-backend.d.ts +1 -1
  328. package/dist/search/port.d.ts +1 -1
  329. package/dist/search/remote-backend.d.ts +1 -1
  330. package/dist/{semantic-consolidation-D4KAZO2G.d.ts → semantic-consolidation-CrySDbk3.d.ts} +1 -1
  331. package/dist/semantic-consolidation.d.ts +2 -2
  332. package/dist/semantic-consolidation.js +7 -6
  333. package/dist/semantic-rule-promotion.js +6 -5
  334. package/dist/semantic-rule-verifier.d.ts +1 -1
  335. package/dist/semantic-rule-verifier.js +6 -5
  336. package/dist/{service-BeDxSqE-.d.ts → service-DJ0LDyuN.d.ts} +2 -2
  337. package/dist/session-observer-bands.d.ts +1 -1
  338. package/dist/session-observer-state.d.ts +1 -1
  339. package/dist/shared-context/manager.d.ts +9 -9
  340. package/dist/signal.d.ts +1 -1
  341. package/dist/source-agent-qualifier.d.ts +4 -1
  342. package/dist/source-agent-qualifier.js +10 -9
  343. package/dist/{storage-DfjxusTE.d.ts → storage-y340tYKb.d.ts} +5 -2
  344. package/dist/storage.d.ts +2 -2
  345. package/dist/storage.js +5 -4
  346. package/dist/summarizer.d.ts +1 -1
  347. package/dist/summary-snapshot.d.ts +1 -1
  348. package/dist/temporal-supersession.d.ts +2 -2
  349. package/dist/temporal-timeline-recall.d.ts +1 -1
  350. package/dist/temporal-validity.d.ts +1 -1
  351. package/dist/threading.d.ts +1 -1
  352. package/dist/tier-migration.d.ts +2 -2
  353. package/dist/tier-migration.js +1 -1
  354. package/dist/tier-routing.d.ts +1 -1
  355. package/dist/topics.d.ts +1 -1
  356. package/dist/transcript.d.ts +1 -1
  357. package/dist/transfer/types.d.ts +66 -66
  358. package/dist/trust-score-stage.d.ts +1 -1
  359. package/dist/trust-score.d.ts +1 -1
  360. package/dist/{types-yX_FwERf.d.ts → types-D_Au9qJO.d.ts} +13 -2
  361. package/dist/types.d.ts +1 -1
  362. package/dist/types.js +1 -1
  363. package/dist/utility-runtime.d.ts +1 -1
  364. package/dist/verified-recall.js +6 -5
  365. package/dist/write-envelope.d.ts +1 -1
  366. package/package.json +2 -12
  367. package/src/access-http-offline-stream.ts +1 -0
  368. package/src/access-http.ts +0 -57
  369. package/src/access-operations-batch.ts +1 -1
  370. package/src/access-service-observe-lcm-parity.test.ts +45 -20
  371. package/src/access-service.ts +3 -4
  372. package/src/ambient-provenance.test.ts +510 -0
  373. package/src/ambient-provenance.ts +229 -0
  374. package/src/buffer-turn-helpers.ts +17 -1
  375. package/src/compat/checks.test.ts +45 -1
  376. package/src/compat/checks.ts +16 -16
  377. package/src/external-wiki-cli.ts +28 -20
  378. package/src/external-wiki-search.test.ts +68 -2
  379. package/src/external-wiki.ts +12 -38
  380. package/src/extraction-prompt.ts +142 -0
  381. package/src/extraction.ts +37 -148
  382. package/src/index.ts +1 -5
  383. package/src/maintenance/first-start-migration.ts +11 -11
  384. package/src/meetings/memory-gen.test.ts +51 -0
  385. package/src/meetings/memory-gen.ts +36 -8
  386. package/src/meetings/summary-extractor.ts +4 -2
  387. package/src/memory-snapshot.ts +15 -0
  388. package/src/orchestration/recall-internal.ts +5 -148
  389. package/src/orchestration/recall-profile-storage.ts +194 -0
  390. package/src/orchestration/recall-search-pipeline.ts +13 -182
  391. package/src/orchestration/recall-search-prefilter.ts +254 -0
  392. package/src/orchestration/session-context.ts +1 -1
  393. package/src/orchestrator.ts +1 -1
  394. package/src/sdk-compat.ts +2 -4
  395. package/src/source-agent-qualifier.ts +3 -0
  396. package/src/storage-contract/cache-coherence.test.ts +99 -0
  397. package/src/storage-fact-hash-index-defer.test.ts +14 -7
  398. package/src/storage.ts +47 -48
  399. package/src/testing/subjects/first-start-tier-migration.test.ts +75 -0
  400. package/src/testing/subjects/recall-profile-storage.test.ts +362 -0
  401. package/src/testing/subjects/recall-search-prefilter.test.ts +365 -0
  402. package/src/tier-migration.ts +10 -12
  403. package/src/types.ts +2 -2
  404. package/src/wearables/memory-gen.test.ts +82 -0
  405. package/src/wearables/memory-gen.ts +54 -5
  406. package/src/wearables/trust.ts +19 -2
  407. package/dist/chunk-AJQ57VV3.js.map +0 -1
  408. package/dist/chunk-DYVMXPCF.js.map +0 -1
  409. package/dist/chunk-DZPFMQZ7.js.map +0 -1
  410. package/dist/chunk-ER7W6H4T.js.map +0 -1
  411. package/dist/chunk-FZP32336.js.map +0 -1
  412. package/dist/chunk-GQL52GQ5.js.map +0 -1
  413. package/dist/chunk-MDISBSYA.js.map +0 -1
  414. package/dist/chunk-ULVR5KG7.js.map +0 -1
  415. package/dist/chunk-UV72DEZD.js.map +0 -1
  416. package/dist/chunk-VOUOLGIP.js.map +0 -1
  417. package/dist/chunk-ZI32MKDW.js.map +0 -1
  418. package/dist/chunk-ZMAYKGPN.js.map +0 -1
  419. package/dist/legacy-hook-compat.d.ts +0 -3
  420. package/dist/legacy-hook-compat.js +0 -36
  421. package/dist/legacy-hook-compat.js.map +0 -1
  422. package/src/legacy-hook-compat.test.ts +0 -20
  423. package/src/legacy-hook-compat.ts +0 -45
  424. /package/dist/{chunk-7RZJWZ46.js.map → chunk-227UFSEQ.js.map} +0 -0
  425. /package/dist/{chunk-UQWIKLQK.js.map → chunk-47J4EDGR.js.map} +0 -0
  426. /package/dist/{chunk-5SNZSWWR.js.map → chunk-5LRDM4R7.js.map} +0 -0
  427. /package/dist/{chunk-7YERSTN7.js.map → chunk-5R6S4DJZ.js.map} +0 -0
  428. /package/dist/{chunk-C26TE27X.js.map → chunk-5VQPZ4GV.js.map} +0 -0
  429. /package/dist/{chunk-U2VLVBBH.js.map → chunk-64BHFFKZ.js.map} +0 -0
  430. /package/dist/{chunk-7CITSYSH.js.map → chunk-7T4TOGMS.js.map} +0 -0
  431. /package/dist/{chunk-YMAQDHQM.js.map → chunk-BDNL34CT.js.map} +0 -0
  432. /package/dist/{chunk-JH6BPLOP.js.map → chunk-E4FOAENZ.js.map} +0 -0
  433. /package/dist/{chunk-ZFGZ6PZ2.js.map → chunk-FULKGK7P.js.map} +0 -0
  434. /package/dist/{chunk-BGHFOD5A.js.map → chunk-HJ3SVHUW.js.map} +0 -0
  435. /package/dist/{chunk-TYISDI6B.js.map → chunk-HXXTXLKA.js.map} +0 -0
  436. /package/dist/{chunk-7SHJHPTY.js.map → chunk-ILBLZ5Y5.js.map} +0 -0
  437. /package/dist/{chunk-DSUAAZZX.js.map → chunk-JFO5QZ7N.js.map} +0 -0
  438. /package/dist/{chunk-EJHEWCGQ.js.map → chunk-KA47C7BF.js.map} +0 -0
  439. /package/dist/{chunk-NUEQKLNB.js.map → chunk-KMWYZTIE.js.map} +0 -0
  440. /package/dist/{chunk-TQ4GD737.js.map → chunk-L7G72WY4.js.map} +0 -0
  441. /package/dist/{chunk-CLB32OHM.js.map → chunk-LI7OE7G6.js.map} +0 -0
  442. /package/dist/{chunk-TN76AKO3.js.map → chunk-M2INOSTA.js.map} +0 -0
  443. /package/dist/{chunk-WQIHRA5F.js.map → chunk-N3LL5NEU.js.map} +0 -0
  444. /package/dist/{chunk-HFPASSFV.js.map → chunk-P2OTGMTR.js.map} +0 -0
  445. /package/dist/{chunk-Y7HRYCNW.js.map → chunk-PFJXPOD4.js.map} +0 -0
  446. /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
  447. /package/dist/{chunk-QCECHYZL.js.map → chunk-RVO6TCTU.js.map} +0 -0
  448. /package/dist/{chunk-D3I2MCN7.js.map → chunk-RVPTS4U5.js.map} +0 -0
  449. /package/dist/{chunk-W3IC7QOY.js.map → chunk-RVYVMQK4.js.map} +0 -0
  450. /package/dist/{chunk-2MRHJNWL.js.map → chunk-ST5IEK3H.js.map} +0 -0
  451. /package/dist/{chunk-O4KMGRXE.js.map → chunk-SXWHN7GC.js.map} +0 -0
  452. /package/dist/{chunk-KXEFRMCF.js.map → chunk-T6JRMVOV.js.map} +0 -0
  453. /package/dist/{chunk-R5RFK3CB.js.map → chunk-U6JGQ37L.js.map} +0 -0
  454. /package/dist/{chunk-EITZHSX6.js.map → chunk-V5FE3UAI.js.map} +0 -0
  455. /package/dist/{chunk-NTOIP2E6.js.map → chunk-W2ZSNIBP.js.map} +0 -0
  456. /package/dist/{chunk-QVSBTCVP.js.map → chunk-WHWDBTCJ.js.map} +0 -0
  457. /package/dist/{chunk-5CEECY6P.js.map → chunk-WOC6DXP5.js.map} +0 -0
  458. /package/dist/{chunk-XTAUXTDO.js.map → chunk-XBMJ35IP.js.map} +0 -0
  459. /package/dist/{chunk-P7NGM24P.js.map → chunk-YWCOJOUI.js.map} +0 -0
  460. /package/dist/{chunk-6NNNURLK.js.map → chunk-Z54EM5YZ.js.map} +0 -0
@@ -0,0 +1,229 @@
1
+ /**
2
+ * Ambient-capture provenance for extraction (issue #2294).
3
+ *
4
+ * Always-on capture devices — wearable recorders, room microphones — hand the
5
+ * extraction engine speech the user never authored: television and film
6
+ * dialogue, podcasts, radio, music with spoken segments, and conversations the
7
+ * user merely walked past. The extraction prompt otherwise reads every turn as
8
+ * first-person user input, so a scripted line about a relative's birthday or a
9
+ * medical diagnosis lands as a high-confidence personal fact and auto-promotes
10
+ * into recall. That output is plausible, personally relevant, and wrong, which
11
+ * makes it materially worse than a missed fact.
12
+ *
13
+ * This module owns both halves of the fix:
14
+ *
15
+ * 1. The prompt text that teaches the model to separate the user's own speech
16
+ * from background media, drop high-consequence personal claims it cannot
17
+ * attribute to the user, and score the remainder speculatively. One source
18
+ * of truth, shared by the cloud, direct-client, and local-LLM prompts so the
19
+ * three paths cannot drift.
20
+ * 2. A deterministic backstop — `clampAmbientCaptureConfidence` — for when the
21
+ * model ignores the prompt anyway. It clamps ONLY high-impact personal facts
22
+ * (family, milestones, medical) to the speculative ceiling. Clamping every
23
+ * ambient fact would gut the wearable integration, which is explicitly not
24
+ * the goal; clamping this class costs a birthday landing in the review queue
25
+ * instead of active recall.
26
+ *
27
+ * The provenance signal itself is `BufferTurn.ambientCapture`, set by the
28
+ * ingesting subsystem (the wearable memory pass), never by tool arguments.
29
+ */
30
+
31
+ import type { ExtractionResult } from "./types.js";
32
+
33
+ /**
34
+ * Upper bound of the speculative confidence tier, matching the tier table in
35
+ * the extraction prompt ("Speculative (0.00-0.39)"). A fact at or below this
36
+ * value cannot auto-promote through the wearable trust bands.
37
+ */
38
+ export const SPECULATIVE_CONFIDENCE_CEILING = 0.39;
39
+
40
+ /**
41
+ * Appended to the speculative tier definition when the input is ambient
42
+ * capture, so the tier itself carries the rule rather than relying on the
43
+ * separate section below being obeyed in isolation.
44
+ */
45
+ export const AMBIENT_SPECULATIVE_TIER_CLAUSE =
46
+ " Speculative also applies to any fact whose only evidence is ambient or background audio from an always-on capture device, even when the content is concrete and specific.";
47
+
48
+ /**
49
+ * Full provenance section for the cloud and direct-client extraction prompts.
50
+ */
51
+ export const AMBIENT_CAPTURE_PROMPT_SECTION = `
52
+ Source provenance — always-on capture audio:
53
+ - This transcript came from an always-on capture device (a wearable recorder or room microphone). It may contain audio the user did not author: television, film, podcasts, radio, advertisements, music with spoken segments, and conversations the user merely overheard or walked past.
54
+ - Separate the user's own speech from background media before extracting anything. Narrative, scripted, performed, or third-person speech — a show's dialogue, a podcast host, an ad read, a lecture playing in the room — is media, not user input. Never attribute it to the user or to anyone the user knows.
55
+ - High-consequence personal claims must be dropped entirely unless the user's own voice is clearly identifiable as their source: family relationships, personal milestones (births, birthdays, anniversaries, weddings, funerals, divorces), and any medical or health detail. Omit them; do not emit them at reduced confidence as a compromise.
56
+ - When you cannot tell whether a statement was spoken by the user or captured passively, skip it or set its confidence in the speculative tier (0.00-0.39). Never resolve that doubt upward.`;
57
+
58
+ /**
59
+ * Compact variant for the local-LLM prompt, which is deliberately small to fit
60
+ * 4k-8k context windows.
61
+ */
62
+ export const AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT = `
63
+ Ambient capture:
64
+ - This transcript came from an always-on capture device and may contain TV, film, podcast, music, or overheard speech the user did not author.
65
+ - Treat narrative, scripted, or third-person speech as media, not user input.
66
+ - Drop family, milestone (birth, birthday, anniversary, wedding, funeral), and medical claims unless the user's own voice is clearly the source.
67
+ - Otherwise, when unsure whether the user said it, set confidence in the speculative tier (0.00-0.39).`;
68
+
69
+ /**
70
+ * Single rule for prompts that already have their own rule list and only need
71
+ * the ambient warning (the meeting scribe, whose transcript is the same
72
+ * wearable audio).
73
+ */
74
+ export const AMBIENT_CAPTURE_PROMPT_RULE =
75
+ "- The transcript may contain ambient audio nobody in the meeting authored: television, podcasts, music, or a passing conversation. Treat scripted, performed, or third-person speech as background media and never record it as a decision, commitment, or question.";
76
+
77
+ /**
78
+ * Categories that are personal-claim-shaped by construction, independent of any
79
+ * vocabulary: `moment` is defined as an emotionally significant event or
80
+ * milestone, and on ambient audio a `relationship` claim is a link the model
81
+ * inferred between people it overheard. Non-lexical, so they still catch harm
82
+ * the term lists below miss.
83
+ */
84
+ const HIGH_IMPACT_CATEGORIES: Record<string, true> = { moment: true, relationship: true };
85
+
86
+ /**
87
+ * Kinship, milestone, and health vocabulary. Deliberately broad: a false
88
+ * positive costs one ambient fact a trip through the review queue, a false
89
+ * negative puts a fabricated medical claim into active recall. The list cannot
90
+ * be exhaustive and is not the primary defense — the prompt is, and the
91
+ * category signal above plus the trust-band cap in the wearable pass catch
92
+ * classes no word list enumerates. Extend it when a miss is observed.
93
+ *
94
+ * Word-bounded alternation only — no nesting, no backtracking risk.
95
+ */
96
+ const HIGH_IMPACT_TOPIC_PATTERN =
97
+ /\b(?:mother|mothers|mom|moms|mum|father|fathers|dad|dads|sister|sisters|brother|brothers|son|sons|daughter|daughters|wife|wives|husband|husbands|spouse|fiance|fiancee|grandmother|grandfather|grandma|grandpa|grandparent|grandparents|grandson|granddaughter|grandchild|grandchildren|aunt|uncle|cousin|niece|nephew|stepmother|stepfather|stepson|stepdaughter|stepchild|godmother|godfather|birthday|birthdays|anniversary|anniversaries|wedding|weddings|honeymoon|married|marriage|divorce|divorced|widow|widowed|funeral|memorial service|engagement party|baby shower|christening|bar mitzvah|pregnant|pregnancy|miscarriage|miscarried|newborn|gave birth|stillbirth|infertility|ivf|menopause|diagnosis|diagnosed|prognosis|tested positive|cancer|carcinoma|leukemia|tumor|tumour|biopsy|chemotherapy|chemo|radiation therapy|remission|hospice|palliative|terminal illness|surgery|surgeon|hospital|hospitalized|hospitalised|icu|emergency room|ambulance|stroke|heart attack|cardiac|arrhythmia|afib|seizure|epilepsy|asthma|allergy|allergic|diabetes|diabetic|insulin|cholesterol|blood pressure|hypertension|dementia|alzheimer|alzheimers|parkinson|parkinsons|hiv|aids diagnosis|medication|medications|prescription|prescribed|dosage|symptom|symptoms|illness|disease|disorder|syndrome|therapy|therapist|psychiatrist|psychologist|antidepressant|depression|anxiety|bipolar|schizophrenia|adhd|autism|ptsd|overdose|relapse|sobriety|rehab|addiction|alcoholism|concussion|transplant|dialysis|immunocompromised|mental health|covid|covid-19|coronavirus|flu|influenza|pneumonia|bronchitis|infection|infected|fever|migraine|ulcer|hernia|appendicitis|sepsis|sick leave|urgent care|broken leg|broken arm|broken wrist|broken hip|broken rib|broken ribs|sprained|dislocated|torn ligament|torn acl|whiplash|burn unit|chronic pain|disability|wheelchair|hearing aid|blind in|vaccinated|vaccination|immunization|blood test|scan results|mri|ct scan|x-ray|deaf|deafness|blind|blindness|mute|nonverbal|paralyzed|paralysed|paraplegic|quadriplegic|amputee|amputation|prosthetic|multiple sclerosis|lupus|crohn|celiac|fibromyalgia|cystic fibrosis|sickle cell|cerebral palsy|down syndrome|muscular dystrophy|chronic fatigue|chronic illness|terminally ill|life support|coma|special needs|caregiver|nursing home|assisted living|treatment|treatments|in treatment|medical leave|oncologist|cardiologist|neurologist|pediatrician|pediatric|als|copd|epilepsy|seizures|hospitalization|infirm|frail|bedridden|home health|physical therapy|occupational therapy|speech therapy)\b/i;
98
+
99
+ /**
100
+ * Bodily-harm and affliction SHAPES rather than nouns: "broke her leg", "tore
101
+ * his ACL", "caught something at the office". A vocabulary of conditions can
102
+ * never be complete, so this matches the sentence form instead — a verb of
103
+ * injury or contagion pointed at a person's POSSESSION. Articles are excluded
104
+ * on purpose: "the build broke the deploy pipeline" is not an injury.
105
+ */
106
+ const AFFLICTION_SHAPE_PATTERN =
107
+ /\b(?:broke|broken|fractured|sprained|dislocated|tore|torn|bruised|burned|scalded|injured|hurt)\s+(?:his|her|their|my|your|our)\s+\w+|\b(?:caught|contracted|came down with|is recovering from|was rushed to|passed away|died of|died from)\b/i;
108
+
109
+ /**
110
+ * Words that are personal only when someone possesses them: "child process",
111
+ * "parent component", "sibling node", and "customer family" are everyday
112
+ * technical speech, while "his child" and "Rachel's parents" are not.
113
+ */
114
+ const POSSESSED_KINSHIP_PATTERN =
115
+ /(?:\b(?:my|your|his|her|their|our)|'s)\s+(?:child|children|kid|kids|parent|parents|partner|family|sibling|siblings|in-law|in-laws|relatives)\b/i;
116
+
117
+ /** Tags that mark a fact as belonging to the same high-impact classes. */
118
+ const HIGH_IMPACT_TAGS: Record<string, true> = {
119
+ disability: true,
120
+ family: true,
121
+ health: true,
122
+ medical: true,
123
+ medication: true,
124
+ diagnosis: true,
125
+ birthday: true,
126
+ anniversary: true,
127
+ marriage: true,
128
+ pregnancy: true,
129
+ "mental-health": true,
130
+ };
131
+
132
+ /**
133
+ * True when this claim is personal in a way whose fabrication causes real
134
+ * harm — a family relationship, a personal milestone, or a medical detail.
135
+ *
136
+ * Read by every ambient guard: the post-extraction confidence clamp below, the
137
+ * wearable trust-band cap, and the meeting trust-band cap. A fact this flags
138
+ * can never auto-approve, on any path, however the boosts add up.
139
+ *
140
+ * Takes the shape rather than `ExtractedFact` so meeting candidates — which
141
+ * carry no tags — pass without a synthetic empty array.
142
+ *
143
+ * `personRefs` comes from `collectPersonEntityRefs` over the same extraction:
144
+ * pass it whenever the entity list is available, so personhood is read from
145
+ * the extractor's own `type: "person"` metadata instead of inferred from how
146
+ * it happened to spell the ref.
147
+ */
148
+ export function isHighImpactPersonalFact(
149
+ fact: {
150
+ category: string;
151
+ content: string;
152
+ tags?: readonly string[];
153
+ entityRef?: string;
154
+ },
155
+ personRefs?: ReadonlySet<string>,
156
+ ): boolean {
157
+ // The strongest non-lexical signal: a claim ABOUT A PERSON is high-impact
158
+ // whatever condition, relationship, or milestone the sentence names. This is
159
+ // what covers wording no list anticipates ("Dana is deaf").
160
+ if (isPersonRef(fact.entityRef, personRefs)) return true;
161
+ if (HIGH_IMPACT_CATEGORIES[fact.category] === true) return true;
162
+ if (HIGH_IMPACT_TOPIC_PATTERN.test(fact.content)) return true;
163
+ if (AFFLICTION_SHAPE_PATTERN.test(fact.content)) return true;
164
+ if (POSSESSED_KINSHIP_PATTERN.test(fact.content)) return true;
165
+ for (const tag of fact.tags ?? []) {
166
+ if (HIGH_IMPACT_TAGS[tag.trim().toLowerCase()] === true) return true;
167
+ }
168
+ return false;
169
+ }
170
+
171
+ /**
172
+ * Normalize an entity reference for comparison: casefold, strip a leading
173
+ * type prefix, and collapse separators. `Person-Jane_Doe`, `person:jane-doe`,
174
+ * and `jane doe` all reduce to `jane-doe`.
175
+ */
176
+ function normalizeEntityRef(ref: string): string {
177
+ return ref
178
+ .trim()
179
+ .toLowerCase()
180
+ .replace(/^(?:person|people)[-:_\s]+/, "")
181
+ .replace(/[\s_]+/g, "-");
182
+ }
183
+
184
+ /**
185
+ * Names of every `type: "person"` entity in an extraction, normalized for
186
+ * lookup. Personhood is the extractor's own metadata, not a guess from the
187
+ * shape of `entityRef` — the prompt asks for `person-jane-doe` but the field is
188
+ * optional and models routinely emit a bare `jane-doe`.
189
+ */
190
+ export function collectPersonEntityRefs(result: {
191
+ entities: ReadonlyArray<{ name: string; type: string }>;
192
+ }): ReadonlySet<string> {
193
+ const refs = new Set<string>();
194
+ for (const entity of result.entities) {
195
+ if (entity.type !== "person") continue;
196
+ const normalized = normalizeEntityRef(entity.name);
197
+ if (normalized.length > 0) refs.add(normalized);
198
+ }
199
+ return refs;
200
+ }
201
+
202
+ /** True when this ref names a person, by metadata or by explicit prefix. */
203
+ function isPersonRef(ref: string | undefined, personRefs?: ReadonlySet<string>): boolean {
204
+ if (ref === undefined || ref.trim().length === 0) return false;
205
+ if (/^(?:person|people)[-:_]/i.test(ref.trim())) return true;
206
+ return personRefs !== undefined && personRefs.has(normalizeEntityRef(ref));
207
+ }
208
+
209
+ /**
210
+ * Deterministic backstop applied after extraction on ambient-capture input:
211
+ * hold high-impact personal facts at or below the speculative ceiling so they
212
+ * cannot auto-promote to active recall on a model's unsupported confidence.
213
+ *
214
+ * Returns the input unchanged when nothing needs clamping, so the non-ambient
215
+ * path pays one predicate per fact and allocates nothing.
216
+ */
217
+ export function clampAmbientCaptureConfidence(
218
+ result: ExtractionResult,
219
+ ): ExtractionResult {
220
+ let clampedAny = false;
221
+ const personRefs = collectPersonEntityRefs(result);
222
+ const facts = result.facts.map((fact) => {
223
+ if (fact.confidence <= SPECULATIVE_CONFIDENCE_CEILING) return fact;
224
+ if (!isHighImpactPersonalFact(fact, personRefs)) return fact;
225
+ clampedAny = true;
226
+ return { ...fact, confidence: SPECULATIVE_CONFIDENCE_CEILING };
227
+ });
228
+ return clampedAny ? { ...result, facts } : result;
229
+ }
@@ -9,6 +9,18 @@ export interface BufferTurnOwner {
9
9
  sessionOwnerPrincipal?: string;
10
10
  }
11
11
 
12
+ export interface AmbientCaptureProvenance {
13
+ /**
14
+ * True when this turn's content came from an always-on ambient capture
15
+ * device (a wearable recorder, a room microphone) and may therefore carry
16
+ * speech the user never authored: TV, podcasts, music, overheard
17
+ * conversation (issue #2294). Set by the ingesting subsystem, never from
18
+ * tool arguments — extraction reads it to warn the model about media audio
19
+ * and to clamp high-impact personal facts to the speculative tier.
20
+ */
21
+ ambientCapture?: boolean;
22
+ }
23
+
12
24
  export function describeError(err: unknown): string {
13
25
  if (err instanceof Error) return err.message;
14
26
  if (err === null) return "null";
@@ -46,6 +58,9 @@ export function copyBufferTurn(turn: BufferTurn): BufferTurn {
46
58
  if (typeof turn.sourceConnector === "string") {
47
59
  copy.sourceConnector = turn.sourceConnector;
48
60
  }
61
+ if (typeof turn.ambientCapture === "boolean") {
62
+ copy.ambientCapture = turn.ambientCapture;
63
+ }
49
64
  return copy;
50
65
  }
51
66
 
@@ -61,7 +76,8 @@ export function bufferTurnsEqual(left: BufferTurn | undefined, right: BufferTurn
61
76
  left.providerThreadId === right.providerThreadId &&
62
77
  left.turnFingerprint === right.turnFingerprint &&
63
78
  left.persistProcessedFingerprint === right.persistProcessedFingerprint &&
64
- left.sourceConnector === right.sourceConnector
79
+ left.sourceConnector === right.sourceConnector &&
80
+ left.ambientCapture === right.ambientCapture
65
81
  );
66
82
  }
67
83
 
@@ -154,7 +154,11 @@ test("memory prompt section registration must be on the plugin api object", asyn
154
154
 
155
155
  const hookCheck = checkById(checks, "hook-registration-core");
156
156
  assert.equal(hookCheck.level, "error");
157
- assert.match(hookCheck.message, /before_prompt_build|before_agent_start/);
157
+ assert.match(hookCheck.message, /before_prompt_build/);
158
+ assert.doesNotMatch(
159
+ `${hookCheck.message} ${hookCheck.remediation ?? ""}`,
160
+ /before_agent_start/,
161
+ );
158
162
  });
159
163
 
160
164
  test("memory prompt section registration on api satisfies recall hook requirement", async () => {
@@ -173,6 +177,46 @@ test("memory prompt section registration on api satisfies recall hook requiremen
173
177
  assert.equal(hookCheck.level, "ok");
174
178
  });
175
179
 
180
+ test("memory prompt section remediation requests only missing required hooks", async () => {
181
+ const checks = await runFixture({
182
+ enginesNode: ">=22.12.0",
183
+ currentNodeVersion: "v22.12.0",
184
+ indexSource: [
185
+ "api.registerService({ start: async () => {} });",
186
+ "api.registerMemoryPromptSection(() => null);",
187
+ "registerCli(api, orchestrator);",
188
+ ].join("\n"),
189
+ });
190
+
191
+ const hookCheck = checkById(checks, "hook-registration-core");
192
+ assert.equal(hookCheck.level, "error");
193
+ assert.match(`${hookCheck.message} ${hookCheck.remediation ?? ""}`, /agent_end/);
194
+ assert.doesNotMatch(
195
+ `${hookCheck.message} ${hookCheck.remediation ?? ""}`,
196
+ /before_prompt_build|before_agent_start|gateway_start/,
197
+ );
198
+ });
199
+
200
+ test("memory prompt section remediation requests startup only when absent", async () => {
201
+ const checks = await runFixture({
202
+ enginesNode: ">=22.12.0",
203
+ currentNodeVersion: "v22.12.0",
204
+ indexSource: [
205
+ "api.on('agent_end', async () => {});",
206
+ "api.registerMemoryPromptSection(() => null);",
207
+ "registerCli(api, orchestrator);",
208
+ ].join("\n"),
209
+ });
210
+
211
+ const hookCheck = checkById(checks, "hook-registration-core");
212
+ assert.equal(hookCheck.level, "error");
213
+ assert.match(`${hookCheck.message} ${hookCheck.remediation ?? ""}`, /startup wiring/);
214
+ assert.doesNotMatch(
215
+ `${hookCheck.message} ${hookCheck.remediation ?? ""}`,
216
+ /before_prompt_build|before_agent_start/,
217
+ );
218
+ });
219
+
176
220
  test("service start detection ignores nested start properties", async () => {
177
221
  const checks = await runFixture({
178
222
  enginesNode: ">=22.12.0",
@@ -4,8 +4,7 @@ import type { CompatCheckOptions, CompatCheckResult, CompatReport, CompatRunner
4
4
  import { compareVersions } from "../version-utils.js";
5
5
  import { launchProcess } from "../runtime/child-process.js";
6
6
 
7
- const REQUIRED_HOOKS_LEGACY = ["before_agent_start", "agent_end"];
8
- const REQUIRED_HOOKS_NEW = ["before_prompt_build", "agent_end"];
7
+ const REQUIRED_HOOKS = ["before_prompt_build", "agent_end"];
9
8
  const OPENCLAW_REMNIC_PLUGIN_ID = "openclaw-remnic";
10
9
  const OPENCLAW_REMNIC_LEGACY_PLUGIN_ID = "openclaw-engram";
11
10
 
@@ -698,22 +697,16 @@ export async function runCompatChecks(options: CompatCheckOptions): Promise<Comp
698
697
  const indexRaw = await readFile(indexPath, "utf-8");
699
698
  const structuralSource = stripCommentsAndStrings(indexRaw);
700
699
  const hooks = parseHookRegistrations(indexRaw);
701
- const missingLegacy = REQUIRED_HOOKS_LEGACY.filter((hook) => !hooks.has(hook));
702
- const missingNew = REQUIRED_HOOKS_NEW.filter((hook) => !hooks.has(hook));
700
+ const missingHooks = REQUIRED_HOOKS.filter((hook) => !hooks.has(hook));
703
701
  // registerMemoryPromptSection is a valid alternative to the recall hook only
704
702
  // when it is registered on the OpenClaw plugin API object.
705
703
  const hasMemoryPromptSection = hasMemoryPromptSectionRegistration(structuralSource);
706
- const missingLegacyAdj = hasMemoryPromptSection
707
- ? missingLegacy.filter((h) => h !== "before_agent_start")
708
- : missingLegacy;
709
- const missingNewAdj = hasMemoryPromptSection
710
- ? missingNew.filter((h) => h !== "before_prompt_build")
711
- : missingNew;
712
- // Accept whichever hook set has fewer missing entries
713
- const missingHooks = missingNewAdj.length <= missingLegacyAdj.length ? missingNewAdj : missingLegacyAdj;
704
+ const missingRequiredHooks = hasMemoryPromptSection
705
+ ? missingHooks.filter((hook) => hook !== "before_prompt_build")
706
+ : missingHooks;
714
707
  const hasGatewayStartHook = hooks.has("gateway_start");
715
708
  const hasServiceStart = hasServiceStartRegistration(structuralSource);
716
- if (missingHooks.length === 0 && (hasGatewayStartHook || hasServiceStart)) {
709
+ if (missingRequiredHooks.length === 0 && (hasGatewayStartHook || hasServiceStart)) {
717
710
  checks.push({
718
711
  id: "hook-registration-core",
719
712
  title: "Core hook registration",
@@ -722,18 +715,25 @@ export async function runCompatChecks(options: CompatCheckOptions): Promise<Comp
722
715
  });
723
716
  } else {
724
717
  const missingParts: string[] = [];
725
- if (missingHooks.length > 0) {
726
- missingParts.push(`hooks: ${missingHooks.join(", ")}`);
718
+ if (missingRequiredHooks.length > 0) {
719
+ missingParts.push(`hooks: ${missingRequiredHooks.join(", ")}`);
727
720
  }
728
721
  if (!hasGatewayStartHook && !hasServiceStart) {
729
722
  missingParts.push("startup wiring: gateway_start hook or api.registerService({ start })");
730
723
  }
724
+ const remediationParts: string[] = [];
725
+ if (missingRequiredHooks.length > 0) {
726
+ remediationParts.push(`registers ${missingRequiredHooks.join(", ")}`);
727
+ }
728
+ if (!hasGatewayStartHook && !hasServiceStart) {
729
+ remediationParts.push("registers gateway_start or api.registerService({ start })");
730
+ }
731
731
  checks.push({
732
732
  id: "hook-registration-core",
733
733
  title: "Core hook registration",
734
734
  level: "error",
735
735
  message: `Missing expected registration(s): ${missingParts.join("; ")}`,
736
- remediation: "Ensure src/index.ts registers before_prompt_build (or before_agent_start) and agent_end, plus either gateway_start or api.registerService({ start }).",
736
+ remediation: `Ensure src/index.ts ${remediationParts.join(" and ")}.`,
737
737
  });
738
738
  }
739
739
 
@@ -1,4 +1,4 @@
1
- import { type ExternalWikiRoot, searchExternalWikis } from "./external-wiki-search.js";
1
+ import { type ExternalWikiRoot, type ExternalWikiSearchResult, searchExternalWikis } from "./external-wiki-search.js";
2
2
 
3
3
  interface ExternalWikiCliIo {
4
4
  readonly stdout: { write(chunk: string): unknown };
@@ -13,28 +13,25 @@ export async function runExternalWikiCliCommand(
13
13
  args: readonly string[],
14
14
  io: ExternalWikiCliIo
15
15
  ): Promise<number> {
16
- if (args.length === 0 || args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
16
+ if (args[0] === "help" || args[0] === "--help" || args[0] === "-h") {
17
17
  io.stdout.write(USAGE);
18
18
  return 0;
19
19
  }
20
- if (args[0] !== "search") {
21
- io.stderr.write(`external-wiki: unknown command '${args[0]}'\n${USAGE}`);
22
- return 2;
23
- }
20
+ const searchArgs = args[0] === "search" ? args.slice(1) : args;
24
21
 
25
22
  let limit: number | undefined;
26
23
  let wikiId: string | undefined;
27
24
  let maxCharsPerHit: number | undefined;
28
25
  let json = false;
29
26
  const queryParts: string[] = [];
30
- for (let index = 1; index < args.length; index += 1) {
31
- const argument = args[index];
27
+ for (let index = 0; index < searchArgs.length; index += 1) {
28
+ const argument = searchArgs[index];
32
29
  if (argument === "--json") {
33
30
  json = true;
34
31
  continue;
35
32
  }
36
33
  if (argument === "--limit" || argument === "--wiki-id" || argument === "--max-chars-per-hit") {
37
- const value = args[index + 1];
34
+ const value = searchArgs[index + 1];
38
35
  if (value === undefined || value.startsWith("--")) {
39
36
  io.stderr.write(`external-wiki: ${argument} requires a value\n`);
40
37
  return 2;
@@ -68,25 +65,36 @@ export async function runExternalWikiCliCommand(
68
65
 
69
66
  const query = queryParts.join(" ").trim();
70
67
  if (query.length === 0) {
71
- io.stderr.write(`external-wiki: query is required\n${USAGE}`);
72
- return 2;
68
+ io.stderr.write("external-wiki: provide a search query\n");
69
+ return 1;
70
+ }
71
+ const enabled = roots.filter((root) => root.enabled !== false);
72
+ if (enabled.length === 0) {
73
+ io.stderr.write("external-wiki: no enabled wiki roots configured\n");
74
+ return 1;
73
75
  }
74
76
 
75
- const result = await searchExternalWikis(roots, { query, limit, wikiId, maxCharsPerHit });
77
+ let result: ExternalWikiSearchResult;
78
+ try {
79
+ result = await searchExternalWikis(enabled, { query, limit, wikiId, maxCharsPerHit });
80
+ } catch (error) {
81
+ io.stderr.write(`external-wiki: ${error instanceof Error ? error.message : "search failed"}\n`);
82
+ return 1;
83
+ }
76
84
  if (json) {
77
85
  io.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
78
86
  return 0;
79
87
  }
80
88
 
81
- io.stdout.write(`External wiki results for "${result.query}" (${result.count})\n`);
82
- for (const hit of result.hits) {
83
- const citation = hit.citations[0];
84
- const location = citation ? `${citation.path}:${citation.lineStart}-${citation.lineEnd}` : hit.path;
85
- io.stdout.write(`${hit.rank}. [${hit.wikiId}] ${hit.title} (${location})\n`);
86
- io.stdout.write(` ${hit.snippet.replace(/\s+/g, " ").trim()}\n`);
87
- }
88
89
  if (result.degradedWikiIds.length > 0) {
89
- io.stderr.write(`external-wiki: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
90
+ io.stderr.write(`Warning: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
91
+ }
92
+ if (result.hits.length === 0) {
93
+ io.stdout.write("No results.\n");
94
+ return 0;
95
+ }
96
+ for (const hit of result.hits) {
97
+ io.stdout.write(`[${hit.wikiId}] ${hit.path} (score ${hit.score})\n${hit.snippet}\n\n`);
90
98
  }
91
99
  return 0;
92
100
  }
@@ -257,7 +257,7 @@ test("external wiki search fails open to filesystem candidates when a dedicated
257
257
  }
258
258
  });
259
259
 
260
- test("external wiki CLI searches multi-word queries and renders cited JSON or text", async () => {
260
+ test("external wiki CLI preserves text contracts and supports cited JSON", async () => {
261
261
  const root = await createWiki("cli", {
262
262
  "INDEX.md": "- [[wiki/agents|Agent Planning]] - planner fan-out with citations\n",
263
263
  "wiki/agents.md": "# Agent Planning\n\nPlanner fan-out uses cited retrieval evidence.\n",
@@ -286,7 +286,7 @@ test("external wiki CLI searches multi-word queries and renders cited JSON or te
286
286
  stderr: { write: () => undefined },
287
287
  });
288
288
  assert.equal(textCode, 0);
289
- assert.match(textOutput.join(""), /\[cli\] Agent Planning \(wiki\/agents\.md:\d+-\d+\)/);
289
+ assert.match(textOutput.join(""), /\[cli\] wiki\/agents\.md \(score [\d.]+\)/);
290
290
 
291
291
  const invalidErrors: string[] = [];
292
292
  const invalidCode = await runExternalWikiCliCommand([root], ["search", "--limit", "0", "query"], {
@@ -295,6 +295,72 @@ test("external wiki CLI searches multi-word queries and renders cited JSON or te
295
295
  });
296
296
  assert.equal(invalidCode, 2);
297
297
  assert.match(invalidErrors.join(""), /--limit must be an integer from 1 to 20/);
298
+
299
+ const noQueryErrors: string[] = [];
300
+ const noQueryCode = await runExternalWikiCliCommand([root], ["search"], {
301
+ stdout: { write: () => undefined },
302
+ stderr: { write: (chunk) => noQueryErrors.push(chunk) },
303
+ });
304
+ assert.equal(noQueryCode, 1);
305
+ assert.equal(noQueryErrors.join(""), "external-wiki: provide a search query\n");
306
+
307
+ const disabledErrors: string[] = [];
308
+ const disabledCode = await runExternalWikiCliCommand([{ ...root, enabled: false }], ["search", "planner"], {
309
+ stdout: { write: () => undefined },
310
+ stderr: { write: (chunk) => disabledErrors.push(chunk) },
311
+ });
312
+ assert.equal(disabledCode, 1);
313
+ assert.equal(disabledErrors.join(""), "external-wiki: no enabled wiki roots configured\n");
314
+
315
+ const emptyOutput: string[] = [];
316
+ const emptyCode = await runExternalWikiCliCommand([root], ["search", "unmatched-token"], {
317
+ stdout: { write: (chunk) => emptyOutput.push(chunk) },
318
+ stderr: { write: () => undefined },
319
+ });
320
+ assert.equal(emptyCode, 0);
321
+ assert.equal(emptyOutput.join(""), "No results.\n");
322
+
323
+ const searchErrors: string[] = [];
324
+ const searchErrorCode = await runExternalWikiCliCommand([root], ["search", "planner", "--wiki-id", "missing"], {
325
+ stdout: { write: () => undefined },
326
+ stderr: { write: (chunk) => searchErrors.push(chunk) },
327
+ });
328
+ assert.equal(searchErrorCode, 1);
329
+ assert.equal(searchErrors.join(""), "external-wiki: unknown external wiki: missing\n");
330
+
331
+ const legacyOutput: string[] = [];
332
+ const legacyCode = await runExternalWikiCliCommand([root], ["planner", "fan-out"], {
333
+ stdout: { write: (chunk) => legacyOutput.push(chunk) },
334
+ stderr: { write: () => undefined },
335
+ });
336
+ assert.equal(legacyCode, 0);
337
+ assert.match(legacyOutput.join(""), /^\[cli\] wiki\/agents\.md \(score [\d.]+\)/);
338
+
339
+ const degradedErrors: string[] = [];
340
+ const degradedCode = await runExternalWikiCliCommand(
341
+ [root, { ...root, id: "broken", rootDir: path.join(root.rootDir, "missing") }],
342
+ ["search", "planner"],
343
+ {
344
+ stdout: { write: () => undefined },
345
+ stderr: { write: (chunk) => degradedErrors.push(chunk) },
346
+ }
347
+ );
348
+ assert.equal(degradedCode, 0);
349
+ assert.equal(degradedErrors.join(""), "Warning: degraded roots: broken\n");
350
+
351
+ const allDegradedOutput: string[] = [];
352
+ const allDegradedErrors: string[] = [];
353
+ const allDegradedCode = await runExternalWikiCliCommand(
354
+ [{ ...root, id: "broken", rootDir: path.join(root.rootDir, "missing") }],
355
+ ["search", "planner"],
356
+ {
357
+ stdout: { write: (chunk) => allDegradedOutput.push(chunk) },
358
+ stderr: { write: (chunk) => allDegradedErrors.push(chunk) },
359
+ }
360
+ );
361
+ assert.equal(allDegradedCode, 0);
362
+ assert.equal(allDegradedOutput.join(""), "No results.\n");
363
+ assert.equal(allDegradedErrors.join(""), "Warning: degraded roots: broken\n");
298
364
  } finally {
299
365
  await removeWikis([root]);
300
366
  }
@@ -170,9 +170,18 @@ function normalizeCatalogPath(target: string, config: ExternalWikiRoot, base: Ca
170
170
  }
171
171
 
172
172
  const pagesDir = path.posix.normalize(config.pagesDir);
173
- const baseDir = base === "index" ? path.posix.dirname(config.indexFile) : pagesDir;
174
- const rootRelativeTarget = path.posix.normalize(path.posix.join(baseDir, withoutFragment));
175
- const relative = path.posix.relative(pagesDir, rootRelativeTarget);
173
+ let relative: string;
174
+ if (base === "index") {
175
+ const baseDir = path.posix.dirname(config.indexFile);
176
+ const rootRelativeTarget = path.posix.normalize(path.posix.join(baseDir, withoutFragment));
177
+ relative = path.posix.relative(pagesDir, rootRelativeTarget);
178
+ } else {
179
+ const pagesPrefix = pagesDir === "." ? "" : `${pagesDir}/`;
180
+ const stripped = pagesPrefix.length > 0 && withoutFragment.startsWith(pagesPrefix)
181
+ ? withoutFragment.slice(pagesPrefix.length)
182
+ : withoutFragment;
183
+ relative = path.posix.normalize(stripped);
184
+ }
176
185
  if (
177
186
  relative === ".." ||
178
187
  relative.startsWith("../") ||
@@ -416,38 +425,3 @@ export async function readExternalWikiPage(
416
425
  bytes: page.bytes,
417
426
  };
418
427
  }
419
-
420
- export async function runExternalWikiCliCommand(
421
- roots: readonly ExternalWikiRoot[],
422
- rest: readonly string[],
423
- io: { stdout: NodeJS.WritableStream; stderr: NodeJS.WritableStream },
424
- ): Promise<number> {
425
- const { searchExternalWikis } = await import("./external-wiki-search.js");
426
- const query = rest.filter((a) => !a.startsWith("-")).join(" ").trim();
427
- if (!query) {
428
- io.stderr.write("external-wiki: provide a search query\n");
429
- return 1;
430
- }
431
- const enabled = roots.filter((r) => r.enabled !== false);
432
- if (enabled.length === 0) {
433
- io.stderr.write("external-wiki: no enabled wiki roots configured\n");
434
- return 1;
435
- }
436
- try {
437
- const result = await searchExternalWikis(enabled, { query });
438
- if (result.hits.length === 0) {
439
- io.stdout.write("No results.\n");
440
- return 0;
441
- }
442
- for (const hit of result.hits) {
443
- io.stdout.write(`[${hit.wikiId}] ${hit.path} (score ${hit.score})\n${hit.snippet}\n\n`);
444
- }
445
- if (result.degradedWikiIds.length > 0) {
446
- io.stderr.write(`Warning: degraded roots: ${result.degradedWikiIds.join(", ")}\n`);
447
- }
448
- return 0;
449
- } catch (error) {
450
- io.stderr.write(`external-wiki: ${error instanceof Error ? error.message : "search failed"}\n`);
451
- return 1;
452
- }
453
- }