@remnic/core 9.7.15 → 9.8.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 (929) hide show
  1. package/dist/access-admin-ops-surface.d.ts +13 -6
  2. package/dist/access-admin-ops-surface.js +85 -71
  3. package/dist/access-audit.js +2 -2
  4. package/dist/access-boundary.d.ts +35 -17
  5. package/dist/access-boundary.js +86 -74
  6. package/dist/access-citation.d.ts +28 -0
  7. package/dist/access-citation.js +9 -0
  8. package/dist/access-cli.js +194 -178
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-errors.d.ts +16 -1
  11. package/dist/access-errors.js +7 -3
  12. package/dist/access-http.d.ts +25 -19
  13. package/dist/access-http.js +100 -87
  14. package/dist/access-identity-continuity-surface.d.ts +13 -8
  15. package/dist/access-identity-continuity-surface.js +85 -71
  16. package/dist/access-lcm-surface.d.ts +16 -9
  17. package/dist/access-lcm-surface.js +85 -71
  18. package/dist/access-mcp.d.ts +23 -16
  19. package/dist/access-mcp.js +96 -84
  20. package/dist/access-memory-search-fanout.d.ts +93 -0
  21. package/dist/access-memory-search-fanout.js +18 -0
  22. package/dist/access-observe-write-surface.d.ts +26 -8
  23. package/dist/access-observe-write-surface.js +85 -71
  24. package/dist/access-operations-batch.js +92 -80
  25. package/dist/access-operations.d.ts +29 -22
  26. package/dist/access-operations.js +94 -82
  27. package/dist/access-recall-concurrency.d.ts +250 -0
  28. package/dist/access-recall-concurrency.js +157 -0
  29. package/dist/access-recall-response.d.ts +130 -0
  30. package/dist/access-recall-response.js +147 -0
  31. package/dist/access-recall-surface.d.ts +15 -7
  32. package/dist/access-recall-surface.js +85 -71
  33. package/dist/access-schema.d.ts +98 -98
  34. package/dist/access-schema.js +8 -6
  35. package/dist/{access-service-DpcYZ9Nl.d.ts → access-service-DEL4qCrc.d.ts} +25 -32
  36. package/dist/access-service.d.ts +13 -6
  37. package/dist/access-service.js +89 -72
  38. package/dist/access-surface-catalog.d.ts +23 -16
  39. package/dist/access-surface-catalog.js +1 -0
  40. package/dist/access-surface-catalog.js.map +1 -1
  41. package/dist/access-token-capabilities.d.ts +2 -1
  42. package/dist/access-token-capabilities.js +4 -2
  43. package/dist/action-confidence.d.ts +3 -1
  44. package/dist/active-memory-bridge.d.ts +3 -1
  45. package/dist/active-memory-bridge.js +4 -4
  46. package/dist/active-recall.d.ts +4 -1
  47. package/dist/active-recall.js +23 -13
  48. package/dist/active-recall.js.map +1 -1
  49. package/dist/adapters/index.js +4 -4
  50. package/dist/adapters/registry.js +2 -2
  51. package/dist/{auto-sync-AAMTVZMK.js → auto-sync-UZG3XQZ5.js} +14 -8
  52. package/dist/{auto-sync-AAMTVZMK.js.map → auto-sync-UZG3XQZ5.js.map} +1 -1
  53. package/dist/behavior-learner.d.ts +3 -1
  54. package/dist/behavior-signals.d.ts +3 -1
  55. package/dist/bootstrap.d.ts +12 -7
  56. package/dist/bootstrap.js +2 -2
  57. package/dist/bounded-jsonl-state.d.ts +54 -0
  58. package/dist/bounded-jsonl-state.js +10 -0
  59. package/dist/boxes.js +2 -2
  60. package/dist/briefing.d.ts +5 -2
  61. package/dist/briefing.js +34 -24
  62. package/dist/buffer-surprise-report.d.ts +3 -1
  63. package/dist/buffer.d.ts +60 -2
  64. package/dist/buffer.js +3 -3
  65. package/dist/bulk-import/index.d.ts +5 -3
  66. package/dist/calibration.d.ts +3 -1
  67. package/dist/calibration.js +6 -6
  68. package/dist/capabilities.d.ts +7 -7
  69. package/dist/capabilities.js +1 -1
  70. package/dist/{capsule-crypto-CZJSLEFG.js → capsule-crypto-YO5QJ6L3.js} +3 -3
  71. package/dist/capsule-crypto-YO5QJ6L3.js.map +1 -0
  72. package/dist/{catalog-C9444P10.d.ts → catalog-BWqHb5HT.d.ts} +1 -1
  73. package/dist/causal-behavior.d.ts +3 -1
  74. package/dist/causal-behavior.js +6 -6
  75. package/dist/causal-chain.js +4 -4
  76. package/dist/causal-consolidation.d.ts +3 -1
  77. package/dist/causal-consolidation.js +43 -34
  78. package/dist/causal-consolidation.js.map +1 -1
  79. package/dist/causal-retrieval.js +6 -6
  80. package/dist/causal-trajectory-graph.d.ts +3 -1
  81. package/dist/causal-trajectory-graph.js +1 -1
  82. package/dist/causal-trajectory.js +1 -1
  83. package/dist/{chunk-A3GOMRJG.js → chunk-23L3IXFD.js} +2 -2
  84. package/dist/chunk-2CGLBUW3.js +15 -0
  85. package/dist/chunk-2CGLBUW3.js.map +1 -0
  86. package/dist/{chunk-MRHFJV44.js → chunk-2DQ2XREU.js} +2 -2
  87. package/dist/{chunk-QKQYXZVS.js → chunk-2EJOEICD.js} +1819 -1481
  88. package/dist/chunk-2EJOEICD.js.map +1 -0
  89. package/dist/{chunk-L2B3EE7B.js → chunk-2QMKMVHH.js} +2 -2
  90. package/dist/{chunk-VJVNLNDQ.js → chunk-2UFO7X4Q.js} +7 -7
  91. package/dist/{chunk-2MR3MFQB.js → chunk-2VEOKUPP.js} +3 -3
  92. package/dist/chunk-2Z24E5W2.js +22 -0
  93. package/dist/chunk-2Z24E5W2.js.map +1 -0
  94. package/dist/{chunk-RHOZ5LLO.js → chunk-347WD2LE.js} +2 -2
  95. package/dist/{chunk-HDTQVNWD.js → chunk-3QAH2S33.js} +3 -3
  96. package/dist/{chunk-37CTGERM.js → chunk-3WCASNQZ.js} +12 -1
  97. package/dist/chunk-3WCASNQZ.js.map +1 -0
  98. package/dist/{chunk-LRNMRXJO.js → chunk-3Y224NYC.js} +3 -3
  99. package/dist/{chunk-3IY64MV6.js → chunk-44XZ75OQ.js} +44 -10
  100. package/dist/chunk-44XZ75OQ.js.map +1 -0
  101. package/dist/{chunk-VFSP73LP.js → chunk-45GF7Y3V.js} +2 -2
  102. package/dist/{chunk-K7LOWSLU.js → chunk-4BJQODZF.js} +2479 -1520
  103. package/dist/chunk-4BJQODZF.js.map +1 -0
  104. package/dist/{chunk-JREB6UFH.js → chunk-57OWKFUQ.js} +17 -6
  105. package/dist/chunk-57OWKFUQ.js.map +1 -0
  106. package/dist/{chunk-OEHCMALU.js → chunk-5I4M26Q7.js} +5 -5
  107. package/dist/{chunk-2AZXIZEN.js → chunk-5Q7EVV4X.js} +6 -6
  108. package/dist/{chunk-LC7OODWZ.js → chunk-5SB7SC2G.js} +80 -49
  109. package/dist/chunk-5SB7SC2G.js.map +1 -0
  110. package/dist/{chunk-PUBTHW5O.js → chunk-6DRPPQEJ.js} +2 -2
  111. package/dist/{chunk-NWTGD4AN.js → chunk-6KIQT7RG.js} +10 -9
  112. package/dist/chunk-6KIQT7RG.js.map +1 -0
  113. package/dist/{chunk-FDCTQWLW.js → chunk-6O22TZSB.js} +3 -3
  114. package/dist/{chunk-ZQ7UBUZ6.js → chunk-6QYST5XN.js} +6 -6
  115. package/dist/{chunk-W4PGTAS2.js → chunk-6WAFYNVT.js} +3 -3
  116. package/dist/chunk-6ZMAMSHS.js +20 -0
  117. package/dist/chunk-6ZMAMSHS.js.map +1 -0
  118. package/dist/{chunk-R5VAVVHP.js → chunk-72A4L5JJ.js} +2 -2
  119. package/dist/{chunk-X64YLC24.js → chunk-72VAXGEI.js} +5 -13
  120. package/dist/chunk-72VAXGEI.js.map +1 -0
  121. package/dist/{chunk-IKQTFQMI.js → chunk-755Q3DGF.js} +22 -3
  122. package/dist/chunk-755Q3DGF.js.map +1 -0
  123. package/dist/{chunk-OVJ2HIPE.js → chunk-76GLCM57.js} +158 -125
  124. package/dist/chunk-76GLCM57.js.map +1 -0
  125. package/dist/{chunk-D7FOKIY5.js → chunk-7AMFUATK.js} +12 -9
  126. package/dist/{chunk-D7FOKIY5.js.map → chunk-7AMFUATK.js.map} +1 -1
  127. package/dist/{chunk-BFVEEB7W.js → chunk-7ON2JW73.js} +57 -22
  128. package/dist/chunk-7ON2JW73.js.map +1 -0
  129. package/dist/chunk-7RNBVZZO.js +270 -0
  130. package/dist/chunk-7RNBVZZO.js.map +1 -0
  131. package/dist/{chunk-3FAMU5TX.js → chunk-A6USBZTO.js} +2 -2
  132. package/dist/{chunk-ZHIVCODT.js → chunk-A72SWTWW.js} +7 -7
  133. package/dist/{chunk-FC77VUX5.js → chunk-A7Q43EUZ.js} +2 -2
  134. package/dist/{chunk-UJBESW6X.js → chunk-AE7WMV4V.js} +7 -7
  135. package/dist/{chunk-J2HSAU72.js → chunk-AIK5W3IW.js} +29 -1
  136. package/dist/chunk-AIK5W3IW.js.map +1 -0
  137. package/dist/{chunk-A5UXZRRM.js → chunk-AJ7QCSIS.js} +2 -2
  138. package/dist/{chunk-FNMFJWBY.js → chunk-ANEUPF6O.js} +5 -5
  139. package/dist/chunk-AREGMX2J.js +50 -0
  140. package/dist/chunk-AREGMX2J.js.map +1 -0
  141. package/dist/chunk-AVPXXV6J.js +448 -0
  142. package/dist/chunk-AVPXXV6J.js.map +1 -0
  143. package/dist/{chunk-2A3OXAP2.js → chunk-B7RWBZXW.js} +2 -2
  144. package/dist/{chunk-GWTFLF2P.js → chunk-BJMBJZ2Y.js} +59 -59
  145. package/dist/chunk-BJMBJZ2Y.js.map +1 -0
  146. package/dist/{chunk-74F5STS4.js → chunk-BLAKS3CP.js} +4 -4
  147. package/dist/{chunk-M7VGG3ID.js → chunk-BV5WMSIJ.js} +9 -9
  148. package/dist/{chunk-2BFLDH5F.js → chunk-BXLOS5AJ.js} +2 -2
  149. package/dist/{chunk-UXKMMNJD.js → chunk-C23BYTJV.js} +6 -6
  150. package/dist/{chunk-JZHHREBL.js → chunk-C3AKM55W.js} +2 -2
  151. package/dist/{chunk-RP7YXA67.js → chunk-C5JF6EZ7.js} +2 -2
  152. package/dist/{chunk-T7Y5KPLN.js → chunk-C6XBRYVD.js} +16 -15
  153. package/dist/chunk-C6XBRYVD.js.map +1 -0
  154. package/dist/{chunk-FTYDWKO6.js → chunk-CEN6DW6X.js} +12 -2
  155. package/dist/chunk-CEN6DW6X.js.map +1 -0
  156. package/dist/chunk-CGASUJVP.js +421 -0
  157. package/dist/chunk-CGASUJVP.js.map +1 -0
  158. package/dist/{chunk-EHCONI6E.js → chunk-CQMEM5CC.js} +2 -2
  159. package/dist/{chunk-PBNZVPFS.js → chunk-CXZQOVIE.js} +12 -12
  160. package/dist/chunk-D3V3UMET.js +44 -0
  161. package/dist/chunk-D3V3UMET.js.map +1 -0
  162. package/dist/{chunk-7N2RUBAP.js → chunk-DDA47TES.js} +2 -2
  163. package/dist/{chunk-64SE4X5G.js → chunk-DEBHXHJR.js} +3 -3
  164. package/dist/{chunk-EHK6KZHK.js → chunk-DNHVPZOD.js} +2 -2
  165. package/dist/{chunk-437S3G37.js → chunk-DQEMWVMT.js} +2 -2
  166. package/dist/{chunk-LZZNTPLR.js → chunk-DX3XRGLH.js} +2 -2
  167. package/dist/chunk-EA2H5LML.js +72 -0
  168. package/dist/chunk-EA2H5LML.js.map +1 -0
  169. package/dist/{chunk-INELTPRG.js → chunk-EEC7UJPX.js} +103 -106
  170. package/dist/chunk-EEC7UJPX.js.map +1 -0
  171. package/dist/{chunk-KSNVDPDF.js → chunk-EKBNDKDY.js} +21 -20
  172. package/dist/chunk-EKBNDKDY.js.map +1 -0
  173. package/dist/{chunk-YF6FMLBT.js → chunk-EQWEIIKQ.js} +64 -34
  174. package/dist/chunk-EQWEIIKQ.js.map +1 -0
  175. package/dist/{chunk-DZKHSDOM.js → chunk-ES36HTSC.js} +4 -4
  176. package/dist/{chunk-TN7THW5U.js → chunk-ET356KSB.js} +2 -2
  177. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  178. package/dist/{chunk-DMSDUGDM.js → chunk-F7GAIWFA.js} +20 -20
  179. package/dist/{chunk-G6XXLKC5.js → chunk-FFPJINJE.js} +6 -6
  180. package/dist/chunk-FMLKOL2Z.js +636 -0
  181. package/dist/chunk-FMLKOL2Z.js.map +1 -0
  182. package/dist/chunk-FQC3DHH2.js +20 -0
  183. package/dist/chunk-FQC3DHH2.js.map +1 -0
  184. package/dist/{chunk-G4CN3ZXL.js → chunk-FUTF72MJ.js} +15 -15
  185. package/dist/chunk-GCASGYIO.js +71 -0
  186. package/dist/chunk-GCASGYIO.js.map +1 -0
  187. package/dist/{chunk-HF77M34J.js → chunk-GFPZS3F5.js} +8 -8
  188. package/dist/{chunk-BCDKBDSY.js → chunk-GNVZQ5JN.js} +99 -41
  189. package/dist/chunk-GNVZQ5JN.js.map +1 -0
  190. package/dist/{chunk-G6NKALRN.js → chunk-H4WG3UQZ.js} +2 -2
  191. package/dist/{chunk-UDQUSU27.js → chunk-HNZKVLAN.js} +2 -2
  192. package/dist/{chunk-5EZXHU36.js → chunk-HYQJQGD3.js} +2 -2
  193. package/dist/{chunk-OAZVR2BV.js → chunk-IDZFBSHN.js} +8 -6
  194. package/dist/{chunk-OAZVR2BV.js.map → chunk-IDZFBSHN.js.map} +1 -1
  195. package/dist/{chunk-PLQE6MJA.js → chunk-IFH6LWTO.js} +50 -8
  196. package/dist/chunk-IFH6LWTO.js.map +1 -0
  197. package/dist/{chunk-RULE4VG5.js → chunk-ILGC6JH6.js} +21 -6
  198. package/dist/chunk-ILGC6JH6.js.map +1 -0
  199. package/dist/chunk-IUM3VSHI.js +113 -0
  200. package/dist/chunk-IUM3VSHI.js.map +1 -0
  201. package/dist/{chunk-DCFV7A7H.js → chunk-IYNGIMVG.js} +101 -91
  202. package/dist/chunk-IYNGIMVG.js.map +1 -0
  203. package/dist/{chunk-TRWPCR6P.js → chunk-JECBQBEX.js} +3 -3
  204. package/dist/{chunk-E6CBU7XP.js → chunk-JYIFGGEM.js} +2 -2
  205. package/dist/{chunk-VA4WSW54.js → chunk-JYIJNNN3.js} +3 -3
  206. package/dist/{chunk-L5HJQC36.js → chunk-K2TDK7GG.js} +3 -3
  207. package/dist/{chunk-KDXVOFYY.js → chunk-KAVBJSBQ.js} +4 -4
  208. package/dist/{chunk-BS4SGLWV.js → chunk-KF5EUVKQ.js} +16 -6
  209. package/dist/chunk-KF5EUVKQ.js.map +1 -0
  210. package/dist/chunk-KFZY2OFH.js +42 -0
  211. package/dist/chunk-KFZY2OFH.js.map +1 -0
  212. package/dist/{chunk-4OKLXWDZ.js → chunk-KNB7IBBU.js} +2 -2
  213. package/dist/{chunk-QLULYKWZ.js → chunk-KSXJOC4F.js} +2 -2
  214. package/dist/{chunk-2S6QHZGJ.js → chunk-L2DPF4DF.js} +1 -1
  215. package/dist/{chunk-JI5AVXYO.js → chunk-LEPOP46W.js} +6 -6
  216. package/dist/{chunk-O7BBFJLP.js → chunk-LTAVSOZW.js} +2 -2
  217. package/dist/{chunk-E3VODCC3.js → chunk-LUDXM7MD.js} +14 -2
  218. package/dist/{chunk-E3VODCC3.js.map → chunk-LUDXM7MD.js.map} +1 -1
  219. package/dist/{chunk-2IZAGAJR.js → chunk-LULR4IUW.js} +3 -3
  220. package/dist/{chunk-QQGPUKMT.js → chunk-MC5Q3J7S.js} +398 -7
  221. package/dist/chunk-MC5Q3J7S.js.map +1 -0
  222. package/dist/{chunk-WMWVO45V.js → chunk-MC6XO7T4.js} +2 -2
  223. package/dist/chunk-MKQBXQKU.js +107 -0
  224. package/dist/chunk-MKQBXQKU.js.map +1 -0
  225. package/dist/{chunk-7PND4PUC.js → chunk-MMGGVZ4Q.js} +29 -9
  226. package/dist/{chunk-7PND4PUC.js.map → chunk-MMGGVZ4Q.js.map} +1 -1
  227. package/dist/{chunk-D6RIFG4O.js → chunk-MNB5RMAY.js} +2 -2
  228. package/dist/{chunk-Q5WG43OP.js → chunk-MYFQ3ED4.js} +7 -7
  229. package/dist/{chunk-V3UE5I5F.js → chunk-MYVPLJOO.js} +2 -2
  230. package/dist/chunk-NINSR6LX.js +83 -0
  231. package/dist/chunk-NINSR6LX.js.map +1 -0
  232. package/dist/{chunk-MTWKDOVO.js → chunk-NLE6TSLG.js} +2 -2
  233. package/dist/{chunk-DBRYEIGY.js → chunk-OJP3N7UK.js} +2 -2
  234. package/dist/{chunk-VDW4VU7B.js → chunk-OQJIB32H.js} +28 -23
  235. package/dist/chunk-OQJIB32H.js.map +1 -0
  236. package/dist/{chunk-SMX5267P.js → chunk-OZKOPQCM.js} +2 -2
  237. package/dist/{chunk-JCK7V6SN.js → chunk-P65YJEEL.js} +2 -2
  238. package/dist/{chunk-MTR7BZQN.js → chunk-PBGWYM3H.js} +3 -3
  239. package/dist/chunk-PIG4WJFQ.js +87 -0
  240. package/dist/chunk-PIG4WJFQ.js.map +1 -0
  241. package/dist/chunk-PQVCH2AE.js +76 -0
  242. package/dist/chunk-PQVCH2AE.js.map +1 -0
  243. package/dist/{chunk-AXTXN4T6.js → chunk-PWFCHOB3.js} +2 -2
  244. package/dist/{chunk-FDPZVY6D.js → chunk-QFN4U7AG.js} +2 -2
  245. package/dist/{chunk-K2ZLHESQ.js → chunk-QIEUU4UK.js} +2 -2
  246. package/dist/{chunk-DYP3YYJJ.js → chunk-QJAQNXWI.js} +39 -5
  247. package/dist/chunk-QJAQNXWI.js.map +1 -0
  248. package/dist/{chunk-3D6AFGQR.js → chunk-QVT3E4CE.js} +7 -7
  249. package/dist/{chunk-FIJUY7GG.js → chunk-R26ZMXR2.js} +23 -23
  250. package/dist/{chunk-FIJUY7GG.js.map → chunk-R26ZMXR2.js.map} +1 -1
  251. package/dist/chunk-R3DJVOSM.js +34 -0
  252. package/dist/chunk-R3DJVOSM.js.map +1 -0
  253. package/dist/{chunk-SFQ6QNL7.js → chunk-R6YJI3HE.js} +2 -1
  254. package/dist/{chunk-5CJVLG3H.js → chunk-RFDD3B7W.js} +5 -5
  255. package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
  256. package/dist/chunk-ROI7BK7H.js +88 -0
  257. package/dist/chunk-ROI7BK7H.js.map +1 -0
  258. package/dist/{chunk-FNZQGN76.js → chunk-S2BBISHU.js} +4 -4
  259. package/dist/{chunk-IALLX7EE.js → chunk-S2FSBU4H.js} +3 -3
  260. package/dist/{chunk-BFPETA3S.js → chunk-SCCO46KZ.js} +3 -2
  261. package/dist/chunk-SCCO46KZ.js.map +1 -0
  262. package/dist/chunk-SICXL4MK.js +165 -0
  263. package/dist/chunk-SICXL4MK.js.map +1 -0
  264. package/dist/chunk-SK7AMF2J.js +168 -0
  265. package/dist/chunk-SK7AMF2J.js.map +1 -0
  266. package/dist/{chunk-LZOV7MX7.js → chunk-TDTXKOAJ.js} +6474 -5747
  267. package/dist/chunk-TDTXKOAJ.js.map +1 -0
  268. package/dist/{chunk-KSBEEMQF.js → chunk-TG6IHVE2.js} +151 -6
  269. package/dist/chunk-TG6IHVE2.js.map +1 -0
  270. package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
  271. package/dist/{chunk-DPAENM7O.js → chunk-U3ZAVRP3.js} +2 -2
  272. package/dist/{chunk-ODPLEWB6.js → chunk-UFGFMWAD.js} +47 -17
  273. package/dist/chunk-UFGFMWAD.js.map +1 -0
  274. package/dist/{chunk-4KJLYTLS.js → chunk-V57NLO5P.js} +2 -2
  275. package/dist/{chunk-FLVL4L3L.js → chunk-VDX2J7OX.js} +2 -2
  276. package/dist/{chunk-AJLLIIML.js → chunk-W4FBGYGK.js} +1 -1
  277. package/dist/{chunk-TXLGHDHS.js → chunk-W4XJFLAL.js} +53 -32
  278. package/dist/chunk-W4XJFLAL.js.map +1 -0
  279. package/dist/{chunk-6SXVCD7W.js → chunk-W7IGLX4G.js} +2 -2
  280. package/dist/{chunk-KQDNAXOM.js → chunk-WG5HSQ4P.js} +19 -6
  281. package/dist/chunk-WG5HSQ4P.js.map +1 -0
  282. package/dist/{chunk-LTJAMRGI.js → chunk-WL5EBRDH.js} +17 -3
  283. package/dist/chunk-WL5EBRDH.js.map +1 -0
  284. package/dist/{chunk-KAWTOYAW.js → chunk-WLZYGLJ4.js} +2 -2
  285. package/dist/{chunk-RO4LQGT3.js → chunk-WON4APQY.js} +4 -4
  286. package/dist/{chunk-PQVK2S3J.js → chunk-WZFAPHIK.js} +6 -6
  287. package/dist/{chunk-KQPJLK3X.js → chunk-XL24QQ63.js} +2 -2
  288. package/dist/{chunk-RVZRYUQH.js → chunk-YROFNEG5.js} +7 -7
  289. package/dist/{chunk-RAR2BSEM.js → chunk-YV32N67O.js} +1 -1
  290. package/dist/chunk-YV32N67O.js.map +1 -0
  291. package/dist/{chunk-PBSAPHHA.js → chunk-YVKF3HEW.js} +1 -1
  292. package/dist/chunk-YVKF3HEW.js.map +1 -0
  293. package/dist/{chunk-VRAD2FGO.js → chunk-Z54EM5YZ.js} +12 -12
  294. package/dist/{chunk-2VN4JAX7.js → chunk-ZOKZIR5K.js} +95 -33
  295. package/dist/chunk-ZOKZIR5K.js.map +1 -0
  296. package/dist/{cli-Cd5fMmhq.d.ts → cli-C_pqqTCw.d.ts} +28 -12
  297. package/dist/cli.d.ts +16 -9
  298. package/dist/cli.js +142 -127
  299. package/dist/compounding/engine.d.ts +5 -2
  300. package/dist/compounding/engine.js +36 -26
  301. package/dist/compounding/preference-consolidator.d.ts +3 -1
  302. package/dist/compounding/preference-consolidator.js +1 -1
  303. package/dist/compression-optimizer.d.ts +3 -1
  304. package/dist/config-qmd.d.ts +8 -0
  305. package/dist/config-qmd.js +20 -0
  306. package/dist/config-qmd.js.map +1 -0
  307. package/dist/config.d.ts +3 -1
  308. package/dist/config.js +15 -10
  309. package/dist/connectors/codex-materialize-runner.d.ts +3 -1
  310. package/dist/connectors/codex-materialize-runner.js +36 -26
  311. package/dist/connectors/codex-materialize.d.ts +3 -1
  312. package/dist/connectors/codex-materialize.js +2 -2
  313. package/dist/connectors/index.d.ts +3 -1
  314. package/dist/connectors/index.js +41 -32
  315. package/dist/consolidation-provenance-check.d.ts +5 -2
  316. package/dist/consolidation-undo.d.ts +5 -2
  317. package/dist/contradiction/index.d.ts +5 -2
  318. package/dist/contradiction/index.js +10 -4
  319. package/dist/{contradiction-scan-J57T5QV7.js → contradiction-scan-RJBABNRH.js} +4 -4
  320. package/dist/contradiction-scan-RJBABNRH.js.map +1 -0
  321. package/dist/conversation-index/backend.d.ts +3 -1
  322. package/dist/conversation-index/backend.js +5 -5
  323. package/dist/conversation-index/chunker.d.ts +3 -1
  324. package/dist/conversation-index/cleanup.js +2 -2
  325. package/dist/conversation-index/faiss-adapter.d.ts +3 -1
  326. package/dist/conversation-index/faiss-adapter.js +2 -2
  327. package/dist/conversation-index/indexer.d.ts +3 -1
  328. package/dist/conversation-index/indexer.js +2 -2
  329. package/dist/conversation-index/search.d.ts +3 -1
  330. package/dist/conversation-index/search.js +2 -2
  331. package/dist/cross-namespace-budget.d.ts +45 -1
  332. package/dist/cross-namespace-budget.js +5 -3
  333. package/dist/dashboard-runtime.js +2 -2
  334. package/dist/day-summary.d.ts +3 -1
  335. package/dist/day-summary.js +3 -3
  336. package/dist/delinearize.d.ts +3 -1
  337. package/dist/direct-answer-wiring.d.ts +3 -1
  338. package/dist/direct-answer.d.ts +3 -1
  339. package/dist/{dreams-ledger-6UODQOX6.js → dreams-ledger-567VKVOU.js} +4 -2
  340. package/dist/dreams-ledger-567VKVOU.js.map +1 -0
  341. package/dist/embedding-fallback.d.ts +3 -1
  342. package/dist/embedding-fallback.js +3 -3
  343. package/dist/enrichment/index.d.ts +3 -1
  344. package/dist/entity-retrieval.d.ts +5 -2
  345. package/dist/entity-retrieval.js +35 -26
  346. package/dist/entity-schema.d.ts +3 -1
  347. package/dist/explicit-capture.d.ts +13 -8
  348. package/dist/explicit-capture.js +7 -3
  349. package/dist/extraction-faithfulness.d.ts +3 -1
  350. package/dist/extraction-faithfulness.js +5 -5
  351. package/dist/extraction-judge-telemetry.d.ts +3 -1
  352. package/dist/extraction-judge-telemetry.js +2 -2
  353. package/dist/extraction-judge-training.d.ts +3 -1
  354. package/dist/extraction-judge-training.js +2 -2
  355. package/dist/extraction-judge.d.ts +3 -1
  356. package/dist/extraction-judge.js +5 -5
  357. package/dist/extraction.d.ts +3 -1
  358. package/dist/extraction.js +13 -12
  359. package/dist/faithfulness-config.js +3 -2
  360. package/dist/fallback-llm.d.ts +3 -1
  361. package/dist/fallback-llm.js +4 -4
  362. package/dist/{first-start-migration-TI67YMLG.js → first-start-migration-CSRHCJIQ.js} +2 -2
  363. package/dist/{forget-CQCLB5LB.js → forget-HRPLVB3W.js} +5 -5
  364. package/dist/graph-dashboard-diff.d.ts +3 -1
  365. package/dist/graph-dashboard-key.d.ts +3 -1
  366. package/dist/graph-dashboard-parser.d.ts +3 -1
  367. package/dist/{graph-edge-decay-IOGBBAGC.js → graph-edge-decay-Z6ENALU2.js} +3 -3
  368. package/dist/graph-edge-decay-Z6ENALU2.js.map +1 -0
  369. package/dist/graph-edge-reinforcement.d.ts +3 -1
  370. package/dist/graph-snapshot.d.ts +3 -1
  371. package/dist/graph-snapshot.js +2 -2
  372. package/dist/graph.d.ts +3 -1
  373. package/dist/graph.js +1 -1
  374. package/dist/identity-continuity.d.ts +1 -2
  375. package/dist/importance.d.ts +3 -1
  376. package/dist/importers/index.d.ts +3 -1
  377. package/dist/in-flight-reads.d.ts +3 -1
  378. package/dist/index.d.ts +473 -464
  379. package/dist/index.js +287 -239
  380. package/dist/intent.d.ts +3 -1
  381. package/dist/lcm/archive.js +2 -2
  382. package/dist/lcm/engine.d.ts +3 -1
  383. package/dist/lcm/engine.js +6 -6
  384. package/dist/lcm/index.d.ts +3 -1
  385. package/dist/lcm/index.js +13 -13
  386. package/dist/lcm/schema.js +2 -2
  387. package/dist/lcm/summarizer.js +3 -3
  388. package/dist/lcm/tools.d.ts +3 -1
  389. package/dist/lifecycle.d.ts +3 -1
  390. package/dist/live-connectors-runner.d.ts +3 -1
  391. package/dist/local-llm.d.ts +5 -2
  392. package/dist/local-llm.js +3 -3
  393. package/dist/local-model-endpoint.d.ts +3 -1
  394. package/dist/logger.d.ts +3 -1
  395. package/dist/logger.js +7 -3
  396. package/dist/maintenance/archive-observations.js +2 -2
  397. package/dist/maintenance/memory-governance.d.ts +3 -1
  398. package/dist/maintenance/memory-governance.js +35 -25
  399. package/dist/maintenance/migrate-observations.js +3 -3
  400. package/dist/maintenance/observation-ledger-utils.js +2 -2
  401. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +102 -1
  402. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +37 -25
  403. package/dist/maintenance/rebuild-memory-projection.js +38 -28
  404. package/dist/maintenance/rebuild-observations.js +3 -3
  405. package/dist/mcp-memory-inspector-app.d.ts +22 -15
  406. package/dist/memory-action-policy.d.ts +3 -1
  407. package/dist/memory-cache.d.ts +3 -1
  408. package/dist/memory-lifecycle-ledger-utils.d.ts +25 -2
  409. package/dist/memory-lifecycle-ledger-utils.js +11 -1
  410. package/dist/memory-projection-store.d.ts +3 -1
  411. package/dist/memory-projection-store.js +2 -2
  412. package/dist/memory-provenance.d.ts +3 -1
  413. package/dist/memory-worth-outcomes.d.ts +5 -2
  414. package/dist/model-registry.js +2 -2
  415. package/dist/models-json.d.ts +3 -1
  416. package/dist/models-json.js +2 -2
  417. package/dist/namespaces/migrate.d.ts +6 -3
  418. package/dist/namespaces/migrate.js +51 -42
  419. package/dist/namespaces/principal.d.ts +27 -2
  420. package/dist/namespaces/principal.js +6 -2
  421. package/dist/namespaces/search.d.ts +16 -2
  422. package/dist/namespaces/search.js +24 -20
  423. package/dist/namespaces/storage.d.ts +24 -3
  424. package/dist/namespaces/storage.js +35 -27
  425. package/dist/native-knowledge.d.ts +3 -1
  426. package/dist/native-knowledge.js +2 -2
  427. package/dist/negative.js +2 -2
  428. package/dist/offline-sync-exclude-globs.d.ts +13 -0
  429. package/dist/offline-sync-exclude-globs.js +10 -0
  430. package/dist/offline-sync-exclude-globs.js.map +1 -0
  431. package/dist/offline-sync-impression-drain.d.ts +78 -0
  432. package/dist/offline-sync-impression-drain.js +37 -0
  433. package/dist/offline-sync-impression-drain.js.map +1 -0
  434. package/dist/offline-sync.js +4 -2
  435. package/dist/operator-toolkit.d.ts +5 -2
  436. package/dist/operator-toolkit.js +69 -54
  437. package/dist/orchestration/compression-guideline-coordinator.d.ts +5 -2
  438. package/dist/orchestration/compression-guideline-coordinator.js +3 -3
  439. package/dist/orchestration/maintenance.d.ts +121 -2
  440. package/dist/orchestration/maintenance.js +44 -31
  441. package/dist/{orchestrator-Bp_jeBHK.d.ts → orchestrator-CQJ8U7En.d.ts} +85 -79
  442. package/dist/orchestrator.d.ts +13 -8
  443. package/dist/orchestrator.js +194 -177
  444. package/dist/patterns-cli.d.ts +3 -1
  445. package/dist/{pipeline-BAj5bx7g.d.ts → pipeline-Cn-kvYeV.d.ts} +1 -1
  446. package/dist/policy-runtime.d.ts +3 -1
  447. package/dist/prioritized-embed.d.ts +19 -0
  448. package/dist/prioritized-embed.js +8 -0
  449. package/dist/prioritized-embed.js.map +1 -0
  450. package/dist/proactive-contention.d.ts +28 -0
  451. package/dist/proactive-contention.js +8 -0
  452. package/dist/proactive-contention.js.map +1 -0
  453. package/dist/profiling.js +2 -2
  454. package/dist/provenance.d.ts +3 -1
  455. package/dist/provenance.js +3 -2
  456. package/dist/{purge-NDWV6WYD.js → purge-IRF47ZTX.js} +3 -3
  457. package/dist/{qmd-_MDSlj1m.d.ts → qmd-oh9VXz1d.d.ts} +11 -1
  458. package/dist/qmd-preflight.d.ts +5 -2
  459. package/dist/qmd-recall-cache.d.ts +3 -1
  460. package/dist/qmd-status.d.ts +57 -0
  461. package/dist/qmd-status.js +18 -0
  462. package/dist/qmd-status.js.map +1 -0
  463. package/dist/qmd.d.ts +5 -2
  464. package/dist/qmd.js +7 -3
  465. package/dist/recall-concurrency-config.d.ts +16 -0
  466. package/dist/recall-concurrency-config.js +10 -0
  467. package/dist/recall-concurrency-config.js.map +1 -0
  468. package/dist/recall-disclosure-escalation.d.ts +3 -1
  469. package/dist/recall-explain-renderer.d.ts +4 -1
  470. package/dist/recall-explain-renderer.js +3 -3
  471. package/dist/recall-memory-map.d.ts +26 -0
  472. package/dist/recall-memory-map.js +18 -0
  473. package/dist/recall-memory-map.js.map +1 -0
  474. package/dist/recall-planner-llm.d.ts +3 -1
  475. package/dist/recall-planner-llm.js +4 -4
  476. package/dist/recall-qos.js +2 -2
  477. package/dist/recall-state.d.ts +163 -2
  478. package/dist/recall-state.js +6 -3
  479. package/dist/recall-tag-filter.d.ts +3 -1
  480. package/dist/recall-timings.d.ts +11 -2
  481. package/dist/recall-timings.js +3 -1
  482. package/dist/recall-xray-cli.d.ts +3 -1
  483. package/dist/recall-xray-cli.js +4 -4
  484. package/dist/recall-xray-renderer.d.ts +3 -1
  485. package/dist/recall-xray-renderer.js +3 -3
  486. package/dist/recall-xray.d.ts +3 -1
  487. package/dist/recall-xray.js +2 -2
  488. package/dist/relevance.js +3 -3
  489. package/dist/replay/normalizers/chatgpt.d.ts +3 -1
  490. package/dist/replay/normalizers/claude.d.ts +3 -1
  491. package/dist/replay/normalizers/openclaw.d.ts +3 -1
  492. package/dist/replay/normalizers/shared.d.ts +3 -1
  493. package/dist/replay/runner.d.ts +3 -1
  494. package/dist/replay/types.d.ts +3 -1
  495. package/dist/rerank.d.ts +8 -1
  496. package/dist/rerank.js +3 -1
  497. package/dist/resolution-3K27T4VO.js +18 -0
  498. package/dist/resolution-3K27T4VO.js.map +1 -0
  499. package/dist/resolve-auth-token.d.ts +3 -1
  500. package/dist/resolve-provider-secret.js +2 -2
  501. package/dist/resume-bundles.js +19 -14
  502. package/dist/retrieval-agents.d.ts +19 -16
  503. package/dist/retrieval-agents.js +3 -3
  504. package/dist/retrieval-tiers.d.ts +3 -1
  505. package/dist/routing/engine.d.ts +3 -1
  506. package/dist/routing/store.d.ts +3 -1
  507. package/dist/routing/store.js +2 -2
  508. package/dist/salvage-envelope.d.ts +18 -0
  509. package/dist/salvage-envelope.js +15 -0
  510. package/dist/salvage-envelope.js.map +1 -0
  511. package/dist/schemas.d.ts +98 -98
  512. package/dist/scope-profiles-EpJG7yKP.d.ts +30 -0
  513. package/dist/search/document-scanner.js +3 -2
  514. package/dist/search/embed-helper.d.ts +3 -1
  515. package/dist/search/embed-helper.js +3 -3
  516. package/dist/search/factory.d.ts +3 -1
  517. package/dist/search/factory.js +18 -16
  518. package/dist/search/index.d.ts +3 -1
  519. package/dist/search/index.js +22 -20
  520. package/dist/search/lancedb-backend.d.ts +3 -1
  521. package/dist/search/lancedb-backend.js +6 -5
  522. package/dist/search/meilisearch-backend.d.ts +3 -1
  523. package/dist/search/meilisearch-backend.js +6 -5
  524. package/dist/search/noop-backend.d.ts +3 -1
  525. package/dist/search/orama-backend.d.ts +3 -1
  526. package/dist/search/orama-backend.js +6 -5
  527. package/dist/search/port.d.ts +16 -2
  528. package/dist/search/port.js +1 -1
  529. package/dist/search/remote-backend.d.ts +3 -1
  530. package/dist/search/remote-backend.js +3 -3
  531. package/dist/secure-store/index.d.ts +12 -1
  532. package/dist/secure-store/index.js +6 -3
  533. package/dist/{semantic-consolidation-C2m5eHHE.d.ts → semantic-consolidation-DILZEQq3.d.ts} +1 -1
  534. package/dist/semantic-consolidation.d.ts +4 -2
  535. package/dist/semantic-consolidation.js +38 -29
  536. package/dist/semantic-rule-promotion.js +34 -24
  537. package/dist/semantic-rule-verifier.d.ts +3 -1
  538. package/dist/semantic-rule-verifier.js +35 -25
  539. package/dist/session-observer-bands.d.ts +3 -1
  540. package/dist/session-observer-state.d.ts +3 -1
  541. package/dist/session-observer-state.js +2 -2
  542. package/dist/session-transcript-migration.js +2 -2
  543. package/dist/shared-context/manager.d.ts +11 -9
  544. package/dist/shared-context/manager.js +3 -3
  545. package/dist/signal.d.ts +3 -1
  546. package/dist/{storage-hr_Y2z5R.d.ts → storage-NIyKYD8g.d.ts} +489 -110
  547. package/dist/storage-guards.js +2 -2
  548. package/dist/storage.d.ts +6 -3
  549. package/dist/storage.js +38 -26
  550. package/dist/structured-attributes.d.ts +23 -1
  551. package/dist/structured-attributes.js +7 -1
  552. package/dist/summarizer.d.ts +3 -1
  553. package/dist/summarizer.js +11 -11
  554. package/dist/summary-snapshot.d.ts +3 -1
  555. package/dist/summary-snapshot.js +2 -2
  556. package/dist/temporal-index-batch.d.ts +1 -0
  557. package/dist/temporal-index-batch.js +10 -0
  558. package/dist/temporal-index-batch.js.map +1 -0
  559. package/dist/temporal-index-compat.d.ts +279 -1
  560. package/dist/temporal-index-compat.js +1 -1
  561. package/dist/temporal-index.d.ts +1 -225
  562. package/dist/temporal-index.js +35 -3
  563. package/dist/temporal-supersession.d.ts +5 -2
  564. package/dist/temporal-supersession.js +2 -2
  565. package/dist/temporal-timeline-recall.d.ts +3 -1
  566. package/dist/temporal-validity.d.ts +3 -1
  567. package/dist/threading.d.ts +3 -1
  568. package/dist/threading.js +2 -2
  569. package/dist/tier-migration.d.ts +5 -2
  570. package/dist/tier-routing.d.ts +3 -1
  571. package/dist/{tier-stats-KV7IWCJR.js → tier-stats-QEJSPFV2.js} +2 -2
  572. package/dist/tokens.js +3 -3
  573. package/dist/topics.d.ts +3 -1
  574. package/dist/transcript.d.ts +3 -1
  575. package/dist/transcript.js +2 -2
  576. package/dist/transfer/backup.js +3 -3
  577. package/dist/transfer/capsule-export.js +3 -3
  578. package/dist/transfer/capsule-import.js +3 -3
  579. package/dist/transfer/types.d.ts +90 -90
  580. package/dist/trust-score-stage.d.ts +75 -38
  581. package/dist/trust-score-stage.js +11 -3
  582. package/dist/trust-score.d.ts +3 -1
  583. package/dist/{types-Cg8q7W7_.d.ts → types-D_fG2ix8.d.ts} +39 -63
  584. package/dist/types-continuity.d.ts +52 -0
  585. package/dist/types-continuity.js +1 -0
  586. package/dist/types-continuity.js.map +1 -0
  587. package/dist/types.d.ts +3 -1
  588. package/dist/types.js +1 -1
  589. package/dist/utility-runtime.d.ts +3 -1
  590. package/dist/utils/serialize-mutations.d.ts +31 -2
  591. package/dist/utils/serialize-mutations.js +1 -1
  592. package/dist/verified-recall.js +36 -26
  593. package/dist/write-envelope.d.ts +282 -0
  594. package/dist/write-envelope.js +35 -0
  595. package/dist/write-envelope.js.map +1 -0
  596. package/dist/write-quarantine.d.ts +79 -0
  597. package/dist/write-quarantine.js +11 -0
  598. package/dist/write-quarantine.js.map +1 -0
  599. package/dist/write-rate-limiter.d.ts +45 -0
  600. package/dist/write-rate-limiter.js +9 -0
  601. package/dist/write-rate-limiter.js.map +1 -0
  602. package/package.json +37 -2
  603. package/src/access-admin-ops-surface.ts +17 -7
  604. package/src/access-boundary.test.ts +28 -0
  605. package/src/access-boundary.ts +31 -2
  606. package/src/access-citation.test.ts +72 -0
  607. package/src/access-citation.ts +139 -0
  608. package/src/access-errors.ts +21 -0
  609. package/src/access-fingerprint-parity.test.ts +211 -0
  610. package/src/access-http-cancellation.test.ts +59 -21
  611. package/src/access-http.test.ts +90 -0
  612. package/src/access-http.ts +79 -79
  613. package/src/access-mcp-cancellation.test.ts +16 -7
  614. package/src/access-memory-search-fanout.test.ts +220 -0
  615. package/src/access-memory-search-fanout.ts +168 -0
  616. package/src/access-observe-quarantine.test.ts +120 -0
  617. package/src/access-observe-write-surface.ts +130 -11
  618. package/src/access-operations-batch.ts +2 -0
  619. package/src/access-recall-concurrency.ts +773 -0
  620. package/src/access-recall-response.ts +307 -0
  621. package/src/access-recall-surface.ts +100 -252
  622. package/src/access-service-coding-write.test.ts +22 -4
  623. package/src/access-service-health.test.ts +49 -0
  624. package/src/access-service-namespace.test.ts +486 -8
  625. package/src/access-service-observe-scope.test.ts +4 -0
  626. package/src/access-service-recall-concurrency.test.ts +1990 -0
  627. package/src/access-service.ts +182 -175
  628. package/src/access-surface-catalog.ts +1 -0
  629. package/src/access-token-capabilities.ts +16 -9
  630. package/src/active-recall.test.ts +35 -0
  631. package/src/active-recall.ts +7 -0
  632. package/src/bounded-jsonl-state.ts +93 -0
  633. package/src/buffer-session.test.ts +422 -5
  634. package/src/buffer-surprise-trigger.test.ts +41 -0
  635. package/src/buffer.ts +218 -3
  636. package/src/capabilities-cluster-b.test.ts +1 -0
  637. package/src/capabilities.ts +5 -6
  638. package/src/cli.ts +21 -22
  639. package/src/coding/architecture-surfaces.test.ts +6 -3
  640. package/src/coding/architecture-surfaces.ts +36 -25
  641. package/src/coding/decision-surfaces.ts +42 -34
  642. package/src/compounding/engine.test.ts +5 -1
  643. package/src/compounding/engine.ts +7 -7
  644. package/src/config-qmd.ts +89 -0
  645. package/src/config.test.ts +136 -0
  646. package/src/config.ts +113 -118
  647. package/src/connector-provenance-lifecycle.test.ts +4 -4
  648. package/src/connectors/coerce.test.ts +131 -0
  649. package/src/connectors/coerce.ts +80 -7
  650. package/src/contradiction/contradiction.test.ts +10 -6
  651. package/src/contradiction/resolution.ts +17 -4
  652. package/src/correction/correction-access-wiring.ts +62 -18
  653. package/src/cross-namespace-budget.test.ts +35 -0
  654. package/src/cross-namespace-budget.ts +86 -19
  655. package/src/explicit-capture.ts +54 -17
  656. package/src/extraction.ts +2 -3
  657. package/src/faithfulness-graph-guard.test.ts +16 -69
  658. package/src/graph-recall.test.ts +31 -0
  659. package/src/index.ts +22 -2
  660. package/src/local-llm.ts +4 -6
  661. package/src/logger.ts +16 -0
  662. package/src/maintenance/dreams-ledger.ts +100 -49
  663. package/src/maintenance/rebuild-memory-lifecycle-ledger-cli.ts +77 -0
  664. package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +373 -9
  665. package/src/memory-lifecycle-ledger-utils.ts +51 -5
  666. package/src/namespaces/principal.test.ts +37 -1
  667. package/src/namespaces/principal.ts +48 -0
  668. package/src/namespaces/search.test.ts +79 -5
  669. package/src/namespaces/search.ts +59 -6
  670. package/src/namespaces/storage.ts +43 -1
  671. package/src/offline-sync-exclude-globs.ts +58 -0
  672. package/src/offline-sync-impression-drain.test.ts +316 -0
  673. package/src/offline-sync-impression-drain.ts +260 -0
  674. package/src/offline-sync.test.ts +32 -5
  675. package/src/offline-sync.ts +1 -14
  676. package/src/operator-toolkit.ts +1 -1
  677. package/src/orchestration/batch-deindex-flush.test.ts +146 -0
  678. package/src/orchestration/consolidation-run.ts +96 -85
  679. package/src/orchestration/extraction-envelope.ts +94 -0
  680. package/src/orchestration/extraction-persist-promotion.ts +134 -0
  681. package/src/orchestration/extraction-persist.ts +325 -260
  682. package/src/orchestration/extraction-run.test.ts +1 -1
  683. package/src/orchestration/extraction-run.ts +2 -2
  684. package/src/orchestration/graph-recall-coordinator.ts +18 -7
  685. package/src/orchestration/lifecycle-policy-coordinator.ts +63 -48
  686. package/src/orchestration/maintenance.test.ts +2103 -3
  687. package/src/orchestration/maintenance.ts +574 -2
  688. package/src/orchestration/namespace-read-fanout.ts +14 -8
  689. package/src/orchestration/orchestrator-helpers.ts +8 -1
  690. package/src/orchestration/orchestrator-init.ts +22 -6
  691. package/src/orchestration/orchestrator-namespace-scope.ts +71 -0
  692. package/src/orchestration/persistence-index.ts +64 -9
  693. package/src/orchestration/qmd-result-resolver.ts +27 -0
  694. package/src/orchestration/recall-entry.ts +34 -19
  695. package/src/orchestration/recall-internal.ts +207 -79
  696. package/src/orchestration/recall-rerank-coordinator.ts +229 -82
  697. package/src/orchestration/recall-result-formatter.ts +76 -20
  698. package/src/orchestration/recall-search-pipeline.test.ts +70 -0
  699. package/src/orchestration/recall-search-pipeline.ts +102 -129
  700. package/src/orchestration/recall-section-coordinator.ts +315 -85
  701. package/src/orchestration/semantic-consolidation-coordinator.ts +69 -37
  702. package/src/orchestration/session-context.ts +21 -0
  703. package/src/orchestration/workspace-ops.test.ts +348 -0
  704. package/src/orchestration/workspace-ops.ts +168 -34
  705. package/src/orchestrator-chunked-hash-durability.test.ts +126 -0
  706. package/src/orchestrator-connector-dedup.test.ts +1061 -40
  707. package/src/orchestrator-flush.test.ts +155 -39
  708. package/src/orchestrator-nonchunked-hash-durability.test.ts +121 -0
  709. package/src/orchestrator-source-attribution.test.ts +9 -9
  710. package/src/orchestrator.ts +160 -149
  711. package/src/prioritized-embed.ts +123 -0
  712. package/src/proactive-contention.test.ts +80 -0
  713. package/src/proactive-contention.ts +39 -0
  714. package/src/procedural/procedure-miner.test.ts +19 -14
  715. package/src/procedural/procedure-miner.ts +44 -13
  716. package/src/qmd-client.test.ts +111 -1
  717. package/src/qmd-status.ts +186 -0
  718. package/src/qmd.ts +47 -47
  719. package/src/recall-budget-config.test.ts +30 -0
  720. package/src/recall-cold-deadline.test.ts +149 -0
  721. package/src/recall-concurrency-config.ts +28 -0
  722. package/src/recall-memory-map.ts +74 -0
  723. package/src/recall-rerank-coordinator.test.ts +508 -0
  724. package/src/recall-state.test.ts +825 -1
  725. package/src/recall-state.ts +406 -7
  726. package/src/recall-timings-access.test.ts +41 -0
  727. package/src/recall-timings.ts +16 -0
  728. package/src/relay/mission-access.test.ts +5 -5
  729. package/src/rerank.ts +22 -0
  730. package/src/retrieval-agents.test.ts +79 -0
  731. package/src/retrieval-agents.ts +71 -19
  732. package/src/salvage-envelope.ts +28 -0
  733. package/src/scopes/scope-plan.test.ts +42 -0
  734. package/src/scopes/scope-plan.ts +45 -0
  735. package/src/search/port.ts +13 -0
  736. package/src/secure-store/index.ts +1 -0
  737. package/src/secure-store/secure-fs.ts +48 -0
  738. package/src/secure-store/secure-store.test.ts +40 -0
  739. package/src/semantic-rule-promotion.ts +13 -4
  740. package/src/storage/content-hash-index.ts +655 -0
  741. package/src/storage/entity-timeline.ts +473 -0
  742. package/src/storage/memory-lifecycle-ledger-access.ts +603 -0
  743. package/src/storage/secure-line-reader.test.ts +197 -0
  744. package/src/storage/secure-line-reader.ts +181 -3
  745. package/src/storage-append-header-sniff.test.ts +195 -0
  746. package/src/storage-behavior-signals-cache.test.ts +237 -0
  747. package/src/storage-contract/cache-coherence.test.ts +96 -1
  748. package/src/storage-contract/content-hash.test.ts +47 -2
  749. package/src/storage-fact-hash-index-defer.test.ts +1200 -0
  750. package/src/storage-memory-lifecycle-ledger.test.ts +1146 -3
  751. package/src/storage.ts +882 -890
  752. package/src/structured-attributes.ts +52 -0
  753. package/src/temporal-index-batch.ts +112 -0
  754. package/src/temporal-index.test.ts +193 -0
  755. package/src/temporal-index.ts +49 -53
  756. package/src/testing/lifecycle-matrix.test.ts +212 -0
  757. package/src/testing/lifecycle-matrix.ts +271 -0
  758. package/src/testing/orchestrator-lite.ts +236 -0
  759. package/src/testing/subjects/dreams-ledger.test.ts +67 -0
  760. package/src/testing/subjects/extraction-lifecycle.test.ts +442 -0
  761. package/src/testing/subjects/lifecycle-ledger.test.ts +93 -0
  762. package/src/testing/subjects/recall-budget.test.ts +461 -0
  763. package/src/testing/subjects/serialized-write-chain.test.ts +224 -0
  764. package/src/trust-score-stage.test.ts +154 -0
  765. package/src/trust-score-stage.ts +216 -53
  766. package/src/types-continuity.ts +57 -0
  767. package/src/types.ts +51 -77
  768. package/src/utils/path-containment.test.ts +75 -0
  769. package/src/utils/path-containment.ts +76 -0
  770. package/src/utils/serialize-mutations.test.ts +122 -0
  771. package/src/utils/serialize-mutations.ts +68 -3
  772. package/src/wearables/memory-gen.test.ts +31 -9
  773. package/src/wearables/memory-gen.ts +95 -55
  774. package/src/wearables/pipeline.test.ts +10 -7
  775. package/src/wearables/service.test.ts +6 -8
  776. package/src/wearables/service.ts +2 -2
  777. package/src/write-envelope.extension.test.ts +111 -0
  778. package/src/write-envelope.test.ts +683 -0
  779. package/src/write-envelope.ts +902 -0
  780. package/src/write-quarantine.test.ts +193 -0
  781. package/src/write-quarantine.ts +241 -0
  782. package/src/write-rate-limiter.test.ts +105 -0
  783. package/src/write-rate-limiter.ts +135 -0
  784. package/src/write-sealed-parity.test.ts +204 -0
  785. package/dist/chunk-2VN4JAX7.js.map +0 -1
  786. package/dist/chunk-37CTGERM.js.map +0 -1
  787. package/dist/chunk-3IY64MV6.js.map +0 -1
  788. package/dist/chunk-BCDKBDSY.js.map +0 -1
  789. package/dist/chunk-BFPETA3S.js.map +0 -1
  790. package/dist/chunk-BFVEEB7W.js.map +0 -1
  791. package/dist/chunk-BS4SGLWV.js.map +0 -1
  792. package/dist/chunk-DCFV7A7H.js.map +0 -1
  793. package/dist/chunk-DYP3YYJJ.js.map +0 -1
  794. package/dist/chunk-E5BK6CGV.js +0 -335
  795. package/dist/chunk-E5BK6CGV.js.map +0 -1
  796. package/dist/chunk-FTYDWKO6.js.map +0 -1
  797. package/dist/chunk-GWTFLF2P.js.map +0 -1
  798. package/dist/chunk-IKQTFQMI.js.map +0 -1
  799. package/dist/chunk-INELTPRG.js.map +0 -1
  800. package/dist/chunk-J2HSAU72.js.map +0 -1
  801. package/dist/chunk-JREB6UFH.js.map +0 -1
  802. package/dist/chunk-K7LOWSLU.js.map +0 -1
  803. package/dist/chunk-KQDNAXOM.js.map +0 -1
  804. package/dist/chunk-KSBEEMQF.js.map +0 -1
  805. package/dist/chunk-KSNVDPDF.js.map +0 -1
  806. package/dist/chunk-LC7OODWZ.js.map +0 -1
  807. package/dist/chunk-LTJAMRGI.js.map +0 -1
  808. package/dist/chunk-LZOV7MX7.js.map +0 -1
  809. package/dist/chunk-NWTGD4AN.js.map +0 -1
  810. package/dist/chunk-ODPLEWB6.js.map +0 -1
  811. package/dist/chunk-OVJ2HIPE.js.map +0 -1
  812. package/dist/chunk-PBSAPHHA.js.map +0 -1
  813. package/dist/chunk-PHK3HARR.js +0 -32
  814. package/dist/chunk-PHK3HARR.js.map +0 -1
  815. package/dist/chunk-PLQE6MJA.js.map +0 -1
  816. package/dist/chunk-QKQYXZVS.js.map +0 -1
  817. package/dist/chunk-QQGPUKMT.js.map +0 -1
  818. package/dist/chunk-RANHFI3P.js +0 -8
  819. package/dist/chunk-RANHFI3P.js.map +0 -1
  820. package/dist/chunk-RAR2BSEM.js.map +0 -1
  821. package/dist/chunk-RULE4VG5.js.map +0 -1
  822. package/dist/chunk-SVOZFLIQ.js +0 -16
  823. package/dist/chunk-SVOZFLIQ.js.map +0 -1
  824. package/dist/chunk-T7Y5KPLN.js.map +0 -1
  825. package/dist/chunk-TXLGHDHS.js.map +0 -1
  826. package/dist/chunk-VDW4VU7B.js.map +0 -1
  827. package/dist/chunk-VSMRDBFT.js +0 -17
  828. package/dist/chunk-VSMRDBFT.js.map +0 -1
  829. package/dist/chunk-X64YLC24.js.map +0 -1
  830. package/dist/chunk-XDSXEKYK.js +0 -118
  831. package/dist/chunk-XDSXEKYK.js.map +0 -1
  832. package/dist/chunk-YF6FMLBT.js.map +0 -1
  833. package/dist/resolution-VH4NGENZ.js +0 -12
  834. /package/dist/{capsule-crypto-CZJSLEFG.js.map → access-citation.js.map} +0 -0
  835. /package/dist/{contradiction-scan-J57T5QV7.js.map → access-memory-search-fanout.js.map} +0 -0
  836. /package/dist/{dreams-ledger-6UODQOX6.js.map → access-recall-concurrency.js.map} +0 -0
  837. /package/dist/{graph-edge-decay-IOGBBAGC.js.map → access-recall-response.js.map} +0 -0
  838. /package/dist/{resolution-VH4NGENZ.js.map → bounded-jsonl-state.js.map} +0 -0
  839. /package/dist/{chunk-A3GOMRJG.js.map → chunk-23L3IXFD.js.map} +0 -0
  840. /package/dist/{chunk-MRHFJV44.js.map → chunk-2DQ2XREU.js.map} +0 -0
  841. /package/dist/{chunk-L2B3EE7B.js.map → chunk-2QMKMVHH.js.map} +0 -0
  842. /package/dist/{chunk-VJVNLNDQ.js.map → chunk-2UFO7X4Q.js.map} +0 -0
  843. /package/dist/{chunk-2MR3MFQB.js.map → chunk-2VEOKUPP.js.map} +0 -0
  844. /package/dist/{chunk-RHOZ5LLO.js.map → chunk-347WD2LE.js.map} +0 -0
  845. /package/dist/{chunk-HDTQVNWD.js.map → chunk-3QAH2S33.js.map} +0 -0
  846. /package/dist/{chunk-LRNMRXJO.js.map → chunk-3Y224NYC.js.map} +0 -0
  847. /package/dist/{chunk-VFSP73LP.js.map → chunk-45GF7Y3V.js.map} +0 -0
  848. /package/dist/{chunk-OEHCMALU.js.map → chunk-5I4M26Q7.js.map} +0 -0
  849. /package/dist/{chunk-2AZXIZEN.js.map → chunk-5Q7EVV4X.js.map} +0 -0
  850. /package/dist/{chunk-PUBTHW5O.js.map → chunk-6DRPPQEJ.js.map} +0 -0
  851. /package/dist/{chunk-FDCTQWLW.js.map → chunk-6O22TZSB.js.map} +0 -0
  852. /package/dist/{chunk-ZQ7UBUZ6.js.map → chunk-6QYST5XN.js.map} +0 -0
  853. /package/dist/{chunk-W4PGTAS2.js.map → chunk-6WAFYNVT.js.map} +0 -0
  854. /package/dist/{chunk-R5VAVVHP.js.map → chunk-72A4L5JJ.js.map} +0 -0
  855. /package/dist/{chunk-3FAMU5TX.js.map → chunk-A6USBZTO.js.map} +0 -0
  856. /package/dist/{chunk-ZHIVCODT.js.map → chunk-A72SWTWW.js.map} +0 -0
  857. /package/dist/{chunk-FC77VUX5.js.map → chunk-A7Q43EUZ.js.map} +0 -0
  858. /package/dist/{chunk-UJBESW6X.js.map → chunk-AE7WMV4V.js.map} +0 -0
  859. /package/dist/{chunk-A5UXZRRM.js.map → chunk-AJ7QCSIS.js.map} +0 -0
  860. /package/dist/{chunk-FNMFJWBY.js.map → chunk-ANEUPF6O.js.map} +0 -0
  861. /package/dist/{chunk-2A3OXAP2.js.map → chunk-B7RWBZXW.js.map} +0 -0
  862. /package/dist/{chunk-74F5STS4.js.map → chunk-BLAKS3CP.js.map} +0 -0
  863. /package/dist/{chunk-M7VGG3ID.js.map → chunk-BV5WMSIJ.js.map} +0 -0
  864. /package/dist/{chunk-2BFLDH5F.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  865. /package/dist/{chunk-UXKMMNJD.js.map → chunk-C23BYTJV.js.map} +0 -0
  866. /package/dist/{chunk-JZHHREBL.js.map → chunk-C3AKM55W.js.map} +0 -0
  867. /package/dist/{chunk-RP7YXA67.js.map → chunk-C5JF6EZ7.js.map} +0 -0
  868. /package/dist/{chunk-EHCONI6E.js.map → chunk-CQMEM5CC.js.map} +0 -0
  869. /package/dist/{chunk-PBNZVPFS.js.map → chunk-CXZQOVIE.js.map} +0 -0
  870. /package/dist/{chunk-7N2RUBAP.js.map → chunk-DDA47TES.js.map} +0 -0
  871. /package/dist/{chunk-64SE4X5G.js.map → chunk-DEBHXHJR.js.map} +0 -0
  872. /package/dist/{chunk-EHK6KZHK.js.map → chunk-DNHVPZOD.js.map} +0 -0
  873. /package/dist/{chunk-437S3G37.js.map → chunk-DQEMWVMT.js.map} +0 -0
  874. /package/dist/{chunk-LZZNTPLR.js.map → chunk-DX3XRGLH.js.map} +0 -0
  875. /package/dist/{chunk-DZKHSDOM.js.map → chunk-ES36HTSC.js.map} +0 -0
  876. /package/dist/{chunk-TN7THW5U.js.map → chunk-ET356KSB.js.map} +0 -0
  877. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  878. /package/dist/{chunk-DMSDUGDM.js.map → chunk-F7GAIWFA.js.map} +0 -0
  879. /package/dist/{chunk-G6XXLKC5.js.map → chunk-FFPJINJE.js.map} +0 -0
  880. /package/dist/{chunk-G4CN3ZXL.js.map → chunk-FUTF72MJ.js.map} +0 -0
  881. /package/dist/{chunk-HF77M34J.js.map → chunk-GFPZS3F5.js.map} +0 -0
  882. /package/dist/{chunk-G6NKALRN.js.map → chunk-H4WG3UQZ.js.map} +0 -0
  883. /package/dist/{chunk-UDQUSU27.js.map → chunk-HNZKVLAN.js.map} +0 -0
  884. /package/dist/{chunk-5EZXHU36.js.map → chunk-HYQJQGD3.js.map} +0 -0
  885. /package/dist/{chunk-TRWPCR6P.js.map → chunk-JECBQBEX.js.map} +0 -0
  886. /package/dist/{chunk-E6CBU7XP.js.map → chunk-JYIFGGEM.js.map} +0 -0
  887. /package/dist/{chunk-VA4WSW54.js.map → chunk-JYIJNNN3.js.map} +0 -0
  888. /package/dist/{chunk-L5HJQC36.js.map → chunk-K2TDK7GG.js.map} +0 -0
  889. /package/dist/{chunk-KDXVOFYY.js.map → chunk-KAVBJSBQ.js.map} +0 -0
  890. /package/dist/{chunk-4OKLXWDZ.js.map → chunk-KNB7IBBU.js.map} +0 -0
  891. /package/dist/{chunk-QLULYKWZ.js.map → chunk-KSXJOC4F.js.map} +0 -0
  892. /package/dist/{chunk-2S6QHZGJ.js.map → chunk-L2DPF4DF.js.map} +0 -0
  893. /package/dist/{chunk-JI5AVXYO.js.map → chunk-LEPOP46W.js.map} +0 -0
  894. /package/dist/{chunk-O7BBFJLP.js.map → chunk-LTAVSOZW.js.map} +0 -0
  895. /package/dist/{chunk-2IZAGAJR.js.map → chunk-LULR4IUW.js.map} +0 -0
  896. /package/dist/{chunk-WMWVO45V.js.map → chunk-MC6XO7T4.js.map} +0 -0
  897. /package/dist/{chunk-D6RIFG4O.js.map → chunk-MNB5RMAY.js.map} +0 -0
  898. /package/dist/{chunk-Q5WG43OP.js.map → chunk-MYFQ3ED4.js.map} +0 -0
  899. /package/dist/{chunk-V3UE5I5F.js.map → chunk-MYVPLJOO.js.map} +0 -0
  900. /package/dist/{chunk-MTWKDOVO.js.map → chunk-NLE6TSLG.js.map} +0 -0
  901. /package/dist/{chunk-DBRYEIGY.js.map → chunk-OJP3N7UK.js.map} +0 -0
  902. /package/dist/{chunk-SMX5267P.js.map → chunk-OZKOPQCM.js.map} +0 -0
  903. /package/dist/{chunk-JCK7V6SN.js.map → chunk-P65YJEEL.js.map} +0 -0
  904. /package/dist/{chunk-MTR7BZQN.js.map → chunk-PBGWYM3H.js.map} +0 -0
  905. /package/dist/{chunk-AXTXN4T6.js.map → chunk-PWFCHOB3.js.map} +0 -0
  906. /package/dist/{chunk-FDPZVY6D.js.map → chunk-QFN4U7AG.js.map} +0 -0
  907. /package/dist/{chunk-K2ZLHESQ.js.map → chunk-QIEUU4UK.js.map} +0 -0
  908. /package/dist/{chunk-3D6AFGQR.js.map → chunk-QVT3E4CE.js.map} +0 -0
  909. /package/dist/{chunk-SFQ6QNL7.js.map → chunk-R6YJI3HE.js.map} +0 -0
  910. /package/dist/{chunk-5CJVLG3H.js.map → chunk-RFDD3B7W.js.map} +0 -0
  911. /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
  912. /package/dist/{chunk-FNZQGN76.js.map → chunk-S2BBISHU.js.map} +0 -0
  913. /package/dist/{chunk-IALLX7EE.js.map → chunk-S2FSBU4H.js.map} +0 -0
  914. /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
  915. /package/dist/{chunk-DPAENM7O.js.map → chunk-U3ZAVRP3.js.map} +0 -0
  916. /package/dist/{chunk-4KJLYTLS.js.map → chunk-V57NLO5P.js.map} +0 -0
  917. /package/dist/{chunk-FLVL4L3L.js.map → chunk-VDX2J7OX.js.map} +0 -0
  918. /package/dist/{chunk-AJLLIIML.js.map → chunk-W4FBGYGK.js.map} +0 -0
  919. /package/dist/{chunk-6SXVCD7W.js.map → chunk-W7IGLX4G.js.map} +0 -0
  920. /package/dist/{chunk-KAWTOYAW.js.map → chunk-WLZYGLJ4.js.map} +0 -0
  921. /package/dist/{chunk-RO4LQGT3.js.map → chunk-WON4APQY.js.map} +0 -0
  922. /package/dist/{chunk-PQVK2S3J.js.map → chunk-WZFAPHIK.js.map} +0 -0
  923. /package/dist/{chunk-KQPJLK3X.js.map → chunk-XL24QQ63.js.map} +0 -0
  924. /package/dist/{chunk-RVZRYUQH.js.map → chunk-YROFNEG5.js.map} +0 -0
  925. /package/dist/{chunk-VRAD2FGO.js.map → chunk-Z54EM5YZ.js.map} +0 -0
  926. /package/dist/{first-start-migration-TI67YMLG.js.map → first-start-migration-CSRHCJIQ.js.map} +0 -0
  927. /package/dist/{forget-CQCLB5LB.js.map → forget-HRPLVB3W.js.map} +0 -0
  928. /package/dist/{purge-NDWV6WYD.js.map → purge-IRF47ZTX.js.map} +0 -0
  929. /package/dist/{tier-stats-KV7IWCJR.js.map → tier-stats-QEJSPFV2.js.map} +0 -0
@@ -0,0 +1,902 @@
1
+ /**
2
+ * Sealed memory-write envelope (issue #1989, umbrella #1988).
3
+ *
4
+ * THE single stamping point for cross-cutting memory-creation fields.
5
+ *
6
+ * Why this exists: PR #1852 needed 27 rework commits because adding one
7
+ * cross-cutting field (`sourceConnector`) required hand-editing every
8
+ * write call site and every idempotency payload, and reviewers discovered
9
+ * missed sites one round at a time. This module removes the fan-out:
10
+ *
11
+ * 1. `composeMemoryEnvelope()` is the only way to mint a
12
+ * `SealedMemoryEnvelope` — the brand is a non-exported `unique symbol`,
13
+ * so a hand-built object literal fails `tsc` (`npm run check-types`
14
+ * is already a required repo-wide gate; the type system IS the fence).
15
+ * 2. `buildWriteIdempotencyPayload()` derives every access-surface
16
+ * idempotency payload from ONE ordered field registry
17
+ * (`WRITE_FINGERPRINT_FIELDS`). Adding a fingerprint-relevant field is
18
+ * a one-line registry change picked up by every surface; forgetting to
19
+ * classify a new `MemoryWriteInput` field is a compile error (see the
20
+ * exhaustiveness guards at the bottom of this file).
21
+ *
22
+ * PR1 scope (no call-site changes): the composer, the registry, and the
23
+ * payload builder, fully tested. PR2–PR4 migrate storage entry points and
24
+ * the write call sites onto this module (see #1989 for the slicing).
25
+ */
26
+
27
+ import type { MemoryCategory } from "./types.js";
28
+ import { normalizeTags } from "./recall-tag-filter.js";
29
+ import { parseFlexibleIsoTimestamp } from "./utils/iso-timestamp.js";
30
+ import { assemblePersistedBody } from "./structured-attributes.js";
31
+
32
+ // ---------------------------------------------------------------------------
33
+ // Input surface
34
+ // ---------------------------------------------------------------------------
35
+
36
+ /**
37
+ * Every cross-cutting memory-creation field lives HERE and only here.
38
+ *
39
+ * When you add a field you MUST also add it to either
40
+ * `WRITE_FINGERPRINT_FIELDS` or `FINGERPRINT_EXEMPT_FIELDS` — the
41
+ * exhaustiveness guard below makes forgetting a compile error.
42
+ */
43
+ export interface MemoryWriteInput {
44
+ /** Raw memory content. Must be non-empty after trimming. */
45
+ content: string;
46
+ /** Memory category — validated against the canonical category set. */
47
+ category: MemoryCategory;
48
+ /** Free-form labels; normalized (trim/dedupe) and capped, see TAG_LIMITS. */
49
+ tags?: string[];
50
+ /** String→string structured attributes; non-string values are rejected. */
51
+ structuredAttributes?: Record<string, string>;
52
+ /** Entity file reference (e.g. `person-jane-doe`). */
53
+ entityRef?: string;
54
+ /** Extraction confidence in [0, 1]. */
55
+ confidence?: number;
56
+ /** Opaque TTL expression (e.g. `90d` or an ISO date) — validated non-empty. */
57
+ ttl?: string;
58
+ /** Event-time validity start (ISO 8601). */
59
+ validAt?: string;
60
+ /** Connector identity that produced this write (issue #1852). */
61
+ sourceConnector?: string;
62
+ /** Human-readable provenance note. */
63
+ sourceReason?: string;
64
+ }
65
+
66
+ /** Context supplied by the write path, not by the payload author. */
67
+ export interface WriteContext {
68
+ /** Frontmatter `source` string (e.g. `extraction`, `wearable:bee`). */
69
+ source: string;
70
+ /** Clock override for tests. */
71
+ now?: () => Date;
72
+ }
73
+
74
+ /** Scope facts that participate in idempotency but never in frontmatter. */
75
+ export interface FingerprintScope {
76
+ /** Access surface performing the write (e.g. `memory_store`, `observe`). */
77
+ surface: string;
78
+ namespace?: string;
79
+ principal?: string;
80
+ codingContext?: string;
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // Normalization limits (single source of truth — docs/tags.md contract)
85
+ // ---------------------------------------------------------------------------
86
+
87
+ export const TAG_LIMITS = Object.freeze({
88
+ /** Maximum number of tags persisted per memory. */
89
+ maxTags: 50,
90
+ /** Maximum length of a single tag. */
91
+ maxTagLength: 256,
92
+ });
93
+
94
+ export const STRUCTURED_ATTRIBUTE_LIMITS = Object.freeze({
95
+ /** Maximum number of structured attributes per memory. */
96
+ maxEntries: 64,
97
+ /** Maximum length of one attribute key. */
98
+ maxKeyLength: 128,
99
+ /** Maximum length of one attribute value. */
100
+ maxValueLength: 1024,
101
+ });
102
+
103
+ const MEMORY_CATEGORY_TABLE: Record<MemoryCategory, true> = {
104
+ fact: true,
105
+ preference: true,
106
+ correction: true,
107
+ entity: true,
108
+ decision: true,
109
+ relationship: true,
110
+ principle: true,
111
+ commitment: true,
112
+ moment: true,
113
+ skill: true,
114
+ rule: true,
115
+ procedure: true,
116
+ reasoning_trace: true,
117
+ };
118
+
119
+ const MEMORY_CATEGORY_NAMES = Object.keys(MEMORY_CATEGORY_TABLE).sort();
120
+
121
+ export function isMemoryCategory(value: string): value is MemoryCategory {
122
+ return Object.prototype.hasOwnProperty.call(MEMORY_CATEGORY_TABLE, value);
123
+ }
124
+
125
+ // ---------------------------------------------------------------------------
126
+ // Sealed envelope
127
+ // ---------------------------------------------------------------------------
128
+
129
+ declare const sealed: unique symbol;
130
+
131
+ /**
132
+ * A normalized, validated memory-write envelope.
133
+ *
134
+ * Opaque: only `composeMemoryEnvelope()` can mint one. Storage creation
135
+ * entry points accept this type (PR2), so every write path is forced
136
+ * through the composer at compile time.
137
+ */
138
+ export interface SealedMemoryEnvelope {
139
+ readonly [sealed]: true;
140
+ /**
141
+ * Caller-supplied content VERBATIM (validated non-empty-after-trim).
142
+ * `StorageManager.writeMemory` persists content byte-for-byte (callers
143
+ * that trim, e.g. explicit capture, do so before composing), so the
144
+ * envelope must not transform it — the earlier compose-time trim/sanitize
145
+ * broke byte-parity with extraction writes and was removed in PR2.
146
+ */
147
+ readonly content: string;
148
+ /**
149
+ * The exact body persistence will write: attribute-suffix enrichment then
150
+ * combined sanitization, produced by the SAME `assemblePersistedBody`
151
+ * helper `writeMemory` uses (issue #1989 PR2; AGENTS.md §13). This is the
152
+ * form write-idempotency fingerprints hash.
153
+ */
154
+ readonly persistedBody: string;
155
+ /** Injection patterns matched during body assembly (empty = clean). */
156
+ readonly sanitizeViolations: readonly string[];
157
+ /**
158
+ * Salvage-mode hygiene notes (empty in strict mode): each dropped/clamped
159
+ * invalid optional field is recorded here — visible, never silent
160
+ * (repo rule 34). Callers persisting machine-generated input log these.
161
+ */
162
+ readonly salvageNotes: readonly string[];
163
+ readonly category: MemoryCategory;
164
+ readonly tags: readonly string[];
165
+ /**
166
+ * CANONICAL attributes (keys trim+lowercase, values trim) — the form
167
+ * fingerprints and downstream consumers use; stable across caller casing.
168
+ */
169
+ readonly structuredAttributes: Readonly<Record<string, string>> | undefined;
170
+ /**
171
+ * The validated ORIGINAL attribute map, byte-preserved. `writeMemory`
172
+ * persists frontmatter attributes raw (canonicalizing only the body
173
+ * suffix via normalizeAttributePairs) — a pre-existing raw/canonical
174
+ * inconsistency (supersession keys read the raw form). The sealed path
175
+ * preserves those bytes; canonicalizing the frontmatter at the storage
176
+ * boundary is a follow-up once the legacy path retires (#1989 PR4).
177
+ */
178
+ readonly rawStructuredAttributes: Readonly<Record<string, string>> | undefined;
179
+ readonly entityRef: string | undefined;
180
+ readonly confidence: number | undefined;
181
+ readonly ttl: string | undefined;
182
+ readonly validAt: string | undefined;
183
+ readonly sourceConnector: string | undefined;
184
+ readonly sourceReason: string | undefined;
185
+ readonly source: string;
186
+ /** ISO timestamp the envelope was composed (from ctx.now). */
187
+ readonly composedAt: string;
188
+ }
189
+
190
+ function fail(field: string, message: string): never {
191
+ throw new Error(`composeMemoryEnvelope: ${field} ${message}`);
192
+ }
193
+
194
+ /**
195
+ * Compose-time input hygiene mode (issue #1989 PR2, review round on #2014).
196
+ *
197
+ * - `strict` (default): every invalid field throws — correct for OPERATOR
198
+ * and API input (explicit capture, memory_store), where a bad value is a
199
+ * caller bug that must surface.
200
+ * - `salvage`: for MACHINE-GENERATED input (LLM extraction, wearable
201
+ * ingestion). One malformed fact from an extractor must not abort a whole
202
+ * persistence batch that legacy `writeMemory` would have accepted.
203
+ * Invalid tags/attributes/optional fields are DROPPED with a note pushed
204
+ * to `envelope.salvageNotes` — visible, never silent (repo rule 34);
205
+ * callers log the notes. Content, category, ctx.source, and validAt stay
206
+ * FATAL in both modes (legacy writeMemory also throws on bad validAt, and
207
+ * a write without valid content/category cannot proceed).
208
+ */
209
+ export interface ComposeEnvelopeOptions {
210
+ salvage?: boolean;
211
+ }
212
+
213
+ /** Internal reporter: throws in strict mode, records a note in salvage. */
214
+ interface Hygiene {
215
+ salvage: boolean;
216
+ notes: string[];
217
+ flag(field: string, message: string): void;
218
+ }
219
+
220
+ function makeHygiene(salvage: boolean): Hygiene {
221
+ const notes: string[] = [];
222
+ return {
223
+ salvage,
224
+ notes,
225
+ flag(field: string, message: string): void {
226
+ if (!salvage) fail(field, message);
227
+ notes.push(`${field} ${message}`);
228
+ },
229
+ };
230
+ }
231
+
232
+ /**
233
+ * Validate and CANONICALIZE `validAt` via the repo's shared flexible ISO
234
+ * parser (`utils/iso-timestamp.ts`) — the same family durable writes use, so
235
+ * the envelope can never accept a value storage would reject or reinterpret
236
+ * (review findings on #1998: no second validation convention; reduced
237
+ * precision like `2026-07-17T09:30Z` is valid; offsets are bounded ±14:00;
238
+ * `Date.parse` alone is not an ISO validator).
239
+ *
240
+ * Canonical form is the epoch round-trip (`Date.toISOString()`), so
241
+ * fingerprints are identical for `...T09:30Z`, `...T09:30:00.000Z`, and the
242
+ * same instant expressed with an offset (§13 hash-consistency).
243
+ */
244
+ function validateIsoTimestamp(field: string, value: string): string {
245
+ const trimmed = value.trim();
246
+ if (trimmed.length === 0) fail(field, "must be a non-empty ISO 8601 timestamp");
247
+ const epochMs = parseFlexibleIsoTimestamp(trimmed);
248
+ if (epochMs === null) {
249
+ fail(
250
+ field,
251
+ `is not a valid ISO 8601 date/timestamp: ${JSON.stringify(value)} (date-only, reduced precision, Z, and ±HH:MM offsets up to ±14:00 are accepted; calendar overflow is not)`,
252
+ );
253
+ }
254
+ return new Date(epochMs).toISOString();
255
+ }
256
+
257
+ function normalizeEnvelopeTags(raw: string[] | undefined, hygiene: Hygiene): readonly string[] {
258
+ if (raw === undefined) return Object.freeze([]);
259
+ if (!Array.isArray(raw)) {
260
+ hygiene.flag("tags", "must be an array of strings — dropped");
261
+ return Object.freeze([]);
262
+ }
263
+ const usable: string[] = [];
264
+ for (const tag of raw) {
265
+ if (typeof tag !== "string") {
266
+ hygiene.flag("tags", `entries must be strings (got ${typeof tag})`);
267
+ continue;
268
+ }
269
+ if (tag.trim().length > TAG_LIMITS.maxTagLength) {
270
+ hygiene.flag("tags", `entry exceeds ${TAG_LIMITS.maxTagLength} characters: ${JSON.stringify(tag.slice(0, 40))}…`);
271
+ continue;
272
+ }
273
+ usable.push(tag);
274
+ }
275
+ let normalized = normalizeTags(usable) ?? [];
276
+ if (normalized.length > TAG_LIMITS.maxTags) {
277
+ hygiene.flag("tags", `exceed the ${TAG_LIMITS.maxTags}-tag limit (got ${normalized.length}) — keeping the first ${TAG_LIMITS.maxTags}`);
278
+ normalized = normalized.slice(0, TAG_LIMITS.maxTags);
279
+ }
280
+ return Object.freeze(normalized);
281
+ }
282
+
283
+ function normalizeStructuredAttributes(
284
+ raw: Record<string, string> | undefined,
285
+ hygiene: Hygiene,
286
+ ): { canonical: Readonly<Record<string, string>>; raw: Readonly<Record<string, string>> } | undefined {
287
+ if (raw === undefined) return undefined;
288
+ if (
289
+ raw === null ||
290
+ typeof raw !== "object" ||
291
+ Array.isArray(raw) ||
292
+ (Object.getPrototypeOf(raw) !== Object.prototype && Object.getPrototypeOf(raw) !== null)
293
+ ) {
294
+ // Map/Date/class instances have empty Object.entries() and would
295
+ // silently normalize to "no attributes" (review finding on #1998
296
+ // round 5) — never a plain pass-through.
297
+ hygiene.flag("structuredAttributes", "must be a plain object of string values (Map, Date, and class instances are rejected) — dropped");
298
+ return undefined;
299
+ }
300
+ let entries = Object.entries(raw);
301
+ if (entries.length === 0) return undefined;
302
+ if (entries.length > STRUCTURED_ATTRIBUTE_LIMITS.maxEntries) {
303
+ hygiene.flag(
304
+ "structuredAttributes",
305
+ `exceed the ${STRUCTURED_ATTRIBUTE_LIMITS.maxEntries}-entry limit (got ${entries.length}) — keeping the first ${STRUCTURED_ATTRIBUTE_LIMITS.maxEntries} in insertion order`,
306
+ );
307
+ entries = entries.slice(0, STRUCTURED_ATTRIBUTE_LIMITS.maxEntries);
308
+ }
309
+ // Keys that collide with Object.prototype machinery are REJECTED outright:
310
+ // `hashAccessIdempotencyPayload`'s stableStringify rebuilds objects with
311
+ // plain assignment, where a "__proto__" own property silently vanishes —
312
+ // so such a key can never round-trip through the fingerprint faithfully
313
+ // (review finding on #1998 round 3). Rejection beats smuggling (§1/§39).
314
+ const FORBIDDEN_ATTRIBUTE_KEYS = ["__proto__", "constructor", "prototype"];
315
+ const out: Record<string, string> = Object.create(null);
316
+ const survivingOriginal: Array<[string, string]> = [];
317
+ for (const [key, value] of entries) {
318
+ // Canonicalize exactly like storage's normalizeAttributePairs
319
+ // (storage.ts:1277): keys trim+lowercase, values trim — so the
320
+ // fingerprint and the persisted searchable form can never diverge
321
+ // (review finding on #1998; AGENTS.md §13 hash-consistency).
322
+ const cleanKey = key.trim().toLowerCase();
323
+ if (cleanKey.length === 0) {
324
+ hygiene.flag("structuredAttributes", "contain an empty key");
325
+ continue;
326
+ }
327
+ if (cleanKey.length > STRUCTURED_ATTRIBUTE_LIMITS.maxKeyLength) {
328
+ hygiene.flag("structuredAttributes", `key exceeds ${STRUCTURED_ATTRIBUTE_LIMITS.maxKeyLength} characters: ${JSON.stringify(cleanKey.slice(0, 40))}…`);
329
+ continue;
330
+ }
331
+ if (typeof value !== "string") {
332
+ hygiene.flag("structuredAttributes", `value for ${JSON.stringify(cleanKey)} must be a string (got ${typeof value}) — stringify numbers/booleans at the call site`);
333
+ continue;
334
+ }
335
+ const cleanValue = value.trim();
336
+ if (FORBIDDEN_ATTRIBUTE_KEYS.includes(cleanKey)) {
337
+ hygiene.flag(
338
+ "structuredAttributes",
339
+ `contain the reserved key ${JSON.stringify(cleanKey)} — prototype-machinery names cannot round-trip through fingerprint serialization`,
340
+ );
341
+ continue;
342
+ }
343
+ if (cleanValue.length > STRUCTURED_ATTRIBUTE_LIMITS.maxValueLength) {
344
+ hygiene.flag("structuredAttributes", `value for ${JSON.stringify(cleanKey)} exceeds ${STRUCTURED_ATTRIBUTE_LIMITS.maxValueLength} characters`);
345
+ continue;
346
+ }
347
+ if (Object.hasOwn(out, cleanKey)) {
348
+ hygiene.flag("structuredAttributes", `contain duplicate key after canonicalization (trim + lowercase): ${JSON.stringify(cleanKey)}`);
349
+ continue;
350
+ }
351
+ out[cleanKey] = cleanValue;
352
+ survivingOriginal.push([key, value]);
353
+ }
354
+ if (Object.keys(out).length === 0) return undefined;
355
+ // Copy onto a normal object so downstream JSON/stableStringify behavior is
356
+ // unchanged; keys are already validated. The RAW map carries only the
357
+ // SURVIVING original pairs — dropped entries must not reach frontmatter.
358
+ return {
359
+ canonical: Object.freeze({ ...out }),
360
+ raw: Object.freeze(Object.fromEntries(survivingOriginal)),
361
+ };
362
+ }
363
+
364
+ function normalizeOptionalString(
365
+ field: string,
366
+ value: string | undefined,
367
+ hygiene: Hygiene,
368
+ ): string | undefined {
369
+ if (value === undefined) return undefined;
370
+ if (typeof value !== "string") {
371
+ hygiene.flag(field, `must be a string (got ${typeof value}) — dropped`);
372
+ return undefined;
373
+ }
374
+ const trimmed = value.trim();
375
+ if (trimmed.length === 0) {
376
+ hygiene.flag(field, "must be non-empty when provided — dropped");
377
+ return undefined;
378
+ }
379
+ return trimmed;
380
+ }
381
+
382
+ /**
383
+ * Compose (normalize + validate + seal) a memory-write envelope.
384
+ *
385
+ * Strict mode (default) throws on any invalid input — never silently
386
+ * defaults (AGENTS.md §1/§39). Salvage mode (`{ salvage: true }`, for
387
+ * machine-generated input like LLM extraction) drops invalid OPTIONAL
388
+ * fields with notes on `envelope.salvageNotes` instead of aborting the
389
+ * batch; content/category/source/validAt stay fatal in both modes.
390
+ */
391
+ export function composeMemoryEnvelope(
392
+ input: MemoryWriteInput,
393
+ ctx: WriteContext,
394
+ opts: ComposeEnvelopeOptions = {},
395
+ ): SealedMemoryEnvelope {
396
+ if (input === null || typeof input !== "object") fail("input", "must be an object");
397
+ if (ctx === null || typeof ctx !== "object") fail("ctx", "must be an object");
398
+ const hygiene = makeHygiene(opts.salvage === true);
399
+
400
+ if (typeof input.content !== "string" || input.content.trim().length === 0) {
401
+ fail("content", "must be a non-empty string");
402
+ }
403
+ if (typeof input.category !== "string" || !isMemoryCategory(input.category)) {
404
+ fail(
405
+ "category",
406
+ `must be one of: ${MEMORY_CATEGORY_NAMES.join(", ")} (got ${JSON.stringify(input.category)})`,
407
+ );
408
+ }
409
+ if (typeof ctx.source !== "string" || ctx.source.trim().length === 0) {
410
+ fail("ctx.source", "must be a non-empty string");
411
+ }
412
+
413
+ let confidence: number | undefined;
414
+ if (input.confidence !== undefined) {
415
+ if (
416
+ typeof input.confidence !== "number" ||
417
+ !Number.isFinite(input.confidence) ||
418
+ input.confidence < 0 ||
419
+ input.confidence > 1
420
+ ) {
421
+ hygiene.flag(
422
+ "confidence",
423
+ `must be a finite number within [0, 1] (got ${String(input.confidence)}) — dropped (storage defaults apply)`,
424
+ );
425
+ } else {
426
+ confidence = input.confidence;
427
+ }
428
+ }
429
+
430
+ // validAt stays FATAL in salvage too: legacy writeMemory throws on an
431
+ // invalid validAt (normalizeMemoryWriteTimestamp), so salvage-dropping it
432
+ // would CHANGE behavior rather than preserve it.
433
+ const validAt =
434
+ input.validAt === undefined ? undefined : validateIsoTimestamp("validAt", input.validAt);
435
+
436
+ const now = ctx.now ? ctx.now() : new Date();
437
+ if (!(now instanceof Date) || Number.isNaN(now.getTime())) {
438
+ fail("ctx.now", "must return a valid Date");
439
+ }
440
+
441
+ const attributes = normalizeStructuredAttributes(input.structuredAttributes, hygiene);
442
+ // Assemble the EXACT persisted form (attribute suffix + combined sanitize)
443
+ // with the same helper writeMemory uses — fingerprints hash this form, so
444
+ // envelope and storage cannot diverge (§13; #1998 round-8 thread resolved
445
+ // here in PR2 as promised). writeMemory assembles from the RAW map;
446
+ // normalizeAttributePairs canonicalizes internally, so raw and canonical
447
+ // maps yield the same suffix — asserted by the parity suite.
448
+ const assembled = assemblePersistedBody(
449
+ input.content,
450
+ attributes ? { ...attributes.raw } : undefined,
451
+ );
452
+ if (assembled.text.trim().length === 0) {
453
+ fail("content", "is empty after sanitization");
454
+ }
455
+
456
+ const body = {
457
+ content: input.content,
458
+ persistedBody: assembled.text,
459
+ sanitizeViolations: Object.freeze([...assembled.violations]),
460
+ category: input.category,
461
+ tags: normalizeEnvelopeTags(input.tags, hygiene),
462
+ structuredAttributes: attributes?.canonical,
463
+ rawStructuredAttributes: attributes?.raw,
464
+ entityRef: normalizeOptionalString("entityRef", input.entityRef, hygiene),
465
+ confidence,
466
+ ttl: normalizeOptionalString("ttl", input.ttl, hygiene),
467
+ validAt,
468
+ sourceConnector: normalizeOptionalString("sourceConnector", input.sourceConnector, hygiene),
469
+ sourceReason: normalizeOptionalString("sourceReason", input.sourceReason, hygiene),
470
+ source: ctx.source.trim(),
471
+ composedAt: now.toISOString(),
472
+ salvageNotes: Object.freeze([...hygiene.notes]),
473
+ };
474
+ const envelope = Object.freeze(body) as unknown as SealedMemoryEnvelope;
475
+ SEALED_ENVELOPES.add(envelope);
476
+ return envelope;
477
+ }
478
+
479
+ // The runtime seal registry. The declared `sealed` unique symbol exists only
480
+ // at the type level (compile-time fence); this WeakSet is the runtime fence.
481
+ const SEALED_ENVELOPES = new WeakSet<object>();
482
+
483
+ /**
484
+ * TOCTOU guard for the structural arm (#2014 round 4): a frozen object may
485
+ * still carry ACCESSOR properties whose getters return different values on
486
+ * each read — valid data during re-composition, forged data when the write
487
+ * path reads the field again. Frozen DATA properties are immutable, so
488
+ * requiring data-only descriptors (on the envelope and its array/map
489
+ * fields) makes every later read provably identical to the validated one.
490
+ */
491
+ function hasOnlyFrozenDataProperties(value: object): boolean {
492
+ if (!Object.isFrozen(value)) return false;
493
+ // Inherited accessors are as dangerous as own ones (round 5): a frozen
494
+ // object can inherit a `tags` getter from a custom prototype. Composer
495
+ // envelopes are plain object literals and plain arrays — require exactly
496
+ // those prototypes so prototype-supplied getters cannot serve fields.
497
+ const proto = Object.getPrototypeOf(value);
498
+ if (Array.isArray(value)) {
499
+ if (proto !== Array.prototype) return false;
500
+ } else if (proto !== Object.prototype && proto !== null) {
501
+ return false;
502
+ }
503
+ for (const key of Reflect.ownKeys(value)) {
504
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
505
+ if (!descriptor || descriptor.get !== undefined || descriptor.set !== undefined) {
506
+ return false;
507
+ }
508
+ }
509
+ return true;
510
+ }
511
+
512
+ /**
513
+ * Runtime check (belt) — the compile-time brand is the real fence.
514
+ *
515
+ * Fast path: WeakSet membership (same module graph). Fallback: RE-COMPOSITION
516
+ * EQUIVALENCE — Node resolves `@remnic/core` through `dist/` for built
517
+ * consumers and `src/` for tsx-loaded tests, and each graph gets its OWN
518
+ * WeakSet, so identity alone would reject genuinely-sealed envelopes that
519
+ * crossed a build boundary. The structural arm requires frozen DATA-only
520
+ * properties (no accessors — TOCTOU guard, round 4), then re-runs the
521
+ * STRICT composer on the candidate's own inputs and demands every envelope
522
+ * field reproduce exactly (#2014 round 2: shape-only validation admitted
523
+ * lookalikes with 51 tags or out-of-range confidence). A value that
524
+ * survives has, by construction, passed every composer invariant, and its
525
+ * fields cannot change between validation and the write that follows.
526
+ *
527
+ * `salvageNotes` is deliberately NOT compared: a legitimately salvage-minted
528
+ * envelope carries notes while the strict re-composition of its (already
529
+ * clean) surviving fields yields none. Notes are advisory provenance, not
530
+ * identity — every load-bearing field is still verified.
531
+ */
532
+
533
+ export function isSealedMemoryEnvelope(value: unknown): value is SealedMemoryEnvelope {
534
+ if (typeof value !== "object" || value === null) return false;
535
+ if (SEALED_ENVELOPES.has(value)) return true;
536
+ if (!hasOnlyFrozenDataProperties(value)) return false;
537
+ const v = value as Partial<SealedMemoryEnvelope>;
538
+ if (
539
+ typeof v.content !== "string" ||
540
+ typeof v.persistedBody !== "string" ||
541
+ typeof v.source !== "string" ||
542
+ typeof v.composedAt !== "string" ||
543
+ typeof v.category !== "string" ||
544
+ !isMemoryCategory(v.category) ||
545
+ !Array.isArray(v.tags) ||
546
+ !hasOnlyFrozenDataProperties(v.tags) ||
547
+ !Array.isArray(v.sanitizeViolations) ||
548
+ !hasOnlyFrozenDataProperties(v.sanitizeViolations) ||
549
+ !Array.isArray(v.salvageNotes) ||
550
+ !hasOnlyFrozenDataProperties(v.salvageNotes)
551
+ ) {
552
+ return false;
553
+ }
554
+ const attrs = v.rawStructuredAttributes;
555
+ if (
556
+ attrs !== undefined &&
557
+ (attrs === null || typeof attrs !== "object" || Array.isArray(attrs) || !hasOnlyFrozenDataProperties(attrs))
558
+ ) {
559
+ return false;
560
+ }
561
+ const canonicalAttrs = v.structuredAttributes;
562
+ if (
563
+ canonicalAttrs !== undefined &&
564
+ (canonicalAttrs === null ||
565
+ typeof canonicalAttrs !== "object" ||
566
+ Array.isArray(canonicalAttrs) ||
567
+ !hasOnlyFrozenDataProperties(canonicalAttrs))
568
+ ) {
569
+ return false;
570
+ }
571
+ let rebuilt: SealedMemoryEnvelope;
572
+ try {
573
+ rebuilt = composeMemoryEnvelope(
574
+ {
575
+ content: v.content,
576
+ category: v.category,
577
+ ...(v.tags.length > 0 ? { tags: [...(v.tags as string[])] } : {}),
578
+ ...(attrs !== undefined ? { structuredAttributes: { ...attrs } } : {}),
579
+ ...(v.entityRef !== undefined ? { entityRef: v.entityRef } : {}),
580
+ ...(v.confidence !== undefined ? { confidence: v.confidence } : {}),
581
+ ...(v.ttl !== undefined ? { ttl: v.ttl } : {}),
582
+ ...(v.validAt !== undefined ? { validAt: v.validAt } : {}),
583
+ ...(v.sourceConnector !== undefined ? { sourceConnector: v.sourceConnector } : {}),
584
+ ...(v.sourceReason !== undefined ? { sourceReason: v.sourceReason } : {}),
585
+ },
586
+ { source: v.source, now: () => new Date(v.composedAt as string) },
587
+ );
588
+ } catch {
589
+ // Strict re-composition rejected an input — the candidate carries a
590
+ // value the composer would never have minted.
591
+ return false;
592
+ }
593
+ const sameArray = (a: readonly string[], b: readonly string[]): boolean =>
594
+ a.length === b.length && a.every((entry, i) => entry === b[i]);
595
+ const sameMap = (
596
+ a: Readonly<Record<string, string>> | undefined,
597
+ b: Readonly<Record<string, string>> | undefined,
598
+ ): boolean => {
599
+ if (a === undefined || b === undefined) return a === b;
600
+ const ak = Object.keys(a);
601
+ const bk = Object.keys(b);
602
+ return ak.length === bk.length && ak.every((k) => Object.hasOwn(b, k) && a[k] === b[k]);
603
+ };
604
+ return (
605
+ rebuilt.content === v.content &&
606
+ rebuilt.persistedBody === v.persistedBody &&
607
+ rebuilt.category === v.category &&
608
+ rebuilt.source === v.source &&
609
+ rebuilt.composedAt === v.composedAt &&
610
+ rebuilt.confidence === v.confidence &&
611
+ rebuilt.entityRef === v.entityRef &&
612
+ rebuilt.ttl === v.ttl &&
613
+ rebuilt.validAt === v.validAt &&
614
+ rebuilt.sourceConnector === v.sourceConnector &&
615
+ rebuilt.sourceReason === v.sourceReason &&
616
+ sameArray(rebuilt.tags, v.tags as string[]) &&
617
+ sameArray(rebuilt.sanitizeViolations, v.sanitizeViolations as string[]) &&
618
+ sameMap(rebuilt.structuredAttributes, v.structuredAttributes) &&
619
+ sameMap(rebuilt.rawStructuredAttributes, attrs)
620
+ );
621
+ }
622
+
623
+ /**
624
+ * The ONE mapping from a sealed envelope (+ extras) to the legacy
625
+ * `writeMemory(category, content, options)` argument shape. Used by
626
+ * `StorageManager.writeSealedMemory` AND by test doubles that stub storage —
627
+ * so mock fidelity (AGENTS.md §21) cannot drift from production.
628
+ */
629
+ export function sealedWriteToLegacyArgs(
630
+ envelope: SealedMemoryEnvelope,
631
+ extras: Record<string, unknown> = {},
632
+ ): { category: MemoryCategory; content: string; options: Record<string, unknown> } {
633
+ return {
634
+ category: envelope.category,
635
+ content: envelope.content,
636
+ options: {
637
+ ...extras,
638
+ confidence: envelope.confidence,
639
+ tags: envelope.tags.length > 0 ? [...envelope.tags] : undefined,
640
+ entityRef: envelope.entityRef,
641
+ source: envelope.source,
642
+ expiresAt: envelope.ttl,
643
+ validAt: envelope.validAt,
644
+ // RAW map for frontmatter byte-parity with the legacy path; the body
645
+ // suffix canonicalizes identically from either form.
646
+ structuredAttributes: envelope.rawStructuredAttributes
647
+ ? { ...envelope.rawStructuredAttributes }
648
+ : undefined,
649
+ // Unconditional (round 3): envelope-owned fields must ALWAYS overwrite
650
+ // extras — a conditional spread let extras.sourceConnector smuggle
651
+ // unvalidated connector provenance past the sealed envelope when the
652
+ // envelope had none.
653
+ sourceConnector: envelope.sourceConnector,
654
+ },
655
+ };
656
+ }
657
+
658
+ // ---------------------------------------------------------------------------
659
+ // Idempotency field registry
660
+ // ---------------------------------------------------------------------------
661
+
662
+ /**
663
+ * Ordered registry of envelope fields that participate in write-idempotency
664
+ * fingerprints. Adding a fingerprint-relevant field = one entry here; every
665
+ * surface that builds its payload via `buildWriteIdempotencyPayload()` picks
666
+ * it up automatically.
667
+ */
668
+ export const WRITE_FINGERPRINT_FIELDS = [
669
+ "content",
670
+ "category",
671
+ "tags",
672
+ "structuredAttributes",
673
+ "entityRef",
674
+ "ttl",
675
+ "validAt",
676
+ "sourceConnector",
677
+ ] as const satisfies readonly (keyof MemoryWriteInput)[];
678
+
679
+ /**
680
+ * Envelope fields deliberately EXCLUDED from fingerprints. Exempting a field
681
+ * is a visible, reviewable decision — this list exists so the exhaustiveness
682
+ * guard can force every new `MemoryWriteInput` field to be classified.
683
+ */
684
+ export const FINGERPRINT_EXEMPT_FIELDS = [
685
+ // Confidence is a scoring detail: two extractions of the same fact with
686
+ // slightly different confidence are the same write for dedup purposes.
687
+ "confidence",
688
+ // Free-text provenance note; carries no identity.
689
+ "sourceReason",
690
+ ] as const satisfies readonly (keyof MemoryWriteInput)[];
691
+
692
+ /** Scope keys always folded into the fingerprint payload. */
693
+ export const FINGERPRINT_SCOPE_FIELDS = [
694
+ "surface",
695
+ "namespace",
696
+ "principal",
697
+ "codingContext",
698
+ ] as const satisfies readonly (keyof FingerprintScope)[];
699
+
700
+ // --- compile-time exhaustiveness guards ------------------------------------
701
+ // A new MemoryWriteInput field that is in NEITHER list is a compile error;
702
+ // a registry entry that names a non-existent field is a compile error; a
703
+ // field in BOTH lists is a compile error.
704
+
705
+ type RegistryField = (typeof WRITE_FINGERPRINT_FIELDS)[number];
706
+ type ExemptField = (typeof FINGERPRINT_EXEMPT_FIELDS)[number];
707
+ type UnclassifiedField = Exclude<keyof MemoryWriteInput, RegistryField | ExemptField>;
708
+ type DoublyClassifiedField = RegistryField & ExemptField;
709
+
710
+ const assertEveryFieldClassified: UnclassifiedField extends never ? true : never = true;
711
+ const assertNoDoubleClassification: DoublyClassifiedField extends never ? true : never = true;
712
+ void assertEveryFieldClassified;
713
+ void assertNoDoubleClassification;
714
+
715
+ // ---------------------------------------------------------------------------
716
+ // Payload builder
717
+ // ---------------------------------------------------------------------------
718
+
719
+ /**
720
+ * Build the canonical write-idempotency payload for a sealed envelope.
721
+ *
722
+ * Determinism guarantees (AGENTS.md §26):
723
+ * - tags are SORTED in the payload (tag order never changes identity);
724
+ * - structured attributes are serialized key-sorted by the existing
725
+ * `stableStringify` inside `hashAccessIdempotencyPayload`;
726
+ * - the payload shape is versioned (`v: 1`) so a future field-semantics
727
+ * change can migrate stored idempotency state explicitly instead of
728
+ * silently colliding.
729
+ *
730
+ * Feed the result to `hashAccessIdempotencyPayload()` — this module does
731
+ * not hash so surfaces keep a single hashing implementation.
732
+ */
733
+ export function buildWriteIdempotencyPayload(
734
+ envelope: SealedMemoryEnvelope,
735
+ scope: FingerprintScope,
736
+ ): Record<string, unknown> {
737
+ if (!isSealedMemoryEnvelope(envelope)) {
738
+ throw new Error(
739
+ "buildWriteIdempotencyPayload: envelope must be minted by composeMemoryEnvelope",
740
+ );
741
+ }
742
+ if (scope === null || typeof scope !== "object") {
743
+ throw new Error("buildWriteIdempotencyPayload: scope must be an object");
744
+ }
745
+ if (typeof scope.surface !== "string" || scope.surface.trim().length === 0) {
746
+ throw new Error("buildWriteIdempotencyPayload: scope.surface must be a non-empty string");
747
+ }
748
+
749
+ const fields: Record<string, unknown> = {};
750
+ for (const field of WRITE_FINGERPRINT_FIELDS) {
751
+ const value = envelope[field];
752
+ if (value === undefined) continue;
753
+ if (field === "tags") {
754
+ const tags = value as readonly string[];
755
+ if (tags.length === 0) continue;
756
+ fields.tags = [...tags].sort();
757
+ continue;
758
+ }
759
+ if (field === "content") {
760
+ // Fingerprints hash the PERSISTED form (attribute suffix + combined
761
+ // sanitize), not the raw input — one instant of stored state, one
762
+ // fingerprint (§13; issue #1989 PR2).
763
+ fields.content = envelope.persistedBody;
764
+ continue;
765
+ }
766
+ fields[field] = value;
767
+ }
768
+ // The write source (extraction vs wearable:bee vs observe replay, ...) is
769
+ // identity: the same content arriving from two different sources must not
770
+ // dedupe into one write (review finding on #1998). Not a MemoryWriteInput
771
+ // key, so it rides beside the registry fields explicitly.
772
+ fields.source = envelope.source;
773
+
774
+ const scopeOut: Record<string, string> = {};
775
+ for (const key of FINGERPRINT_SCOPE_FIELDS) {
776
+ const value = scope[key];
777
+ if (value === undefined) continue;
778
+ if (typeof value !== "string") {
779
+ throw new Error(`buildWriteIdempotencyPayload: scope.${key} must be a string`);
780
+ }
781
+ // Trimmed: "ns" and "ns " must not mint distinct fingerprints (review
782
+ // finding on #1998). Empty-after-trim optional scope values are dropped.
783
+ const cleanValue = value.trim();
784
+ if (key === "surface" || cleanValue.length > 0) {
785
+ scopeOut[key] = cleanValue;
786
+ }
787
+ }
788
+
789
+ return { v: 1, kind: "memory-write", fields, scope: scopeOut };
790
+ }
791
+
792
+ // ---------------------------------------------------------------------------
793
+ // Access-surface request fingerprints (issue #1989 PR3)
794
+ // ---------------------------------------------------------------------------
795
+ //
796
+ // The access surfaces (memory_store / suggestion_submit writes, their peek
797
+ // twins, and observe) key their idempotency dedup on a hash of the RAW
798
+ // request — computed BEFORE validation, and persisted indefinitely in
799
+ // `AccessIdempotencyStore` (last-512 LRU, no time TTL). Those stored hashes
800
+ // are load-bearing state: changing the payload shape would silently break
801
+ // replay/conflict detection for every in-flight key. So these builders
802
+ // REPRODUCE each surface's historical shape byte-for-byte (asserted by the
803
+ // parity suite) instead of adopting the versioned envelope payload above —
804
+ // a versioned migration of stored state is the explicit prerequisite for
805
+ // unifying them (#1989 PR3 scope note).
806
+ //
807
+ // What centralizing buys even under byte-parity: one module now owns every
808
+ // fingerprint shape, and the compile-time assertion below ties the write
809
+ // shape to WRITE_FINGERPRINT_FIELDS — adding a fingerprint-relevant field
810
+ // to MemoryWriteInput fails compilation here until the author decides how
811
+ // the access surfaces represent it.
812
+
813
+ /** The raw request fields the write surfaces fingerprint (legacy shape). */
814
+ export interface AccessWriteFingerprintParts {
815
+ schemaVersion: number;
816
+ namespace: string;
817
+ content: string;
818
+ category?: string;
819
+ confidence?: number;
820
+ tags?: string[];
821
+ entityRef?: string;
822
+ ttl?: string;
823
+ sourceReason?: string;
824
+ sourceConnector?: string;
825
+ }
826
+
827
+ // Registry coupling: every fingerprint-relevant MemoryWriteInput field must
828
+ // either appear in AccessWriteFingerprintParts or be named in this explicit
829
+ // exemption list. `structuredAttributes` and `validAt` are exempt because
830
+ // the access write requests cannot express them today (ExplicitCaptureInput
831
+ // has no such fields) — the moment they become representable, this type
832
+ // stops compiling and forces a fingerprint decision (+ versioned state
833
+ // migration) instead of a silent dedup gap.
834
+ type AccessSurfaceUnrepresentable = "structuredAttributes" | "validAt";
835
+ type UncoveredAccessFingerprintField = Exclude<
836
+ Extract<RegistryField, keyof MemoryWriteInput>,
837
+ keyof AccessWriteFingerprintParts | AccessSurfaceUnrepresentable
838
+ >;
839
+ const assertAccessFingerprintCoversRegistry: UncoveredAccessFingerprintField extends never
840
+ ? true
841
+ : never = true;
842
+ void assertAccessFingerprintCoversRegistry;
843
+
844
+ /**
845
+ * Fingerprint payload for `memory_store` / `suggestion_submit` (write AND
846
+ * peek paths — both MUST call this so peek can never diverge from the
847
+ * write it predicts). Key set and values reproduce the historical inline
848
+ * literals exactly; `hashAccessIdempotencyPayload`'s stableStringify sorts
849
+ * keys and drops `undefined`, so optional absent fields hash identically
850
+ * to the old shape.
851
+ */
852
+ export function buildAccessWriteRequestFingerprint(
853
+ parts: AccessWriteFingerprintParts,
854
+ ): Record<string, unknown> {
855
+ return {
856
+ schemaVersion: parts.schemaVersion,
857
+ content: parts.content,
858
+ category: parts.category,
859
+ confidence: parts.confidence,
860
+ namespace: parts.namespace,
861
+ tags: parts.tags,
862
+ entityRef: parts.entityRef,
863
+ ttl: parts.ttl,
864
+ sourceReason: parts.sourceReason,
865
+ sourceConnector: parts.sourceConnector,
866
+ };
867
+ }
868
+
869
+ /** The raw request fields the observe surface fingerprints (legacy shape). */
870
+ export interface ObserveFingerprintParts {
871
+ sessionKey: string;
872
+ messages: unknown;
873
+ namespace?: string;
874
+ skipExtraction?: boolean;
875
+ authenticatedPrincipal?: string;
876
+ cwd?: string;
877
+ projectTag?: string;
878
+ /** Resolved coding context — `null` (not undefined) when absent, matching the historical literal. */
879
+ effectiveCodingContext: unknown;
880
+ sourceConnector?: string;
881
+ }
882
+
883
+ /**
884
+ * Fingerprint payload for `observe` — turn ingestion, not a memory write,
885
+ * so it fingerprints session/message identity rather than MemoryWriteInput
886
+ * fields. Shape reproduces the historical inline literal exactly.
887
+ */
888
+ export function buildObserveRequestFingerprint(
889
+ parts: ObserveFingerprintParts,
890
+ ): Record<string, unknown> {
891
+ return {
892
+ sessionKey: parts.sessionKey,
893
+ messages: parts.messages,
894
+ namespace: parts.namespace,
895
+ skipExtraction: parts.skipExtraction,
896
+ authenticatedPrincipal: parts.authenticatedPrincipal,
897
+ cwd: parts.cwd,
898
+ projectTag: parts.projectTag,
899
+ effectiveCodingContext: parts.effectiveCodingContext,
900
+ sourceConnector: parts.sourceConnector,
901
+ };
902
+ }