@remnic/core 9.65.7 → 9.66.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 (713) hide show
  1. package/dist/access-admin-ops-surface.d.ts +15 -14
  2. package/dist/access-admin-ops-surface.js +65 -62
  3. package/dist/access-authorization-probe.d.ts +15 -14
  4. package/dist/access-authorization-probe.js +66 -63
  5. package/dist/access-boundary.d.ts +15 -14
  6. package/dist/access-boundary.js +65 -62
  7. package/dist/access-citation-namespace.js +3 -3
  8. package/dist/access-cli.js +182 -174
  9. package/dist/access-cli.js.map +1 -1
  10. package/dist/access-coding-context-resolution.d.ts +2 -2
  11. package/dist/access-coding-context-resolution.js +2 -2
  12. package/dist/access-extraction-force-flush.d.ts +15 -14
  13. package/dist/access-extraction-force-flush.js +65 -62
  14. package/dist/access-health-types.d.ts +2 -2
  15. package/dist/access-http-lcm-compaction.d.ts +15 -14
  16. package/dist/access-http-lifecycle-flush.d.ts +15 -14
  17. package/dist/access-http-offline-stream.d.ts +15 -14
  18. package/dist/access-http-query.d.ts +3 -3
  19. package/dist/access-http-query.js +67 -64
  20. package/dist/access-http.d.ts +16 -15
  21. package/dist/access-http.js +87 -84
  22. package/dist/access-identity-continuity-surface.d.ts +13 -12
  23. package/dist/access-identity-continuity-surface.js +65 -62
  24. package/dist/access-lcm-surface.d.ts +15 -14
  25. package/dist/access-lcm-surface.js +65 -62
  26. package/dist/access-mcp-output-schemas.js +1 -1
  27. package/dist/access-mcp.d.ts +15 -14
  28. package/dist/access-mcp.js +77 -74
  29. package/dist/access-memory-search-fanout.d.ts +3 -3
  30. package/dist/{access-namespace-preflight-8VYKmRX0.d.ts → access-namespace-preflight-CLWUoMyW.d.ts} +1 -1
  31. package/dist/access-namespace-preflight.d.ts +4 -4
  32. package/dist/access-namespace-preflight.js +65 -62
  33. package/dist/access-observe-write-surface.d.ts +15 -14
  34. package/dist/access-observe-write-surface.js +65 -62
  35. package/dist/access-offline-manifest.d.ts +13 -12
  36. package/dist/access-offline-manifest.js +16 -16
  37. package/dist/access-operations-batch.js +69 -66
  38. package/dist/access-operations.d.ts +16 -15
  39. package/dist/access-operations.js +74 -71
  40. package/dist/access-recall-concurrency.d.ts +15 -14
  41. package/dist/access-recall-concurrency.js +65 -62
  42. package/dist/access-recall-response.d.ts +15 -14
  43. package/dist/access-recall-response.js +65 -62
  44. package/dist/access-recall-surface.d.ts +15 -14
  45. package/dist/access-recall-surface.js +65 -62
  46. package/dist/access-schema.js +7 -7
  47. package/dist/{access-service-Crk__Git.d.ts → access-service-CEUE1Isj.d.ts} +14 -14
  48. package/dist/access-service-helpers.d.ts +15 -14
  49. package/dist/access-service.d.ts +15 -14
  50. package/dist/access-service.js +65 -62
  51. package/dist/access-surface-catalog.d.ts +15 -14
  52. package/dist/access-surface-catalog.js +69 -64
  53. package/dist/access-surface-catalog.js.map +1 -1
  54. package/dist/access-wearables-meetings-surface.d.ts +6 -4
  55. package/dist/action-confidence.d.ts +2 -2
  56. package/dist/active-context-config.d.ts +27 -0
  57. package/dist/active-context-config.js +14 -0
  58. package/dist/active-context-transform.d.ts +267 -0
  59. package/dist/active-context-transform.js +31 -0
  60. package/dist/active-memory-bridge.d.ts +2 -2
  61. package/dist/active-memory-bridge.js +2 -2
  62. package/dist/active-recall.d.ts +2 -2
  63. package/dist/active-recall.js +17 -16
  64. package/dist/active-recall.js.map +1 -1
  65. package/dist/adapters/index.js +7 -7
  66. package/dist/adapters/registry.js +3 -3
  67. package/dist/ambient-provenance.d.ts +2 -2
  68. package/dist/artifact-search.d.ts +2 -2
  69. package/dist/{auto-sync-XVMLL2RH.js → auto-sync-Q6Q2FVSC.js} +10 -10
  70. package/dist/behavior-learner.d.ts +2 -2
  71. package/dist/behavior-signals.d.ts +2 -2
  72. package/dist/bootstrap.d.ts +13 -12
  73. package/dist/briefing-window.d.ts +5 -3
  74. package/dist/briefing.d.ts +5 -3
  75. package/dist/briefing.js +33 -33
  76. package/dist/buffer-surprise-report.d.ts +2 -2
  77. package/dist/buffer-turn-helpers.d.ts +2 -2
  78. package/dist/buffer.d.ts +5 -3
  79. package/dist/buffer.js +24 -8
  80. package/dist/bulk-import/index.d.ts +4 -4
  81. package/dist/calibration.d.ts +2 -2
  82. package/dist/calibration.js +1 -1
  83. package/dist/capabilities.d.ts +2 -2
  84. package/dist/{capsule-merge-SGIVB3WA.js → capsule-merge-SEHERWWP.js} +4 -4
  85. package/dist/{catalog-DybwVNW3.d.ts → catalog-D1HgugTA.d.ts} +1 -1
  86. package/dist/causal-behavior.d.ts +4 -4
  87. package/dist/causal-consolidation.d.ts +2 -2
  88. package/dist/causal-consolidation.js +34 -34
  89. package/dist/causal-trajectory-graph.d.ts +2 -2
  90. package/dist/{chunk-CFGU52XJ.js → chunk-23CVL7HS.js} +2 -2
  91. package/dist/{chunk-PO7NXBG2.js → chunk-2GF27PGH.js} +5 -5
  92. package/dist/{chunk-6CPUQ5D6.js → chunk-2LBAFHOQ.js} +15 -15
  93. package/dist/{chunk-JBPKEARU.js → chunk-2QSZNTDO.js} +7 -7
  94. package/dist/{chunk-IP4ZNT4U.js → chunk-33MFRY25.js} +2 -2
  95. package/dist/{chunk-VFYRYFLL.js → chunk-3TSU662L.js} +3 -3
  96. package/dist/chunk-43HUVDTD.js +114 -0
  97. package/dist/chunk-43HUVDTD.js.map +1 -0
  98. package/dist/{chunk-VXVZ2GM3.js → chunk-4FHRZD5T.js} +2 -2
  99. package/dist/{chunk-FP7YTTVO.js → chunk-4OFKZAJG.js} +2 -1
  100. package/dist/chunk-4OFKZAJG.js.map +1 -0
  101. package/dist/{chunk-5VPQSRQO.js → chunk-4STAANV7.js} +3 -3
  102. package/dist/{chunk-46WM6JX2.js → chunk-4ZWCQJNM.js} +5 -5
  103. package/dist/{chunk-LLQCM2U2.js → chunk-56IV4J5W.js} +617 -167
  104. package/dist/chunk-56IV4J5W.js.map +1 -0
  105. package/dist/{chunk-52II7PB6.js → chunk-645WOU5I.js} +4 -4
  106. package/dist/{chunk-YKWFK7XA.js → chunk-6CEGSTBD.js} +7 -7
  107. package/dist/{chunk-I7EX6KSH.js → chunk-6QDXA26G.js} +264 -210
  108. package/dist/chunk-6QDXA26G.js.map +1 -0
  109. package/dist/{chunk-GEPACVWN.js → chunk-6RUHELWR.js} +3 -3
  110. package/dist/{chunk-ZAOHJDKH.js → chunk-72OIT7KS.js} +4 -4
  111. package/dist/{chunk-KQAFEZQX.js → chunk-7LCGFUMB.js} +4 -4
  112. package/dist/{chunk-7TCGNUVP.js → chunk-7UTDHQZ5.js} +3 -3
  113. package/dist/{chunk-5HK3CJAR.js → chunk-7XOG75AU.js} +3 -3
  114. package/dist/{chunk-7BDZTALN.js → chunk-AJTG3CP7.js} +12 -2
  115. package/dist/chunk-AJTG3CP7.js.map +1 -0
  116. package/dist/{chunk-2LWQSV6A.js → chunk-AL3UYZ5N.js} +3 -2
  117. package/dist/chunk-AL3UYZ5N.js.map +1 -0
  118. package/dist/chunk-B32WYRXX.js +77 -0
  119. package/dist/chunk-B32WYRXX.js.map +1 -0
  120. package/dist/{chunk-C24UZSFW.js → chunk-CEH2AFXG.js} +6 -6
  121. package/dist/{chunk-YOXVZJFM.js → chunk-CFVTRUR3.js} +2 -2
  122. package/dist/{chunk-ACOC27BB.js → chunk-CN4VKV3S.js} +2 -2
  123. package/dist/{chunk-PMVPCZJZ.js → chunk-CTCGHNWN.js} +6 -6
  124. package/dist/{chunk-EGBDFJ36.js → chunk-DD5JFCWM.js} +2 -2
  125. package/dist/{chunk-T42L3S6A.js → chunk-DDX6KIXF.js} +2 -2
  126. package/dist/{chunk-JIYDRBVZ.js → chunk-DJORULH3.js} +2 -2
  127. package/dist/{chunk-WTOZBZNN.js → chunk-DMEHOEC7.js} +6 -6
  128. package/dist/{chunk-OPPBTPUU.js → chunk-DUAJKRR2.js} +4 -4
  129. package/dist/{chunk-XDL5CYZN.js → chunk-EEOUMG3J.js} +2 -1
  130. package/dist/{chunk-XDL5CYZN.js.map → chunk-EEOUMG3J.js.map} +1 -1
  131. package/dist/{chunk-SVVIASVX.js → chunk-EFQCDJZ2.js} +7 -7
  132. package/dist/{chunk-Q57GOHLF.js → chunk-EGALNSZ4.js} +3 -3
  133. package/dist/{chunk-KCT36JAW.js → chunk-ESNFSSO4.js} +2 -2
  134. package/dist/{chunk-XQ3HXAQH.js → chunk-ET2CNMLD.js} +4 -4
  135. package/dist/{chunk-Z4U3UN56.js → chunk-EZSCW4EM.js} +6 -6
  136. package/dist/{chunk-F6QHHRWP.js → chunk-FESUGFIL.js} +3 -3
  137. package/dist/{chunk-S3K2CIK5.js → chunk-FKKGCGYL.js} +3 -3
  138. package/dist/{chunk-BWGCOLEL.js → chunk-FTTJRVB7.js} +2 -2
  139. package/dist/{chunk-JAQXUGLN.js → chunk-FYWLSFFS.js} +2 -2
  140. package/dist/{chunk-BJTHRFFC.js → chunk-GEJKYA7D.js} +77 -36
  141. package/dist/chunk-GEJKYA7D.js.map +1 -0
  142. package/dist/chunk-GSKINLAK.js +267 -0
  143. package/dist/chunk-GSKINLAK.js.map +1 -0
  144. package/dist/{chunk-OPGL46PX.js → chunk-GX6FTSYH.js} +2 -2
  145. package/dist/{chunk-A32YEQAM.js → chunk-H7VDIF2V.js} +2 -2
  146. package/dist/{chunk-PDDSFELN.js → chunk-HJXA6ZM7.js} +2 -2
  147. package/dist/{chunk-RGCF4XNH.js → chunk-HNPE66LB.js} +8 -8
  148. package/dist/{chunk-SEA6M7SS.js → chunk-I5VB44ZK.js} +2 -2
  149. package/dist/{chunk-SDEPLF7V.js → chunk-IBJ6U753.js} +2 -2
  150. package/dist/{chunk-EUYWQ7TS.js → chunk-IEZ6CGTW.js} +2 -2
  151. package/dist/{chunk-RQE4TITU.js → chunk-IHGMRDEE.js} +431 -1834
  152. package/dist/chunk-IHGMRDEE.js.map +1 -0
  153. package/dist/{chunk-3RI5Y7KU.js → chunk-IVIAHQBR.js} +2 -2
  154. package/dist/{chunk-7WR462EM.js → chunk-J3OND5QT.js} +4 -4
  155. package/dist/{chunk-UW5NPZJ2.js → chunk-JALOAKSZ.js} +59 -7
  156. package/dist/chunk-JALOAKSZ.js.map +1 -0
  157. package/dist/{chunk-T3JQTCCO.js → chunk-JI7U6AS3.js} +4 -4
  158. package/dist/{chunk-DVYRD4HY.js → chunk-JRRQ747T.js} +36 -7
  159. package/dist/chunk-JRRQ747T.js.map +1 -0
  160. package/dist/{chunk-I32NKXE2.js → chunk-JTWZKNUH.js} +5 -5
  161. package/dist/chunk-K66OY4EI.js +202 -0
  162. package/dist/chunk-K66OY4EI.js.map +1 -0
  163. package/dist/{chunk-XAB6STPO.js → chunk-KODXCHXJ.js} +17 -3
  164. package/dist/chunk-KODXCHXJ.js.map +1 -0
  165. package/dist/{chunk-ZPUIRTIZ.js → chunk-KOLJJN5G.js} +12 -75
  166. package/dist/chunk-KOLJJN5G.js.map +1 -0
  167. package/dist/{chunk-FMQ4MOQO.js → chunk-KXIXO76C.js} +32 -19
  168. package/dist/chunk-KXIXO76C.js.map +1 -0
  169. package/dist/{chunk-VKCAHCBI.js → chunk-L4X4PJYK.js} +2 -2
  170. package/dist/chunk-LB7WCZHY.js +553 -0
  171. package/dist/chunk-LB7WCZHY.js.map +1 -0
  172. package/dist/{chunk-W4BMEGQA.js → chunk-LUDBXTBJ.js} +8 -8
  173. package/dist/{chunk-I4343FIA.js → chunk-MAH64N55.js} +28 -10
  174. package/dist/chunk-MAH64N55.js.map +1 -0
  175. package/dist/{chunk-RIAM7DND.js → chunk-ME35HVDJ.js} +2 -2
  176. package/dist/{chunk-H63EDPFJ.js → chunk-MI2OTWV5.js} +15 -2
  177. package/dist/{chunk-H63EDPFJ.js.map → chunk-MI2OTWV5.js.map} +1 -1
  178. package/dist/{chunk-LBFFNDFM.js → chunk-MINHJ55X.js} +1 -1
  179. package/dist/chunk-MINHJ55X.js.map +1 -0
  180. package/dist/{chunk-NG3MBQV4.js → chunk-MJRGVXPQ.js} +2 -2
  181. package/dist/{chunk-773TRRGT.js → chunk-MJUCDM3C.js} +2 -2
  182. package/dist/{chunk-7F27PCSN.js → chunk-MN5NOOI7.js} +2 -2
  183. package/dist/{chunk-JCWY73FK.js → chunk-N4F7ZSSG.js} +2 -2
  184. package/dist/{chunk-TR7DGXGI.js → chunk-NACLNNFQ.js} +5 -5
  185. package/dist/{chunk-LC2BDILZ.js → chunk-NBP4EX5N.js} +2 -2
  186. package/dist/{chunk-ZVPVTPGI.js → chunk-NNZFPYYX.js} +4 -4
  187. package/dist/{chunk-MFOSZUIT.js → chunk-NPIBN2VL.js} +2 -2
  188. package/dist/{chunk-IY7UXD3J.js → chunk-O57GM3FR.js} +2 -2
  189. package/dist/{chunk-I2HTKOOP.js → chunk-O7ERGZDA.js} +5 -5
  190. package/dist/{chunk-GTSVEEP3.js → chunk-OAJMQKQR.js} +3 -3
  191. package/dist/{chunk-HSZMX3ZJ.js → chunk-ODW5GDFE.js} +2 -2
  192. package/dist/{chunk-D4QVPP3G.js → chunk-PEBH5DCK.js} +18 -11
  193. package/dist/chunk-PEBH5DCK.js.map +1 -0
  194. package/dist/{chunk-J2WC5LF4.js → chunk-QBC33MPY.js} +2 -1
  195. package/dist/{chunk-EOHKUWXW.js → chunk-QCRJMU5V.js} +2 -2
  196. package/dist/chunk-QJCWK2A7.js +1466 -0
  197. package/dist/chunk-QJCWK2A7.js.map +1 -0
  198. package/dist/{chunk-THG4GYIE.js → chunk-RDGKVH6T.js} +11 -7
  199. package/dist/{chunk-THG4GYIE.js.map → chunk-RDGKVH6T.js.map} +1 -1
  200. package/dist/{chunk-5DH6PG4B.js → chunk-RZ3IZIJG.js} +3 -3
  201. package/dist/{chunk-AAXJNINV.js → chunk-SN4JXNLL.js} +2 -2
  202. package/dist/chunk-TB2MJRI6.js +866 -0
  203. package/dist/chunk-TB2MJRI6.js.map +1 -0
  204. package/dist/{chunk-7PHI6GUI.js → chunk-TEZ2HTC7.js} +42 -2
  205. package/dist/chunk-TEZ2HTC7.js.map +1 -0
  206. package/dist/{chunk-SVSRPG6M.js → chunk-TNGH4ZYI.js} +2 -2
  207. package/dist/{chunk-HZNYJN77.js → chunk-TNXNECAN.js} +6 -6
  208. package/dist/{chunk-JOEJG4SD.js → chunk-TVW4C7PV.js} +5 -5
  209. package/dist/{chunk-UFKPQBXH.js → chunk-U62OK7BB.js} +2 -2
  210. package/dist/{chunk-R2MZCYA6.js → chunk-UNUMFURP.js} +3 -3
  211. package/dist/{chunk-AX7UXCHJ.js → chunk-UYA36DQ7.js} +2 -1
  212. package/dist/chunk-UYA36DQ7.js.map +1 -0
  213. package/dist/{chunk-AFR6AIM4.js → chunk-VCKWULAK.js} +112 -87
  214. package/dist/chunk-VCKWULAK.js.map +1 -0
  215. package/dist/chunk-VOSWUO3K.js +100 -0
  216. package/dist/chunk-VOSWUO3K.js.map +1 -0
  217. package/dist/{chunk-YRVAKONL.js → chunk-VQ4AMTGZ.js} +1 -1
  218. package/dist/{chunk-3BCULS4U.js → chunk-VQNRICAQ.js} +145 -507
  219. package/dist/chunk-VQNRICAQ.js.map +1 -0
  220. package/dist/{chunk-RAIUTAZZ.js → chunk-WKAXBXVA.js} +2 -2
  221. package/dist/{chunk-ZIJDI4CP.js → chunk-WKJFIMVN.js} +2 -2
  222. package/dist/{chunk-SXIMQLGV.js → chunk-WVGXCBOC.js} +2 -2
  223. package/dist/{chunk-7BEPVIH3.js → chunk-X5YYSAZX.js} +4 -4
  224. package/dist/{chunk-FZEEWOI2.js → chunk-XJJYSX6F.js} +2 -2
  225. package/dist/{chunk-F635GAL7.js → chunk-XKNHFDTT.js} +33 -13
  226. package/dist/chunk-XKNHFDTT.js.map +1 -0
  227. package/dist/{chunk-UG6VXIOK.js → chunk-XSTNGNJP.js} +2 -2
  228. package/dist/{chunk-YDPAE2RD.js → chunk-YFLLGRXO.js} +2 -2
  229. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  230. package/dist/{chunk-ANJXPFRS.js → chunk-YXFCALVT.js} +14 -14
  231. package/dist/{chunk-Q4WONDMJ.js → chunk-YYGZJPOK.js} +2 -2
  232. package/dist/{chunk-5HERQ5FX.js → chunk-Z3YEGSR4.js} +10 -10
  233. package/dist/{chunk-YWSQD2IB.js → chunk-ZJPM7GZ3.js} +2 -2
  234. package/dist/{chunk-5S4LQOPE.js → chunk-ZW4VXELZ.js} +2 -2
  235. package/dist/{cli-B322UMvB.d.ts → cli-BEkm2MEf.d.ts} +5 -5
  236. package/dist/cli.d.ts +17 -16
  237. package/dist/cli.js +126 -120
  238. package/dist/coding/export-okf-codegraph.d.ts +56 -0
  239. package/dist/coding/export-okf-codegraph.js +526 -0
  240. package/dist/coding/export-okf-codegraph.js.map +1 -0
  241. package/dist/coding/pre-action-gate.d.ts +2 -2
  242. package/dist/compounding/engine.d.ts +5 -3
  243. package/dist/compounding/engine.js +34 -34
  244. package/dist/compounding/preference-consolidator.d.ts +4 -4
  245. package/dist/compression-optimizer.d.ts +2 -2
  246. package/dist/config-security.js +2 -2
  247. package/dist/config.d.ts +2 -2
  248. package/dist/config.js +17 -16
  249. package/dist/connectors/codex-materialize-runner.d.ts +2 -2
  250. package/dist/connectors/codex-materialize-runner.js +33 -33
  251. package/dist/connectors/codex-materialize.d.ts +2 -2
  252. package/dist/connectors/index.d.ts +2 -2
  253. package/dist/connectors/index.js +33 -33
  254. package/dist/consolidation-provenance-check.d.ts +5 -3
  255. package/dist/consolidation-provenance-check.js +5 -5
  256. package/dist/consolidation-undo.d.ts +5 -3
  257. package/dist/consolidation-undo.js +3 -3
  258. package/dist/context-summary.d.ts +43 -0
  259. package/dist/context-summary.js +14 -0
  260. package/dist/context-summary.js.map +1 -0
  261. package/dist/contradiction/index.d.ts +6 -4
  262. package/dist/contradiction/index.js +10 -10
  263. package/dist/{contradiction-scan-AKUWPX5N.js → contradiction-scan-NOYMFG66.js} +3 -3
  264. package/dist/contradiction-scan-NOYMFG66.js.map +1 -0
  265. package/dist/converge-config.d.ts +2 -2
  266. package/dist/convergence-refresh.d.ts +5 -3
  267. package/dist/convergence-refresh.js +36 -36
  268. package/dist/conversation-index/backend.d.ts +2 -2
  269. package/dist/conversation-index/chunker.d.ts +2 -2
  270. package/dist/conversation-index/faiss-adapter.d.ts +2 -2
  271. package/dist/conversation-index/indexer.d.ts +2 -2
  272. package/dist/conversation-index/search.d.ts +2 -2
  273. package/dist/corpus-watermark.d.ts +2 -2
  274. package/dist/corpus-watermark.js +35 -35
  275. package/dist/cross-lingual-recall.d.ts +2 -2
  276. package/dist/dashboard-runtime.js +2 -2
  277. package/dist/day-summary.d.ts +2 -2
  278. package/dist/delinearize.d.ts +2 -2
  279. package/dist/dependency-propagation-config.d.ts +2 -2
  280. package/dist/{dependency-propagation-delivery-BGcNairQ.d.ts → dependency-propagation-delivery-BCpeo14F.d.ts} +1 -1
  281. package/dist/direct-answer-wiring.d.ts +2 -2
  282. package/dist/direct-answer.d.ts +2 -2
  283. package/dist/embedding-fallback.d.ts +2 -2
  284. package/dist/enrichment/index.d.ts +2 -2
  285. package/dist/entity-origin-fields.d.ts +2 -2
  286. package/dist/entity-retrieval.d.ts +5 -3
  287. package/dist/entity-retrieval.js +34 -34
  288. package/dist/entity-schema.d.ts +2 -2
  289. package/dist/episodic-context.d.ts +2 -2
  290. package/dist/eval-trajectory-contracts.d.ts +2 -2
  291. package/dist/eval-trajectory-store.d.ts +2 -2
  292. package/dist/eval-trajectory.d.ts +2 -2
  293. package/dist/event-order-recall.js +3 -3
  294. package/dist/explicit-capture.d.ts +13 -12
  295. package/dist/explicit-capture.js +12 -12
  296. package/dist/external-wiki-access.d.ts +15 -14
  297. package/dist/external-wiki-access.js +66 -63
  298. package/dist/external-wiki-collection-registration.d.ts +2 -2
  299. package/dist/external-wiki-collection.d.ts +2 -2
  300. package/dist/external-wiki-mcp-tools.d.ts +15 -14
  301. package/dist/extraction-error-classification.d.ts +2 -2
  302. package/dist/extraction-faithfulness.d.ts +2 -2
  303. package/dist/extraction-faithfulness.js +2 -2
  304. package/dist/extraction-judge-telemetry.d.ts +2 -2
  305. package/dist/extraction-judge-training.d.ts +2 -2
  306. package/dist/extraction-judge.d.ts +2 -2
  307. package/dist/extraction-judge.js +2 -2
  308. package/dist/extraction-liveness.d.ts +2 -2
  309. package/dist/extraction-normalization.d.ts +2 -2
  310. package/dist/extraction-prompt.d.ts +2 -2
  311. package/dist/extraction-source-grounding-rules.d.ts +2 -2
  312. package/dist/extraction-source-grounding.d.ts +2 -2
  313. package/dist/extraction.d.ts +2 -2
  314. package/dist/extraction.js +47 -44
  315. package/dist/fallback-llm.d.ts +8 -2
  316. package/dist/fallback-llm.js +1 -1
  317. package/dist/{first-start-migration-4NETATFF.js → first-start-migration-KHIMCBIC.js} +3 -3
  318. package/dist/{forget-SZ2BXDGF.js → forget-2AE4MDK3.js} +3 -3
  319. package/dist/graph-dashboard-diff.d.ts +2 -2
  320. package/dist/graph-dashboard-key.d.ts +2 -2
  321. package/dist/graph-dashboard-parser.d.ts +2 -2
  322. package/dist/graph-edge-reinforcement.d.ts +2 -2
  323. package/dist/graph-path-reconstruction.d.ts +2 -2
  324. package/dist/graph-path-scoring.d.ts +2 -2
  325. package/dist/graph-snapshot.d.ts +2 -2
  326. package/dist/graph.d.ts +2 -2
  327. package/dist/harmonic-retrieval.js +1 -1
  328. package/dist/importance.d.ts +2 -2
  329. package/dist/importers/index.d.ts +2 -2
  330. package/dist/in-flight-reads.d.ts +2 -2
  331. package/dist/{index-By2QUAMh.d.ts → index-D_pyMUaP.d.ts} +2 -2
  332. package/dist/index.d.ts +261 -30
  333. package/dist/index.js +321 -257
  334. package/dist/intent.d.ts +2 -2
  335. package/dist/lcm/engine.d.ts +3 -3
  336. package/dist/lcm/engine.js +5 -4
  337. package/dist/lcm/index.d.ts +4 -3
  338. package/dist/lcm/index.js +12 -11
  339. package/dist/lcm/summarizer.d.ts +4 -6
  340. package/dist/lcm/summarizer.js +2 -1
  341. package/dist/lcm/tools.d.ts +4 -4
  342. package/dist/lifecycle.d.ts +2 -2
  343. package/dist/live-connectors-runner.d.ts +2 -2
  344. package/dist/local-llm.d.ts +2 -2
  345. package/dist/local-model-endpoint.d.ts +2 -2
  346. package/dist/location/index.d.ts +315 -6
  347. package/dist/location/index.js +151 -19
  348. package/dist/maintenance/memory-governance.d.ts +2 -2
  349. package/dist/maintenance/memory-governance.js +34 -34
  350. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +5 -3
  351. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +33 -33
  352. package/dist/maintenance/rebuild-memory-projection.d.ts +5 -3
  353. package/dist/maintenance/rebuild-memory-projection.js +35 -35
  354. package/dist/{maintenance-Dm2McrIx.d.ts → maintenance-DDUX9d6D.d.ts} +3 -3
  355. package/dist/mcp-memory-inspector-app.d.ts +15 -14
  356. package/dist/mcp-read-only-tools.js +1 -1
  357. package/dist/memory-action-policy.d.ts +18 -3
  358. package/dist/memory-action-policy.js +3 -1
  359. package/dist/memory-cache.d.ts +2 -2
  360. package/dist/memory-controller.d.ts +2 -2
  361. package/dist/memory-controller.js +2 -2
  362. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -2
  363. package/dist/memory-projection-mutations.js +3 -3
  364. package/dist/memory-projection-store.d.ts +2 -2
  365. package/dist/memory-projection-store.js +1 -1
  366. package/dist/memory-provenance.d.ts +2 -2
  367. package/dist/memory-snapshot.d.ts +2 -2
  368. package/dist/memory-subject-cli.d.ts +15 -14
  369. package/dist/memory-subject.d.ts +15 -14
  370. package/dist/memory-subject.js +5 -5
  371. package/dist/memory-worth-outcomes.d.ts +5 -3
  372. package/dist/models-json.d.ts +2 -2
  373. package/dist/namespaces/migrate.d.ts +6 -4
  374. package/dist/namespaces/migrate.js +34 -34
  375. package/dist/namespaces/principal.d.ts +2 -2
  376. package/dist/namespaces/search.d.ts +2 -2
  377. package/dist/namespaces/search.js +8 -8
  378. package/dist/namespaces/storage.d.ts +6 -4
  379. package/dist/namespaces/storage.js +33 -33
  380. package/dist/native-knowledge.d.ts +2 -2
  381. package/dist/offline-sync-file-io.js +3 -3
  382. package/dist/offline-sync-impression-drain.d.ts +2 -2
  383. package/dist/offline-sync-impression-drain.js +9 -9
  384. package/dist/offline-sync.js +4 -4
  385. package/dist/operator-doctor-corpus.d.ts +2 -2
  386. package/dist/operator-doctor-corpus.js +36 -36
  387. package/dist/operator-doctor-replica.d.ts +2 -2
  388. package/dist/operator-toolkit.d.ts +6 -4
  389. package/dist/operator-toolkit.js +56 -55
  390. package/dist/orchestration/compression-guideline-coordinator.d.ts +5 -3
  391. package/dist/orchestration/maintenance.d.ts +7 -5
  392. package/dist/orchestration/maintenance.js +48 -47
  393. package/dist/{orchestrator-Co1DyfuP.d.ts → orchestrator-3F4jihCo.d.ts} +8 -8
  394. package/dist/orchestrator.d.ts +13 -12
  395. package/dist/orchestrator.js +182 -174
  396. package/dist/page-versioning.js +3 -3
  397. package/dist/patterns-cli.d.ts +2 -2
  398. package/dist/{pipeline-DotMnb6y.d.ts → pipeline-CB1dj6Uh.d.ts} +1 -1
  399. package/dist/policy-runtime.d.ts +2 -2
  400. package/dist/proactive-contention.d.ts +2 -2
  401. package/dist/provenance.d.ts +2 -2
  402. package/dist/{public-http-PJRtnSi-.d.ts → public-http-34-JIAGQ.d.ts} +1 -1
  403. package/dist/{purge-GB7PZHT2.js → purge-OP6BEDFY.js} +2 -2
  404. package/dist/{qmd-BP0n11fR.d.ts → qmd-edLLZXc5.d.ts} +1 -1
  405. package/dist/qmd-preflight.d.ts +3 -3
  406. package/dist/qmd-recall-cache.d.ts +2 -2
  407. package/dist/qmd.d.ts +3 -3
  408. package/dist/qmd.js +4 -4
  409. package/dist/recall-concurrency-config.d.ts +2 -2
  410. package/dist/recall-disclosure-escalation.d.ts +2 -2
  411. package/dist/recall-explain-renderer.d.ts +2 -2
  412. package/dist/recall-explain-renderer.js +3 -3
  413. package/dist/recall-memory-map.d.ts +2 -2
  414. package/dist/recall-planner-llm.d.ts +2 -2
  415. package/dist/recall-planner-llm.js +1 -1
  416. package/dist/recall-state.d.ts +2 -2
  417. package/dist/recall-tag-filter.d.ts +2 -2
  418. package/dist/recall-timings.d.ts +2 -2
  419. package/dist/recall-xray-cli.d.ts +2 -2
  420. package/dist/recall-xray-cli.js +4 -4
  421. package/dist/recall-xray-renderer.d.ts +2 -2
  422. package/dist/recall-xray-renderer.js +3 -3
  423. package/dist/recall-xray.d.ts +2 -2
  424. package/dist/recall-xray.js +2 -2
  425. package/dist/reconcile/cursor.d.ts +2 -2
  426. package/dist/reconcile/manifest.d.ts +2 -2
  427. package/dist/reconcile/manifest.js +5 -5
  428. package/dist/reconcile/plan.d.ts +2 -2
  429. package/dist/replay/normalizers/chatgpt.d.ts +2 -2
  430. package/dist/replay/normalizers/claude.d.ts +2 -2
  431. package/dist/replay/normalizers/openclaw.d.ts +2 -2
  432. package/dist/replay/normalizers/shared.d.ts +2 -2
  433. package/dist/replay/runner.d.ts +2 -2
  434. package/dist/replay/types.d.ts +2 -2
  435. package/dist/replica-divergence.d.ts +2 -2
  436. package/dist/replica-peers-config.d.ts +2 -2
  437. package/dist/{resolution-4552BNRV.js → resolution-4DLI3IOR.js} +11 -11
  438. package/dist/resolution-4DLI3IOR.js.map +1 -0
  439. package/dist/resolve-auth-token.d.ts +2 -2
  440. package/dist/resume-bundles.js +18 -17
  441. package/dist/retrieval-agents.d.ts +3 -3
  442. package/dist/retrieval-tiers.d.ts +2 -2
  443. package/dist/routing/engine.d.ts +2 -2
  444. package/dist/routing/store.d.ts +2 -2
  445. package/dist/salvage-envelope.d.ts +2 -2
  446. package/dist/salvage-envelope.js +7 -7
  447. package/dist/schemas.d.ts +572 -107
  448. package/dist/schemas.js +3 -1
  449. package/dist/{scope-profiles-6ChZKTy-.d.ts → scope-profiles-BF2lu81V.d.ts} +1 -1
  450. package/dist/search/document-scanner.js +1 -1
  451. package/dist/search/embed-helper.d.ts +2 -2
  452. package/dist/search/factory.d.ts +2 -2
  453. package/dist/search/factory.js +7 -7
  454. package/dist/search/index.d.ts +2 -2
  455. package/dist/search/index.js +13 -13
  456. package/dist/search/lancedb-backend.d.ts +2 -2
  457. package/dist/search/lancedb-backend.js +1 -1
  458. package/dist/search/meilisearch-backend.d.ts +2 -2
  459. package/dist/search/meilisearch-backend.js +1 -1
  460. package/dist/search/noop-backend.d.ts +2 -2
  461. package/dist/search/orama-backend.d.ts +2 -2
  462. package/dist/search/orama-backend.js +1 -1
  463. package/dist/search/port.d.ts +2 -2
  464. package/dist/search/remote-backend.d.ts +2 -2
  465. package/dist/secure-store/index.js +3 -3
  466. package/dist/{semantic-consolidation-DziYcW5J.d.ts → semantic-consolidation-5OuWXBRt.d.ts} +1 -1
  467. package/dist/semantic-consolidation.d.ts +3 -3
  468. package/dist/semantic-consolidation.js +37 -37
  469. package/dist/semantic-rule-promotion.js +33 -33
  470. package/dist/semantic-rule-verifier.d.ts +2 -2
  471. package/dist/semantic-rule-verifier.js +33 -33
  472. package/dist/{service-C7rIBuK_.d.ts → service-CrqEhLXD.d.ts} +2 -2
  473. package/dist/session-observer-bands.d.ts +2 -2
  474. package/dist/session-observer-state.d.ts +2 -2
  475. package/dist/shared-context/manager.d.ts +2 -2
  476. package/dist/signal.d.ts +2 -2
  477. package/dist/source-agent-qualifier.d.ts +2 -2
  478. package/dist/source-agent-qualifier.js +42 -39
  479. package/dist/standup/build.d.ts +16 -0
  480. package/dist/standup/build.js +17 -0
  481. package/dist/standup/build.js.map +1 -0
  482. package/dist/{storage-B1hEx8Xg.d.ts → storage-BQn-xnxm.d.ts} +4 -1
  483. package/dist/storage.d.ts +5 -3
  484. package/dist/storage.js +32 -32
  485. package/dist/subject-config.d.ts +2 -2
  486. package/dist/subject-config.js +6 -6
  487. package/dist/summarizer.d.ts +2 -2
  488. package/dist/summarizer.js +2 -2
  489. package/dist/summary-snapshot.d.ts +2 -2
  490. package/dist/support-passport/index.d.ts +20 -19
  491. package/dist/support-passport/index.js +68 -65
  492. package/dist/temporal-supersession.d.ts +3 -3
  493. package/dist/temporal-timeline-recall.d.ts +2 -2
  494. package/dist/temporal-validity.d.ts +2 -2
  495. package/dist/threading.d.ts +2 -2
  496. package/dist/tier-migration.d.ts +5 -3
  497. package/dist/tier-routing.d.ts +2 -2
  498. package/dist/tier-routing.js +2 -2
  499. package/dist/{tier-stats-4B5IJ3NE.js → tier-stats-2TOW3QNL.js} +3 -3
  500. package/dist/topics.d.ts +2 -2
  501. package/dist/transcript.d.ts +2 -2
  502. package/dist/transfer/capsule-export.js +2 -2
  503. package/dist/transfer/capsule-import.js +5 -5
  504. package/dist/transfer/export-okf.d.ts +39 -0
  505. package/dist/transfer/export-okf.js +112 -0
  506. package/dist/transfer/export-okf.js.map +1 -0
  507. package/dist/transfer/types.d.ts +12 -12
  508. package/dist/trust-score-stage.d.ts +2 -2
  509. package/dist/trust-score.d.ts +2 -2
  510. package/dist/{types-BHDNxGTT.d.ts → types-BRpcNjHZ.d.ts} +119 -3
  511. package/dist/types.d.ts +2 -2
  512. package/dist/types.js +1 -1
  513. package/dist/utility-runtime.d.ts +2 -2
  514. package/dist/verified-recall.js +33 -33
  515. package/dist/who-knows-cli.d.ts +15 -14
  516. package/dist/who-knows-cli.js +34 -34
  517. package/dist/who-knows.d.ts +15 -14
  518. package/dist/who-knows.js +33 -33
  519. package/dist/write-envelope.d.ts +2 -2
  520. package/dist/write-envelope.js +6 -6
  521. package/package.json +54 -3
  522. package/src/access-admin-ops-surface.ts +6 -1
  523. package/src/access-boundary.ts +1 -0
  524. package/src/access-http.ts +3 -1
  525. package/src/access-mcp-output-schemas.ts +1 -0
  526. package/src/access-mcp.ts +3 -3
  527. package/src/access-operations.ts +1 -0
  528. package/src/access-service-offline-file-content.test.ts +63 -0
  529. package/src/access-surface-catalog.ts +2 -0
  530. package/src/active-context-config.ts +98 -0
  531. package/src/active-context-transform.test.ts +533 -0
  532. package/src/active-context-transform.ts +981 -0
  533. package/src/activity/config.test.ts +1 -0
  534. package/src/activity/config.ts +21 -1
  535. package/src/activity/index.ts +1 -0
  536. package/src/activity/timeline/build.ts +279 -0
  537. package/src/activity/timeline/categories.ts +111 -0
  538. package/src/activity/timeline/classify.ts +110 -0
  539. package/src/activity/timeline/corrections.ts +145 -0
  540. package/src/activity/timeline/index.ts +6 -0
  541. package/src/activity/timeline/timeline.test.ts +277 -0
  542. package/src/activity/timeline/types.ts +106 -0
  543. package/src/activity/types.ts +6 -0
  544. package/src/cli/okf-commands.ts +45 -0
  545. package/src/cli.ts +2 -2
  546. package/src/coding/export-okf-codegraph.test.ts +381 -0
  547. package/src/coding/export-okf-codegraph.ts +565 -0
  548. package/src/config.test.ts +1 -0
  549. package/src/config.ts +3 -5
  550. package/src/context-summary.ts +182 -0
  551. package/src/extraction-prompt-safety.test.ts +14 -2
  552. package/src/extraction.ts +21 -1
  553. package/src/fallback-llm.test.ts +134 -0
  554. package/src/fallback-llm.ts +77 -5
  555. package/src/index.ts +4 -11
  556. package/src/lcm/summarizer.ts +14 -93
  557. package/src/location/access-operations.ts +17 -8
  558. package/src/location/backfill.ts +137 -0
  559. package/src/location/config.test.ts +3 -0
  560. package/src/location/config.ts +46 -2
  561. package/src/location/http-glue.ts +1 -1
  562. package/src/location/index.ts +3 -0
  563. package/src/location/intervals.ts +1 -0
  564. package/src/location/matching.test.ts +65 -0
  565. package/src/location/matching.ts +354 -0
  566. package/src/location/mcp-tools.ts +2 -1
  567. package/src/location/surfaces.test.ts +15 -2
  568. package/src/location/surfaces.ts +95 -18
  569. package/src/location/tagging.test.ts +119 -0
  570. package/src/location/tagging.ts +277 -0
  571. package/src/location/types.ts +23 -1
  572. package/src/mcp-read-only-tools.ts +1 -0
  573. package/src/memory-action-policy.ts +28 -0
  574. package/src/memory-projection-store.ts +3 -1
  575. package/src/okf/cli.ts +18 -5
  576. package/src/okf/config.ts +5 -0
  577. package/src/okf/index-files.test.ts +60 -0
  578. package/src/okf/index-files.ts +114 -0
  579. package/src/okf/render.ts +133 -0
  580. package/src/okf/type-mapping.test.ts +3 -0
  581. package/src/okf/type-mapping.ts +2 -0
  582. package/src/orchestration/extraction-run.ts +2 -1
  583. package/src/orchestration/generic-recall-paths.ts +4 -3
  584. package/src/schemas.ts +17 -1
  585. package/src/standup/access-operations.ts +14 -0
  586. package/src/standup/build.test.ts +34 -0
  587. package/src/standup/build.ts +115 -0
  588. package/src/standup/http-glue.ts +15 -0
  589. package/src/standup/mcp-tools.ts +16 -0
  590. package/src/storage/context-transform-ledger.ts +39 -0
  591. package/src/storage/secure-line-reader.ts +50 -1
  592. package/src/storage.ts +4 -1
  593. package/src/support-passport/card-projection.ts +1 -0
  594. package/src/support-passport/card-service-commit-forwarding.test.ts +1 -0
  595. package/src/support-passport/card-service.test.ts +75 -1
  596. package/src/support-passport/card-service.ts +6 -3
  597. package/src/support-passport/card-state.ts +5 -1
  598. package/src/support-passport/offline-sync-guard.ts +14 -1
  599. package/src/transfer/export-okf.test.ts +164 -0
  600. package/src/transfer/export-okf.ts +286 -0
  601. package/src/types.ts +2 -3
  602. package/dist/chunk-2LWQSV6A.js.map +0 -1
  603. package/dist/chunk-3BCULS4U.js.map +0 -1
  604. package/dist/chunk-7BDZTALN.js.map +0 -1
  605. package/dist/chunk-7PHI6GUI.js.map +0 -1
  606. package/dist/chunk-AFR6AIM4.js.map +0 -1
  607. package/dist/chunk-AX7UXCHJ.js.map +0 -1
  608. package/dist/chunk-BJTHRFFC.js.map +0 -1
  609. package/dist/chunk-D4QVPP3G.js.map +0 -1
  610. package/dist/chunk-DVYRD4HY.js.map +0 -1
  611. package/dist/chunk-F635GAL7.js.map +0 -1
  612. package/dist/chunk-FMQ4MOQO.js.map +0 -1
  613. package/dist/chunk-FP7YTTVO.js.map +0 -1
  614. package/dist/chunk-I4343FIA.js.map +0 -1
  615. package/dist/chunk-I7EX6KSH.js.map +0 -1
  616. package/dist/chunk-LBFFNDFM.js.map +0 -1
  617. package/dist/chunk-LLQCM2U2.js.map +0 -1
  618. package/dist/chunk-RQE4TITU.js.map +0 -1
  619. package/dist/chunk-UW5NPZJ2.js.map +0 -1
  620. package/dist/chunk-XAB6STPO.js.map +0 -1
  621. package/dist/chunk-ZPUIRTIZ.js.map +0 -1
  622. package/dist/types-CM86alG1.d.ts +0 -89
  623. /package/dist/{contradiction-scan-AKUWPX5N.js.map → active-context-config.js.map} +0 -0
  624. /package/dist/{resolution-4552BNRV.js.map → active-context-transform.js.map} +0 -0
  625. /package/dist/{auto-sync-XVMLL2RH.js.map → auto-sync-Q6Q2FVSC.js.map} +0 -0
  626. /package/dist/{capsule-merge-SGIVB3WA.js.map → capsule-merge-SEHERWWP.js.map} +0 -0
  627. /package/dist/{chunk-CFGU52XJ.js.map → chunk-23CVL7HS.js.map} +0 -0
  628. /package/dist/{chunk-PO7NXBG2.js.map → chunk-2GF27PGH.js.map} +0 -0
  629. /package/dist/{chunk-6CPUQ5D6.js.map → chunk-2LBAFHOQ.js.map} +0 -0
  630. /package/dist/{chunk-JBPKEARU.js.map → chunk-2QSZNTDO.js.map} +0 -0
  631. /package/dist/{chunk-IP4ZNT4U.js.map → chunk-33MFRY25.js.map} +0 -0
  632. /package/dist/{chunk-VFYRYFLL.js.map → chunk-3TSU662L.js.map} +0 -0
  633. /package/dist/{chunk-VXVZ2GM3.js.map → chunk-4FHRZD5T.js.map} +0 -0
  634. /package/dist/{chunk-5VPQSRQO.js.map → chunk-4STAANV7.js.map} +0 -0
  635. /package/dist/{chunk-46WM6JX2.js.map → chunk-4ZWCQJNM.js.map} +0 -0
  636. /package/dist/{chunk-52II7PB6.js.map → chunk-645WOU5I.js.map} +0 -0
  637. /package/dist/{chunk-YKWFK7XA.js.map → chunk-6CEGSTBD.js.map} +0 -0
  638. /package/dist/{chunk-GEPACVWN.js.map → chunk-6RUHELWR.js.map} +0 -0
  639. /package/dist/{chunk-ZAOHJDKH.js.map → chunk-72OIT7KS.js.map} +0 -0
  640. /package/dist/{chunk-KQAFEZQX.js.map → chunk-7LCGFUMB.js.map} +0 -0
  641. /package/dist/{chunk-7TCGNUVP.js.map → chunk-7UTDHQZ5.js.map} +0 -0
  642. /package/dist/{chunk-5HK3CJAR.js.map → chunk-7XOG75AU.js.map} +0 -0
  643. /package/dist/{chunk-C24UZSFW.js.map → chunk-CEH2AFXG.js.map} +0 -0
  644. /package/dist/{chunk-YOXVZJFM.js.map → chunk-CFVTRUR3.js.map} +0 -0
  645. /package/dist/{chunk-ACOC27BB.js.map → chunk-CN4VKV3S.js.map} +0 -0
  646. /package/dist/{chunk-PMVPCZJZ.js.map → chunk-CTCGHNWN.js.map} +0 -0
  647. /package/dist/{chunk-EGBDFJ36.js.map → chunk-DD5JFCWM.js.map} +0 -0
  648. /package/dist/{chunk-T42L3S6A.js.map → chunk-DDX6KIXF.js.map} +0 -0
  649. /package/dist/{chunk-JIYDRBVZ.js.map → chunk-DJORULH3.js.map} +0 -0
  650. /package/dist/{chunk-WTOZBZNN.js.map → chunk-DMEHOEC7.js.map} +0 -0
  651. /package/dist/{chunk-OPPBTPUU.js.map → chunk-DUAJKRR2.js.map} +0 -0
  652. /package/dist/{chunk-SVVIASVX.js.map → chunk-EFQCDJZ2.js.map} +0 -0
  653. /package/dist/{chunk-Q57GOHLF.js.map → chunk-EGALNSZ4.js.map} +0 -0
  654. /package/dist/{chunk-KCT36JAW.js.map → chunk-ESNFSSO4.js.map} +0 -0
  655. /package/dist/{chunk-XQ3HXAQH.js.map → chunk-ET2CNMLD.js.map} +0 -0
  656. /package/dist/{chunk-Z4U3UN56.js.map → chunk-EZSCW4EM.js.map} +0 -0
  657. /package/dist/{chunk-F6QHHRWP.js.map → chunk-FESUGFIL.js.map} +0 -0
  658. /package/dist/{chunk-S3K2CIK5.js.map → chunk-FKKGCGYL.js.map} +0 -0
  659. /package/dist/{chunk-BWGCOLEL.js.map → chunk-FTTJRVB7.js.map} +0 -0
  660. /package/dist/{chunk-JAQXUGLN.js.map → chunk-FYWLSFFS.js.map} +0 -0
  661. /package/dist/{chunk-OPGL46PX.js.map → chunk-GX6FTSYH.js.map} +0 -0
  662. /package/dist/{chunk-A32YEQAM.js.map → chunk-H7VDIF2V.js.map} +0 -0
  663. /package/dist/{chunk-PDDSFELN.js.map → chunk-HJXA6ZM7.js.map} +0 -0
  664. /package/dist/{chunk-RGCF4XNH.js.map → chunk-HNPE66LB.js.map} +0 -0
  665. /package/dist/{chunk-SEA6M7SS.js.map → chunk-I5VB44ZK.js.map} +0 -0
  666. /package/dist/{chunk-SDEPLF7V.js.map → chunk-IBJ6U753.js.map} +0 -0
  667. /package/dist/{chunk-EUYWQ7TS.js.map → chunk-IEZ6CGTW.js.map} +0 -0
  668. /package/dist/{chunk-3RI5Y7KU.js.map → chunk-IVIAHQBR.js.map} +0 -0
  669. /package/dist/{chunk-7WR462EM.js.map → chunk-J3OND5QT.js.map} +0 -0
  670. /package/dist/{chunk-T3JQTCCO.js.map → chunk-JI7U6AS3.js.map} +0 -0
  671. /package/dist/{chunk-I32NKXE2.js.map → chunk-JTWZKNUH.js.map} +0 -0
  672. /package/dist/{chunk-VKCAHCBI.js.map → chunk-L4X4PJYK.js.map} +0 -0
  673. /package/dist/{chunk-W4BMEGQA.js.map → chunk-LUDBXTBJ.js.map} +0 -0
  674. /package/dist/{chunk-RIAM7DND.js.map → chunk-ME35HVDJ.js.map} +0 -0
  675. /package/dist/{chunk-NG3MBQV4.js.map → chunk-MJRGVXPQ.js.map} +0 -0
  676. /package/dist/{chunk-773TRRGT.js.map → chunk-MJUCDM3C.js.map} +0 -0
  677. /package/dist/{chunk-7F27PCSN.js.map → chunk-MN5NOOI7.js.map} +0 -0
  678. /package/dist/{chunk-JCWY73FK.js.map → chunk-N4F7ZSSG.js.map} +0 -0
  679. /package/dist/{chunk-TR7DGXGI.js.map → chunk-NACLNNFQ.js.map} +0 -0
  680. /package/dist/{chunk-LC2BDILZ.js.map → chunk-NBP4EX5N.js.map} +0 -0
  681. /package/dist/{chunk-ZVPVTPGI.js.map → chunk-NNZFPYYX.js.map} +0 -0
  682. /package/dist/{chunk-MFOSZUIT.js.map → chunk-NPIBN2VL.js.map} +0 -0
  683. /package/dist/{chunk-IY7UXD3J.js.map → chunk-O57GM3FR.js.map} +0 -0
  684. /package/dist/{chunk-I2HTKOOP.js.map → chunk-O7ERGZDA.js.map} +0 -0
  685. /package/dist/{chunk-GTSVEEP3.js.map → chunk-OAJMQKQR.js.map} +0 -0
  686. /package/dist/{chunk-HSZMX3ZJ.js.map → chunk-ODW5GDFE.js.map} +0 -0
  687. /package/dist/{chunk-J2WC5LF4.js.map → chunk-QBC33MPY.js.map} +0 -0
  688. /package/dist/{chunk-EOHKUWXW.js.map → chunk-QCRJMU5V.js.map} +0 -0
  689. /package/dist/{chunk-5DH6PG4B.js.map → chunk-RZ3IZIJG.js.map} +0 -0
  690. /package/dist/{chunk-AAXJNINV.js.map → chunk-SN4JXNLL.js.map} +0 -0
  691. /package/dist/{chunk-SVSRPG6M.js.map → chunk-TNGH4ZYI.js.map} +0 -0
  692. /package/dist/{chunk-HZNYJN77.js.map → chunk-TNXNECAN.js.map} +0 -0
  693. /package/dist/{chunk-JOEJG4SD.js.map → chunk-TVW4C7PV.js.map} +0 -0
  694. /package/dist/{chunk-UFKPQBXH.js.map → chunk-U62OK7BB.js.map} +0 -0
  695. /package/dist/{chunk-R2MZCYA6.js.map → chunk-UNUMFURP.js.map} +0 -0
  696. /package/dist/{chunk-YRVAKONL.js.map → chunk-VQ4AMTGZ.js.map} +0 -0
  697. /package/dist/{chunk-RAIUTAZZ.js.map → chunk-WKAXBXVA.js.map} +0 -0
  698. /package/dist/{chunk-ZIJDI4CP.js.map → chunk-WKJFIMVN.js.map} +0 -0
  699. /package/dist/{chunk-SXIMQLGV.js.map → chunk-WVGXCBOC.js.map} +0 -0
  700. /package/dist/{chunk-7BEPVIH3.js.map → chunk-X5YYSAZX.js.map} +0 -0
  701. /package/dist/{chunk-FZEEWOI2.js.map → chunk-XJJYSX6F.js.map} +0 -0
  702. /package/dist/{chunk-UG6VXIOK.js.map → chunk-XSTNGNJP.js.map} +0 -0
  703. /package/dist/{chunk-YDPAE2RD.js.map → chunk-YFLLGRXO.js.map} +0 -0
  704. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  705. /package/dist/{chunk-ANJXPFRS.js.map → chunk-YXFCALVT.js.map} +0 -0
  706. /package/dist/{chunk-Q4WONDMJ.js.map → chunk-YYGZJPOK.js.map} +0 -0
  707. /package/dist/{chunk-5HERQ5FX.js.map → chunk-Z3YEGSR4.js.map} +0 -0
  708. /package/dist/{chunk-YWSQD2IB.js.map → chunk-ZJPM7GZ3.js.map} +0 -0
  709. /package/dist/{chunk-5S4LQOPE.js.map → chunk-ZW4VXELZ.js.map} +0 -0
  710. /package/dist/{first-start-migration-4NETATFF.js.map → first-start-migration-KHIMCBIC.js.map} +0 -0
  711. /package/dist/{forget-SZ2BXDGF.js.map → forget-2AE4MDK3.js.map} +0 -0
  712. /package/dist/{purge-GB7PZHT2.js.map → purge-OP6BEDFY.js.map} +0 -0
  713. /package/dist/{tier-stats-4B5IJ3NE.js.map → tier-stats-2TOW3QNL.js.map} +0 -0
