@remnic/core 9.65.5 → 9.65.7

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 (500) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +26 -26
  3. package/dist/access-authorization-probe.d.ts +11 -11
  4. package/dist/access-authorization-probe.js +27 -27
  5. package/dist/access-boundary.d.ts +11 -11
  6. package/dist/access-boundary.js +26 -26
  7. package/dist/access-cli.js +110 -104
  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 +11 -11
  11. package/dist/access-extraction-force-flush.js +26 -26
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +11 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +11 -11
  15. package/dist/access-http-offline-stream.d.ts +11 -11
  16. package/dist/access-http-query.d.ts +2 -2
  17. package/dist/access-http-query.js +28 -28
  18. package/dist/access-http.d.ts +13 -18
  19. package/dist/access-http.js +46 -44
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +26 -26
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +26 -26
  24. package/dist/access-mcp-output-schemas.js +1 -1
  25. package/dist/access-mcp.d.ts +11 -11
  26. package/dist/access-mcp.js +37 -35
  27. package/dist/access-memory-search-fanout.d.ts +2 -2
  28. package/dist/{access-namespace-preflight-D_6mo8ms.d.ts → access-namespace-preflight-8VYKmRX0.d.ts} +1 -1
  29. package/dist/access-namespace-preflight.d.ts +3 -3
  30. package/dist/access-namespace-preflight.js +26 -26
  31. package/dist/access-observe-write-surface.d.ts +11 -11
  32. package/dist/access-observe-write-surface.js +26 -26
  33. package/dist/access-offline-manifest.d.ts +9 -9
  34. package/dist/access-operations-batch.js +29 -29
  35. package/dist/access-operations.d.ts +12 -12
  36. package/dist/access-operations.js +34 -32
  37. package/dist/access-recall-concurrency.d.ts +11 -11
  38. package/dist/access-recall-concurrency.js +26 -26
  39. package/dist/access-recall-response.d.ts +11 -11
  40. package/dist/access-recall-response.js +26 -26
  41. package/dist/access-recall-surface.d.ts +11 -11
  42. package/dist/access-recall-surface.js +26 -26
  43. package/dist/access-schema.js +3 -3
  44. package/dist/{access-service-sbiNS5UB.d.ts → access-service-Crk__Git.d.ts} +8 -8
  45. package/dist/access-service-helpers.d.ts +11 -11
  46. package/dist/access-service.d.ts +11 -11
  47. package/dist/access-service.js +26 -26
  48. package/dist/access-surface-catalog.d.ts +11 -11
  49. package/dist/access-surface-catalog.js +38 -28
  50. package/dist/access-surface-catalog.js.map +1 -1
  51. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  52. package/dist/action-confidence.d.ts +1 -1
  53. package/dist/active-memory-bridge.d.ts +1 -1
  54. package/dist/active-recall.d.ts +1 -1
  55. package/dist/active-recall.js +4 -4
  56. package/dist/adapters/index.js +4 -4
  57. package/dist/adapters/registry.js +2 -2
  58. package/dist/ambient-provenance.d.ts +1 -1
  59. package/dist/artifact-search.d.ts +1 -1
  60. package/dist/behavior-learner.d.ts +1 -1
  61. package/dist/behavior-signals.d.ts +1 -1
  62. package/dist/bootstrap.d.ts +9 -9
  63. package/dist/briefing-window.d.ts +2 -2
  64. package/dist/briefing.d.ts +2 -2
  65. package/dist/briefing.js +8 -8
  66. package/dist/buffer-surprise-report.d.ts +1 -1
  67. package/dist/buffer-turn-helpers.d.ts +1 -1
  68. package/dist/buffer.d.ts +2 -2
  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/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
  73. package/dist/{catalog-DO_7zfkv.d.ts → catalog-DybwVNW3.d.ts} +1 -1
  74. package/dist/causal-behavior.d.ts +1 -1
  75. package/dist/causal-behavior.js +2 -2
  76. package/dist/causal-chain.js +2 -2
  77. package/dist/causal-consolidation.d.ts +1 -1
  78. package/dist/causal-consolidation.js +11 -11
  79. package/dist/causal-retrieval.js +2 -2
  80. package/dist/causal-trajectory-graph.d.ts +1 -1
  81. package/dist/causal-trajectory-graph.js +2 -2
  82. package/dist/causal-trajectory.js +1 -1
  83. package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
  84. package/dist/{chunk-NZPFCP5A.js → chunk-2PSX5BJU.js} +2 -2
  85. package/dist/chunk-3BCULS4U.js +1093 -0
  86. package/dist/chunk-3BCULS4U.js.map +1 -0
  87. package/dist/{chunk-IIRCHGWD.js → chunk-3RI5Y7KU.js} +2 -2
  88. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  89. package/dist/{chunk-J3ATBB7M.js → chunk-5DH6PG4B.js} +2 -2
  90. package/dist/{chunk-M4AHBM72.js → chunk-5HERQ5FX.js} +10 -10
  91. package/dist/{chunk-W675UJCZ.js → chunk-5HK3CJAR.js} +2 -2
  92. package/dist/{chunk-2MVTAIL3.js → chunk-5S4LQOPE.js} +2 -2
  93. package/dist/{chunk-OZDFB22S.js → chunk-5VPQSRQO.js} +3 -3
  94. package/dist/{chunk-YZJM6CLF.js → chunk-6CPUQ5D6.js} +10 -10
  95. package/dist/{chunk-2IXQSGCU.js → chunk-7F27PCSN.js} +2 -2
  96. package/dist/{chunk-OWQNJJY2.js → chunk-7TCGNUVP.js} +2 -2
  97. package/dist/{chunk-3NH3VP3U.js → chunk-7WR462EM.js} +2 -2
  98. package/dist/{chunk-NH6LC57D.js → chunk-A32YEQAM.js} +2 -2
  99. package/dist/{chunk-HF5BUTI6.js → chunk-ACOC27BB.js} +2 -2
  100. package/dist/{chunk-N56GVOWR.js → chunk-AFR6AIM4.js} +144 -78
  101. package/dist/chunk-AFR6AIM4.js.map +1 -0
  102. package/dist/{chunk-LYBIHM4N.js → chunk-ANJXPFRS.js} +47 -26
  103. package/dist/chunk-ANJXPFRS.js.map +1 -0
  104. package/dist/{chunk-FC7TIRFS.js → chunk-AX7UXCHJ.js} +6 -1
  105. package/dist/chunk-AX7UXCHJ.js.map +1 -0
  106. package/dist/{chunk-THVI4Y7X.js → chunk-BJTHRFFC.js} +6 -6
  107. package/dist/chunk-BWGCOLEL.js +61 -0
  108. package/dist/chunk-BWGCOLEL.js.map +1 -0
  109. package/dist/{chunk-BW4GAF57.js → chunk-CFGU52XJ.js} +2 -2
  110. package/dist/{chunk-DPNXADEI.js → chunk-D4QVPP3G.js} +2 -2
  111. package/dist/{chunk-BK5G2MHO.js → chunk-EOHKUWXW.js} +2 -2
  112. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  113. package/dist/{chunk-ZK4BFABK.js → chunk-F635GAL7.js} +4 -4
  114. package/dist/{chunk-IURMJBGP.js → chunk-F6QHHRWP.js} +2 -2
  115. package/dist/{chunk-BA2GLSIP.js → chunk-FMQ4MOQO.js} +91 -28
  116. package/dist/chunk-FMQ4MOQO.js.map +1 -0
  117. package/dist/{chunk-LDBFXD4F.js → chunk-FP7YTTVO.js} +3 -1
  118. package/dist/chunk-FP7YTTVO.js.map +1 -0
  119. package/dist/{chunk-TJFI3K2O.js → chunk-GEPACVWN.js} +2 -2
  120. package/dist/{chunk-PP7R754B.js → chunk-GPFZFCRN.js} +1 -1
  121. package/dist/{chunk-UCKG36HO.js → chunk-GTSVEEP3.js} +2 -2
  122. package/dist/{chunk-KTPXXVDQ.js → chunk-I4343FIA.js} +79 -6
  123. package/dist/chunk-I4343FIA.js.map +1 -0
  124. package/dist/{chunk-DPGH6LHQ.js → chunk-I7EX6KSH.js} +57 -57
  125. package/dist/{chunk-JPAKBNTM.js → chunk-IP4ZNT4U.js} +2 -2
  126. package/dist/{chunk-AXGFOFNY.js → chunk-IY7UXD3J.js} +2 -2
  127. package/dist/{chunk-YHCBJULX.js → chunk-JAQXUGLN.js} +2 -2
  128. package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
  129. package/dist/chunk-JCCWJHOP.js +240 -0
  130. package/dist/chunk-JCCWJHOP.js.map +1 -0
  131. package/dist/{chunk-VDX2J7OX.js → chunk-KQAFEZQX.js} +2 -2
  132. package/dist/{chunk-D2YNNDML.js → chunk-KWIGDKM2.js} +2 -2
  133. package/dist/{chunk-YB4GBWBU.js → chunk-LLQCM2U2.js} +81 -81
  134. package/dist/{chunk-OLBZ2WGG.js → chunk-LTBKKSCX.js} +2 -2
  135. package/dist/{chunk-DORFF5N5.js → chunk-NG3MBQV4.js} +2 -2
  136. package/dist/{chunk-DUEDOYZD.js → chunk-OPGL46PX.js} +2 -2
  137. package/dist/{chunk-OUKBMQ2O.js → chunk-PD66CVSD.js} +2 -2
  138. package/dist/{chunk-CQBIN77D.js → chunk-PDDSFELN.js} +2 -2
  139. package/dist/{chunk-6433HV72.js → chunk-PMVPCZJZ.js} +2 -2
  140. package/dist/{chunk-DJZWNKFO.js → chunk-RGCF4XNH.js} +7 -7
  141. package/dist/{chunk-CV3GNPOE.js → chunk-RQE4TITU.js} +29 -24
  142. package/dist/chunk-RQE4TITU.js.map +1 -0
  143. package/dist/{chunk-4JSF7UUP.js → chunk-S3K2CIK5.js} +2 -2
  144. package/dist/chunk-SDEPLF7V.js +325 -0
  145. package/dist/chunk-SDEPLF7V.js.map +1 -0
  146. package/dist/{chunk-OCCHUEZB.js → chunk-SEA6M7SS.js} +2 -2
  147. package/dist/{chunk-KOO37E4Y.js → chunk-SVVIASVX.js} +2 -2
  148. package/dist/{chunk-4K7IW3F7.js → chunk-UD7UNYRD.js} +34 -3
  149. package/dist/chunk-UD7UNYRD.js.map +1 -0
  150. package/dist/chunk-ULM7JCDH.js +154 -0
  151. package/dist/chunk-ULM7JCDH.js.map +1 -0
  152. package/dist/{chunk-FBR7PIL4.js → chunk-VKCAHCBI.js} +2 -2
  153. package/dist/{chunk-WDXD6ITO.js → chunk-VXVZ2GM3.js} +2 -2
  154. package/dist/chunk-W2UOAATB.js +521 -0
  155. package/dist/chunk-W2UOAATB.js.map +1 -0
  156. package/dist/{chunk-DUZARALI.js → chunk-WTOZBZNN.js} +3 -3
  157. package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
  158. package/dist/{chunk-2EPOGPKO.js → chunk-YKWFK7XA.js} +5 -5
  159. package/dist/{chunk-BIJAWZYW.js → chunk-YMOPYG3K.js} +6 -6
  160. package/dist/{chunk-UFR6HX7A.js → chunk-YRVAKONL.js} +1 -1
  161. package/dist/{chunk-ECLJ4LA2.js → chunk-YWSQD2IB.js} +2 -2
  162. package/dist/{chunk-NLEH4RTB.js → chunk-Z4U3UN56.js} +2 -2
  163. package/dist/{chunk-YDKF4MSJ.js → chunk-ZAOHJDKH.js} +3 -3
  164. package/dist/{chunk-KFIOPZ25.js → chunk-ZIJDI4CP.js} +2 -2
  165. package/dist/{cli-BqdqPdG_.d.ts → cli-B322UMvB.d.ts} +6 -6
  166. package/dist/cli.d.ts +14 -14
  167. package/dist/cli.js +73 -72
  168. package/dist/coding/pre-action-gate.d.ts +1 -1
  169. package/dist/coding/pre-action-gate.js +2 -2
  170. package/dist/compounding/engine.d.ts +2 -2
  171. package/dist/compounding/engine.js +8 -8
  172. package/dist/compounding/preference-consolidator.d.ts +1 -1
  173. package/dist/compression-optimizer.d.ts +1 -1
  174. package/dist/config.d.ts +1 -1
  175. package/dist/config.js +4 -4
  176. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  177. package/dist/connectors/codex-materialize-runner.js +8 -8
  178. package/dist/connectors/codex-materialize.d.ts +1 -1
  179. package/dist/connectors/index.d.ts +1 -1
  180. package/dist/connectors/index.js +8 -8
  181. package/dist/consolidation-provenance-check.d.ts +2 -2
  182. package/dist/consolidation-undo.d.ts +2 -2
  183. package/dist/contradiction/index.d.ts +3 -3
  184. package/dist/converge-config.d.ts +1 -1
  185. package/dist/convergence-refresh.d.ts +2 -2
  186. package/dist/convergence-refresh.js +10 -10
  187. package/dist/conversation-index/backend.d.ts +1 -1
  188. package/dist/conversation-index/chunker.d.ts +1 -1
  189. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  190. package/dist/conversation-index/indexer.d.ts +1 -1
  191. package/dist/conversation-index/search.d.ts +1 -1
  192. package/dist/corpus-watermark.d.ts +1 -1
  193. package/dist/corpus-watermark.js +10 -10
  194. package/dist/cross-lingual-recall.d.ts +1 -1
  195. package/dist/dashboard-runtime.js +2 -2
  196. package/dist/day-summary.d.ts +1 -1
  197. package/dist/delinearize.d.ts +1 -1
  198. package/dist/dependency-propagation-config.d.ts +1 -1
  199. package/dist/{dependency-propagation-delivery-D23_x-s5.d.ts → dependency-propagation-delivery-BGcNairQ.d.ts} +1 -1
  200. package/dist/direct-answer-wiring.d.ts +1 -1
  201. package/dist/direct-answer.d.ts +1 -1
  202. package/dist/embedding-fallback.d.ts +1 -1
  203. package/dist/enrichment/index.d.ts +1 -1
  204. package/dist/entity-origin-fields.d.ts +1 -1
  205. package/dist/entity-retrieval.d.ts +2 -2
  206. package/dist/entity-retrieval.js +8 -8
  207. package/dist/entity-schema.d.ts +1 -1
  208. package/dist/episodic-context.d.ts +1 -1
  209. package/dist/eval-trajectory-contracts.d.ts +256 -0
  210. package/dist/eval-trajectory-contracts.js +56 -0
  211. package/dist/eval-trajectory-store.d.ts +39 -0
  212. package/dist/eval-trajectory-store.js +19 -0
  213. package/dist/eval-trajectory-store.js.map +1 -0
  214. package/dist/eval-trajectory.d.ts +67 -0
  215. package/dist/eval-trajectory.js +46 -0
  216. package/dist/eval-trajectory.js.map +1 -0
  217. package/dist/event-order-recall.js +2 -2
  218. package/dist/explicit-capture.d.ts +9 -9
  219. package/dist/external-wiki-access.d.ts +11 -11
  220. package/dist/external-wiki-access.js +27 -27
  221. package/dist/external-wiki-collection-registration.d.ts +1 -1
  222. package/dist/external-wiki-collection.d.ts +1 -1
  223. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  224. package/dist/extraction-error-classification.d.ts +1 -1
  225. package/dist/extraction-faithfulness.d.ts +1 -1
  226. package/dist/extraction-judge-telemetry.d.ts +1 -1
  227. package/dist/extraction-judge-training.d.ts +1 -1
  228. package/dist/extraction-judge.d.ts +1 -1
  229. package/dist/extraction-liveness.d.ts +1 -1
  230. package/dist/extraction-normalization.d.ts +1 -1
  231. package/dist/extraction-prompt.d.ts +1 -1
  232. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  233. package/dist/extraction-source-grounding.d.ts +1 -1
  234. package/dist/extraction.d.ts +1 -1
  235. package/dist/extraction.js +10 -10
  236. package/dist/fallback-llm.d.ts +1 -1
  237. package/dist/graph-dashboard-diff.d.ts +1 -1
  238. package/dist/graph-dashboard-key.d.ts +1 -1
  239. package/dist/graph-dashboard-parser.d.ts +1 -1
  240. package/dist/{graph-edge-decay-FXGELBFA.js → graph-edge-decay-A4SDFMMS.js} +4 -4
  241. package/dist/graph-edge-decay-A4SDFMMS.js.map +1 -0
  242. package/dist/graph-edge-reinforcement.d.ts +1 -1
  243. package/dist/graph-path-reconstruction.d.ts +1 -1
  244. package/dist/graph-path-scoring.d.ts +1 -1
  245. package/dist/graph-snapshot.d.ts +1 -1
  246. package/dist/graph-snapshot.js +3 -3
  247. package/dist/graph.d.ts +1 -1
  248. package/dist/graph.js +3 -3
  249. package/dist/harmonic-retrieval.js +1 -1
  250. package/dist/importance.d.ts +1 -1
  251. package/dist/importers/index.d.ts +1 -1
  252. package/dist/in-flight-reads.d.ts +1 -1
  253. package/dist/{index--QhGIXF2.d.ts → index-By2QUAMh.d.ts} +2 -2
  254. package/dist/index.d.ts +27 -23
  255. package/dist/index.js +199 -141
  256. package/dist/intent.d.ts +1 -1
  257. package/dist/lcm/engine.d.ts +1 -1
  258. package/dist/lcm/engine.js +4 -4
  259. package/dist/lcm/index.d.ts +1 -1
  260. package/dist/lcm/index.js +10 -10
  261. package/dist/lcm/tools.d.ts +1 -1
  262. package/dist/lifecycle.d.ts +1 -1
  263. package/dist/live-connectors-runner.d.ts +1 -1
  264. package/dist/local-llm.d.ts +1 -1
  265. package/dist/local-model-endpoint.d.ts +1 -1
  266. package/dist/location/index.d.ts +128 -1
  267. package/dist/location/index.js +60 -750
  268. package/dist/location/index.js.map +1 -1
  269. package/dist/maintenance/memory-governance.d.ts +1 -1
  270. package/dist/maintenance/memory-governance.js +8 -8
  271. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  272. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +8 -8
  273. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  274. package/dist/maintenance/rebuild-memory-projection.js +9 -9
  275. package/dist/{maintenance-PFvY1Pw_.d.ts → maintenance-Dm2McrIx.d.ts} +4 -3
  276. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  277. package/dist/mcp-read-only-tools.js +1 -1
  278. package/dist/memory-action-policy.d.ts +1 -1
  279. package/dist/memory-cache.d.ts +1 -1
  280. package/dist/memory-controller.d.ts +203 -0
  281. package/dist/memory-controller.js +23 -0
  282. package/dist/memory-controller.js.map +1 -0
  283. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  284. package/dist/memory-projection-store.d.ts +1 -1
  285. package/dist/memory-provenance.d.ts +1 -1
  286. package/dist/memory-snapshot.d.ts +1 -1
  287. package/dist/memory-subject-cli.d.ts +11 -11
  288. package/dist/memory-subject.d.ts +11 -11
  289. package/dist/memory-worth-outcomes.d.ts +47 -3
  290. package/dist/memory-worth-outcomes.js +5 -3
  291. package/dist/models-json.d.ts +1 -1
  292. package/dist/namespaces/migrate.d.ts +3 -3
  293. package/dist/namespaces/migrate.js +9 -9
  294. package/dist/namespaces/principal.d.ts +1 -1
  295. package/dist/namespaces/search.d.ts +1 -1
  296. package/dist/namespaces/search.js +5 -5
  297. package/dist/namespaces/storage.d.ts +3 -3
  298. package/dist/namespaces/storage.js +8 -8
  299. package/dist/native-knowledge.d.ts +1 -1
  300. package/dist/offline-sync-impression-drain.d.ts +1 -1
  301. package/dist/operator-doctor-corpus.d.ts +1 -1
  302. package/dist/operator-doctor-corpus.js +11 -11
  303. package/dist/operator-doctor-replica.d.ts +1 -1
  304. package/dist/operator-toolkit.d.ts +3 -3
  305. package/dist/operator-toolkit.js +22 -22
  306. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  307. package/dist/orchestration/maintenance.d.ts +4 -4
  308. package/dist/orchestration/maintenance.js +16 -14
  309. package/dist/{orchestrator-4wzJrPVm.d.ts → orchestrator-Co1DyfuP.d.ts} +8 -8
  310. package/dist/orchestrator.d.ts +9 -9
  311. package/dist/orchestrator.js +110 -104
  312. package/dist/patterns-cli.d.ts +1 -1
  313. package/dist/{pipeline-CgXgdIrF.d.ts → pipeline-DotMnb6y.d.ts} +1 -1
  314. package/dist/policy-runtime.d.ts +1 -1
  315. package/dist/proactive-contention.d.ts +1 -1
  316. package/dist/provenance.d.ts +1 -1
  317. package/dist/{public-http-BP3VQDl5.d.ts → public-http-PJRtnSi-.d.ts} +1 -1
  318. package/dist/{qmd-BppGGxsi.d.ts → qmd-BP0n11fR.d.ts} +1 -1
  319. package/dist/qmd-preflight.d.ts +2 -2
  320. package/dist/qmd-recall-cache.d.ts +1 -1
  321. package/dist/qmd.d.ts +2 -2
  322. package/dist/recall-concurrency-config.d.ts +1 -1
  323. package/dist/recall-disclosure-escalation.d.ts +1 -1
  324. package/dist/recall-explain-renderer.d.ts +1 -1
  325. package/dist/recall-memory-map.d.ts +1 -1
  326. package/dist/recall-planner-llm.d.ts +1 -1
  327. package/dist/recall-state.d.ts +1 -1
  328. package/dist/recall-tag-filter.d.ts +1 -1
  329. package/dist/recall-timings.d.ts +1 -1
  330. package/dist/recall-xray-cli.d.ts +1 -1
  331. package/dist/recall-xray-renderer.d.ts +1 -1
  332. package/dist/recall-xray.d.ts +1 -1
  333. package/dist/reconcile/cursor.d.ts +1 -1
  334. package/dist/reconcile/manifest.d.ts +1 -1
  335. package/dist/reconcile/plan.d.ts +1 -1
  336. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  337. package/dist/replay/normalizers/claude.d.ts +1 -1
  338. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  339. package/dist/replay/normalizers/shared.d.ts +1 -1
  340. package/dist/replay/runner.d.ts +1 -1
  341. package/dist/replay/types.d.ts +1 -1
  342. package/dist/replica-divergence.d.ts +1 -1
  343. package/dist/replica-peers-config.d.ts +1 -1
  344. package/dist/resolve-auth-token.d.ts +1 -1
  345. package/dist/resume-bundles.js +5 -5
  346. package/dist/retrieval-agents.d.ts +2 -2
  347. package/dist/retrieval-tiers.d.ts +1 -1
  348. package/dist/routing/engine.d.ts +1 -1
  349. package/dist/routing/store.d.ts +1 -1
  350. package/dist/salvage-envelope.d.ts +1 -1
  351. package/dist/{scope-profiles-ChZUtxDU.d.ts → scope-profiles-6ChZKTy-.d.ts} +1 -1
  352. package/dist/search/embed-helper.d.ts +1 -1
  353. package/dist/search/factory.d.ts +1 -1
  354. package/dist/search/factory.js +4 -4
  355. package/dist/search/index.d.ts +1 -1
  356. package/dist/search/index.js +10 -10
  357. package/dist/search/lancedb-backend.d.ts +1 -1
  358. package/dist/search/meilisearch-backend.d.ts +1 -1
  359. package/dist/search/noop-backend.d.ts +1 -1
  360. package/dist/search/orama-backend.d.ts +1 -1
  361. package/dist/search/port.d.ts +1 -1
  362. package/dist/search/remote-backend.d.ts +1 -1
  363. package/dist/{semantic-consolidation-mSPwQSmF.d.ts → semantic-consolidation-DziYcW5J.d.ts} +1 -1
  364. package/dist/semantic-consolidation.d.ts +2 -2
  365. package/dist/semantic-consolidation.js +9 -9
  366. package/dist/semantic-rule-promotion.js +8 -8
  367. package/dist/semantic-rule-verifier.d.ts +1 -1
  368. package/dist/semantic-rule-verifier.js +8 -8
  369. package/dist/{service-BICWLwSP.d.ts → service-C7rIBuK_.d.ts} +2 -2
  370. package/dist/session-observer-bands.d.ts +1 -1
  371. package/dist/session-observer-state.d.ts +1 -1
  372. package/dist/shared-context/manager.d.ts +1 -1
  373. package/dist/signal.d.ts +1 -1
  374. package/dist/source-agent-qualifier.d.ts +1 -1
  375. package/dist/source-agent-qualifier.js +8 -8
  376. package/dist/{storage-B7urx1K3.d.ts → storage-B1hEx8Xg.d.ts} +1 -1
  377. package/dist/storage.d.ts +2 -2
  378. package/dist/storage.js +7 -7
  379. package/dist/subject-config.d.ts +1 -1
  380. package/dist/summarizer.d.ts +1 -1
  381. package/dist/summary-snapshot.d.ts +1 -1
  382. package/dist/support-passport/index.d.ts +14 -14
  383. package/dist/support-passport/index.js +29 -29
  384. package/dist/temporal-supersession.d.ts +2 -2
  385. package/dist/temporal-timeline-recall.d.ts +1 -1
  386. package/dist/temporal-validity.d.ts +1 -1
  387. package/dist/threading.d.ts +1 -1
  388. package/dist/tier-migration.d.ts +2 -2
  389. package/dist/tier-routing.d.ts +1 -1
  390. package/dist/topics.d.ts +1 -1
  391. package/dist/transcript.d.ts +1 -1
  392. package/dist/transfer/backup.js +2 -2
  393. package/dist/transfer/capsule-export.js +2 -2
  394. package/dist/transfer/capsule-import.js +2 -2
  395. package/dist/trust-score-stage.d.ts +1 -1
  396. package/dist/trust-score.d.ts +1 -1
  397. package/dist/{types-ETU5N6nB.d.ts → types-BHDNxGTT.d.ts} +1 -1
  398. package/dist/types.d.ts +1 -1
  399. package/dist/utility-runtime.d.ts +1 -1
  400. package/dist/verified-recall.js +8 -8
  401. package/dist/who-knows-cli.d.ts +11 -11
  402. package/dist/who-knows-cli.js +9 -9
  403. package/dist/who-knows.d.ts +11 -11
  404. package/dist/who-knows.js +8 -8
  405. package/dist/write-envelope.d.ts +1 -1
  406. package/package.json +2 -2
  407. package/src/access-boundary.ts +5 -0
  408. package/src/access-http.ts +15 -16
  409. package/src/access-mcp-output-schemas.ts +5 -0
  410. package/src/access-mcp.ts +6 -6
  411. package/src/access-operations.ts +2 -0
  412. package/src/access-surface-catalog.ts +10 -0
  413. package/src/eval-trajectory-contracts.ts +411 -0
  414. package/src/eval-trajectory-store.ts +306 -0
  415. package/src/eval-trajectory.test.ts +534 -0
  416. package/src/eval-trajectory.ts +773 -0
  417. package/src/index.ts +5 -0
  418. package/src/location/access-operations.ts +84 -0
  419. package/src/location/http-glue.test.ts +100 -0
  420. package/src/location/http-glue.ts +85 -0
  421. package/src/location/index.ts +3 -0
  422. package/src/location/mcp-tools.ts +82 -0
  423. package/src/location/provider-setup.test.ts +106 -0
  424. package/src/location/provider-setup.ts +103 -0
  425. package/src/location/scheduler.test.ts +113 -0
  426. package/src/location/scheduler.ts +98 -0
  427. package/src/location/surfaces.test.ts +241 -0
  428. package/src/location/surfaces.ts +329 -0
  429. package/src/maintenance/day-summary-cron.ts +45 -0
  430. package/src/mcp-read-only-tools.ts +2 -0
  431. package/src/memory-controller.test.ts +347 -0
  432. package/src/memory-controller.ts +547 -0
  433. package/src/memory-worth-outcomes.test.ts +53 -18
  434. package/src/memory-worth-outcomes.ts +91 -9
  435. package/src/orchestration/maintenance.ts +22 -30
  436. package/src/wearables/http-glue.ts +28 -0
  437. package/dist/chunk-4K7IW3F7.js.map +0 -1
  438. package/dist/chunk-BA2GLSIP.js.map +0 -1
  439. package/dist/chunk-CV3GNPOE.js.map +0 -1
  440. package/dist/chunk-FC7TIRFS.js.map +0 -1
  441. package/dist/chunk-KTPXXVDQ.js.map +0 -1
  442. package/dist/chunk-LDBFXD4F.js.map +0 -1
  443. package/dist/chunk-LYBIHM4N.js.map +0 -1
  444. package/dist/chunk-N56GVOWR.js.map +0 -1
  445. /package/dist/{capsule-crypto-YO5QJ6L3.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
  446. /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
  447. /package/dist/{chunk-NZPFCP5A.js.map → chunk-2PSX5BJU.js.map} +0 -0
  448. /package/dist/{chunk-IIRCHGWD.js.map → chunk-3RI5Y7KU.js.map} +0 -0
  449. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  450. /package/dist/{chunk-J3ATBB7M.js.map → chunk-5DH6PG4B.js.map} +0 -0
  451. /package/dist/{chunk-M4AHBM72.js.map → chunk-5HERQ5FX.js.map} +0 -0
  452. /package/dist/{chunk-W675UJCZ.js.map → chunk-5HK3CJAR.js.map} +0 -0
  453. /package/dist/{chunk-2MVTAIL3.js.map → chunk-5S4LQOPE.js.map} +0 -0
  454. /package/dist/{chunk-OZDFB22S.js.map → chunk-5VPQSRQO.js.map} +0 -0
  455. /package/dist/{chunk-YZJM6CLF.js.map → chunk-6CPUQ5D6.js.map} +0 -0
  456. /package/dist/{chunk-2IXQSGCU.js.map → chunk-7F27PCSN.js.map} +0 -0
  457. /package/dist/{chunk-OWQNJJY2.js.map → chunk-7TCGNUVP.js.map} +0 -0
  458. /package/dist/{chunk-3NH3VP3U.js.map → chunk-7WR462EM.js.map} +0 -0
  459. /package/dist/{chunk-NH6LC57D.js.map → chunk-A32YEQAM.js.map} +0 -0
  460. /package/dist/{chunk-HF5BUTI6.js.map → chunk-ACOC27BB.js.map} +0 -0
  461. /package/dist/{chunk-THVI4Y7X.js.map → chunk-BJTHRFFC.js.map} +0 -0
  462. /package/dist/{chunk-BW4GAF57.js.map → chunk-CFGU52XJ.js.map} +0 -0
  463. /package/dist/{chunk-DPNXADEI.js.map → chunk-D4QVPP3G.js.map} +0 -0
  464. /package/dist/{chunk-BK5G2MHO.js.map → chunk-EOHKUWXW.js.map} +0 -0
  465. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  466. /package/dist/{chunk-ZK4BFABK.js.map → chunk-F635GAL7.js.map} +0 -0
  467. /package/dist/{chunk-IURMJBGP.js.map → chunk-F6QHHRWP.js.map} +0 -0
  468. /package/dist/{chunk-TJFI3K2O.js.map → chunk-GEPACVWN.js.map} +0 -0
  469. /package/dist/{chunk-PP7R754B.js.map → chunk-GPFZFCRN.js.map} +0 -0
  470. /package/dist/{chunk-UCKG36HO.js.map → chunk-GTSVEEP3.js.map} +0 -0
  471. /package/dist/{chunk-DPGH6LHQ.js.map → chunk-I7EX6KSH.js.map} +0 -0
  472. /package/dist/{chunk-JPAKBNTM.js.map → chunk-IP4ZNT4U.js.map} +0 -0
  473. /package/dist/{chunk-AXGFOFNY.js.map → chunk-IY7UXD3J.js.map} +0 -0
  474. /package/dist/{chunk-YHCBJULX.js.map → chunk-JAQXUGLN.js.map} +0 -0
  475. /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
  476. /package/dist/{chunk-VDX2J7OX.js.map → chunk-KQAFEZQX.js.map} +0 -0
  477. /package/dist/{chunk-D2YNNDML.js.map → chunk-KWIGDKM2.js.map} +0 -0
  478. /package/dist/{chunk-YB4GBWBU.js.map → chunk-LLQCM2U2.js.map} +0 -0
  479. /package/dist/{chunk-OLBZ2WGG.js.map → chunk-LTBKKSCX.js.map} +0 -0
  480. /package/dist/{chunk-DORFF5N5.js.map → chunk-NG3MBQV4.js.map} +0 -0
  481. /package/dist/{chunk-DUEDOYZD.js.map → chunk-OPGL46PX.js.map} +0 -0
  482. /package/dist/{chunk-OUKBMQ2O.js.map → chunk-PD66CVSD.js.map} +0 -0
  483. /package/dist/{chunk-CQBIN77D.js.map → chunk-PDDSFELN.js.map} +0 -0
  484. /package/dist/{chunk-6433HV72.js.map → chunk-PMVPCZJZ.js.map} +0 -0
  485. /package/dist/{chunk-DJZWNKFO.js.map → chunk-RGCF4XNH.js.map} +0 -0
  486. /package/dist/{chunk-4JSF7UUP.js.map → chunk-S3K2CIK5.js.map} +0 -0
  487. /package/dist/{chunk-OCCHUEZB.js.map → chunk-SEA6M7SS.js.map} +0 -0
  488. /package/dist/{chunk-KOO37E4Y.js.map → chunk-SVVIASVX.js.map} +0 -0
  489. /package/dist/{chunk-FBR7PIL4.js.map → chunk-VKCAHCBI.js.map} +0 -0
  490. /package/dist/{chunk-WDXD6ITO.js.map → chunk-VXVZ2GM3.js.map} +0 -0
  491. /package/dist/{chunk-DUZARALI.js.map → chunk-WTOZBZNN.js.map} +0 -0
  492. /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
  493. /package/dist/{chunk-2EPOGPKO.js.map → chunk-YKWFK7XA.js.map} +0 -0
  494. /package/dist/{chunk-BIJAWZYW.js.map → chunk-YMOPYG3K.js.map} +0 -0
  495. /package/dist/{chunk-UFR6HX7A.js.map → chunk-YRVAKONL.js.map} +0 -0
  496. /package/dist/{chunk-ECLJ4LA2.js.map → chunk-YWSQD2IB.js.map} +0 -0
  497. /package/dist/{chunk-NLEH4RTB.js.map → chunk-Z4U3UN56.js.map} +0 -0
  498. /package/dist/{chunk-YDKF4MSJ.js.map → chunk-ZAOHJDKH.js.map} +0 -0
  499. /package/dist/{chunk-KFIOPZ25.js.map → chunk-ZIJDI4CP.js.map} +0 -0
  500. /package/dist/{graph-edge-decay-FXGELBFA.js.map → eval-trajectory-contracts.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SUPPORT_PASSPORT_DRAFT_MAX_CONTENT_CHARACTERS,
3
3
  SUPPORT_PASSPORT_DRAFT_MAX_MEMORIES
4
- } from "./chunk-CV3GNPOE.js";
4
+ } from "./chunk-RQE4TITU.js";
5
5
  import {
6
6
  SUPPORT_PASSPORT_SOURCE_MEMORY_ID_MAX_LENGTH
7
7
  } from "./chunk-XDL5CYZN.js";
