@remnic/core 10.0.13 → 10.0.15

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 (614) hide show
  1. package/dist/abstraction-nodes.js +3 -2
  2. package/dist/access-admin-ops-surface.js +96 -92
  3. package/dist/access-authorization-probe.js +97 -93
  4. package/dist/access-boundary.js +96 -92
  5. package/dist/access-cli.js +203 -198
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-extraction-force-flush.js +96 -92
  8. package/dist/access-http-briefing.js +97 -93
  9. package/dist/access-http-query.js +98 -94
  10. package/dist/access-http.js +121 -117
  11. package/dist/access-idempotency.js +3 -2
  12. package/dist/access-identity-continuity-surface.js +96 -92
  13. package/dist/access-lcm-surface.js +96 -92
  14. package/dist/access-mcp.js +110 -106
  15. package/dist/access-namespace-preflight.js +96 -92
  16. package/dist/access-observe-write-category.js +18 -17
  17. package/dist/access-observe-write-surface.js +96 -92
  18. package/dist/access-offline-manifest.js +17 -15
  19. package/dist/access-operations-batch.js +101 -97
  20. package/dist/access-operations.js +108 -104
  21. package/dist/access-recall-concurrency.js +96 -92
  22. package/dist/access-recall-diagnostics.js +2 -2
  23. package/dist/access-recall-response.js +96 -92
  24. package/dist/access-recall-surface.js +96 -92
  25. package/dist/access-schema.d.ts +2 -2
  26. package/dist/access-schema.js +13 -12
  27. package/dist/access-service.js +96 -92
  28. package/dist/access-surface-catalog.js +98 -94
  29. package/dist/access-surface-catalog.js.map +1 -1
  30. package/dist/active-recall.js +43 -39
  31. package/dist/active-recall.js.map +1 -1
  32. package/dist/adapters/index.js +4 -4
  33. package/dist/adapters/registry.js +2 -2
  34. package/dist/{auto-sync-DGJOZYGT.js → auto-sync-7WWAKW6F.js} +8 -8
  35. package/dist/briefing.js +32 -28
  36. package/dist/buffer.js +13 -13
  37. package/dist/calibration.d.ts.map +1 -1
  38. package/dist/calibration.js +6 -3
  39. package/dist/calibration.js.map +1 -1
  40. package/dist/{capsule-merge-M4HETD27.js → capsule-merge-LGYURS3C.js} +6 -5
  41. package/dist/{capsule-merge-M4HETD27.js.map → capsule-merge-LGYURS3C.js.map} +1 -1
  42. package/dist/capture-write-lock-backoff.d.ts +50 -0
  43. package/dist/capture-write-lock-backoff.d.ts.map +1 -0
  44. package/dist/capture-write-lock-backoff.js +30 -0
  45. package/dist/capture-write-lock.d.ts +6 -0
  46. package/dist/capture-write-lock.d.ts.map +1 -0
  47. package/dist/capture-write-lock.js +15 -0
  48. package/dist/causal-behavior.js +4 -3
  49. package/dist/causal-behavior.js.map +1 -1
  50. package/dist/causal-chain.js +4 -3
  51. package/dist/causal-consolidation.js +36 -32
  52. package/dist/causal-consolidation.js.map +1 -1
  53. package/dist/causal-retrieval.js +4 -3
  54. package/dist/causal-retrieval.js.map +1 -1
  55. package/dist/causal-trajectory-graph.js +7 -6
  56. package/dist/causal-trajectory-graph.js.map +1 -1
  57. package/dist/causal-trajectory.js +3 -2
  58. package/dist/{chunk-KZO43HPY.js → chunk-22RM2ZUJ.js} +112 -112
  59. package/dist/{chunk-ZUMXY4KA.js → chunk-22W2XWGH.js} +3 -3
  60. package/dist/{chunk-MZBWIJJN.js → chunk-23ZQPP2G.js} +24 -19
  61. package/dist/chunk-23ZQPP2G.js.map +1 -0
  62. package/dist/{chunk-PCWXLAJY.js → chunk-2PTH4PRL.js} +2 -2
  63. package/dist/{chunk-ZIZ2G47N.js → chunk-2PYHLSXK.js} +2 -2
  64. package/dist/{chunk-B6O2YLUR.js → chunk-2Z5DIDQD.js} +6 -1
  65. package/dist/chunk-2Z5DIDQD.js.map +1 -0
  66. package/dist/{chunk-7OAIOE5P.js → chunk-33G67YZF.js} +2 -2
  67. package/dist/{chunk-AV2OQF2O.js → chunk-3F3HA3R2.js} +2 -2
  68. package/dist/{chunk-RP5SJ3XR.js → chunk-3GNIJUUE.js} +2 -2
  69. package/dist/{chunk-QZZPUREO.js → chunk-3GYSZHMT.js} +3 -3
  70. package/dist/{chunk-QWWMS4AE.js → chunk-3MO4LWYU.js} +1 -1
  71. package/dist/chunk-3MO4LWYU.js.map +1 -0
  72. package/dist/{chunk-SWIKABKI.js → chunk-3Q3XD3NO.js} +2 -2
  73. package/dist/{chunk-AL6EHLB5.js → chunk-3X3PNU3T.js} +2 -2
  74. package/dist/{chunk-BTJ6CAIA.js → chunk-4IYIGN53.js} +10 -10
  75. package/dist/{chunk-BZTRPCCH.js → chunk-4PDTVVSW.js} +2 -2
  76. package/dist/{chunk-HM7RHKS4.js → chunk-4RNBLLZR.js} +2 -2
  77. package/dist/{chunk-Y3VDGK2O.js → chunk-4SCZZ3U7.js} +282 -84
  78. package/dist/chunk-4SCZZ3U7.js.map +1 -0
  79. package/dist/{chunk-JUWJYXI4.js → chunk-5ATSXCAG.js} +4 -4
  80. package/dist/{chunk-EHRE7ZG3.js → chunk-5B5WYAHQ.js} +2 -2
  81. package/dist/{chunk-WCGJK4NQ.js → chunk-5FNZ3G6X.js} +10 -10
  82. package/dist/{chunk-Y6DZ33PA.js → chunk-5GX5457J.js} +4 -4
  83. package/dist/{chunk-EMFBC7L3.js → chunk-5KGYTX5O.js} +2 -2
  84. package/dist/{chunk-OFCHT2TN.js → chunk-5LRV557D.js} +2 -2
  85. package/dist/{chunk-DXHVD4DS.js → chunk-5SMR542T.js} +3 -3
  86. package/dist/{chunk-S7LWX2PQ.js → chunk-655FVTCD.js} +2 -2
  87. package/dist/{chunk-DGRMWDQY.js → chunk-66BCOVW2.js} +7 -7
  88. package/dist/chunk-6EDW54SQ.js +298 -0
  89. package/dist/chunk-6EDW54SQ.js.map +1 -0
  90. package/dist/{chunk-5MDM7UE4.js → chunk-6WGMZQGG.js} +2 -2
  91. package/dist/chunk-77R7BQZ2.js +152 -0
  92. package/dist/chunk-77R7BQZ2.js.map +1 -0
  93. package/dist/{chunk-IPLYGWQF.js → chunk-7LCGFUMB.js} +6 -6
  94. package/dist/{chunk-5ZJYHOJT.js → chunk-7VQ6AI7H.js} +8 -8
  95. package/dist/{chunk-KYY4EACB.js → chunk-7Z3DLNSD.js} +2 -2
  96. package/dist/{chunk-LNH76ZJX.js → chunk-AIYXVWUH.js} +27 -2
  97. package/dist/{chunk-LNH76ZJX.js.map → chunk-AIYXVWUH.js.map} +1 -1
  98. package/dist/{chunk-G7NYVKD6.js → chunk-B2NXOVZN.js} +2 -2
  99. package/dist/{chunk-B43NMCGQ.js → chunk-BK2BVLZW.js} +2 -2
  100. package/dist/{chunk-QJ622LTI.js → chunk-BQOGQULP.js} +30 -8
  101. package/dist/chunk-BQOGQULP.js.map +1 -0
  102. package/dist/{chunk-BOOFTFFE.js → chunk-C2RW36YR.js} +2 -2
  103. package/dist/{chunk-XERVJYH2.js → chunk-C6JMGAMO.js} +7 -3
  104. package/dist/chunk-C6JMGAMO.js.map +1 -0
  105. package/dist/{chunk-5JMI26Q7.js → chunk-CBH2Z4UA.js} +2 -2
  106. package/dist/{chunk-P2S6P7X6.js → chunk-CFZ4SXXH.js} +2 -2
  107. package/dist/{chunk-YRH3C2OJ.js → chunk-CIIHIAJ2.js} +13 -5
  108. package/dist/chunk-CIIHIAJ2.js.map +1 -0
  109. package/dist/{chunk-6M56RFFJ.js → chunk-CJRENHVZ.js} +3 -3
  110. package/dist/{chunk-EGDYVYU7.js → chunk-CLWBFR7Q.js} +3 -3
  111. package/dist/{chunk-375ARKRS.js → chunk-D5SSBCYY.js} +70 -59
  112. package/dist/chunk-D5SSBCYY.js.map +1 -0
  113. package/dist/{chunk-KI6UOSNR.js → chunk-DEY7B77Y.js} +2 -2
  114. package/dist/chunk-DEY7B77Y.js.map +1 -0
  115. package/dist/{chunk-6VAHJ2F6.js → chunk-DMDWFQMR.js} +2 -2
  116. package/dist/{chunk-BLVHDY2U.js → chunk-DOWACHYO.js} +5 -2
  117. package/dist/chunk-DOWACHYO.js.map +1 -0
  118. package/dist/{chunk-UZSBCQEC.js → chunk-DPSOFK4D.js} +2 -2
  119. package/dist/{chunk-IZT3BVDW.js → chunk-DQR2LD3V.js} +2 -2
  120. package/dist/{chunk-K4QY55XV.js → chunk-EH4BQ7LT.js} +2 -2
  121. package/dist/chunk-EHHQJTAU.js +131 -0
  122. package/dist/chunk-EHHQJTAU.js.map +1 -0
  123. package/dist/{chunk-EBA5DA77.js → chunk-EOU6V4IN.js} +2 -2
  124. package/dist/{chunk-GD7BWGIB.js → chunk-EU6IRUCY.js} +6 -4
  125. package/dist/{chunk-GD7BWGIB.js.map → chunk-EU6IRUCY.js.map} +1 -1
  126. package/dist/{chunk-7KYJNHGM.js → chunk-EUCYTCFP.js} +2 -2
  127. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  128. package/dist/{chunk-CKUUP64O.js → chunk-F2772ATT.js} +2 -2
  129. package/dist/{chunk-46EST7JO.js → chunk-F2XNSIPP.js} +2 -2
  130. package/dist/{chunk-2KRNPFPK.js → chunk-FLI6DEIU.js} +2 -2
  131. package/dist/{chunk-OAIWPB2I.js → chunk-FT4UQYOV.js} +2 -2
  132. package/dist/{chunk-HYNEDMYJ.js → chunk-G2OYFTUD.js} +2 -2
  133. package/dist/{chunk-XTN54NML.js → chunk-G3T6YMBO.js} +4 -4
  134. package/dist/{chunk-CNG2XVZG.js → chunk-G3UUAQOD.js} +2 -2
  135. package/dist/{chunk-2ZQJLBV6.js → chunk-GCVDFX66.js} +4 -4
  136. package/dist/{chunk-ON4ILX3G.js → chunk-GFAM2LTC.js} +2 -2
  137. package/dist/{chunk-2LUSQV4U.js → chunk-GKJJNO7C.js} +2 -2
  138. package/dist/{chunk-T2YX56QI.js → chunk-GQJKVQJR.js} +2 -2
  139. package/dist/{chunk-5AOAQR37.js → chunk-GWVNGDJW.js} +3 -3
  140. package/dist/{chunk-YDH2FSDI.js → chunk-GZXXPCWJ.js} +3 -3
  141. package/dist/{chunk-5JCLELOP.js → chunk-H5IUN433.js} +2 -2
  142. package/dist/{chunk-IWHEJXR2.js → chunk-H6FREOYX.js} +8 -8
  143. package/dist/{chunk-B7CANWCA.js → chunk-HBAOOSHU.js} +2 -2
  144. package/dist/{chunk-Q4E24IRR.js → chunk-HDN7IVIO.js} +14 -11
  145. package/dist/chunk-HDN7IVIO.js.map +1 -0
  146. package/dist/{chunk-T3FMRLWQ.js → chunk-HFSPY26A.js} +2 -2
  147. package/dist/{chunk-B657ZGDH.js → chunk-HQSK2INQ.js} +2 -2
  148. package/dist/{chunk-RT6D3WN7.js → chunk-IJMDBYCO.js} +2 -2
  149. package/dist/{chunk-CS2JEHTB.js → chunk-IUCPLBDS.js} +9 -9
  150. package/dist/{chunk-XRBHXUTQ.js → chunk-IWD33CF4.js} +6 -6
  151. package/dist/{chunk-4IHBN6WU.js → chunk-JKMIGCK6.js} +2 -2
  152. package/dist/{chunk-YYO447A7.js → chunk-JNIVZNIB.js} +41 -253
  153. package/dist/chunk-JNIVZNIB.js.map +1 -0
  154. package/dist/{chunk-ROBHL3GL.js → chunk-JWX2Q6HS.js} +2 -2
  155. package/dist/{chunk-3I3U6FFT.js → chunk-K7BN34IA.js} +2 -2
  156. package/dist/{chunk-4O6WRBGE.js → chunk-KJXP6RUG.js} +5 -1
  157. package/dist/chunk-KJXP6RUG.js.map +1 -0
  158. package/dist/{chunk-4THZGKQ2.js → chunk-KLJVTZ3R.js} +3 -3
  159. package/dist/{chunk-4G4B3Z2B.js → chunk-KW4AJ7T3.js} +2 -2
  160. package/dist/{chunk-HT2C4EXO.js → chunk-L5VCT7LU.js} +8 -4
  161. package/dist/chunk-L5VCT7LU.js.map +1 -0
  162. package/dist/{chunk-ZI7LMSNI.js → chunk-LLHZZOIB.js} +2 -2
  163. package/dist/{chunk-LS2FHUML.js → chunk-LQ5SS4OP.js} +3 -3
  164. package/dist/{chunk-NSFOERZQ.js → chunk-LWFWZTWX.js} +3 -3
  165. package/dist/{chunk-BMWN7B3Y.js → chunk-LXATZLSC.js} +3 -3
  166. package/dist/{chunk-OYKQ6T4V.js → chunk-MATDGSJ7.js} +2 -2
  167. package/dist/{chunk-3NFN4Y4P.js → chunk-MGCKZWAE.js} +5 -5
  168. package/dist/{chunk-O4KYRDRT.js → chunk-MJIOGYKX.js} +2 -2
  169. package/dist/{chunk-6OMUHXHP.js → chunk-ML7ZJAKJ.js} +2 -2
  170. package/dist/{chunk-GKIXBH7Y.js → chunk-MO6N4QYY.js} +4 -4
  171. package/dist/{chunk-A2E4WNW4.js → chunk-MWWAQXZ6.js} +2 -2
  172. package/dist/{chunk-VYPFEVOM.js → chunk-NHUX6GXA.js} +6 -6
  173. package/dist/{chunk-AKREOU5F.js → chunk-NZCKG25S.js} +2 -2
  174. package/dist/{chunk-4NDWE44P.js → chunk-NZFFGO5O.js} +2 -2
  175. package/dist/{chunk-WWSRLS4M.js → chunk-O2YPCFJT.js} +17 -17
  176. package/dist/{chunk-ZSJGYC3C.js → chunk-OQJKY3Z5.js} +2 -2
  177. package/dist/{chunk-U7VPOXVM.js → chunk-OQR42XCN.js} +82 -78
  178. package/dist/chunk-OQR42XCN.js.map +1 -0
  179. package/dist/{chunk-OFEHITAZ.js → chunk-OXNTOHL6.js} +2 -2
  180. package/dist/{chunk-FQD2KPQH.js → chunk-P55FACBG.js} +2 -2
  181. package/dist/chunk-PGRZ3FYC.js +34 -0
  182. package/dist/chunk-PGRZ3FYC.js.map +1 -0
  183. package/dist/{chunk-JYZSRNR7.js → chunk-PIITB2YZ.js} +2 -2
  184. package/dist/{chunk-PBVNVKYN.js → chunk-PIN5OPBA.js} +2 -2
  185. package/dist/chunk-PPUNC7UX.js +73 -0
  186. package/dist/chunk-PPUNC7UX.js.map +1 -0
  187. package/dist/{chunk-EQWEIIKQ.js → chunk-PQM3B54K.js} +6 -1
  188. package/dist/chunk-PQM3B54K.js.map +1 -0
  189. package/dist/{chunk-4TTGRETU.js → chunk-PRU7OF3Y.js} +5 -5
  190. package/dist/{chunk-K2FSASGZ.js → chunk-PVHQSLNN.js} +7 -7
  191. package/dist/{chunk-SVDU4OHO.js → chunk-Q35L7TYB.js} +2 -2
  192. package/dist/{chunk-5VC7J76U.js → chunk-QPH52AZB.js} +2 -2
  193. package/dist/{chunk-6T42L5FI.js → chunk-QS3OLP5I.js} +2 -2
  194. package/dist/{chunk-P34FDDB5.js → chunk-QSEUUQUF.js} +2 -2
  195. package/dist/chunk-QUIRIG2P.js +31 -0
  196. package/dist/chunk-QUIRIG2P.js.map +1 -0
  197. package/dist/{chunk-PAAJWQH5.js → chunk-QUMKDRCF.js} +2 -2
  198. package/dist/{chunk-KZEMFD6E.js → chunk-R2H4ZFBJ.js} +3 -3
  199. package/dist/{chunk-X3VID2TT.js → chunk-RI2KCQHP.js} +7 -3
  200. package/dist/chunk-RI2KCQHP.js.map +1 -0
  201. package/dist/{chunk-JFVCDEIC.js → chunk-RP7PQWZM.js} +7 -7
  202. package/dist/{chunk-KC46VZR5.js → chunk-RTTPBBAN.js} +9 -9
  203. package/dist/{chunk-ZQ3WU6JO.js → chunk-RXFCU3CY.js} +2 -2
  204. package/dist/{chunk-CBP4HWCL.js → chunk-RYYVMZBR.js} +3 -3
  205. package/dist/{chunk-2NCBDGND.js → chunk-SA6GMZJY.js} +3 -3
  206. package/dist/{chunk-VFTK5WKI.js → chunk-STBX5X6B.js} +2 -2
  207. package/dist/{chunk-WVHRNAXL.js → chunk-SWWHIJUJ.js} +2 -2
  208. package/dist/{chunk-WADSXS4K.js → chunk-SX4QDWXK.js} +2 -2
  209. package/dist/{chunk-WETFW255.js → chunk-T7ASDYNK.js} +2 -2
  210. package/dist/{chunk-XZLWYZ7C.js → chunk-THEPGZBM.js} +2 -2
  211. package/dist/{chunk-YEM7K3KD.js → chunk-TMC7HBED.js} +6 -6
  212. package/dist/{chunk-RWRQ67OR.js → chunk-TPNCXSXP.js} +2 -2
  213. package/dist/{chunk-LZKOVXMX.js → chunk-TRMJ6BYC.js} +2 -2
  214. package/dist/{chunk-A6TVQ3QP.js → chunk-UGYUBENJ.js} +3 -3
  215. package/dist/{chunk-AAM66QCP.js → chunk-UZRSI6NX.js} +2 -2
  216. package/dist/{chunk-XHWJRUVP.js → chunk-V3TXIXXY.js} +3 -3
  217. package/dist/{chunk-2CXQZXWM.js → chunk-V4MB5ONM.js} +6 -6
  218. package/dist/{chunk-UOKPJFO3.js → chunk-VNZMZPAC.js} +3 -3
  219. package/dist/{chunk-FZB4TS2W.js → chunk-VPXIKBPX.js} +5 -5
  220. package/dist/{chunk-CYEK6Z3P.js → chunk-VW6VIJOS.js} +2 -2
  221. package/dist/{chunk-QUA7RLK6.js → chunk-W3FVQBGF.js} +2 -2
  222. package/dist/{chunk-6OQ6N5RP.js → chunk-WGTR573G.js} +22 -22
  223. package/dist/{chunk-W3K3HITK.js → chunk-WLT6LTQP.js} +2 -2
  224. package/dist/{chunk-6Z2AZ4AJ.js → chunk-XKRXN63M.js} +2 -2
  225. package/dist/{chunk-3J5JKBYD.js → chunk-XLBFX63V.js} +80 -77
  226. package/dist/chunk-XLBFX63V.js.map +1 -0
  227. package/dist/{chunk-FZVROZKC.js → chunk-XVZA6VXC.js} +4 -4
  228. package/dist/{chunk-DA2INEB5.js → chunk-XYGQSDTH.js} +4 -4
  229. package/dist/chunk-YET735EZ.js +99 -0
  230. package/dist/chunk-YET735EZ.js.map +1 -0
  231. package/dist/{chunk-RBJQYMMT.js → chunk-YRULQW5J.js} +4 -4
  232. package/dist/{chunk-QUNDYIYZ.js → chunk-YYEOR4XN.js} +3 -3
  233. package/dist/{chunk-6WHJ2EAB.js → chunk-Z64TS5V4.js} +2 -2
  234. package/dist/{chunk-NHLLKEKK.js → chunk-ZAJLJ35W.js} +2 -2
  235. package/dist/{chunk-M7V65M6H.js → chunk-ZKHSAMTE.js} +2 -2
  236. package/dist/cli.d.ts.map +1 -1
  237. package/dist/cli.js +154 -150
  238. package/dist/coding/export-okf-codegraph.js +32 -28
  239. package/dist/coding/export-okf-codegraph.js.map +1 -1
  240. package/dist/coding/pre-action-gate.js +4 -3
  241. package/dist/commitment-ledger.js +3 -2
  242. package/dist/compounding/engine.js +34 -30
  243. package/dist/config.js +43 -39
  244. package/dist/connectors/codex-materialize-runner.js +32 -28
  245. package/dist/connectors/index.js +32 -28
  246. package/dist/console/trace.d.ts +5 -14
  247. package/dist/console/trace.d.ts.map +1 -1
  248. package/dist/consolidation-provenance-check.d.ts.map +1 -1
  249. package/dist/consolidation-provenance-check.js +8 -6
  250. package/dist/consolidation-undo.js +5 -4
  251. package/dist/consolidation-undo.js.map +1 -1
  252. package/dist/contradiction/index.js +9 -7
  253. package/dist/converge-config.d.ts +2 -0
  254. package/dist/converge-config.d.ts.map +1 -1
  255. package/dist/converge-config.js +7 -3
  256. package/dist/convergence-refresh.js +34 -30
  257. package/dist/corpus-watermark.js +34 -30
  258. package/dist/correction/correction-planner.d.ts.map +1 -1
  259. package/dist/cue-anchors.js +4 -3
  260. package/dist/dashboard-runtime.js +2 -2
  261. package/dist/deep-recall-http-glue.js +14 -13
  262. package/dist/deep-recall.js +2 -2
  263. package/dist/{dreams-ledger-567VKVOU.js → dreams-ledger-UCHHRQ4R.js} +3 -2
  264. package/dist/embedding-fallback.js +5 -4
  265. package/dist/embedding-generation-lock.js +4 -3
  266. package/dist/entity-retrieval.js +33 -29
  267. package/dist/eval-trajectory-store.js +4 -3
  268. package/dist/eval-trajectory.js +4 -3
  269. package/dist/evals.js +3 -2
  270. package/dist/explicit-capture.js +11 -8
  271. package/dist/external-wiki-access.js +97 -93
  272. package/dist/extraction-quote-grounding.d.ts +67 -0
  273. package/dist/extraction-quote-grounding.d.ts.map +1 -0
  274. package/dist/extraction-quote-grounding.js +27 -0
  275. package/dist/extraction-quote-grounding.js.map +1 -0
  276. package/dist/extraction-source-grounding-helpers.d.ts +8 -0
  277. package/dist/extraction-source-grounding-helpers.d.ts.map +1 -1
  278. package/dist/extraction-source-grounding-helpers.js +11 -1
  279. package/dist/extraction-source-grounding-rules.d.ts +3 -1
  280. package/dist/extraction-source-grounding-rules.d.ts.map +1 -1
  281. package/dist/extraction-source-grounding-rules.js +3 -2
  282. package/dist/extraction-source-grounding.d.ts +1 -1
  283. package/dist/extraction-source-grounding.d.ts.map +1 -1
  284. package/dist/extraction-source-grounding.js +4 -3
  285. package/dist/extraction-span-materialize.js +2 -2
  286. package/dist/extraction.js +44 -39
  287. package/dist/{first-start-migration-HYAMKJ6V.js → first-start-migration-QVD22WWS.js} +9 -8
  288. package/dist/{first-start-migration-HYAMKJ6V.js.map → first-start-migration-QVD22WWS.js.map} +1 -1
  289. package/dist/{forget-OHAJ6PSU.js → forget-GXBWFKRC.js} +5 -4
  290. package/dist/{forget-OHAJ6PSU.js.map → forget-GXBWFKRC.js.map} +1 -1
  291. package/dist/{graph-edge-decay-CZ3SYLM4.js → graph-edge-decay-BYPZVJT4.js} +10 -9
  292. package/dist/graph-edge-decay-BYPZVJT4.js.map +1 -0
  293. package/dist/graph-jsonl.js +8 -7
  294. package/dist/graph-snapshot.js +8 -7
  295. package/dist/graph-write-lock.js +4 -3
  296. package/dist/graph.js +9 -8
  297. package/dist/harmonic-construction.js +5 -4
  298. package/dist/harmonic-retrieval.js +36 -32
  299. package/dist/harmonic-source-lookup.js +3 -2
  300. package/dist/http-retry.js +2 -1
  301. package/dist/http-retry.js.map +1 -1
  302. package/dist/index.d.ts +1 -1
  303. package/dist/index.d.ts.map +1 -1
  304. package/dist/index.js +244 -237
  305. package/dist/json-store.d.ts.map +1 -1
  306. package/dist/json-store.js +2 -1
  307. package/dist/lcm/engine.js +4 -4
  308. package/dist/lcm/index.js +12 -12
  309. package/dist/location/index.js +35 -31
  310. package/dist/maintenance/dreams-ledger.d.ts.map +1 -1
  311. package/dist/maintenance/memory-governance.d.ts.map +1 -1
  312. package/dist/maintenance/memory-governance.js +32 -28
  313. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +32 -28
  314. package/dist/maintenance/rebuild-memory-projection-runner.js +34 -30
  315. package/dist/maintenance/rebuild-memory-projection.js +33 -29
  316. package/dist/memory-browse-operations.js +97 -93
  317. package/dist/memory-browse.js +7 -7
  318. package/dist/memory-subject.js +5 -4
  319. package/dist/namespaces/migrate.js +33 -29
  320. package/dist/namespaces/search.js +11 -10
  321. package/dist/namespaces/storage.d.ts.map +1 -1
  322. package/dist/namespaces/storage.js +32 -28
  323. package/dist/objective-state-writers.js +4 -3
  324. package/dist/objective-state.js +3 -2
  325. package/dist/offline-sync-changeset-generations.js +7 -6
  326. package/dist/offline-sync-embedding-generation.js +6 -5
  327. package/dist/offline-sync-impression-drain.js +4 -4
  328. package/dist/offline-sync-snapshot-stream.js +10 -9
  329. package/dist/offline-sync.d.ts.map +1 -1
  330. package/dist/offline-sync.js +11 -10
  331. package/dist/operator-doctor-corpus.js +35 -31
  332. package/dist/operator-toolkit.js +58 -54
  333. package/dist/orchestration/maintenance.js +44 -40
  334. package/dist/orchestrator.js +205 -200
  335. package/dist/page-versioning.js +5 -4
  336. package/dist/profiling.d.ts.map +1 -1
  337. package/dist/profiling.js +2 -1
  338. package/dist/qmd-daemon-session.js +2 -2
  339. package/dist/qmd.js +4 -4
  340. package/dist/recall-explain-renderer.js +3 -3
  341. package/dist/recall-navigate-access.js +2 -2
  342. package/dist/recall-navigate-disclosure.js +2 -2
  343. package/dist/recall-navigate.js +2 -2
  344. package/dist/recall-navigation-operations.js +97 -93
  345. package/dist/recall-navigation.js +96 -92
  346. package/dist/recall-state-view-admission.js +7 -7
  347. package/dist/recall-state.js +4 -3
  348. package/dist/recall-why-service.js +7 -7
  349. package/dist/recall-xray-cli.js +4 -4
  350. package/dist/recall-xray-renderer.js +3 -3
  351. package/dist/recall-xray.js +2 -2
  352. package/dist/reconcile/cursor.js +4 -2
  353. package/dist/reconcile/cursor.js.map +1 -1
  354. package/dist/reconcile/manifest.js +9 -6
  355. package/dist/reconcile/plan.js +4 -2
  356. package/dist/{resolution-EKJHREVJ.js → resolution-ZU5BIAJA.js} +10 -8
  357. package/dist/resolution-ZU5BIAJA.js.map +1 -0
  358. package/dist/resume-bundles.js +48 -44
  359. package/dist/retrieval-agents.d.ts +1 -1
  360. package/dist/retrieval-agents.d.ts.map +1 -1
  361. package/dist/retrieval-agents.js +7 -1
  362. package/dist/salvage-envelope.js +7 -6
  363. package/dist/search/document-scanner.d.ts.map +1 -1
  364. package/dist/search/document-scanner.js +2 -1
  365. package/dist/search/factory.js +10 -9
  366. package/dist/search/index.js +16 -15
  367. package/dist/search/lancedb-backend.js +3 -2
  368. package/dist/search/meilisearch-backend.js +3 -2
  369. package/dist/search/orama-backend.js +3 -2
  370. package/dist/semantic-consolidation.js +37 -33
  371. package/dist/semantic-rule-promotion.js +32 -28
  372. package/dist/semantic-rule-verifier.js +32 -28
  373. package/dist/source-agent-qualifier.js +40 -35
  374. package/dist/standup/build.js +32 -28
  375. package/dist/storage/content-hash-index.d.ts +10 -0
  376. package/dist/storage/content-hash-index.d.ts.map +1 -1
  377. package/dist/storage/entity-canonical-id-migration.d.ts.map +1 -1
  378. package/dist/storage/entity-store.d.ts +32 -1
  379. package/dist/storage/entity-store.d.ts.map +1 -1
  380. package/dist/storage/memory-read-store.d.ts.map +1 -1
  381. package/dist/storage/supersession-audit.d.ts.map +1 -1
  382. package/dist/storage/tombstone-blocked-capture-index.d.ts +3 -0
  383. package/dist/storage/tombstone-blocked-capture-index.d.ts.map +1 -1
  384. package/dist/storage/tombstone-blocked-capture-mutation.d.ts +23 -3
  385. package/dist/storage/tombstone-blocked-capture-mutation.d.ts.map +1 -1
  386. package/dist/storage.d.ts +6 -0
  387. package/dist/storage.d.ts.map +1 -1
  388. package/dist/storage.js +33 -29
  389. package/dist/subject-config.js +6 -5
  390. package/dist/summarizer.js +4 -4
  391. package/dist/summary-snapshot.js +4 -3
  392. package/dist/support-passport/index.js +99 -95
  393. package/dist/{tier-stats-RQM76XYY.js → tier-stats-C3IAMS4X.js} +6 -5
  394. package/dist/{tier-stats-RQM76XYY.js.map → tier-stats-C3IAMS4X.js.map} +1 -1
  395. package/dist/{trace-LXXCMZJA.js → trace-QBQVS5BC.js} +5 -21
  396. package/dist/trace-QBQVS5BC.js.map +1 -0
  397. package/dist/transcript.d.ts.map +1 -1
  398. package/dist/transcript.js +2 -1
  399. package/dist/transfer/autodetect.js +1 -1
  400. package/dist/transfer/backup.js +1 -1
  401. package/dist/transfer/capsule-export.js +3 -3
  402. package/dist/transfer/capsule-import.js +7 -6
  403. package/dist/transfer/export-okf.js +32 -28
  404. package/dist/trust-zones.js +3 -2
  405. package/dist/types.d.ts +9 -0
  406. package/dist/types.d.ts.map +1 -1
  407. package/dist/types.js +1 -1
  408. package/dist/utility-learner.js +4 -3
  409. package/dist/utility-runtime.js +5 -4
  410. package/dist/utility-telemetry.js +3 -2
  411. package/dist/utils/macos-replication-junk.d.ts +32 -0
  412. package/dist/utils/macos-replication-junk.d.ts.map +1 -0
  413. package/dist/utils/malformed-entity-record.d.ts +24 -0
  414. package/dist/utils/malformed-entity-record.d.ts.map +1 -0
  415. package/dist/utils/serialize-mutations.js +3 -2
  416. package/dist/utils/sleep.d.ts +6 -0
  417. package/dist/utils/sleep.d.ts.map +1 -1
  418. package/dist/verified-recall.js +32 -28
  419. package/dist/who-knows-cli.js +33 -29
  420. package/dist/who-knows.js +32 -28
  421. package/dist/work-product-ledger.js +3 -2
  422. package/dist/write-envelope.js +6 -5
  423. package/package.json +22 -2
  424. package/src/calibration.ts +3 -2
  425. package/src/capture-write-lock-backoff.test.ts +534 -0
  426. package/src/capture-write-lock-backoff.ts +140 -0
  427. package/src/capture-write-lock.ts +8 -0
  428. package/src/cli.ts +2 -2
  429. package/src/console/trace.ts +5 -36
  430. package/src/consolidation-provenance-check.ts +2 -0
  431. package/src/converge-config.ts +80 -1
  432. package/src/correction/correction-planner.ts +3 -2
  433. package/src/extraction-quote-grounding.test.ts +546 -0
  434. package/src/extraction-quote-grounding.ts +232 -0
  435. package/src/extraction-source-grounding-helpers.ts +35 -0
  436. package/src/extraction-source-grounding-rules.ts +90 -65
  437. package/src/extraction-source-grounding.ts +11 -2
  438. package/src/index.ts +1 -1
  439. package/src/json-store.ts +3 -0
  440. package/src/macos-replication-junk-scanners.test.ts +275 -0
  441. package/src/maintenance/dreams-ledger.ts +2 -0
  442. package/src/maintenance/memory-governance.ts +2 -0
  443. package/src/namespaces/storage.ts +2 -0
  444. package/src/offline-sync-macos-junk.test.ts +169 -0
  445. package/src/offline-sync.ts +7 -0
  446. package/src/profiling.ts +2 -1
  447. package/src/providers/codex-subscription.test.ts +15 -3
  448. package/src/retrieval-agents.ts +29 -12
  449. package/src/search/document-scanner.ts +4 -0
  450. package/src/storage/content-hash-index.ts +10 -0
  451. package/src/storage/entity-canonical-id-migration.ts +56 -13
  452. package/src/storage/entity-store.ts +173 -15
  453. package/src/storage/memory-read-store.ts +30 -5
  454. package/src/storage/supersession-audit.ts +2 -0
  455. package/src/storage/tombstone-blocked-capture-index.ts +8 -1
  456. package/src/storage/tombstone-blocked-capture-mutation.ts +133 -43
  457. package/src/storage.ts +16 -2
  458. package/src/transcript.ts +11 -10
  459. package/src/types.ts +9 -0
  460. package/src/utils/macos-replication-junk.test.ts +46 -0
  461. package/src/utils/macos-replication-junk.ts +65 -0
  462. package/src/utils/malformed-entity-record.ts +101 -0
  463. package/src/utils/sleep.ts +28 -0
  464. package/dist/chunk-375ARKRS.js.map +0 -1
  465. package/dist/chunk-3J5JKBYD.js.map +0 -1
  466. package/dist/chunk-4O6WRBGE.js.map +0 -1
  467. package/dist/chunk-6MINUTGJ.js +0 -64
  468. package/dist/chunk-6MINUTGJ.js.map +0 -1
  469. package/dist/chunk-7LEQREP2.js +0 -9
  470. package/dist/chunk-7LEQREP2.js.map +0 -1
  471. package/dist/chunk-B6O2YLUR.js.map +0 -1
  472. package/dist/chunk-BLVHDY2U.js.map +0 -1
  473. package/dist/chunk-EQWEIIKQ.js.map +0 -1
  474. package/dist/chunk-HT2C4EXO.js.map +0 -1
  475. package/dist/chunk-KI6UOSNR.js.map +0 -1
  476. package/dist/chunk-MZBWIJJN.js.map +0 -1
  477. package/dist/chunk-Q4E24IRR.js.map +0 -1
  478. package/dist/chunk-QJ622LTI.js.map +0 -1
  479. package/dist/chunk-QWWMS4AE.js.map +0 -1
  480. package/dist/chunk-U7VPOXVM.js.map +0 -1
  481. package/dist/chunk-X3VID2TT.js.map +0 -1
  482. package/dist/chunk-XERVJYH2.js.map +0 -1
  483. package/dist/chunk-Y3VDGK2O.js.map +0 -1
  484. package/dist/chunk-YRH3C2OJ.js.map +0 -1
  485. package/dist/chunk-YYO447A7.js.map +0 -1
  486. package/dist/trace-LXXCMZJA.js.map +0 -1
  487. /package/dist/{auto-sync-DGJOZYGT.js.map → auto-sync-7WWAKW6F.js.map} +0 -0
  488. /package/dist/{dreams-ledger-567VKVOU.js.map → capture-write-lock-backoff.js.map} +0 -0
  489. /package/dist/{graph-edge-decay-CZ3SYLM4.js.map → capture-write-lock.js.map} +0 -0
  490. /package/dist/{chunk-KZO43HPY.js.map → chunk-22RM2ZUJ.js.map} +0 -0
  491. /package/dist/{chunk-ZUMXY4KA.js.map → chunk-22W2XWGH.js.map} +0 -0
  492. /package/dist/{chunk-PCWXLAJY.js.map → chunk-2PTH4PRL.js.map} +0 -0
  493. /package/dist/{chunk-ZIZ2G47N.js.map → chunk-2PYHLSXK.js.map} +0 -0
  494. /package/dist/{chunk-7OAIOE5P.js.map → chunk-33G67YZF.js.map} +0 -0
  495. /package/dist/{chunk-AV2OQF2O.js.map → chunk-3F3HA3R2.js.map} +0 -0
  496. /package/dist/{chunk-RP5SJ3XR.js.map → chunk-3GNIJUUE.js.map} +0 -0
  497. /package/dist/{chunk-QZZPUREO.js.map → chunk-3GYSZHMT.js.map} +0 -0
  498. /package/dist/{chunk-SWIKABKI.js.map → chunk-3Q3XD3NO.js.map} +0 -0
  499. /package/dist/{chunk-AL6EHLB5.js.map → chunk-3X3PNU3T.js.map} +0 -0
  500. /package/dist/{chunk-BTJ6CAIA.js.map → chunk-4IYIGN53.js.map} +0 -0
  501. /package/dist/{chunk-BZTRPCCH.js.map → chunk-4PDTVVSW.js.map} +0 -0
  502. /package/dist/{chunk-HM7RHKS4.js.map → chunk-4RNBLLZR.js.map} +0 -0
  503. /package/dist/{chunk-JUWJYXI4.js.map → chunk-5ATSXCAG.js.map} +0 -0
  504. /package/dist/{chunk-EHRE7ZG3.js.map → chunk-5B5WYAHQ.js.map} +0 -0
  505. /package/dist/{chunk-WCGJK4NQ.js.map → chunk-5FNZ3G6X.js.map} +0 -0
  506. /package/dist/{chunk-Y6DZ33PA.js.map → chunk-5GX5457J.js.map} +0 -0
  507. /package/dist/{chunk-EMFBC7L3.js.map → chunk-5KGYTX5O.js.map} +0 -0
  508. /package/dist/{chunk-OFCHT2TN.js.map → chunk-5LRV557D.js.map} +0 -0
  509. /package/dist/{chunk-DXHVD4DS.js.map → chunk-5SMR542T.js.map} +0 -0
  510. /package/dist/{chunk-S7LWX2PQ.js.map → chunk-655FVTCD.js.map} +0 -0
  511. /package/dist/{chunk-DGRMWDQY.js.map → chunk-66BCOVW2.js.map} +0 -0
  512. /package/dist/{chunk-5MDM7UE4.js.map → chunk-6WGMZQGG.js.map} +0 -0
  513. /package/dist/{chunk-IPLYGWQF.js.map → chunk-7LCGFUMB.js.map} +0 -0
  514. /package/dist/{chunk-5ZJYHOJT.js.map → chunk-7VQ6AI7H.js.map} +0 -0
  515. /package/dist/{chunk-KYY4EACB.js.map → chunk-7Z3DLNSD.js.map} +0 -0
  516. /package/dist/{chunk-G7NYVKD6.js.map → chunk-B2NXOVZN.js.map} +0 -0
  517. /package/dist/{chunk-B43NMCGQ.js.map → chunk-BK2BVLZW.js.map} +0 -0
  518. /package/dist/{chunk-BOOFTFFE.js.map → chunk-C2RW36YR.js.map} +0 -0
  519. /package/dist/{chunk-5JMI26Q7.js.map → chunk-CBH2Z4UA.js.map} +0 -0
  520. /package/dist/{chunk-P2S6P7X6.js.map → chunk-CFZ4SXXH.js.map} +0 -0
  521. /package/dist/{chunk-6M56RFFJ.js.map → chunk-CJRENHVZ.js.map} +0 -0
  522. /package/dist/{chunk-EGDYVYU7.js.map → chunk-CLWBFR7Q.js.map} +0 -0
  523. /package/dist/{chunk-6VAHJ2F6.js.map → chunk-DMDWFQMR.js.map} +0 -0
  524. /package/dist/{chunk-UZSBCQEC.js.map → chunk-DPSOFK4D.js.map} +0 -0
  525. /package/dist/{chunk-IZT3BVDW.js.map → chunk-DQR2LD3V.js.map} +0 -0
  526. /package/dist/{chunk-K4QY55XV.js.map → chunk-EH4BQ7LT.js.map} +0 -0
  527. /package/dist/{chunk-EBA5DA77.js.map → chunk-EOU6V4IN.js.map} +0 -0
  528. /package/dist/{chunk-7KYJNHGM.js.map → chunk-EUCYTCFP.js.map} +0 -0
  529. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  530. /package/dist/{chunk-CKUUP64O.js.map → chunk-F2772ATT.js.map} +0 -0
  531. /package/dist/{chunk-46EST7JO.js.map → chunk-F2XNSIPP.js.map} +0 -0
  532. /package/dist/{chunk-2KRNPFPK.js.map → chunk-FLI6DEIU.js.map} +0 -0
  533. /package/dist/{chunk-OAIWPB2I.js.map → chunk-FT4UQYOV.js.map} +0 -0
  534. /package/dist/{chunk-HYNEDMYJ.js.map → chunk-G2OYFTUD.js.map} +0 -0
  535. /package/dist/{chunk-XTN54NML.js.map → chunk-G3T6YMBO.js.map} +0 -0
  536. /package/dist/{chunk-CNG2XVZG.js.map → chunk-G3UUAQOD.js.map} +0 -0
  537. /package/dist/{chunk-2ZQJLBV6.js.map → chunk-GCVDFX66.js.map} +0 -0
  538. /package/dist/{chunk-ON4ILX3G.js.map → chunk-GFAM2LTC.js.map} +0 -0
  539. /package/dist/{chunk-2LUSQV4U.js.map → chunk-GKJJNO7C.js.map} +0 -0
  540. /package/dist/{chunk-T2YX56QI.js.map → chunk-GQJKVQJR.js.map} +0 -0
  541. /package/dist/{chunk-5AOAQR37.js.map → chunk-GWVNGDJW.js.map} +0 -0
  542. /package/dist/{chunk-YDH2FSDI.js.map → chunk-GZXXPCWJ.js.map} +0 -0
  543. /package/dist/{chunk-5JCLELOP.js.map → chunk-H5IUN433.js.map} +0 -0
  544. /package/dist/{chunk-IWHEJXR2.js.map → chunk-H6FREOYX.js.map} +0 -0
  545. /package/dist/{chunk-B7CANWCA.js.map → chunk-HBAOOSHU.js.map} +0 -0
  546. /package/dist/{chunk-T3FMRLWQ.js.map → chunk-HFSPY26A.js.map} +0 -0
  547. /package/dist/{chunk-B657ZGDH.js.map → chunk-HQSK2INQ.js.map} +0 -0
  548. /package/dist/{chunk-RT6D3WN7.js.map → chunk-IJMDBYCO.js.map} +0 -0
  549. /package/dist/{chunk-CS2JEHTB.js.map → chunk-IUCPLBDS.js.map} +0 -0
  550. /package/dist/{chunk-XRBHXUTQ.js.map → chunk-IWD33CF4.js.map} +0 -0
  551. /package/dist/{chunk-4IHBN6WU.js.map → chunk-JKMIGCK6.js.map} +0 -0
  552. /package/dist/{chunk-ROBHL3GL.js.map → chunk-JWX2Q6HS.js.map} +0 -0
  553. /package/dist/{chunk-3I3U6FFT.js.map → chunk-K7BN34IA.js.map} +0 -0
  554. /package/dist/{chunk-4THZGKQ2.js.map → chunk-KLJVTZ3R.js.map} +0 -0
  555. /package/dist/{chunk-4G4B3Z2B.js.map → chunk-KW4AJ7T3.js.map} +0 -0
  556. /package/dist/{chunk-ZI7LMSNI.js.map → chunk-LLHZZOIB.js.map} +0 -0
  557. /package/dist/{chunk-LS2FHUML.js.map → chunk-LQ5SS4OP.js.map} +0 -0
  558. /package/dist/{chunk-NSFOERZQ.js.map → chunk-LWFWZTWX.js.map} +0 -0
  559. /package/dist/{chunk-BMWN7B3Y.js.map → chunk-LXATZLSC.js.map} +0 -0
  560. /package/dist/{chunk-OYKQ6T4V.js.map → chunk-MATDGSJ7.js.map} +0 -0
  561. /package/dist/{chunk-3NFN4Y4P.js.map → chunk-MGCKZWAE.js.map} +0 -0
  562. /package/dist/{chunk-O4KYRDRT.js.map → chunk-MJIOGYKX.js.map} +0 -0
  563. /package/dist/{chunk-6OMUHXHP.js.map → chunk-ML7ZJAKJ.js.map} +0 -0
  564. /package/dist/{chunk-GKIXBH7Y.js.map → chunk-MO6N4QYY.js.map} +0 -0
  565. /package/dist/{chunk-A2E4WNW4.js.map → chunk-MWWAQXZ6.js.map} +0 -0
  566. /package/dist/{chunk-VYPFEVOM.js.map → chunk-NHUX6GXA.js.map} +0 -0
  567. /package/dist/{chunk-AKREOU5F.js.map → chunk-NZCKG25S.js.map} +0 -0
  568. /package/dist/{chunk-4NDWE44P.js.map → chunk-NZFFGO5O.js.map} +0 -0
  569. /package/dist/{chunk-WWSRLS4M.js.map → chunk-O2YPCFJT.js.map} +0 -0
  570. /package/dist/{chunk-ZSJGYC3C.js.map → chunk-OQJKY3Z5.js.map} +0 -0
  571. /package/dist/{chunk-OFEHITAZ.js.map → chunk-OXNTOHL6.js.map} +0 -0
  572. /package/dist/{chunk-FQD2KPQH.js.map → chunk-P55FACBG.js.map} +0 -0
  573. /package/dist/{chunk-JYZSRNR7.js.map → chunk-PIITB2YZ.js.map} +0 -0
  574. /package/dist/{chunk-PBVNVKYN.js.map → chunk-PIN5OPBA.js.map} +0 -0
  575. /package/dist/{chunk-4TTGRETU.js.map → chunk-PRU7OF3Y.js.map} +0 -0
  576. /package/dist/{chunk-K2FSASGZ.js.map → chunk-PVHQSLNN.js.map} +0 -0
  577. /package/dist/{chunk-SVDU4OHO.js.map → chunk-Q35L7TYB.js.map} +0 -0
  578. /package/dist/{chunk-5VC7J76U.js.map → chunk-QPH52AZB.js.map} +0 -0
  579. /package/dist/{chunk-6T42L5FI.js.map → chunk-QS3OLP5I.js.map} +0 -0
  580. /package/dist/{chunk-P34FDDB5.js.map → chunk-QSEUUQUF.js.map} +0 -0
  581. /package/dist/{chunk-PAAJWQH5.js.map → chunk-QUMKDRCF.js.map} +0 -0
  582. /package/dist/{chunk-KZEMFD6E.js.map → chunk-R2H4ZFBJ.js.map} +0 -0
  583. /package/dist/{chunk-JFVCDEIC.js.map → chunk-RP7PQWZM.js.map} +0 -0
  584. /package/dist/{chunk-KC46VZR5.js.map → chunk-RTTPBBAN.js.map} +0 -0
  585. /package/dist/{chunk-ZQ3WU6JO.js.map → chunk-RXFCU3CY.js.map} +0 -0
  586. /package/dist/{chunk-CBP4HWCL.js.map → chunk-RYYVMZBR.js.map} +0 -0
  587. /package/dist/{chunk-2NCBDGND.js.map → chunk-SA6GMZJY.js.map} +0 -0
  588. /package/dist/{chunk-VFTK5WKI.js.map → chunk-STBX5X6B.js.map} +0 -0
  589. /package/dist/{chunk-WVHRNAXL.js.map → chunk-SWWHIJUJ.js.map} +0 -0
  590. /package/dist/{chunk-WADSXS4K.js.map → chunk-SX4QDWXK.js.map} +0 -0
  591. /package/dist/{chunk-WETFW255.js.map → chunk-T7ASDYNK.js.map} +0 -0
  592. /package/dist/{chunk-XZLWYZ7C.js.map → chunk-THEPGZBM.js.map} +0 -0
  593. /package/dist/{chunk-YEM7K3KD.js.map → chunk-TMC7HBED.js.map} +0 -0
  594. /package/dist/{chunk-RWRQ67OR.js.map → chunk-TPNCXSXP.js.map} +0 -0
  595. /package/dist/{chunk-LZKOVXMX.js.map → chunk-TRMJ6BYC.js.map} +0 -0
  596. /package/dist/{chunk-A6TVQ3QP.js.map → chunk-UGYUBENJ.js.map} +0 -0
  597. /package/dist/{chunk-AAM66QCP.js.map → chunk-UZRSI6NX.js.map} +0 -0
  598. /package/dist/{chunk-XHWJRUVP.js.map → chunk-V3TXIXXY.js.map} +0 -0
  599. /package/dist/{chunk-2CXQZXWM.js.map → chunk-V4MB5ONM.js.map} +0 -0
  600. /package/dist/{chunk-UOKPJFO3.js.map → chunk-VNZMZPAC.js.map} +0 -0
  601. /package/dist/{chunk-FZB4TS2W.js.map → chunk-VPXIKBPX.js.map} +0 -0
  602. /package/dist/{chunk-CYEK6Z3P.js.map → chunk-VW6VIJOS.js.map} +0 -0
  603. /package/dist/{chunk-QUA7RLK6.js.map → chunk-W3FVQBGF.js.map} +0 -0
  604. /package/dist/{chunk-6OQ6N5RP.js.map → chunk-WGTR573G.js.map} +0 -0
  605. /package/dist/{chunk-W3K3HITK.js.map → chunk-WLT6LTQP.js.map} +0 -0
  606. /package/dist/{chunk-6Z2AZ4AJ.js.map → chunk-XKRXN63M.js.map} +0 -0
  607. /package/dist/{chunk-FZVROZKC.js.map → chunk-XVZA6VXC.js.map} +0 -0
  608. /package/dist/{chunk-DA2INEB5.js.map → chunk-XYGQSDTH.js.map} +0 -0
  609. /package/dist/{chunk-RBJQYMMT.js.map → chunk-YRULQW5J.js.map} +0 -0
  610. /package/dist/{chunk-QUNDYIYZ.js.map → chunk-YYEOR4XN.js.map} +0 -0
  611. /package/dist/{chunk-6WHJ2EAB.js.map → chunk-Z64TS5V4.js.map} +0 -0
  612. /package/dist/{chunk-NHLLKEKK.js.map → chunk-ZAJLJ35W.js.map} +0 -0
  613. /package/dist/{chunk-M7V65M6H.js.map → chunk-ZKHSAMTE.js.map} +0 -0
  614. /package/dist/{resolution-EKJHREVJ.js.map → dreams-ledger-UCHHRQ4R.js.map} +0 -0
