@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
@@ -19,7 +19,12 @@ import { chmodSync, chownSync, lstatSync, mkdirSync, readFileSync, realpathSync,
19
19
  import path from "node:path";
20
20
 
21
21
  import { expandTildePath } from "../utils/path.js";
22
- import { applyManagedRegion, fileLines } from "./vault-publish.js";
22
+ import { applyManagedRegion, fileLines, headingSurvivesRoundTrip } from "./vault-publish.js";
23
+ import {
24
+ renderVaultPropertyValue,
25
+ validateVaultProperties,
26
+ type VaultPropertyValue,
27
+ } from "./vault-frontmatter.js";
23
28
  import { insertMarkersUnderHeading } from "./vault-insert.js";
24
29
  import { validateRegionName } from "./vault-region.js";
25
30
  import { assertBeginEndPair } from "./vault-region-pair.js";
@@ -37,8 +42,8 @@ export interface VaultSectionPublish {
37
42
  name: string;
38
43
  /** Rendered artifact body the region owns. */
39
44
  content: string;
40
- /** Unprefixed stats, e.g. `{ focus_minutes: "220" }`; keys get the configured prefix. */
41
- properties?: Readonly<Record<string, string>>;
45
+ /** Unprefixed stats, e.g. `{ focus_minutes: "220" }`; keys get the configured prefix. Values are plain single-line scalars or lists of them (vault-frontmatter.ts). */
46
+ properties?: Readonly<Record<string, VaultPropertyValue>>;
42
47
  /** When present, a provenance footer line is appended inside the region. */
43
48
  provenance?: VaultSectionProvenance;
44
49
  }
@@ -97,6 +102,48 @@ export function publishVaultNote(input: PublishVaultNoteInput): VaultPublishStat
97
102
  }
98
103
  }
99
104
 
105
+
106
+ // Issue #2917: input boundaries are total and run BEFORE any note byte
107
+ // is read or written, so a rejection can never leave a half-merged
108
+ // note behind.
109
+
110
+ // The heading strategy matches a section by scanning note headings with
111
+ // the shared ATX parser (`applyHeadingRegion`/`insertMarkersUnderHeading`).
112
+ // A name whose rendered heading parses back to something else — a
113
+ // trailing `#` run is stripped as a closing sequence (`## Timeline #`
114
+ // reads as `Timeline`) — can never be matched, so every publish would
115
+ // no-op or mis-scope. Reject it here rather than at match time.
116
+ const headingsToProbe =
117
+ strategy === "heading" ? input.sections.map((section) => section.name) : [];
118
+ if (typeof input.insertUnderHeading === "string" && input.insertUnderHeading.length > 0) {
119
+ headingsToProbe.push(input.insertUnderHeading);
120
+ }
121
+ for (const headingName of headingsToProbe) {
122
+ if (!headingSurvivesRoundTrip(headingName)) {
123
+ throw new RangeError(
124
+ `Section name ${JSON.stringify(headingName)} is not matchable by the heading parser; it must survive a render-and-parse round trip.`,
125
+ );
126
+ }
127
+ }
128
+
129
+ // Property values land in note frontmatter or inline fields; validate
130
+ // their shape and bounds (vault-frontmatter.ts) against the final
131
+ // prefixed keys, in every mode, before any file access.
132
+ const propertyEntries: Array<{ key: string; value: VaultPropertyValue }> = [];
133
+ for (const section of input.sections) {
134
+ if (!section.properties) continue;
135
+ for (const key of Object.keys(section.properties)) {
136
+ const value = section.properties[key];
137
+ if (value === undefined) continue;
138
+ propertyEntries.push({ key: `${prefix}${key}`, value });
139
+ }
140
+ }
141
+ if (propertyEntries.length > 0) {
142
+ const checked = validateVaultProperties(propertyEntries);
143
+ if (!checked.ok) {
144
+ throw new RangeError(`Vault publish properties rejected: ${checked.reason}.`);
145
+ }
146
+ }
100
147
  const relative = resolveVaultNotePath(input.notePathTemplate, input.date);
101
148
  const result = publishRelative(input, relative, { strategy, propertiesMode, prefix });
102
149
  return summarizeVaultPublish(result);
@@ -262,13 +309,13 @@ function refuse(relative: string, outcome: "skipped" | "error", reason: string):
262
309
 
