@remnic/core 9.69.39 → 9.69.40

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 (639) hide show
  1. package/dist/access-admin-ops-surface.d.ts +16 -14
  2. package/dist/access-admin-ops-surface.js +37 -37
  3. package/dist/access-authorization-probe.d.ts +16 -14
  4. package/dist/access-authorization-probe.js +38 -38
  5. package/dist/access-boundary.d.ts +16 -14
  6. package/dist/access-boundary.js +37 -37
  7. package/dist/access-cli.js +98 -97
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +16 -14
  11. package/dist/access-extraction-force-flush.js +37 -37
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-briefing.d.ts +16 -14
  14. package/dist/access-http-briefing.js +38 -38
  15. package/dist/access-http-lcm-compaction.d.ts +16 -14
  16. package/dist/access-http-lifecycle-flush.d.ts +16 -14
  17. package/dist/access-http-offline-stream.d.ts +16 -14
  18. package/dist/access-http-query.d.ts +2 -2
  19. package/dist/access-http-query.js +39 -39
  20. package/dist/access-http.d.ts +17 -15
  21. package/dist/access-http.js +53 -53
  22. package/dist/access-identity-continuity-surface.d.ts +13 -12
  23. package/dist/access-identity-continuity-surface.js +37 -37
  24. package/dist/access-lcm-surface.d.ts +16 -14
  25. package/dist/access-lcm-surface.js +37 -37
  26. package/dist/access-mcp.d.ts +16 -14
  27. package/dist/access-mcp.js +45 -45
  28. package/dist/access-memory-search-fanout.d.ts +2 -2
  29. package/dist/{access-namespace-preflight-DY4z6L5X.d.ts → access-namespace-preflight-CKBumJ8W.d.ts} +1 -1
  30. package/dist/access-namespace-preflight.d.ts +3 -3
  31. package/dist/access-namespace-preflight.js +37 -37
  32. package/dist/access-observe-transcript.d.ts +13 -12
  33. package/dist/access-observe-write-category.d.ts +1 -1
  34. package/dist/access-observe-write-category.js +2 -2
  35. package/dist/access-observe-write-surface.d.ts +16 -14
  36. package/dist/access-observe-write-surface.js +37 -37
  37. package/dist/access-offline-manifest.d.ts +37 -13
  38. package/dist/access-offline-manifest.js +7 -3
  39. package/dist/access-operations-batch.js +39 -39
  40. package/dist/access-operations.d.ts +16 -14
  41. package/dist/access-operations.js +44 -44
  42. package/dist/access-recall-concurrency.d.ts +16 -14
  43. package/dist/access-recall-concurrency.js +37 -37
  44. package/dist/access-recall-response.d.ts +16 -14
  45. package/dist/access-recall-response.js +37 -37
  46. package/dist/access-recall-surface.d.ts +16 -14
  47. package/dist/access-recall-surface.js +37 -37
  48. package/dist/access-schema.d.ts +5 -3
  49. package/dist/access-schema.js +1 -1
  50. package/dist/{access-service-MY4bsr_Q.d.ts → access-service-DJ3qogNt.d.ts} +8 -8
  51. package/dist/access-service-helpers.d.ts +16 -14
  52. package/dist/access-service.d.ts +16 -14
  53. package/dist/access-service.js +37 -37
  54. package/dist/access-surface-catalog.d.ts +16 -14
  55. package/dist/access-surface-catalog.js +39 -39
  56. package/dist/access-wearables-meetings-surface.d.ts +6 -5
  57. package/dist/action-confidence.d.ts +1 -1
  58. package/dist/active-memory-bridge.d.ts +1 -1
  59. package/dist/active-recall.d.ts +1 -1
  60. package/dist/active-recall.js +6 -5
  61. package/dist/active-recall.js.map +1 -1
  62. package/dist/activity/digest.d.ts +1 -1
  63. package/dist/ambient-provenance.d.ts +1 -1
  64. package/dist/artifact-search.d.ts +1 -1
  65. package/dist/{auto-sync-RP4C6ZPF.js → auto-sync-D6BAPIJV.js} +5 -5
  66. package/dist/background-generation-config.d.ts +1 -1
  67. package/dist/background-generation-config.js +3 -1
  68. package/dist/background-generation.d.ts +1 -1
  69. package/dist/behavior-learner.d.ts +1 -1
  70. package/dist/behavior-signals.d.ts +1 -1
  71. package/dist/bootstrap.d.ts +13 -12
  72. package/dist/briefing-window.d.ts +2 -2
  73. package/dist/briefing.d.ts +2 -2
  74. package/dist/briefing.js +15 -15
  75. package/dist/buffer-surprise-report.d.ts +1 -1
  76. package/dist/buffer-turn-helpers.d.ts +1 -1
  77. package/dist/buffer.d.ts +2 -2
  78. package/dist/buffer.js +5 -5
  79. package/dist/bulk-import/index.d.ts +3 -3
  80. package/dist/calibration.d.ts +3 -2
  81. package/dist/calibration.js +2 -2
  82. package/dist/capabilities.d.ts +1 -1
  83. package/dist/{catalog-CW87xGx8.d.ts → catalog-BHXkBVhg.d.ts} +1 -1
  84. package/dist/causal-behavior.d.ts +1 -1
  85. package/dist/causal-consolidation.d.ts +1 -1
  86. package/dist/causal-consolidation.js +19 -18
  87. package/dist/causal-consolidation.js.map +1 -1
  88. package/dist/causal-trajectory-graph.d.ts +1 -1
  89. package/dist/{chunk-B36GUU6T.js → chunk-23HFXQ5J.js} +36 -3
  90. package/dist/chunk-23HFXQ5J.js.map +1 -0
  91. package/dist/{chunk-YFTNZMGR.js → chunk-27NO2KVB.js} +31 -8
  92. package/dist/chunk-27NO2KVB.js.map +1 -0
  93. package/dist/{chunk-JTQR6L2N.js → chunk-2SKMZUOW.js} +2 -2
  94. package/dist/{chunk-GG5FHZJJ.js → chunk-2SNCQHJZ.js} +2 -2
  95. package/dist/{chunk-O76F5QPP.js → chunk-3QEVOQF5.js} +2 -2
  96. package/dist/{chunk-3N3PBBEH.js → chunk-3XPN7AVY.js} +2 -2
  97. package/dist/{chunk-X4TD4O2F.js → chunk-46Z3VGWF.js} +2 -2
  98. package/dist/{chunk-2ZTDRNCS.js → chunk-4CMXI55L.js} +2 -2
  99. package/dist/{chunk-FWWWUPOE.js → chunk-5LYSEZOF.js} +18 -9
  100. package/dist/chunk-5LYSEZOF.js.map +1 -0
  101. package/dist/{chunk-IQEJIOEU.js → chunk-62HFZNCJ.js} +17 -10
  102. package/dist/chunk-62HFZNCJ.js.map +1 -0
  103. package/dist/{chunk-YKREX63Z.js → chunk-6L2II3KS.js} +5 -3
  104. package/dist/chunk-6L2II3KS.js.map +1 -0
  105. package/dist/{chunk-MUTVRKKY.js → chunk-7D6SER6A.js} +8 -8
  106. package/dist/{chunk-WBM2MVBK.js → chunk-7Z54NXVS.js} +2 -2
  107. package/dist/{chunk-ACY4ZPF7.js → chunk-AEOOGXMQ.js} +10 -5
  108. package/dist/chunk-AEOOGXMQ.js.map +1 -0
  109. package/dist/{chunk-UHRZ324M.js → chunk-BGRTZOJB.js} +3 -3
  110. package/dist/{chunk-ZEGL7YCC.js → chunk-BXIJSPCL.js} +2 -2
  111. package/dist/{chunk-JKKII6GX.js → chunk-BYQX4IOG.js} +2 -2
  112. package/dist/{chunk-WIWLX65T.js → chunk-C5R73BON.js} +2 -2
  113. package/dist/{chunk-BD7JTBYP.js → chunk-D7MAYFQP.js} +2 -2
  114. package/dist/{chunk-TNZNSMVJ.js → chunk-DAZANIYU.js} +249 -295
  115. package/dist/chunk-DAZANIYU.js.map +1 -0
  116. package/dist/{chunk-LMLGBG6H.js → chunk-DFVSJFHK.js} +2 -2
  117. package/dist/{chunk-3NPNBVFR.js → chunk-ES5BUPYB.js} +2 -2
  118. package/dist/{chunk-MVAQ2WM3.js → chunk-G2XZFGYN.js} +6 -2
  119. package/dist/chunk-G2XZFGYN.js.map +1 -0
  120. package/dist/{chunk-TNSCIPBQ.js → chunk-G6NQ3L4T.js} +2 -2
  121. package/dist/{chunk-5N4MZLEH.js → chunk-GO5LOHCD.js} +2 -2
  122. package/dist/{chunk-AECJY3GJ.js → chunk-GSSDHAYH.js} +2 -2
  123. package/dist/{chunk-TSP5WH72.js → chunk-HJUP3K6L.js} +2 -2
  124. package/dist/{chunk-AAZEKXUP.js → chunk-ICNJ6J46.js} +2 -2
  125. package/dist/{chunk-6EHM2AV7.js → chunk-IMBQFHRV.js} +2 -2
  126. package/dist/{chunk-4RZLTZVM.js → chunk-IOPIGX7Y.js} +1 -1
  127. package/dist/{chunk-EYKIDK33.js → chunk-IS2IDFJP.js} +13 -13
  128. package/dist/{chunk-VJIE4D2I.js → chunk-J4WGTN2N.js} +2 -2
  129. package/dist/{chunk-NXGSONWM.js → chunk-J7FVMLBR.js} +2 -2
  130. package/dist/{chunk-VSL63CFJ.js → chunk-JAJIMTFB.js} +6 -6
  131. package/dist/{chunk-4JVQRFZD.js → chunk-JOP7W24J.js} +9 -9
  132. package/dist/{chunk-YUW66UAH.js → chunk-JUDT33RX.js} +2 -2
  133. package/dist/{chunk-QHT7MOUF.js → chunk-K4A6UVPB.js} +22 -11
  134. package/dist/chunk-K4A6UVPB.js.map +1 -0
  135. package/dist/{chunk-D545Z7UH.js → chunk-K4JKAXMO.js} +2 -2
  136. package/dist/{chunk-BV4ZKIZH.js → chunk-K75A5XWU.js} +3 -2
  137. package/dist/{chunk-3CBI2ZSA.js → chunk-KG2OOAFF.js} +20 -12
  138. package/dist/chunk-KG2OOAFF.js.map +1 -0
  139. package/dist/{chunk-M6HBPLBA.js → chunk-KOTG3RXE.js} +2 -2
  140. package/dist/{chunk-CWTCMZGE.js → chunk-KTOXQMW3.js} +119 -3
  141. package/dist/chunk-KTOXQMW3.js.map +1 -0
  142. package/dist/{chunk-OB3XMWX5.js → chunk-KVO2BTA4.js} +2 -2
  143. package/dist/{chunk-GI4ZBWPQ.js → chunk-KY236SP5.js} +3 -3
  144. package/dist/{chunk-4BCHFSC7.js → chunk-LFVZD5EC.js} +3 -3
  145. package/dist/{chunk-O4M4BDIJ.js → chunk-LKFVVN7R.js} +2 -2
  146. package/dist/{chunk-IYKZJVL5.js → chunk-MDIEES23.js} +1 -1
  147. package/dist/chunk-MDIEES23.js.map +1 -0
  148. package/dist/{chunk-4RX5O34R.js → chunk-MJC7UKH7.js} +2 -2
  149. package/dist/{chunk-CZTPU65V.js → chunk-MVG3KXON.js} +63 -16
  150. package/dist/chunk-MVG3KXON.js.map +1 -0
  151. package/dist/{chunk-YDVAM7S4.js → chunk-NETQXOPY.js} +2 -2
  152. package/dist/chunk-NETQXOPY.js.map +1 -0
  153. package/dist/{chunk-UZZ7SQT3.js → chunk-NVVZPBKI.js} +2 -2
  154. package/dist/{chunk-BLDBT6HZ.js → chunk-PJRKLB4Z.js} +18 -2
  155. package/dist/chunk-PJRKLB4Z.js.map +1 -0
  156. package/dist/{chunk-VBSNUH4J.js → chunk-PKUJNICO.js} +2 -2
  157. package/dist/{chunk-OPBFP4TF.js → chunk-QE6YVNP5.js} +7 -7
  158. package/dist/{chunk-WKDFJXW5.js → chunk-QM2SPLKQ.js} +1 -1
  159. package/dist/chunk-QM2SPLKQ.js.map +1 -0
  160. package/dist/{chunk-ENBPQEVU.js → chunk-QPVNK2VE.js} +2 -2
  161. package/dist/{chunk-RLJHJQUY.js → chunk-QS5Q5RBV.js} +2 -2
  162. package/dist/{chunk-3EKVN2OP.js → chunk-RDLPFM7I.js} +2 -2
  163. package/dist/{chunk-F4EHXVP7.js → chunk-RJQAP333.js} +2 -2
  164. package/dist/{chunk-QTQ6XKGT.js → chunk-RLU2Y5GV.js} +4 -4
  165. package/dist/chunk-RLU2Y5GV.js.map +1 -0
  166. package/dist/{chunk-5SPCMAUC.js → chunk-ROEFLU37.js} +4 -4
  167. package/dist/{chunk-UZEHHXYC.js → chunk-SFHLQPBF.js} +22 -22
  168. package/dist/chunk-SK7D34OL.js +68 -0
  169. package/dist/chunk-SK7D34OL.js.map +1 -0
  170. package/dist/{chunk-ZBW7A667.js → chunk-SUEOG2S4.js} +2 -2
  171. package/dist/{chunk-Q7CLGFA7.js → chunk-TEMKBSV6.js} +2 -2
  172. package/dist/{chunk-LQNRVPTV.js → chunk-THTF2W7M.js} +151 -118
  173. package/dist/chunk-THTF2W7M.js.map +1 -0
  174. package/dist/{chunk-GMIQV6DD.js → chunk-TO36VPZI.js} +2 -2
  175. package/dist/{chunk-6YAIN5XJ.js → chunk-TZ44E732.js} +44 -6
  176. package/dist/chunk-TZ44E732.js.map +1 -0
  177. package/dist/{chunk-JXN77SGO.js → chunk-U2VDCFXW.js} +1 -1
  178. package/dist/chunk-U2VDCFXW.js.map +1 -0
  179. package/dist/{chunk-LPYYY4AP.js → chunk-UZ6JYPJ6.js} +500 -218
  180. package/dist/chunk-UZ6JYPJ6.js.map +1 -0
  181. package/dist/{chunk-FXHOZGSE.js → chunk-V2ZA4YWE.js} +2 -2
  182. package/dist/{chunk-XH3HGI2N.js → chunk-VHKXRYQN.js} +2 -2
  183. package/dist/{chunk-GAS7KYC7.js → chunk-VKWFNPBH.js} +2 -2
  184. package/dist/{chunk-6H2G7RFT.js → chunk-VNQRRUNS.js} +11 -10
  185. package/dist/chunk-VNQRRUNS.js.map +1 -0
  186. package/dist/{chunk-IL6ODG6M.js → chunk-VQWBUPSJ.js} +2 -2
  187. package/dist/{chunk-5YCNDC3C.js → chunk-VQYWKCDR.js} +2 -2
  188. package/dist/{chunk-54NX5EG4.js → chunk-W23JARAQ.js} +2 -2
  189. package/dist/{chunk-YQNNHLCG.js → chunk-WPGR3RW4.js} +2 -2
  190. package/dist/{chunk-FNHLI2RE.js → chunk-WZYHPAG5.js} +3 -3
  191. package/dist/{chunk-5HYUUFMQ.js → chunk-XCPNH2MG.js} +259 -10
  192. package/dist/chunk-XCPNH2MG.js.map +1 -0
  193. package/dist/{chunk-TA4C3XB7.js → chunk-XM46Y66S.js} +2 -2
  194. package/dist/{chunk-PCOVEDPK.js → chunk-YRIFXXMI.js} +3 -3
  195. package/dist/{chunk-TRLOFIQC.js → chunk-YTK5MVNF.js} +2 -2
  196. package/dist/{chunk-Q432REND.js → chunk-YTZN2UZO.js} +2 -2
  197. package/dist/{chunk-6AGWBKQU.js → chunk-Z4GUX2M6.js} +2 -2
  198. package/dist/{chunk-AENM6GKU.js → chunk-ZAEPD4C2.js} +2 -2
  199. package/dist/{chunk-KQW3YGEN.js → chunk-ZRMMXWYI.js} +2 -2
  200. package/dist/{chunk-P4ZAEYKG.js → chunk-ZX3AYNNV.js} +6 -3
  201. package/dist/chunk-ZX3AYNNV.js.map +1 -0
  202. package/dist/{chunk-MCRVQ5YQ.js → chunk-ZZCR2QYL.js} +2 -2
  203. package/dist/{cli-DGq0MNpO.d.ts → cli-BWri5-am.d.ts} +5 -5
  204. package/dist/cli.d.ts +18 -16
  205. package/dist/cli.js +75 -74
  206. package/dist/coding/export-okf-codegraph.d.ts +1 -1
  207. package/dist/coding/export-okf-codegraph.js +14 -14
  208. package/dist/coding/pre-action-gate.d.ts +1 -1
  209. package/dist/compounding/engine.d.ts +2 -2
  210. package/dist/compounding/engine.js +15 -15
  211. package/dist/compounding/preference-consolidator.d.ts +1 -1
  212. package/dist/compression-optimizer.d.ts +1 -1
  213. package/dist/config.d.ts +1 -1
  214. package/dist/config.js +6 -5
  215. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  216. package/dist/connectors/codex-materialize-runner.js +15 -15
  217. package/dist/connectors/codex-materialize.d.ts +1 -1
  218. package/dist/connectors/index.d.ts +1 -1
  219. package/dist/connectors/index.js +15 -15
  220. package/dist/consolidation-provenance-check.d.ts +2 -2
  221. package/dist/consolidation-undo.d.ts +2 -2
  222. package/dist/contradiction/index.d.ts +6 -5
  223. package/dist/converge-config.d.ts +1 -1
  224. package/dist/convergence-refresh.d.ts +2 -2
  225. package/dist/convergence-refresh.js +17 -17
  226. package/dist/conversation-index/backend.d.ts +1 -1
  227. package/dist/conversation-index/chunker.d.ts +1 -1
  228. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  229. package/dist/conversation-index/indexer.d.ts +1 -1
  230. package/dist/conversation-index/search.d.ts +1 -1
  231. package/dist/corpus-watermark.d.ts +1 -1
  232. package/dist/corpus-watermark.js +17 -17
  233. package/dist/cross-lingual-recall.d.ts +1 -1
  234. package/dist/day-summary.d.ts +1 -1
  235. package/dist/deep-recall-http-glue.d.ts +16 -14
  236. package/dist/deep-recall-http-glue.js +2 -2
  237. package/dist/deep-recall-mcp-tools.d.ts +16 -14
  238. package/dist/deep-recall-policy-llm.d.ts +4 -3
  239. package/dist/deep-recall-policy-llm.js +3 -3
  240. package/dist/deep-recall-seeds.d.ts +1 -1
  241. package/dist/delinearize.d.ts +1 -1
  242. package/dist/dependency-propagation-config.d.ts +1 -1
  243. package/dist/{dependency-propagation-delivery-Cq1ekOwV.d.ts → dependency-propagation-delivery-ueZlKTQB.d.ts} +1 -1
  244. package/dist/direct-answer-wiring.d.ts +1 -1
  245. package/dist/direct-answer.d.ts +1 -1
  246. package/dist/embedding-fallback.d.ts +1 -1
  247. package/dist/enrichment/index.d.ts +1 -1
  248. package/dist/entity-origin-fields.d.ts +1 -1
  249. package/dist/entity-retrieval.d.ts +2 -2
  250. package/dist/entity-retrieval.js +15 -15
  251. package/dist/entity-schema.d.ts +1 -1
  252. package/dist/episodic-context.d.ts +1 -1
  253. package/dist/eval-trajectory-contracts.d.ts +1 -1
  254. package/dist/eval-trajectory-store.d.ts +1 -1
  255. package/dist/eval-trajectory.d.ts +1 -1
  256. package/dist/explicit-capture.d.ts +13 -12
  257. package/dist/external-wiki-access.d.ts +16 -14
  258. package/dist/external-wiki-access.js +38 -38
  259. package/dist/external-wiki-collection-registration.d.ts +1 -1
  260. package/dist/external-wiki-collection.d.ts +1 -1
  261. package/dist/external-wiki-mcp-tools.d.ts +16 -14
  262. package/dist/extraction-error-classification.d.ts +14 -3
  263. package/dist/extraction-error-classification.js +5 -3
  264. package/dist/extraction-faithfulness.d.ts +4 -3
  265. package/dist/extraction-faithfulness.js +3 -3
  266. package/dist/extraction-judge-telemetry.d.ts +4 -3
  267. package/dist/extraction-judge-training.d.ts +4 -3
  268. package/dist/extraction-judge.d.ts +4 -3
  269. package/dist/extraction-judge.js +3 -3
  270. package/dist/extraction-liveness.d.ts +1 -1
  271. package/dist/extraction-normalization.d.ts +1 -1
  272. package/dist/extraction-prompt.d.ts +1 -1
  273. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  274. package/dist/extraction-source-grounding.d.ts +1 -1
  275. package/dist/extraction-span-config.d.ts +1 -1
  276. package/dist/extraction-span-materialize.d.ts +1 -1
  277. package/dist/extraction.d.ts +4 -4
  278. package/dist/extraction.js +25 -23
  279. package/dist/fallback-llm-codex-subscription.d.ts +52 -7
  280. package/dist/fallback-llm-codex-subscription.js +17 -1
  281. package/dist/fallback-llm.d.ts +25 -28
  282. package/dist/fallback-llm.js +4 -3
  283. package/dist/{generic-recall-paths-BcySh_f9.d.ts → generic-recall-paths-CpyVmA88.d.ts} +1 -1
  284. package/dist/graph-append-error.d.ts +1 -1
  285. package/dist/graph-dashboard-diff.d.ts +1 -1
  286. package/dist/graph-dashboard-key.d.ts +1 -1
  287. package/dist/graph-dashboard-parser.d.ts +1 -1
  288. package/dist/graph-edge-reinforcement.d.ts +1 -1
  289. package/dist/graph-jsonl.d.ts +1 -1
  290. package/dist/graph-path-reconstruction.d.ts +1 -1
  291. package/dist/graph-path-scoring.d.ts +1 -1
  292. package/dist/graph-snapshot.d.ts +1 -1
  293. package/dist/graph.d.ts +1 -1
  294. package/dist/harmonic-retrieval.js +1 -1
  295. package/dist/importance.d.ts +1 -1
  296. package/dist/importers/index.d.ts +1 -1
  297. package/dist/importers/test-utils.d.ts +1 -1
  298. package/dist/in-flight-reads.d.ts +1 -1
  299. package/dist/{index-DWOb4wz9.d.ts → index-BvUA4S7M.d.ts} +3 -3
  300. package/dist/index.d.ts +79 -39
  301. package/dist/index.js +119 -103
  302. package/dist/intent.d.ts +1 -1
  303. package/dist/lcm/engine.d.ts +1 -1
  304. package/dist/lcm/index.d.ts +1 -1
  305. package/dist/lcm/index.js +3 -3
  306. package/dist/lcm/tools.d.ts +1 -1
  307. package/dist/lifecycle.d.ts +1 -1
  308. package/dist/live-connectors-runner.d.ts +1 -1
  309. package/dist/local-llm-BsJGulur.d.ts +247 -0
  310. package/dist/local-llm-config.d.ts +4 -1
  311. package/dist/local-llm-config.js +4 -2
  312. package/dist/local-llm-helpers.d.ts +18 -69
  313. package/dist/local-llm-helpers.js +1 -1
  314. package/dist/local-llm.d.ts +3 -170
  315. package/dist/local-llm.js +2 -2
  316. package/dist/local-model-endpoint.d.ts +1 -1
  317. package/dist/location/index.d.ts +3 -3
  318. package/dist/location/index.js +17 -17
  319. package/dist/maintenance/memory-governance.d.ts +1 -1
  320. package/dist/maintenance/memory-governance.js +15 -15
  321. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  322. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +15 -15
  323. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  324. package/dist/maintenance/rebuild-memory-projection.js +16 -16
  325. package/dist/{maintenance-CW9wCzMP.d.ts → maintenance-CYubtIRr.d.ts} +9 -3
  326. package/dist/mcp-memory-inspector-app.d.ts +16 -14
  327. package/dist/memory-action-policy.d.ts +1 -1
  328. package/dist/memory-cache.d.ts +1 -1
  329. package/dist/memory-controller.d.ts +1 -1
  330. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  331. package/dist/memory-projection-store.d.ts +1 -1
  332. package/dist/memory-provenance.d.ts +1 -1
  333. package/dist/memory-snapshot.d.ts +1 -1
  334. package/dist/memory-subject-cli.d.ts +16 -14
  335. package/dist/memory-subject.d.ts +16 -14
  336. package/dist/memory-worth-outcomes.d.ts +2 -2
  337. package/dist/models-json.d.ts +1 -1
  338. package/dist/namespaces/migrate.d.ts +3 -3
  339. package/dist/namespaces/migrate.js +16 -16
  340. package/dist/namespaces/principal.d.ts +1 -1
  341. package/dist/namespaces/search.d.ts +12 -1
  342. package/dist/namespaces/search.js +9 -9
  343. package/dist/namespaces/storage.d.ts +3 -3
  344. package/dist/namespaces/storage.js +15 -15
  345. package/dist/native-knowledge.d.ts +1 -1
  346. package/dist/offline-sync-impression-drain.d.ts +1 -1
  347. package/dist/operator-doctor-corpus.d.ts +1 -1
  348. package/dist/operator-doctor-corpus.js +18 -18
  349. package/dist/operator-doctor-replica.d.ts +1 -1
  350. package/dist/operator-toolkit.d.ts +3 -3
  351. package/dist/operator-toolkit.js +29 -28
  352. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  353. package/dist/orchestration/maintenance.d.ts +4 -4
  354. package/dist/orchestration/maintenance.js +26 -26
  355. package/dist/{orchestrator-ComHLm49.d.ts → orchestrator-BWDRJ_0d.d.ts} +24 -11
  356. package/dist/orchestrator.d.ts +13 -12
  357. package/dist/orchestrator.js +101 -98
  358. package/dist/patterns-cli.d.ts +1 -1
  359. package/dist/{pipeline-CiYcqqhl.d.ts → pipeline-7JMn2yMH.d.ts} +1 -1
  360. package/dist/policy-runtime.d.ts +1 -1
  361. package/dist/proactive-contention.d.ts +2 -2
  362. package/dist/provenance.d.ts +1 -1
  363. package/dist/{public-http-CuK4_Cb1.d.ts → public-http-CJWs3mo9.d.ts} +1 -1
  364. package/dist/{qmd-qXD4vatU.d.ts → qmd-CxCH9G9m.d.ts} +2 -2
  365. package/dist/qmd-preflight.d.ts +2 -2
  366. package/dist/qmd-recall-cache.d.ts +1 -1
  367. package/dist/qmd.d.ts +2 -2
  368. package/dist/qmd.js +2 -2
  369. package/dist/recall-concurrency-config.d.ts +1 -1
  370. package/dist/recall-disclosure-escalation.d.ts +1 -1
  371. package/dist/recall-explain-renderer.d.ts +1 -1
  372. package/dist/recall-explain-renderer.js +3 -3
  373. package/dist/recall-memory-map.d.ts +1 -1
  374. package/dist/recall-navigate-access.d.ts +1 -1
  375. package/dist/recall-navigate-access.js +2 -2
  376. package/dist/recall-navigate-disclosure.d.ts +1 -1
  377. package/dist/recall-navigate-disclosure.js +1 -1
  378. package/dist/recall-navigate.d.ts +1 -1
  379. package/dist/recall-navigate.js +2 -2
  380. package/dist/recall-planner-llm.d.ts +3 -2
  381. package/dist/recall-planner-llm.js +4 -3
  382. package/dist/recall-planner-llm.js.map +1 -1
  383. package/dist/recall-state-view-admission.d.ts +13 -3
  384. package/dist/recall-state-view-admission.js +8 -8
  385. package/dist/recall-state-view-anchors.d.ts +1 -1
  386. package/dist/recall-state-view-anchors.js +2 -2
  387. package/dist/recall-state-view-inject.js +2 -2
  388. package/dist/recall-state-view-render.js +2 -2
  389. package/dist/recall-state-view-widen.js +2 -2
  390. package/dist/recall-state-view-wire.js +3 -3
  391. package/dist/recall-state-view.d.ts +1 -0
  392. package/dist/recall-state-view.js +1 -1
  393. package/dist/recall-state.d.ts +1 -1
  394. package/dist/recall-tag-filter.d.ts +1 -1
  395. package/dist/recall-timings.d.ts +1 -1
  396. package/dist/recall-xray-cli.d.ts +1 -1
  397. package/dist/recall-xray-cli.js +4 -4
  398. package/dist/recall-xray-renderer.d.ts +1 -1
  399. package/dist/recall-xray-renderer.js +3 -3
  400. package/dist/recall-xray.d.ts +1 -1
  401. package/dist/recall-xray.js +2 -2
  402. package/dist/reconcile/cursor.d.ts +1 -1
  403. package/dist/reconcile/manifest.d.ts +1 -1
  404. package/dist/reconcile/plan.d.ts +1 -1
  405. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  406. package/dist/replay/normalizers/claude.d.ts +1 -1
  407. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  408. package/dist/replay/normalizers/shared.d.ts +1 -1
  409. package/dist/replay/runner.d.ts +1 -1
  410. package/dist/replay/types.d.ts +1 -1
  411. package/dist/replica-divergence.d.ts +1 -1
  412. package/dist/replica-peers-config.d.ts +1 -1
  413. package/dist/resolve-auth-token.d.ts +1 -1
  414. package/dist/resume-bundles.js +7 -6
  415. package/dist/retrieval-agents.d.ts +2 -2
  416. package/dist/retrieval-tiers.d.ts +1 -1
  417. package/dist/routing/engine.d.ts +1 -1
  418. package/dist/routing/store.d.ts +1 -1
  419. package/dist/salvage-envelope.d.ts +1 -1
  420. package/dist/{scope-profiles-BT9rqC3w.d.ts → scope-profiles-BGAUqhBR.d.ts} +1 -1
  421. package/dist/search/embed-helper.d.ts +1 -1
  422. package/dist/search/factory.d.ts +1 -1
  423. package/dist/search/factory.js +8 -8
  424. package/dist/search/index.d.ts +1 -1
  425. package/dist/search/index.js +10 -10
  426. package/dist/search/lancedb-backend.d.ts +1 -1
  427. package/dist/search/lancedb-backend.js +2 -2
  428. package/dist/search/meilisearch-backend.d.ts +1 -1
  429. package/dist/search/meilisearch-backend.js +2 -2
  430. package/dist/search/noop-backend.d.ts +1 -1
  431. package/dist/search/orama-backend.d.ts +1 -1
  432. package/dist/search/orama-backend.js +2 -2
  433. package/dist/search/port.d.ts +2 -2
  434. package/dist/search/port.js +1 -1
  435. package/dist/search/remote-backend.d.ts +1 -1
  436. package/dist/search/remote-backend.js +2 -2
  437. package/dist/{semantic-consolidation-CmZi7thY.d.ts → semantic-consolidation-CCeRD9pV.d.ts} +1 -1
  438. package/dist/semantic-consolidation.d.ts +2 -2
  439. package/dist/semantic-consolidation.js +16 -16
  440. package/dist/semantic-rule-promotion.js +15 -15
  441. package/dist/semantic-rule-verifier.d.ts +1 -1
  442. package/dist/semantic-rule-verifier.js +15 -15
  443. package/dist/{service-CLkA7AQB.d.ts → service-BwpzRduk.d.ts} +2 -2
  444. package/dist/session-observer-bands.d.ts +1 -1
  445. package/dist/session-observer-state.d.ts +1 -1
  446. package/dist/shared-context/manager.d.ts +1 -1
  447. package/dist/signal.d.ts +1 -1
  448. package/dist/source-agent-qualifier.d.ts +1 -1
  449. package/dist/source-agent-qualifier.js +18 -18
  450. package/dist/standup/build.js +15 -15
  451. package/dist/{storage-wvX01lht.d.ts → storage-BprAGBG0.d.ts} +2 -1
  452. package/dist/storage.d.ts +2 -2
  453. package/dist/storage.js +14 -14
  454. package/dist/subject-config.d.ts +1 -1
  455. package/dist/summarizer.d.ts +1 -1
  456. package/dist/summarizer.js +5 -5
  457. package/dist/summary-snapshot.d.ts +1 -1
  458. package/dist/support-passport/index.d.ts +18 -17
  459. package/dist/support-passport/index.js +40 -40
  460. package/dist/task-llm-config.d.ts +16 -0
  461. package/dist/task-llm-config.js +12 -0
  462. package/dist/task-llm-config.js.map +1 -0
  463. package/dist/temporal-supersession.d.ts +2 -2
  464. package/dist/temporal-timeline-recall.d.ts +1 -1
  465. package/dist/temporal-validity.d.ts +1 -1
  466. package/dist/threading.d.ts +1 -1
  467. package/dist/tier-migration.d.ts +2 -2
  468. package/dist/tier-routing.d.ts +1 -1
  469. package/dist/topics.d.ts +1 -1
  470. package/dist/transcript.d.ts +1 -1
  471. package/dist/transfer/export-okf.d.ts +1 -1
  472. package/dist/transfer/export-okf.js +15 -15
  473. package/dist/trust-score-stage.d.ts +1 -1
  474. package/dist/trust-score.d.ts +1 -1
  475. package/dist/{types-Cyr32ABj.d.ts → types-nJV23pa3.d.ts} +1 -1
  476. package/dist/types.d.ts +1 -1
  477. package/dist/types.js +1 -1
  478. package/dist/utility-runtime.d.ts +1 -1
  479. package/dist/verified-recall.js +15 -15
  480. package/dist/who-knows-cli.d.ts +16 -14
  481. package/dist/who-knows-cli.js +16 -16
  482. package/dist/who-knows.d.ts +16 -14
  483. package/dist/who-knows.js +15 -15
  484. package/dist/write-envelope.d.ts +1 -1
  485. package/package.json +2 -2
  486. package/src/access-category-alias.test.ts +93 -0
  487. package/src/access-offline-manifest.ts +52 -2
  488. package/src/access-schema.ts +9 -4
  489. package/src/activity/config.test.ts +61 -0
  490. package/src/activity/config.ts +40 -1
  491. package/src/activity/timeline/analysis-provider.ts +8 -2
  492. package/src/activity/timeline/analysis-run.test.ts +82 -0
  493. package/src/activity/timeline/publish-cli.test.ts +30 -0
  494. package/src/activity/timeline/publish-cli.ts +7 -0
  495. package/src/activity/timeline/query.ts +8 -1
  496. package/src/activity/timeline/regenerate.test.ts +82 -2
  497. package/src/activity/timeline/regenerate.ts +7 -1
  498. package/src/activity/vault-frontmatter.test.ts +99 -1
  499. package/src/activity/vault-frontmatter.ts +131 -0
  500. package/src/activity/vault-publish.ts +6 -0
  501. package/src/activity/vault-publisher.test.ts +172 -0
  502. package/src/activity/vault-publisher.ts +69 -15
  503. package/src/activity/vault-region.test.ts +7 -2
  504. package/src/activity/vault-region.ts +7 -3
  505. package/src/background-generation-config.ts +32 -6
  506. package/src/background-generation.test.ts +10 -1
  507. package/src/cli/timeline-publish-commands.ts +9 -0
  508. package/src/config.test.ts +170 -43
  509. package/src/config.ts +17 -5
  510. package/src/extraction-error-classification.ts +36 -1
  511. package/src/extraction-timeout.test.ts +110 -1
  512. package/src/extraction.test.ts +19 -1
  513. package/src/extraction.ts +23 -21
  514. package/src/fallback-llm-codex-subscription.ts +193 -7
  515. package/src/fallback-llm-parse-failure.test.ts +156 -0
  516. package/src/fallback-llm.test.ts +58 -0
  517. package/src/fallback-llm.ts +187 -186
  518. package/src/index.ts +1 -0
  519. package/src/local-llm-config.ts +11 -10
  520. package/src/local-llm-headers-timeout.test.ts +30 -0
  521. package/src/local-llm-helpers.ts +28 -0
  522. package/src/local-llm.ts +8 -19
  523. package/src/namespaces/search.test.ts +51 -1
  524. package/src/namespaces/search.ts +48 -3
  525. package/src/orchestration/extraction-persist-promotion.test.ts +228 -2
  526. package/src/orchestration/extraction-persist-promotion.ts +17 -14
  527. package/src/orchestration/orchestrator-helpers.test.ts +104 -0
  528. package/src/orchestration/orchestrator-init.ts +366 -106
  529. package/src/orchestration/recall-internal.ts +5 -11
  530. package/src/orchestration/semantic-merge-promotion-payload.ts +62 -6
  531. package/src/orchestration/startup-collection-checks.ts +85 -0
  532. package/src/orchestrator-flush.test.ts +7 -0
  533. package/src/orchestrator-init.test.ts +1539 -0
  534. package/src/orchestrator.ts +7 -0
  535. package/src/qmd.ts +21 -10
  536. package/src/recall-state-view-admission.ts +11 -1
  537. package/src/recall-state-view-cron-intent.test.ts +268 -0
  538. package/src/recall-state-view-widen.test.ts +14 -5
  539. package/src/recall-state-view-widen.ts +8 -1
  540. package/src/recall-state-view.ts +5 -2
  541. package/src/reconcile-identity-cache.test.ts +82 -1
  542. package/src/search/port.ts +1 -1
  543. package/src/storage/cas-revision-store.test.ts +4 -0
  544. package/src/storage/cas-revision-store.ts +104 -12
  545. package/src/storage-frontmatter-cas.test.ts +19 -17
  546. package/src/summarizer.ts +5 -1
  547. package/src/task-llm-config.test.ts +124 -0
  548. package/src/task-llm-config.ts +88 -0
  549. package/src/testing/subjects/startup-discovery-lifecycle.test.ts +273 -0
  550. package/src/types.ts +1 -0
  551. package/dist/chunk-3CBI2ZSA.js.map +0 -1
  552. package/dist/chunk-5HYUUFMQ.js.map +0 -1
  553. package/dist/chunk-6H2G7RFT.js.map +0 -1
  554. package/dist/chunk-6YAIN5XJ.js.map +0 -1
  555. package/dist/chunk-ACY4ZPF7.js.map +0 -1
  556. package/dist/chunk-B36GUU6T.js.map +0 -1
  557. package/dist/chunk-BLDBT6HZ.js.map +0 -1
  558. package/dist/chunk-CWTCMZGE.js.map +0 -1
  559. package/dist/chunk-CZTPU65V.js.map +0 -1
  560. package/dist/chunk-FWWWUPOE.js.map +0 -1
  561. package/dist/chunk-IQEJIOEU.js.map +0 -1
  562. package/dist/chunk-IYKZJVL5.js.map +0 -1
  563. package/dist/chunk-JXN77SGO.js.map +0 -1
  564. package/dist/chunk-LPYYY4AP.js.map +0 -1
  565. package/dist/chunk-LQNRVPTV.js.map +0 -1
  566. package/dist/chunk-MVAQ2WM3.js.map +0 -1
  567. package/dist/chunk-P4ZAEYKG.js.map +0 -1
  568. package/dist/chunk-QHT7MOUF.js.map +0 -1
  569. package/dist/chunk-QTQ6XKGT.js.map +0 -1
  570. package/dist/chunk-TNZNSMVJ.js.map +0 -1
  571. package/dist/chunk-WKDFJXW5.js.map +0 -1
  572. package/dist/chunk-YDVAM7S4.js.map +0 -1
  573. package/dist/chunk-YFTNZMGR.js.map +0 -1
  574. package/dist/chunk-YKREX63Z.js.map +0 -1
  575. /package/dist/{auto-sync-RP4C6ZPF.js.map → auto-sync-D6BAPIJV.js.map} +0 -0
  576. /package/dist/{chunk-JTQR6L2N.js.map → chunk-2SKMZUOW.js.map} +0 -0
  577. /package/dist/{chunk-GG5FHZJJ.js.map → chunk-2SNCQHJZ.js.map} +0 -0
  578. /package/dist/{chunk-O76F5QPP.js.map → chunk-3QEVOQF5.js.map} +0 -0
  579. /package/dist/{chunk-3N3PBBEH.js.map → chunk-3XPN7AVY.js.map} +0 -0
  580. /package/dist/{chunk-X4TD4O2F.js.map → chunk-46Z3VGWF.js.map} +0 -0
  581. /package/dist/{chunk-2ZTDRNCS.js.map → chunk-4CMXI55L.js.map} +0 -0
  582. /package/dist/{chunk-MUTVRKKY.js.map → chunk-7D6SER6A.js.map} +0 -0
  583. /package/dist/{chunk-WBM2MVBK.js.map → chunk-7Z54NXVS.js.map} +0 -0
  584. /package/dist/{chunk-UHRZ324M.js.map → chunk-BGRTZOJB.js.map} +0 -0
  585. /package/dist/{chunk-ZEGL7YCC.js.map → chunk-BXIJSPCL.js.map} +0 -0
  586. /package/dist/{chunk-JKKII6GX.js.map → chunk-BYQX4IOG.js.map} +0 -0
  587. /package/dist/{chunk-WIWLX65T.js.map → chunk-C5R73BON.js.map} +0 -0
  588. /package/dist/{chunk-BD7JTBYP.js.map → chunk-D7MAYFQP.js.map} +0 -0
  589. /package/dist/{chunk-LMLGBG6H.js.map → chunk-DFVSJFHK.js.map} +0 -0
  590. /package/dist/{chunk-3NPNBVFR.js.map → chunk-ES5BUPYB.js.map} +0 -0
  591. /package/dist/{chunk-TNSCIPBQ.js.map → chunk-G6NQ3L4T.js.map} +0 -0
  592. /package/dist/{chunk-5N4MZLEH.js.map → chunk-GO5LOHCD.js.map} +0 -0
  593. /package/dist/{chunk-AECJY3GJ.js.map → chunk-GSSDHAYH.js.map} +0 -0
  594. /package/dist/{chunk-TSP5WH72.js.map → chunk-HJUP3K6L.js.map} +0 -0
  595. /package/dist/{chunk-AAZEKXUP.js.map → chunk-ICNJ6J46.js.map} +0 -0
  596. /package/dist/{chunk-6EHM2AV7.js.map → chunk-IMBQFHRV.js.map} +0 -0
  597. /package/dist/{chunk-4RZLTZVM.js.map → chunk-IOPIGX7Y.js.map} +0 -0
  598. /package/dist/{chunk-EYKIDK33.js.map → chunk-IS2IDFJP.js.map} +0 -0
  599. /package/dist/{chunk-VJIE4D2I.js.map → chunk-J4WGTN2N.js.map} +0 -0
  600. /package/dist/{chunk-NXGSONWM.js.map → chunk-J7FVMLBR.js.map} +0 -0
  601. /package/dist/{chunk-VSL63CFJ.js.map → chunk-JAJIMTFB.js.map} +0 -0
  602. /package/dist/{chunk-4JVQRFZD.js.map → chunk-JOP7W24J.js.map} +0 -0
  603. /package/dist/{chunk-YUW66UAH.js.map → chunk-JUDT33RX.js.map} +0 -0
  604. /package/dist/{chunk-D545Z7UH.js.map → chunk-K4JKAXMO.js.map} +0 -0
  605. /package/dist/{chunk-BV4ZKIZH.js.map → chunk-K75A5XWU.js.map} +0 -0
  606. /package/dist/{chunk-M6HBPLBA.js.map → chunk-KOTG3RXE.js.map} +0 -0
  607. /package/dist/{chunk-OB3XMWX5.js.map → chunk-KVO2BTA4.js.map} +0 -0
  608. /package/dist/{chunk-GI4ZBWPQ.js.map → chunk-KY236SP5.js.map} +0 -0
  609. /package/dist/{chunk-4BCHFSC7.js.map → chunk-LFVZD5EC.js.map} +0 -0
  610. /package/dist/{chunk-O4M4BDIJ.js.map → chunk-LKFVVN7R.js.map} +0 -0
  611. /package/dist/{chunk-4RX5O34R.js.map → chunk-MJC7UKH7.js.map} +0 -0
  612. /package/dist/{chunk-UZZ7SQT3.js.map → chunk-NVVZPBKI.js.map} +0 -0
  613. /package/dist/{chunk-VBSNUH4J.js.map → chunk-PKUJNICO.js.map} +0 -0
  614. /package/dist/{chunk-OPBFP4TF.js.map → chunk-QE6YVNP5.js.map} +0 -0
  615. /package/dist/{chunk-ENBPQEVU.js.map → chunk-QPVNK2VE.js.map} +0 -0
  616. /package/dist/{chunk-RLJHJQUY.js.map → chunk-QS5Q5RBV.js.map} +0 -0
  617. /package/dist/{chunk-3EKVN2OP.js.map → chunk-RDLPFM7I.js.map} +0 -0
  618. /package/dist/{chunk-F4EHXVP7.js.map → chunk-RJQAP333.js.map} +0 -0
  619. /package/dist/{chunk-5SPCMAUC.js.map → chunk-ROEFLU37.js.map} +0 -0
  620. /package/dist/{chunk-UZEHHXYC.js.map → chunk-SFHLQPBF.js.map} +0 -0
  621. /package/dist/{chunk-ZBW7A667.js.map → chunk-SUEOG2S4.js.map} +0 -0
  622. /package/dist/{chunk-Q7CLGFA7.js.map → chunk-TEMKBSV6.js.map} +0 -0
  623. /package/dist/{chunk-GMIQV6DD.js.map → chunk-TO36VPZI.js.map} +0 -0
  624. /package/dist/{chunk-FXHOZGSE.js.map → chunk-V2ZA4YWE.js.map} +0 -0
  625. /package/dist/{chunk-XH3HGI2N.js.map → chunk-VHKXRYQN.js.map} +0 -0
  626. /package/dist/{chunk-GAS7KYC7.js.map → chunk-VKWFNPBH.js.map} +0 -0
  627. /package/dist/{chunk-IL6ODG6M.js.map → chunk-VQWBUPSJ.js.map} +0 -0
  628. /package/dist/{chunk-5YCNDC3C.js.map → chunk-VQYWKCDR.js.map} +0 -0
  629. /package/dist/{chunk-54NX5EG4.js.map → chunk-W23JARAQ.js.map} +0 -0
  630. /package/dist/{chunk-YQNNHLCG.js.map → chunk-WPGR3RW4.js.map} +0 -0
  631. /package/dist/{chunk-FNHLI2RE.js.map → chunk-WZYHPAG5.js.map} +0 -0
  632. /package/dist/{chunk-TA4C3XB7.js.map → chunk-XM46Y66S.js.map} +0 -0
  633. /package/dist/{chunk-PCOVEDPK.js.map → chunk-YRIFXXMI.js.map} +0 -0
  634. /package/dist/{chunk-TRLOFIQC.js.map → chunk-YTK5MVNF.js.map} +0 -0
  635. /package/dist/{chunk-Q432REND.js.map → chunk-YTZN2UZO.js.map} +0 -0
  636. /package/dist/{chunk-6AGWBKQU.js.map → chunk-Z4GUX2M6.js.map} +0 -0
  637. /package/dist/{chunk-AENM6GKU.js.map → chunk-ZAEPD4C2.js.map} +0 -0
  638. /package/dist/{chunk-KQW3YGEN.js.map → chunk-ZRMMXWYI.js.map} +0 -0
  639. /package/dist/{chunk-MCRVQ5YQ.js.map → chunk-ZZCR2QYL.js.map} +0 -0
