@remnic/core 10.0.91 → 10.0.93

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 (522) hide show
  1. package/dist/access-admin-ops-surface.js +334 -61
  2. package/dist/access-authorization-probe.js +2 -283
  3. package/dist/access-boundary.d.ts +1 -1
  4. package/dist/access-boundary.d.ts.map +1 -1
  5. package/dist/access-boundary.js +1 -282
  6. package/dist/access-cli.js +288 -304
  7. package/dist/access-cli.js.map +1 -1
  8. package/dist/access-coding-context-resolution.js +3 -3
  9. package/dist/access-extraction-force-flush.js +334 -61
  10. package/dist/access-http-briefing.js +334 -62
  11. package/dist/access-http-query.js +334 -63
  12. package/dist/access-http.js +332 -114
  13. package/dist/access-identity-continuity-surface.js +334 -61
  14. package/dist/access-lcm-surface.js +334 -61
  15. package/dist/access-mcp-frames.d.ts +20 -6
  16. package/dist/access-mcp-frames.d.ts.map +1 -1
  17. package/dist/access-mcp-frames.js +1 -1
  18. package/dist/access-mcp.d.ts +5 -0
  19. package/dist/access-mcp.d.ts.map +1 -1
  20. package/dist/access-mcp.js +332 -89
  21. package/dist/access-namespace-preflight.js +2 -282
  22. package/dist/access-observe-transcript.js +3 -3
  23. package/dist/access-observe-write-category.js +6 -6
  24. package/dist/access-observe-write-surface.js +334 -61
  25. package/dist/access-offline-manifest.js +12 -11
  26. package/dist/access-operations-batch.js +332 -66
  27. package/dist/access-operations.js +332 -75
  28. package/dist/access-recall-concurrency.js +334 -61
  29. package/dist/access-recall-diagnostics.js +6 -5
  30. package/dist/access-recall-response.js +334 -61
  31. package/dist/access-recall-surface.js +334 -61
  32. package/dist/access-schema.js +2 -2
  33. package/dist/access-service.d.ts +1 -0
  34. package/dist/access-service.d.ts.map +1 -1
  35. package/dist/access-service.js +337 -64
  36. package/dist/access-surface-catalog.js +6 -283
  37. package/dist/access-surface-catalog.js.map +1 -1
  38. package/dist/active-context-transform.js +1 -1
  39. package/dist/active-memory-bridge.js +3 -2
  40. package/dist/active-recall.js +36 -37
  41. package/dist/active-recall.js.map +1 -1
  42. package/dist/activity/journal-extract.d.ts +13 -1
  43. package/dist/activity/journal-extract.d.ts.map +1 -1
  44. package/dist/{auto-sync-3AZW7MXI.js → auto-sync-BO5YZKM6.js} +13 -15
  45. package/dist/{auto-sync-3AZW7MXI.js.map → auto-sync-BO5YZKM6.js.map} +1 -1
  46. package/dist/briefing.js +20 -20
  47. package/dist/buffer.js +16 -16
  48. package/dist/calibration.js +10 -10
  49. package/dist/{capsule-merge-2IIXFXN5.js → capsule-merge-6IDAYTKG.js} +6 -6
  50. package/dist/causal-consolidation.js +23 -23
  51. package/dist/{chunk-QL7RHYK6.js → chunk-2LMA22UU.js} +5 -5
  52. package/dist/{chunk-RGUUBAT5.js → chunk-2WCLTWV2.js} +3 -3
  53. package/dist/{chunk-RSK2WIEM.js → chunk-2YODOG2O.js} +2 -2
  54. package/dist/{chunk-WYG5UNDY.js → chunk-3AUDELZL.js} +2 -2
  55. package/dist/{chunk-OFVCFKDH.js → chunk-3CYOCE6U.js} +3 -3
  56. package/dist/{chunk-6HM6HARE.js → chunk-3FBAEPCU.js} +2 -2
  57. package/dist/{chunk-PIITB2YZ.js → chunk-3ZS3NUEI.js} +4 -4
  58. package/dist/{chunk-V4XE263I.js → chunk-43AA5FVD.js} +1 -1
  59. package/dist/chunk-43AA5FVD.js.map +1 -0
  60. package/dist/{chunk-ANZZLRUX.js → chunk-4IVRQMZW.js} +2 -2
  61. package/dist/{chunk-63E37JCN.js → chunk-4RAJT5L2.js} +4 -4
  62. package/dist/{chunk-45VUHDV2.js → chunk-5CO5G4MN.js} +2 -2
  63. package/dist/{chunk-PUEO37QG.js → chunk-5YT2IIFX.js} +729 -17
  64. package/dist/chunk-5YT2IIFX.js.map +1 -0
  65. package/dist/{chunk-P5VZSSYL.js → chunk-622V2AZA.js} +233 -40
  66. package/dist/chunk-622V2AZA.js.map +1 -0
  67. package/dist/{chunk-3UMDRGFS.js → chunk-65HWAQ4F.js} +3 -3
  68. package/dist/{chunk-T67LUYCR.js → chunk-77NTFICT.js} +5 -5
  69. package/dist/chunk-A2WFUMUN.js +86 -0
  70. package/dist/chunk-A2WFUMUN.js.map +1 -0
  71. package/dist/{chunk-UE6RRXMF.js → chunk-A4F7OIC5.js} +2 -2
  72. package/dist/chunk-AHA5VQGP.js +117 -0
  73. package/dist/chunk-AHA5VQGP.js.map +1 -0
  74. package/dist/{chunk-AOFEMUHG.js → chunk-ATG2PQ4V.js} +56 -5
  75. package/dist/chunk-ATG2PQ4V.js.map +1 -0
  76. package/dist/{chunk-63O7LVMN.js → chunk-B33YWUJV.js} +3 -3
  77. package/dist/{chunk-QVMOCJRV.js → chunk-B377OKUP.js} +2 -2
  78. package/dist/{chunk-IUKYFTGW.js → chunk-B3DR2JBZ.js} +140 -125
  79. package/dist/chunk-B3DR2JBZ.js.map +1 -0
  80. package/dist/{chunk-ZT6WPSII.js → chunk-BGHCSLE5.js} +2 -2
  81. package/dist/{chunk-YYOMGOHB.js → chunk-BOK6BN5M.js} +2 -2
  82. package/dist/{chunk-OH7QLI6W.js → chunk-BPPUH5JM.js} +5 -5
  83. package/dist/{chunk-EV76IZ37.js → chunk-BTI4C4MA.js} +2 -2
  84. package/dist/{chunk-O6ZSWHVR.js → chunk-C2KE5DMD.js} +4 -4
  85. package/dist/{chunk-47F6WWLQ.js → chunk-C73N66PR.js} +2 -2
  86. package/dist/{chunk-3XIWW4TB.js → chunk-CGJYL633.js} +2 -2
  87. package/dist/{chunk-WRT7GJ2D.js → chunk-CIWMTNHW.js} +4 -4
  88. package/dist/{chunk-O55EKIEC.js → chunk-D3ZKHLN2.js} +2 -2
  89. package/dist/{chunk-CD4BCCNP.js → chunk-DJ7WVEWX.js} +2 -2
  90. package/dist/{chunk-RO7RUBLD.js → chunk-EFL24KOI.js} +2 -2
  91. package/dist/{chunk-4CJTQHEG.js → chunk-ESLOLCD4.js} +3 -3
  92. package/dist/{chunk-Z4Q6USKJ.js → chunk-ETBVCRVL.js} +4 -4
  93. package/dist/{chunk-VILPVT4S.js → chunk-EZ47HOJ6.js} +4 -4
  94. package/dist/{chunk-EFYN5I7Z.js → chunk-F4QFU5IZ.js} +2 -2
  95. package/dist/{chunk-T6OZW2WR.js → chunk-FA7SLQ5X.js} +7 -1
  96. package/dist/chunk-FA7SLQ5X.js.map +1 -0
  97. package/dist/{chunk-SHUBTAY2.js → chunk-FMKILENU.js} +14 -14
  98. package/dist/{chunk-YLXETSAH.js → chunk-GCZJ7XRI.js} +2 -2
  99. package/dist/{chunk-J4MMPQ7Q.js → chunk-GQXOBKPL.js} +7 -9
  100. package/dist/{chunk-J4MMPQ7Q.js.map → chunk-GQXOBKPL.js.map} +1 -1
  101. package/dist/{chunk-UDKWFDV2.js → chunk-HLUHEMN4.js} +27 -3
  102. package/dist/chunk-HLUHEMN4.js.map +1 -0
  103. package/dist/{chunk-QFEDITXM.js → chunk-JNDMIAJ4.js} +2 -2
  104. package/dist/chunk-JTSSSR4L.js +359 -0
  105. package/dist/chunk-JTSSSR4L.js.map +1 -0
  106. package/dist/{chunk-5KBIOI4G.js → chunk-JVBAPAWZ.js} +217 -13
  107. package/dist/chunk-JVBAPAWZ.js.map +1 -0
  108. package/dist/{chunk-E5PPE4VA.js → chunk-K2VRKCPA.js} +2 -2
  109. package/dist/{chunk-MKRYQROF.js → chunk-LGEHAQHK.js} +4 -4
  110. package/dist/{chunk-7HTUYFR3.js → chunk-LLPMMMWG.js} +27 -10
  111. package/dist/chunk-LLPMMMWG.js.map +1 -0
  112. package/dist/{chunk-XYTQJD7F.js → chunk-LMJVP5CM.js} +2 -2
  113. package/dist/{chunk-JC36FPQ5.js → chunk-LPV72KRQ.js} +2 -2
  114. package/dist/{chunk-2LCRG2YV.js → chunk-M2XR6B6V.js} +2 -2
  115. package/dist/{chunk-GGRRF4PZ.js → chunk-MDPT6QFK.js} +1 -1
  116. package/dist/{chunk-GGRRF4PZ.js.map → chunk-MDPT6QFK.js.map} +1 -1
  117. package/dist/{chunk-VPQFK63H.js → chunk-MH632KPO.js} +2 -2
  118. package/dist/{chunk-EQ4U73UH.js → chunk-MLAMXQAW.js} +14 -2
  119. package/dist/chunk-MLAMXQAW.js.map +1 -0
  120. package/dist/{chunk-ZU5JDLOH.js → chunk-MMRTPH3J.js} +2 -2
  121. package/dist/{chunk-ZZ67UTQX.js → chunk-MUX7IL77.js} +2 -2
  122. package/dist/{chunk-RYWROSL5.js → chunk-NAQ4A5IX.js} +7 -7
  123. package/dist/{chunk-TVIVY7KU.js → chunk-NED7IR7B.js} +4 -4
  124. package/dist/{chunk-ADYP7HXE.js → chunk-NHVAX7MH.js} +3 -3
  125. package/dist/{chunk-TG3R2SID.js → chunk-NMGHGTVR.js} +5 -5
  126. package/dist/{chunk-YCNIGRRF.js → chunk-NS7U4ZYU.js} +13 -117
  127. package/dist/chunk-NS7U4ZYU.js.map +1 -0
  128. package/dist/{chunk-NGHDW6UU.js → chunk-NUQEREIP.js} +2 -2
  129. package/dist/{chunk-5IIQU4JZ.js → chunk-OB72KNMF.js} +4 -4
  130. package/dist/{chunk-7L3TODI7.js → chunk-OJXJWNFY.js} +2 -2
  131. package/dist/{chunk-66L5ZRJC.js → chunk-P3WRNWWM.js} +157 -4
  132. package/dist/chunk-P3WRNWWM.js.map +1 -0
  133. package/dist/{chunk-E6M225BJ.js → chunk-PC5DRBGD.js} +18 -8
  134. package/dist/chunk-PC5DRBGD.js.map +1 -0
  135. package/dist/{chunk-EURPSF4Y.js → chunk-PH5ZQM35.js} +2 -2
  136. package/dist/{chunk-BMWMTAQF.js → chunk-PRAUN6PN.js} +3 -3
  137. package/dist/{chunk-RWGRSKN5.js → chunk-PT4DZDJA.js} +2 -2
  138. package/dist/{chunk-7EPY3IQL.js → chunk-PZJQ46DH.js} +2 -2
  139. package/dist/{chunk-AH637HZ5.js → chunk-QDESY76F.js} +3 -3
  140. package/dist/{chunk-I6QGI65T.js → chunk-QRMG4HK4.js} +3 -3
  141. package/dist/{chunk-ZU3NJNO7.js → chunk-QSF5SJAM.js} +4 -4
  142. package/dist/{chunk-5IYOKDM4.js → chunk-R23JWJD3.js} +5 -5
  143. package/dist/{chunk-EWJZZDRG.js → chunk-R4BBGPI2.js} +219 -219
  144. package/dist/chunk-R4BBGPI2.js.map +1 -0
  145. package/dist/{chunk-LJQFJF4J.js → chunk-RM2YUFH6.js} +6 -6
  146. package/dist/{chunk-IPT2OY4B.js → chunk-RQFXZYTF.js} +35 -33
  147. package/dist/chunk-RQFXZYTF.js.map +1 -0
  148. package/dist/{chunk-AP6NCP3V.js → chunk-S3S72HRM.js} +8 -6
  149. package/dist/chunk-S3S72HRM.js.map +1 -0
  150. package/dist/{chunk-6QMWECO5.js → chunk-SGQPR5SX.js} +7 -7
  151. package/dist/{chunk-ZGFLIK5H.js → chunk-SPAKBUJY.js} +2 -2
  152. package/dist/{chunk-ER7XANP3.js → chunk-SQ3GEIEL.js} +4 -4
  153. package/dist/{chunk-5UCMYPVF.js → chunk-SVT5IA2H.js} +2 -2
  154. package/dist/{chunk-HVKUCT3W.js → chunk-T4KY6UYF.js} +5 -3
  155. package/dist/{chunk-HVKUCT3W.js.map → chunk-T4KY6UYF.js.map} +1 -1
  156. package/dist/{chunk-FRSHF6FU.js → chunk-TJ4F6H4H.js} +3 -3
  157. package/dist/{chunk-R6HMAIKM.js → chunk-TOSPNM4T.js} +2 -2
  158. package/dist/{chunk-NJJMVS5Y.js → chunk-TRQE3RYR.js} +5 -5
  159. package/dist/{chunk-RMXS4I66.js → chunk-TVDJEUV5.js} +2 -2
  160. package/dist/{chunk-PLCYKAWH.js → chunk-TYRWSE4B.js} +2 -2
  161. package/dist/{chunk-YS2GHSWN.js → chunk-UBEKET2V.js} +389 -39
  162. package/dist/chunk-UBEKET2V.js.map +1 -0
  163. package/dist/{chunk-IQWUACVG.js → chunk-UHMHJX5G.js} +3 -3
  164. package/dist/{chunk-YODUDA6R.js → chunk-UN4RVUG2.js} +22 -22
  165. package/dist/{chunk-KZSGBWOJ.js → chunk-V2KGDESV.js} +2 -2
  166. package/dist/{chunk-E6Z4FBX6.js → chunk-V2QSNFCT.js} +2 -2
  167. package/dist/{chunk-BCCG7VWM.js → chunk-V65H7MI6.js} +396 -13
  168. package/dist/chunk-V65H7MI6.js.map +1 -0
  169. package/dist/chunk-W54Z2MOP.js +4500 -0
  170. package/dist/chunk-W54Z2MOP.js.map +1 -0
  171. package/dist/{chunk-N74SGESS.js → chunk-WKSQTMU7.js} +2 -2
  172. package/dist/{chunk-RIZ5NUNN.js → chunk-WQ4XKIOX.js} +4 -4
  173. package/dist/{chunk-WWK6J6SE.js → chunk-WQURALGV.js} +4996 -2748
  174. package/dist/chunk-WQURALGV.js.map +1 -0
  175. package/dist/{chunk-QEYTRFR3.js → chunk-X26YOFGS.js} +2 -2
  176. package/dist/{chunk-ITHZFHST.js → chunk-X2BVB74H.js} +2 -2
  177. package/dist/{chunk-GNXGJBCA.js → chunk-XIYLWEXC.js} +2 -2
  178. package/dist/{chunk-IBJ6U753.js → chunk-XKZBZOKV.js} +4 -4
  179. package/dist/{chunk-7O2MC42R.js → chunk-XNRLRNQF.js} +2 -2
  180. package/dist/{chunk-65AUYLU3.js → chunk-XPXHQI6N.js} +2 -2
  181. package/dist/{chunk-JBCCWVU2.js → chunk-XRDYRWZI.js} +2 -2
  182. package/dist/chunk-XRWWCW4H.js +102 -0
  183. package/dist/chunk-XRWWCW4H.js.map +1 -0
  184. package/dist/chunk-YKJBSMMP.js +67137 -0
  185. package/dist/chunk-YKJBSMMP.js.map +1 -0
  186. package/dist/{chunk-2JSDPUKD.js → chunk-YMFPFXEX.js} +2 -2
  187. package/dist/{chunk-645WOU5I.js → chunk-ZDZJNXL6.js} +4 -4
  188. package/dist/{chunk-6TCXIRP5.js → chunk-ZKE4CO6B.js} +4 -4
  189. package/dist/{chunk-KEPXC4KN.js → chunk-ZSE774RV.js} +2 -2
  190. package/dist/cli.d.ts.map +1 -1
  191. package/dist/cli.js +305 -187
  192. package/dist/coding/export-okf-codegraph.js +29 -29
  193. package/dist/compounding/engine.js +23 -24
  194. package/dist/config.d.ts.map +1 -1
  195. package/dist/config.js +36 -37
  196. package/dist/connectors/codex-materialize-runner.js +20 -20
  197. package/dist/connectors/index.js +21 -21
  198. package/dist/connectors/live/framework.d.ts +7 -0
  199. package/dist/connectors/live/framework.d.ts.map +1 -1
  200. package/dist/connectors/live/google-drive.d.ts +17 -3
  201. package/dist/connectors/live/google-drive.d.ts.map +1 -1
  202. package/dist/consolidation-provenance-check.js +4 -4
  203. package/dist/consolidation-undo.js +5 -5
  204. package/dist/contradiction/index.js +7 -6
  205. package/dist/{contradiction-scan-P2MHYFVG.js → contradiction-scan-IBPYGQZF.js} +4 -3
  206. package/dist/convergence-refresh.js +22 -22
  207. package/dist/corpus-watermark.js +23 -23
  208. package/dist/deep-recall-http-glue.js +2 -2
  209. package/dist/deep-recall-policy-llm.js +4 -4
  210. package/dist/direct-answer-wiring.js +2 -2
  211. package/dist/embedding-fallback.js +1 -1
  212. package/dist/entity-retrieval.js +21 -21
  213. package/dist/eval-trajectory-store.js +2 -2
  214. package/dist/eval-trajectory.js +2 -2
  215. package/dist/event-order-recall.js +2 -2
  216. package/dist/explicit-capture.d.ts +3 -2
  217. package/dist/explicit-capture.d.ts.map +1 -1
  218. package/dist/explicit-capture.js +530 -6
  219. package/dist/explicit-cue-recall.js +2 -2
  220. package/dist/external-wiki-access.js +2 -283
  221. package/dist/extraction-faithfulness.js +4 -4
  222. package/dist/extraction-judge.js +5 -5
  223. package/dist/extraction-normalization.js +1 -1
  224. package/dist/extraction-quote-grounding.d.ts.map +1 -1
  225. package/dist/extraction-quote-grounding.js +1 -1
  226. package/dist/extraction-source-grounding-rules.js +2 -2
  227. package/dist/extraction-source-grounding.js +3 -3
  228. package/dist/extraction.js +43 -44
  229. package/dist/fallback-llm-codex-subscription.js +2 -2
  230. package/dist/fallback-llm.js +3 -3
  231. package/dist/{first-start-migration-QFI7B5SH.js → first-start-migration-FILJH3RO.js} +6 -5
  232. package/dist/{first-start-migration-QFI7B5SH.js.map → first-start-migration-FILJH3RO.js.map} +1 -1
  233. package/dist/focused-list-recall.js +2 -2
  234. package/dist/harmonic-retrieval.js +20 -20
  235. package/dist/index.js +776 -797
  236. package/dist/lcm/index.js +2 -2
  237. package/dist/live-connectors-runner.d.ts +2 -0
  238. package/dist/live-connectors-runner.d.ts.map +1 -1
  239. package/dist/live-connectors-runner.js +3 -4
  240. package/dist/local-llm-config.js +2 -2
  241. package/dist/local-llm-helpers.d.ts +4 -0
  242. package/dist/local-llm-helpers.d.ts.map +1 -1
  243. package/dist/local-llm-helpers.js +3 -1
  244. package/dist/local-llm.d.ts +4 -1
  245. package/dist/local-llm.d.ts.map +1 -1
  246. package/dist/local-llm.js +4 -4
  247. package/dist/location/index.js +27 -29
  248. package/dist/maintenance/memory-governance.js +20 -20
  249. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -20
  250. package/dist/maintenance/rebuild-memory-projection-runner.js +22 -22
  251. package/dist/maintenance/rebuild-memory-projection.js +21 -21
  252. package/dist/memory-browse-operations.js +2 -283
  253. package/dist/memory-browse.js +8 -7
  254. package/dist/memory-controller.js +2 -2
  255. package/dist/memory-subject.js +2 -2
  256. package/dist/namespaces/migrate.js +21 -21
  257. package/dist/namespaces/search.js +5 -5
  258. package/dist/namespaces/storage.js +20 -20
  259. package/dist/offline-sync-changeset-generations.js +1 -1
  260. package/dist/offline-sync-embedding-generation.js +1 -1
  261. package/dist/offline-sync-impression-drain.js +6 -6
  262. package/dist/offline-sync-snapshot-stream.js +1 -1
  263. package/dist/offline-sync.js +1 -1
  264. package/dist/operator-doctor-corpus.js +24 -24
  265. package/dist/operator-toolkit.js +58 -61
  266. package/dist/orchestration/backlog-scheduler.js +279 -295
  267. package/dist/orchestration/backlog-scheduler.js.map +1 -1
  268. package/dist/orchestration/buffer-drain-runner.js +279 -295
  269. package/dist/orchestration/extraction-run.d.ts +4 -0
  270. package/dist/orchestration/extraction-run.d.ts.map +1 -1
  271. package/dist/orchestration/fact-dedup-window.d.ts +1 -1
  272. package/dist/orchestration/fact-dedup-window.d.ts.map +1 -1
  273. package/dist/orchestration/maintenance.js +39 -42
  274. package/dist/orchestrator.d.ts +11 -11
  275. package/dist/orchestrator.d.ts.map +1 -1
  276. package/dist/orchestrator.js +291 -308
  277. package/dist/page-versioning.js +3 -3
  278. package/dist/qmd-daemon-session.js +2 -2
  279. package/dist/qmd.js +3 -3
  280. package/dist/recall-explain-renderer.js +3 -3
  281. package/dist/recall-navigate-access.js +2 -2
  282. package/dist/recall-navigate-disclosure.js +2 -2
  283. package/dist/recall-navigate.js +2 -2
  284. package/dist/recall-navigation-operations.js +2 -283
  285. package/dist/recall-navigation.js +334 -61
  286. package/dist/recall-planner-llm.js +3 -3
  287. package/dist/recall-state-view-admission.js +6 -6
  288. package/dist/recall-why-service.js +10 -9
  289. package/dist/recall-why.js +4 -3
  290. package/dist/recall-xray-cli.js +4 -4
  291. package/dist/recall-xray-renderer.js +3 -3
  292. package/dist/recall-xray.js +2 -2
  293. package/dist/reconcile/manifest.js +3 -3
  294. package/dist/{resolution-N7H3F2E4.js → resolution-OVVIF7ZY.js} +8 -7
  295. package/dist/response-guidance-recall.js +2 -2
  296. package/dist/resume-bundles.js +40 -41
  297. package/dist/salvage-envelope.js +4 -4
  298. package/dist/search/factory.js +4 -4
  299. package/dist/search/index.js +4 -4
  300. package/dist/semantic-consolidation.js +23 -23
  301. package/dist/semantic-rule-promotion.js +20 -20
  302. package/dist/semantic-rule-verifier.js +20 -20
  303. package/dist/shared-context/manager.js +2 -3
  304. package/dist/source-agent-qualifier.js +32 -33
  305. package/dist/standup/build.js +20 -20
  306. package/dist/{state-store-I5HLZTZT.js → state-store-EEAX2MBS.js} +2 -2
  307. package/dist/storage/content-hash-index.d.ts +10 -0
  308. package/dist/storage/content-hash-index.d.ts.map +1 -1
  309. package/dist/storage.js +19 -19
  310. package/dist/subject-config.js +3 -3
  311. package/dist/summarizer.d.ts +4 -1
  312. package/dist/summarizer.d.ts.map +1 -1
  313. package/dist/summarizer.js +6 -6
  314. package/dist/support-passport/index.js +53 -297
  315. package/dist/targeted-fact-recall.js +2 -2
  316. package/dist/tier-routing.js +3 -2
  317. package/dist/{tier-stats-FQGQSFET.js → tier-stats-FXEUJN73.js} +6 -5
  318. package/dist/{tier-stats-FQGQSFET.js.map → tier-stats-FXEUJN73.js.map} +1 -1
  319. package/dist/transcript.js +2 -2
  320. package/dist/transfer/capsule-import.js +4 -4
  321. package/dist/transfer/export-okf.js +20 -20
  322. package/dist/types.d.ts +10 -10
  323. package/dist/types.d.ts.map +1 -1
  324. package/dist/types.js +1 -1
  325. package/dist/verified-recall.js +20 -20
  326. package/dist/wearables/memory-gen.d.ts +5 -1
  327. package/dist/wearables/memory-gen.d.ts.map +1 -1
  328. package/dist/wearables/service.d.ts.map +1 -1
  329. package/dist/who-knows-cli.js +21 -21
  330. package/dist/who-knows.js +20 -20
  331. package/dist/write-envelope.js +3 -3
  332. package/package.json +2 -2
  333. package/src/access-boundary.ts +5 -1
  334. package/src/access-category-alias.test.ts +5 -0
  335. package/src/access-mcp-frames.test.ts +60 -5
  336. package/src/access-mcp-frames.ts +72 -18
  337. package/src/access-mcp.test.ts +66 -2
  338. package/src/access-mcp.ts +19 -13
  339. package/src/access-service-coding-write.test.ts +7 -0
  340. package/src/access-service.ts +3 -0
  341. package/src/activity/journal-extract-storage.test.ts +31 -0
  342. package/src/activity/journal-extract.test.ts +1 -0
  343. package/src/activity/journal-extract.ts +24 -3
  344. package/src/cli.ts +1 -2
  345. package/src/config.test.ts +17 -0
  346. package/src/config.ts +25 -7
  347. package/src/connectors/live/framework.ts +8 -0
  348. package/src/connectors/live/google-drive.test.ts +74 -0
  349. package/src/connectors/live/google-drive.ts +138 -11
  350. package/src/explicit-capture.test.ts +109 -17
  351. package/src/explicit-capture.ts +90 -37
  352. package/src/extraction-quote-grounding.test.ts +20 -0
  353. package/src/extraction-quote-grounding.ts +21 -11
  354. package/src/fact-dedup-window.test.ts +37 -0
  355. package/src/live-connectors-runner.ts +3 -0
  356. package/src/live-connectors-secretref.test.ts +126 -0
  357. package/src/local-llm-helpers.ts +12 -0
  358. package/src/local-llm-shutdown.test.ts +194 -0
  359. package/src/local-llm.ts +32 -30
  360. package/src/orchestration/extraction-run.ts +12 -3
  361. package/src/orchestration/fact-dedup-window.ts +5 -1
  362. package/src/orchestrator-connector-dedup.test.ts +9 -5
  363. package/src/orchestrator.ts +52 -55
  364. package/src/storage/content-hash-index.ts +27 -2
  365. package/src/storage-fact-hash-publish-failure.test.ts +87 -0
  366. package/src/summarizer-shutdown.test.ts +195 -0
  367. package/src/summarizer.ts +15 -2
  368. package/src/types.ts +10 -10
  369. package/src/wearables/memory-gen.test.ts +20 -0
  370. package/src/wearables/memory-gen.ts +14 -7
  371. package/src/wearables/service.ts +14 -1
  372. package/src/wearables/storage-io.test.ts +25 -0
  373. package/dist/chunk-27XYV2XL.js +0 -43
  374. package/dist/chunk-27XYV2XL.js.map +0 -1
  375. package/dist/chunk-5KBIOI4G.js.map +0 -1
  376. package/dist/chunk-66L5ZRJC.js.map +0 -1
  377. package/dist/chunk-7HTUYFR3.js.map +0 -1
  378. package/dist/chunk-AOFEMUHG.js.map +0 -1
  379. package/dist/chunk-AP6NCP3V.js.map +0 -1
  380. package/dist/chunk-APYY5CX3.js +0 -335
  381. package/dist/chunk-APYY5CX3.js.map +0 -1
  382. package/dist/chunk-ATPWMT2E.js +0 -223
  383. package/dist/chunk-ATPWMT2E.js.map +0 -1
  384. package/dist/chunk-BCCG7VWM.js.map +0 -1
  385. package/dist/chunk-E6M225BJ.js.map +0 -1
  386. package/dist/chunk-EQ4U73UH.js.map +0 -1
  387. package/dist/chunk-ETSJD5IV.js +0 -361
  388. package/dist/chunk-ETSJD5IV.js.map +0 -1
  389. package/dist/chunk-EWJZZDRG.js.map +0 -1
  390. package/dist/chunk-FHGWKODN.js +0 -2300
  391. package/dist/chunk-FHGWKODN.js.map +0 -1
  392. package/dist/chunk-GRTKLWYX.js +0 -621
  393. package/dist/chunk-GRTKLWYX.js.map +0 -1
  394. package/dist/chunk-IGLJNHOX.js +0 -62
  395. package/dist/chunk-IGLJNHOX.js.map +0 -1
  396. package/dist/chunk-IPT2OY4B.js.map +0 -1
  397. package/dist/chunk-IUKYFTGW.js.map +0 -1
  398. package/dist/chunk-KUIRDD74.js +0 -3991
  399. package/dist/chunk-KUIRDD74.js.map +0 -1
  400. package/dist/chunk-MVMRUGBH.js +0 -1919
  401. package/dist/chunk-MVMRUGBH.js.map +0 -1
  402. package/dist/chunk-ODL4ZTNI.js +0 -3644
  403. package/dist/chunk-ODL4ZTNI.js.map +0 -1
  404. package/dist/chunk-OGXXGHW6.js +0 -223
  405. package/dist/chunk-OGXXGHW6.js.map +0 -1
  406. package/dist/chunk-P5VZSSYL.js.map +0 -1
  407. package/dist/chunk-PPCLZ4JU.js +0 -28
  408. package/dist/chunk-PPCLZ4JU.js.map +0 -1
  409. package/dist/chunk-PUEO37QG.js.map +0 -1
  410. package/dist/chunk-RRTVGD3J.js +0 -792
  411. package/dist/chunk-RRTVGD3J.js.map +0 -1
  412. package/dist/chunk-STSLB4HT.js +0 -18793
  413. package/dist/chunk-STSLB4HT.js.map +0 -1
  414. package/dist/chunk-T6OZW2WR.js.map +0 -1
  415. package/dist/chunk-TRBGGJKZ.js +0 -32218
  416. package/dist/chunk-TRBGGJKZ.js.map +0 -1
  417. package/dist/chunk-UDKWFDV2.js.map +0 -1
  418. package/dist/chunk-V4XE263I.js.map +0 -1
  419. package/dist/chunk-V7IZKJI3.js +0 -22
  420. package/dist/chunk-V7IZKJI3.js.map +0 -1
  421. package/dist/chunk-VMVVSZTD.js +0 -61
  422. package/dist/chunk-VMVVSZTD.js.map +0 -1
  423. package/dist/chunk-VNUOAXWP.js +0 -203
  424. package/dist/chunk-VNUOAXWP.js.map +0 -1
  425. package/dist/chunk-WLBEZZK5.js +0 -729
  426. package/dist/chunk-WLBEZZK5.js.map +0 -1
  427. package/dist/chunk-WUUES6CU.js +0 -25
  428. package/dist/chunk-WUUES6CU.js.map +0 -1
  429. package/dist/chunk-WWK6J6SE.js.map +0 -1
  430. package/dist/chunk-XICOH5HT.js +0 -346
  431. package/dist/chunk-XICOH5HT.js.map +0 -1
  432. package/dist/chunk-YCNIGRRF.js.map +0 -1
  433. package/dist/chunk-YS2GHSWN.js.map +0 -1
  434. package/dist/chunk-ZCLEYJPB.js +0 -10143
  435. package/dist/chunk-ZCLEYJPB.js.map +0 -1
  436. /package/dist/{capsule-merge-2IIXFXN5.js.map → capsule-merge-6IDAYTKG.js.map} +0 -0
  437. /package/dist/{chunk-QL7RHYK6.js.map → chunk-2LMA22UU.js.map} +0 -0
  438. /package/dist/{chunk-RGUUBAT5.js.map → chunk-2WCLTWV2.js.map} +0 -0
  439. /package/dist/{chunk-RSK2WIEM.js.map → chunk-2YODOG2O.js.map} +0 -0
  440. /package/dist/{chunk-WYG5UNDY.js.map → chunk-3AUDELZL.js.map} +0 -0
  441. /package/dist/{chunk-OFVCFKDH.js.map → chunk-3CYOCE6U.js.map} +0 -0
  442. /package/dist/{chunk-6HM6HARE.js.map → chunk-3FBAEPCU.js.map} +0 -0
  443. /package/dist/{chunk-PIITB2YZ.js.map → chunk-3ZS3NUEI.js.map} +0 -0
  444. /package/dist/{chunk-ANZZLRUX.js.map → chunk-4IVRQMZW.js.map} +0 -0
  445. /package/dist/{chunk-63E37JCN.js.map → chunk-4RAJT5L2.js.map} +0 -0
  446. /package/dist/{chunk-45VUHDV2.js.map → chunk-5CO5G4MN.js.map} +0 -0
  447. /package/dist/{chunk-3UMDRGFS.js.map → chunk-65HWAQ4F.js.map} +0 -0
  448. /package/dist/{chunk-T67LUYCR.js.map → chunk-77NTFICT.js.map} +0 -0
  449. /package/dist/{chunk-UE6RRXMF.js.map → chunk-A4F7OIC5.js.map} +0 -0
  450. /package/dist/{chunk-63O7LVMN.js.map → chunk-B33YWUJV.js.map} +0 -0
  451. /package/dist/{chunk-QVMOCJRV.js.map → chunk-B377OKUP.js.map} +0 -0
  452. /package/dist/{chunk-ZT6WPSII.js.map → chunk-BGHCSLE5.js.map} +0 -0
  453. /package/dist/{chunk-YYOMGOHB.js.map → chunk-BOK6BN5M.js.map} +0 -0
  454. /package/dist/{chunk-OH7QLI6W.js.map → chunk-BPPUH5JM.js.map} +0 -0
  455. /package/dist/{chunk-EV76IZ37.js.map → chunk-BTI4C4MA.js.map} +0 -0
  456. /package/dist/{chunk-O6ZSWHVR.js.map → chunk-C2KE5DMD.js.map} +0 -0
  457. /package/dist/{chunk-47F6WWLQ.js.map → chunk-C73N66PR.js.map} +0 -0
  458. /package/dist/{chunk-3XIWW4TB.js.map → chunk-CGJYL633.js.map} +0 -0
  459. /package/dist/{chunk-WRT7GJ2D.js.map → chunk-CIWMTNHW.js.map} +0 -0
  460. /package/dist/{chunk-O55EKIEC.js.map → chunk-D3ZKHLN2.js.map} +0 -0
  461. /package/dist/{chunk-CD4BCCNP.js.map → chunk-DJ7WVEWX.js.map} +0 -0
  462. /package/dist/{chunk-RO7RUBLD.js.map → chunk-EFL24KOI.js.map} +0 -0
  463. /package/dist/{chunk-4CJTQHEG.js.map → chunk-ESLOLCD4.js.map} +0 -0
  464. /package/dist/{chunk-Z4Q6USKJ.js.map → chunk-ETBVCRVL.js.map} +0 -0
  465. /package/dist/{chunk-VILPVT4S.js.map → chunk-EZ47HOJ6.js.map} +0 -0
  466. /package/dist/{chunk-EFYN5I7Z.js.map → chunk-F4QFU5IZ.js.map} +0 -0
  467. /package/dist/{chunk-SHUBTAY2.js.map → chunk-FMKILENU.js.map} +0 -0
  468. /package/dist/{chunk-YLXETSAH.js.map → chunk-GCZJ7XRI.js.map} +0 -0
  469. /package/dist/{chunk-QFEDITXM.js.map → chunk-JNDMIAJ4.js.map} +0 -0
  470. /package/dist/{chunk-E5PPE4VA.js.map → chunk-K2VRKCPA.js.map} +0 -0
  471. /package/dist/{chunk-MKRYQROF.js.map → chunk-LGEHAQHK.js.map} +0 -0
  472. /package/dist/{chunk-XYTQJD7F.js.map → chunk-LMJVP5CM.js.map} +0 -0
  473. /package/dist/{chunk-JC36FPQ5.js.map → chunk-LPV72KRQ.js.map} +0 -0
  474. /package/dist/{chunk-2LCRG2YV.js.map → chunk-M2XR6B6V.js.map} +0 -0
  475. /package/dist/{chunk-VPQFK63H.js.map → chunk-MH632KPO.js.map} +0 -0
  476. /package/dist/{chunk-ZU5JDLOH.js.map → chunk-MMRTPH3J.js.map} +0 -0
  477. /package/dist/{chunk-ZZ67UTQX.js.map → chunk-MUX7IL77.js.map} +0 -0
  478. /package/dist/{chunk-RYWROSL5.js.map → chunk-NAQ4A5IX.js.map} +0 -0
  479. /package/dist/{chunk-TVIVY7KU.js.map → chunk-NED7IR7B.js.map} +0 -0
  480. /package/dist/{chunk-ADYP7HXE.js.map → chunk-NHVAX7MH.js.map} +0 -0
  481. /package/dist/{chunk-TG3R2SID.js.map → chunk-NMGHGTVR.js.map} +0 -0
  482. /package/dist/{chunk-NGHDW6UU.js.map → chunk-NUQEREIP.js.map} +0 -0
  483. /package/dist/{chunk-5IIQU4JZ.js.map → chunk-OB72KNMF.js.map} +0 -0
  484. /package/dist/{chunk-7L3TODI7.js.map → chunk-OJXJWNFY.js.map} +0 -0
  485. /package/dist/{chunk-EURPSF4Y.js.map → chunk-PH5ZQM35.js.map} +0 -0
  486. /package/dist/{chunk-BMWMTAQF.js.map → chunk-PRAUN6PN.js.map} +0 -0
  487. /package/dist/{chunk-RWGRSKN5.js.map → chunk-PT4DZDJA.js.map} +0 -0
  488. /package/dist/{chunk-7EPY3IQL.js.map → chunk-PZJQ46DH.js.map} +0 -0
  489. /package/dist/{chunk-AH637HZ5.js.map → chunk-QDESY76F.js.map} +0 -0
  490. /package/dist/{chunk-I6QGI65T.js.map → chunk-QRMG4HK4.js.map} +0 -0
  491. /package/dist/{chunk-ZU3NJNO7.js.map → chunk-QSF5SJAM.js.map} +0 -0
  492. /package/dist/{chunk-5IYOKDM4.js.map → chunk-R23JWJD3.js.map} +0 -0
  493. /package/dist/{chunk-LJQFJF4J.js.map → chunk-RM2YUFH6.js.map} +0 -0
  494. /package/dist/{chunk-6QMWECO5.js.map → chunk-SGQPR5SX.js.map} +0 -0
  495. /package/dist/{chunk-ZGFLIK5H.js.map → chunk-SPAKBUJY.js.map} +0 -0
  496. /package/dist/{chunk-ER7XANP3.js.map → chunk-SQ3GEIEL.js.map} +0 -0
  497. /package/dist/{chunk-5UCMYPVF.js.map → chunk-SVT5IA2H.js.map} +0 -0
  498. /package/dist/{chunk-FRSHF6FU.js.map → chunk-TJ4F6H4H.js.map} +0 -0
  499. /package/dist/{chunk-R6HMAIKM.js.map → chunk-TOSPNM4T.js.map} +0 -0
  500. /package/dist/{chunk-NJJMVS5Y.js.map → chunk-TRQE3RYR.js.map} +0 -0
  501. /package/dist/{chunk-RMXS4I66.js.map → chunk-TVDJEUV5.js.map} +0 -0
  502. /package/dist/{chunk-PLCYKAWH.js.map → chunk-TYRWSE4B.js.map} +0 -0
  503. /package/dist/{chunk-IQWUACVG.js.map → chunk-UHMHJX5G.js.map} +0 -0
  504. /package/dist/{chunk-YODUDA6R.js.map → chunk-UN4RVUG2.js.map} +0 -0
  505. /package/dist/{chunk-KZSGBWOJ.js.map → chunk-V2KGDESV.js.map} +0 -0
  506. /package/dist/{chunk-E6Z4FBX6.js.map → chunk-V2QSNFCT.js.map} +0 -0
  507. /package/dist/{chunk-N74SGESS.js.map → chunk-WKSQTMU7.js.map} +0 -0
  508. /package/dist/{chunk-RIZ5NUNN.js.map → chunk-WQ4XKIOX.js.map} +0 -0
  509. /package/dist/{chunk-QEYTRFR3.js.map → chunk-X26YOFGS.js.map} +0 -0
  510. /package/dist/{chunk-ITHZFHST.js.map → chunk-X2BVB74H.js.map} +0 -0
  511. /package/dist/{chunk-GNXGJBCA.js.map → chunk-XIYLWEXC.js.map} +0 -0
  512. /package/dist/{chunk-IBJ6U753.js.map → chunk-XKZBZOKV.js.map} +0 -0
  513. /package/dist/{chunk-7O2MC42R.js.map → chunk-XNRLRNQF.js.map} +0 -0
  514. /package/dist/{chunk-65AUYLU3.js.map → chunk-XPXHQI6N.js.map} +0 -0
  515. /package/dist/{chunk-JBCCWVU2.js.map → chunk-XRDYRWZI.js.map} +0 -0
  516. /package/dist/{chunk-2JSDPUKD.js.map → chunk-YMFPFXEX.js.map} +0 -0
  517. /package/dist/{chunk-645WOU5I.js.map → chunk-ZDZJNXL6.js.map} +0 -0
  518. /package/dist/{chunk-6TCXIRP5.js.map → chunk-ZKE4CO6B.js.map} +0 -0
  519. /package/dist/{chunk-KEPXC4KN.js.map → chunk-ZSE774RV.js.map} +0 -0
  520. /package/dist/{contradiction-scan-P2MHYFVG.js.map → contradiction-scan-IBPYGQZF.js.map} +0 -0
  521. /package/dist/{resolution-N7H3F2E4.js.map → resolution-OVVIF7ZY.js.map} +0 -0
  522. /package/dist/{state-store-I5HLZTZT.js.map → state-store-EEAX2MBS.js.map} +0 -0