@@ -343,4 +343,4 @@ export {
343
343
  parseSupportPassportModelJob,
344
344
  SupportPassportModelBridge
345
345
  };
346
- //# sourceMappingURL=chunk-4JSF7UUP.js.map
346
+ //# sourceMappingURL=chunk-S3K2CIK5.js.map
@@ -0,0 +1,325 @@
1
+ import {
2
+ evaluateMemoryActionPolicy
3
+ } from "./chunk-H63EDPFJ.js";
4
+ import {
5
+ planRecallMode
6
+ } from "./chunk-CSAKJVXW.js";
7
+
8
+ // src/memory-controller.ts
9
+ import { createHash, randomUUID } from "crypto";
10
+ var NO_OP_FLOOR = 0.35;
11
+ var REVIEW_ONLY_ACTIONS = { discard: true };
12
+ function controllerConfigHash(config) {
13
+ return sha256(
14
+ JSON.stringify({
15
+ mode: config.mode,
16
+ reportVersion: config.reportVersion,
17
+ evidenceMaxAgeMs: config.evidenceMaxAgeMs,
18
+ minPairedSeeds: config.minPairedSeeds,
19
+ shadowMinRecords: config.shadowMinRecords
20
+ })
21
+ );
22
+ }
23
+ function hashControllerState(state) {
24
+ return sha256(
25
+ JSON.stringify({
26
+ prompt: state.prompt,
27
+ persistentMemoryCandidate: state.persistentMemoryCandidate ?? null,
28
+ contextMessages: state.contextMessages ?? null,
29
+ contextPressure: state.contextPressure ?? null
30
+ })
31
+ );
32
+ }
33
+ function computeEvidenceReportHash(fields) {
34
+ return sha256(JSON.stringify(fields));
35
+ }
36
+ function verifyEvidenceReport(report) {
37
+ return computeEvidenceReportHash({
38
+ status: report.status,
39
+ version: report.version,
40
+ configHash: report.configHash,
41
+ generatedAt: report.generatedAt
42
+ }) === report.reportHash;
43
+ }
44
+ function sha256(input) {
45
+ return createHash("sha256").update(input).digest("hex");
46
+ }
47
+ function clampScore(value) {
48
+ if (!Number.isFinite(value)) return Number.NaN;
49
+ return Math.max(0, Math.min(1, value));
50
+ }
51
+ function chooseAction(input) {
52
+ const { state, activeContextAdapter, runtimeValues, utilityValues } = input;
53
+ const recallMode = planRecallMode(state.prompt ?? "");
54
+ const recallScore = recallMode === "no_recall" ? 0 : recallMode === "minimal" ? 0.4 : 0.6 + 0.2 * (runtimeValues?.recencyWeight ?? 0);
55
+ let persistentScore = 0;
56
+ const candidate = state.persistentMemoryCandidate;
57
+ if (candidate) {
58
+ const policy = evaluateMemoryActionPolicy({
59
+ action: candidate.action,
60
+ eligibility: candidate.eligibility,
61
+ options: { actionsEnabled: true, maxCompressionTokensPerHour: Number.POSITIVE_INFINITY }
62
+ });
63
+ if (policy.decision === "allow") {
64
+ persistentScore = 0.4 + 0.4 * (candidate.eligibility.confidence ?? 0);
65
+ } else if (policy.decision === "defer") {
66
+ persistentScore = 0.2;
67
+ }
68
+ if (utilityValues && utilityValues.rankingSuppressMultiplier > 1) {
69
+ persistentScore *= 1 / utilityValues.rankingSuppressMultiplier;
70
+ }
71
+ }
72
+ let contextScore = 0;
73
+ let contextPlan = null;
74
+ const pressure = state.contextPressure;
75
+ if (activeContextAdapter && typeof pressure === "number" && Number.isFinite(pressure) && pressure > 0.5) {
76
+ contextPlan = activeContextAdapter.plan(state.contextMessages ?? []);
77
+ if (contextPlan && contextPlan.messageIds.length > 0) {
78
+ contextScore = 0.3 + 0.5 * Math.max(0, Math.min(1, pressure));
79
+ }
80
+ }
81
+ const scores = {
82
+ recall: clampScore(recallScore),
83
+ persistent_memory: clampScore(persistentScore),
84
+ active_context: clampScore(contextScore),
85
+ no_op: NO_OP_FLOOR
86
+ };
87
+ if (Object.values(scores).some((score) => !Number.isFinite(score) || score < 0 || score > 1)) {
88
+ return { choice: { family: "no_op" }, scores };
89
+ }
90
+ let choice = { family: "no_op" };
91
+ let best = scores.no_op;
92
+ if (scores.recall > best) {
93
+ best = scores.recall;
94
+ choice = { family: "recall", mode: recallMode };
95
+ }
96
+ if (scores.persistent_memory > best) {
97
+ best = scores.persistent_memory;
98
+ choice = {
99
+ family: "persistent_memory",
100
+ action: candidate.action,
101
+ eligibility: candidate.eligibility
102
+ };
103
+ }
104
+ if (scores.active_context > best) {
105
+ choice = { family: "active_context", plan: contextPlan };
106
+ }
107
+ return { choice, scores };
108
+ }
109
+ async function evaluateActiveGates(input) {
110
+ const { config, reportReader, recorder, consecutiveReceiptFailures, now } = input;
111
+ const reasons = [];
112
+ if (!reportReader) return ["no_report_reader"];
113
+ const evidence = await reportReader.read();
114
+ if (!evidence) return ["no_evidence"];
115
+ const { report, pairedSeed } = evidence;
116
+ if (report.status !== "pass") reasons.push("report_not_passing");
117
+ if (report.version !== config.reportVersion) reasons.push("report_version_mismatch");
118
+ if (report.configHash !== controllerConfigHash(config)) reasons.push("report_config_unbound");
119
+ if (!verifyEvidenceReport(report)) reasons.push("report_hash_invalid");
120
+ const reportGeneratedAt = Date.parse(report.generatedAt);
121
+ if (!Number.isFinite(reportGeneratedAt) || now.getTime() - reportGeneratedAt > config.evidenceMaxAgeMs) {
122
+ reasons.push("report_stale");
123
+ }
124
+ if (pairedSeed.status !== "pass") reasons.push("paired_seed_not_passing");
125
+ if (pairedSeed.seedCount < config.minPairedSeeds) reasons.push("paired_seed_count_low");
126
+ const seedGeneratedAt = Date.parse(pairedSeed.generatedAt);
127
+ if (!Number.isFinite(seedGeneratedAt) || now.getTime() - seedGeneratedAt > config.evidenceMaxAgeMs) {
128
+ reasons.push("paired_seed_stale");
129
+ }
130
+ const shadowRecords = recorder ? await recorder.countShadowRecords() : 0;
131
+ if (shadowRecords < config.shadowMinRecords) reasons.push("shadow_history_insufficient");
132
+ if (consecutiveReceiptFailures > 0) reasons.push("recent_receipt_failures");
133
+ return reasons;
134
+ }
135
+ var MemoryControllerCoordinator = class {
136
+ deps;
137
+ clock;
138
+ consecutiveReceiptFailures = 0;
139
+ constructor(deps) {
140
+ this.deps = deps;
141
+ this.clock = deps.clock ?? (() => /* @__PURE__ */ new Date());
142
+ }
143
+ async run(state) {
144
+ const decisionId = randomUUID();
145
+ const stateHash = hashControllerState(state);
146
+ const requestedMode = this.deps.config.mode;
147
+ if (requestedMode === "off") {
148
+ return {
149
+ decisionId,
150
+ requestedMode,
151
+ effectiveMode: "off",
152
+ stateHash,
153
+ choice: { family: "no_op" },
154
+ scores: { persistent_memory: 0, recall: 0, active_context: 0, no_op: 0 },
155
+ executed: false,
156
+ reviewOnly: false,
157
+ recorded: false,
158
+ demotionReasons: ["mode_off"]
159
+ };
160
+ }
161
+ const [runtimeValues, utilityValues] = await Promise.all([
162
+ this.deps.policyRuntime?.loadRuntimeValues() ?? null,
163
+ this.deps.readUtilityRuntime?.() ?? null
164
+ ]);
165
+ const { choice, scores } = chooseAction({
166
+ state,
167
+ activeContextAdapter: this.deps.activeContextAdapter,
168
+ runtimeValues,
169
+ utilityValues
170
+ });
171
+ let demotionReasons = [];
172
+ let effectiveMode = requestedMode;
173
+ if (requestedMode === "active") {
174
+ demotionReasons = await evaluateActiveGates({
175
+ config: this.deps.config,
176
+ reportReader: this.deps.reportReader,
177
+ recorder: this.deps.recorder,
178
+ consecutiveReceiptFailures: this.consecutiveReceiptFailures,
179
+ now: this.clock()
180
+ });
181
+ if (demotionReasons.length > 0) effectiveMode = "shadow";
182
+ }
183
+ const baseEvent = {
184
+ schemaVersion: 1,
185
+ phase: "choice",
186
+ decisionId,
187
+ timestamp: this.clock().toISOString(),
188
+ requestedMode,
189
+ effectiveMode,
190
+ stateHash,
191
+ choice,
192
+ scores,
193
+ executed: false,
194
+ ...demotionReasons.length > 0 ? { demotionReasons } : {}
195
+ };
196
+ let recorded = false;
197
+ if (this.deps.recorder) {
198
+ try {
199
+ await this.deps.recorder.record(baseEvent);
200
+ this.deps.telemetry?.(baseEvent);
201
+ recorded = true;
202
+ } catch {
203
+ return {
204
+ decisionId,
205
+ requestedMode,
206
+ effectiveMode,
207
+ stateHash,
208
+ choice,
209
+ scores,
210
+ executed: false,
211
+ reviewOnly: false,
212
+ recorded: false,
213
+ demotionReasons: [...demotionReasons, "record_failed"]
214
+ };
215
+ }
216
+ }
217
+ if (effectiveMode !== "active") {
218
+ return {
219
+ decisionId,
220
+ requestedMode,
221
+ effectiveMode,
222
+ stateHash,
223
+ choice,
224
+ scores,
225
+ executed: false,
226
+ reviewOnly: false,
227
+ recorded,
228
+ demotionReasons
229
+ };
230
+ }
231
+ if (choice.family === "persistent_memory" && REVIEW_ONLY_ACTIONS[choice.action]) {
232
+ const event = {
233
+ ...baseEvent,
234
+ phase: "outcome",
235
+ reviewOnly: true,
236
+ demotionReasons: ["review_only_action"]
237
+ };
238
+ await this.recordOutcome(event);
239
+ return {
240
+ decisionId,
241
+ requestedMode,
242
+ effectiveMode,
243
+ stateHash,
244
+ choice,
245
+ scores,
246
+ executed: false,
247
+ reviewOnly: true,
248
+ recorded,
249
+ demotionReasons
250
+ };
251
+ }
252
+ const receipt = await this.dispatch(choice, stateHash, decisionId, baseEvent);
253
+ return {
254
+ decisionId,
255
+ requestedMode,
256
+ effectiveMode,
257
+ stateHash,
258
+ choice,
259
+ scores,
260
+ executed: receipt?.ok === true,
261
+ reviewOnly: false,
262
+ recorded,
263
+ ...receipt ? { receipt } : {},
264
+ demotionReasons
265
+ };
266
+ }
267
+ async dispatch(choice, stateHash, decisionId, baseEvent) {
268
+ const executors = this.deps.executors ?? {};
269
+ try {
270
+ let receipt;
271
+ if (choice.family === "persistent_memory") {
272
+ if (!executors.executePersistentMemory) throw new Error("no_executor:persistent_memory");
273
+ receipt = await executors.executePersistentMemory({
274
+ decisionId,
275
+ action: choice.action,
276
+ eligibility: choice.eligibility,
277
+ stateHash
278
+ });
279
+ } else if (choice.family === "recall") {
280
+ if (!executors.executeRecall) throw new Error("no_executor:recall");
281
+ receipt = await executors.executeRecall({ decisionId, mode: choice.mode });
282
+ } else if (choice.family === "active_context") {
283
+ if (!executors.executeActiveContext) throw new Error("no_executor:active_context");
284
+ receipt = await executors.executeActiveContext({ decisionId, plan: choice.plan });
285
+ } else {
286
+ receipt = { decisionId, ok: true };
287
+ }
288
+ if (!isValidReceipt(receipt, decisionId)) {
289
+ this.consecutiveReceiptFailures += 1;
290
+ await this.recordOutcome({ ...baseEvent, phase: "outcome", failureClass: "bad_receipt" });
291
+ return void 0;
292
+ }
293
+ this.consecutiveReceiptFailures = 0;
294
+ await this.recordOutcome({ ...baseEvent, phase: "outcome", executed: receipt.ok, receipt });
295
+ return receipt;
296
+ } catch (error) {
297
+ this.consecutiveReceiptFailures += 1;
298
+ await this.recordOutcome({
299
+ ...baseEvent,
300
+ phase: "outcome",
301
+ failureClass: error?.message?.startsWith("no_executor:") ? "no_executor" : "executor_error"
302
+ });
303
+ return void 0;
304
+ }
305
+ }
306
+ async recordOutcome(event) {
307
+ if (!this.deps.recorder) return;
308
+ await this.deps.recorder.record(event);
309
+ this.deps.telemetry?.(event);
310
+ }
311
+ };
312
+ function isValidReceipt(receipt, decisionId) {
313
+ return typeof receipt === "object" && receipt !== null && receipt.decisionId === decisionId && typeof receipt.ok === "boolean";
314
+ }
315
+
316
+ export {
317
+ controllerConfigHash,
318
+ hashControllerState,
319
+ computeEvidenceReportHash,
320
+ verifyEvidenceReport,
321
+ chooseAction,
322
+ evaluateActiveGates,
323
+ MemoryControllerCoordinator
324
+ };
325
+ //# sourceMappingURL=chunk-SDEPLF7V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory-controller.ts"],"sourcesContent":["import { createHash, randomUUID } from \"node:crypto\";\nimport { planRecallMode } from \"./intent.js\";\nimport { evaluateMemoryActionPolicy } from \"./memory-action-policy.js\";\nimport type { RuntimePolicyValues } from \"./policy-runtime.js\";\nimport type { UtilityRuntimeValues } from \"./utility-runtime.js\";\nimport type { MemoryActionEligibilityContext, MemoryActionType, RecallPlanMode } from \"./types.js\";\n\n/**\n * Gated unified memory controller (#2348).\n *\n * One state enters, one choice leaves. Host-free: every effectful collaborator\n * (adapters, executors, report reader, recorder, telemetry, clock) is injected.\n * The coordinator creates no store and claims no counterfactual lift.\n */\n\nexport type MemoryControllerMode = \"off\" | \"shadow\" | \"active\";\n\nexport type MemoryControllerActionFamily = \"persistent_memory\" | \"recall\" | \"active_context\" | \"no_op\";\n\n/** #2347 adapter seam: the host supplies plans, core only picks one. */\nexport interface ActiveContextMessage {\n id: string;\n text: string;\n}\n\nexport interface ActiveContextPlan {\n transform: \"SUMMARY\" | \"FILTER\";\n messageIds: string[];\n planId: string;\n}\n\nexport interface ActiveContextAdapter {\n plan(messages: ActiveContextMessage[]): ActiveContextPlan | null;\n}\n\n/** #2345 report + #2346 paired-seed evidence, read through one port. */\nexport interface MemoryControllerEvidenceReport {\n status: \"pass\" | \"fail\";\n version: string;\n configHash: string;\n generatedAt: string;\n /** sha256 over the canonical report fields; recomputed on verification. */\n reportHash: string;\n}\n\nexport interface MemoryControllerPairedSeedEvidence {\n status: \"pass\" | \"fail\";\n seedCount: number;\n generatedAt: string;\n}\n\nexport interface MemoryControllerEvidence {\n report: MemoryControllerEvidenceReport;\n pairedSeed: MemoryControllerPairedSeedEvidence;\n}\n\nexport interface MemoryControllerReportReader {\n read(): Promise<MemoryControllerEvidence | null>;\n}\n\nexport interface MemoryControllerReceipt {\n decisionId: string;\n ok: boolean;\n detail?: string;\n}\n\nexport interface MemoryControllerExecutors {\n executePersistentMemory?(input: {\n decisionId: string;\n action: MemoryActionType;\n eligibility: MemoryActionEligibilityContext;\n stateHash: string;\n }): Promise<MemoryControllerReceipt>;\n executeRecall?(input: { decisionId: string; mode: RecallPlanMode }): Promise<MemoryControllerReceipt>;\n executeActiveContext?(input: {\n decisionId: string;\n plan: ActiveContextPlan;\n }): Promise<MemoryControllerReceipt>;\n}\n\nexport interface MemoryControllerEvent {\n schemaVersion: 1;\n phase: \"choice\" | \"outcome\";\n decisionId: string;\n timestamp: string;\n requestedMode: MemoryControllerMode;\n effectiveMode: MemoryControllerMode;\n stateHash: string;\n choice: MemoryControllerChoice;\n scores: Record<MemoryControllerActionFamily, number>;\n executed: boolean;\n reviewOnly?: boolean;\n demotionReasons?: string[];\n failureClass?: \"record_failed\" | \"executor_error\" | \"bad_receipt\" | \"no_executor\";\n receipt?: MemoryControllerReceipt;\n}\n\nexport interface MemoryControllerRecorder {\n record(event: MemoryControllerEvent): Promise<void>;\n /** Prior shadow choice records; active promotion requires shadow history. */\n countShadowRecords(): Promise<number>;\n}\n\nexport interface MemoryControllerConfig {\n mode: MemoryControllerMode;\n /** Expected #2345 report schema version. */\n reportVersion: string;\n /** Evidence older than this is stale and forces shadow. */\n evidenceMaxAgeMs: number;\n /** Paired-seed arms must cover at least this many seeds (#2346). */\n minPairedSeeds: number;\n /** Active promotion requires at least this many prior shadow records. */\n shadowMinRecords: number;\n}\n\nexport interface MemoryControllerState {\n prompt: string;\n persistentMemoryCandidate?: {\n action: MemoryActionType;\n eligibility: MemoryActionEligibilityContext;\n };\n contextMessages?: ActiveContextMessage[];\n /** 0..1 host-measured context pressure. */\n contextPressure?: number;\n}\n\nexport type MemoryControllerChoice =\n | { family: \"persistent_memory\"; action: MemoryActionType; eligibility: MemoryActionEligibilityContext }\n | { family: \"recall\"; mode: RecallPlanMode }\n | { family: \"active_context\"; plan: ActiveContextPlan }\n | { family: \"no_op\" };\n\nexport interface MemoryControllerRunResult {\n decisionId: string;\n requestedMode: MemoryControllerMode;\n effectiveMode: MemoryControllerMode;\n stateHash: string;\n choice: MemoryControllerChoice;\n scores: Record<MemoryControllerActionFamily, number>;\n executed: boolean;\n reviewOnly: boolean;\n recorded: boolean;\n receipt?: MemoryControllerReceipt;\n demotionReasons: string[];\n}\n\nexport interface MemoryControllerDeps {\n config: MemoryControllerConfig;\n reportReader?: MemoryControllerReportReader;\n recorder?: MemoryControllerRecorder;\n executors?: MemoryControllerExecutors;\n activeContextAdapter?: ActiveContextAdapter;\n policyRuntime?: { loadRuntimeValues(): Promise<RuntimePolicyValues | null> };\n readUtilityRuntime?: () => Promise<UtilityRuntimeValues | null>;\n telemetry?: (event: MemoryControllerEvent) => void;\n clock?: () => Date;\n}\n\nconst NO_OP_FLOOR = 0.35;\n/** `discard` (and any destructive change) stays review-only in active mode. */\nconst REVIEW_ONLY_ACTIONS: Partial<Record<MemoryActionType, true>> = { discard: true };\n\nexport function controllerConfigHash(config: MemoryControllerConfig): string {\n return sha256(\n JSON.stringify({\n mode: config.mode,\n reportVersion: config.reportVersion,\n evidenceMaxAgeMs: config.evidenceMaxAgeMs,\n minPairedSeeds: config.minPairedSeeds,\n shadowMinRecords: config.shadowMinRecords,\n })\n );\n}\n\nexport function hashControllerState(state: MemoryControllerState): string {\n return sha256(\n JSON.stringify({\n prompt: state.prompt,\n persistentMemoryCandidate: state.persistentMemoryCandidate ?? null,\n contextMessages: state.contextMessages ?? null,\n contextPressure: state.contextPressure ?? null,\n })\n );\n}\n\n/** Canonical #2345 report hash; producers sign with this, the controller verifies. */\nexport function computeEvidenceReportHash(fields: {\n status: MemoryControllerEvidenceReport[\"status\"];\n version: string;\n configHash: string;\n generatedAt: string;\n}): string {\n return sha256(JSON.stringify(fields));\n}\n\n/** Verifies the #2345 report hash over its canonical fields. */\nexport function verifyEvidenceReport(report: MemoryControllerEvidenceReport): boolean {\n return (\n computeEvidenceReportHash({\n status: report.status,\n version: report.version,\n configHash: report.configHash,\n generatedAt: report.generatedAt,\n }) === report.reportHash\n );\n}\n\nfunction sha256(input: string): string {\n return createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nfunction clampScore(value: number): number {\n if (!Number.isFinite(value)) return Number.NaN;\n return Math.max(0, Math.min(1, value));\n}\n\n/**\n * Bad scores fail closed to `no_op`.\n */\nexport function chooseAction(input: {\n state: MemoryControllerState;\n activeContextAdapter?: ActiveContextAdapter;\n runtimeValues?: RuntimePolicyValues | null;\n utilityValues?: UtilityRuntimeValues | null;\n}): { choice: MemoryControllerChoice; scores: Record<MemoryControllerActionFamily, number> } {\n const { state, activeContextAdapter, runtimeValues, utilityValues } = input;\n\n // recall: current recall path.\n const recallMode = planRecallMode(state.prompt ?? \"\");\n const recallScore =\n recallMode === \"no_recall\" ? 0 : recallMode === \"minimal\" ? 0.4 : 0.6 + 0.2 * (runtimeValues?.recencyWeight ?? 0);\n\n // persistent_memory: current action path + policy.\n let persistentScore = 0;\n const candidate = state.persistentMemoryCandidate;\n if (candidate) {\n const policy = evaluateMemoryActionPolicy({\n action: candidate.action,\n eligibility: candidate.eligibility,\n options: { actionsEnabled: true, maxCompressionTokensPerHour: Number.POSITIVE_INFINITY },\n });\n if (policy.decision === \"allow\") {\n persistentScore = 0.4 + 0.4 * (candidate.eligibility.confidence ?? 0);\n } else if (policy.decision === \"defer\") {\n persistentScore = 0.2;\n }\n // Utility runtime may suppress the persistent family.\n if (utilityValues && utilityValues.rankingSuppressMultiplier > 1) {\n persistentScore *= 1 / utilityValues.rankingSuppressMultiplier;\n }\n }\n\n // active_context: current context path through the #2347 adapter.\n let contextScore = 0;\n let contextPlan: ActiveContextPlan | null = null;\n const pressure = state.contextPressure;\n if (activeContextAdapter && typeof pressure === \"number\" && Number.isFinite(pressure) && pressure > 0.5) {\n contextPlan = activeContextAdapter.plan(state.contextMessages ?? []);\n if (contextPlan && contextPlan.messageIds.length > 0) {\n contextScore = 0.3 + 0.5 * Math.max(0, Math.min(1, pressure));\n }\n }\n\n const scores: Record<MemoryControllerActionFamily, number> = {\n recall: clampScore(recallScore),\n persistent_memory: clampScore(persistentScore),\n active_context: clampScore(contextScore),\n no_op: NO_OP_FLOOR,\n };\n\n // Bad scores fail closed.\n if (Object.values(scores).some((score) => !Number.isFinite(score) || score < 0 || score > 1)) {\n return { choice: { family: \"no_op\" }, scores };\n }\n\n let choice: MemoryControllerChoice = { family: \"no_op\" };\n let best = scores.no_op;\n if (scores.recall > best) {\n best = scores.recall;\n choice = { family: \"recall\", mode: recallMode };\n }\n if (scores.persistent_memory > best) {\n best = scores.persistent_memory;\n choice = {\n family: \"persistent_memory\",\n action: candidate!.action,\n eligibility: candidate!.eligibility,\n };\n }\n if (scores.active_context > best) {\n choice = { family: \"active_context\", plan: contextPlan! };\n }\n return { choice, scores };\n}\n\n/** Returns the demotion reasons when active-mode gates fail; empty means go. */\nexport async function evaluateActiveGates(input: {\n config: MemoryControllerConfig;\n reportReader?: MemoryControllerReportReader;\n recorder?: MemoryControllerRecorder;\n consecutiveReceiptFailures: number;\n now: Date;\n}): Promise<string[]> {\n const { config, reportReader, recorder, consecutiveReceiptFailures, now } = input;\n const reasons: string[] = [];\n\n if (!reportReader) return [\"no_report_reader\"];\n\n const evidence = await reportReader.read();\n if (!evidence) return [\"no_evidence\"];\n\n const { report, pairedSeed } = evidence;\n if (report.status !== \"pass\") reasons.push(\"report_not_passing\");\n if (report.version !== config.reportVersion) reasons.push(\"report_version_mismatch\");\n if (report.configHash !== controllerConfigHash(config)) reasons.push(\"report_config_unbound\");\n if (!verifyEvidenceReport(report)) reasons.push(\"report_hash_invalid\");\n const reportGeneratedAt = Date.parse(report.generatedAt);\n if (!Number.isFinite(reportGeneratedAt) || now.getTime() - reportGeneratedAt > config.evidenceMaxAgeMs) {\n reasons.push(\"report_stale\");\n }\n\n if (pairedSeed.status !== \"pass\") reasons.push(\"paired_seed_not_passing\");\n if (pairedSeed.seedCount < config.minPairedSeeds) reasons.push(\"paired_seed_count_low\");\n const seedGeneratedAt = Date.parse(pairedSeed.generatedAt);\n if (!Number.isFinite(seedGeneratedAt) || now.getTime() - seedGeneratedAt > config.evidenceMaxAgeMs) {\n reasons.push(\"paired_seed_stale\");\n }\n\n const shadowRecords = recorder ? await recorder.countShadowRecords() : 0;\n if (shadowRecords < config.shadowMinRecords) reasons.push(\"shadow_history_insufficient\");\n\n if (consecutiveReceiptFailures > 0) reasons.push(\"recent_receipt_failures\");\n\n return reasons;\n}\n\nexport class MemoryControllerCoordinator {\n private readonly deps: MemoryControllerDeps;\n private readonly clock: () => Date;\n private consecutiveReceiptFailures = 0;\n\n constructor(deps: MemoryControllerDeps) {\n this.deps = deps;\n this.clock = deps.clock ?? (() => new Date());\n }\n\n async run(state: MemoryControllerState): Promise<MemoryControllerRunResult> {\n const decisionId = randomUUID();\n const stateHash = hashControllerState(state);\n const requestedMode = this.deps.config.mode;\n\n // off: no choice, no read, no write, no call.\n if (requestedMode === \"off\") {\n return {\n decisionId,\n requestedMode,\n effectiveMode: \"off\",\n stateHash,\n choice: { family: \"no_op\" },\n scores: { persistent_memory: 0, recall: 0, active_context: 0, no_op: 0 },\n executed: false,\n reviewOnly: false,\n recorded: false,\n demotionReasons: [\"mode_off\"],\n };\n }\n\n const [runtimeValues, utilityValues] = await Promise.all([\n this.deps.policyRuntime?.loadRuntimeValues() ?? null,\n this.deps.readUtilityRuntime?.() ?? null,\n ]);\n const { choice, scores } = chooseAction({\n state,\n activeContextAdapter: this.deps.activeContextAdapter,\n runtimeValues,\n utilityValues,\n });\n\n let demotionReasons: string[] = [];\n let effectiveMode = requestedMode;\n if (requestedMode === \"active\") {\n demotionReasons = await evaluateActiveGates({\n config: this.deps.config,\n reportReader: this.deps.reportReader,\n recorder: this.deps.recorder,\n consecutiveReceiptFailures: this.consecutiveReceiptFailures,\n now: this.clock(),\n });\n if (demotionReasons.length > 0) effectiveMode = \"shadow\";\n }\n\n const baseEvent: MemoryControllerEvent = {\n schemaVersion: 1,\n phase: \"choice\",\n decisionId,\n timestamp: this.clock().toISOString(),\n requestedMode,\n effectiveMode,\n stateHash,\n choice,\n scores,\n executed: false,\n ...(demotionReasons.length > 0 ? { demotionReasons } : {}),\n };\n\n // Shadow records before any active dispatch.\n let recorded = false;\n if (this.deps.recorder) {\n try {\n await this.deps.recorder.record(baseEvent);\n this.deps.telemetry?.(baseEvent);\n recorded = true;\n } catch {\n // Bad recorder stops work: no dispatch, no outcome event.\n return {\n decisionId,\n requestedMode,\n effectiveMode,\n stateHash,\n choice,\n scores,\n executed: false,\n reviewOnly: false,\n recorded: false,\n demotionReasons: [...demotionReasons, \"record_failed\"],\n };\n }\n }\n\n if (effectiveMode !== \"active\") {\n return {\n decisionId,\n requestedMode,\n effectiveMode,\n stateHash,\n choice,\n scores,\n executed: false,\n reviewOnly: false,\n recorded,\n demotionReasons,\n };\n }\n\n // First active scope: reversible actions only.\n if (choice.family === \"persistent_memory\" && REVIEW_ONLY_ACTIONS[choice.action]) {\n const event: MemoryControllerEvent = {\n ...baseEvent,\n phase: \"outcome\",\n reviewOnly: true,\n demotionReasons: [\"review_only_action\"],\n };\n await this.recordOutcome(event);\n return {\n decisionId,\n requestedMode,\n effectiveMode,\n stateHash,\n choice,\n scores,\n executed: false,\n reviewOnly: true,\n recorded,\n demotionReasons,\n };\n }\n\n const receipt = await this.dispatch(choice, stateHash, decisionId, baseEvent);\n return {\n decisionId,\n requestedMode,\n effectiveMode,\n stateHash,\n choice,\n scores,\n executed: receipt?.ok === true,\n reviewOnly: false,\n recorded,\n ...(receipt ? { receipt } : {}),\n demotionReasons,\n };\n }\n\n private async dispatch(\n choice: MemoryControllerChoice,\n stateHash: string,\n decisionId: string,\n baseEvent: MemoryControllerEvent\n ): Promise<MemoryControllerReceipt | undefined> {\n const executors = this.deps.executors ?? {};\n try {\n let receipt: MemoryControllerReceipt | undefined;\n if (choice.family === \"persistent_memory\") {\n if (!executors.executePersistentMemory) throw new Error(\"no_executor:persistent_memory\");\n receipt = await executors.executePersistentMemory({\n decisionId,\n action: choice.action,\n eligibility: choice.eligibility,\n stateHash,\n });\n } else if (choice.family === \"recall\") {\n if (!executors.executeRecall) throw new Error(\"no_executor:recall\");\n receipt = await executors.executeRecall({ decisionId, mode: choice.mode });\n } else if (choice.family === \"active_context\") {\n if (!executors.executeActiveContext) throw new Error(\"no_executor:active_context\");\n receipt = await executors.executeActiveContext({ decisionId, plan: choice.plan });\n } else {\n // no_op executed trivially; no executor call.\n receipt = { decisionId, ok: true };\n }\n if (!isValidReceipt(receipt, decisionId)) {\n this.consecutiveReceiptFailures += 1;\n await this.recordOutcome({ ...baseEvent, phase: \"outcome\", failureClass: \"bad_receipt\" });\n return undefined;\n }\n this.consecutiveReceiptFailures = 0;\n await this.recordOutcome({ ...baseEvent, phase: \"outcome\", executed: receipt.ok, receipt });\n return receipt;\n } catch (error) {\n this.consecutiveReceiptFailures += 1;\n await this.recordOutcome({\n ...baseEvent,\n phase: \"outcome\",\n failureClass: (error as Error)?.message?.startsWith(\"no_executor:\") ? \"no_executor\" : \"executor_error\",\n });\n return undefined;\n }\n }\n\n private async recordOutcome(event: MemoryControllerEvent): Promise<void> {\n if (!this.deps.recorder) return;\n await this.deps.recorder.record(event);\n this.deps.telemetry?.(event);\n }\n}\n\nfunction isValidReceipt(receipt: unknown, decisionId: string): boolean {\n return (\n typeof receipt === \"object\" &&\n receipt !== null &&\n (receipt as MemoryControllerReceipt).decisionId === decisionId &&\n typeof (receipt as MemoryControllerReceipt).ok === \"boolean\"\n );\n}\n\n// ponytail: consecutiveReceiptFailures is per-instance, not persisted; persist\n// with the recorder if coordinator restarts must carry receipt health forward.\n"],"mappings":"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","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StorageManager
3
- } from "./chunk-THVI4Y7X.js";
3
+ } from "./chunk-BJTHRFFC.js";
4
4
  import {
5
5
  getCachedRuleMemories,
6
6
  setCachedRuleMemories
@@ -119,4 +119,4 @@ export {
119
119
  compareVerifiedSemanticRuleResults,
120
120
  searchVerifiedSemanticRules
121
121
  };
122
- //# sourceMappingURL=chunk-OCCHUEZB.js.map
122
+ //# sourceMappingURL=chunk-SEA6M7SS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  StorageManager
3
- } from "./chunk-THVI4Y7X.js";
3
+ } from "./chunk-BJTHRFFC.js";
4
4
  import {
5
5
  bumpMemoryCorpusVersionForDir
6
6
  } from "./chunk-XCB6QDL6.js";