@@ -0,0 +1,534 @@
1
+ import assert from "node:assert/strict";
2
+ import { mkdtemp, rm } from "node:fs/promises";
3
+ import os from "node:os";
4
+ import path from "node:path";
5
+ import test from "node:test";
6
+
7
+ import { isAbortError } from "./abort-error.js";
8
+ import {
9
+ CAPTURE_WRITE_LOCK_BUSY_MESSAGE,
10
+ DEFAULT_CAPTURE_WRITE_LOCK_DEADLINE_MS,
11
+ DEFAULT_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
12
+ LEGACY_CAPTURE_WRITE_LOCK_DEADLINE_MS,
13
+ LEGACY_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
14
+ LEGACY_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
15
+ DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
16
+ MAX_CAPTURE_WRITE_LOCK_WAIT_MS,
17
+ captureWriteLockDelayMs,
18
+ isTombstoneBlockedCaptureWriteLockBusy,
19
+ resolveCaptureWriteLockBackoffLimits,
20
+ } from "./capture-write-lock-backoff.js";
21
+ import { parseConfig } from "./config.js";
22
+ import { resolveConvergeCaptureWriteLockBackoff } from "./converge-config.js";
23
+ import { TombstoneBlockedCaptureWriteLock } from "./storage/tombstone-blocked-capture-mutation.js";
24
+ import type { withHeldFileLock } from "./utils/serialize-mutations.js";
25
+
26
+ const LIMITS = {
27
+ initialDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
28
+ maxDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
29
+ };
30
+
31
+ test("capture write lock backoff is bounded and capped", () => {
32
+ assert.equal(
33
+ captureWriteLockDelayMs(0, LIMITS, () => 0),
34
+ 25
35
+ );
36
+ assert.equal(
37
+ captureWriteLockDelayMs(0, LIMITS, () => 1),
38
+ 50
39
+ );
40
+ assert.equal(
41
+ captureWriteLockDelayMs(1, LIMITS, () => 1),
42
+ 100
43
+ );
44
+
45
+ for (let attempt = 0; attempt < 20; attempt += 1) {
46
+ const exponent = Math.min(attempt, 16);
47
+ const ceiling = Math.min(LIMITS.maxDelayMs, LIMITS.initialDelayMs * 2 ** exponent);
48
+ const floor = Math.ceil(ceiling / 2);
49
+ for (const unit of [0, 0.5, 1]) {
50
+ const delay = captureWriteLockDelayMs(attempt, LIMITS, () => unit);
51
+ assert.ok(delay >= floor && delay <= ceiling, `attempt ${attempt} unit ${unit} delay ${delay}`);
52
+ assert.ok(delay <= DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS);
53
+ }
54
+ }
55
+
56
+ const capped = { initialDelayMs: 50, maxDelayMs: 2_000 };
57
+ assert.equal(
58
+ captureWriteLockDelayMs(16, capped, () => 1),
59
+ 2_000
60
+ );
61
+ assert.equal(
62
+ captureWriteLockDelayMs(19, capped, () => 0),
63
+ 1_000
64
+ );
65
+ assert.equal(
66
+ captureWriteLockDelayMs(4, { initialDelayMs: 1, maxDelayMs: 1 }, () => 1),
67
+ 1
68
+ );
69
+ });
70
+
71
+ test("capture write lock acquire succeeds after a brief hold", async () => {
72
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-brief-"));
73
+ try {
74
+ let now = 0;
75
+ let held = 0;
76
+ let probes = 0;
77
+ let busy = true;
78
+ const sleeps: number[] = [];
79
+ const debugs: string[] = [];
80
+ const warns: string[] = [];
81
+ const lock = new TombstoneBlockedCaptureWriteLock({
82
+ stateDir: dir,
83
+ lockOptions: () => ({
84
+ captureWriteLockInitialDelayMs: 50,
85
+ captureWriteLockMaxDelayMs: 200,
86
+ captureWriteLockDeadlineMs: 1_000,
87
+ }),
88
+ now: () => now,
89
+ random: () => 0,
90
+ sleep: async (ms) => {
91
+ assert.equal(held, 0, "backoff must run only after every capture lock is released");
92
+ sleeps.push(ms);
93
+ now += ms;
94
+ busy = false;
95
+ },
96
+ logDebug: (message) => debugs.push(message),
97
+ logWarn: (message) => warns.push(message),
98
+ withHeldFileLock: (async (_lockPath, options, task) => {
99
+ assert.equal(options.maxWaitMs, 1);
100
+ assert.equal(options.pollMs, 1);
101
+ probes += 1;
102
+ // The second lock in the chain stays busy for one attempt, while the
103
+ // first lock is already held. Sleep must observe that hold released.
104
+ if (probes % 2 === 0 && busy) {
105
+ return await task(false, { failure: "timeout", refresh: async () => false });
106
+ }
107
+ held += 1;
108
+ try {
109
+ return await task(true, { refresh: async () => true });
110
+ } finally {
111
+ held -= 1;
112
+ }
113
+ }) as typeof withHeldFileLock,
114
+ });
115
+
116
+ const value = await lock.withCaptureWriteLock(async () => "acquired", ["first-identity", "second-identity"]);
117
+ assert.equal(value, "acquired");
118
+ assert.ok(sleeps.length >= 1);
119
+ assert.ok(sleeps.every((ms) => ms <= 200));
120
+ assert.equal(warns.length, 0);
121
+ assert.ok(debugs.some((line) => line.includes("backing off")));
122
+ } finally {
123
+ await rm(dir, { recursive: true, force: true });
124
+ }
125
+ });
126
+
127
+ test("capture write lock deadline fails with the busy error", async () => {
128
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-deadline-"));
129
+ try {
130
+ let now = 0;
131
+ const held = 0;
132
+ const sleeps: number[] = [];
133
+ const debugs: string[] = [];
134
+ const warns: string[] = [];
135
+ const lock = new TombstoneBlockedCaptureWriteLock({
136
+ stateDir: dir,
137
+ lockOptions: () => ({
138
+ captureWriteLockInitialDelayMs: 20,
139
+ captureWriteLockMaxDelayMs: 20,
140
+ captureWriteLockDeadlineMs: 80,
141
+ }),
142
+ now: () => now,
143
+ random: () => 1,
144
+ sleep: async (ms) => {
145
+ assert.equal(held, 0, "backoff must run only after every capture lock is released");
146
+ assert.ok(ms <= 20);
147
+ sleeps.push(ms);
148
+ now += ms;
149
+ },
150
+ logDebug: (message) => debugs.push(message),
151
+ logWarn: (message) => warns.push(message),
152
+ withHeldFileLock: (async (_lockPath, _options, task) => {
153
+ return await task(false, { failure: "timeout", refresh: async () => false });
154
+ }) as typeof withHeldFileLock,
155
+ });
156
+
157
+ await assert.rejects(
158
+ lock.withCaptureWriteLock(async () => "unreachable", "held-identity"),
159
+ (error: unknown) => {
160
+ assert.equal(isTombstoneBlockedCaptureWriteLockBusy(error), true);
161
+ assert.ok(error instanceof Error);
162
+ assert.equal(error.message, CAPTURE_WRITE_LOCK_BUSY_MESSAGE);
163
+ return true;
164
+ }
165
+ );
166
+ assert.equal(warns.length, 1);
167
+ assert.match(warns[0] ?? "", /remained busy after 80ms/);
168
+ assert.ok(debugs.length >= 1);
169
+ assert.ok(sleeps.length >= 1);
170
+ assert.ok(now >= 80);
171
+ } finally {
172
+ await rm(dir, { recursive: true, force: true });
173
+ }
174
+ });
175
+
176
+ test("aborted capture write lock does not probe, sleep, or write", async () => {
177
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-aborted-"));
178
+ try {
179
+ const controller = new AbortController();
180
+ controller.abort();
181
+ let probes = 0;
182
+ let slept = false;
183
+ let ran = false;
184
+ const warns: string[] = [];
185
+ const lock = new TombstoneBlockedCaptureWriteLock({
186
+ stateDir: dir,
187
+ lockOptions: () => ({ captureWriteLockSignal: controller.signal }),
188
+ sleep: async () => {
189
+ slept = true;
190
+ },
191
+ logWarn: (message) => warns.push(message),
192
+ withHeldFileLock: (async () => {
193
+ probes += 1;
194
+ return "held";
195
+ }) as typeof withHeldFileLock,
196
+ });
197
+ await assert.rejects(
198
+ lock.withCaptureWriteLock(async () => {
199
+ ran = true;
200
+ return "written";
201
+ }, "path 1 x"),
202
+ (error: unknown) => isAbortError(error)
203
+ );
204
+ assert.equal(probes, 0);
205
+ assert.equal(slept, false);
206
+ assert.equal(ran, false);
207
+ assert.equal(warns.length, 0);
208
+ } finally {
209
+ await rm(dir, { recursive: true, force: true });
210
+ }
211
+ });
212
+
213
+ test("abort during capture write lock backoff does not run the write", async () => {
214
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-abort-sleep-"));
215
+ try {
216
+ const controller = new AbortController();
217
+ let probes = 0;
218
+ let ran = false;
219
+ const warns: string[] = [];
220
+ const lock = new TombstoneBlockedCaptureWriteLock({
221
+ stateDir: dir,
222
+ signal: controller.signal,
223
+ lockOptions: () => ({
224
+ captureWriteLockInitialDelayMs: 40,
225
+ captureWriteLockMaxDelayMs: 40,
226
+ captureWriteLockDeadlineMs: 400,
227
+ }),
228
+ now: () => 0,
229
+ random: () => 1,
230
+ sleep: async () => {
231
+ controller.abort();
232
+ },
233
+ logWarn: (message) => warns.push(message),
234
+ withHeldFileLock: (async (_lockPath, _options, task) => {
235
+ probes += 1;
236
+ if (probes === 1) {
237
+ return await task(false, { failure: "timeout", refresh: async () => false });
238
+ }
239
+ return await task(true, { refresh: async () => true });
240
+ }) as typeof withHeldFileLock,
241
+ });
242
+ await assert.rejects(
243
+ lock.withCaptureWriteLock(async () => {
244
+ ran = true;
245
+ return "written";
246
+ }, "held-identity"),
247
+ (error: unknown) => isAbortError(error)
248
+ );
249
+ assert.equal(probes, 1);
250
+ assert.equal(ran, false);
251
+ assert.equal(warns.length, 0);
252
+ } finally {
253
+ await rm(dir, { recursive: true, force: true });
254
+ }
255
+ });
256
+
257
+ test("abort is rechecked after the capture write lock is acquired", async () => {
258
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-abort-held-"));
259
+ try {
260
+ const controller = new AbortController();
261
+ let ran = false;
262
+ const lock = new TombstoneBlockedCaptureWriteLock({
263
+ stateDir: dir,
264
+ lockOptions: () => ({ captureWriteLockSignal: controller.signal }),
265
+ withHeldFileLock: (async (_lockPath, _options, task) => {
266
+ controller.abort();
267
+ return await task(true, { refresh: async () => true });
268
+ }) as typeof withHeldFileLock,
269
+ });
270
+ await assert.rejects(
271
+ lock.withCaptureWriteLock(async () => {
272
+ ran = true;
273
+ return "written";
274
+ }, "held-identity"),
275
+ (error: unknown) => isAbortError(error)
276
+ );
277
+ assert.equal(ran, false);
278
+ } finally {
279
+ await rm(dir, { recursive: true, force: true });
280
+ }
281
+ });
282
+
283
+ test("capture write lock backoff config rejects junk and inverted schedules", () => {
284
+ assert.deepEqual(parseConfig({}).converge, { conflictPolicy: "newest-wins" });
285
+ // No lock-options source is a plain (non-converge) capture: short legacy bounds.
286
+ assert.deepEqual(resolveCaptureWriteLockBackoffLimits(undefined), {
287
+ initialDelayMs: LEGACY_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
288
+ maxDelayMs: LEGACY_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
289
+ deadlineMs: LEGACY_CAPTURE_WRITE_LOCK_DEADLINE_MS,
290
+ });
291
+ // A converge source with no overrides gets the long converge defaults.
292
+ assert.deepEqual(resolveCaptureWriteLockBackoffLimits({}), {
293
+ initialDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
294
+ maxDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
295
+ deadlineMs: DEFAULT_CAPTURE_WRITE_LOCK_DEADLINE_MS,
296
+ });
297
+
298
+ const parsed = parseConfig({
299
+ converge: {
300
+ captureWriteLockInitialDelayMs: 40,
301
+ captureWriteLockMaxDelayMs: MAX_CAPTURE_WRITE_LOCK_WAIT_MS + 5,
302
+ captureWriteLockDeadlineMs: MAX_CAPTURE_WRITE_LOCK_WAIT_MS + 9,
303
+ },
304
+ });
305
+ assert.equal(parsed.converge.captureWriteLockInitialDelayMs, 40);
306
+ assert.equal(parsed.converge.captureWriteLockMaxDelayMs, MAX_CAPTURE_WRITE_LOCK_WAIT_MS);
307
+ assert.equal(parsed.converge.captureWriteLockDeadlineMs, MAX_CAPTURE_WRITE_LOCK_WAIT_MS);
308
+
309
+ for (const value of [0, 1.5, -1, "50", Number.NaN]) {
310
+ assert.throws(
311
+ () => parseConfig({ converge: { captureWriteLockInitialDelayMs: value as number } }),
312
+ /captureWriteLockInitialDelayMs must be a positive integer/
313
+ );
314
+ }
315
+ assert.throws(
316
+ () =>
317
+ parseConfig({
318
+ converge: { captureWriteLockInitialDelayMs: 80, captureWriteLockMaxDelayMs: 40 },
319
+ }),
320
+ /captureWriteLockInitialDelayMs \(80\) must be <= converge.captureWriteLockMaxDelayMs \(40\)/
321
+ );
322
+ assert.throws(
323
+ () =>
324
+ parseConfig({
325
+ converge: { captureWriteLockMaxDelayMs: 500, captureWriteLockDeadlineMs: 100 },
326
+ }),
327
+ /captureWriteLockMaxDelayMs \(500\) must be <= converge.captureWriteLockDeadlineMs \(100\)/
328
+ );
329
+ assert.throws(
330
+ () => resolveConvergeCaptureWriteLockBackoff({ conflictPolicy: "newest-wins", captureWriteLockDeadlineMs: 40 }),
331
+ /captureWriteLockMaxDelayMs \(2000\) must be <= captureWriteLockDeadlineMs \(40\)/
332
+ );
333
+ });
334
+
335
+ test("capture write lock backoff env yields to config", () => {
336
+ const keys = [
337
+ "REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS",
338
+ "REMNIC_CONVERGE_CAPTURE_LOCK_MAX_DELAY_MS",
339
+ "REMNIC_CONVERGE_CAPTURE_LOCK_DEADLINE_MS",
340
+ "ENGRAM_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS",
341
+ "ENGRAM_CONVERGE_CAPTURE_LOCK_MAX_DELAY_MS",
342
+ "ENGRAM_CONVERGE_CAPTURE_LOCK_DEADLINE_MS",
343
+ ] as const;
344
+ const saved = new Map<string, string | undefined>();
345
+ for (const key of keys) saved.set(key, process.env[key]);
346
+ try {
347
+ for (const key of keys) delete process.env[key];
348
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS = "30";
349
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_MAX_DELAY_MS = "90";
350
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_DEADLINE_MS = "400";
351
+ assert.deepEqual(resolveConvergeCaptureWriteLockBackoff({ conflictPolicy: "newest-wins" }), {
352
+ initialDelayMs: 30,
353
+ maxDelayMs: 90,
354
+ deadlineMs: 400,
355
+ });
356
+
357
+ for (const key of keys) delete process.env[key];
358
+ process.env.ENGRAM_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS = "30";
359
+ process.env.ENGRAM_CONVERGE_CAPTURE_LOCK_MAX_DELAY_MS = "90";
360
+ process.env.ENGRAM_CONVERGE_CAPTURE_LOCK_DEADLINE_MS = "400";
361
+ assert.equal(resolveConvergeCaptureWriteLockBackoff({ conflictPolicy: "newest-wins" }).initialDelayMs, 30);
362
+
363
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS = "80";
364
+ const overridden = resolveConvergeCaptureWriteLockBackoff({
365
+ conflictPolicy: "newest-wins",
366
+ captureWriteLockInitialDelayMs: 40,
367
+ captureWriteLockMaxDelayMs: 80,
368
+ captureWriteLockDeadlineMs: 200,
369
+ });
370
+ assert.equal(overridden.initialDelayMs, 40);
371
+
372
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS = "0";
373
+ assert.throws(
374
+ () => resolveConvergeCaptureWriteLockBackoff({ conflictPolicy: "newest-wins" }),
375
+ /REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS must be a positive integer/
376
+ );
377
+ process.env.REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS = "nope";
378
+ assert.throws(
379
+ () => resolveConvergeCaptureWriteLockBackoff({ conflictPolicy: "newest-wins" }),
380
+ /REMNIC_CONVERGE_CAPTURE_LOCK_INITIAL_DELAY_MS must be a positive integer/
381
+ );
382
+ } finally {
383
+ for (const key of keys) {
384
+ const value = saved.get(key);
385
+ if (value === undefined) delete process.env[key];
386
+ else process.env[key] = value;
387
+ }
388
+ }
389
+ });
390
+
391
+ test("capture write lock deadline is checked before each lock probe", async () => {
392
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-probe-deadline-"));
393
+ try {
394
+ let now = 0;
395
+ let probes = 0;
396
+ const lock = new TombstoneBlockedCaptureWriteLock({
397
+ stateDir: dir,
398
+ lockOptions: () => ({
399
+ captureWriteLockInitialDelayMs: 20,
400
+ captureWriteLockMaxDelayMs: 20,
401
+ captureWriteLockDeadlineMs: 100,
402
+ }),
403
+ now: () => now,
404
+ random: () => 1,
405
+ sleep: async (ms) => {
406
+ // The backoff itself pushes the clock past the deadline.
407
+ now += 200 + ms;
408
+ },
409
+ withHeldFileLock: (async (_lockPath, _options, task) => {
410
+ probes += 1;
411
+ return await task(false, { failure: "timeout", refresh: async () => false });
412
+ }) as typeof withHeldFileLock,
413
+ });
414
+
415
+ await assert.rejects(
416
+ lock.withCaptureWriteLock(async () => "unreachable", "held-identity"),
417
+ (error: unknown) => isTombstoneBlockedCaptureWriteLockBusy(error)
418
+ );
419
+ // The first attempt probed once; the deadline must fail the second
420
+ // attempt before it probes the lock file again.
421
+ assert.equal(probes, 1);
422
+ } finally {
423
+ await rm(dir, { recursive: true, force: true });
424
+ }
425
+ });
426
+
427
+ test("capture write lock deadline is checked right before the write", async () => {
428
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-write-deadline-"));
429
+ try {
430
+ let now = 0;
431
+ let ran = false;
432
+ const lock = new TombstoneBlockedCaptureWriteLock({
433
+ stateDir: dir,
434
+ lockOptions: () => ({
435
+ captureWriteLockInitialDelayMs: 20,
436
+ captureWriteLockMaxDelayMs: 20,
437
+ captureWriteLockDeadlineMs: 1_000,
438
+ }),
439
+ now: () => now,
440
+ withHeldFileLock: (async (_lockPath, _options, task) => {
441
+ // Waiting for the lock file consumed the whole deadline.
442
+ now += 5_000;
443
+ return await task(true, { refresh: async () => true });
444
+ }) as typeof withHeldFileLock,
445
+ });
446
+
447
+ await assert.rejects(
448
+ lock.withCaptureWriteLock(async () => {
449
+ ran = true;
450
+ return "written";
451
+ }, "held-identity"),
452
+ (error: unknown) => isTombstoneBlockedCaptureWriteLockBusy(error)
453
+ );
454
+ assert.equal(ran, false, "the write must not run once the deadline has passed");
455
+ } finally {
456
+ await rm(dir, { recursive: true, force: true });
457
+ }
458
+ });
459
+
460
+ test("aborting capture write lock backoff cancels the pending timer", async () => {
461
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-timer-cancel-"));
462
+ try {
463
+ const controller = new AbortController();
464
+ // Real timers on purpose: this test observes that abort clears the live
465
+ // Timeout handle the default backoff sleep created (same approach as the
466
+ // sleepAbortable tests in console/trace.test.ts).
467
+ const baseline = process.getActiveResourcesInfo().filter((entry) => entry === "Timeout").length;
468
+ const lock = new TombstoneBlockedCaptureWriteLock({
469
+ stateDir: dir,
470
+ signal: controller.signal,
471
+ lockOptions: () => ({
472
+ captureWriteLockInitialDelayMs: 5_000,
473
+ captureWriteLockMaxDelayMs: 5_000,
474
+ captureWriteLockDeadlineMs: 60_000,
475
+ }),
476
+ random: () => 1,
477
+ withHeldFileLock: (async (_lockPath, _options, task) => {
478
+ return await task(false, { failure: "timeout", refresh: async () => false });
479
+ }) as typeof withHeldFileLock,
480
+ });
481
+
482
+ const abortTimer = setTimeout(() => controller.abort(), 25);
483
+ try {
484
+ const started = Date.now();
485
+ await assert.rejects(
486
+ lock.withCaptureWriteLock(async () => "unreachable", "held-identity"),
487
+ (error: unknown) => isAbortError(error)
488
+ );
489
+ assert.ok(Date.now() - started < 1_000, "abort must not wait out the 5s backoff");
490
+ await new Promise((resolve) => setImmediate(resolve));
491
+ assert.equal(
492
+ process.getActiveResourcesInfo().filter((entry) => entry === "Timeout").length,
493
+ baseline,
494
+ "the cancelled backoff timer must be cleared, not left to fire"
495
+ );
496
+ } finally {
497
+ clearTimeout(abortTimer);
498
+ }
499
+ } finally {
500
+ await rm(dir, { recursive: true, force: true });
501
+ }
502
+ });
503
+
504
+ test("a capture without lock options keeps the short legacy backoff", async () => {
505
+ const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-capture-lock-legacy-"));
506
+ try {
507
+ let now = 0;
508
+ const sleeps: number[] = [];
509
+ const lock = new TombstoneBlockedCaptureWriteLock({
510
+ stateDir: dir,
511
+ now: () => now,
512
+ random: () => 1,
513
+ sleep: async (ms) => {
514
+ sleeps.push(ms);
515
+ now += ms;
516
+ },
517
+ withHeldFileLock: (async (_lockPath, _options, task) => {
518
+ return await task(false, { failure: "timeout", refresh: async () => false });
519
+ }) as typeof withHeldFileLock,
520
+ });
521
+
522
+ await assert.rejects(
523
+ lock.withCaptureWriteLock(async () => "unreachable", "held-identity"),
524
+ (error: unknown) => isTombstoneBlockedCaptureWriteLockBusy(error)
525
+ );
526
+ // Bounded legacy tolerance: short waits, the ~3s pre-backoff deadline,
527
+ // then the busy error — not the 60s converge deadline.
528
+ assert.ok(sleeps.length >= 3);
529
+ assert.ok(sleeps.every((ms) => ms >= 12 && ms <= 50), `sleeps out of legacy range: ${sleeps.join(",")}`);
530
+ assert.ok(now >= 3_000 && now < 3_100, `expected the ~3s legacy deadline, stopped at ${now}`);
531
+ } finally {
532
+ await rm(dir, { recursive: true, force: true });
533
+ }
534
+ });
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Backoff for the tombstone-blocked capture write lock (COS-392).
3
+ *
4
+ * A converge cycle used to give up after three probes about 25ms apart while
5
+ * the daemon still held the lock for an ordinary write. Waiters now sleep
6
+ * outside every lock: equal-jitter exponential backoff, capped per wait, with
7
+ * one overall deadline. The numbers are the production defaults; converge
8
+ * config and env can override them.
9
+ */
10
+
11
+ export const CAPTURE_WRITE_LOCK_BUSY_MESSAGE = "tombstone-blocked capture write lock remained busy";
12
+
13
+ export function isTombstoneBlockedCaptureWriteLockBusy(error: unknown): boolean {
14
+ return error instanceof Error && error.message === CAPTURE_WRITE_LOCK_BUSY_MESSAGE;
15
+ }
16
+
17
+ export const DEFAULT_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS = 50;
18
+ export const DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS = 2_000;
19
+ export const DEFAULT_CAPTURE_WRITE_LOCK_DEADLINE_MS = 60_000;
20
+ /** Same hour ceiling as the converge peer HTTP timeout. */
21
+ export const MAX_CAPTURE_WRITE_LOCK_WAIT_MS = 3_600_000;
22
+
23
+ const MAX_BACKOFF_EXPONENT = 16;
24
+
25
+ export type CaptureWriteLockBackoffLimits = {
26
+ readonly initialDelayMs: number;
27
+ readonly maxDelayMs: number;
28
+ readonly deadlineMs: number;
29
+ };
30
+
31
+ export type CaptureWriteLockLimitSource = {
32
+ readonly captureWriteLockInitialDelayMs?: number;
33
+ readonly captureWriteLockMaxDelayMs?: number;
34
+ readonly captureWriteLockDeadlineMs?: number;
35
+ /**
36
+ * Read when an acquire starts. Converge installs the apply abort signal
37
+ * here so a SIGINT during backoff never reaches the guarded write.
38
+ */
39
+ readonly captureWriteLockSignal?: AbortSignal;
40
+ };
41
+
42
+ /**
43
+ * One backoff wait. Attempt 0 is uniform in `[ceil(initial/2), initial]`
44
+ * (25–50ms at the defaults). Each later attempt doubles that window until
45
+ * `maxDelayMs`. `random` returns a finite number in `[0, 1]`.
46
+ */
47
+ export function captureWriteLockDelayMs(
48
+ attempt: number,
49
+ limits: Pick<CaptureWriteLockBackoffLimits, "initialDelayMs" | "maxDelayMs">,
50
+ random: () => number = Math.random
51
+ ): number {
52
+ if (!Number.isInteger(attempt) || attempt < 0) {
53
+ throw new TypeError("capture write lock backoff attempt must be a non-negative integer");
54
+ }
55
+ if (!Number.isInteger(limits.initialDelayMs) || limits.initialDelayMs <= 0) {
56
+ throw new TypeError("capture write lock initialDelayMs must be a positive integer");
57
+ }
58
+ if (!Number.isInteger(limits.maxDelayMs) || limits.maxDelayMs <= 0) {
59
+ throw new TypeError("capture write lock maxDelayMs must be a positive integer");
60
+ }
61
+ if (limits.initialDelayMs > limits.maxDelayMs) {
62
+ throw new TypeError("capture write lock initialDelayMs must be <= maxDelayMs");
63
+ }
64
+ const unit = random();
65
+ if (typeof unit !== "number" || !Number.isFinite(unit) || unit < 0 || unit > 1) {
66
+ throw new TypeError("capture write lock jitter source must return a finite number in [0, 1]");
67
+ }
68
+ const exponent = Math.min(attempt, MAX_BACKOFF_EXPONENT);
69
+ const ceiling = Math.min(limits.maxDelayMs, limits.initialDelayMs * 2 ** exponent);
70
+ const floor = Math.ceil(ceiling / 2);
71
+ if (ceiling <= floor) return ceiling;
72
+ const span = ceiling - floor;
73
+ const offset = Math.min(span, Math.floor(unit * (span + 1)));
74
+ return floor + offset;
75
+ }
76
+
77
+ export function normalizeCaptureWriteLockWaitMs(value: unknown, label: string): number {
78
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
79
+ throw new Error(`${label} must be a positive integer number of milliseconds; got ${JSON.stringify(value)}`);
80
+ }
81
+ return Math.min(value, MAX_CAPTURE_WRITE_LOCK_WAIT_MS);
82
+ }
83
+
84
+ function pickWaitMs(value: number | undefined, fallback: number, label: string): number {
85
+ if (value === undefined) return fallback;
86
+ return normalizeCaptureWriteLockWaitMs(value, label);
87
+ }
88
+
89
+ /**
90
+ * Limits for a capture with no lock-options source — the plain daemon or an
91
+ * inline capture. The deadline matches the pre-backoff tolerance of about 3s
92
+ * (three probe waits of up to 1s each plus short retry sleeps), so ordinary
93
+ * capture contention keeps that wait and still fails in bounded time.
94
+ */
95
+ export const LEGACY_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS = 25;
96
+ export const LEGACY_CAPTURE_WRITE_LOCK_MAX_DELAY_MS = 50;
97
+ export const LEGACY_CAPTURE_WRITE_LOCK_DEADLINE_MS = 3_000;
98
+
99
+ /** Fill omitted knobs from the defaults and reject an inverted schedule. */
100
+ export function resolveCaptureWriteLockBackoffLimits(
101
+ source: CaptureWriteLockLimitSource | undefined
102
+ ): CaptureWriteLockBackoffLimits {
103
+ // No source means a non-converge capture: keep the short legacy bounds.
104
+ const defaults =
105
+ source === undefined
106
+ ? {
107
+ initialDelayMs: LEGACY_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
108
+ maxDelayMs: LEGACY_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
109
+ deadlineMs: LEGACY_CAPTURE_WRITE_LOCK_DEADLINE_MS,
110
+ }
111
+ : {
112
+ initialDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_INITIAL_DELAY_MS,
113
+ maxDelayMs: DEFAULT_CAPTURE_WRITE_LOCK_MAX_DELAY_MS,
114
+ deadlineMs: DEFAULT_CAPTURE_WRITE_LOCK_DEADLINE_MS,
115
+ };
116
+ const initialDelayMs = pickWaitMs(
117
+ source?.captureWriteLockInitialDelayMs,
118
+ defaults.initialDelayMs,
119
+ "captureWriteLockInitialDelayMs"
120
+ );
121
+ const maxDelayMs = pickWaitMs(
122
+ source?.captureWriteLockMaxDelayMs,
123
+ defaults.maxDelayMs,
124
+ "captureWriteLockMaxDelayMs"
125
+ );
126
+ const deadlineMs = pickWaitMs(
127
+ source?.captureWriteLockDeadlineMs,
128
+ defaults.deadlineMs,
129
+ "captureWriteLockDeadlineMs"
130
+ );
131
+ if (initialDelayMs > maxDelayMs) {
132
+ throw new Error(
133
+ `captureWriteLockInitialDelayMs (${initialDelayMs}) must be <= captureWriteLockMaxDelayMs (${maxDelayMs})`
134
+ );
135
+ }
136
+ if (maxDelayMs > deadlineMs) {
137
+ throw new Error(`captureWriteLockMaxDelayMs (${maxDelayMs}) must be <= captureWriteLockDeadlineMs (${deadlineMs})`);
138
+ }
139
+ return { initialDelayMs, maxDelayMs, deadlineMs };
140
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Public seam for the tombstone-blocked capture write lock.
3
+ * Converge tests hold the same lock the apply path acquires.
4
+ */
5
+ export {
6
+ buildCapturePathLockIdentity,
7
+ TombstoneBlockedCaptureWriteLock,
8
+ } from "./storage/tombstone-blocked-capture-mutation.js";