@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,142 @@
1
+ /**
2
+ * Extraction prompt construction (issue #1995 sibling extraction).
3
+ *
4
+ * The system prompt, its JSON response shape, and the placeholder table
5
+ * derived from that shape are prompt DATA, not engine behavior. They live here
6
+ * so `extraction.ts` holds the pipeline and one module owns the text every
7
+ * extraction path — local LLM, direct client, gateway fallback — sends.
8
+ */
9
+
10
+ import { AMBIENT_CAPTURE_PROMPT_SECTION, AMBIENT_SPECULATIVE_TIER_CLAUSE } from "./ambient-provenance.js";
11
+ import { resolveMemoryLifecycleCapabilities, resolveRecallAuxiliaryCapabilities } from "./capabilities.js";
12
+ import type { PluginConfig } from "./types.js";
13
+
14
+ export const EXTRACTION_RESPONSE_SHAPE = `{
15
+ "facts": [{
16
+ "category": "<category>",
17
+ "content": "<source-grounded statement>",
18
+ "confidence": 0.0,
19
+ "tags": ["<tag>"],
20
+ "entityRef": "<optional normalized-name>",
21
+ "promptedByQuestion": "<optional source-grounded question>",
22
+ "quote": "<optional exact contiguous source span>",
23
+ "scope": "<optional project-or-global>",
24
+ "structuredAttributes": {"<key>": "<value>"},
25
+ "procedureSteps": [{"order": 1, "intent": "<step>"}, {"order": 2, "intent": "<step>"}],
26
+ "reasoningTrace": {
27
+ "steps": [{"order": 1, "description": "<step>"}, {"order": 2, "description": "<step>"}],
28
+ "finalAnswer": "<answer>",
29
+ "observedOutcome": "<optional outcome>"
30
+ },
31
+ "eventTime": "<optional source temporal expression>"
32
+ }],
33
+ "entities": [{
34
+ "name": "<normalized-name>",
35
+ "type": "<entity-type>",
36
+ "facts": ["<source-grounded statement>"],
37
+ "promptedByQuestion": "<optional source-grounded question>",
38
+ "structuredSections": [{"key": "<section-key>", "title": "<section-title>", "facts": ["<source-grounded statement>"]}]
39
+ }],
40
+ "profileUpdates": ["<source-grounded profile update>"],
41
+ "questions": [{"question": "<source-grounded unresolved question>", "context": "<source-grounded context>", "priority": 0.0}],
42
+ "identityReflection": "<conversation-grounded agent reflection>",
43
+ "relationships": [{"source": "<normalized-name>", "target": "<normalized-name>", "label": "<source-grounded relationship>"}]
44
+ }`;
45
+ export const EXTRACTION_RESPONSE_PLACEHOLDERS: Record<string, true> = {};
46
+ for (const placeholder of EXTRACTION_RESPONSE_SHAPE.match(/<[^<>\r\n]+>/g) ?? []) {
47
+ EXTRACTION_RESPONSE_PLACEHOLDERS[placeholder] = true;
48
+ }
49
+
50
+ /**
51
+ * Bi-temporal event-time extraction instruction (#1578 PR2). Emitted on
52
+ * every extraction entry path when `temporal.biTemporal` is on so the LLM
53
+ * emits an optional per-fact `eventTime` expression. The expression is
54
+ * resolved against the source turn timestamp at write time — never
55
+ * wall-clock — so replay/import of old transcripts anchors correctly.
56
+ * Returns an empty string when the gate is off (byte-identical prompt).
57
+ */
58
+ export function eventTimePromptInstruction(config: PluginConfig): string {
59
+ if (!config.temporalBiTemporal) return "";
60
+ return `
61
+ When a fact states when it became or stopped being true, copy that explicit temporal expression verbatim into "eventTime". Omit "eventTime" when no such expression appears; never infer dates.`;
62
+ }
63
+
64
+ /**
65
+ * Build extraction instructions shared between local and cloud LLM.
66
+ *
67
+ * `ambientCapture` marks input from an always-on recorder, which may carry
68
+ * speech the user never authored (issue #2294).
69
+ */
70
+ export function buildExtractionInstructions(config: PluginConfig, existingEntities?: string[], ambientCapture = false): string {
71
+ const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);
72
+ return `You are a memory extraction system. Analyze the following conversation and extract durable, reusable memories.
73
+
74
+ Memory categories:
75
+ - fact: Objective information about the world
76
+ - preference: User likes, dislikes, or stylistic choices
77
+ - correction: User correcting a mistake or misconception (highest priority)
78
+ - entity: Information about a specific person, project, tool, or company
79
+ - decision: A choice that was made with rationale
80
+ - relationship: How two entities relate to each other (e.g., "Alice is Bob's manager", "Acme Corp uses Shopify")
81
+ - principle: Durable rules, values, or operating beliefs (e.g., "never use Chat Completions API")
82
+ - commitment: Promises, obligations, or deadlines (e.g., "deploy by Friday", "call accountant Monday")
83
+ - moment: Emotionally significant events or milestones (e.g., "first successful deployment of engram")
84
+ - skill: Capabilities the user or agent has demonstrated (e.g., "user is proficient with Kubernetes")${resolveRecallAuxiliaryCapabilities(config).causalRuleExtraction ? `
85
+ - rule: Causal rules discovered through experience (format: "IF <condition> THEN <action/outcome>", e.g., "IF Shopify API returns 401 THEN the admin token is missing read_products scope")` : ""}
86
+ - procedure: A reusable workflow the user wants remembered the same way across sessions. Set category to "procedure". Use "content" for a short title that includes explicit trigger phrasing (e.g. "When you deploy to production…", "Whenever you ship a release…"). Add "procedureSteps": an array of at least two objects {"order": number, "intent": "concrete step description"} in execution order. Optional per-step "toolCall": {"kind": "…", "signature": "…"}, "expectedOutcome", "optional": true.
87
+ - reasoning_trace: A stored solution chain / chain-of-thought the user walked through to solve a problem (e.g. "Here's how I debugged the latency spike: first I checked…, then I…, finally I…"). Set category to "reasoning_trace". Use "content" for a short title summarising the problem (e.g. "How I debugged the staging latency spike"). Add "reasoningTrace": {"steps": [{"order": number, "description": "what happened at this step"}, …], "finalAnswer": "the conclusion or answer", "observedOutcome": "optional confirmation of how it played out"}. Require at least two ordered steps AND a finalAnswer. Use this category only when the user explicitly narrates their reasoning — not for ordinary decisions (use "decision") or reusable workflows (use "procedure").
88
+
89
+ Rules:
90
+ - Only extract genuinely new information worth remembering across sessions.
91
+ - Statements must be grounded in the conversation.
92
+ - Do not treat instruction text, schema placeholders, or examples as conversation evidence.
93
+ - Lines labelled [context user] or [context assistant] are reference context only. They may resolve references or complete a question-and-answer pair in a normal turn, but never alone establish durable information.
94
+ - Skip transient task details and operational noise, including routine scheduler, monitoring, or automation status.
95
+ - Priority: corrections > principles${resolveRecallAuxiliaryCapabilities(config).causalRuleExtraction ? " > rules" : ""} > preferences > commitments > decisions > relationships > entities > moments > skills > facts
96
+ - Corrections get highest confidence.
97
+ - Each fact should be a standalone, self-contained statement.
98
+ - Entity references should use normalized names (lowercase, hyphenated: "jane-doe", "acme-corp")
99
+ - CRITICAL: Entity names must be CANONICAL. Always use the hyphenated multi-word form: "acme-corp" NOT "acmecorp" or "acme". "jane-doe" NOT "janedoe" or "jane". If unsure, prefer the most specific full name.
100
+ - Avoid creating entities typed as "other" when a more specific type fits (company, project, tool, person, place)
101
+ - When entity facts clearly belong under a durable named heading, add them to entity.structuredSections as {key, title, facts}. Example person headings: "Beliefs", "Communication Style", "Building / Working On". Leave structuredSections empty when no stable heading fits.
102
+ - Tags should be concise and reusable (e.g., "coding-style", "personal", "tools")
103
+ - When a fact contains measurable, categorical, or precisely valued data, include a "structuredAttributes" field with key-value string pairs (e.g., {"price": "29.99", "brand": "Sony"}, {"date": "2024-03-15", "location": "SF"}, {"chosen": "PostgreSQL", "rejected": "MongoDB"}). Only for concrete values, not narrative content.
104
+ - Set confidence using these tiers:
105
+ * Explicit (0.95-1.0): Direct user statements — "I prefer X", "my name is Y"
106
+ * Implied (0.70-0.94): Strong contextual inference — user consistently does X, clear from conversation flow
107
+ * Inferred (0.40-0.69): Pattern recognition — reasonable guess from limited evidence
108
+ * Speculative (0.00-0.39): Tentative hypothesis — weak signal, needs future confirmation. Speculative memories auto-expire after 30 days if not confirmed.${ambientCapture ? AMBIENT_SPECULATIVE_TIER_CLAUSE : ""}${config.provenance?.enabled ? `
109
+ - Source quotes: For each fact, include a "quote" field containing the EXACT verbatim words from the conversation that support the fact. Copy a contiguous span from a single speaker turn (not a paraphrase, not a summary). Cap at ~300 characters. This grounds every memory in the literal utterance that created it.` : ""}
110
+ - For commitments: include any deadline or timeframe mentioned${lifecycleCaps.extractionScopeClassification ? `
111
+
112
+ Scope classification:
113
+ For each fact, set "scope" to one of:
114
+ - "global" — knowledge that applies across projects: core framework/library bugs, API behavior patterns, user preferences (editor, language, style), general coding patterns, infrastructure knowledge, technology facts not tied to one codebase
115
+ - "project" — knowledge specific to one codebase: file paths, environment configs, deployment details, project-specific workarounds, team/stakeholder info tied to one project, repo-specific conventions. Tool, command, or CLI-flag instructions TIED TO ONE AGENT are also "project", because the same tool name means different things in different agent integrations (a "search" tool may search repository code in one agent and the web in another); when keeping such an agent-tied instruction, the fact text MUST name the originating agent as a leading "In <agent>," clause (e.g. "In Pi, use the search tool with a repository path."). A tool/command fact that holds in every agent and every repo is NOT agent-tied — leave it "global" and do not add a qualifier (e.g. "\`git status --short\` emits compact output"). Examples: "In Pi, the search tool takes a repository path" -> "project"; "\`git status --short\` emits compact output" -> "global".
116
+ When in doubt, prefer "project" — it is safer to keep knowledge scoped narrowly.` : ""}
117
+ ${ambientCapture ? `${AMBIENT_CAPTURE_PROMPT_SECTION}
118
+ ` : ""}
119
+ Entity creation rules (STRICT):
120
+ - Only create entities for DURABLE things: real people, companies, products, tools, ongoing projects
121
+ - NEVER create entities for transient items: individual PRs, branches, Jira tickets, meetings, agent task IDs, log files, database tables, cron job runs, sessions
122
+ - When you learn something about a transient item (e.g., PR #58 fixed a bug), store it as a FACT with an entityRef to the parent project — do NOT create an entity for the PR itself
123
+ - Prefer attaching facts to broad parent entities rather than creating sub-entities. E.g., "acme-store uses Algolia for search" is a fact on entity "acme-store", NOT a new entity "acme-store-algolia-connector"
124
+ - The entity list should be SHORT — think "things that would have their own Wikipedia page" not "things mentioned in passing"
125
+
126
+ ${existingEntities && existingEntities.length > 0 ? `
127
+ KNOWN ENTITIES (use these exact names when referencing existing things):
128
+ ${existingEntities.join(", ")}
129
+
130
+ When you see something that matches a known entity, use THAT name exactly. Only create a NEW entity if nothing in this list represents it.
131
+ ` : ""}
132
+ ${eventTimePromptInstruction(config)}
133
+ Also extract relationships between entities mentioned in the conversation.
134
+ - Format: {source: "entity-name", target: "entity-name", label: "relationship description"}
135
+ - Max 5 relationships per extraction
136
+ - Only include clear, durable relationships (e.g., "works at", "created", "manages", "uses")
137
+ - Use normalized entity names (e.g., "person-jane-doe", "company-acme-corp")
138
+
139
+ Questions are optional. Include only source-grounded unresolved questions that would be useful in future sessions; otherwise return an empty array.
140
+
141
+ Finally, write a brief identity reflection about the agent who had this conversation, based only on the conversation. Do not write about the extraction process.`;
142
+ }
package/src/extraction.ts CHANGED
@@ -46,10 +46,10 @@ import {
46
46
  import { applyGroundingWithConnector, headerConnector, renderExtractionConversation, resolveSourceConnector, type ExtractionGroundingContext } from "./source-agent-qualifier.js";
47
47
  import { isMemoryCategory } from "./write-envelope.js";
48
48
  import { classifyExtractionThrownError, classifyFallbackParseFailure } from "./extraction-error-classification.js";
49
+ import { AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT, clampAmbientCaptureConfidence } from "./ambient-provenance.js";
50
+ import { EXTRACTION_RESPONSE_PLACEHOLDERS, EXTRACTION_RESPONSE_SHAPE, buildExtractionInstructions, eventTimePromptInstruction } from "./extraction-prompt.js";
49
51
  export { classifyExtractionThrownError, classifyFallbackParseFailure } from "./extraction-error-classification.js";
50
- import { resolvePipelineProcessingCapabilities } from "./capabilities.js";
51
- import { resolveMemoryLifecycleCapabilities,
52
- resolveLocalLlmCapabilities,resolveRecallAuxiliaryCapabilities } from "./capabilities.js";
52
+ import { resolveLocalLlmCapabilities, resolveMemoryLifecycleCapabilities, resolvePipelineProcessingCapabilities, resolveRecallAuxiliaryCapabilities } from "./capabilities.js";
53
53
 
54
54
  type ExtractionQuestion = ExtractionResult["questions"][number];
55
55
  type ExtractedFactResult = ExtractionResult["facts"][number];
@@ -57,41 +57,6 @@ type ExtractedEntityResult = ExtractionResult["entities"][number];
57
57
  type ExtractedRelationshipResult = NonNullable<ExtractionResult["relationships"]>[number];
58
58
 
59
59
  const PROACTIVE_MIN_CONFIDENCE = 0.8;
60
- const EXTRACTION_RESPONSE_SHAPE = `{
61
- "facts": [{
62
- "category": "<category>",
63
- "content": "<source-grounded statement>",
64
- "confidence": 0.0,
65
- "tags": ["<tag>"],
66
- "entityRef": "<optional normalized-name>",
67
- "promptedByQuestion": "<optional source-grounded question>",
68
- "quote": "<optional exact contiguous source span>",
69
- "scope": "<optional project-or-global>",
70
- "structuredAttributes": {"<key>": "<value>"},
71
- "procedureSteps": [{"order": 1, "intent": "<step>"}, {"order": 2, "intent": "<step>"}],
72
- "reasoningTrace": {
73
- "steps": [{"order": 1, "description": "<step>"}, {"order": 2, "description": "<step>"}],
74
- "finalAnswer": "<answer>",
75
- "observedOutcome": "<optional outcome>"
76
- },
77
- "eventTime": "<optional source temporal expression>"
78
- }],
79
- "entities": [{
80
- "name": "<normalized-name>",
81
- "type": "<entity-type>",
82
- "facts": ["<source-grounded statement>"],
83
- "promptedByQuestion": "<optional source-grounded question>",
84
- "structuredSections": [{"key": "<section-key>", "title": "<section-title>", "facts": ["<source-grounded statement>"]}]
85
- }],
86
- "profileUpdates": ["<source-grounded profile update>"],
87
- "questions": [{"question": "<source-grounded unresolved question>", "context": "<source-grounded context>", "priority": 0.0}],
88
- "identityReflection": "<conversation-grounded agent reflection>",
89
- "relationships": [{"source": "<normalized-name>", "target": "<normalized-name>", "label": "<source-grounded relationship>"}]
90
- }`;
91
- const EXTRACTION_RESPONSE_PLACEHOLDERS: Record<string, true> = {};
92
- for (const placeholder of EXTRACTION_RESPONSE_SHAPE.match(/<[^<>\r\n]+>/g) ?? []) {
93
- EXTRACTION_RESPONSE_PLACEHOLDERS[placeholder] = true;
94
- }
95
60
  const CONSOLIDATION_RESPONSE_SCHEMA = `{
96
61
  "items": [
97
62
  {
@@ -674,16 +639,11 @@ export class ExtractionEngine {
674
639
  if (!shouldRunProactivePass(this.config, maxAdditional, this.shouldUseLocalLlm, this.localLlm)) return base;
675
640
 
676
641
  try {
677
- const proactive = await this.generateProactiveQuestions(conversation, base, maxAdditional, signal);
642
+ const proactive = await this.generateProactiveQuestions(conversation, base, maxAdditional, ctx.ambientCapture === true, signal);
678
643
  if (proactive.length === 0) return base;
644
+ const ambient = ctx.ambientCapture === true;
679
645
  const proactiveAdditions = await this.answerProactiveQuestions(
680
- conversation,
681
- base,
682
- proactive,
683
- maxAdditional,
684
- ctx.sourceConnector,
685
- signal,
686
- );
646
+ conversation, base, proactive, maxAdditional, ctx.sourceConnector, ambient, signal);
687
647
  const sanitizedAdditions = this.sanitizeExtractionResult(proactiveAdditions, ctx.messageTimestamp);
688
648
  const groundedAdditions = applyGroundingWithConnector(this.config, sanitizedAdditions, ctx);
689
649
  if (!this.hasExtractionOutputs(groundedAdditions)) return base;
@@ -733,6 +693,7 @@ export class ExtractionEngine {
733
693
  conversation: string,
734
694
  base: ExtractionResult,
735
695
  maxAdditional: number,
696
+ ambientCapture: boolean,
736
697
  signal?: AbortSignal,
737
698
  ): Promise<ExtractionQuestion[]> {
738
699
  const existingQuestionKeys = new Set(
@@ -751,7 +712,7 @@ export class ExtractionEngine {
751
712
 
752
713
  const prompt = [
753
714
  "You are doing a proactive second-pass memory extraction.",
754
- `Generate up to ${maxAdditional} additional high-value follow-up questions not already covered.`,
715
+ `Generate up to ${maxAdditional} additional high-value follow-up questions not already covered.${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}`,
755
716
  "Return only valid JSON with this shape:",
756
717
  '{"questions":[{"question":"...","context":"...","priority":0.0}]}',
757
718
  "",
@@ -834,6 +795,7 @@ export class ExtractionEngine {
834
795
  proactiveQuestions: ExtractionQuestion[],
835
796
  maxAdditional: number,
836
797
  sourceConnector: string | undefined,
798
+ ambientCapture: boolean,
837
799
  signal?: AbortSignal,
838
800
  ): Promise<ExtractionResult> {
839
801
  const factsPreview = base.facts
@@ -852,7 +814,7 @@ export class ExtractionEngine {
852
814
  const prompt = [
853
815
  "You are answering proactive memory follow-up questions using only the provided buffered conversation.",
854
816
  `Return at most ${maxAdditional} additional high-confidence memory candidates that were omitted from the base extraction.`,
855
- "Only include information directly supported by the conversation. Do not speculate. Do not repeat the base extraction.",
817
+ `Only include information directly supported by the conversation. Do not speculate. Do not repeat the base extraction.${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}`,
856
818
  "Return only valid JSON with this shape:",
857
819
  '{"facts":[{"category":"fact","content":"...","confidence":0.0,"tags":["..."],"entityRef":"optional","promptedByQuestion":"optional","quote":"optional verbatim span from a single turn"}],"profileUpdates":["..."],"entities":[{"name":"...","type":"person","facts":["..."],"structuredSections":[{"key":"beliefs","title":"Beliefs","facts":["..."]}],"promptedByQuestion":"optional"}],"relationships":[{"source":"...","target":"...","label":"...","promptedByQuestion":"optional"}]}',
858
820
  this.config.provenance?.enabled
@@ -862,7 +824,7 @@ export class ExtractionEngine {
862
824
  // paths so proactive-recovered facts also carry an optional eventTime
863
825
  // (chatgpt-codex thread on extraction.ts:1607). Returns "" when the
864
826
  // bi-temporal gate is off, keeping the prompt unchanged by default.
865
- this.eventTimePromptInstruction(),
827
+ eventTimePromptInstruction(this.config),
866
828
  headerConnector(sourceConnector) !== undefined && resolveMemoryLifecycleCapabilities(this.config).extractionScopeClassification
867
829
  ? `Tool, command, or CLI-flag instructions tied to the ${sourceConnector} agent are "project" scope; when you recover one, begin the fact with a leading "In ${sourceConnector}, " clause naming that agent (e.g. "In ${sourceConnector}, use the search tool with a repository path.").`
868
830
  : "",
@@ -1093,6 +1055,11 @@ export class ExtractionEngine {
1093
1055
  return null;
1094
1056
  }
1095
1057
 
1058
+ /**
1059
+ * The one funnel every successful extraction path returns through — local
1060
+ * LLM, direct client, and gateway fallback alike. The ambient clamp lives
1061
+ * here so a new path cannot bypass it (issue #2294).
1062
+ */
1096
1063
  private finalizeExtractionResult(
1097
1064
  result: ExtractionResult,
1098
1065
  turns: ReadonlyArray<{
@@ -1103,8 +1070,10 @@ export class ExtractionEngine {
1103
1070
  turnFingerprint?: string;
1104
1071
  }>,
1105
1072
  sourceConnector?: string,
1073
+ ambientCapture = false,
1106
1074
  ): ExtractionResult {
1107
- const provenanced = attachExtractionProvenance(result, turns, this.config.provenance);
1075
+ const clamped = ambientCapture ? clampAmbientCaptureConfidence(result) : result;
1076
+ const provenanced = attachExtractionProvenance(clamped, turns, this.config.provenance);
1108
1077
  return sourceConnector === undefined ? provenanced : { ...provenanced, sourceConnector };
1109
1078
  }
1110
1079
 
@@ -1135,6 +1104,12 @@ export class ExtractionEngine {
1135
1104
  // operate on. result.sourceConnector carries it to persistence so the
1136
1105
  // orchestrator does not recompute over a different turn set (#2183).
1137
1106
  const resolvedConnector = resolveSourceConnector(boundedTurns);
1107
+ // Ambient-capture provenance (issue #2294): true when any contributing turn
1108
+ // came from an always-on recorder, so the prompt warns about media audio
1109
+ // and the finalize chokepoint clamps high-impact personal facts.
1110
+ const ambientCapture = boundedTurns.some(
1111
+ (turn) => turn.ambientCapture === true && turn.extractionContextOnly !== true,
1112
+ );
1138
1113
  // The header and qualifier strip/restore are gated on the scope-classification
1139
1114
  // capability; persistence records resolvedConnector regardless (trusted metadata).
1140
1115
  const sourceConnector = lifecycleCaps.extractionScopeClassification
@@ -1192,6 +1167,7 @@ export class ExtractionEngine {
1192
1167
  roleAssertionSources,
1193
1168
  messageTimestamp,
1194
1169
  sourceConnector,
1170
+ ambientCapture,
1195
1171
  scopeClassificationEnabled: lifecycleCaps.extractionScopeClassification,
1196
1172
  };
1197
1173
 
@@ -1222,7 +1198,7 @@ export class ExtractionEngine {
1222
1198
  this.profiler.startSpan("local-llm", extractionTraceId);
1223
1199
  primaryExtractorAttempted = true;
1224
1200
  try {
1225
- const localResult = await this.extractWithLocalLlm(conversation, existingEntities, signal);
1201
+ const localResult = await this.extractWithLocalLlm(conversation, existingEntities, signal, ambientCapture);
1226
1202
  throwIfExtractionAborted(signal);
1227
1203
  if (localResult) {
1228
1204
  const durationMs = Date.now() - startTime;
@@ -1232,7 +1208,7 @@ export class ExtractionEngine {
1232
1208
  const sanitized = this.sanitizeExtractionResult(localResult, messageTimestamp);
1233
1209
  const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
1234
1210
  const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
1235
- return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector);
1211
+ return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
1236
1212
  }
1237
1213
  // Local failed, fall back if allowed
1238
1214
  if (!this.config.localLlmFallback) {
@@ -1272,7 +1248,7 @@ export class ExtractionEngine {
1272
1248
  this.profiler.startSpan("direct-client", extractionTraceId);
1273
1249
  primaryExtractorAttempted = true;
1274
1250
  try {
1275
- const directResult = await this.extractWithDirectClient(conversation, existingEntities, signal);
1251
+ const directResult = await this.extractWithDirectClient(conversation, existingEntities, signal, ambientCapture);
1276
1252
  if (directResult) {
1277
1253
  const durationMs = Date.now() - startTime;
1278
1254
  this.profiler.endSpan("direct-client", extractionTraceId);
@@ -1281,7 +1257,7 @@ export class ExtractionEngine {
1281
1257
  const sanitized = this.sanitizeExtractionResult(directResult, messageTimestamp);
1282
1258
  const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
1283
1259
  const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
1284
- return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector);
1260
+ return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
1285
1261
  }
1286
1262
  // Emit error event so Opik sees the direct client failure before fallback.
1287
1263
  // Wrapped in try/catch so a subscriber error doesn't break the fallback path.
@@ -1337,7 +1313,7 @@ export class ExtractionEngine {
1337
1313
  this.profiler.startSpan("gateway-fallback", extractionTraceId);
1338
1314
  try {
1339
1315
  const messages = [
1340
- { role: "system" as const, content: this.buildExtractionInstructions(existingEntities) },
1316
+ { role: "system" as const, content: buildExtractionInstructions(this.config, existingEntities, ambientCapture) },
1341
1317
  { role: "user" as const, content: conversation },
1342
1318
  ];
1343
1319
 
@@ -1369,7 +1345,7 @@ export class ExtractionEngine {
1369
1345
  const sanitized = this.sanitizeExtractionResult(normalized, messageTimestamp);
1370
1346
  const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
1371
1347
  const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
1372
- return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector);
1348
+ return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
1373
1349
  }
1374
1350
 
1375
1351
  this.emit({
@@ -1427,6 +1403,7 @@ export class ExtractionEngine {
1427
1403
  conversation: string,
1428
1404
  existingEntities?: string[],
1429
1405
  signal?: AbortSignal,
1406
+ ambientCapture = false,
1430
1407
  ): Promise<ExtractionResult | null> {
1431
1408
  const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
1432
1409
  log.debug(
@@ -1473,8 +1450,8 @@ Rules:
1473
1450
  - Add structuredAttributes only for concrete values.
1474
1451
  - Include at most five durable relationships.${this.config.provenance?.enabled ? `
1475
1452
  - Each fact must include a quote copied verbatim from one contiguous conversation span.` : ""}${lifecycleCaps.extractionScopeClassification ? `
1476
- - Set each fact scope to "global" for cross-project knowledge or "project" for codebase-specific knowledge. Tool, command, or CLI-flag instructions tied to one agent are "project" (the same tool name can mean different things across agents); when keeping one, begin the fact with a leading "In <agent>," clause naming that agent.` : ""}
1477
- ${this.eventTimePromptInstruction()}
1453
+ - Set each fact scope to "global" for cross-project knowledge or "project" for codebase-specific knowledge. Tool, command, or CLI-flag instructions tied to one agent are "project" (the same tool name can mean different things across agents); when keeping one, begin the fact with a leading "In <agent>," clause naming that agent.` : ""}${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}
1454
+ ${eventTimePromptInstruction(this.config)}
1478
1455
  Return only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:
1479
1456
  ${EXTRACTION_RESPONSE_SHAPE}
1480
1457
 
@@ -1550,6 +1527,7 @@ ${truncatedConversation}`;
1550
1527
  conversation: string,
1551
1528
  existingEntities?: string[],
1552
1529
  signal?: AbortSignal,
1530
+ ambientCapture = false,
1553
1531
  ): Promise<ExtractionResult | null> {
1554
1532
  if (!this.client) return null;
1555
1533
 
@@ -1565,7 +1543,7 @@ ${truncatedConversation}`;
1565
1543
  {
1566
1544
  role: "system",
1567
1545
  content:
1568
- this.buildExtractionInstructions(existingEntities) +
1546
+ buildExtractionInstructions(this.config, existingEntities, ambientCapture) +
1569
1547
  `\n\nReturn only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:\n${EXTRACTION_RESPONSE_SHAPE}`,
1570
1548
  },
1571
1549
  { role: "user", content: conversation },
@@ -1641,95 +1619,6 @@ ${truncatedConversation}`;
1641
1619
  return this.normalizeExtractionResultPayload({ facts, entities, profileUpdates: [], questions: [] });
1642
1620
  }
1643
1621
 
1644
- /**
1645
- * Bi-temporal event-time extraction instruction (#1578 PR2). Emitted on
1646
- * every extraction entry path when `temporal.biTemporal` is on so the LLM
1647
- * emits an optional per-fact `eventTime` expression. The expression is
1648
- * resolved against the source turn timestamp at write time — never
1649
- * wall-clock — so replay/import of old transcripts anchors correctly.
1650
- * Returns an empty string when the gate is off (byte-identical prompt).
1651
- */
1652
- private eventTimePromptInstruction(): string {
1653
- if (!this.config.temporalBiTemporal) return "";
1654
- return `
1655
- When a fact states when it became or stopped being true, copy that explicit temporal expression verbatim into "eventTime". Omit "eventTime" when no such expression appears; never infer dates.`;
1656
- }
1657
-
1658
- /**
1659
- * Build extraction instructions shared between local and cloud LLM.
1660
- */
1661
- private buildExtractionInstructions(existingEntities?: string[]): string {
1662
- const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);
1663
- return `You are a memory extraction system. Analyze the following conversation and extract durable, reusable memories.
1664
-
1665
- Memory categories:
1666
- - fact: Objective information about the world
1667
- - preference: User likes, dislikes, or stylistic choices
1668
- - correction: User correcting a mistake or misconception (highest priority)
1669
- - entity: Information about a specific person, project, tool, or company
1670
- - decision: A choice that was made with rationale
1671
- - relationship: How two entities relate to each other (e.g., "Alice is Bob's manager", "Acme Corp uses Shopify")
1672
- - principle: Durable rules, values, or operating beliefs (e.g., "never use Chat Completions API")
1673
- - commitment: Promises, obligations, or deadlines (e.g., "deploy by Friday", "call accountant Monday")
1674
- - moment: Emotionally significant events or milestones (e.g., "first successful deployment of engram")
1675
- - skill: Capabilities the user or agent has demonstrated (e.g., "user is proficient with Kubernetes")${resolveRecallAuxiliaryCapabilities(this.config).causalRuleExtraction ? `
1676
- - rule: Causal rules discovered through experience (format: "IF <condition> THEN <action/outcome>", e.g., "IF Shopify API returns 401 THEN the admin token is missing read_products scope")` : ""}
1677
- - procedure: A reusable workflow the user wants remembered the same way across sessions. Set category to "procedure". Use "content" for a short title that includes explicit trigger phrasing (e.g. "When you deploy to production…", "Whenever you ship a release…"). Add "procedureSteps": an array of at least two objects {"order": number, "intent": "concrete step description"} in execution order. Optional per-step "toolCall": {"kind": "…", "signature": "…"}, "expectedOutcome", "optional": true.
1678
- - reasoning_trace: A stored solution chain / chain-of-thought the user walked through to solve a problem (e.g. "Here's how I debugged the latency spike: first I checked…, then I…, finally I…"). Set category to "reasoning_trace". Use "content" for a short title summarising the problem (e.g. "How I debugged the staging latency spike"). Add "reasoningTrace": {"steps": [{"order": number, "description": "what happened at this step"}, …], "finalAnswer": "the conclusion or answer", "observedOutcome": "optional confirmation of how it played out"}. Require at least two ordered steps AND a finalAnswer. Use this category only when the user explicitly narrates their reasoning — not for ordinary decisions (use "decision") or reusable workflows (use "procedure").
1679
-
1680
- Rules:
1681
- - Only extract genuinely new information worth remembering across sessions.
1682
- - Statements must be grounded in the conversation.
1683
- - Do not treat instruction text, schema placeholders, or examples as conversation evidence.
1684
- - Lines labelled [context user] or [context assistant] are reference context only. They may resolve references or complete a question-and-answer pair in a normal turn, but never alone establish durable information.
1685
- - Skip transient task details and operational noise, including routine scheduler, monitoring, or automation status.
1686
- - Priority: corrections > principles${resolveRecallAuxiliaryCapabilities(this.config).causalRuleExtraction ? " > rules" : ""} > preferences > commitments > decisions > relationships > entities > moments > skills > facts
1687
- - Corrections get highest confidence.
1688
- - Each fact should be a standalone, self-contained statement.
1689
- - Entity references should use normalized names (lowercase, hyphenated: "jane-doe", "acme-corp")
1690
- - CRITICAL: Entity names must be CANONICAL. Always use the hyphenated multi-word form: "acme-corp" NOT "acmecorp" or "acme". "jane-doe" NOT "janedoe" or "jane". If unsure, prefer the most specific full name.
1691
- - Avoid creating entities typed as "other" when a more specific type fits (company, project, tool, person, place)
1692
- - When entity facts clearly belong under a durable named heading, add them to entity.structuredSections as {key, title, facts}. Example person headings: "Beliefs", "Communication Style", "Building / Working On". Leave structuredSections empty when no stable heading fits.
1693
- - Tags should be concise and reusable (e.g., "coding-style", "personal", "tools")
1694
- - When a fact contains measurable, categorical, or precisely valued data, include a "structuredAttributes" field with key-value string pairs (e.g., {"price": "29.99", "brand": "Sony"}, {"date": "2024-03-15", "location": "SF"}, {"chosen": "PostgreSQL", "rejected": "MongoDB"}). Only for concrete values, not narrative content.
1695
- - Set confidence using these tiers:
1696
- * Explicit (0.95-1.0): Direct user statements — "I prefer X", "my name is Y"
1697
- * Implied (0.70-0.94): Strong contextual inference — user consistently does X, clear from conversation flow
1698
- * Inferred (0.40-0.69): Pattern recognition — reasonable guess from limited evidence
1699
- * Speculative (0.00-0.39): Tentative hypothesis — weak signal, needs future confirmation. Speculative memories auto-expire after 30 days if not confirmed.${this.config.provenance?.enabled ? `
1700
- - Source quotes: For each fact, include a "quote" field containing the EXACT verbatim words from the conversation that support the fact. Copy a contiguous span from a single speaker turn (not a paraphrase, not a summary). Cap at ~300 characters. This grounds every memory in the literal utterance that created it.` : ""}
1701
- - For commitments: include any deadline or timeframe mentioned${lifecycleCaps.extractionScopeClassification ? `
1702
-
1703
- Scope classification:
1704
- For each fact, set "scope" to one of:
1705
- - "global" — knowledge that applies across projects: core framework/library bugs, API behavior patterns, user preferences (editor, language, style), general coding patterns, infrastructure knowledge, technology facts not tied to one codebase
1706
- - "project" — knowledge specific to one codebase: file paths, environment configs, deployment details, project-specific workarounds, team/stakeholder info tied to one project, repo-specific conventions. Tool, command, or CLI-flag instructions TIED TO ONE AGENT are also "project", because the same tool name means different things in different agent integrations (a "search" tool may search repository code in one agent and the web in another); when keeping such an agent-tied instruction, the fact text MUST name the originating agent as a leading "In <agent>," clause (e.g. "In Pi, use the search tool with a repository path."). A tool/command fact that holds in every agent and every repo is NOT agent-tied — leave it "global" and do not add a qualifier (e.g. "\`git status --short\` emits compact output"). Examples: "In Pi, the search tool takes a repository path" -> "project"; "\`git status --short\` emits compact output" -> "global".
1707
- When in doubt, prefer "project" — it is safer to keep knowledge scoped narrowly.` : ""}
1708
- Entity creation rules (STRICT):
1709
- - Only create entities for DURABLE things: real people, companies, products, tools, ongoing projects
1710
- - NEVER create entities for transient items: individual PRs, branches, Jira tickets, meetings, agent task IDs, log files, database tables, cron job runs, sessions
1711
- - When you learn something about a transient item (e.g., PR #58 fixed a bug), store it as a FACT with an entityRef to the parent project — do NOT create an entity for the PR itself
1712
- - Prefer attaching facts to broad parent entities rather than creating sub-entities. E.g., "acme-store uses Algolia for search" is a fact on entity "acme-store", NOT a new entity "acme-store-algolia-connector"
1713
- - The entity list should be SHORT — think "things that would have their own Wikipedia page" not "things mentioned in passing"
1714
-
1715
- ${existingEntities && existingEntities.length > 0 ? `
1716
- KNOWN ENTITIES (use these exact names when referencing existing things):
1717
- ${existingEntities.join(", ")}
1718
-
1719
- When you see something that matches a known entity, use THAT name exactly. Only create a NEW entity if nothing in this list represents it.
1720
- ` : ""}
1721
- ${this.eventTimePromptInstruction()}
1722
- Also extract relationships between entities mentioned in the conversation.
1723
- - Format: {source: "entity-name", target: "entity-name", label: "relationship description"}
1724
- - Max 5 relationships per extraction
1725
- - Only include clear, durable relationships (e.g., "works at", "created", "manages", "uses")
1726
- - Use normalized entity names (e.g., "person-jane-doe", "company-acme-corp")
1727
-
1728
- Questions are optional. Include only source-grounded unresolved questions that would be useful in future sessions; otherwise return an empty array.
1729
-
1730
- Finally, write a brief identity reflection about the agent who had this conversation, based only on the conversation. Do not write about the extraction process.`;
1731
- }
1732
-
1733
1622
  async consolidate(
1734
1623
  newMemories: MemoryFile[],
1735
1624
  existingMemories: MemoryFile[],
package/src/index.ts CHANGED
@@ -9,11 +9,6 @@
9
9
  * This package has ZERO OpenClaw imports — it can be consumed by
10
10
  * any host adapter (CLI, HTTP server, MCP server, etc.).
11
11
  *
12
- * Usage:
13
- * import { Orchestrator, parseConfig } from "@remnic/core";
14
- * const config = parseConfig({ memoryDir: "/tmp/mem" });
15
- * const orch = new Orchestrator(config);
16
- * await orch.initialize();
17
12
  */
18
13
 
19
14
  // ---------------------------------------------------------------------------
@@ -29,6 +24,7 @@ export { resolvePluginEntry, type PluginEntryResolverOptions } from "./plugin-en
29
24
  export { parseConfig, isOpenaiApiKeyDisabled, resolveEnvVars } from "./config.js";
30
25
  export { resolveRemnicConfigRecord } from "./config-record.js";
31
26
  export * from "./external-wiki.js";
27
+ export * from "./external-wiki-cli.js";
32
28
  export {
33
29
  parseFlexibleIsoTimestamp,
34
30
  parseIsoOffsetTimestamp,
@@ -278,7 +278,7 @@ export async function runFirstStartMigration(
278
278
  qmd,
279
279
  hotCollection: options.hotCollection ?? config.qmdCollection ?? "openclaw-engram",
280
280
  coldCollection: options.coldCollection ?? config.qmdColdCollection ?? "openclaw-engram-cold",
281
- })
281
+ })
282
282
  : null;
283
283
  const coldCollection = options.coldCollection ?? config.qmdColdCollection ?? "openclaw-engram-cold";
284
284
 
@@ -287,17 +287,17 @@ export async function runFirstStartMigration(
287
287
  return abortedResult(candidateCount, demotedCount, failureCount);
288
288
  }
289
289
  try {
290
- if (executor) {
291
- await executor.migrateMemory({
292
- memory,
293
- fromTier: "hot",
294
- toTier: "cold",
295
- reason: "first-start-lifecycle-migration",
296
- });
297
- } else {
298
- await storage.migrateMemoryToTier(memory, "cold");
290
+ const result = executor
291
+ ? await executor.migrateMemory({
292
+ memory,
293
+ fromTier: "hot",
294
+ toTier: "cold",
295
+ reason: "first-start-lifecycle-migration",
296
+ })
297
+ : await storage.migrateMemoryToTier(memory, "cold");
298
+ if (result.changed) {
299
+ demotedCount += 1;
299
300
  }
300
- demotedCount += 1;
301
301
  } catch {
302
302
  const targetPath = storage.buildTierMemoryPath(memory, "cold");
303
303
  const [targetExists, sourceExists] = await Promise.all([
@@ -129,6 +129,32 @@ test("episode write is idempotent — an identical episode is skipped", async ()
129
129
  assert.equal(writer.writes.length, 1);
130
130
  });
131
131
 
132
+ test("an episode whose provider title is a personal claim is held for review (#2294)", async () => {
133
+ // The episode is a recall anchor written active, but its title comes from the
134
+ // provider's read of the same ambient audio — so a title lifted from a
135
+ // television scene must not enter recall on the anchor.
136
+ const writer = new FakeWriter();
137
+ await writeMeetingEpisodeMemory(record({ title: "Dana's cancer diagnosis" }), writer);
138
+ assert.equal(writer.writes[0]!.extras.status, "pending_review");
139
+
140
+ const clean = new FakeWriter();
141
+ await writeMeetingEpisodeMemory(record({ title: "Sprint planning" }), clean);
142
+ assert.equal(clean.writes[0]!.extras.status, "active", "an ordinary title is unaffected");
143
+ });
144
+
145
+ test("an audio-only episode is held for review — detection alone is not corroboration (#2294)", async () => {
146
+ // `audio` detection is a heuristic over speech with no app span behind it, so
147
+ // fifteen minutes of television with two voices yields an episode asserting a
148
+ // meeting happened with the show's speakers as attendees.
149
+ const writer = new FakeWriter();
150
+ await writeMeetingEpisodeMemory(record({ app: undefined, detectionSource: "audio" }), writer);
151
+ assert.equal(writer.writes[0]!.extras.status, "pending_review");
152
+
153
+ const corroborated = new FakeWriter();
154
+ await writeMeetingEpisodeMemory(record({ detectionSource: "app+audio" }), corroborated);
155
+ assert.equal(corroborated.writes[0]!.extras.status, "active");
156
+ });
157
+
132
158
  test("an audio-only meeting omits the meetingApp attribute and the app suffix", async () => {
133
159
  const writer = new FakeWriter();
134
160
  const audioOnly = record({ app: undefined, detectionSource: "audio" });
@@ -206,6 +232,31 @@ test("summaryMode smart routes a high-trust decision to active with meeting prov
206
232
  assert.ok(writer.writes.some((w) => w.envelope.category === "commitment"), "a commitment fact was written");
207
233
  });
208
234
 
235
+ test("a high-impact personal claim never goes active, however the trust adds up (#2294)", async () => {
236
+ // A meeting transcript is the same always-on capture audio a wearable
237
+ // records, so a fabricated medical line can arrive in it. At the extractor's
238
+ // fixed 0.9 confidence, 0.9 * 0.85 = 0.765 clears the 0.7 auto-approve line;
239
+ // the ambient cap must hold it in the review queue anyway.
240
+ const writer = new FakeWriter();
241
+ const extractor = spyExtractor("Meeting summary.", [
242
+ { content: "Dana was diagnosed with cancer last month", category: "decision", confidence: 0.9 },
243
+ { content: "Team decided to ship v2 on Friday", category: "decision", confidence: 0.9 },
244
+ ]);
245
+
246
+ const res = await generateMeetingSummaryFacts(TRANSCRIPT_RECORD(), meetingConfig({ summaryMode: "smart" }), {
247
+ extractor,
248
+ writer,
249
+ });
250
+
251
+ assert.equal(res.dropped, 0, "the cap downgrades rather than drops");
252
+ const medical = writer.writes.find((w) => w.envelope.content.includes("diagnosed"));
253
+ assert.ok(medical, "the medical claim was written");
254
+ assert.equal(medical!.extras.status, "pending_review");
255
+ const ordinary = writer.writes.find((w) => w.envelope.content.includes("ship v2"));
256
+ assert.ok(ordinary, "the ordinary decision was written");
257
+ assert.equal(ordinary!.extras.status, "active", "ordinary meeting facts are unaffected");
258
+ });
259
+
209
260
  test("summaryMode smart drops a low-trust candidate but corroboration promotes it to review", async () => {
210
261
  // conf 0.5 * sourceTrust 0.85 = 0.425 < reviewTrust 0.45 -> drop.
211
262
  const lowConf: MeetingFactCandidate[] = [{ content: "maybe we will refactor later", category: "fact", confidence: 0.5 }];