@@ -3,7 +3,7 @@ import {
3
3
  getOperation,
4
4
  operationRequiresAuthorizedNamespace,
5
5
  operationUsesPrincipalNamespace
6
- } from "./chunk-RQE4TITU.js";
6
+ } from "./chunk-IHGMRDEE.js";
7
7
  import {
8
8
  assertOperationAuthorizationAllowed
9
9
  } from "./chunk-MZWSOLMT.js";
@@ -60,4 +60,4 @@ export {
60
60
  authorizationProbeNamespaces,
61
61
  authorizationProbeRequiresPrincipalNamespace
62
62
  };
63
- //# sourceMappingURL=chunk-3RI5Y7KU.js.map
63
+ //# sourceMappingURL=chunk-IVIAHQBR.js.map
@@ -3,14 +3,14 @@ import {
3
3
  } from "./chunk-KJTKLXTH.js";
4
4
  import {
5
5
  StorageManager
6
- } from "./chunk-BJTHRFFC.js";
6
+ } from "./chunk-GEJKYA7D.js";
7
7
  import {
8
8
  copyExistingFileToBackup,
9
9
  writeFileAtomically
10
10
  } from "./chunk-AW4QUFQF.js";
11
11
  import {
12
12
  assertInjectedStorageRooted
13
- } from "./chunk-DVYRD4HY.js";
13
+ } from "./chunk-JRRQ747T.js";
14
14
  import {
15
15
  MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,
16
16
  buildLifecycleEventsForMemory,
@@ -28,7 +28,7 @@ import {
28
28
  } from "./chunk-FFAZ2XFU.js";
29
29
  import {
30
30
  probeEncryptedRegularFileHeader
31
- } from "./chunk-XQ3HXAQH.js";
31
+ } from "./chunk-ET2CNMLD.js";
32
32
  import {
33
33
  log
34
34
  } from "./chunk-3WCASNQZ.js";