263
310
  function decorate(
264
311
  section: VaultSectionPublish,
265
- prefixed: Record<string, string> | undefined,
312
+ prefixed: Record<string, VaultPropertyValue> | undefined,
266
313
  mode: string,
267
314
  ): string {
268
315
  const parts: string[] = [section.content];
269
316
  if (prefixed !== undefined && mode === "dataview-inline") {
270
317
  for (const [key, value] of Object.entries(prefixed)) {
271
- parts.push(`${key}:: ${value}`);
318
+ parts.push(`${key}:: ${renderVaultPropertyValue(value)}`);
272
319
  }
273
320
  }
274
321
  if (section.provenance !== undefined) {
@@ -388,8 +435,8 @@ function looksLikeRemnicMarkerLine(trimmed: string): boolean {
388
435
  function frontmatterUpdates(
389
436
  sections: readonly VaultSectionPublish[],
390
437
  prefix: string,
391
- ): Record<string, string> {
392
- const updates: Record<string, string> = {};
438
+ ): Record<string, VaultPropertyValue> {
439
+ const updates: Record<string, VaultPropertyValue> = {};
393
440
  for (const section of sections) {
394
441
  if (!section.properties) continue;
395
442
  for (const [key, value] of Object.entries(section.properties)) {
@@ -406,14 +453,16 @@ function frontmatterUpdates(
406
453
  */
407
454
  export function mergeFrontmatterKeys(
408
455
  noteText: string,
409
- updates: Readonly<Record<string, string>>,
456
+ updates: Readonly<Record<string, VaultPropertyValue>>,
410
457
  ): { ok: true; text: string } | { ok: false; reason: string } {
411
458
  const entries = Object.entries(updates);
412
459
  if (entries.length === 0) return { ok: true, text: noteText };
413
- for (const [key] of entries) {
414
- if (key.includes("\n") || key.includes("\r") || key.trim() !== key || key.length === 0) {
415
- return { ok: false, reason: "invalid_property_key" };
416
- }
460
+ // The writer re-validates the same boundary the publisher entry checked
461
+ // (issue #2917): this function is exported, so a direct caller must not
462
+ // be able to smuggle a newline-bearing or unbounded value into a note.
463
+ const checked = validateVaultProperties(entries.map(([key, value]) => ({ key, value })));
464
+ if (!checked.ok) {
465
+ return { ok: false, reason: "invalid_property" };
417
466
  }
418
467
 
419
468
  const eol = noteText.includes("\r\n") ? "\r\n" : "\n";
@@ -422,7 +471,12 @@ export function mergeFrontmatterKeys(
422
471
  const firstLine = firstLineEnd === -1 ? noteText : noteText.slice(0, firstLineEnd);
423
472
 
424
473
  if (!openRe.test(firstLine)) {
425
- const block = ["---", ...entries.map(([key, value]) => `${key}: ${value}`), "---", ""].join(eol);
474
+ const block = [
475
+ "---",
476
+ ...entries.map(([key, value]) => `${key}: ${renderVaultPropertyValue(value)}`),
477
+ "---",
478
+ "",
479
+ ].join(eol);
426
480
  return { ok: true, text: block + eol + noteText };
427
481
  }
428
482
 
@@ -451,13 +505,13 @@ export function mergeFrontmatterKeys(
451
505
  if (rawKey !== rawKey.trimStart()) continue;
452
506
  const key = rawKey.trimEnd();
453
507
  if (!pending.has(key)) continue;
454
- lines[i] = `${rawKey}: ${pending.get(key)}`;
508
+ lines[i] = `${rawKey}: ${renderVaultPropertyValue(pending.get(key)!)}`;
455
509
  pending.delete(key);
456
510
  }
457
511
  const insertAt = closeIdx;
458
512
  const added: string[] = [];
459
513
  for (const [key, value] of pending.entries()) {
460
- added.push(`${key}: ${value}`);
514
+ added.push(`${key}: ${renderVaultPropertyValue(value)}`);
461
515
  }
462
516
  lines.splice(insertAt, 0, ...added);
463
517
  return { ok: true, text: lines.join(eol) };
@@ -3,9 +3,14 @@ import test from "node:test";
3
3
 
4
4
  import { validateRegionName } from "./vault-region.js";
5
5
 
6
- test("validateRegionName trims a valid name", () => {
6
+ test("validateRegionName accepts a valid name unchanged", () => {
7
7
  assert.deepEqual(validateRegionName("timeline"), { ok: true, name: "timeline" });
8
- assert.deepEqual(validateRegionName(" weekly "), { ok: true, name: "weekly" });
8
+ });
9
+
10
+ test("validateRegionName rejects whitespace-padded names instead of trimming them (#2917)", () => {
11
+ assert.deepEqual(validateRegionName(" weekly"), { ok: false, error: "invalid_name" });
12
+ assert.deepEqual(validateRegionName("weekly "), { ok: false, error: "invalid_name" });
13
+ assert.deepEqual(validateRegionName(" weekly "), { ok: false, error: "invalid_name" });
9
14
  });
10
15
 
11
16
  test("validateRegionName rejects empty and whitespace-only names", () => {
@@ -8,6 +8,10 @@
8
8
  * or as name `A` with a `B:start` suffix) and a publisher that resolved
9
9
  * that ambiguity differently from the note's own markers would pair a
10
10
  * start with a later end and delete the user bytes in between.
11
+ *
12
+ * Whitespace-padded names are rejected, not trimmed (issue #2917): the
13
+ * old silent trim validated one name and wrote another, so markers and
14
+ * heading matches were computed against bytes the caller never saw.
11
15
  */
12
16
 
13
17
  export type ValidateRegionNameResult =
@@ -21,9 +25,9 @@ export function validateRegionName(name: string): ValidateRegionNameResult {
21
25
  if (name.includes("\n") || name.includes("\r") || name.includes("-->") || name.includes(":")) {
22
26
  return { ok: false, error: "invalid_name" };
23
27
  }
24
- const trimmed = name.trim();
25
- if (trimmed.length === 0) {
28
+ if (name.trim() !== name || name.trim().length === 0) {
26
29
  return { ok: false, error: "invalid_name" };
27
30
  }
28
- return { ok: true, name: trimmed };
31
+ return { ok: true, name };
29
32
  }
33
+
@@ -1,4 +1,7 @@
1
+ import { readFileSync } from "node:fs";
2
+
1
3
  import { isLoopbackHost } from "./runtime/http-transport.js";
4
+ import { expandTildePath } from "./utils/path.js";
2
5
 
3
6
  export interface BackgroundGenerationConfig {
4
7
  /** Full chat-completions URL. Never used as the global OpenAI base URL. */
@@ -54,14 +57,13 @@ function parseBackgroundGenerationObject(
54
57
  if (typeof tokenRaw !== "string" || tokenRaw.length === 0) {
55
58
  throw new Error(`${keyName} must include a token`);
56
59
  }
57
- const timeoutRaw = record.timeoutSeconds;
60
+ const timeoutRaw = record.timeoutSeconds ?? record.timeout_seconds;
58
61
  let timeoutSeconds = 120;
59
62
  if (timeoutRaw !== undefined) {
60
- const parsed = typeof timeoutRaw === "number" ? timeoutRaw : Number(timeoutRaw);
61
- if (!Number.isFinite(parsed) || parsed <= 0) {
63
+ if (typeof timeoutRaw !== "number" || !Number.isFinite(timeoutRaw) || timeoutRaw <= 0) {
62
64
  throw new Error(`${keyName} timeoutSeconds must be a finite number > 0`);
63
65
  }
64
- timeoutSeconds = parsed;
66
+ timeoutSeconds = timeoutRaw;
65
67
  }
66
68
  return {
67
69
  endpoint: parseBackgroundEndpoint(endpointRaw, `${keyName}.endpoint`),
@@ -72,8 +74,32 @@ function parseBackgroundGenerationObject(
72
74
 
73
75
  export function parseBackgroundGeneration(
74
76
  cfg: Record<string, unknown>,
77
+ expandEnv: (value: string) => string,
75
78
  ): BackgroundGenerationConfig | undefined {
79
+ const pathRaw = cfg.llmBridgeClientConfigPath;
80
+ let fromFile: BackgroundGenerationConfig | undefined;
81
+ if (pathRaw !== undefined && pathRaw !== null && pathRaw !== "") {
82
+ if (typeof pathRaw !== "string") {
83
+ throw new Error("llmBridgeClientConfigPath must be a string");
84
+ }
85
+ const expanded = expandTildePath(expandEnv(pathRaw.trim()));
86
+ let parsed: unknown;
87
+ try {
88
+ parsed = JSON.parse(readFileSync(expanded, "utf8"));
89
+ } catch {
90
+ throw new Error(`llmBridgeClientConfigPath could not be read: ${expanded}`);
91
+ }
92
+ fromFile = parseBackgroundGenerationObject(parsed, "llmBridgeClientConfigPath");
93
+ }
76
94
  const explicitRaw = cfg.backgroundGeneration;
77
- if (explicitRaw === undefined || explicitRaw === null) return undefined;
78
- return parseBackgroundGenerationObject(explicitRaw, "backgroundGeneration");
95
+ const fromExplicit =
96
+ explicitRaw === undefined || explicitRaw === null
97
+ ? undefined
98
+ : parseBackgroundGenerationObject(explicitRaw, "backgroundGeneration");
99
+ if (!fromFile && !fromExplicit) return undefined;
100
+ return {
101
+ endpoint: fromExplicit?.endpoint ?? fromFile!.endpoint,
102
+ token: fromExplicit?.token ?? fromFile!.token,
103
+ timeoutSeconds: fromExplicit?.timeoutSeconds ?? fromFile!.timeoutSeconds,
104
+ };
79
105
  }
@@ -83,11 +83,13 @@ test("HourlySummarizer uses backgroundGeneration and not openaiBaseUrl", async (
83
83
  timeoutSeconds: 12,
84
84
  },
85
85
  });
86
- globalThis.fetch = (async (url) => {
86
+ let sentBody: string | undefined;
87
+ globalThis.fetch = (async (url, init) => {
87
88
  calls.push(String(url));
88
89
  if (String(url) !== "http://127.0.0.1:8765/v1/chat/completions") {
89
90
  return new Response("not the bridge", { status: 404 });
90
91
  }
92
+ sentBody = String(init?.body);
91
93
  return new Response(
92
94
  JSON.stringify({
93
95
  choices: [{ message: { content: '{"bullets":["bridge-only"]}' } }],
@@ -114,6 +116,13 @@ test("HourlySummarizer uses backgroundGeneration and not openaiBaseUrl", async (
114
116
  assert.deepEqual(summary?.bullets, ["bridge-only"]);
115
117
  assert.deepEqual(calls, ["http://127.0.0.1:8765/v1/chat/completions"]);
116
118
  assert.equal(config.openaiBaseUrl, "http://127.0.0.1:9999/v1");
119
+ // The bridge prompt must spell out the required JSON shape; without it a
120
+ // literal host model returns {"summary": "..."} and the schema rejects it.
121
+ const sent = JSON.parse(String(sentBody)) as {
122
+ messages: Array<{ role: string; content: string }>;
123
+ };
124
+ const system = sent.messages.find((message) => message.role === "system")?.content ?? "";
125
+ assert.match(system, /"bullets"/);
117
126
  } finally {
118
127
  globalThis.fetch = previousFetch;
119
128
  if (previousXdg === undefined) delete process.env.XDG_CONFIG_HOME;
@@ -23,6 +23,15 @@ export function registerTimelineCommands(cmd: CliCommand, orchestrator: Orchestr
23
23
  .option("--what <kinds>", "Comma-separated artifacts to publish (default: timeline)")
24
24
  .option("--dry-run", "Report per-file outcomes without writing")
25
25
  .action((...args: unknown[]) => {
26
+ // Commander passes declared positional args before the options
27
+ // object; `publish` declares none, so a stray positional would
28
+ // displace the options object and silently publish with defaults
29
+ // (issue #2917). Reject any string arg outright.
30
+ if (args.some((arg) => typeof arg === "string")) {
31
+ process.stderr.write("timeline publish takes no positional arguments.\n");
32
+ process.exitCode = 1;
33
+ return;
34
+ }
26
35
  const options = (args[0] ?? {}) as Record<string, unknown>;
27
36
  const code = runTimelinePublishCli(orchestrator.config, options, {
28
37
  stdout: process.stdout,
@@ -2724,21 +2724,88 @@ test("parseConfig coerces string-typed sharedContextAllowBindingAuthority from t
2724
2724
  );
2725
2725
  }
2726
2726
  });
2727
+ test("parseConfig coerces string-typed sharedContextEnabled from the CLI", () => {
2728
+ // `--config sharedContextEnabled=true` arrives as a string, so a strict
2729
+ // `=== true` silently left the feature off for anyone who enabled it.
2730
+ // Parity with sharedContextAllowBindingAuthority (issue #2918).
2731
+ // The default recall-pipeline shared-context gate must use the same
2732
+ // coerced boolean — string true with no custom pipeline enables the
2733
+ // section; false/malformed stay off.
2734
+ for (const enabled of ["true", "1", "yes", "on", true]) {
2735
+ const parsed = parseConfig({ sharedContextEnabled: enabled });
2736
+ assert.equal(
2737
+ parsed.sharedContextEnabled,
2738
+ true,
2739
+ `${JSON.stringify(enabled)} must enable shared context`,
2740
+ );
2741
+ assert.equal(
2742
+ parsed.recallPipeline.find((section) => section.id === "shared-context")?.enabled,
2743
+ true,
2744
+ `${JSON.stringify(enabled)} must enable the default shared-context section`,
2745
+ );
2746
+ }
2747
+ for (const disabled of ["false", "0", "no", "off", false, undefined, "", "garbage"]) {
2748
+ const parsed = parseConfig({ sharedContextEnabled: disabled });
2749
+ assert.equal(
2750
+ parsed.sharedContextEnabled,
2751
+ false,
2752
+ `${JSON.stringify(disabled)} must leave shared context off (malformed input never activates)`,
2753
+ );
2754
+ assert.equal(
2755
+ parsed.recallPipeline.find((section) => section.id === "shared-context")?.enabled,
2756
+ false,
2757
+ `${JSON.stringify(disabled)} must leave the default shared-context section off`,
2758
+ );
2759
+ }
2760
+ });
2761
+
2762
+ test("custom recallPipeline keeps operator shared-context enabled (#2918)", () => {
2763
+ const customOff = parseConfig({
2764
+ sharedContextEnabled: "true",
2765
+ recallPipeline: [{ id: "shared-context", enabled: false, maxChars: 1000 }],
2766
+ });
2767
+ assert.equal(customOff.sharedContextEnabled, true);
2768
+ assert.equal(
2769
+ customOff.recallPipeline.find((section) => section.id === "shared-context")?.enabled,
2770
+ false,
2771
+ "custom pipeline must not silently activate shared-context",
2772
+ );
2773
+
2774
+ const customOn = parseConfig({
2775
+ sharedContextEnabled: "false",
2776
+ recallPipeline: [{ id: "shared-context", enabled: true, maxChars: 1000 }],
2777
+ });
2778
+ assert.equal(customOn.sharedContextEnabled, false);
2779
+ assert.equal(
2780
+ customOn.recallPipeline.find((section) => section.id === "shared-context")?.enabled,
2781
+ true,
2782
+ "custom pipeline enabled stays as specified",
2783
+ );
2784
+ });
2727
2785
 
2728
- test("parseConfig consumes backgroundGeneration and leaves openaiBaseUrl untouched", () => {
2786
+
2787
+ test("parseConfig consumes llmBridgeClientConfigPath into backgroundGeneration only", () => {
2729
2788
  withIsolatedConnectorsDir(false, () => {
2789
+ const dir = mkdtempSync(path.join(tmpdir(), "remnic-llm-bridge-client-"));
2730
2790
  const previousKey = process.env.OPENAI_API_KEY;
2731
2791
  const previousBase = process.env.OPENAI_BASE_URL;
2732
2792
  delete process.env.OPENAI_API_KEY;
2733
2793
  delete process.env.OPENAI_BASE_URL;
2734
2794
  try {
2735
- const parsed = parseConfig({
2736
- backgroundGeneration: {
2795
+ const file = path.join(dir, "client.json");
2796
+ writeFileSync(
2797
+ file,
2798
+ JSON.stringify({
2737
2799
  endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2800
+ health_endpoint: "http://127.0.0.1:8765/healthz",
2801
+ bind: "127.0.0.1",
2802
+ model_policy: "server-owned",
2803
+ max_body_bytes: 524288,
2804
+ timeout_seconds: 120,
2738
2805
  token: "bridge-token-fixture",
2739
- timeoutSeconds: 120,
2740
- },
2741
- });
2806
+ }),
2807
+ );
2808
+ const parsed = parseConfig({ llmBridgeClientConfigPath: file });
2742
2809
  assert.equal(parsed.openaiBaseUrl, undefined);
2743
2810
  assert.equal(parsed.openaiApiKey, undefined);
2744
2811
  assert.deepEqual(parsed.backgroundGeneration, {
@@ -2748,11 +2815,7 @@ test("parseConfig consumes backgroundGeneration and leaves openaiBaseUrl untouch
2748
2815
  });
2749
2816
 
2750
2817
  const explicitOpenAi = parseConfig({
2751
- backgroundGeneration: {
2752
- endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2753
- token: "bridge-token-fixture",
2754
- timeoutSeconds: 120,
2755
- },
2818
+ llmBridgeClientConfigPath: file,
2756
2819
  openaiBaseUrl: "http://127.0.0.1:9999/v1",
2757
2820
  openaiApiKey: "keep-me",
2758
2821
  });
@@ -2762,65 +2825,78 @@ test("parseConfig consumes backgroundGeneration and leaves openaiBaseUrl untouch
2762
2825
  explicitOpenAi.backgroundGeneration?.endpoint,
2763
2826
  "http://127.0.0.1:8765/v1/chat/completions",
2764
2827
  );
2828
+
2829
+ const explicitBg = parseConfig({
2830
+ backgroundGeneration: {
2831
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2832
+ token: "explicit-token",
2833
+ timeoutSeconds: 30,
2834
+ },
2835
+ });
2836
+ assert.equal(explicitBg.openaiBaseUrl, undefined);
2837
+ assert.deepEqual(explicitBg.backgroundGeneration, {
2838
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2839
+ token: "explicit-token",
2840
+ timeoutSeconds: 30,
2841
+ });
2765
2842
  } finally {
2766
2843
  if (previousKey === undefined) delete process.env.OPENAI_API_KEY;
2767
2844
  else process.env.OPENAI_API_KEY = previousKey;
2768
2845
  if (previousBase === undefined) delete process.env.OPENAI_BASE_URL;
2769
2846
  else process.env.OPENAI_BASE_URL = previousBase;
2847
+ rmSync(dir, { recursive: true, force: true });
2770
2848
  }
2771
2849
  });
2772
2850
  });
2773
2851
 
2774
- test("parseConfig ignores llmBridgeClientConfigPath", () => {
2775
- withIsolatedConnectorsDir(false, () => {
2776
- const parsed = parseConfig({
2777
- llmBridgeClientConfigPath: "/no/such/remnic-llm-bridge-client.json",
2778
- });
2779
- assert.equal(parsed.backgroundGeneration, undefined);
2780
- });
2781
- });
2782
-
2783
- test("parseConfig rejects backgroundGeneration without a token", () => {
2852
+ test("parseConfig rejects an unreadable llmBridgeClientConfigPath", () => {
2784
2853
  withIsolatedConnectorsDir(false, () => {
2785
2854
  assert.throws(
2786
- () =>
2787
- parseConfig({
2788
- backgroundGeneration: {
2789
- endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2790
- },
2791
- }),
2792
- /must include a token/,
2855
+ () => parseConfig({ llmBridgeClientConfigPath: "/no/such/remnic-llm-bridge-client.json" }),
2856
+ /llmBridgeClientConfigPath could not be read/,
2793
2857
  );
2794
2858
  });
2795
2859
  });
2796
2860
 
2797
- test("parseConfig ignores Hermes timeout_seconds on backgroundGeneration", () => {
2861
+ test("parseConfig rejects a bridge client file without a token", () => {
2798
2862
  withIsolatedConnectorsDir(false, () => {
2799
- const parsed = parseConfig({
2800
- backgroundGeneration: {
2801
- endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2802
- token: "bridge-token-fixture",
2803
- timeout_seconds: 45,
2804
- },
2805
- });
2806
- assert.equal(parsed.backgroundGeneration?.timeoutSeconds, 120);
2863
+ const dir = mkdtempSync(path.join(tmpdir(), "remnic-llm-bridge-client-"));
2864
+ try {
2865
+ const file = path.join(dir, "client.json");
2866
+ writeFileSync(
2867
+ file,
2868
+ JSON.stringify({
2869
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2870
+ }),
2871
+ );
2872
+ assert.throws(
2873
+ () => parseConfig({ llmBridgeClientConfigPath: file }),
2874
+ /must include a token/,
2875
+ );
2876
+ } finally {
2877
+ rmSync(dir, { recursive: true, force: true });
2878
+ }
2807
2879
  });
2808
2880
  });
2809
2881
 
2810
- test("parseConfig keeps env openaiBaseUrl isolated from backgroundGeneration", () => {
2882
+ test("parseConfig keeps env openaiBaseUrl isolated from the Hermes bridge", () => {
2811
2883
  withIsolatedConnectorsDir(false, () => {
2884
+ const dir = mkdtempSync(path.join(tmpdir(), "remnic-llm-bridge-env-"));
2812
2885
  const previousKey = process.env.OPENAI_API_KEY;
2813
2886
  const previousBase = process.env.OPENAI_BASE_URL;
2814
2887
  process.env.OPENAI_API_KEY = "env-openai-key";
2815
2888
  process.env.OPENAI_BASE_URL = "http://127.0.0.1:9999/v1";
2816
2889
  try {
2817
- const parsed = parseConfig({
2818
- backgroundGeneration: {
2890
+ const file = path.join(dir, "client.json");
2891
+ writeFileSync(
2892
+ file,
2893
+ JSON.stringify({
2819
2894
  endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2820
2895
  token: "bridge-token-fixture",
2821
- timeoutSeconds: 45,
2822
- },
2823
- });
2896
+ timeout_seconds: 45,
2897
+ }),
2898
+ );
2899
+ const parsed = parseConfig({ llmBridgeClientConfigPath: file });
2824
2900
  assert.equal(parsed.openaiBaseUrl, "http://127.0.0.1:9999/v1");
2825
2901
  assert.equal(parsed.openaiApiKey, "env-openai-key");
2826
2902
  assert.deepEqual(parsed.backgroundGeneration, {
@@ -2833,6 +2909,57 @@ test("parseConfig keeps env openaiBaseUrl isolated from backgroundGeneration", (
2833
2909
  else process.env.OPENAI_API_KEY = previousKey;
2834
2910
  if (previousBase === undefined) delete process.env.OPENAI_BASE_URL;
2835
2911
  else process.env.OPENAI_BASE_URL = previousBase;
2912
+ rmSync(dir, { recursive: true, force: true });
2913
+ }
2914
+ });
2915
+ });
2916
+
2917
+ test("parseConfig rejects nonnumeric bridge timeout values", () => {
2918
+ withIsolatedConnectorsDir(false, () => {
2919
+ assert.throws(
2920
+ () =>
2921
+ parseConfig({
2922
+ backgroundGeneration: {
2923
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2924
+ token: "t",
2925
+ timeoutSeconds: true,
2926
+ },
2927
+ }),
2928
+ /timeoutSeconds must be a finite number/,
2929
+ );
2930
+ assert.throws(
2931
+ () =>
2932
+ parseConfig({
2933
+ backgroundGeneration: {
2934
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2935
+ token: "t",
2936
+ timeout_seconds: "45",
2937
+ },
2938
+ }),
2939
+ /timeoutSeconds must be a finite number/,
2940
+ );
2941
+ });
2942
+ });
2943
+
2944
+ test("parseConfig rejects a bridge client file with a nonnumeric timeout", () => {
2945
+ withIsolatedConnectorsDir(false, () => {
2946
+ const dir = mkdtempSync(path.join(tmpdir(), "remnic-llm-bridge-badtimeout-"));
2947
+ try {
2948
+ const file = path.join(dir, "client.json");
2949
+ writeFileSync(
2950
+ file,
2951
+ JSON.stringify({
2952
+ endpoint: "http://127.0.0.1:8765/v1/chat/completions",
2953
+ token: "bridge-token-fixture",
2954
+ timeout_seconds: "45",
2955
+ }),
2956
+ );
2957
+ assert.throws(
2958
+ () => parseConfig({ llmBridgeClientConfigPath: file }),
2959
+ /timeoutSeconds must be a finite number/,
2960
+ );
2961
+ } finally {
2962
+ rmSync(dir, { recursive: true, force: true });
2836
2963
  }
2837
2964
  });
2838
2965
  });
package/src/config.ts CHANGED
@@ -25,6 +25,7 @@ import type {
25
25
  TriggerMode,
26
26
  TrustWeights,
27
27
  } from "./types.js";
28
+ import { parseBackgroundGeneration } from "./background-generation-config.js";
28
29
  import { parseLocalLlmConfig } from "./local-llm-config.js";
29
30
  import { parseConvergeConfig } from "./converge-config.js";
30
31
  import { parseExternalWikiRecallGuard } from "./external-wiki-guard.js";
@@ -519,6 +520,7 @@ function normalizeOpenaiBaseUrl(value: string | undefined, source: "config" | "e
519
520
  return url;
520
521
  }
521
522
 
523
+
522
524
  function normalizeMemoryRelativeDir(raw: unknown, fallback: string): string {
523
525
  if (typeof raw !== "string") return fallback;
524
526
  const trimmed = raw.trim();
@@ -1482,6 +1484,7 @@ export function parseConfig(
1482
1484
  } else if (apiKey !== undefined) {
1483
1485
  baseUrl = normalizeOpenaiBaseUrl(readEnvVar("OPENAI_BASE_URL"), "env");
1484
1486
  }
1487
+ const backgroundGeneration = parseBackgroundGeneration(cfg, resolveEnvVars);
1485
1488
 
1486
1489
  const sharedCrossSignalSemanticEnabled =
1487
1490
  cfg.sharedCrossSignalSemanticEnabled === true || cfg.crossSignalsSemanticEnabled === true;
@@ -1491,7 +1494,15 @@ export function parseConfig(
1491
1494
  : typeof cfg.crossSignalsSemanticTimeoutMs === "number"
1492
1495
  ? Math.max(1, Math.floor(cfg.crossSignalsSemanticTimeoutMs))
1493
1496
  : 4000;
1494
- const recallPipelineConfig = buildRecallPipelineConfig(cfg);
1497
+ // Coerce once. The default recall-pipeline shared-context gate reads
1498
+ // `cfg.sharedContextEnabled === true`, so it must see this boolean —
1499
+ // not the raw CLI/config string. Custom `recallPipeline` is unchanged.
1500
+ const sharedContextEnabled =
1501
+ coerceBool(cfg.sharedContextEnabled, "sharedContextEnabled") ?? false;
1502
+ const recallPipelineConfig = buildRecallPipelineConfig({
1503
+ ...cfg,
1504
+ sharedContextEnabled,
1505
+ });
1495
1506
  const maintenanceNamespaceFanoutEnabled = resolveBooleanConfig(
1496
1507
  readFlatOrNestedConfig(
1497
1508
  cfg,
@@ -1560,6 +1571,7 @@ export function parseConfig(
1560
1571
  return {
1561
1572
  openaiApiKey: apiKey,
1562
1573
  openaiBaseUrl: baseUrl,
1574
+ backgroundGeneration,
1563
1575
  model,
1564
1576
  reasoningEffort,
1565
1577
  triggerMode,
@@ -3003,10 +3015,9 @@ export function parseConfig(
3003
3015
  ? cfg.routingRulesStateFile.trim()
3004
3016
  : "state/routing-rules.json",
3005
3017
 
3006
- // v4.0 shared-context (default off)
3007
- sharedContextEnabled: cfg.sharedContextEnabled === true,
3008
- // CLI values arrive as strings (`--config sharedContextAllowBindingAuthority=true`),
3009
- // so a strict `=== true` silently keeps the feature off. Default stays false.
3018
+ // Reuse the hoisted coerce above (default pipeline already saw it).
3019
+ sharedContextEnabled,
3020
+ // Same coercion contract for the binding-authority sibling (#2918 parity).
3010
3021
  sharedContextAllowBindingAuthority:
3011
3022
  coerceBool(cfg.sharedContextAllowBindingAuthority, "sharedContextAllowBindingAuthority") ?? false,
3012
3023
  sharedContextDir:
@@ -4217,6 +4228,7 @@ function buildDefaultRecallPipeline(cfg: Record<string, unknown>): RecallSection
4217
4228
  return [
4218
4229
  {
4219
4230
  id: "shared-context",
4231
+ // Already coerced in parseConfig; do not coerce again.
4220
4232
  enabled: cfg.sharedContextEnabled === true,
4221
4233
  maxChars:
4222
4234
  typeof cfg.sharedContextMaxInjectChars === "number"