@@ -765,4 +765,4 @@ export {
765
765
  listMemoryGovernanceRuns,
766
766
  readMemoryGovernanceRunArtifact
767
767
  };
768
- //# sourceMappingURL=chunk-KOO37E4Y.js.map
768
+ //# sourceMappingURL=chunk-SVVIASVX.js.map
@@ -16,7 +16,10 @@ function runSerialized(key, task) {
16
16
  });
17
17
  return next;
18
18
  }
19
- var MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES = /* @__PURE__ */ new Set(["fact", "procedure"]);
19
+ var MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES = /* @__PURE__ */ new Set([
20
+ "fact",
21
+ "procedure"
22
+ ]);
20
23
  function memoryWorthOutcomeEligibleCategories() {
21
24
  return new Set(MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES);
22
25
  }
@@ -82,9 +85,37 @@ async function recordMemoryOutcome(storage, input) {
82
85
  };
83
86
  });
84
87
  }
88
+ var OBSERVATION_ISO_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
89
+ function toMemoryOutcomeObservation(raw) {
90
+ if (typeof raw.memoryId !== "string" || raw.memoryId.length === 0 || typeof raw.namespace !== "string" || raw.namespace.length === 0 || raw.outcome !== "success" && raw.outcome !== "failure") {
91
+ throw new Error("toMemoryOutcomeObservation requires memoryId, namespace, and outcome");
92
+ }
93
+ const observedAt = typeof raw.observedAt === "string" && OBSERVATION_ISO_RE.test(raw.observedAt) ? raw.observedAt : raw.observedAt instanceof Date ? raw.observedAt.toISOString() : null;
94
+ if (observedAt === null) {
95
+ return { status: "missing_observation", memoryId: raw.memoryId, reason: "missing_observed_at" };
96
+ }
97
+ const joinId = typeof raw.joinId === "string" && raw.joinId.length > 0 ? raw.joinId : void 0;
98
+ const sessionKey = typeof raw.sessionKey === "string" && raw.sessionKey.length > 0 ? raw.sessionKey : void 0;
99
+ if (joinId === void 0 && sessionKey === void 0) {
100
+ return { status: "missing_observation", memoryId: raw.memoryId, reason: "missing_join_data" };
101
+ }
102
+ return {
103
+ status: "observed",
104
+ observation: {
105
+ schemaVersion: 1,
106
+ memoryId: raw.memoryId,
107
+ namespace: raw.namespace,
108
+ outcome: raw.outcome,
109
+ observedAt,
110
+ joinId,
111
+ sessionKey
112
+ }
113
+ };
114
+ }
85
115
 