@@ -260,4 +260,4 @@ export {
260
260
  backupExistingLedger,
261
261
  rebuildMemoryLifecycleLedger
262
262
  };
263
- //# sourceMappingURL=chunk-7WR462EM.js.map
263
+ //# sourceMappingURL=chunk-J3OND5QT.js.map
@@ -41,6 +41,16 @@ function fallbackLlmRuntimeContextFromConfig(config, overrides = {}) {
41
41
  ...overrides
42
42
  };
43
43
  }
44
+ function isUnsupportedJsonSchemaError(error) {
45
+ const message = error instanceof Error ? error.message : String(error);
46
+ if (!/\b(?:400|404|422)\b/.test(message)) {
47
+ return false;
48
+ }
49
+ if (/(?:response[_ ]?format|json[_ ]?schema|structured[_ ]?output)/i.test(message)) {
50
+ return true;
51
+ }
52
+ return /\bunsupported\b[\s\S]{0,40}\b(?:schema|format)\b/i.test(message);
53
+ }
44
54
  var PROVIDER_ALIASES = {
45
55
  "openai-codex": ["codex"],
46
56
  codex: ["openai-codex"],
@@ -97,7 +107,8 @@ var FallbackLlmClient = class {
97
107
  log.warn("fallback LLM: no models configured in gateway");
98
108
  return null;
99
109
  }
100
- const runChain = async (runOptions) => {
110
+ const runChain = async (initialOptions) => {
111
+ let runOptions = initialOptions;
101
112
  let lastRejectedResponse = null;
102
113
  for (let i = 0; i < models.length; i++) {
103
114
  if (runOptions.signal?.aborted) {
@@ -127,6 +138,37 @@ var FallbackLlmClient = class {
127
138
  if (runOptions.signal?.aborted) {
128
139
  throw abortReason(runOptions.signal);
129
140
  }
141
+ if ((runOptions.jsonSchema || runOptions.responsesJsonSchema) && isUnsupportedJsonSchemaError(err)) {
142
+ log.debug(`fallback LLM: ${model.modelString} rejected native JSON schema; retrying without it`);
143
+ runOptions = {
144
+ ...runOptions,
145
+ jsonSchema: void 0,
146
+ responsesJsonSchema: void 0
147
+ };
148
+ try {
149
+ const result = await this.tryModel(model, messages, runOptions);
150
+ if (result) {
151
+ const response = {
152
+ content: result.content,
153
+ modelUsed: model.modelString,
154
+ usage: result.usage
155
+ };
156
+ if (!runOptions.acceptResponse || runOptions.acceptResponse(response)) {
157
+ return response;
158
+ }
159
+ lastRejectedResponse = response;
160
+ log.debug(`fallback LLM: ${model.modelString} unstructured retry output rejected by acceptResponse, trying next model...`);
161
+ continue;
162
+ }
163
+ } catch (retryError) {
164
+ if (runOptions.signal?.aborted) throw abortReason(runOptions.signal);
165
+ const retryErrorMsg = runOptions.redactProviderErrors ? "provider error details redacted" : retryError instanceof Error ? retryError.message : String(retryError);
166
+ log.debug(
167
+ `fallback LLM: ${model.modelString} unstructured retry failed (${retryErrorMsg})`
168
+ );
169
+ }
170
+ continue;
171
+ }
130
172
  const errorMsg = runOptions.redactProviderErrors ? "provider error details redacted" : err instanceof Error ? err.message : String(err);
131
173
  log.debug(`fallback LLM: ${model.modelString} failed (${errorMsg}), trying next...`);
132
174
  }
@@ -498,7 +540,17 @@ var FallbackLlmClient = class {
498
540
  }),
499
541
  ...buildChatCompletionTokenLimit(modelId, options.maxTokens ?? 4096, {
500
542
  assumeOpenAI
501
- })
543
+ }),
544
+ ...options.jsonSchema ? {
545
+ response_format: {
546
+ type: "json_schema",
547
+ json_schema: {
548
+ name: options.jsonSchema.name,
549
+ strict: options.jsonSchema.strict ?? false,
550
+ schema: options.jsonSchema.schema
551
+ }
552
+ }
553
+ } : {}
502
554
  };
503
555
  const response = await fetch(url, {
504
556
  method: "POST",
@@ -603,13 +655,13 @@ var FallbackLlmClient = class {
603
655
  assumeOpenAI: shouldAssumeOpenAiChatCompletions(config.baseUrl)
604
656
  }),
605
657
  ...options.store === void 0 ? {} : { store: options.store },
606
- ...options.responsesJsonSchema ? {
658
+ ...options.jsonSchema || options.responsesJsonSchema ? {
607
659
  text: {
608
660
  format: {
609
661
  type: "json_schema",
610
- name: options.responsesJsonSchema.name,
611
- strict: true,
612
- schema: options.responsesJsonSchema.schema
662
+ name: (options.jsonSchema ?? options.responsesJsonSchema).name,
663
+ strict: options.jsonSchema?.strict ?? (options.responsesJsonSchema ? true : false),
664
+ schema: (options.jsonSchema ?? options.responsesJsonSchema).schema
613
665
  }
614
666
  }
615
667
  } : {}
@@ -736,4 +788,4 @@ export {
736
788
  fallbackLlmRuntimeContextFromConfig,
737
789
  FallbackLlmClient
738
790
  };
739
- //# sourceMappingURL=chunk-UW5NPZJ2.js.map
791
+ //# sourceMappingURL=chunk-JALOAKSZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fallback-llm.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport path from \"node:path\";\nimport type { AgentPersonaModelConfig, GatewayConfig, ModelProviderConfig, PluginConfig } from \"./types.js\";\nimport { extractJsonCandidates } from \"./json-extract.js\";\nimport {\n buildChatCompletionTemperature,\n buildChatCompletionTokenLimit,\n shouldAssumeOpenAiChatCompletions,\n} from \"./openai-chat-compat.js\";\nimport {\n resolveProviderApiKey,\n getGatewayRuntimeAuthForModel,\n type GetRuntimeAuthForModelFn,\n type ResolveApiKeyFn,\n} from \"./resolve-provider-secret.js\";\nimport { loadModelsJsonProviders } from \"./models-json.js\";\nimport { callCodexCliFallback } from \"./cli-fallback.js\";\nimport { resolveHomeDir } from \"./runtime/env.js\";\nimport { expandTildePath } from \"./utils/path.js\";\n\nexport interface FallbackLlmOptions {\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n signal?: AbortSignal;\n /** Set the Responses API storage policy. Other transports ignore this value. */\n store?: boolean;\n /** Request strict JSON output when a route uses the Responses API. */\n responsesJsonSchema?: { name: string; schema: Record<string, unknown> };\n /** Request provider-native structured output on supported JSON transports. */\n jsonSchema?: { name: string; schema: Record<string, unknown>; strict?: boolean };\n /** Hide provider error details that could echo private request content. */\n redactProviderErrors?: boolean;\n /** Explicit \"provider/model\" override to try before the configured chain. */\n model?: string;\n /** Explicit model chain override to use instead of the configured agent/default chain. */\n modelChain?: AgentPersonaModelConfig;\n /** Append the gateway default chain after an explicit model chain. */\n includeDefaultModelFallback?: boolean;\n /** Override which agent persona's model chain to use (by ID from agents.list[]). */\n agentId?: string;\n /** Reject a transport-successful response and continue through the configured model chain. */\n acceptResponse?: (response: FallbackLlmResponse) => boolean;\n}\n\nexport interface FallbackLlmAvailabilityOptions {\n agentId?: string;\n modelChain?: AgentPersonaModelConfig;\n}\n\n/**\n * Resolve the gateway routing options Remnic's background tasks should pass to\n * FallbackLlmClient — extraction, fact/profile/identity consolidation,\n * summarization, calibration, and causal/semantic consolidation. Single source\n * of truth so every task path stays consistent and can't diverge (gotcha #22):\n * in gateway mode an explicit `taskModelChain` wins over the gateway agent\n * persona; otherwise the persona (if any) is used. Returns `{}` in plugin mode\n * because the chain resolves through gateway providers only. Issue #1365.\n */\nexport function gatewayTaskChainOptions(\n config: Pick<PluginConfig, \"modelSource\" | \"taskModelChain\" | \"gatewayAgentId\">,\n): Pick<FallbackLlmOptions, \"modelChain\" | \"agentId\"> {\n if (config.modelSource !== \"gateway\") return {};\n if (config.taskModelChain) return { modelChain: config.taskModelChain };\n return config.gatewayAgentId ? { agentId: config.gatewayAgentId } : {};\n}\n\nexport interface FallbackLlmResponse {\n content: string;\n modelUsed: string;\n usage?: {\n inputTokens?: number;\n outputTokens?: number;\n totalTokens?: number;\n };\n}\n\nexport interface FallbackLlmRuntimeContext {\n agentDir?: string;\n getRuntimeAuthForModel?: GetRuntimeAuthForModelFn | null;\n resolveApiKeyForProvider?: ResolveApiKeyFn | null;\n workspaceDir?: string;\n}\n\nexport function fallbackLlmRuntimeContextFromConfig(\n config: Pick<\n GatewayBackedRuntimeConfig,\n \"providerApiKeyResolver\" | \"runtimeAuthForModelResolver\" | \"workspaceDir\"\n >,\n overrides: FallbackLlmRuntimeContext = {},\n): FallbackLlmRuntimeContext {\n return {\n workspaceDir: config.workspaceDir,\n resolveApiKeyForProvider: config.providerApiKeyResolver,\n getRuntimeAuthForModel: config.runtimeAuthForModelResolver,\n ...overrides,\n };\n}\n\ntype GatewayBackedRuntimeConfig = {\n providerApiKeyResolver?: ResolveApiKeyFn | null;\n runtimeAuthForModelResolver?: GetRuntimeAuthForModelFn | null;\n workspaceDir?: string;\n};\n\ninterface ModelRef {\n providerId: string;\n modelId: string;\n providerConfig: ModelProviderConfig;\n modelString: string;\n}\n\nfunction isUnsupportedJsonSchemaError(error: unknown): boolean {\n const message = error instanceof Error ? error.message : String(error);\n // Require an HTTP status plus explicit schema/format context. A bare\n // \"unsupported\" (e.g. \"'temperature' is unsupported with this model\") must\n // NOT trigger the schema-stripping retry, or we pay a duplicate request\n // for unrelated provider errors.\n if (!/\\b(?:400|404|422)\\b/.test(message)) {\n return false;\n }\n if (/(?:response[_ ]?format|json[_ ]?schema|structured[_ ]?output)/i.test(message)) {\n return true;\n }\n // \"unsupported\" only counts when adjacent to schema/format terminology.\n return /\\bunsupported\\b[\\s\\S]{0,40}\\b(?:schema|format)\\b/i.test(message);\n}\n\nconst PROVIDER_ALIASES: Record<string, readonly string[]> = {\n \"openai-codex\": [\"codex\"],\n codex: [\"openai-codex\"],\n \"claude-cli\": [\"anthropic\"],\n};\n\nconst LEGACY_PROVIDER_IDS = new Set([\"openai-codex\", \"claude-cli\"]);\n\nconst MANAGED_SECRETREF_MARKER = [\"secretref\", \"managed\"].join(\"-\");\nconst PROVIDER_API_KEY_FIELD = [\"api\", \"Key\"].join(\"\") as keyof ModelProviderConfig;\n\n/**\n * Built-in provider fallbacks for providers that are commonly configured via\n * OAuth or gateway-managed auth rather than an explicit apiKey in\n * openclaw.json. These entries let resolveProviderConfig() succeed so the\n * chain proceeds to tryModel() → resolveRuntimeAuth(), which is where the\n * gateway's native OAuth token exchange happens.\n *\n * Without these, OAuth-only providers like `openai` are rejected with\n * \"provider not found\" before runtime auth is ever attempted.\n */\nconst BUILT_IN_PROVIDER_FALLBACKS: Record<string, ModelProviderConfig> = {\n anthropic: {\n baseUrl: \"https://api.anthropic.com/v1\",\n api: \"anthropic-messages\",\n models: [],\n [PROVIDER_API_KEY_FIELD]: MANAGED_SECRETREF_MARKER,\n },\n openai: {\n baseUrl: \"https://api.openai.com/v1\",\n api: \"openai-responses\",\n models: [],\n [PROVIDER_API_KEY_FIELD]: MANAGED_SECRETREF_MARKER,\n },\n};\n\n/**\n * Generic fallback LLM client that uses the gateway's default AI configuration\n * and walks through the full fallback chain (primary + fallbacks).\n * Supports OpenAI and Anthropic API formats.\n */\nexport class FallbackLlmClient {\n private gatewayConfig: GatewayConfig | undefined;\n private runtimeContext: FallbackLlmRuntimeContext;\n\n constructor(\n gatewayConfig?: GatewayConfig,\n runtimeContext: FallbackLlmRuntimeContext = {},\n ) {\n this.gatewayConfig = gatewayConfig;\n this.runtimeContext = {\n ...runtimeContext,\n workspaceDir:\n normalizeRuntimePath(runtimeContext.workspaceDir) ??\n readGatewayWorkspaceDir(gatewayConfig) ??\n defaultOpenClawWorkspaceDir(),\n };\n }\n\n /**\n * Check if fallback is available (gateway config has at least one model).\n */\n isAvailable(agentIdOrOptions?: string | FallbackLlmAvailabilityOptions): boolean {\n const options = typeof agentIdOrOptions === \"string\"\n ? { agentId: agentIdOrOptions }\n : (agentIdOrOptions ?? {});\n const models = this.getModelChain(options.agentId, undefined, options.modelChain);\n return models.length > 0;\n }\n\n /**\n * Make a chat completion request using the gateway's default AI chain.\n * Tries primary first, then each fallback in order.\n * When agentId is provided, uses that agent persona's model chain instead of defaults.\n */\n async chatCompletion(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions = {},\n ): Promise<FallbackLlmResponse | null> {\n const models = this.getModelChain(\n options.agentId,\n options.model,\n options.modelChain,\n options.includeDefaultModelFallback,\n );\n if (models.length === 0) {\n log.warn(\"fallback LLM: no models configured in gateway\");\n return null;\n }\n\n const runChain = async (\n initialOptions: FallbackLlmOptions,\n ): Promise<FallbackLlmResponse | null> => {\n let runOptions = initialOptions;\n let lastRejectedResponse: FallbackLlmResponse | null = null;\n // Try each model in the chain\n for (let i = 0; i < models.length; i++) {\n if (runOptions.signal?.aborted) {\n throw abortReason(runOptions.signal);\n }\n const model = models[i];\n const isFallback = i > 0;\n\n try {\n const result = await this.tryModel(model, messages, runOptions);\n if (result) {\n const response = {\n content: result.content,\n modelUsed: model.modelString,\n usage: result.usage,\n };\n if (runOptions.acceptResponse && !runOptions.acceptResponse(response)) {\n lastRejectedResponse = response;\n log.debug(`fallback LLM: ${model.modelString} returned rejected output, trying next...`);\n continue;\n }\n if (isFallback) {\n log.debug(`fallback LLM: succeeded using ${model.modelString} (fallback ${i})`);\n }\n return response;\n }\n } catch (err) {\n if (runOptions.signal?.aborted) {\n throw abortReason(runOptions.signal);\n }\n if (\n (runOptions.jsonSchema || runOptions.responsesJsonSchema) &&\n isUnsupportedJsonSchemaError(err)\n ) {\n log.debug(`fallback LLM: ${model.modelString} rejected native JSON schema; retrying without it`);\n // Degrade to prompt-only for the REST of the chain too, so an\n // N-model chain where every provider rejects structured output\n // costs N+1 requests instead of 2N.\n runOptions = {\n ...runOptions,\n jsonSchema: undefined,\n responsesJsonSchema: undefined,\n };\n try {\n const result = await this.tryModel(model, messages, runOptions);\n if (result) {\n const response = {\n content: result.content,\n modelUsed: model.modelString,\n usage: result.usage,\n };\n if (!runOptions.acceptResponse || runOptions.acceptResponse(response)) {\n return response;\n }\n lastRejectedResponse = response;\n log.debug(`fallback LLM: ${model.modelString} unstructured retry output rejected by acceptResponse, trying next model...`);\n continue;\n }\n } catch (retryError) {\n if (runOptions.signal?.aborted) throw abortReason(runOptions.signal);\n const retryErrorMsg = runOptions.redactProviderErrors\n ? \"provider error details redacted\"\n : retryError instanceof Error\n ? retryError.message\n : String(retryError);\n log.debug(\n `fallback LLM: ${model.modelString} unstructured retry failed (${retryErrorMsg})`,\n );\n }\n continue;\n }\n const errorMsg = runOptions.redactProviderErrors\n ? \"provider error details redacted\"\n : err instanceof Error\n ? err.message\n : String(err);\n log.debug(`fallback LLM: ${model.modelString} failed (${errorMsg}), trying next...`);\n // Continue to next model in chain\n }\n }\n\n log.warn(`fallback LLM: all ${models.length} models in chain failed`);\n return lastRejectedResponse;\n };\n\n if (typeof options.timeoutMs === \"number\") {\n if (options.timeoutMs <= 0) {\n log.warn(\"fallback LLM: timed out before request started\");\n return null;\n }\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const controller = new AbortController();\n const onCallerAbort = (): void => {\n controller.abort(abortReason(options.signal));\n };\n options.signal?.addEventListener(\"abort\", onCallerAbort, { once: true });\n if (options.signal?.aborted) {\n onCallerAbort();\n }\n const timedOptions = { ...options, signal: controller.signal };\n const chain = runChain(timedOptions);\n chain.catch(() => {});\n try {\n return await Promise.race([\n chain,\n new Promise<null>((resolve) => {\n timeoutHandle = setTimeout(() => {\n log.warn(`fallback LLM: timed out after ${options.timeoutMs}ms`);\n controller.abort(\n new Error(`fallback LLM timed out after ${options.timeoutMs}ms`),\n );\n resolve(null);\n }, options.timeoutMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n options.signal?.removeEventListener(\"abort\", onCallerAbort);\n }\n }\n\n return await runChain(options);\n }\n\n /**\n * Make a request with structured output (Zod schema).\n * Returns parsed JSON or null on failure.\n */\n async parseWithSchema<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<T | null> {\n const detailed = await this.parseWithSchemaDetailed(messages, schema, options);\n return detailed?.result ?? null;\n }\n\n /**\n * Like parseWithSchema but also returns the model that was used,\n * so callers can emit accurate trace events.\n */\n async parseWithSchemaDetailed<T>(\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n schema: { parse: (data: unknown) => T },\n options: FallbackLlmOptions = {},\n ): Promise<\n | { result: T; modelUsed: string }\n | { result: null; failureReason: \"no_models\" | \"empty\" | \"http_error\" }\n > {\n let response: FallbackLlmResponse | null;\n try {\n response = await this.chatCompletion(messages, options);\n } catch (err) {\n // Caller aborts must propagate (e.g. recall planner cancellation) — do\n // not swallow them as a provider failure, or abort-driven callers lose\n // cancellation and treat it as an extraction error (codex review).\n if (options.signal?.aborted) throw err;\n log.warn(\"fallback LLM: chatCompletion threw during structured parse:\", err);\n return { result: null, failureReason: \"http_error\" };\n }\n if (!response?.content) {\n // chatCompletion returns null both when no models are configured\n // (auth/config) and when every configured model errored (transient).\n // Disambiguate via the resolved model chain so the retry layer can pick\n // the right failure class.\n const hasModels =\n this.getModelChain(\n options.agentId,\n options.model,\n options.modelChain,\n options.includeDefaultModelFallback,\n ).length > 0;\n return { result: null, failureReason: hasModels ? \"http_error\" : \"no_models\" };\n }\n\n try {\n const candidates = extractJsonCandidates(response.content);\n for (const c of candidates) {\n try {\n const parsed = JSON.parse(c);\n return { result: schema.parse(parsed), modelUsed: response.modelUsed };\n } catch {\n // keep trying other candidates\n }\n }\n return { result: null, failureReason: \"empty\" };\n } catch (err) {\n log.warn(\"fallback LLM: failed to parse structured output:\", err);\n return { result: null, failureReason: \"empty\" };\n }\n }\n\n /**\n * Get the full model chain from gateway config.\n * Returns array of models in order: [primary, fallback1, fallback2, ...]\n *\n * When modelChainOverride is provided, uses it instead of any configured\n * agent/default chain. Otherwise, when agentId is provided, looks up the\n * matching entry in agents.list[] and uses that persona's model chain.\n * Falls back to agents.defaults.model if agentId is not found or not provided.\n */\n private getModelChain(\n agentId?: string,\n modelOverride?: string,\n modelChainOverride?: AgentPersonaModelConfig,\n includeDefaultModelFallback = true,\n ): ModelRef[] {\n const chain: ModelRef[] = [];\n const providers = this.gatewayConfig?.models?.providers ?? {};\n\n // Resolve the model config: explicit task chain, agent persona chain, or global defaults\n let modelConfig: AgentPersonaModelConfig | undefined;\n\n if (modelChainOverride?.primary) {\n modelConfig = modelChainOverride;\n log.debug(\"fallback LLM: using explicit model chain override\");\n } else if (modelChainOverride) {\n log.warn(\"fallback LLM: ignoring explicit model chain override without primary model\");\n }\n\n if (!modelConfig && agentId) {\n const persona = this.gatewayConfig?.agents?.list?.find(\n (a) => a.id === agentId,\n );\n if (persona?.model) {\n modelConfig = persona.model;\n log.debug(`fallback LLM: using agent persona \"${agentId}\" model chain`);\n } else {\n log.warn(\n `fallback LLM: agent persona \"${agentId}\" not found or has no model config, falling back to defaults`,\n );\n }\n }\n\n if (!modelConfig) {\n modelConfig = this.gatewayConfig?.agents?.defaults?.model;\n }\n\n // Build list of model strings: primary + fallbacks\n const modelStrings: string[] = [];\n\n const addModelString = (value: unknown): void => {\n if (typeof value !== \"string\") return;\n const trimmed = value.trim();\n if (trimmed.length > 0 && !modelStrings.includes(trimmed)) {\n modelStrings.push(trimmed);\n }\n };\n\n addModelString(modelOverride);\n addModelString(modelConfig?.primary);\n\n if (Array.isArray(modelConfig?.fallbacks)) {\n for (const fb of modelConfig.fallbacks) {\n addModelString(fb);\n }\n }\n\n // Parse each model string and look up provider config\n for (const modelString of modelStrings) {\n const modelRef = this.parseModelString(modelString, providers);\n if (modelRef) {\n chain.push(modelRef);\n }\n }\n\n // Implicit last-resort: when a task-specific modelChain override is active,\n // append the gateway default model so a stale or exhausted taskModelChain\n // never leaves the chain empty — Remnic should never be the reason a chat is\n // interrupted by a flush failure. Keyed on `modelChainOverride?.primary` —\n // the SAME activation condition chain resolution uses above — so a\n // primary-less override (e.g. {}) that falls through to a persona/default\n // chain does NOT get the default appended (gotcha #39). Issue #1365 / PR #1370.\n if (includeDefaultModelFallback && modelChainOverride?.primary && modelStrings.length > 0) {\n // Append the FULL gateway default chain (primary + fallbacks), not just\n // the primary — if the default primary is also unreachable, a listed\n // default fallback may still succeed (cursor review #1425).\n const defaults = this.gatewayConfig?.agents?.defaults?.model;\n const defaultStrings: string[] = [\n ...(typeof defaults?.primary === \"string\" ? [defaults.primary] : []),\n ...(Array.isArray(defaults?.fallbacks) ? defaults.fallbacks : []),\n ];\n for (const candidate of defaultStrings) {\n if (typeof candidate !== \"string\") continue;\n const trimmed = candidate.trim();\n if (trimmed.length === 0 || modelStrings.includes(trimmed)) continue;\n const defaultRef = this.parseModelString(trimmed, providers);\n if (defaultRef) {\n chain.push(defaultRef);\n modelStrings.push(trimmed); // keep dedupe correct for later default fallbacks\n log.debug(\n `fallback LLM: appended gateway default model \"${trimmed}\" as implicit last resort`,\n );\n }\n }\n }\n\n return chain;\n }\n\n /**\n * Parse a \"provider/model\" string and look up its config.\n */\n private parseModelString(\n modelString: string,\n providers: Record<string, ModelProviderConfig>,\n ): ModelRef | null {\n // Parse \"provider/model\" format (e.g., \"openai/gpt-5.5\", \"anthropic/claude-opus-4-6\")\n const parts = modelString.split(\"/\");\n if (parts.length < 2) {\n log.warn(`fallback LLM: invalid model format: ${modelString}`);\n return null;\n }\n\n const requestedProviderId = parts[0];\n const modelId = parts.slice(1).join(\"/\"); // Handle cases like \"openai/gpt-5.5\"\n\n // Respect the active gateway config first so profile-local overrides and\n // credentials win. Fall back to the materialized models.json only when\n // the provider is absent from the loaded config (for built-in providers\n // registered by the gateway at runtime).\n const resolvedProvider = this.resolveProviderConfig(requestedProviderId, providers);\n const providerConfig = resolvedProvider?.config;\n if (!providerConfig) {\n log.warn(\n `fallback LLM: provider not found: ${requestedProviderId} ` +\n `(tried: ${this.providerResolutionCandidates(requestedProviderId).join(\", \")})`,\n );\n return null;\n }\n\n return {\n providerId: resolvedProvider.providerId,\n modelId,\n providerConfig,\n modelString,\n };\n }\n\n private resolveProviderConfig(\n providerId: string,\n providers: Record<string, ModelProviderConfig>,\n ): { providerId: string; config: ModelProviderConfig } | null {\n const candidates = this.providerResolutionCandidates(providerId);\n const aliasCandidates = candidates.filter((candidate) => candidate !== providerId);\n const fallbackCandidates = LEGACY_PROVIDER_IDS.has(providerId)\n ? [...aliasCandidates, providerId]\n : [providerId, ...aliasCandidates];\n for (const candidate of candidates) {\n const config = providers[candidate];\n if (config) {\n if (candidate !== providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via alias \"${candidate}\"`);\n }\n return { providerId: candidate, config };\n }\n }\n for (const candidate of fallbackCandidates) {\n const config = this.resolveFromModelsJson(candidate);\n if (config) {\n if (candidate !== providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via models.json alias \"${candidate}\"`);\n }\n return { providerId: candidate, config };\n }\n const builtInConfig = BUILT_IN_PROVIDER_FALLBACKS[candidate];\n if (builtInConfig) {\n if (candidate === providerId) {\n log.debug(`fallback LLM: provider \"${providerId}\" resolved from built-in defaults`);\n return { providerId, config: builtInConfig };\n }\n log.debug(`fallback LLM: provider \"${providerId}\" resolved via built-in alias \"${candidate}\"`);\n return { providerId: candidate, config: builtInConfig };\n }\n }\n return null;\n }\n\n private providerResolutionCandidates(providerId: string): string[] {\n const candidates = [providerId, ...(PROVIDER_ALIASES[providerId] ?? [])];\n return [...new Set(candidates)];\n }\n\n /**\n * Look up a provider from the gateway's materialized models.json, which\n * contains all providers including built-in ones (openai-codex, google-vertex,\n * etc.) that aren't in the user's openclaw.json but are registered by\n * gateway plugins. Returns null if the provider isn't found there either.\n */\n private resolveFromModelsJson(providerId: string): ModelProviderConfig | null {\n const allProviders = loadModelsJsonProviders();\n const config = allProviders[providerId];\n if (config) {\n log.debug(`fallback LLM: resolved provider \"${providerId}\" from models.json (api: ${config.api ?? \"default\"})`);\n return config;\n }\n return null;\n }\n\n /**\n * Try to call a single model.\n *\n * Uses the gateway's native getRuntimeAuthForModel when available — this\n * handles all provider-specific auth transforms (OAuth token exchange,\n * base URL overrides for codex/copilot/etc.) through the same codepath\n * the gateway itself uses. Falls back to resolveProviderApiKey for\n * simpler providers or when the runtime module isn't loaded.\n */\n private async tryModel(\n model: ModelRef,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n // Try the gateway's native runtime auth first — it handles all provider-\n // specific transforms (OAuth exchange, base URL rewrite, etc.)\n const runtimeAuth = model.providerConfig.api === \"codex-cli\"\n ? null\n : await this.resolveRuntimeAuth(model);\n const effectiveBaseUrl = runtimeAuth?.baseUrl ?? model.providerConfig.baseUrl;\n const resolvedApiKey = runtimeAuth?.apiKey\n ?? (\n model.providerConfig.api === \"codex-cli\" && model.providerConfig.apiKey === undefined\n ? undefined\n : await this.resolveFallbackApiKey(model)\n );\n\n // If the raw key looks like an unresolved secret ref and resolution fails,\n // skip this provider entirely so the chain falls through to the next.\n const rawKey = model.providerConfig.apiKey;\n const needsResolution = rawKey === \"secretref-managed\"\n || (typeof rawKey === \"object\" && rawKey !== null);\n if (needsResolution && !resolvedApiKey) {\n throw new Error(`API key for provider \"${model.providerId}\" could not be resolved from secret ref`);\n }\n\n const effectiveConfig: ModelProviderConfig = {\n ...model.providerConfig,\n baseUrl: effectiveBaseUrl,\n ...(resolvedApiKey ? { apiKey: resolvedApiKey } : {}),\n };\n\n if (model.providerConfig.api === \"anthropic-messages\") {\n return await this.callAnthropic(effectiveConfig, model.modelId, messages, options);\n }\n\n if (model.providerConfig.api === \"codex-cli\") {\n return await callCodexCliFallback(\n effectiveConfig,\n model.modelId,\n messages,\n { timeoutMs: options.timeoutMs, signal: options.signal },\n );\n }\n\n if (model.providerConfig.api === \"ollama-chat\") {\n return await this.callOllamaChat(effectiveConfig, model.modelId, messages, options);\n }\n\n if (\n model.providerConfig.api === \"openai-responses\" ||\n model.providerConfig.api === \"openai-codex-responses\" ||\n model.providerConfig.api === \"azure-openai-responses\"\n ) {\n return await this.callOpenAIResponses(\n effectiveConfig,\n model.modelId,\n messages,\n options,\n );\n }\n\n // For OpenAI-compatible chat-completions APIs (openai-completions,\n // ollama, etc.) and unknown formats, use chat completions — the gateway's\n // runtime auth resolver returns request-ready base URL and credentials for\n // most providers.\n return await this.callOpenAI(\n effectiveConfig,\n model.modelId,\n messages,\n options,\n shouldAssumeOpenAiChatCompletions(effectiveConfig.baseUrl),\n );\n }\n\n /**\n * Resolve request-ready auth through the gateway's native runtime, which\n * handles provider-specific transforms (OAuth token exchange for codex/copilot,\n * base URL rewrite, etc.). Returns null if the runtime isn't available.\n */\n private async resolveRuntimeAuth(\n model: ModelRef,\n ): Promise<{ apiKey?: string; baseUrl?: string } | null> {\n try {\n const getRuntimeAuth = await getGatewayRuntimeAuthForModel({\n getRuntimeAuthForModel: this.runtimeContext.getRuntimeAuthForModel,\n });\n if (!getRuntimeAuth) return null;\n\n const result = await getRuntimeAuth({\n model: {\n provider: model.providerId,\n id: model.modelId,\n api: model.providerConfig.api,\n baseUrl: model.providerConfig.baseUrl,\n },\n cfg: this.gatewayConfig,\n workspaceDir: this.runtimeContext.workspaceDir,\n });\n\n if (result?.apiKey || result?.baseUrl) {\n log.debug(\n `fallback LLM: resolved runtime auth for \"${model.modelString}\" (source: ${result.source ?? \"unknown\"}, mode: ${result.mode ?? \"unknown\"})`,\n );\n return { apiKey: result.apiKey, baseUrl: result.baseUrl };\n }\n } catch (err) {\n log.debug(\n `fallback LLM: gateway runtime auth failed for \"${model.modelString}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n return null;\n }\n\n /**\n * Resolve API key through the existing provider-level resolution (env vars,\n * secret refs, etc.). Used as fallback when gateway runtime auth isn't available.\n */\n private async resolveFallbackApiKey(model: ModelRef): Promise<string | undefined> {\n return resolveProviderApiKey(\n model.providerId,\n model.providerConfig.apiKey,\n this.gatewayConfig,\n this.runtimeContext.agentDir,\n {\n resolveApiKeyForProvider: this.runtimeContext.resolveApiKeyForProvider,\n },\n );\n }\n\n /**\n * Call OpenAI-compatible API.\n */\n private async callOpenAI(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n assumeOpenAI: boolean,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/chat/completions`\n : `${base}/v1/chat/completions`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n\n // Handle auth — apiKey is already resolved to a string by tryModel()\n if (config.apiKey && typeof config.apiKey === \"string\") {\n if (config.authHeader !== false) {\n headers[\"Authorization\"] = `Bearer ${config.apiKey}`;\n }\n }\n\n const body = {\n model: modelId,\n messages,\n ...buildChatCompletionTemperature(modelId, options.temperature ?? 0.3, {\n assumeOpenAI,\n }),\n ...buildChatCompletionTokenLimit(modelId, options.maxTokens ?? 4096, {\n assumeOpenAI,\n }),\n ...(options.jsonSchema\n ? {\n response_format: {\n type: \"json_schema\",\n json_schema: {\n name: options.jsonSchema.name,\n strict: options.jsonSchema.strict ?? false,\n schema: options.jsonSchema.schema,\n },\n },\n }\n : {}),\n };\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n signal: options.signal,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n choices: Array<{\n message: {\n content: string;\n };\n }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const content = data.choices?.[0]?.message?.content;\n if (!content) {\n throw new Error(\"Empty response from OpenAI API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.prompt_tokens,\n outputTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Call Ollama's native /api/chat transport. This lets benchmark-isolated\n * gateway configs route Remnic's own internal LLM calls to Ollama Cloud\n * without requiring an OpenAI-compatible shim.\n */\n private async callOllamaChat(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/api\") ? `${base}/chat` : `${base}/api/chat`;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n if (config.apiKey && typeof config.apiKey === \"string\" && config.authHeader !== false) {\n headers.Authorization = `Bearer ${config.apiKey}`;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n signal: options.signal,\n body: JSON.stringify({\n model: modelId,\n messages,\n stream: false,\n ...(config.disableThinking ? { think: false } : {}),\n options: {\n temperature: options.temperature ?? 0.3,\n num_predict: options.maxTokens ?? 4096,\n },\n }),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Ollama API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n message?: { content?: string };\n response?: string;\n prompt_eval_count?: number;\n eval_count?: number;\n };\n const content = data.message?.content ?? data.response;\n if (!content) {\n throw new Error(\"Empty response from Ollama API\");\n }\n\n const inputTokens = data.prompt_eval_count ?? 0;\n const outputTokens = data.eval_count ?? 0;\n return {\n content,\n usage: {\n inputTokens,\n outputTokens,\n totalTokens: inputTokens + outputTokens,\n },\n };\n }\n\n /**\n * Call an OpenAI-compatible Responses API.\n */\n private async callOpenAIResponses(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/responses`\n : `${base}/v1/responses`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...config.headers,\n };\n\n if (config.apiKey && typeof config.apiKey === \"string\" && config.authHeader !== false) {\n headers[\"Authorization\"] = `Bearer ${config.apiKey}`;\n }\n\n const instructions = messages\n .filter((message) => message.role === \"system\")\n .map((message) => message.content)\n .join(\"\\n\\n\")\n .trim();\n const input = messages\n .filter((message) => message.role !== \"system\")\n .map((message) => ({\n role: message.role,\n content: [{\n type: message.role === \"assistant\" ? \"output_text\" : \"input_text\",\n text: message.content,\n }],\n }));\n\n const body: Record<string, unknown> = {\n model: modelId,\n input,\n max_output_tokens: Math.max(0, Math.floor(options.maxTokens ?? 4096)),\n ...buildChatCompletionTemperature(modelId, options.temperature ?? 0.3, {\n assumeOpenAI: shouldAssumeOpenAiChatCompletions(config.baseUrl),\n }),\n ...(options.store === undefined ? {} : { store: options.store }),\n ...(options.jsonSchema || options.responsesJsonSchema\n ? {\n text: {\n format: {\n type: \"json_schema\",\n name: (options.jsonSchema ?? options.responsesJsonSchema)!.name,\n strict: (options.jsonSchema?.strict ?? (options.responsesJsonSchema ? true : false)),\n schema: (options.jsonSchema ?? options.responsesJsonSchema)!.schema,\n },\n },\n }\n : {}),\n };\n if (instructions.length > 0) {\n body.instructions = instructions;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n signal: options.signal,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`OpenAI Responses API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n output_text?: string;\n output?: Array<{\n type?: string;\n text?: string;\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n total_tokens?: number;\n };\n };\n\n const outputText = extractResponsesOutputText(data);\n if (!outputText) {\n throw new Error(\"Empty response from OpenAI Responses API\");\n }\n\n return {\n content: outputText,\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n };\n }\n\n /**\n * Call Anthropic Messages API.\n */\n private async callAnthropic(\n config: ModelProviderConfig,\n modelId: string,\n messages: Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n options: FallbackLlmOptions,\n ): Promise<{ content: string; usage?: FallbackLlmResponse[\"usage\"] } | null> {\n const base = config.baseUrl.replace(/\\/$/, \"\");\n const url = base.endsWith(\"/v1\")\n ? `${base}/messages`\n : `${base}/v1/messages`;\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n \"anthropic-version\": \"2023-06-01\",\n ...config.headers,\n };\n\n // Handle auth - Anthropic uses x-api-key header (apiKey resolved by tryModel)\n if (config.apiKey && typeof config.apiKey === \"string\") {\n headers[\"x-api-key\"] = config.apiKey;\n }\n\n // Extract system message (Anthropic handles it separately)\n const systemMessage = messages.find((m) => m.role === \"system\")?.content;\n const nonSystemMessages = messages.filter((m) => m.role !== \"system\");\n\n // Convert messages to Anthropic format\n const anthropicMessages = nonSystemMessages.map((m) => ({\n role: m.role,\n content: m.content,\n }));\n\n const body: Record<string, unknown> = {\n model: modelId,\n messages: anthropicMessages,\n max_tokens: options.maxTokens ?? 4096,\n temperature: options.temperature ?? 0.3,\n };\n\n if (systemMessage) {\n body.system = systemMessage;\n }\n\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n signal: options.signal,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n const error = await response.text();\n throw new Error(`Anthropic API error: ${response.status} ${error}`);\n }\n\n const data = (await response.json()) as {\n content: Array<{\n type: string;\n text: string;\n }>;\n usage?: {\n input_tokens?: number;\n output_tokens?: number;\n };\n };\n\n const content = data.content?.[0]?.text;\n if (!content) {\n throw new Error(\"Empty response from Anthropic API\");\n }\n\n return {\n content,\n usage: data.usage\n ? {\n inputTokens: data.usage.input_tokens,\n outputTokens: data.usage.output_tokens,\n totalTokens: (data.usage.input_tokens ?? 0) + (data.usage.output_tokens ?? 0),\n }\n : undefined,\n };\n }\n}\n\nfunction abortReason(signal: AbortSignal | undefined): Error {\n const reason = signal?.reason;\n return reason instanceof Error ? reason : new Error(\"fallback LLM request aborted\");\n}\n\nfunction normalizeRuntimePath(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n return trimmed.length > 0 ? expandTildePath(trimmed) : undefined;\n}\n\nfunction readGatewayWorkspaceDir(gatewayConfig: GatewayConfig | undefined): string | undefined {\n if (!gatewayConfig || typeof gatewayConfig !== \"object\") return undefined;\n const raw = gatewayConfig as Record<string, unknown>;\n return (\n normalizeRuntimePath(raw.workspaceDir) ??\n normalizeRuntimePath(raw.workspacePath) ??\n normalizeRuntimePath(raw.workspace)\n );\n}\n\nfunction defaultOpenClawWorkspaceDir(): string {\n return path.join(resolveHomeDir(), \".openclaw\", \"workspace\");\n}\n\nfunction extractResponsesOutputText(data: {\n output_text?: string;\n output?: Array<{\n type?: string;\n text?: string;\n content?: Array<{\n type?: string;\n text?: string;\n }>;\n }>;\n}): string | null {\n if (typeof data.output_text === \"string\" && data.output_text.trim().length > 0) {\n return data.output_text;\n }\n\n const chunks: string[] = [];\n for (const item of data.output ?? []) {\n if (typeof item.text === \"string\" && item.text.trim().length > 0) {\n chunks.push(item.text);\n }\n for (const part of item.content ?? []) {\n if (\n (part.type === \"output_text\" || part.type === \"text\") &&\n typeof part.text === \"string\" &&\n part.text.trim().length > 0\n ) {\n chunks.push(part.text);\n }\n }\n }\n\n const joined = chunks.join(\"\\n\").trim();\n return joined.length > 0 ? joined : null;\n}\n"],"mappings":"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","names":[]}
@@ -1,9 +1,9 @@
1
- import {
2
- coerceBool
3
- } from "./chunk-PQVCH2AE.js";
4
1
  import {
5
2
  DEFAULT_UNTRUSTED_ORIGINS
6
3
  } from "./chunk-6Q3ZTEF6.js";
4
+ import {
5
+ coerceBool
6
+ } from "./chunk-PQVCH2AE.js";
7
7
  import {
8
8
  readEnvVar
9
9
  } from "./chunk-JUC24CTX.js";
@@ -91,4 +91,4 @@ function parseSecurityConfig(cfg, rawOperatorConfig) {
91
91
  export {
92
92
  parseSecurityConfig
93
93
  };
94
- //# sourceMappingURL=chunk-T3JQTCCO.js.map
94
+ //# sourceMappingURL=chunk-JI7U6AS3.js.map
@@ -1,10 +1,6 @@
1
1
  import {
2
2
  warnProjectionFallback
3
3
  } from "./chunk-ZA53AZND.js";
4
- import {
5
- ensureContainedSpillDir,
6
- listContainedSpillFiles
7
- } from "./chunk-GCASGYIO.js";
8
4
  import {
9
5
  MEMORY_LIFECYCLE_LEDGER_APPEND_LOCK_MAX_WAIT_MS,
10
6
  MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,
@@ -20,10 +16,14 @@ import {
20
16
  readProjectedEntityMentions,
21
17
  readProjectedGovernanceRecord,
22
18
  readProjectedNativeKnowledgeChunks
23
- } from "./chunk-2LWQSV6A.js";
19
+ } from "./chunk-AL3UYZ5N.js";
24
20
  import {
25
21
  displayErrorDetail
26
22
  } from "./chunk-RL6NEVXT.js";
23
+ import {
24
+ ensureContainedSpillDir,
25
+ listContainedSpillFiles
26
+ } from "./chunk-GCASGYIO.js";
27
27
  import {
28
28
  withHeldFileLock
29
29
  } from "./chunk-FFAZ2XFU.js";
@@ -31,7 +31,7 @@ import {
31
31
  MAGIC_HEADER_SIZE,
32
32
  SecureStoreLockedError,
33
33
  isEncryptedFile
34
- } from "./chunk-XQ3HXAQH.js";
34
+ } from "./chunk-ET2CNMLD.js";
35
35
  import {
36
36
  isErrnoCode
37
37
  } from "./chunk-5UZXUTVO.js";
@@ -219,6 +219,7 @@ async function readMemoryActionEventRowsFromLines(lines, limit) {
219
219
  if (!line) continue;
220
220
  try {
221
221
  const parsed = JSON.parse(line);
222
+ if (parsed.recordKind !== void 0) continue;
222
223
  const outcome = parsed.outcome === "applied" || parsed.outcome === "skipped" || parsed.outcome === "failed" ? parsed.outcome : null;
223
224
  if (typeof parsed.timestamp === "string" && typeof parsed.action === "string" && outcome !== null) {
224
225
  const entry = {
@@ -237,6 +238,33 @@ async function readMemoryActionEventRowsFromLines(lines, limit) {
237
238
  }
238
239
  return writeIndex === 0 ? out : [...out.slice(writeIndex), ...out.slice(0, writeIndex)];
239
240
  }
241
+ async function readContextTransformRecordRowsFromLines(lines, limit) {
242
+ const out = [];
243
+ let writeIndex = 0;
244
+ let lineNumber = 0;
245
+ for await (const row of lines) {
246
+ lineNumber += 1;
247
+ const line = row.trim();
248
+ if (!line) continue;
249
+ try {
250
+ const parsed = JSON.parse(line);
251
+ if (parsed.recordKind === "context_transform" && typeof parsed.timestamp === "string" && typeof parsed.actionId === "string" && typeof parsed.planHash === "string") {
252
+ const entry = {
253
+ line: lineNumber,
254
+ record: parsed
255
+ };
256
+ if (out.length < limit) {
257
+ out.push(entry);
258
+ } else {
259
+ out[writeIndex] = entry;
260
+ writeIndex = (writeIndex + 1) % limit;
261
+ }
262
+ }
263
+ } catch {
264
+ }
265
+ }
266
+ return writeIndex === 0 ? out : [...out.slice(writeIndex), ...out.slice(0, writeIndex)];
267
+ }
240
268
  function isValidLifecycleEventRow(parsed) {
241
269
  return typeof parsed.eventId === "string" && typeof parsed.memoryId === "string" && typeof parsed.eventType === "string" && typeof parsed.timestamp === "string" && typeof parsed.actor === "string" && typeof parsed.ruleVersion === "string";
242
270
  }
@@ -713,6 +741,7 @@ export {
713
741
  STATE_FILE_MAX_DECRYPT_BYTES,
714
742
  readMaybeEncryptedLines,
715
743
  readMemoryActionEventRowsFromLines,
744
+ readContextTransformRecordRowsFromLines,
716
745
  readAllLifecycleEventsFromLedger,
717
746
  readAllLifecycleEventsFromLedgerBuffer,
718
747
  readBoundedLifecycleEventsFromLedger,
@@ -724,4 +753,4 @@ export {
724
753
  drainPendingLifecycleLedgerForSync,
725
754
  drainPendingLifecycleForSyncOrThrow
726
755
  };
727
- //# sourceMappingURL=chunk-DVYRD4HY.js.map
756
+ //# sourceMappingURL=chunk-JRRQ747T.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/maintenance/projection-support.ts","../src/storage/secure-line-reader.ts","../src/storage/memory-lifecycle-ledger-access.ts"],"sourcesContent":["/**\n * Projection maintenance support (issue #2119) — helpers shared by the\n * scheduled projection rebuild, the CLI rebuild, and the ledger rebuild.\n * Lives beside the rebuild ops so the at-ceiling store/rebuild modules stay\n * within their structural ratchets.\n */\n\nimport path from \"node:path\";\nimport {\n openProjectionReadonly,\n readProjectedEntityMentions,\n readProjectedGovernanceRecord,\n readProjectedNativeKnowledgeChunks,\n type MemoryProjectionGovernanceAppliedActionRow,\n type MemoryProjectionGovernanceReviewQueueRow,\n type ProjectedEntityMentionRow,\n type ProjectedNativeKnowledgeChunkRow,\n} from \"../memory-projection-store.js\";\nimport {\n isFrontmatterDerivedLifecycleEventType,\n memoryLifecycleEventProjectionIdentity,\n} from \"../memory-lifecycle-ledger-utils.js\";\nimport type { MemoryLifecycleEvent } from \"../types.js\";\nimport type { BetterSqlite3Database } from \"../runtime/better-sqlite.js\";\n\n/** Read the projection meta rebuiltAt timestamp; null when absent/unopenable. */\nexport function readProjectionRebuiltAt(memoryDir: string): string | null {\n const db = openProjectionReadonly(memoryDir);\n if (!db) return null;\n try {\n const row = db.prepare(\"SELECT value FROM meta WHERE key = 'rebuiltAt'\").get() as\n | { value?: unknown }\n | undefined;\n return typeof row?.value === \"string\" && row.value.length > 0 ? row.value : null;\n } catch {\n return null;\n } finally {\n db.close();\n }\n}\n\n/** Format projection age description string for fallback warning telemetry. */\nexport function formatProjectionAge(rebuiltAt: string | null): string {\n if (!rebuiltAt) return \"projection never rebuilt\";\n const ageMs = Date.now() - Date.parse(rebuiltAt);\n if (!Number.isFinite(ageMs)) return `projection rebuiltAt=${rebuiltAt}`;\n const ageMin = Math.max(0, Math.round(ageMs / 60_000));\n const age = ageMin >= 120 ? `${Math.round(ageMin / 60)}h` : `${ageMin}m`;\n return `projection ${age} stale, last rebuilt ${rebuiltAt}`;\n}\n\nexport interface ProjectionLifecycleLedgerHighWater {\n eventCount: number;\n sourceEventCount: number;\n}\n\nfunction readProjectionHighWaterFromDb(\n db: BetterSqlite3Database,\n): ProjectionLifecycleLedgerHighWater | null {\n const sourceRow = db.prepare(\n \"SELECT value FROM meta WHERE key = 'sourceLifecycleLedgerEventCount'\",\n ).get() as { value?: unknown } | undefined;\n const projectedRow = db.prepare(\n \"SELECT value FROM meta WHERE key = 'projectedLifecycleLedgerEventCount'\",\n ).get() as { value?: unknown } | undefined;\n if (\n typeof sourceRow?.value !== \"string\"\n || !/^\\d+$/.test(sourceRow.value)\n || typeof projectedRow?.value !== \"string\"\n || !/^\\d+$/.test(projectedRow.value)\n ) return null;\n const sourceEventCount = Number(sourceRow.value);\n const eventCount = Number(projectedRow.value);\n if (!Number.isSafeInteger(sourceEventCount) || !Number.isSafeInteger(eventCount)) return null;\n return { eventCount, sourceEventCount };\n}\n\nexport function readProjectionLifecycleLedgerHighWater(\n memoryDir: string,\n): ProjectionLifecycleLedgerHighWater | null {\n const db = openProjectionReadonly(memoryDir);\n if (!db) return null;\n try {\n return readProjectionHighWaterFromDb(db);\n } catch {\n return null;\n } finally {\n db.close();\n }\n}\n\nexport interface ProjectionLifecycleLedgerLagTracker {\n highWater: ProjectionLifecycleLedgerHighWater;\n record(event: MemoryLifecycleEvent): { unique: boolean; projected: boolean };\n close(): void;\n}\n\nexport function openProjectionLifecycleLedgerLagTracker(\n memoryDir: string,\n): ProjectionLifecycleLedgerLagTracker | null {\n const db = openProjectionReadonly(memoryDir);\n if (!db) return null;\n try {\n const highWater = readProjectionHighWaterFromDb(db);\n if (!highWater) {\n db.close();\n return null;\n }\n db.pragma(\"temp_store = FILE\");\n db.exec(`\n CREATE TEMP TABLE projection_lag_current_identity (\n identity TEXT PRIMARY KEY\n ) WITHOUT ROWID;\n `);\n db.pragma(\"temp.cache_size = -1024\");\n const insertCurrent = db.prepare(\n \"INSERT OR IGNORE INTO projection_lag_current_identity(identity) VALUES (?)\",\n );\n const findProjectedEvent = db.prepare(\n \"SELECT 1 FROM memory_timeline WHERE event_id = ? LIMIT 1\",\n );\n const findProjectedFrontmatterEvent = db.prepare(`\n SELECT 1\n FROM memory_timeline\n WHERE memory_id = ? AND event_type = ? AND timestamp = ?\n LIMIT 1\n `);\n return {\n highWater,\n record(event) {\n if (!event.memoryId.trim()) return { unique: false, projected: false };\n const identity = memoryLifecycleEventProjectionIdentity(event);\n const inserted = insertCurrent.run(identity);\n if (inserted.changes === 0) return { unique: false, projected: false };\n const projected = isFrontmatterDerivedLifecycleEventType(event.eventType)\n ? findProjectedFrontmatterEvent.get(event.memoryId, event.eventType, event.timestamp)\n : findProjectedEvent.get(event.eventId);\n return { unique: true, projected: projected !== undefined };\n },\n close: () => db.close(),\n };\n } catch {\n db.close();\n return null;\n }\n}\n/** Write the high-water ledger marker counts to projection meta store. */\nexport function writeProjectionMetaHighWater(\n insertMeta: { run: (key: string, value: string) => void },\n sourceLifecycleLedgerEventCount: number,\n timelineRows: MemoryLifecycleEvent[],\n): void {\n insertMeta.run(\"sourceLifecycleLedgerEventCount\", String(sourceLifecycleLedgerEventCount));\n insertMeta.run(\n \"projectedLifecycleLedgerEventCount\",\n String(new Set(timelineRows.map(memoryLifecycleEventProjectionIdentity)).size),\n );\n}\n\nexport function readProjectedEntityMentionRows(\n memoryDir: string,\n): { projectionExists: boolean; rows: ProjectedEntityMentionRow[] } {\n const rows = readProjectedEntityMentions(memoryDir);\n if (rows === null) return { projectionExists: false, rows: [] };\n return { projectionExists: true, rows };\n}\n\nexport function readProjectedNativeKnowledgeRows(\n memoryDir: string,\n): { projectionExists: boolean; rows: ProjectedNativeKnowledgeChunkRow[] } {\n const rows = readProjectedNativeKnowledgeChunks(memoryDir);\n if (rows === null) return { projectionExists: false, rows: [] };\n return { projectionExists: true, rows };\n}\n\nexport function readProjectedGovernanceRows(memoryDir: string): {\n projectionExists: boolean;\n runId: string | null;\n summary: unknown;\n metrics: unknown;\n reviewQueueRows: MemoryProjectionGovernanceReviewQueueRow[];\n appliedActionRows: MemoryProjectionGovernanceAppliedActionRow[];\n report: string;\n} {\n const record = readProjectedGovernanceRecord(memoryDir);\n if (record === null) {\n return {\n projectionExists: false,\n runId: null,\n summary: undefined,\n metrics: undefined,\n reviewQueueRows: [],\n appliedActionRows: [],\n report: \"\",\n };\n }\n return {\n projectionExists: true,\n runId: record.runId,\n summary: record.summary,\n metrics: record.metrics,\n reviewQueueRows: record.reviewQueueRows,\n appliedActionRows: record.appliedActionRows,\n report: record.report,\n };\n}\n\n/**\n * Assert an optionally injected storage (e.g. the daemon's live unlocked\n * secure-store instance) is rooted at `memoryDir`, and hand it back. Shared\n * by the projection and lifecycle-ledger rebuilds so the containment guard\n * cannot drift between them; callers construct their own StorageManager when\n * nothing was injected (keeps this module off the direct-storage-import\n * ratchet, issue #1533).\n */\nexport function assertInjectedStorageRooted<T extends { dir: string }>(\n label: string,\n memoryDir: string,\n injected: T | undefined,\n): T | undefined {\n if (injected && path.resolve(injected.dir) !== path.resolve(memoryDir)) {\n throw new Error(\n `${label}: storage.dir (${injected.dir}) must match memoryDir (${memoryDir})`,\n );\n }\n return injected;\n}\n\nexport interface SkippedDuplicateMemory {\n memoryId: string;\n keptPath: string;\n skippedPath: string;\n}\n\nexport interface SkippedBlankIdMemory {\n path: string;\n}\nexport interface SkippedDuplicateTimelineEvent {\n eventId: string;\n keptPath: string;\n skippedPath: string;\n}\n\nexport interface SkippedBlankIdTimelineEvent {\n eventId: string;\n path: string;\n}\n","import { createReadStream } from \"node:fs\";\nimport { lstat, open } from \"node:fs/promises\";\nimport { createInterface } from \"node:readline\";\n\nimport { isEncryptedFile, MAGIC_HEADER_SIZE } from \"../secure-store/secure-fs.js\";\nimport type { ContextTransformTelemetryRecord } from \"../active-context-transform.js\";\nimport type { MemoryActionEvent, MemoryLifecycleEvent } from \"../types.js\";\n\n/**\n * Whole-file decrypt ceiling for encrypted state files. V8's max string length\n * is ~512MB; a decrypted body that approaches it throws an opaque\n * `Invalid string length` on every read (the 691MB lifecycle-ledger incident).\n * We refuse at a size comfortably under the cap and point the operator at the\n * compaction remedy instead of letting the runtime crash. Plaintext streaming\n * is unaffected at any size.\n */\nexport const STATE_FILE_MAX_DECRYPT_BYTES = 400 * 1024 * 1024;\n\n/**\n * Stream plaintext files by line while preserving authenticated whole-file\n * reads for encrypted files. `maxDecryptBytes` bounds the whole-file decrypt:\n * when set, an encrypted file at/over it is refused before decryption with an\n * actionable error. The ceiling is OPT-IN so it applies ONLY to callers with a\n * compaction-backed remedy (the lifecycle ledger). Callers with no bounded\n * maintenance path — e.g. the memory-actions ledger — omit it and keep the\n * prior unbounded read (issue #1910).\n */\nexport async function* readMaybeEncryptedLines(\n filePath: string,\n readEncryptedFile: () => Promise<string>,\n maxDecryptBytes?: number,\n): AsyncGenerator<string> {\n // Reject a symlink/FIFO/device BEFORE opening, matching the maintenance ledger\n // probe (probeEncryptedRegularFileHeader, #2033): opening a FIFO blocks until a\n // writer appears and a symlink would redirect the read outside our tree. An\n // ENOENT from the missing regular file propagates so callers keep their\n // absent-file → [] behavior (they catch ENOENT), exactly as a missing open did.\n const entryStat = await lstat(filePath);\n if (!entryStat.isFile()) {\n throw new Error(\n `refusing to read non-regular state file ${filePath} `\n + `(symlink/FIFO/device); opening it could block or escape containment (#2033)`,\n );\n }\n const file = await open(filePath, \"r\");\n const header = Buffer.alloc(MAGIC_HEADER_SIZE);\n try {\n const { bytesRead } = await file.read(header, 0, header.length, 0);\n if (isEncryptedFile(header.subarray(0, bytesRead))) {\n if (maxDecryptBytes !== undefined) {\n const { size } = await file.stat();\n if (size >= maxDecryptBytes) {\n throw new Error(\n `encrypted state file ${filePath} is ${size} bytes, at or over the ${maxDecryptBytes}-byte `\n + `whole-file decrypt limit. Run 'remnic rebuild-memory-lifecycle-ledger --write' (add `\n + `'--namespace <ns>' when the path is under namespaces/<ns>/state) or 'remnic doctor' to compact it.`,\n );\n }\n }\n yield* (await readEncryptedFile()).split(\"\\n\");\n return;\n }\n\n const input = createReadStream(filePath, {\n autoClose: false,\n encoding: \"utf8\",\n fd: file.fd,\n start: 0,\n });\n const lines = createInterface({ input, crlfDelay: Infinity });\n try {\n for await (const line of lines) yield line;\n } finally {\n lines.close();\n }\n } finally {\n await file.close();\n }\n}\n\nexport async function readMemoryActionEventRowsFromLines(\n lines: AsyncIterable<string>,\n limit: number,\n): Promise<Array<{ line: number; event: MemoryActionEvent }>> {\n const out: Array<{ line: number; event: MemoryActionEvent }> = [];\n let writeIndex = 0;\n let lineNumber = 0;\n for await (const row of lines) {\n lineNumber += 1;\n const line = row.trim();\n if (!line) continue;\n try {\n const parsed = JSON.parse(line) as Partial<MemoryActionEvent> & { recordKind?: unknown };\n // Ledger discriminated union (#2347): any row carrying a `recordKind`\n // belongs to another record family (e.g. context_transform) and must\n // be ignored here — the legacy parser stays strict for its own kind.\n if (parsed.recordKind !== undefined) continue;\n const outcome = parsed.outcome === \"applied\" || parsed.outcome === \"skipped\" || parsed.outcome === \"failed\"\n ? parsed.outcome\n : null;\n if (\n typeof parsed.timestamp === \"string\" &&\n typeof parsed.action === \"string\" &&\n outcome !== null\n ) {\n const entry = {\n line: lineNumber,\n event: { ...parsed, outcome } as MemoryActionEvent,\n };\n if (out.length < limit) {\n out.push(entry);\n } else {\n out[writeIndex] = entry;\n writeIndex = (writeIndex + 1) % limit;\n }\n }\n } catch {\n // Ignore malformed rows (fail-open).\n }\n }\n return writeIndex === 0 ? out : [...out.slice(writeIndex), ...out.slice(0, writeIndex)];\n}\n\n/**\n * Tail read for context-transform telemetry rows (#2347). Selects ONLY\n * records discriminated by `recordKind: \"context_transform\"` — the sibling\n * of `readMemoryActionEventRowsFromLines`, with the same O(limit) ring\n * buffer and line-number semantics. Malformed rows are skipped fail-open;\n * legacy action rows are never returned here.\n */\nexport async function readContextTransformRecordRowsFromLines(\n lines: AsyncIterable<string>,\n limit: number,\n): Promise<Array<{ line: number; record: ContextTransformTelemetryRecord }>> {\n const out: Array<{ line: number; record: ContextTransformTelemetryRecord }> = [];\n let writeIndex = 0;\n let lineNumber = 0;\n for await (const row of lines) {\n lineNumber += 1;\n const line = row.trim();\n if (!line) continue;\n try {\n const parsed = JSON.parse(line) as Partial<ContextTransformTelemetryRecord>;\n if (\n parsed.recordKind === \"context_transform\" &&\n typeof parsed.timestamp === \"string\" &&\n typeof parsed.actionId === \"string\" &&\n typeof parsed.planHash === \"string\"\n ) {\n const entry = {\n line: lineNumber,\n record: parsed as ContextTransformTelemetryRecord,\n };\n if (out.length < limit) {\n out.push(entry);\n } else {\n out[writeIndex] = entry;\n writeIndex = (writeIndex + 1) % limit;\n }\n }\n } catch {\n // Ignore malformed rows (fail-open).\n }\n }\n return writeIndex === 0 ? out : [...out.slice(writeIndex), ...out.slice(0, writeIndex)];\n}\n\n/**\n * Validate that a parsed row carries every required lifecycle-event field.\n * Shared by the tail reader and the per-memory reader so both apply the EXACT\n * same fail-open guard as `readAllLifecycleEventsFromLedger` (`eventType` is any\n * string). Governance reads via `readMemoryLifecycleEvents(MAX_SAFE_INTEGER)`\n * must be byte-for-byte identical to `readAllMemoryLifecycleEvents`, so this\n * MUST NOT restrict `eventType` to a handled allow-list — an unknown type is\n * still admitted here and sorted deterministically by `lifecycleEventSortRank`\n * (issue #1910).\n */\nfunction isValidLifecycleEventRow(\n parsed: Partial<MemoryLifecycleEvent>,\n): parsed is MemoryLifecycleEvent {\n return (\n typeof parsed.eventId === \"string\" &&\n typeof parsed.memoryId === \"string\" &&\n typeof parsed.eventType === \"string\" &&\n typeof parsed.timestamp === \"string\" &&\n typeof parsed.actor === \"string\" &&\n typeof parsed.ruleVersion === \"string\"\n );\n}\n\n/**\n * Bounded min-heap that retains the `limit` rows that rank highest under\n * `compare`, breaking ties by append order (later rows win). Heap use is\n * O(limit); each row costs O(log limit). Used for the per-memory timeline\n * fallback, which must keep the last `limit` events in canonical\n * timestamp/event order — not merely the last `limit` appended rows.\n */\nclass BoundedLifecycleTopN {\n private readonly heap: Array<{ event: MemoryLifecycleEvent; seq: number }> = [];\n\n constructor(\n private readonly limit: number,\n private readonly compare: (a: MemoryLifecycleEvent, b: MemoryLifecycleEvent) => number,\n ) {}\n\n private less(\n a: { event: MemoryLifecycleEvent; seq: number },\n b: { event: MemoryLifecycleEvent; seq: number },\n ): boolean {\n const c = this.compare(a.event, b.event);\n return c !== 0 ? c < 0 : a.seq < b.seq;\n }\n\n add(event: MemoryLifecycleEvent, seq: number): void {\n const item = { event, seq };\n if (this.heap.length < this.limit) {\n this.heap.push(item);\n this.siftUp(this.heap.length - 1);\n } else if (this.heap.length > 0 && this.less(this.heap[0], item)) {\n this.heap[0] = item;\n this.siftDown(0);\n }\n }\n\n /** Kept rows in ascending canonical order (append order breaks ties). */\n drainSorted(): MemoryLifecycleEvent[] {\n return this.heap\n .slice()\n .sort((a, b) => (this.less(a, b) ? -1 : this.less(b, a) ? 1 : 0))\n .map((item) => item.event);\n }\n\n private siftUp(index: number): void {\n let i = index;\n while (i > 0) {\n const parent = (i - 1) >> 1;\n if (!this.less(this.heap[i], this.heap[parent])) break;\n [this.heap[i], this.heap[parent]] = [this.heap[parent], this.heap[i]];\n i = parent;\n }\n }\n\n private siftDown(index: number): void {\n let i = index;\n const n = this.heap.length;\n for (;;) {\n const left = 2 * i + 1;\n const right = 2 * i + 2;\n let smallest = i;\n if (left < n && this.less(this.heap[left], this.heap[smallest])) smallest = left;\n if (right < n && this.less(this.heap[right], this.heap[smallest])) smallest = right;\n if (smallest === i) break;\n [this.heap[i], this.heap[smallest]] = [this.heap[smallest], this.heap[i]];\n i = smallest;\n }\n }\n}\n\n/**\n * Bounded tail read for lifecycle-event rows, mirroring\n * `readMemoryActionEventRowsFromLines`: heap use is O(limit) rather than\n * O(rows), no matter how large the ledger is. When `memoryId` is supplied,\n * only rows for that memory are considered, so the per-memory timeline\n * fallback never materializes the whole ledger either.\n *\n * Without `compare`, the retained rows are the last `limit` *appended* rows\n * (returned oldest→newest of that tail); callers apply\n * `sortMemoryLifecycleEvents` for canonical ordering. With `compare`, the\n * retained rows are the `limit` rows that rank highest under `compare` (ties\n * broken by append order), returned in ascending `compare` order — preserving\n * the prior \"filter → canonical sort → last N\" semantics without loading the\n * whole file.\n */\nexport async function readMemoryLifecycleEventsFromLines(\n lines: AsyncIterable<string>,\n limit: number,\n memoryId?: string,\n compare?: (a: MemoryLifecycleEvent, b: MemoryLifecycleEvent) => number,\n onEvent?: (event: MemoryLifecycleEvent) => void,\n): Promise<MemoryLifecycleEvent[]> {\n if (limit <= 0) return [];\n const top = compare ? new BoundedLifecycleTopN(limit, compare) : null;\n const ring: MemoryLifecycleEvent[] = [];\n let writeIndex = 0;\n let seq = 0;\n for await (const row of lines) {\n const line = row.trim();\n if (!line) continue;\n try {\n const parsed = JSON.parse(line) as Partial<MemoryLifecycleEvent>;\n if (!isValidLifecycleEventRow(parsed)) continue;\n onEvent?.(parsed);\n if (memoryId !== undefined && parsed.memoryId !== memoryId) continue;\n if (top) {\n top.add(parsed, seq++);\n } else if (ring.length < limit) {\n ring.push(parsed);\n } else {\n ring[writeIndex] = parsed;\n writeIndex = (writeIndex + 1) % limit;\n }\n } catch {\n // Ignore malformed rows (fail-open).\n }\n }\n if (top) return top.drainSorted();\n return writeIndex === 0 ? ring : [...ring.slice(writeIndex), ...ring.slice(0, writeIndex)];\n}\n","import { SecureStoreLockedError } from \"../secure-store/secure-fs.js\";\nimport { isErrnoCode } from \"../utils/errno.js\";\nimport { displayErrorDetail } from \"../runtime/better-sqlite.js\";\nimport { lstat, rename, stat, unlink } from \"node:fs/promises\";\nimport { randomUUID } from \"node:crypto\";\nimport path from \"node:path\";\nimport type { MemoryLifecycleEvent } from \"../types.js\";\nimport {\n compareMemoryLifecycleEvents,\n sortMemoryLifecycleEvents,\n memoryLifecycleLedgerLockPath,\n MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,\n MEMORY_LIFECYCLE_LEDGER_APPEND_LOCK_MAX_WAIT_MS,\n} from \"../memory-lifecycle-ledger-utils.js\";\nimport { withHeldFileLock, type HeldFileLockOptions } from \"../utils/serialize-mutations.js\";\nimport { ensureContainedSpillDir, listContainedSpillFiles } from \"../utils/path-containment.js\";\nimport {\n readMaybeEncryptedLines,\n readMemoryLifecycleEventsFromLines,\n STATE_FILE_MAX_DECRYPT_BYTES,\n} from \"./secure-line-reader.js\";\nimport { getMemoryProjectionPath } from \"../memory-projection-store.js\";\nimport {\n openProjectionLifecycleLedgerLagTracker,\n type ProjectionLifecycleLedgerLagTracker,\n} from \"../maintenance/projection-support.js\";\nimport {\n type ProjectionLedgerLagTelemetry,\n warnProjectionFallback,\n} from \"../storage-guards.js\";\n\n/** Reads a lifecycle-ledger file through the secure whole-file/plaintext line source. */\nexport type LedgerSecureReader = (filePath: string) => Promise<string>;\n\n/**\n * Lifecycle-ledger read access, extracted from storage.ts (issues #1910,\n * #1995) so the god-file line-count ratchet does not grow. Behavior is\n * unchanged: both readers stream `state/memory-lifecycle-ledger.jsonl` through\n * the same secure whole-file-or-plaintext line source, are fail-open on\n * malformed rows, return `[]` on an absent ledger (ENOENT), and rethrow when a\n * required secure store is locked.\n */\n\n/** Reads a lifecycle-ledger file as a raw (possibly still-encrypted-on-disk)\n * buffer, decrypting through the live secure key when present. */\nexport type LedgerSecureBufferReader = (filePath: string) => Promise<Buffer>;\n\n/**\n * Parse + canonically sort lifecycle rows from a line source. Permissive\n * validation (any `eventType` string is admitted) — matches the historical\n * `readAllMemoryLifecycleEvents` contract that projection rebuild depends on.\n * Fail-open on malformed rows.\n */\nasync function collectLifecycleEvents(\n lines: AsyncIterable<string>,\n): Promise<MemoryLifecycleEvent[]> {\n const out: MemoryLifecycleEvent[] = [];\n for await (const line of lines) {\n const row = line.trim();\n if (!row) continue;\n try {\n const parsed = JSON.parse(row) as Partial<MemoryLifecycleEvent>;\n if (\n typeof parsed.eventId === \"string\" &&\n typeof parsed.memoryId === \"string\" &&\n typeof parsed.eventType === \"string\" &&\n typeof parsed.timestamp === \"string\" &&\n typeof parsed.actor === \"string\" &&\n typeof parsed.ruleVersion === \"string\"\n ) {\n out.push(parsed as MemoryLifecycleEvent);\n }\n } catch {\n // Ignore malformed rows (fail-open).\n }\n }\n return sortMemoryLifecycleEvents(out);\n}\n\n/**\n * Max bytes of a single ledger row we will decode to a V8 string. A malformed\n * or truncated row with no newline can span most of an oversized buffer;\n * decoding it whole with `buf.toString` could exceed V8's ~512MB string cap and\n * THROW before the fail-open JSON.parse in {@link collectLifecycleEvents} can\n * skip it, aborting a compaction that could otherwise rewrite the ledger from\n * its remaining good rows (#2033). Comfortably above any real fixed-schema\n * lifecycle row, far below the string cap, so a legitimate row is never dropped.\n */\nconst LEDGER_ROW_MAX_DECODE_BYTES = 64 * 1024 * 1024;\n\n/**\n * Yield ledger lines from a whole-file buffer WITHOUT ever materializing the\n * entire decrypted body as one V8 string. A decrypted Buffer can hold ~4GB\n * where a string tops out near 512MB, so this is the read compaction uses to\n * shrink an oversize encrypted ledger — the exact file the string-capped\n * `readMaybeEncryptedLines` path refuses (issue #1910, #2033 Cursor High).\n * `Buffer.indexOf` scans for the 0x0A newline natively. A single oversized row\n * with no newline (a truncated write or garbled decrypt output) is SKIPPED\n * undecoded rather than passed to `toString`, so it can never exceed the string\n * cap and abort the read; the fail-open reader drops it anyway (#2033).\n */\nasync function* linesFromBuffer(\n readBuffer: () => Promise<Buffer>,\n): AsyncGenerator<string> {\n const buf = await readBuffer();\n let start = 0;\n let nl = buf.indexOf(0x0a, start);\n while (nl !== -1) {\n if (nl - start <= LEDGER_ROW_MAX_DECODE_BYTES) yield buf.toString(\"utf8\", start, nl);\n start = nl + 1;\n nl = buf.indexOf(0x0a, start);\n }\n if (start < buf.length && buf.length - start <= LEDGER_ROW_MAX_DECODE_BYTES) {\n yield buf.toString(\"utf8\", start, buf.length);\n }\n}\n\n/**\n * Every valid ledger row in canonical order, read through the string-capped\n * secure line source (refuses an encrypted body over the whole-file decrypt\n * limit). General readers use this; compaction uses the uncapped buffer variant.\n */\nexport async function readAllLifecycleEventsFromLedger(\n ledgerPath: string,\n readSecureFile: LedgerSecureReader,\n): Promise<MemoryLifecycleEvent[]> {\n try {\n return await collectLifecycleEvents(\n readMaybeEncryptedLines(\n ledgerPath,\n () => readSecureFile(ledgerPath),\n STATE_FILE_MAX_DECRYPT_BYTES,\n ),\n );\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n return [];\n }\n}\n\n/**\n * Compaction-only variant of {@link readAllLifecycleEventsFromLedger} that reads\n * the ledger through a decrypted BUFFER instead of the string-capped whole-file\n * path. This is what lets background compaction shrink an oversize encrypted\n * ledger: the string cap (`STATE_FILE_MAX_DECRYPT_BYTES`) that points general\n * readers at the compaction remedy would otherwise also block the remedy itself\n * (issue #1910, #2033 Cursor High). Same permissive validation, canonical sort,\n * fail-open-on-malformed, and ENOENT→[] / locked-store-rethrow contract.\n */\nexport async function readAllLifecycleEventsFromLedgerBuffer(\n ledgerPath: string,\n readSecureBuffer: LedgerSecureBufferReader,\n): Promise<MemoryLifecycleEvent[]> {\n try {\n return await collectLifecycleEvents(linesFromBuffer(() => readSecureBuffer(ledgerPath)));\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n return [];\n }\n}\n\n/**\n * Bounded tail read: retains at most `limit` rows via a streaming min-heap so\n * the whole ledger is never materialized. Rows are always ranked by the\n * canonical comparator, so the result is the last `limit` events in canonical\n * (memoryId, timestamp, eventType) order — byte-for-byte the prior `readAll →\n * sort → slice(-limit)`, whether or not `memoryId` is supplied. Governance\n * passes `MAX_SAFE_INTEGER`, so the heap keeps every row and equals\n * `readAllMemoryLifecycleEvents` (issue #1910; CodeRabbit: keep the no-memoryId\n * read on the canonical tail). With `memoryId` only that memory's rows are\n * considered, so the per-memory timeline fallback never materializes the whole\n * ledger either.\n */\nexport async function readBoundedLifecycleEventsFromLedger(\n ledgerPath: string,\n readSecureFile: LedgerSecureReader,\n limit: number,\n memoryId?: string,\n): Promise<MemoryLifecycleEvent[]> {\n const cappedLimit = Math.max(0, Math.floor(limit));\n if (cappedLimit === 0 || Number.isNaN(cappedLimit)) return [];\n try {\n return await readMemoryLifecycleEventsFromLines(\n readMaybeEncryptedLines(\n ledgerPath,\n () => readSecureFile(ledgerPath),\n STATE_FILE_MAX_DECRYPT_BYTES,\n ),\n cappedLimit,\n memoryId,\n compareMemoryLifecycleEvents,\n );\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n return [];\n }\n}\n\nexport interface LifecycleLedgerProjectionLagRead {\n events: MemoryLifecycleEvent[];\n currentEventCount: number;\n deltaEvents: number;\n telemetryAvailable: boolean;\n}\n\nexport async function readBoundedLifecycleEventsWithProjectionLag(\n ledgerPath: string,\n readSecureFile: LedgerSecureReader,\n limit: number,\n memoryId: string,\n tracker: ProjectionLifecycleLedgerLagTracker,\n): Promise<LifecycleLedgerProjectionLagRead> {\n let currentEventCount = 0;\n let deltaEvents = 0;\n let telemetryAvailable = true;\n try {\n const events = await readMemoryLifecycleEventsFromLines(\n readMaybeEncryptedLines(\n ledgerPath,\n () => readSecureFile(ledgerPath),\n STATE_FILE_MAX_DECRYPT_BYTES,\n ),\n Math.max(0, Math.floor(limit)),\n memoryId,\n compareMemoryLifecycleEvents,\n (event) => {\n if (!telemetryAvailable) return;\n try {\n const tracked = tracker.record(event);\n if (!tracked.unique) return;\n currentEventCount += 1;\n if (!tracked.projected) deltaEvents += 1;\n } catch {\n telemetryAvailable = false;\n currentEventCount = 0;\n deltaEvents = 0;\n }\n },\n );\n return { events, currentEventCount, deltaEvents, telemetryAvailable };\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n return { events: [], currentEventCount: 0, deltaEvents: 0, telemetryAvailable: false };\n }\n}\n/**\n * Probe filesystem identity stamps (dev:ino:size:mtimeMs:ctimeMs) for the\n * projection database and lifecycle-ledger file. Returns `null` when either\n * file is missing or unstatable so caller can disable the lag cache without\n * throwing on transient I/O or permission errors (#2119 / review).\n */\nexport async function probeProjectionLedgerIdentities(\n projectionPath: string,\n ledgerPath: string,\n): Promise<{ projectionIdentity: string; ledgerIdentity: string } | null> {\n try {\n const [projectionIdentity, ledgerIdentity] = await Promise.all(\n [projectionPath, ledgerPath].map(async (filePath) => {\n try {\n const file = await lstat(filePath);\n return `${file.dev}:${file.ino}:${file.size}:${file.mtimeMs}:${file.ctimeMs}`;\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return \"absent\";\n // Probe failure: disable lag cache, do not block the primary timeline read (#2119 review).\n return null;\n }\n }),\n );\n if (!projectionIdentity || !ledgerIdentity) return null;\n return { projectionIdentity, ledgerIdentity };\n } catch {\n return null;\n }\n}\n\nexport interface ProjectionLedgerLagScan {\n telemetry: ProjectionLedgerLagTelemetry | null;\n events: MemoryLifecycleEvent[];\n memoryId: string;\n limit: number;\n}\n\nexport class ProjectionLedgerLagManager {\n private lagCache: {\n generation: string;\n telemetry: ProjectionLedgerLagTelemetry;\n } | null = null;\n private lagInFlight: {\n generation: string;\n scan: Promise<ProjectionLedgerLagScan>;\n } | null = null;\n\n async resolveTimelineWithLag(options: {\n baseDir: string;\n ledgerPath: string;\n memoryId: string;\n cappedLimit: number;\n readSecureFile: LedgerSecureReader;\n projectionAge: () => string;\n }): Promise<MemoryLifecycleEvent[]> {\n const { baseDir, ledgerPath, memoryId, cappedLimit, readSecureFile, projectionAge } = options;\n const projectionPath = getMemoryProjectionPath(baseDir);\n const identities = await probeProjectionLedgerIdentities(projectionPath, ledgerPath);\n\n if (!identities) {\n warnProjectionFallback(baseDir, \"getMemoryTimeline\", projectionAge);\n return readBoundedLifecycleEventsFromLedger(ledgerPath, readSecureFile, cappedLimit, memoryId);\n }\n\n const { projectionIdentity, ledgerIdentity } = identities;\n const generation = `${projectionIdentity}\\0${ledgerIdentity}`;\n\n const cachedLag = this.lagCache?.generation === generation\n ? this.lagCache.telemetry\n : null;\n if (cachedLag) {\n warnProjectionFallback(baseDir, \"getMemoryTimeline\", projectionAge, cachedLag);\n return readBoundedLifecycleEventsFromLedger(ledgerPath, readSecureFile, cappedLimit, memoryId);\n }\n\n const inFlight = this.lagInFlight?.generation === generation\n ? this.lagInFlight.scan\n : null;\n if (inFlight) {\n const result = await inFlight;\n if (result.telemetry) {\n this.lagCache = { generation, telemetry: result.telemetry };\n }\n warnProjectionFallback(baseDir, \"getMemoryTimeline\", projectionAge, result.telemetry ?? undefined);\n if (result.memoryId === memoryId && result.limit === cappedLimit) return result.events;\n return readBoundedLifecycleEventsFromLedger(ledgerPath, readSecureFile, cappedLimit, memoryId);\n }\n\n const tracker = openProjectionLifecycleLedgerLagTracker(baseDir);\n if (tracker) {\n const highWater = tracker.highWater;\n const scan = (async (): Promise<ProjectionLedgerLagScan> => {\n try {\n const fallback = await readBoundedLifecycleEventsWithProjectionLag(\n ledgerPath,\n readSecureFile,\n cappedLimit,\n memoryId,\n tracker,\n );\n return {\n telemetry: fallback.telemetryAvailable\n ? {\n projectedEvents: highWater.eventCount,\n currentLedgerEvents: fallback.currentEventCount,\n deltaEvents: fallback.deltaEvents,\n }\n : null,\n events: fallback.events,\n memoryId,\n limit: cappedLimit,\n };\n } finally {\n try {\n tracker.close();\n } catch {\n // Lag telemetry cleanup must not replace a successful ledger fallback.\n }\n }\n })();\n this.lagInFlight = { generation, scan };\n try {\n const result = await scan;\n if (result.telemetry) {\n this.lagCache = { generation, telemetry: result.telemetry };\n }\n warnProjectionFallback(baseDir, \"getMemoryTimeline\", projectionAge, result.telemetry ?? undefined);\n return result.events;\n } finally {\n if (this.lagInFlight?.scan === scan) {\n this.lagInFlight = null;\n }\n }\n }\n\n warnProjectionFallback(baseDir, \"getMemoryTimeline\", projectionAge);\n return readBoundedLifecycleEventsFromLedger(ledgerPath, readSecureFile, cappedLimit, memoryId);\n }\n}\n\n/**\n * Directory holding the durable pending-append spill for a lifecycle ledger\n * (#2033). When an append cannot acquire the ledger lock within its budget —\n * because a long compaction/rebuild rewrite legitimately holds it — the event\n * is written as its OWN immutable file here instead of being dropped fail-open,\n * then folded back into the ledger by the next lock holder (a later append or\n * the maintenance drain).\n *\n * A per-event file (not a single appended file) is deliberate: each spill is\n * encrypted at its own path so the path-bound AAD stays valid, and the drainer\n * only ever deletes files it has already read — a spill that lands mid-drain is\n * simply a new file picked up on the next pass, so nothing is clobbered or lost.\n */\nexport function pendingLifecycleLedgerDir(ledgerPath: string): string {\n return `${ledgerPath}.pending.d`;\n}\n\n/**\n * Secure IO the pending spill needs. `writeSecure`/`readSecure` mirror the\n * ledger's own secure write/read so each spill file is encrypted at rest exactly\n * like the ledger it backs (each at its own path-bound AAD).\n *\n * `writeSecure` MUST be ATOMIC (#2033): it writes the payload to a temp file in\n * the SAME directory and then renames it onto `filePath`, so a concurrent lock\n * holder draining the pending dir never lists or reads a half-written spill (the\n * exact partial-fold the drain's `*.jsonl`-only lister must never see). The\n * temp+rename is bound to the FINAL path because the ciphertext's AAD is the\n * final path — an outer rename at the spill layer would leave the bytes\n * undecryptable, so the atomic step lives here in `writeSecure`. The production\n * wiring (`writeMaybeEncryptedFile`) already renames its temp onto `filePath`,\n * naming that temp `<final>.tmp-…` (never `*.jsonl`), so the drain skips it.\n */\nexport interface LifecyclePendingIo {\n writeSecure: (filePath: string, payload: string) => Promise<void>;\n readSecure: (filePath: string) => Promise<string>;\n}\n\nfunction withTrailingNewline(content: string): string {\n return content.length === 0 || content.endsWith(\"\\n\") ? content : `${content}\\n`;\n}\n\n/**\n * Serialize lifecycle events into the ledger's newline-delimited JSON payload,\n * stamping a fallback timestamp on any event that lacks one. Extracted from\n * storage.ts (issue #1995 file-size ratchet); behavior unchanged.\n */\nexport function serializeLifecycleAppendPayload(events: MemoryLifecycleEvent[]): string {\n const nowIso = new Date().toISOString();\n return events\n .map((event) => {\n const normalized: MemoryLifecycleEvent = {\n ...event,\n timestamp: event.timestamp && event.timestamp.length > 0 ? event.timestamp : nowIso,\n };\n return `${JSON.stringify(normalized)}\\n`;\n })\n .join(\"\");\n}\n\n/**\n * Write one spill file (a fresh, uniquely-named, immutable per-append file).\n * The write goes to the FINAL `<uuid>.jsonl` path through {@link LifecyclePendingIo}\n * `writeSecure`, whose atomic temp+rename (bound to that final path, since the\n * ciphertext's AAD is the final path) guarantees a concurrent lock holder's\n * drain never lists or folds a half-written spill (#2033).\n */\nasync function spillPendingAppend(\n ledgerPath: string,\n io: LifecyclePendingIo,\n payload: string,\n): Promise<void> {\n const dir = pendingLifecycleLedgerDir(ledgerPath);\n await ensureContainedSpillDir(dir);\n const finalPath = path.join(dir, `${randomUUID()}.jsonl`);\n await io.writeSecure(finalPath, payload);\n}\n\n/** Suffix marking a spill that has been CLAIMED for commit but not yet deleted. */\nconst CLAIMED_SPILL_SUFFIX = \".claimed\";\n\n/**\n * Recover claims a crashed drain left mid-flight (#2033). A crash-safe drain\n * renames `*.jsonl` → `*.jsonl.claimed` BEFORE committing (see\n * {@link claimSpillBatch}); if the process dies between that rename and the\n * ledger write, the durable `.claimed` file is the ONLY copy of those rows. This\n * renames every orphaned `*.jsonl.claimed` back to `*.jsonl` so it re-enters the\n * normal claim+commit flow — nothing a crash left behind is lost. Reads only\n * ever happen at the restored `.jsonl` path, so the path-bound AAD of an\n * encrypted spill stays valid. A file that vanished or cannot be renamed is left\n * for a later pass. MUST run under the held ledger lock, before draining.\n */\nasync function recoverOrphanedClaims(ledgerPath: string): Promise<void> {\n const claimed = await listContainedSpillFiles(\n pendingLifecycleLedgerDir(ledgerPath),\n `.jsonl${CLAIMED_SPILL_SUFFIX}`,\n );\n for (const claimedPath of claimed) {\n const original = claimedPath.slice(0, -CLAIMED_SPILL_SUFFIX.length);\n await rename(claimedPath, original).catch(() => undefined);\n }\n}\n\n/** Max bytes of pending-spill content folded into one append (#2033). The drain\n * reads and concatenates at most this many bytes of spill content per batch, so\n * a large pending queue folds in bounded segments instead of one giant string:\n * the secure-store append decrypts the active ledger and concatenates the\n * payload as a V8 string, and a single unbounded fold could throw before\n * draining or recreate an encrypted active ledger over the whole-file decrypt\n * cap, stranding the rows in the excluded pending queue. */\nconst PENDING_SPILL_BATCH_MAX_BYTES = 1024 * 1024;\n\n/**\n * Claim ONE bounded batch of spills for commit via a CRASH-SAFE rename (#2033).\n * Content is read LAZILY here — at each spill's original (AAD-bound) path, so an\n * encrypted spill still decrypts — and at most `PENDING_SPILL_BATCH_MAX_BYTES`\n * (plus one spill) is held in memory or concatenated per call, bounding both the\n * fold's memory and the payload handed to a single append. Each spill is read,\n * then atomically renamed `*.jsonl` → `*.jsonl.claimed` BEFORE its rows are\n * committed: a crash between the claim and the commit leaves the rows on disk\n * (recovered by {@link recoverOrphanedClaims}) instead of losing them. A read\n * failure propagates with the file untouched (not yet claimed), leaving it for a\n * later retry; a rename that fails skips that spill this pass. Returns the batch\n * payload, its claimed paths, and the next input index. A lone spill larger than\n * the batch limit is claimed alone so the drain always makes progress.\n */\nasync function claimSpillBatch(\n files: string[],\n startIndex: number,\n io: LifecyclePendingIo,\n): Promise<{\n payload: string;\n claimedPaths: string[];\n nextIndex: number;\n}> {\n const parts: string[] = [];\n const claimedPaths: string[] = [];\n let payloadBytes = 0;\n let nextIndex = startIndex;\n for (; nextIndex < files.length; nextIndex++) {\n const filePath = files[nextIndex]!;\n // Read at the ORIGINAL (AAD-bound) path BEFORE claiming. A read failure\n // propagates with the file untouched, so it stays for a later retry.\n const content = withTrailingNewline(await io.readSecure(filePath));\n const spillBytes = Buffer.byteLength(content, \"utf8\");\n // Stop before a spill that would overflow a non-empty batch so peak memory\n // and the single-append payload stay bounded; it starts the next batch.\n if (parts.length > 0 && payloadBytes + spillBytes > PENDING_SPILL_BATCH_MAX_BYTES) {\n break;\n }\n const claimedPath = `${filePath}${CLAIMED_SPILL_SUFFIX}`;\n try {\n await rename(filePath, claimedPath);\n } catch {\n continue; // could not claim → do not commit; a later drain retries it.\n }\n parts.push(content);\n claimedPaths.push(claimedPath);\n payloadBytes += spillBytes;\n }\n return { payload: parts.join(\"\"), claimedPaths, nextIndex };\n}\n\n/** Delete claimed spill files after their rows are durably committed. A delete\n * that fails leaves an orphan the next drain recovers and re-commits — a\n * duplicate the eventId-deduping rebuild collapses, never a lost row (#2033). */\nasync function finalizeClaimedSpills(claimedPaths: string[]): Promise<void> {\n for (const claimedPath of claimedPaths) {\n await unlink(claimedPath).catch(() => undefined);\n }\n}\n\n/** Roll a failed commit's claims back to unclaimed `*.jsonl` spills so they are\n * retried as normal spills (#2033). Best-effort: an un-renamable claim is\n * instead recovered by the next drain's orphan sweep. */\nasync function rollbackClaimedSpills(claimedPaths: string[]): Promise<void> {\n for (const claimedPath of claimedPaths) {\n const original = claimedPath.slice(0, -CLAIMED_SPILL_SUFFIX.length);\n await rename(claimedPath, original).catch(() => undefined);\n }\n}\n\n/**\n * Under the held ledger lock, fold durable pending spills into the ledger in\n * bounded batches together with `extraPayload` (a new event's rows, or \"\" for a\n * drain-only pass). Recover orphaned claims first, then repeatedly claim ONE\n * bounded batch ({@link claimSpillBatch}) — reading its content lazily — COMMIT\n * the claimed rows, and FINALIZE by deleting the claimed files. A commit failure\n * rolls the current batch's claims back to unclaimed spills and rethrows, so a\n * failed write neither loses nor double-commits rows; batches already committed\n * stay durable (append-only, eventId-deduped on rebuild). Returns true when\n * spill rows were committed.\n */\nasync function foldPendingSpillsIntoAppend(\n ledgerPath: string,\n append: (payload: string) => Promise<void>,\n extraPayload: string,\n pending: LifecyclePendingIo | undefined,\n): Promise<boolean> {\n if (!pending) {\n if (extraPayload.length > 0) await append(extraPayload);\n return false;\n }\n await recoverOrphanedClaims(ledgerPath);\n // listContainedSpillFiles rejects a symlinked pending dir and skips any\n // symlinked/escaping entry BEFORE we secure-read or later unlink it (#2033),\n // so a poisoned link cannot redirect a decrypt/delete outside the spill dir.\n const files = await listContainedSpillFiles(pendingLifecycleLedgerDir(ledgerPath));\n let nextIndex = 0;\n let drained = false;\n\n while (nextIndex < files.length) {\n const batch = await claimSpillBatch(files, nextIndex, pending);\n nextIndex = batch.nextIndex;\n if (batch.claimedPaths.length === 0) {\n if (nextIndex >= files.length) break;\n continue;\n }\n try {\n await append(batch.payload);\n } catch (err) {\n await rollbackClaimedSpills(batch.claimedPaths);\n throw err;\n }\n await finalizeClaimedSpills(batch.claimedPaths);\n drained = true;\n }\n\n if (extraPayload.length > 0) await append(extraPayload);\n return drained;\n}\n\n/**\n * Append `payload` to the lifecycle ledger under the cross-process ledger lock\n * so it is serialized against compaction's whole-file rewrite (issue #1910):\n * both hold this lock, so an append during a rewrite waits and lands on the\n * compacted ledger instead of being clobbered by the atomic rename.\n *\n * The acquisition budget defaults to MEMORY_LIFECYCLE_LEDGER_APPEND_LOCK_MAX_WAIT_MS\n * (twice the stale window), NOT withHeldFileLock's 5s default: a compaction\n * rewrite of a large ledger can legitimately hold the lock past 5s, and giving\n * up there would surface acquired=false. With this budget a normal append waits\n * out the compaction — or, if the holder crashed, past the stale-break window so\n * it still acquires.\n *\n * When the budget is nonetheless exhausted (a rewrite of a very large ledger\n * holds the lock past even this window), a configured `pending` queue makes the\n * append DURABLE instead of dropping it fail-open (#2033): the event is spilled\n * to an encrypted per-event file and folded back into the ledger by the next\n * lock holder, guaranteeing eventual append. Without a pending queue the old\n * behavior stands — REFUSE to append unlocked rather than let a rewrite clobber\n * the row. `lockOptions` lets tests shrink the budget to exercise both branches.\n */\nexport async function appendLifecycleEventsSerialized(\n ledgerPath: string,\n append: (payload: string) => Promise<void>,\n payload: string,\n pending?: LifecyclePendingIo,\n lockOptions?: Pick<HeldFileLockOptions, \"maxWaitMs\" | \"pollMs\">,\n): Promise<void> {\n await withHeldFileLock(\n memoryLifecycleLedgerLockPath(ledgerPath),\n {\n staleMs: MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,\n maxWaitMs: MEMORY_LIFECYCLE_LEDGER_APPEND_LOCK_MAX_WAIT_MS,\n ...lockOptions,\n },\n async (acquired) => {\n if (!acquired) {\n if (!pending) {\n throw new Error(\n \"memory-lifecycle-ledger append aborted: could not acquire the ledger lock within \"\n + \"the budget and no durable pending queue is configured; refusing to append unlocked \"\n + \"so a concurrent compaction rewrite cannot clobber the new event (issue #1910).\",\n );\n }\n await spillPendingAppend(ledgerPath, pending, payload);\n return;\n }\n await foldPendingSpillsIntoAppend(ledgerPath, append, payload, pending);\n },\n );\n}\n\n/**\n * Drain the durable pending spills into the ledger under the ledger lock WITHOUT\n * appending a new event (#2033). Maintenance calls this so events that spilled\n * while a long compaction held the lock are eventually written even when no\n * further append arrives. A non-acquired lock is a no-op (retried next pass).\n * Uses the crash-safe claim/commit protocol ({@link foldPendingSpillsIntoAppend}):\n * spills are claimed by rename before the write and deleted only after it, an\n * orphaned claim from an earlier crash is recovered first, and a write failure\n * rolls the claims back — so a process crash mid-drain can never lose a row.\n * Returns true when rows were drained.\n */\nexport async function drainPendingLifecycleAppendsSerialized(\n ledgerPath: string,\n append: (payload: string) => Promise<void>,\n pending: LifecyclePendingIo,\n lockOptions?: Pick<HeldFileLockOptions, \"maxWaitMs\" | \"pollMs\">,\n): Promise<boolean> {\n let drained = false;\n await withHeldFileLock(\n memoryLifecycleLedgerLockPath(ledgerPath),\n {\n staleMs: MEMORY_LIFECYCLE_LEDGER_LOCK_STALE_MS,\n maxWaitMs: MEMORY_LIFECYCLE_LEDGER_APPEND_LOCK_MAX_WAIT_MS,\n ...lockOptions,\n },\n async (acquired) => {\n if (!acquired) return; // lock busy; the next maintenance pass retries.\n drained = await foldPendingSpillsIntoAppend(ledgerPath, append, \"\", pending);\n },\n );\n return drained;\n}\n\n/**\n * Fast-path pending drain for a store (#2033): a no-op that takes NO lock when\n * the pending directory is absent, otherwise ensures the state dir exists and\n * drains under the ledger lock. Keeps StorageManager's public drain method a\n * thin delegate so the bounded-state logic stays in this sibling (issue #1995\n * file-size ratchet). Returns true when rows were drained.\n */\nexport async function drainPendingLifecycleLedgerIfAny(\n ledgerPath: string,\n io: LifecyclePendingIo,\n append: (payload: string) => Promise<void>,\n ensureReady: () => Promise<void>,\n): Promise<boolean> {\n try {\n await stat(pendingLifecycleLedgerDir(ledgerPath));\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return false; // nothing pending — no lock taken.\n throw err;\n }\n await ensureReady();\n return drainPendingLifecycleAppendsSerialized(ledgerPath, append, io);\n}\n\n/** Result of a pre-snapshot lifecycle drain (#2033): `folded` is true when spill\n * rows were committed to the active ledger; `pendingDeferred` is true when\n * durable spill rows STILL remain in the offline-sync-EXCLUDED pending queue\n * after the attempt (the ledger lock was held by a peer, or a spill could not\n * be claimed). A caller MUST NOT report a clean snapshot while `pendingDeferred`\n * is true — those append-only rows would be silently omitted. */\nexport interface DrainPendingLifecycleForSyncResult {\n folded: boolean;\n pendingDeferred: boolean;\n}\n\n/**\n * Offline-sync pre-snapshot drain (#2033). Like {@link drainPendingLifecycleLedgerIfAny}\n * but reports whether durable rows are STILL pending after the attempt so an\n * offline snapshot never silently drops append-only lifecycle rows (promotions,\n * imports, explicit captures) that spilled while the ledger lock was held. Fast\n * no-op — no lock, no dir creation — when nothing is pending. Otherwise drains\n * under the ledger lock, then re-enumerates the pending directory: any remaining\n * live (`*.jsonl`) or crash-orphaned (`*.jsonl.claimed`) spill marks the drain as\n * deferred. A read/append failure inside the lock (locked key, encrypted body)\n * propagates to the caller, which retries or aborts.\n */\nexport async function drainPendingLifecycleLedgerForSync(\n ledgerPath: string,\n io: LifecyclePendingIo,\n append: (payload: string) => Promise<void>,\n ensureReady: () => Promise<void>,\n): Promise<DrainPendingLifecycleForSyncResult> {\n const dir = pendingLifecycleLedgerDir(ledgerPath);\n try {\n await stat(dir);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return { folded: false, pendingDeferred: false };\n throw err;\n }\n await ensureReady();\n const folded = await drainPendingLifecycleAppendsSerialized(ledgerPath, append, io);\n const remaining =\n (await listContainedSpillFiles(dir)).length +\n (await listContainedSpillFiles(dir, `.jsonl${CLAIMED_SPILL_SUFFIX}`)).length;\n return { folded, pendingDeferred: remaining > 0 };\n}\n\n/**\n * Bounded pre-snapshot drain driver (#2033): invoke `drain` up to `maxAttempts`\n * times and return once it reports no pending rows; if durable rows remain\n * deferred (ledger lock held by a peer) or every attempt throws, throw so the\n * offline-sync caller ABORTS rather than building a snapshot that silently omits\n * append-only lifecycle rows. Kept here (not in the access-service god-file, issue\n * #1995) so both snapshot entrypoints share one retry/abort contract.\n */\nexport async function drainPendingLifecycleForSyncOrThrow(\n drain: () => Promise<DrainPendingLifecycleForSyncResult>,\n maxAttempts = 3,\n): Promise<void> {\n let lastError: unknown;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const result = await drain();\n if (!result.pendingDeferred) return;\n lastError = undefined;\n } catch (err) {\n lastError = err;\n }\n }\n const detail = lastError\n ? `: ${displayErrorDetail(lastError) || \"unknown error\"}`\n : \" (ledger lock held by a peer)\";\n throw new Error(\n `offline-sync lifecycle drain could not fold pending memory-lifecycle events after ${maxAttempts} attempts${detail}; aborting snapshot so the pending rows are not silently excluded (#2033)`,\n );\n}\n"],"mappings":"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","names":["lstat","path","lstat","path"]}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  judgeContradictionPairs,
3
3
  resolveScanStorage
4
- } from "./chunk-Q4WONDMJ.js";
4
+ } from "./chunk-YYGZJPOK.js";
5
5
  import {
6
6
  CONTRADICTION_VERBS,
7
7
  PREFERENCE_DRIFT_VERBS,
@@ -10,12 +10,12 @@ import {
10
10
  resolvePair,
11
11
  writePairs
12
12
  } from "./chunk-CTVWELNK.js";
13
- import {
14
- composeMemoryEnvelope
15
- } from "./chunk-RAIUTAZZ.js";
16
13
  import {
17
14
  bumpMemoryCorpusVersionForDir
18
15
  } from "./chunk-XCB6QDL6.js";
16
+ import {
17
+ composeMemoryEnvelope
18
+ } from "./chunk-WKAXBXVA.js";
19
19
  import {
20
20
  readJsonFile,
21
21
  writeJsonFileAtomic
@@ -876,4 +876,4 @@ export {
876
876
  isValidResolutionVerb,
877
877
  executeResolution
878
878
  };
879
- //# sourceMappingURL=chunk-I32NKXE2.js.map
879
+ //# sourceMappingURL=chunk-JTWZKNUH.js.map