package/src/index.ts CHANGED
@@ -1224,6 +1224,7 @@ export {
1224
1224
 
1225
1225
  export {
1226
1226
  FallbackLlmClient,
1227
+ FallbackLlmClient as TaskLlmClient,
1227
1228
  type FallbackLlmOptions,
1228
1229
  type FallbackLlmResponse,
1229
1230
  type FallbackLlmRuntimeContext,
@@ -2,7 +2,7 @@ import { coerceNumber } from "./connectors/coerce.js";
2
2
  import { parseBackgroundGeneration } from "./background-generation-config.js";
3
3
  import type { BackgroundGenerationConfig } from "./background-generation-config.js";
4
4
  import { readEnvVar } from "./runtime/env.js";
5
-
5
+ import { parseTaskLlmConfig } from "./task-llm-config.js";
6
6
  export interface LocalLlmConfig {
7
7
  // Local LLM Provider (v2.1)
8
8
  localLlmEnabled: boolean;
@@ -17,14 +17,17 @@ export interface LocalLlmConfig {
17
17
  /** If false, do not send Authorization header even when localLlmApiKey is set. */
18
18
  localLlmAuthHeader: boolean;
19
19
  localLlmFallback: boolean;
20
+ taskLlmFallback?: boolean;
20
21
  /** Optional home directory override for local LLM helpers (LM Studio settings, CLI PATH). */
21
22
  localLlmHomeDir?: string;
22
23
  /** Optional absolute path to LMS CLI binary (preferred over auto-detection). */
23
24
  localLmsCliPath?: string;
24
25
  /** Optional bin directory prepended to PATH for LMS CLI execution. */
25
26
  localLmsBinDir?: string;
26
- /** Hard timeout for local LLM and gateway fallback requests (ms). */
27
+ /** Hard timeout for local LLM requests (ms). Legacy alias for the task-chain timeout when `taskLlmTimeoutMs` is absent. */
27
28
  localLlmTimeoutMs: number;
29
+ /** Timeout for the gateway/task LLM chain (ms). */
30
+ taskLlmTimeoutMs?: number;
28
31
  /** Max context window for local LLM (override auto-detection). Set lower if your LLM server defaults to smaller contexts. */
29
32
  localLlmMaxContext?: number;
30
33
  }
@@ -33,11 +36,6 @@ export type LocalLlmParseResult = LocalLlmConfig & {
33
36
  backgroundGeneration?: BackgroundGenerationConfig;
34
37
  };
35
38
 
36
- function parseLocalLlmTimeoutMs(value: unknown): number {
37
- const coerced = coerceNumber(value);
38
- if (coerced === undefined) return 180_000;
39
- return Math.min(86_400_000, Math.max(1, Math.floor(coerced)));
40
- }
41
39
 
42
40
  function parseLocalLlmMaxContext(value: unknown): number | undefined {
43
41
  if (value === undefined || value === null) return undefined;
@@ -70,8 +68,9 @@ export function parseLocalLlmConfig(
70
68
  localLlmApiKeyEnv: string | undefined,
71
69
  resolveEnvVars: (value: string) => string,
72
70
  ): LocalLlmParseResult {
71
+ const taskLlm = parseTaskLlmConfig(cfg);
73
72
  return {
74
- backgroundGeneration: parseBackgroundGeneration(cfg),
73
+ backgroundGeneration: parseBackgroundGeneration(cfg, resolveEnvVars),
75
74
  localLlmEnabled: cfg.localLlmEnabled === true || cfg.localLlmEnabled === "true",
76
75
  localLlmUrl:
77
76
  typeof cfg.localLlmUrl === "string" && cfg.localLlmUrl.length > 0
@@ -90,7 +89,8 @@ export function parseLocalLlmConfig(
90
89
  localLlmApiKeyEnv,
91
90
  localLlmHeaders: copyStringRecord(cfg.localLlmHeaders),
92
91
  localLlmAuthHeader: cfg.localLlmAuthHeader !== false,
93
- localLlmFallback: cfg.localLlmFallback !== false,
92
+ localLlmFallback: taskLlm.fallback,
93
+ taskLlmFallback: taskLlm.fallback,
94
94
  localLlmHomeDir:
95
95
  typeof cfg.localLlmHomeDir === "string" && cfg.localLlmHomeDir.length > 0
96
96
  ? cfg.localLlmHomeDir
@@ -103,7 +103,8 @@ export function parseLocalLlmConfig(
103
103
  typeof cfg.localLmsBinDir === "string" && cfg.localLmsBinDir.length > 0
104
104
  ? cfg.localLmsBinDir
105
105
  : undefined,
106
- localLlmTimeoutMs: parseLocalLlmTimeoutMs(cfg.localLlmTimeoutMs),
106
+ localLlmTimeoutMs: taskLlm.localTimeoutMs,
107
+ taskLlmTimeoutMs: taskLlm.timeoutMs,
107
108
  localLlmMaxContext: parseLocalLlmMaxContext(cfg.localLlmMaxContext),
108
109
  };
109
110
  }
@@ -12,6 +12,7 @@ import {
12
12
  } from "undici";
13
13
 
14
14
  import { LocalLlmClient } from "./local-llm.js";
15
+ import { classifyAnalysisProviderError } from "./activity/timeline/analysis-provider.js";
15
16
  import { ChatTransport } from "./local-llm-transport.js";
16
17
  import { initLogger, resetLogger } from "./logger.js";
17
18
  import type { PluginConfig } from "./types.js";
@@ -553,3 +554,32 @@ test("sensitive local requests do not log provider error bodies", { concurrency:
553
554
  await dispatcherOf(client).close();
554
555
  }
555
556
  });
557
+
558
+ test("failureDiag preserves a 429 rate-limit failure cause (issue #2891)", { concurrency: false }, async () => {
559
+ const original = globalThis.fetch;
560
+ globalThis.fetch = (async () =>
561
+ new Response(JSON.stringify({ error: { message: "rate limit exceeded" } }), {
562
+ status: 429,
563
+ headers: { "content-type": "application/json" },
564
+ })) as typeof fetch;
565
+ const client = new LocalLlmClient(createConfig());
566
+
567
+ try {
568
+ primeClient(client);
569
+ const failureDiag: { lastError?: unknown } = {};
570
+ assert.equal(
571
+ await client.chatCompletion(
572
+ [{ role: "user", content: "test" }],
573
+ { redactProviderErrors: true, failureDiag },
574
+ ),
575
+ null,
576
+ );
577
+ const lastError = failureDiag.lastError;
578
+ assert.ok(lastError instanceof Error, "expected the terminal provider error to survive the request");
579
+ assert.equal("status" in lastError ? lastError.status : undefined, 429);
580
+ assert.equal(classifyAnalysisProviderError(lastError), "rate_limited");
581
+ } finally {
582
+ globalThis.fetch = original;
583
+ await dispatcherOf(client).close();
584
+ }
585
+ });
@@ -1,4 +1,32 @@
1
1
  import { log } from "./logger.js";
2
+ import type { LocalLlmRequestPriority } from "./local-llm.js";
3
+
4
+ export interface LocalLlmChatCompletionOptions {
5
+ temperature?: number;
6
+ maxTokens?: number;
7
+ responseFormat?: { type: string };
8
+ timeoutMs?: number;
9
+ operation?: string;
10
+ forceDisableThinking?: boolean;
11
+ disableThinking?: boolean;
12
+ priority?: LocalLlmRequestPriority;
13
+ signal?: AbortSignal;
14
+ redactProviderErrors?: boolean;
15
+ /** Per-request model; defaults to config.localLlmModel. */
16
+ model?: string;
17
+ /**
18
+ * Optional out-box for the terminal failure cause (issue #2891): on a
19
+ * failed request the client records the last provider error here so
20
+ * callers can classify it (e.g. HTTP 429 → rate-limited) in memory
21
+ * instead of seeing only null. Never logged.
22
+ */
23
+ failureDiag?: { lastError?: unknown };
24
+ }
25
+
26
+ export interface LocalLlmChatCompletionResult {
27
+ content: string;
28
+ usage?: { promptTokens: number; completionTokens: number; totalTokens: number };
29
+ }
2
30
  export function isAbortError(err: unknown): boolean {
3
31
  if (!err || typeof err !== "object") return false;
4
32
  const maybe = err as { name?: string; message?: string };
package/src/local-llm.ts CHANGED
@@ -19,6 +19,8 @@ import {
19
19
  normalizeBackendTripReason,
20
20
  waitForRetryBackoff,
21
21
  SingleFlightProbe,
22
+ type LocalLlmChatCompletionOptions,
23
+ type LocalLlmChatCompletionResult,
22
24
  } from "./local-llm-helpers.js";
23
25
 
24
26
  /** Trim trailing slash characters without backtracking regex. */
@@ -226,20 +228,8 @@ export interface LocalModelInfo {
226
228
 
227
229
  export type LocalLlmRequestPriority = "recall-critical" | "background";
228
230
 
229
- interface LocalLlmChatCompletionOptions {
230
- temperature?: number;
231
- maxTokens?: number;
232
- responseFormat?: { type: string };
233
- timeoutMs?: number;
234
- operation?: string;
235
- forceDisableThinking?: boolean;
236
- disableThinking?: boolean;
237
- priority?: LocalLlmRequestPriority;
238
- signal?: AbortSignal;
239
- redactProviderErrors?: boolean;
240
- /** Per-request model; defaults to config.localLlmModel. */
241
- model?: string;
242
- }
231
+ // LocalLlmChatCompletionOptions and LocalLlmChatCompletionResult live in
232
+ // local-llm-helpers.ts so this file stays under its size ceiling (#1995).
243
233
  interface LocalLlmQueuedRequest {
244
234
  messages: Array<{ role: string; content: string }>;
245
235
  options: LocalLlmChatCompletionOptions;
@@ -248,11 +238,6 @@ interface LocalLlmQueuedRequest {
248
238
  resolve: (value: LocalLlmChatCompletionResult | null) => void;
249
239
  }
250
240
 
251
- interface LocalLlmChatCompletionResult {
252
- content: string;
253
- usage?: { promptTokens: number; completionTokens: number; totalTokens: number };
254
- }
255
-
256
241
  const LOCAL_LLM_GLOBAL_BACKEND_STATE = "__openclawEngramLocalLlmBackendState";
257
242
 
258
243
  type LocalLlmBackendState = {
@@ -1165,6 +1150,10 @@ export class LocalLlmClient {
1165
1150
  } else {
1166
1151
  this.consecutive400s = 0;
1167
1152
  }
1153
+ if (options.failureDiag)
1154
+ options.failureDiag.lastError = Object.assign(new Error("local LLM http failure"), {
1155
+ status: response.status,
1156
+ });
1168
1157
  return null;
1169
1158
  }
1170
1159
  this.consecutive400s = 0;
@@ -21,6 +21,7 @@ class FakeBackend implements SearchBackend {
21
21
  strictEmbeds = 0;
22
22
  strictCollectionEmbeds: string[] = [];
23
23
  disposed = 0;
24
+ disposeWait: Promise<void> | null = null;
24
25
  available = true;
25
26
  calls: Array<{
26
27
  method: string;
@@ -28,6 +29,7 @@ class FakeBackend implements SearchBackend {
28
29
  maxResults: number | undefined;
29
30
  }> = [];
30
31
  availabilitySignals: Array<AbortSignal | undefined> = [];
32
+ probeSignals: Array<AbortSignal | undefined> = [];
31
33
  probeCalls = 0;
32
34
  ensureSignals: Array<AbortSignal | undefined> = [];
33
35
  ensureCollections: Array<string | undefined> = [];
@@ -54,8 +56,9 @@ class FakeBackend implements SearchBackend {
54
56
  : this.results;
55
57
  }
56
58
 
57
- async probe(): Promise<boolean> {
59
+ async probe(execution?: SearchExecutionOptions): Promise<boolean> {
58
60
  this.probeCalls += 1;
61
+ this.probeSignals.push(execution?.signal);
59
62
  return this.available;
60
63
  }
61
64
 
@@ -89,6 +92,7 @@ class FakeBackend implements SearchBackend {
89
92
 
90
93
  async dispose(): Promise<void> {
91
94
  this.disposed += 1;
95
+ await this.disposeWait;
92
96
  }
93
97
 
94
98
  async search(
@@ -470,10 +474,56 @@ test("ensureNamespaceCollection forwards abort signals to backend collection che
470
474
  });
471
475
 
472
476
  assert.equal(state, "present");
477
+ assert.deepEqual(backend.probeSignals, [controller.signal]);
473
478
  assert.deepEqual(backend.ensureSignals, [controller.signal]);
474
479
  assert.deepEqual(backend.ensureCollections, ["openclaw-engram--ns-6d61696e"]);
475
480
  });
476
481
 
482
+ test("disableSearchBackends releases cached namespace backends without recreating search", async () => {
483
+ const backend = new FakeBackend(false);
484
+ const router = new NamespaceSearchRouter(
485
+ config(),
486
+ { storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
487
+ () => backend,
488
+ );
489
+
490
+ assert.equal(await router.ensureNamespaceCollection("main"), "present");
491
+ await router.disableSearchBackends();
492
+
493
+ await router.disableSearchBackends();
494
+
495
+ assert.equal(backend.disposed, 1, "repeated runtime disable must not double-dispose the same backend");
496
+ assert.equal(await router.backendForNamespace("main"), null);
497
+ assert.equal(await router.ensureNamespaceCollection("main"), "missing");
498
+ assert.equal(backend.probeCalls, 1, "disabled records must not recreate a concrete backend");
499
+ });
500
+
501
+ test("clearCache releases evicted namespace backend handles before recreation", async () => {
502
+ const oldBackend = new FakeBackend(false);
503
+ const newBackend = new FakeBackend(false);
504
+ let releaseOldDispose: (() => void) | undefined;
505
+ oldBackend.disposeWait = new Promise<void>((resolve) => { releaseOldDispose = resolve; });
506
+ let createCalls = 0;
507
+ const router = new NamespaceSearchRouter(
508
+ config(),
509
+ { storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
510
+ () => {
511
+ createCalls += 1;
512
+ return createCalls === 1 ? oldBackend : newBackend;
513
+ },
514
+ );
515
+
516
+ await router.ensureNamespaceCollection("main");
517
+ router.clearCache();
518
+ const recreation = router.ensureNamespaceCollection("main");
519
+ await Promise.resolve();
520
+ assert.equal(createCalls, 1, "recreation must wait for the evicted handle disposal barrier");
521
+ releaseOldDispose?.();
522
+ assert.equal(await recreation, "present");
523
+ assert.equal(oldBackend.disposed, 1);
524
+ assert.equal(createCalls, 2);
525
+ });
526
+
477
527
  test("legacy default namespace root auto-creates its base collection (broad root, #1929)", async () => {
478
528
  const backend = new FakeBackend(false);
479
529
  const router = new NamespaceSearchRouter(
@@ -45,6 +45,7 @@ type NamespaceBackendRecord = {
45
45
  available: boolean;
46
46
  collectionState: CollectionState;
47
47
  filtersNestedNamespaces: boolean;
48
+ disposed: boolean;
48
49
  };
49
50
 
50
51
  export interface NamespaceUpdateResult {
@@ -83,6 +84,7 @@ type BackendRecordOptions = {
83
84
 
84
85
  export class NamespaceSearchRouter {
85
86
  private readonly cache = new Map<string, Promise<NamespaceBackendRecord>>();
87
+ private readonly pendingDisposals = new Set<Promise<void>>();
86
88
 
87
89
  constructor(
88
90
  private readonly config: PluginConfig,
@@ -344,21 +346,62 @@ export class NamespaceSearchRouter {
344
346
  return cachedRecord;
345
347
  }
346
348
 
349
+ private trackDisposal(promise: Promise<void>): void {
350
+ this.pendingDisposals.add(promise);
351
+ void promise.finally(() => this.pendingDisposals.delete(promise));
352
+ }
353
+
354
+ private async drainPendingDisposals(): Promise<void> {
355
+ if (this.pendingDisposals.size === 0) return;
356
+ await Promise.allSettled(this.pendingDisposals);
357
+ }
358
+
347
359
  /** Clear cached backend records so the next access re-probes availability. */
348
360
  clearCache(): void {
361
+ const pendingRecords = Array.from(this.cache.values());
349
362
  this.cache.clear();
363
+ const disposal = Promise.allSettled(pendingRecords).then(async (settled) => {
364
+ await Promise.allSettled(
365
+ settled.flatMap((entry) =>
366
+ entry.status === "fulfilled" ? [this.disposeRecord(entry.value)] : []),
367
+ );
368
+ });
369
+ this.trackDisposal(disposal);
370
+ }
371
+
372
+ private async disposeRecord(record: NamespaceBackendRecord): Promise<void> {
373
+ if (record.disposed) return;
374
+ record.disposed = true;
375
+ const dispose = (record.backend as { dispose?: () => void | Promise<void> }).dispose;
376
+ await dispose?.call(record.backend);
350
377
  }
351
378
 
352
379
  /** Release any per-namespace backend handles held by cached records. */
353
380
  async dispose(): Promise<void> {
381
+ await this.drainPendingDisposals();
354
382
  const pendingRecords = Array.from(this.cache.values());
355
383
  this.cache.clear();
356
384
  const settled = await Promise.allSettled(pendingRecords);
385
+ await Promise.allSettled(
386
+ settled.flatMap((entry) =>
387
+ entry.status === "fulfilled" ? [this.disposeRecord(entry.value)] : []),
388
+ );
389
+ }
390
+
391
+ /**
392
+ * Disable namespace search for this runtime while retaining the resolved
393
+ * records as unavailable/missing. This releases concrete QMD/daemon handles
394
+ * without letting later reads recreate a search backend after the root path
395
+ * has been switched to NoopSearchBackend for a missing collection.
396
+ */
397
+ async disableSearchBackends(): Promise<void> {
398
+ const settled = await Promise.allSettled(this.cache.values());
357
399
  await Promise.allSettled(
358
400
  settled.flatMap((entry) => {
359
401
  if (entry.status !== "fulfilled") return [];
360
- const dispose = (entry.value.backend as { dispose?: () => void | Promise<void> }).dispose;
361
- return dispose ? [dispose.call(entry.value.backend)] : [];
402
+ entry.value.available = false;
403
+ entry.value.collectionState = "missing";
404
+ return [this.disposeRecord(entry.value)];
362
405
  }),
363
406
  );
364
407
  }
@@ -367,6 +410,7 @@ export class NamespaceSearchRouter {
367
410
  namespace: string,
368
411
  execution?: SearchExecutionOptions,
369
412
  ): Promise<NamespaceBackendRecord> {
413
+ await this.drainPendingDisposals();
370
414
  const key = namespace.trim() || this.config.defaultNamespace;
371
415
  const existing = this.cache.get(key);
372
416
  if (existing) return await existing;
@@ -412,7 +456,7 @@ export class NamespaceSearchRouter {
412
456
  try {
413
457
  const availabilityProbe =
414
458
  options.autoCreateCollection || typeof backend.checkAvailability !== "function"
415
- ? backend.probe()
459
+ ? backend.probe(execution)
416
460
  : backend.checkAvailability({ signal: execution?.signal });
417
461
  const available = await awaitWithAbort(availabilityProbe, execution?.signal).catch((error) => {
418
462
  if (error instanceof NamespaceSearchAbortError && !options.abortAsUnavailable) {
@@ -453,6 +497,7 @@ export class NamespaceSearchRouter {
453
497
  available,
454
498
  collectionState,
455
499
  filtersNestedNamespaces,
500
+ disposed: false,
456
501
  };
457
502
  } catch (error) {
458
503
  const dispose = (backend as { dispose?: () => void | Promise<void> }).dispose;
@@ -757,7 +757,229 @@ test("buildMergedTargetPromotionPayload and promotion refuse when interleaving w
757
757
  );
758
758
  });
759
759
 
760
- test("buildMergedTargetPromotionPayload: unavailable snapshot digest refuses when a committed digest exists (#2813 P1)", async () => {
760
+ // ── #2870: access-only telemetry vs semantic metadata in the promotion binding ──
761
+
762
+ type RawFileMutator = (raw: string) => string;
763
+
764
+ const withFrontmatterLine = (line: string): RawFileMutator => (raw) =>
765
+ raw.replace("\n---\n", `\n${line}\n---\n`);
766
+
767
+ /** Rewrite the durable file directly — a writer that changes semantics
768
+ * WITHOUT minting a CAS receipt (hand edit, legacy tool). Exactly the
769
+ * writer class the semantic-fingerprint clause must catch. */
770
+ async function rewriteDurableWithoutReceipt(
771
+ storage: StorageManager,
772
+ memoryId: string,
773
+ mutate: RawFileMutator,
774
+ ): Promise<void> {
775
+ const row = await storage.getMemoryByIdIncludingArchived(memoryId);
776
+ assert.ok(row);
777
+ const before = await readFile(row.path, "utf8");
778
+ await writeFile(row.path, mutate(before), "utf8");
779
+ }
780
+ async function flushAccess(
781
+ storage: StorageManager,
782
+ memoryId: string,
783
+ newCount: number,
784
+ ): Promise<number> {
785
+ return await storage.flushAccessTracking([
786
+ { memoryId, newCount, lastAccessed: "2026-08-23T00:00:00.000Z" },
787
+ ]);
788
+ }
789
+
790
+ async function runPromotion(
791
+ s: { source: StorageManager; router: { storageFor: (namespace: string) => Promise<StorageManager> } },
792
+ payload: MergedTargetPromotionPayload | null,
793
+ sourceMemoryId: string,
794
+ ): Promise<number> {
795
+ let promotions = 0;
796
+ await promoteAndReconcileMergedTarget({
797
+ promote: async () => {
798
+ promotions += 1;
799
+ return `copy-${promotions}`;
800
+ },
801
+ config: parseConfig({ memoryDir: s.source.dir, sharedNamespace: "shared" }),
802
+ getStorageRouter: () => s.router,
803
+ scopeProfileWritePlan: null,
804
+ sourceStorage: s.source,
805
+ sourceMemoryId,
806
+ mergedPromotion: payload,
807
+ normalize: (content: string) => content,
808
+ });
809
+ return promotions;
810
+ }
811
+
812
+ test("access flush between merge commit and payload build still promotes (#2870)", async () => {
813
+ const s = await makeStorages();
814
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
815
+ source: "test",
816
+ confidence: 0.5,
817
+ });
818
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
819
+ const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
820
+ assert.ok(committed);
821
+ const shardPath = casShardPath(s.source.dir, committed.path);
822
+ const receiptBefore = JSON.parse(await readFile(shardPath, "utf8")) as { revision: string };
823
+ const bytesBefore = await readFile(committed.path, "utf8");
824
+
825
+ assert.equal(await flushAccess(s.source, target.id, 3), 1, "the access flush landed");
826
+
827
+ // Prove the interleaving is real: bytes changed, receipt did not re-mint.
828
+ assert.notEqual(await readFile(committed.path, "utf8"), bytesBefore, "the flush rewrote the durable file");
829
+ const receiptAfter = JSON.parse(await readFile(shardPath, "utf8")) as { revision: string };
830
+ assert.equal(receiptAfter.revision, receiptBefore.revision, "an access flush mints no receipt");
831
+
832
+ const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
833
+ targetId: target.id,
834
+ mergedContent: A_MERGED_BODY,
835
+ provenancePatched: true,
836
+ });
837
+ assert.equal(readFailed, false);
838
+ assert.ok(payload, "an access-only flush must not refuse the payload");
839
+ assert.ok(payload?.committedSemanticFingerprint, "the payload carries the semantic binding");
840
+
841
+ assert.equal(await runPromotion(s, payload, target.id), 1, "the flushed-but-unchanged semantics still promote");
842
+ });
843
+
844
+ test("access flush between payload build and promotion still promotes (#2870)", async () => {
845
+ const s = await makeStorages();
846
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
847
+ source: "test",
848
+ confidence: 0.5,
849
+ });
850
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
851
+ const { payload } = await buildMergedTargetPromotionPayload(s.source, {
852
+ targetId: target.id,
853
+ mergedContent: A_MERGED_BODY,
854
+ provenancePatched: true,
855
+ });
856
+ assert.ok(payload);
857
+ assert.equal(await flushAccess(s.source, target.id, 7), 1, "the access flush lands after the build");
858
+
859
+ assert.equal(await runPromotion(s, payload, target.id), 1, "the final guard confirms the flushed record's semantics");
860
+ });
861
+
862
+ test("payload build refuses a semantic mutation that minted no receipt (#2870)", async () => {
863
+ const s = await makeStorages();
864
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
865
+ source: "test",
866
+ confidence: 0.5,
867
+ });
868
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
869
+ await rewriteDurableWithoutReceipt(
870
+ s.source,
871
+ target.id,
872
+ (raw) => raw.replace(/^confidence: .*$/m, "confidence: 0.99"),
873
+ );
874
+ const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
875
+ targetId: target.id,
876
+ mergedContent: A_MERGED_BODY,
877
+ provenancePatched: true,
878
+ });
879
+ assert.equal(payload, null, "a same-body confidence change must refuse the payload");
880
+ assert.equal(readFailed, true, "the refusal is an unknown outcome, not a no-promotion verdict");
881
+ });
882
+
883
+ test("final guard refuses each semantic field mutation that minted no receipt (#2870)", async () => {
884
+ const mutations: Array<[label: string, mutate: RawFileMutator]> = [
885
+ ["confidence", (raw) => raw.replace(/^confidence: .*$/m, "confidence: 0.99")],
886
+ ["tags", (raw) => raw.replace(/^tags: .*$/m, 'tags: ["mutated"]')],
887
+ ["status", withFrontmatterLine("status: superseded")],
888
+ ["provenance", withFrontmatterLine("provenance: unverified")],
889
+ ["tool scope", withFrontmatterLine("toolScoped: true")],
890
+ ["body", (raw) => `${raw}\nmutated body suffix`],
891
+ ];
892
+ for (const [label, mutate] of mutations) {
893
+ const s = await makeStorages();
894
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
895
+ source: "test",
896
+ confidence: 0.5,
897
+ });
898
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
899
+ const { payload } = await buildMergedTargetPromotionPayload(s.source, {
900
+ targetId: target.id,
901
+ mergedContent: A_MERGED_BODY,
902
+ provenancePatched: true,
903
+ });
904
+ assert.ok(payload, `payload builds before the ${label} mutation`);
905
+ await rewriteDurableWithoutReceipt(s.source, target.id, mutate);
906
+
907
+ assert.equal(
908
+ await runPromotion(s, payload, target.id),
909
+ 0,
910
+ `a ${label} mutation without a receipt must refuse promotion`,
911
+ );
912
+ }
913
+ });
914
+
915
+ test("a PENDING receipt marker between build and promotion abandons it (#2870)", async () => {
916
+ const s = await makeStorages();
917
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
918
+ source: "test",
919
+ confidence: 0.5,
920
+ });
921
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
922
+ const { payload } = await buildMergedTargetPromotionPayload(s.source, {
923
+ targetId: target.id,
924
+ mergedContent: A_MERGED_BODY,
925
+ provenancePatched: true,
926
+ });
927
+ assert.ok(payload);
928
+ const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
929
+ assert.ok(committed);
930
+ const shardPath = casShardPath(s.source.dir, committed.path);
931
+ const relative = path.relative(s.source.dir, committed.path).split(path.sep).join("/");
932
+ // A pending marker whose expected digest matches nothing: lazy recovery
933
+ // cannot decide it, so the receipt reads UNAVAILABLE and the promotion
934
+ // must refuse rather than confirm against an unknown identity.
935
+ await writeFile(
936
+ shardPath,
937
+ `${JSON.stringify({
938
+ version: 1,
939
+ path: relative,
940
+ revision: "2026-08-23T00:00:00.001Z",
941
+ state: "pending",
942
+ previous: payload.committedRevision ?? "2026-08-23T00:00:00.000Z",
943
+ baselineDigest: "0".repeat(64),
944
+ expectedDigest: "1".repeat(64),
945
+ })}\n`,
946
+ "utf8",
947
+ );
948
+
949
+ assert.equal(
950
+ await runPromotion(s, payload, target.id),
951
+ 0,
952
+ "a pending (recovery-needed) receipt must not confirm the payload",
953
+ );
954
+ });
955
+
956
+ test("a legacy shard without a stored semantic fingerprint keeps the conservative digest refusal (#2870)", async () => {
957
+ const s = await makeStorages();
958
+ const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
959
+ source: "test",
960
+ confidence: 0.5,
961
+ });
962
+ await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
963
+ const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
964
+ assert.ok(committed);
965
+ // Downgrade the shard to its pre-#2870 shape: committed digest, no
966
+ // semantic fingerprint.
967
+ const shardPath = casShardPath(s.source.dir, committed.path);
968
+ const shard = JSON.parse(await readFile(shardPath, "utf8")) as Record<string, unknown>;
969
+ delete shard.committedSemanticFingerprint;
970
+ await writeFile(shardPath, `${JSON.stringify(shard)}\n`, "utf8");
971
+
972
+ assert.equal(await flushAccess(s.source, target.id, 4), 1, "the access flush lands on the legacy shard");
973
+ const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
974
+ targetId: target.id,
975
+ mergedContent: A_MERGED_BODY,
976
+ provenancePatched: true,
977
+ });
978
+ assert.equal(payload, null, "legacy shards keep the full-digest binding until the next semantic write");
979
+ assert.equal(readFailed, true);
980
+ });
981
+
982
+ test("legacy receipt with unavailable snapshot digest refuses promotion (#2813 P1, #2870)", async () => {
761
983
  const s = await makeStorages();
762
984
  const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, { source: "test" });
763
985
  await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
@@ -769,6 +991,10 @@ test("buildMergedTargetPromotionPayload: unavailable snapshot digest refuses whe
769
991
  status.status === "present" && status.committedDigest,
770
992
  "the standing receipt carries a committed digest",
771
993
  );
994
+ const shardPath = casShardPath(s.source.dir, committedRow.path);
995
+ const shard = JSON.parse(await readFile(shardPath, "utf8")) as Record<string, unknown>;
996
+ delete shard.committedSemanticFingerprint;
997
+ await writeFile(shardPath, `${JSON.stringify(shard)}\n`, "utf8");
772
998
 
773
999
  s.source.readDurableFileDigest = async () => null;
774
1000
  const built = await buildMergedTargetPromotionPayload(s.source, {
@@ -776,7 +1002,7 @@ test("buildMergedTargetPromotionPayload: unavailable snapshot digest refuses whe
776
1002
  mergedContent: A_MERGED_BODY,
777
1003
  provenancePatched: true,
778
1004
  });
779
- assert.equal(built.payload, null, "an unreadable snapshot digest must refuse the promotion");
1005
+ assert.equal(built.payload, null, "an unreadable snapshot digest must refuse the legacy receipt");
780
1006
  assert.equal(built.readFailed, true, "unavailable snapshot is unknown, not an absent revision");
781
1007
 
782
1008
  const legacyStore = await makeStorages();