86
116
  export {
87
117
  memoryWorthOutcomeEligibleCategories,
88
- recordMemoryOutcome
118
+ recordMemoryOutcome,
119
+ toMemoryOutcomeObservation
89
120
  };
90
- //# sourceMappingURL=chunk-4K7IW3F7.js.map
121
+ //# sourceMappingURL=chunk-UD7UNYRD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/memory-worth-outcomes.ts"],"sourcesContent":["/**\n * Issue #560 PR 3 — Memory Worth outcome signal pipeline.\n *\n * PR 1 added `mw_success` / `mw_fail` fields to MemoryFrontmatter. PR 2 added\n * a pure scoring helper. This module adds the one piece tying the two\n * together: a way for callers to record a single outcome observation against\n * a memory, which increments the appropriate counter in frontmatter.\n *\n * The public entry point is `recordMemoryOutcome({ memoryPath, outcome, ... })`.\n * Callers pass the full path to the memory file (not just the ID) because in\n * the usual outcome source — the observation ledger — the memory path is\n * already captured in the event payload, and path-based lookup avoids a\n * full-corpus scan.\n *\n * Intentional properties:\n * - Works on a per-memory basis (no bulk API in this slice). Bulk update is\n * an easy layer on top of this once a second caller needs it.\n * - Reuses the existing `updateMemoryFrontmatter(id, patch)` write path so\n * unrelated fields (confidence, importance, lifecycle hooks, etc.) are\n * preserved. The PR 1 serializer rejects negative / non-integer counters,\n * so we rely on that for defensive validation rather than duplicating it.\n * - Only instruments categories in `MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES`\n * (currently `fact` and `procedure` — procedures joined in issue #2370 —\n * matching `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in operator-toolkit.ts for\n * the doctor audit). Non-eligible memories return\n * `{ ok: false, reason: \"ineligible_category\" }` rather than throwing so\n * the caller — typically a ledger consumer draining heterogeneous events\n * — doesn't need to pre-filter by category.\n * - Missing / unknown memory IDs return `{ ok: false, reason: \"not_found\" }`\n * rather than throwing, because outcome events may reference memories\n * that were archived/deleted between the session and the ledger drain.\n * That isn't an operator-actionable error.\n * - On success, returns the new counter values so observability surfaces\n * can report the increment without a second read.\n *\n * Out of scope (later PRs):\n * - Recall filter reading the counters (PR 4).\n * - Benchmark + default flip (PR 5).\n * - Automatic increments from extraction or summarization. Only the\n * explicit `MEM_OUTCOME` ledger tag or an MCP tool call drives writes.\n */\n\nimport path from \"node:path\";\n\nimport type { StorageManager } from \"./storage.js\";\nimport type { MemoryFrontmatter } from \"./types.js\";\n\n/**\n * Per-memory-ID serialization of the read-modify-write increment.\n *\n * Codex P1: without this, concurrent calls for the same memory race. Both\n * callers read the same `mw_*` values, each writes +1, and one increment\n * is lost — silently undercounting outcomes. We chain an async promise\n * per memory ID so read-then-write is atomic with respect to other calls\n * into this module.\n *\n * This serializes only THIS module. Direct writers (e.g. hand-rolled\n * frontmatter patches) still bypass the lock, but the documented surface\n * for Memory Worth increments is this function, and the bench only uses\n * this path.\n *\n * The lock map is WeakRef-free by design: the chain self-cleans once the\n * last pending write resolves (we delete the entry inside the `.finally`\n * of the tail), so memory use stays bounded even for long-running\n * processes that touch many different memory IDs.\n */\nconst outcomeLocks = new Map<string, Promise<unknown>>();\n\nfunction runSerialized<T>(key: string, task: () => Promise<T>): Promise<T> {\n const prev = outcomeLocks.get(key) ?? Promise.resolve();\n // Swallow upstream errors so a failed outcome for memory A doesn't\n // permanently poison the chain for memory A. We still propagate our own\n // result/errors to the caller.\n const next = prev.catch(() => undefined).then(task);\n outcomeLocks.set(key, next);\n // Chain the cleanup off `next` BUT attach a `.catch` so the cleanup\n // promise itself never surfaces as an unhandled rejection. The caller\n // gets `next` back and handles it their own way; this detached cleanup\n // chain has no observer, so without the .catch Node would crash the\n // process on a task rejection even when the caller awaited `next` and\n // handled the error correctly.\n next\n .then(\n () => {\n if (outcomeLocks.get(key) === next) outcomeLocks.delete(key);\n },\n () => {\n if (outcomeLocks.get(key) === next) outcomeLocks.delete(key);\n }\n )\n .catch(() => {\n // Defensive no-op in case a hook inside the cleanup branches throws.\n });\n return next;\n}\n\n/**\n * Categories currently instrumented for Memory Worth counters. `procedure`\n * joined in issue #2370 — the procedure library-health maintenance loop\n * retires on failure-dominant `mw_*` counters, so injected procedures must\n * be able to accrue outcomes. Must be kept in sync with\n * `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in `operator-toolkit.ts`. Declared\n * here (not imported) to avoid a circular dep with operator-toolkit, which\n * imports from this file's peers. The two constants are validated by a\n * test to stay in lockstep.\n */\nconst MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES: ReadonlySet<MemoryFrontmatter[\"category\"]> = new Set([\n \"fact\",\n \"procedure\",\n]);\n\n/**\n * Exported so downstream tests / operators can query the allowlist without\n * re-declaring it. Returned as a frozen copy so consumers cannot mutate the\n * module-internal set.\n */\nexport function memoryWorthOutcomeEligibleCategories(): ReadonlySet<MemoryFrontmatter[\"category\"]> {\n return new Set(MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES);\n}\n\n/**\n * The direction of an outcome — whether the session that consumed this\n * memory succeeded or failed. Restricted to a string literal union so\n * callers in TypeScript land can't pass arbitrary tags.\n */\nexport type MemoryOutcomeKind = \"success\" | \"failure\";\n\n/**\n * Arguments to `recordMemoryOutcome`.\n *\n * `memoryPath` is the filesystem path to the memory; we derive the ID from\n * the basename, matching how the operator-toolkit and recall layers map\n * paths to IDs.\n */\nexport interface RecordMemoryOutcomeInput {\n /**\n * Absolute or repo-relative path to the memory file. Typically the value\n * of `MemoryFile.path` for a memory returned by `readAllMemories`.\n */\n memoryPath: string;\n /** Outcome direction — \"success\" bumps mw_success; \"failure\" bumps mw_fail. */\n outcome: MemoryOutcomeKind;\n /**\n * Optional observation timestamp for audit / telemetry. This PR doesn't\n * persist the timestamp (PR 4/5 will use `lastAccessed`, which already\n * covers the recency-decay requirement), but accepting it here keeps the\n * call shape stable so future ledger integrations don't need a breaking\n * change.\n */\n timestamp?: Date | string;\n}\n\n/**\n * Outcome of a `recordMemoryOutcome` call.\n *\n * `ok: true` means the counter was incremented and flushed. The returned\n * values reflect the post-increment state, so callers can log\n * `\"fact-xyz: 4/1 → 5/1\"` without re-reading.\n *\n * `ok: false` carries a short machine-readable `reason` so a ledger drainer\n * can aggregate metrics (\"how many events hit not_found this hour?\"). The\n * human-readable `message` is a friendlier version for logs.\n */\nexport type RecordMemoryOutcomeResult =\n | {\n ok: true;\n memoryId: string;\n /** New value of `mw_success` after the increment. */\n mw_success: number;\n /** New value of `mw_fail` after the increment. */\n mw_fail: number;\n }\n | {\n ok: false;\n reason: \"not_found\" | \"ineligible_category\" | \"invalid_outcome\" | \"invalid_path\";\n message: string;\n };\n\n/**\n * Extract the memory ID from a file path. Memory files are stored as\n * `<id>.md`, matching the rest of the system (see `getMemoryById`, which\n * infers paths from IDs).\n *\n * Returns `null` for any path that does not end in `.md`. The check is\n * unconditional — `path.basename` strips directory components before the\n * suffix check, so previous conditional logic silently accepted\n * directory-prefixed paths like `/tmp/facts/2026-01-01/not-a-memory`\n * (the basename `not-a-memory` is not equal to the input, so the `.md`\n * guard was skipped). The new check looks at the raw input once.\n */\nfunction memoryIdFromPath(memoryPath: string): string | null {\n if (!memoryPath || typeof memoryPath !== \"string\") return null;\n if (!memoryPath.endsWith(\".md\")) return null;\n const basename = path.basename(memoryPath, \".md\");\n if (!basename) return null;\n return basename;\n}\n\n/**\n * Record a single outcome observation against a memory. Increments\n * `mw_success` or `mw_fail` on the memory's frontmatter (preserving all\n * other fields) via the existing `updateMemoryFrontmatter` write path.\n *\n * See the top-of-file doc comment for policy details (eligible categories,\n * error semantics, and what is intentionally out of scope).\n */\nexport async function recordMemoryOutcome(\n storage: StorageManager,\n input: RecordMemoryOutcomeInput\n): Promise<RecordMemoryOutcomeResult> {\n if (input.outcome !== \"success\" && input.outcome !== \"failure\") {\n return {\n ok: false,\n reason: \"invalid_outcome\",\n message: `outcome must be \"success\" or \"failure\"; got ${JSON.stringify(input.outcome)}`,\n };\n }\n\n const memoryId = memoryIdFromPath(input.memoryPath);\n if (memoryId === null) {\n return {\n ok: false,\n reason: \"invalid_path\",\n message: `memoryPath must end in .md; got ${JSON.stringify(input.memoryPath)}`,\n };\n }\n\n // Serialize the read-modify-write per memory ID so concurrent callers\n // (parallel ledger drain, multiple MCP clients, etc.) can't each read\n // the same snapshot and race to write `+1`, losing an increment.\n return runSerialized(memoryId, async () => {\n const memory = await storage.getMemoryById(memoryId);\n if (!memory) {\n return {\n ok: false,\n reason: \"not_found\",\n message: `no memory with id ${memoryId}`,\n };\n }\n\n if (!MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES.has(memory.frontmatter.category)) {\n return {\n ok: false,\n reason: \"ineligible_category\",\n message: `category ${memory.frontmatter.category} is not instrumented for Memory Worth`,\n };\n }\n\n // Absent counters are treated as 0 (matching the PR 1 semantics — legacy\n // memories implicitly have Beta(1,1) priors). Increments land on the\n // actual counter regardless of whether the field was previously set.\n const currentSuccess = memory.frontmatter.mw_success ?? 0;\n const currentFail = memory.frontmatter.mw_fail ?? 0;\n\n const nextSuccess = input.outcome === \"success\" ? currentSuccess + 1 : currentSuccess;\n const nextFail = input.outcome === \"failure\" ? currentFail + 1 : currentFail;\n\n // `updateMemoryFrontmatter` goes through `writeMemoryFrontmatter`, which\n // routes through the PR 1 serializer — so a stored corrupt value (e.g., a\n // pre-existing float) would be rejected here. That is intentional: we\n // refuse to layer a fresh increment on top of garbage. Operators should\n // use `remnic doctor` to find and fix those rows before PR 4 ships.\n //\n // `updateMemoryFrontmatter` returns `false` when the memory is no\n // longer present (archived / deleted between `getMemoryById` and the\n // write). Surface that as `not_found` so callers see an honest result\n // — silently returning `ok: true` with a counter that never landed\n // would skew downstream worth scoring.\n const updated = await storage.updateMemoryFrontmatter(memoryId, {\n mw_success: nextSuccess,\n mw_fail: nextFail,\n });\n if (!updated) {\n return {\n ok: false,\n reason: \"not_found\",\n message: `memory ${memoryId} disappeared between read and write`,\n };\n }\n\n return {\n ok: true,\n memoryId,\n mw_success: nextSuccess,\n mw_fail: nextFail,\n };\n });\n}\n\n// ---------------------------------------------------------------------------\n// Issue #2345 — pure outcome-observation view (no writes, no counter changes)\n// ---------------------------------------------------------------------------\n\n/**\n * A Memory Worth outcome that carries WHEN it was observed and WHAT it can\n * join to — the facts the trajectory evaluator needs and plain counter rows\n * lack. `mw_success` / `mw_fail` totals have no timestamp or join ID, so they\n * cannot participate in delayed action-to-outcome joins.\n */\nexport interface MemoryOutcomeObservation {\n schemaVersion: 1;\n memoryId: string;\n namespace: string;\n outcome: MemoryOutcomeKind;\n observedAt: string;\n /** Stable join key shared with the action side (never free text). */\n joinId?: string;\n sessionKey?: string;\n}\n\n/**\n * Discriminated view over outcome facts a caller can supply.\n *\n * - `missing_observation` — counter-only or incomplete rows. The evaluator\n * must never guess the action behind an aggregate counter, so these stay\n * visible as missing rather than being inferred.\n */\nexport type MemoryOutcomeObservationView =\n | { status: \"observed\"; observation: MemoryOutcomeObservation }\n | { status: \"missing_observation\"; memoryId: string; reason: \"missing_observed_at\" | \"missing_join_data\" };\n\nconst OBSERVATION_ISO_RE = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n\n/**\n * Build the pure observation view. Accepts exactly what a caller already\n * knows; performs no storage reads and no writes, and does not alter the\n * counter path — `recordMemoryOutcome` keeps its current behavior.\n */\nexport function toMemoryOutcomeObservation(raw: {\n memoryId: string;\n namespace: string;\n outcome: MemoryOutcomeKind;\n observedAt?: unknown;\n joinId?: unknown;\n sessionKey?: unknown;\n}): MemoryOutcomeObservationView {\n if (\n typeof raw.memoryId !== \"string\" ||\n raw.memoryId.length === 0 ||\n typeof raw.namespace !== \"string\" ||\n raw.namespace.length === 0 ||\n (raw.outcome !== \"success\" && raw.outcome !== \"failure\")\n ) {\n throw new Error(\"toMemoryOutcomeObservation requires memoryId, namespace, and outcome\");\n }\n const observedAt =\n typeof raw.observedAt === \"string\" && OBSERVATION_ISO_RE.test(raw.observedAt)\n ? raw.observedAt\n : raw.observedAt instanceof Date\n ? raw.observedAt.toISOString()\n : null;\n if (observedAt === null) {\n return { status: \"missing_observation\", memoryId: raw.memoryId, reason: \"missing_observed_at\" };\n }\n const joinId = typeof raw.joinId === \"string\" && raw.joinId.length > 0 ? raw.joinId : undefined;\n const sessionKey = typeof raw.sessionKey === \"string\" && raw.sessionKey.length > 0 ? raw.sessionKey : undefined;\n if (joinId === undefined && sessionKey === undefined) {\n return { status: \"missing_observation\", memoryId: raw.memoryId, reason: \"missing_join_data\" };\n }\n return {\n status: \"observed\",\n observation: {\n schemaVersion: 1,\n memoryId: raw.memoryId,\n namespace: raw.namespace,\n outcome: raw.outcome,\n observedAt,\n joinId,\n sessionKey,\n },\n };\n}\n"],"mappings":"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","names":[]}