@@ -0,0 +1,194 @@
1
+ // Shutdown-signal behavioral tests for LocalLlmClient: a daemon stop must
2
+ // abort in-flight chat requests at once (the abort reaches the transport),
3
+ // must not start another attempt once aborted, and must not sit out the
4
+ // retry backoff after abort. Uses the globalThis.fetch seam from
5
+ // local-llm-qos.test.ts with a hanging transport so the real retry loop is
6
+ // exercised, not a mock of it.
7
+ import assert from "node:assert/strict";
8
+ import test from "node:test";
9
+
10
+ import { parseConfig } from "./config.js";
11
+ import { LocalLlmClient } from "./local-llm.js";
12
+ import { initLogger, resetLogger, type LoggerBackend } from "./logger.js";
13
+
14
+ /** Captured log lines with the logger's "remnic: " prefix stripped. */
15
+ interface CapturedLog {
16
+ lines: string[];
17
+ }
18
+
19
+ function createConfig(memoryDir: string) {
20
+ return parseConfig({
21
+ openaiApiKey: "sk-test",
22
+ memoryDir,
23
+ workspaceDir: `${memoryDir}/workspace`,
24
+ localLlmEnabled: true,
25
+ localLlmModel: "test-local-model",
26
+ localLlmUrl: "http://127.0.0.1:9",
27
+ // Mirror the production daemon: a 10-minute budget with 2 attempts, so
28
+ // an unhonored abort would outlive any sane test deadline.
29
+ localLlmTimeoutMs: 600_000,
30
+ localLlmRetry5xxCount: 1,
31
+ localLlmRetryBackoffMs: 30_000,
32
+ localLlmHeaders: {},
33
+ localLlm400TripThreshold: 3,
34
+ localLlm400CooldownMs: 60_000,
35
+ localLlmReasoningEffort: "none",
36
+ debug: false,
37
+ });
38
+ }
39
+
40
+ interface HangingFetchSpec {
41
+ calls: { signal: AbortSignal | undefined }[];
42
+ sawAbort: boolean;
43
+ /** Reject with AbortError after delayMs (timeout simulation); default hangs forever. */
44
+ timeoutAfterMs?: number;
45
+ /** Resolves when the transport stub is entered (request is in flight). */
46
+ entered: Promise<void>;
47
+ }
48
+
49
+ function installHangingFetch(spec: HangingFetchSpec): () => void {
50
+ const { promise: entered, resolve: markEntered } = Promise.withResolvers<void>();
51
+ spec.entered = entered;
52
+ const originalFetch = globalThis.fetch;
53
+ // SAFETY: the transport passes a string URL and an init with a signal;
54
+ // this async stub matches that call shape exactly.
55
+ globalThis.fetch = (async (url: string, init?: { signal?: AbortSignal }) => {
56
+ void url;
57
+ const signal = init?.signal;
58
+ spec.calls.push({ signal });
59
+ markEntered();
60
+ const { promise, reject } = Promise.withResolvers<Response>();
61
+ // A real transport rejects with AbortError when its signal aborts
62
+ // (undici behavior); the stub must honor it the same way or the client
63
+ // loop cannot observe the abort.
64
+ const onAbort = (): void => {
65
+ spec.sawAbort = true;
66
+ reject(new DOMException("This operation was aborted", "AbortError"));
67
+ };
68
+ if (signal) {
69
+ if (signal.aborted) onAbort();
70
+ else signal.addEventListener("abort", onAbort, { once: true });
71
+ }
72
+ if (spec.timeoutAfterMs !== undefined) {
73
+ const timer = setTimeout(() => {
74
+ signal?.removeEventListener("abort", onAbort);
75
+ reject(new DOMException("This operation was aborted", "AbortError"));
76
+ }, spec.timeoutAfterMs);
77
+ timer.unref?.();
78
+ }
79
+ return await promise;
80
+ }) as typeof fetch;
81
+ return () => {
82
+ globalThis.fetch = originalFetch;
83
+ };
84
+ }
85
+
86
+ /** Polls a real runtime condition (a log line, a stub entry) instead of a
87
+ * guessed fixed sleep: the condition, not a duration, gates progress. */
88
+ async function waitFor(
89
+ predicate: () => boolean,
90
+ description: string,
91
+ timeoutMs = 5_000,
92
+ ): Promise<void> {
93
+ const deadline = Date.now() + timeoutMs;
94
+ while (!predicate()) {
95
+ if (Date.now() > deadline) throw new Error(`condition not met: ${description}`);
96
+ await new Promise((resolve) => setTimeout(resolve, 10));
97
+ }
98
+ }
99
+
100
+ async function withTestDeadline<T>(promise: Promise<T>, timeoutMs: number, label: string): Promise<T> {
101
+ const { promise: deadline, reject } = Promise.withResolvers<never>();
102
+ const timer = setTimeout(() => reject(new Error(`${label}: test deadline exceeded (${timeoutMs}ms)`)), timeoutMs);
103
+ timer.unref?.();
104
+ try {
105
+ return await Promise.race([promise, deadline]);
106
+ } finally {
107
+ clearTimeout(timer);
108
+ }
109
+ }
110
+
111
+ function installRecordingLogger(): CapturedLog {
112
+ const lines: string[] = [];
113
+ const body = (msg: string) => msg.replace(/^remnic: /, "");
114
+ const backend: LoggerBackend = {
115
+ info: (msg) => lines.push(body(msg)),
116
+ warn: (msg) => lines.push(body(msg)),
117
+ error: (msg) => lines.push(body(msg)),
118
+ };
119
+ initLogger(backend, false, { timestamps: false });
120
+ return { lines };
121
+ }
122
+
123
+ function quietLogger(): void {
124
+ initLogger({ info() {}, warn() {}, error() {}, debug() {} }, false);
125
+ }
126
+
127
+ test("aborting the client shutdown signal aborts an in-flight request and reaches the transport stub", async () => {
128
+ quietLogger();
129
+ const spec: HangingFetchSpec = { calls: [], sawAbort: false, entered: Promise.resolve() };
130
+ const restoreFetch = installHangingFetch(spec);
131
+ try {
132
+ const controller = new AbortController();
133
+ const client = new LocalLlmClient(createConfig("/tmp/remnic-llm-shutdown-inflight"), undefined, controller.signal);
134
+ // SAFETY: availability is stubbed at the established field seam (same as
135
+ // local-llm-qos.test.ts) so the retry loop, not the network probe, runs.
136
+ const seams = client as any;
137
+ seams.isAvailable = true;
138
+ seams.lastHealthCheck = Date.now();
139
+
140
+ const pending = client.chatCompletion(
141
+ [{ role: "user", content: "shutdown abort in flight" }],
142
+ { operation: "extraction" },
143
+ );
144
+
145
+ await spec.entered;
146
+ controller.abort();
147
+
148
+ const result = await withTestDeadline(pending, 2_000, "in-flight abort");
149
+ assert.equal(result, null);
150
+ assert.equal(spec.calls.length, 1, "no second attempt may start after abort");
151
+ assert.equal(spec.sawAbort, true, "the abort signal must reach the transport stub");
152
+ assert.equal(spec.calls[0]?.signal?.aborted, true);
153
+ } finally {
154
+ restoreFetch();
155
+ resetLogger();
156
+ }
157
+ });
158
+
159
+ test("an abort during retry backoff ends the loop without sleeping it out or starting another attempt", async () => {
160
+ const { lines } = installRecordingLogger();
161
+ const spec: HangingFetchSpec = { calls: [], sawAbort: false, timeoutAfterMs: 20, entered: Promise.resolve() };
162
+ const restoreFetch = installHangingFetch(spec);
163
+ try {
164
+ const controller = new AbortController();
165
+ const client = new LocalLlmClient(createConfig("/tmp/remnic-llm-shutdown-backoff"), undefined, controller.signal);
166
+ // SAFETY: availability is stubbed at the established field seam (same as
167
+ // local-llm-qos.test.ts) so the retry loop, not the network probe, runs.
168
+ const seams = client as any;
169
+ seams.isAvailable = true;
170
+ seams.lastHealthCheck = Date.now();
171
+
172
+ const pending = client.chatCompletion(
173
+ [{ role: "user", content: "shutdown abort during backoff" }],
174
+ { operation: "extraction" },
175
+ );
176
+
177
+ // Sync point: the retry loop is in its 30s backoff when the backoff
178
+ // warn line lands; abort there.
179
+ await waitFor(
180
+ () => lines.some((line) => line.includes("retrying after 30000ms")),
181
+ "attempt 1 to fail and backoff to start",
182
+ );
183
+ controller.abort();
184
+
185
+ const startedAtMs = Date.now();
186
+ const result = await withTestDeadline(pending, 2_000, "backoff abort");
187
+ assert.equal(result, null);
188
+ assert.ok(Date.now() - startedAtMs < 1_500, "backoff must not be slept out after abort");
189
+ assert.equal(spec.calls.length, 1, "no second attempt may start after abort");
190
+ } finally {
191
+ restoreFetch();
192
+ resetLogger();
193
+ }
194
+ });
package/src/local-llm.ts CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  type ProbeFetchResult,
21
21
  normalizeBackendTripReason,
22
22
  waitForRetryBackoff,
23
+ combineClientAbortSignals,
23
24
  SingleFlightProbe,
24
25
  type LocalLlmChatCompletionOptions,
25
26
  type LocalLlmChatCompletionResult,
@@ -201,10 +202,14 @@ export class LocalLlmClient {
201
202
  private static readonly HEALTH_CHECK_INTERVAL_MS = 60000; // 1 minute
202
203
  private static readonly LMS_CACHE_INTERVAL_MS = 30000; // 30 seconds
203
204
  private readonly chatTransport = new ChatTransport();
205
+ /** Orchestrator-owned stop signal: aborts every in-flight and queued
206
+ * request (and their retry backoffs) the moment teardown begins. */
207
+ private readonly shutdownSignal: AbortSignal | undefined;
204
208
 
205
- constructor(config: PluginConfig, modelRegistry?: ModelRegistry) {
209
+ constructor(config: PluginConfig, modelRegistry?: ModelRegistry, shutdownSignal?: AbortSignal) {
206
210
  this.config = config;
207
211
  this.modelRegistry = modelRegistry;
212
+ this.shutdownSignal = shutdownSignal;
208
213
  }
209
214
 
210
215
  /**
@@ -829,7 +834,7 @@ export class LocalLlmClient {
829
834
 
830
835
  private async runQueuedRequest(next: LocalLlmQueuedRequest): Promise<void> {
831
836
  try {
832
- if (next.options.signal?.aborted) {
837
+ if (combineClientAbortSignals(next.options.signal, this.shutdownSignal)?.aborted) {
833
838
  next.resolve(null);
834
839
  return;
835
840
  }
@@ -879,8 +884,9 @@ export class LocalLlmClient {
879
884
  }
880
885
 
881
886
  try {
882
- if (options.signal?.aborted) return null;
883
- const isAvailable = await this.checkAvailability(options.signal);
887
+ const signal = combineClientAbortSignals(options.signal, this.shutdownSignal);
888
+ if (signal?.aborted) return null;
889
+ const isAvailable = await this.checkAvailability(signal);
884
890
  if (!isAvailable) {
885
891
  log.debug(
886
892
  `local LLM: checkAvailability returned false for ${this.config.localLlmUrl}`,
@@ -977,7 +983,7 @@ export class LocalLlmClient {
977
983
  response = null;
978
984
  responseBody = "";
979
985
  // Wait out the shared endpoint backoff, then take a concurrency slot.
980
- const gate = await rateLimit.beforeAttempt(options.signal);
986
+ const gate = await rateLimit.beforeAttempt(signal);
981
987
  if (gate.kind === "skip") {
982
988
  log.warn(gate.reason === "queue"
983
989
  ? `local LLM concurrency queue exceeded the ${effectiveTimeoutMs}ms request budget; skipping request (op=${operation})`
@@ -989,24 +995,25 @@ export class LocalLlmClient {
989
995
  if (gate.kind === "aborted") return null;
990
996
  const attemptAbort = new AbortController();
991
997
  const onCallerAbort = (): void => {
992
- attemptAbort.abort(options.signal?.reason);
998
+ attemptAbort.abort(signal?.reason);
993
999
  };
994
- if (options.signal) {
995
- if (options.signal.aborted) {
1000
+ if (signal) {
1001
+ if (signal.aborted) {
996
1002
  onCallerAbort();
997
1003
  } else {
998
- options.signal.addEventListener("abort", onCallerAbort, { once: true });
1004
+ signal.addEventListener("abort", onCallerAbort, { once: true });
999
1005
  }
1000
1006
  }
1001
1007
  const attemptTimeout = setTimeout(() => attemptAbort.abort(), effectiveTimeoutMs);
1008
+ const postAttempt = (bodyJson: string): Promise<Response> => this.chatTransport.post({
1009
+ url: chatUrl,
1010
+ headers: this.buildRequestHeaders({ "Content-Type": "application/json" }),
1011
+ body: bodyJson,
1012
+ signal: attemptAbort.signal,
1013
+ budgetMs: this.config.localLlmTimeoutMs,
1014
+ });
1002
1015
  try {
1003
- response = await this.chatTransport.post({
1004
- url: chatUrl,
1005
- headers: this.buildRequestHeaders({ "Content-Type": "application/json" }),
1006
- body: requestBodyJson,
1007
- signal: attemptAbort.signal,
1008
- budgetMs: this.config.localLlmTimeoutMs,
1009
- });
1016
+ response = await postAttempt(requestBodyJson);
1010
1017
  responseBody = await response.text();
1011
1018
  if (
1012
1019
  response.status === 400 &&
@@ -1019,18 +1026,12 @@ export class LocalLlmClient {
1019
1026
  requestBodyJson = JSON.stringify(requestBody);
1020
1027
  log.debug("local LLM rejected native JSON schema; retrying without it");
1021
1028
  response = null;
1022
- response = await this.chatTransport.post({
1023
- url: chatUrl,
1024
- headers: this.buildRequestHeaders({ "Content-Type": "application/json" }),
1025
- body: requestBodyJson,
1026
- signal: attemptAbort.signal,
1027
- budgetMs: this.config.localLlmTimeoutMs,
1028
- });
1029
+ response = await postAttempt(requestBodyJson);
1029
1030
  responseBody = await response.text();
1030
1031
  }
1031
1032
  } catch (err) {
1032
1033
  const error = err instanceof Error ? err : new Error(String(err));
1033
- if (options.signal?.aborted) {
1034
+ if (signal?.aborted) {
1034
1035
  response = null;
1035
1036
  lastAbortError = error;
1036
1037
  break;
@@ -1046,12 +1047,12 @@ export class LocalLlmClient {
1046
1047
  log.warn(
1047
1048
  `local LLM request aborted: op=${operation} attempt=${attempt}/${maxAttempts} timeoutMs=${effectiveTimeoutMs} model=${this.config.localLlmModel}; retrying after ${backoffMs}ms`,
1048
1049
  );
1049
- if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
1050
+ if (!(await waitForRetryBackoff(backoffMs, signal))) return null;
1050
1051
  continue;
1051
1052
  }
1052
1053
  } finally {
1053
1054
  clearTimeout(attemptTimeout);
1054
- options.signal?.removeEventListener("abort", onCallerAbort);
1055
+ signal?.removeEventListener("abort", onCallerAbort);
1055
1056
  gate.release();
1056
1057
  }
1057
1058
 
@@ -1085,7 +1086,7 @@ export class LocalLlmClient {
1085
1086
  log.warn(
1086
1087
  `local LLM request got ${response.status}; retrying (attempt ${attempt + 1}/${maxAttempts}) after ${backoffMs}ms`,
1087
1088
  );
1088
- if (!(await waitForRetryBackoff(backoffMs, options.signal))) return null;
1089
+ if (!(await waitForRetryBackoff(backoffMs, signal))) return null;
1089
1090
  }
1090
1091
  log.debug(
1091
1092
  `local LLM: received response, status=${response?.status}, ok=${response?.ok}`,
@@ -1401,13 +1402,14 @@ export class LocalLlmClient {
1401
1402
  }
1402
1403
  if (options.priority) {
1403
1404
  const priority = options.priority;
1405
+ const signal = combineClientAbortSignals(options.signal, this.shutdownSignal);
1404
1406
  return await new Promise<LocalLlmChatCompletionResult | null>((resolve) => {
1405
1407
  let settled = false;
1406
1408
  let onAbort: (() => void) | undefined;
1407
1409
  const finish = (value: LocalLlmChatCompletionResult | null): void => {
1408
1410
  if (settled) return;
1409
1411
  settled = true;
1410
- if (onAbort) options.signal?.removeEventListener("abort", onAbort);
1412
+ if (onAbort) signal?.removeEventListener("abort", onAbort);
1411
1413
  resolve(value);
1412
1414
  };
1413
1415
  const queued: LocalLlmQueuedRequest = {
@@ -1424,8 +1426,8 @@ export class LocalLlmClient {
1424
1426
  finish(null);
1425
1427
  };
1426
1428
  this.requestQueues[priority].push(queued);
1427
- if (options.signal?.aborted) onAbort();
1428
- else if (options.signal) options.signal.addEventListener("abort", onAbort, { once: true });
1429
+ if (signal?.aborted) onAbort();
1430
+ else if (signal) signal.addEventListener("abort", onAbort, { once: true });
1429
1431
  this.scheduleQueueDrain();
1430
1432
  });
1431
1433
  }
@@ -113,6 +113,10 @@ export interface ExtractionRunCoordinatorDeps {
113
113
  * threshold and honors a foreground-opened breaker (review round).
114
114
  */
115
115
  providerBreaker?: ProviderCircuitBreaker;
116
+ /** Orchestrator-owned stop signal, combined into every extraction run's
117
+ * abort signal: queued tasks never start and in-flight runs abort the
118
+ * moment destroy() begins. Absent for standalone coordinators (tests). */
119
+ shutdownSignal?: AbortSignal;
116
120
  }
117
121
 
118
122
  // Recall/extraction abort helpers live in orchestrator-helpers.ts since
@@ -692,11 +696,16 @@ export class ExtractionRunCoordinator {
692
696
  typeof deadlineMs === "number" && Number.isFinite(deadlineMs)
693
697
  ? new AbortController()
694
698
  : undefined;
699
+ const shutdownSignal = this.deps.shutdownSignal;
700
+ const callerAbortSignal =
701
+ options.abortSignal && shutdownSignal
702
+ ? AbortSignal.any([options.abortSignal, shutdownSignal])
703
+ : (options.abortSignal ?? shutdownSignal);
695
704
  const extractionAbortSignal = extractionDeadlineController
696
- ? options.abortSignal
697
- ? AbortSignal.any([options.abortSignal, extractionDeadlineController.signal])
705
+ ? callerAbortSignal
706
+ ? AbortSignal.any([callerAbortSignal, extractionDeadlineController.signal])
698
707
  : extractionDeadlineController.signal
699
- : options.abortSignal;
708
+ : callerAbortSignal;
700
709
  let extractionDeadlineTimer: NodeJS.Timeout | undefined;
701
710
  const clearExtractionDeadlineTimer = (): void => {
702
711
  if (extractionDeadlineTimer) {
@@ -1,6 +1,10 @@
1
1
  import path from "node:path";
2
2
  import { serializeMutations, withHeldFileLock } from "../utils/serialize-mutations.js";
3
- import { ContentHashIndex, type StorageManager } from "../index.js";
3
+ // Import from the real modules, NOT the ../index.js barrel: a barrel edge
4
+ // from orchestration code that explicit-capture.ts imports re-orders module
5
+ // initialization and leaves access-boundary's registry in TDZ (#3354).
6
+ import { ContentHashIndex } from "../storage/content-hash-index.js";
7
+ import type { StorageManager } from "../storage.js";
4
8
  import type { MemoryFile } from "../types.js";
5
9
  import { normalizeStoredHashSource } from "./extraction-persist-citation.js";
6
10
  import { stripAttributesSuffix } from "../structured-attributes.js";
@@ -1331,8 +1331,10 @@ test("#1909 round 11: the restart rebuild reflects the current corpus (archived
1331
1331
  test("#1909 round 11 finding 2: destroy() flushes the debounced buffer BEFORE catalog touches", async () => {
1332
1332
  // The buffer save fires a coalesced namespace-catalog touch; if catalog touches
1333
1333
  // were flushed first, that shutdown-time touch would queue after and be lost.
1334
- // destroy() must flush the buffer first so its touch folds into the catalog
1335
- // flush and both settle before destroy() returns.
1334
+ // destroy() flushes the buffer before the extraction drain and again after it
1335
+ // (post-drain removals); every buffer flush must run before the one catalog
1336
+ // flush so each shutdown-time touch folds into it and settles before destroy()
1337
+ // returns.
1336
1338
  const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-destroy-order-"));
1337
1339
  const config = parseConfig({
1338
1340
  openaiApiKey: "sk-test",
@@ -1363,10 +1365,12 @@ test("#1909 round 11 finding 2: destroy() flushes the debounced buffer BEFORE ca
1363
1365
 
1364
1366
  await priv.destroy();
1365
1367
  assert.deepEqual(
1366
- order,
1367
- ["buffer", "catalog"],
1368
- "buffer flush must run before the catalog-touch flush on shutdown",
1368
+ order.filter((step) => step === "catalog"),
1369
+ ["catalog"],
1370
+ "the catalog-touch flush runs exactly once",
1369
1371
  );
1372
+ assert.equal(order.at(-1), "catalog", "no buffer flush may run after the catalog-touch flush");
1373
+ assert.ok(order.includes("buffer"), "destroy() flushes the buffer");
1370
1374
  });
1371
1375
  test("#1909 round 14: destroy() surfaces a buffer flush failure and still completes teardown", async () => {
1372
1376
  // Graceful-shutdown durability contract: a failed shutdown buffer flush must
@@ -236,6 +236,7 @@ import {
236
236
  runLiveConnectorsOnce,
237
237
  type LiveConnectorsRunSummary,
238
238
  } from "./live-connectors-runner.js";
239
+ import type { ResolveSecretRefFn } from "./resolve-auth-token.js";
239
240
  import {
240
241
  runPatternReinforcement,
241
242
  type PatternReinforcementResult,
@@ -738,6 +739,9 @@ export class Orchestrator {
738
739
  private _dependencyPropagationRecovery: Promise<void> | null = null;
739
740
  private destroyed = false;
740
741
  private acceptingEntityMigrationMaintenance = true;
742
+ /** Aborted at the start of destroy(); stops every local-LLM client and extraction task at once. */
743
+ private readonly shutdownController = new AbortController();
744
+ readonly shutdownSignal: AbortSignal = this.shutdownController.signal;
741
745
 
742
746
  private get dependencyPropagationDelivery(): DependencyPropagationDelivery {
743
747
  if (this.destroyed) throw new Error("orchestrator has been destroyed");
@@ -769,9 +773,8 @@ export class Orchestrator {
769
773
  return this._providerBreaker;
770
774
  }
771
775
 
772
- /** The run-coordinator deps bundle, parameterized by its buffer accessor so
773
- * an isolated claim-backed drain can bind its own SmartBuffer (the daemon
774
- * backlog scheduler) while live extraction keeps `this.buffer`. */
776
+ /** The run-coordinator deps bundle, parameterized by its buffer accessor:
777
+ * an isolated claim-backed drain binds its own SmartBuffer (backlog scheduler). */
775
778
  private extractionRunDeps(getBuffer: () => SmartBuffer): ExtractionRunCoordinatorDeps {
776
779
  return {
777
780
  config: this.config,
@@ -794,9 +797,26 @@ export class Orchestrator {
794
797
  runTierMigrationCycle: (storage, trigger, options) => this.runTierMigrationCycle(storage, trigger, options),
795
798
  recordProcessedExtractionFingerprint: (storage, fingerprint, preloadedMeta) =>
796
799
  this.recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta),
800
+ shutdownSignal: this.shutdownSignal,
797
801
  };
798
802
  }
799
803
 
804
+ /** Fast-tier client: low latency at all costs, thinking always suppressed. */
805
+ private buildFastLlm(config: PluginConfig): LocalLlmClient {
806
+ const client = new LocalLlmClient(
807
+ {
808
+ ...config,
809
+ localLlmModel: config.localLlmFastModel || config.localLlmModel,
810
+ localLlmUrl: config.localLlmFastUrl,
811
+ localLlmTimeoutMs: config.localLlmFastTimeoutMs,
812
+ },
813
+ this.modelRegistry,
814
+ this.shutdownSignal,
815
+ );
816
+ client.disableThinking = true;
817
+ return client;
818
+ }
819
+
800
820
  private get extractionRunCoordinator(): ExtractionRunCoordinator {
801
821
  if (!this._extractionRunCoordinator) {
802
822
  this._extractionRunCoordinator = new ExtractionRunCoordinator(this.extractionRunDeps(() => this.buffer));
@@ -982,6 +1002,8 @@ export class Orchestrator {
982
1002
  * commands should call it before returning to let Node exit naturally.
983
1003
  */
984
1004
  async destroy(): Promise<void> {
1005
+ // First, always: every client and extraction task holds this signal.
1006
+ this.shutdownController.abort();
985
1007
  this.acceptingEntityMigrationMaintenance = false;
986
1008
  this._orchestratorInitCoordinator?.retireStartupEpoch();
987
1009
  this.abortDeferredInit();
@@ -995,23 +1017,29 @@ export class Orchestrator {
995
1017
  await this.maintenanceScheduler.dispose();
996
1018
  await this._dependencyPropagationRecovery;
997
1019
  this._dependencyPropagationRecovery = null;
1020
+ // Persist unsent turns BEFORE the extraction drain: buffered turns must
1021
+ // already be on disk when shutdown abandons or bounds the drain's wait.
1022
+ let bufferFlushError: unknown;
1023
+ try {
1024
+ await this.buffer.flushPendingSave({ throwOnFailure: true });
1025
+ } catch (err) {
1026
+ bufferFlushError = err;
1027
+ }
998
1028
  const extractionDrainError = await drainExtractionAndShutdownDependencyPropagation(
999
1029
  this.extractionQueueCoordinator,
1000
1030
  this._dependencyPropagationDelivery,
1001
1031
  );
1032
+ // After the drain, never before: an extraction already in its persist
1033
+ // stage reads dependencyPropagationDelivery, and this flag gates that
1034
+ // getter ("orchestrator has been destroyed").
1002
1035
  this.destroyed = true;
1003
1036
  this._dependencyPropagationDelivery = undefined;
1037
+ // Persist post-drain removals; a failed write stays pending for next boot.
1038
+ await this.buffer.flushPendingSave().catch(() => undefined);
1004
1039
  await drainRecallWrites(this);
1005
1040
  await this.persistenceIndexCoordinator
1006
1041
  .drainContentHashReconcileRetries()
1007
1042
  .catch((err) => log.warn(`content-hash reconcile drain failed during destroy: ${err}`));
1008
- // Save buffered turns before catalog flush; rethrow save failures after teardown.
1009
- let bufferFlushError: unknown;
1010
- try {
1011
- await this.buffer.flushPendingSave({ throwOnFailure: true });
1012
- } catch (err) {
1013
- bufferFlushError = err;
1014
- }
1015
1043
  try {
1016
1044
  // Flush catalog touches before backend disposal.
1017
1045
  await this.namespaceCatalog.flushPendingTouches().catch(() => undefined);
@@ -1667,35 +1695,16 @@ export class Orchestrator {
1667
1695
  config.gatewayConfig,
1668
1696
  this.modelRegistry,
1669
1697
  this.transcript,
1698
+ this.shutdownSignal,
1670
1699
  );
1671
1700
  this.judgeVerdictCache = createVerdictCache();
1672
1701
  this.judgeDeferCounts = createDeferCountMap();
1673
- this.localLlm = new LocalLlmClient(config, this.modelRegistry);
1674
- // Issue #548: the main local-LLM client is used by extraction,
1675
- // consolidation, and other structured-output tasks that gain
1676
- // nothing from chain-of-thought reasoning. Apply the operator's
1677
- // configured preference (default true) so thinking-capable models
1678
- // skip reasoning tokens and avoid the common 60s extraction
1679
- // timeout. Operators can set `localLlmDisableThinking: false`
1680
- // when they want thinking enabled for narrative paths.
1702
+ this.localLlm = new LocalLlmClient(config, this.modelRegistry, this.shutdownSignal);
1703
+ // Operator-controlled thinking suppression for structured-output ops;
1704
+ // full rationale on THINKING_SUPPRESSED_OPERATIONS in local-llm.ts (issue #548).
1681
1705
  this.localLlm.disableThinking = config.localLlmDisableThinking;
1682
1706
  this.fastLlm = resolvePipelineProcessingCapabilities(this.config).localLlmFast
1683
- ? (() => {
1684
- const client = new LocalLlmClient(
1685
- {
1686
- ...config,
1687
- localLlmModel: config.localLlmFastModel || config.localLlmModel,
1688
- localLlmUrl: config.localLlmFastUrl,
1689
- localLlmTimeoutMs: config.localLlmFastTimeoutMs,
1690
- },
1691
- this.modelRegistry,
1692
- );
1693
- // Fast-tier always suppresses thinking — the contract of
1694
- // `fastLlm` is "low latency at all costs" and that is
1695
- // independent of the main-client config.
1696
- client.disableThinking = true;
1697
- return client;
1698
- })()
1707
+ ? this.buildFastLlm(config)
1699
1708
  : this.localLlm;
1700
1709
  this.semanticConsolidationCoordinator = new SemanticConsolidationCoordinator({
1701
1710
  config,
@@ -1714,11 +1723,7 @@ export class Orchestrator {
1714
1723
  )
1715
1724
  : null;
1716
1725
  if (config.modelSource === "gateway") {
1717
- log.debug(
1718
- `orchestrator: gateway model source active` +
1719
- (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : "") +
1720
- (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : ""),
1721
- );
1726
+ log.debug(`orchestrator: gateway model source active (primary: ${config.gatewayAgentId ?? "none"}, fast: ${config.fastGatewayAgentId ?? "none"})`);
1722
1727
  }
1723
1728
  this.extraction = new ExtractionEngine(
1724
1729
  config,
@@ -1972,18 +1977,11 @@ export class Orchestrator {
1972
1977
  };
1973
1978
  }
1974
1979
 
1975
- /**
1976
- * Build a briefing follow-up generator backed by the configured LLM chain
1977
- * (gateway model source or local LLM). Returns `undefined` when no chain
1978
- * is available so `buildBriefing` can surface a clear unavailable reason
1979
- * instead of failing at call time. Used by the access service and CLI as
1980
- * the fallback when no direct `openaiApiKey` is configured, so briefing
1981
- * follow-ups ride the same routing as every other fast-tier LLM feature.
1982
- */
1980
+ /** Briefing follow-up generator over the configured LLM chain, or
1981
+ * `undefined` when no chain is available (see buildBriefing). */
1983
1982
  get briefingChainFollowupGenerator(): BriefingFollowupGenerator | undefined {
1984
- // Plugin mode gates on `localLlmEnabled` alone: `LocalLlmClient.chatCompletion`
1985
- // returns null when the master switch is off, so `localLlmFastEnabled` by
1986
- // itself cannot serve requests (Cursor review on PR #1463).
1983
+ // Plugin mode gates on `localLlmEnabled` alone: chatCompletion returns
1984
+ // null when the master switch is off (Cursor review on PR #1463).
1987
1985
  const chainAvailable =
1988
1986
  this.config.modelSource === "gateway"
1989
1987
  ? this._fastGatewayLlm?.isAvailable(
@@ -2116,20 +2114,19 @@ export class Orchestrator {
2116
2114
  async runLiveConnectors(options: {
2117
2115
  force?: boolean;
2118
2116
  abortSignal?: AbortSignal;
2117
+ resolveSecretRef?: ResolveSecretRefFn | null;
2119
2118
  } = {}): Promise<LiveConnectorsRunSummary> {
2120
2119
  return runLiveConnectorsOnce({
2121
2120
  memoryDir: this.config.memoryDir,
2122
2121
  connectors: this.config.connectors,
2123
2122
  force: options.force === true,
2124
2123
  abortSignal: options.abortSignal,
2124
+ resolveSecretRef: options.resolveSecretRef,
2125
2125
  ingestDocuments: async (docs) => {
2126
2126
  const fetchedAt = new Date().toISOString();
2127
2127
  const turns = docs.map((doc) => ({
2128
- role: "assistant" as const,
2129
- content: doc.title
2130
- ? `# ${doc.title}\n\n${doc.content}`
2131
- : doc.content,
2132
- timestamp: fetchedAt,
2128
+ role: "assistant" as const, timestamp: fetchedAt,
2129
+ content: doc.title ? `# ${doc.title}\n\n${doc.content}` : doc.content,
2133
2130
  }));
2134
2131
  await this.ingestBulkImportBatch(turns);
2135
2132
  },