@remnic/core 10.0.48 → 10.0.50

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 (449) hide show
  1. package/dist/access-admin-ops-surface.js +73 -70
  2. package/dist/access-audit.js +2 -2
  3. package/dist/access-authorization-probe.js +74 -71
  4. package/dist/access-boundary.js +73 -70
  5. package/dist/access-cli.js +170 -167
  6. package/dist/access-cli.js.map +1 -1
  7. package/dist/access-extraction-force-flush.js +73 -70
  8. package/dist/access-http-briefing.d.ts +2 -0
  9. package/dist/access-http-briefing.d.ts.map +1 -1
  10. package/dist/access-http-briefing.js +74 -71
  11. package/dist/access-http-query.js +75 -72
  12. package/dist/access-http.d.ts.map +1 -1
  13. package/dist/access-http.js +96 -93
  14. package/dist/access-identity-continuity-surface.js +73 -70
  15. package/dist/access-lcm-surface.js +73 -70
  16. package/dist/access-mcp.js +85 -82
  17. package/dist/access-namespace-preflight.js +73 -70
  18. package/dist/access-observe-write-category.d.ts +1 -1
  19. package/dist/access-observe-write-category.d.ts.map +1 -1
  20. package/dist/access-observe-write-category.js +15 -14
  21. package/dist/access-observe-write-surface.d.ts.map +1 -1
  22. package/dist/access-observe-write-surface.js +73 -70
  23. package/dist/access-offline-manifest.js +9 -8
  24. package/dist/access-operations-batch.js +76 -73
  25. package/dist/access-operations.js +83 -80
  26. package/dist/access-recall-concurrency.js +73 -70
  27. package/dist/access-recall-response.js +73 -70
  28. package/dist/access-recall-surface.js +73 -70
  29. package/dist/access-schema.js +11 -10
  30. package/dist/access-service.d.ts +5 -0
  31. package/dist/access-service.d.ts.map +1 -1
  32. package/dist/access-service.js +73 -70
  33. package/dist/access-surface-catalog.js +75 -72
  34. package/dist/access-surface-catalog.js.map +1 -1
  35. package/dist/active-recall.js +32 -30
  36. package/dist/active-recall.js.map +1 -1
  37. package/dist/adapters/index.js +4 -4
  38. package/dist/adapters/registry.js +2 -2
  39. package/dist/{auto-sync-BNCBMU6H.js → auto-sync-UQQ6YJSB.js} +3 -3
  40. package/dist/briefing-deadline.d.ts +7 -0
  41. package/dist/briefing-deadline.d.ts.map +1 -0
  42. package/dist/briefing-deadline.js +13 -0
  43. package/dist/briefing-window.d.ts +12 -4
  44. package/dist/briefing-window.d.ts.map +1 -1
  45. package/dist/briefing-window.js +3 -1
  46. package/dist/briefing.d.ts +2 -0
  47. package/dist/briefing.d.ts.map +1 -1
  48. package/dist/briefing.js +22 -20
  49. package/dist/buffer.js +6 -6
  50. package/dist/calibration.js +2 -2
  51. package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
  52. package/dist/{capsule-merge-RNQUP2VL.js → capsule-merge-D4BTIJGK.js} +3 -3
  53. package/dist/capture-write-lock-scope.d.ts +7 -0
  54. package/dist/capture-write-lock-scope.d.ts.map +1 -0
  55. package/dist/capture-write-lock-scope.js +10 -0
  56. package/dist/causal-behavior.js +2 -2
  57. package/dist/causal-chain.js +2 -2
  58. package/dist/causal-consolidation.js +23 -22
  59. package/dist/causal-consolidation.js.map +1 -1
  60. package/dist/causal-retrieval.js +2 -2
  61. package/dist/causal-trajectory-graph.js +3 -3
  62. package/dist/causal-trajectory.js +1 -1
  63. package/dist/{chunk-FAKRTS3Y.js → chunk-2AKIVSHP.js} +2 -2
  64. package/dist/{chunk-EIYJK7OD.js → chunk-2M36PR7R.js} +2 -2
  65. package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
  66. package/dist/{chunk-6P6MZDBL.js → chunk-3NL4ALUP.js} +2 -2
  67. package/dist/{chunk-6CC2YCKG.js → chunk-43TUWQNR.js} +3 -3
  68. package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
  69. package/dist/{chunk-2NLCDNGA.js → chunk-564YP3DW.js} +2 -2
  70. package/dist/{chunk-5KGYR5VN.js → chunk-5DVOBBTV.js} +2 -2
  71. package/dist/{chunk-RT2GN6KQ.js → chunk-5FUDSK6Z.js} +2 -2
  72. package/dist/{chunk-B4XSXFKI.js → chunk-5G53JSRO.js} +2 -2
  73. package/dist/{chunk-BGK3SFCC.js → chunk-5X2H3X4J.js} +2 -2
  74. package/dist/{chunk-OXSTKCYK.js → chunk-6AEKSOWV.js} +33 -5
  75. package/dist/chunk-6AEKSOWV.js.map +1 -0
  76. package/dist/{chunk-4J7BNL7B.js → chunk-6ZQX3R66.js} +2 -2
  77. package/dist/{chunk-JNLYHJG7.js → chunk-74AY3S7U.js} +4 -4
  78. package/dist/{chunk-RUAIO5UA.js → chunk-7J6A5MV2.js} +2 -2
  79. package/dist/{chunk-A45QXZMU.js → chunk-7SAE6T36.js} +2 -2
  80. package/dist/chunk-7VLBZKNB.js +26 -0
  81. package/dist/chunk-7VLBZKNB.js.map +1 -0
  82. package/dist/{chunk-QE2XQM3S.js → chunk-7YVER7ZO.js} +2 -2
  83. package/dist/{chunk-IJH6METJ.js → chunk-A3UFV4K3.js} +4 -4
  84. package/dist/{chunk-LWRIGKFM.js → chunk-A5L5KGDI.js} +19 -1
  85. package/dist/chunk-A5L5KGDI.js.map +1 -0
  86. package/dist/{chunk-LXN737FX.js → chunk-AAANTXCQ.js} +2 -2
  87. package/dist/{chunk-I3IPXGFQ.js → chunk-AJJPXUE6.js} +4 -4
  88. package/dist/{chunk-2DPJFJFH.js → chunk-BNJAVRNJ.js} +11 -11
  89. package/dist/{chunk-YL564QS2.js → chunk-CCL2OXFO.js} +3 -3
  90. package/dist/{chunk-CHSRA76M.js → chunk-CRN3EPE2.js} +4 -3
  91. package/dist/chunk-CRN3EPE2.js.map +1 -0
  92. package/dist/{chunk-ZX5N5D6M.js → chunk-DAOMWGO2.js} +4 -4
  93. package/dist/{chunk-YUE7J2HZ.js → chunk-DMKTOCC7.js} +2 -2
  94. package/dist/chunk-DMKTOCC7.js.map +1 -0
  95. package/dist/{chunk-FRXS6SC7.js → chunk-EKUI7I2X.js} +20 -4
  96. package/dist/chunk-EKUI7I2X.js.map +1 -0
  97. package/dist/{chunk-PKPOO6X5.js → chunk-EKYWZYZJ.js} +25 -17
  98. package/dist/chunk-EKYWZYZJ.js.map +1 -0
  99. package/dist/{chunk-23ZMQONL.js → chunk-ERMT5WQM.js} +2 -2
  100. package/dist/{chunk-VTCNVGM6.js → chunk-EWBXMGXR.js} +2 -2
  101. package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
  102. package/dist/{chunk-XTN54NML.js → chunk-G3T6YMBO.js} +4 -4
  103. package/dist/{chunk-2JNBPOZ2.js → chunk-GDYLZ6FR.js} +3 -3
  104. package/dist/{chunk-DZPTR2XQ.js → chunk-GFAEKSFR.js} +2 -2
  105. package/dist/{chunk-L46MG2GE.js → chunk-GQIYL7OD.js} +400 -301
  106. package/dist/chunk-GQIYL7OD.js.map +1 -0
  107. package/dist/{chunk-M7LA4QBY.js → chunk-GXVXBYRA.js} +3 -3
  108. package/dist/{chunk-UXAF4RQM.js → chunk-HKOMHP6D.js} +27 -15
  109. package/dist/chunk-HKOMHP6D.js.map +1 -0
  110. package/dist/{chunk-JGMJZBFV.js → chunk-HPNXS6W6.js} +2 -2
  111. package/dist/{chunk-BFPF5N3H.js → chunk-HXFIILGF.js} +4 -4
  112. package/dist/{chunk-YBKQAVPZ.js → chunk-IMKOJVD4.js} +101 -81
  113. package/dist/chunk-IMKOJVD4.js.map +1 -0
  114. package/dist/{chunk-CMNL3QSL.js → chunk-IN6U2BS5.js} +2 -2
  115. package/dist/{chunk-BWRX322G.js → chunk-IUYXCTA7.js} +2 -2
  116. package/dist/{chunk-LU57EEJW.js → chunk-JBWD3J5U.js} +3 -3
  117. package/dist/chunk-JNA7LFMQ.js +41 -0
  118. package/dist/chunk-JNA7LFMQ.js.map +1 -0
  119. package/dist/{chunk-2V664H6O.js → chunk-JS44PBCM.js} +5 -5
  120. package/dist/{chunk-XKTHJHSQ.js → chunk-JZCBMKR5.js} +3 -3
  121. package/dist/{chunk-MXPVNDGO.js → chunk-K5QQXVG6.js} +12 -12
  122. package/dist/{chunk-BUKK5SWA.js → chunk-KQAFEZQX.js} +2 -2
  123. package/dist/{chunk-WUBGMV3G.js → chunk-KRAMCBIW.js} +9 -9
  124. package/dist/{chunk-NDMPRT3Z.js → chunk-KW5YZELC.js} +2 -2
  125. package/dist/{chunk-2RQR4TXV.js → chunk-LIBVANOF.js} +2 -2
  126. package/dist/{chunk-M7L5A2AT.js → chunk-LMMBV7QC.js} +4 -4
  127. package/dist/{chunk-PJBYVJKO.js → chunk-LXXIV7Y2.js} +2 -2
  128. package/dist/{chunk-MZCTS3ZG.js → chunk-M2DOJBH7.js} +2 -2
  129. package/dist/{chunk-WOPZ2P5Z.js → chunk-M4HRYLOA.js} +2 -2
  130. package/dist/{chunk-JCYEDMOY.js → chunk-M6TP6UYD.js} +3 -3
  131. package/dist/{chunk-KAUCVTAW.js → chunk-MLNXATFG.js} +2 -2
  132. package/dist/{chunk-2NX7JTST.js → chunk-MPWOAIIH.js} +2 -2
  133. package/dist/{chunk-RQLTCHUL.js → chunk-MWURUSRE.js} +13 -13
  134. package/dist/{chunk-3EGL7XZO.js → chunk-N74WJ7B2.js} +2 -2
  135. package/dist/{chunk-DRXTMDAG.js → chunk-N7FNCE7F.js} +2 -2
  136. package/dist/{chunk-6CWAY4R7.js → chunk-NPLM7AFU.js} +2 -2
  137. package/dist/{chunk-VECRSYQG.js → chunk-NRGQ5HJO.js} +1 -1
  138. package/dist/{chunk-PPDNG7WC.js → chunk-NSP5PIQH.js} +2 -2
  139. package/dist/{chunk-6HVLHIAB.js → chunk-P7OVFGMU.js} +2 -2
  140. package/dist/{chunk-EX27VKU6.js → chunk-PDTNQLPC.js} +2 -2
  141. package/dist/{chunk-ME5LVISI.js → chunk-PJCVI44H.js} +2 -2
  142. package/dist/{chunk-LJCHDFLP.js → chunk-Q3PNQYAC.js} +2 -2
  143. package/dist/{chunk-YFJHFEET.js → chunk-QS765SBL.js} +2 -2
  144. package/dist/{chunk-FJ264QBP.js → chunk-QTDZ2NYC.js} +11 -11
  145. package/dist/{chunk-Q6UZREJK.js → chunk-RKRX4C4H.js} +2 -2
  146. package/dist/{chunk-YFXRLRKP.js → chunk-S4OZKPBS.js} +7 -11
  147. package/dist/{chunk-YFXRLRKP.js.map → chunk-S4OZKPBS.js.map} +1 -1
  148. package/dist/{chunk-GLZWOIU3.js → chunk-SJTSWG2Z.js} +3 -3
  149. package/dist/{chunk-Y57GJDG5.js → chunk-SWRRZNHM.js} +14 -17
  150. package/dist/chunk-SWRRZNHM.js.map +1 -0
  151. package/dist/{chunk-CCTLRRV6.js → chunk-TEH5MDX5.js} +55 -34
  152. package/dist/chunk-TEH5MDX5.js.map +1 -0
  153. package/dist/{chunk-XM747YJF.js → chunk-TFWJXWL6.js} +2 -2
  154. package/dist/{chunk-QFQ4UG3I.js → chunk-TXKQBQYW.js} +4 -4
  155. package/dist/{chunk-BMOJFGVX.js → chunk-UALXWWGN.js} +2 -2
  156. package/dist/{chunk-B44NFHWI.js → chunk-UNOAVHV4.js} +2 -2
  157. package/dist/{chunk-TF5NZGPS.js → chunk-UQBOPCDK.js} +2 -2
  158. package/dist/{chunk-SUKPM6DV.js → chunk-UWMZT2TY.js} +47 -4
  159. package/dist/chunk-UWMZT2TY.js.map +1 -0
  160. package/dist/{chunk-5R2IF2KI.js → chunk-UXGXJUZ5.js} +7 -7
  161. package/dist/{chunk-FWV2SXSL.js → chunk-UZVQFGAY.js} +101 -98
  162. package/dist/chunk-UZVQFGAY.js.map +1 -0
  163. package/dist/{chunk-J6B6FK2X.js → chunk-VCOMACR6.js} +53 -53
  164. package/dist/{chunk-WCGJK4NQ.js → chunk-VKQI47DJ.js} +7 -7
  165. package/dist/{chunk-MPJDQC4G.js → chunk-WJCXUE2J.js} +2 -2
  166. package/dist/{chunk-BCDECPVO.js → chunk-WV4UYDP6.js} +2 -2
  167. package/dist/{chunk-VWJ56T63.js → chunk-WXJC2L66.js} +2 -2
  168. package/dist/chunk-X2KO4FK5.js +40 -0
  169. package/dist/chunk-X2KO4FK5.js.map +1 -0
  170. package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
  171. package/dist/{chunk-FPANDKMQ.js → chunk-XC3H7KON.js} +2 -2
  172. package/dist/{chunk-OOOX5C4X.js → chunk-XL2EE5W3.js} +4 -4
  173. package/dist/{chunk-3DKKZVXS.js → chunk-XTXWR6KQ.js} +26 -11
  174. package/dist/chunk-XTXWR6KQ.js.map +1 -0
  175. package/dist/{chunk-3SL52JKD.js → chunk-XVZA6VXC.js} +4 -4
  176. package/dist/{chunk-CZVNOTLR.js → chunk-XXR4A33N.js} +2 -2
  177. package/dist/{chunk-2AV2U2SZ.js → chunk-YDIOMDBW.js} +2 -2
  178. package/dist/{chunk-XTVH2NAW.js → chunk-YECEEJUU.js} +3 -3
  179. package/dist/{chunk-QR6W3FSW.js → chunk-Z5277JWF.js} +3 -3
  180. package/dist/{chunk-CTHYR4QK.js → chunk-ZFNXJEUG.js} +2 -2
  181. package/dist/{chunk-6Q56WDHG.js → chunk-ZLCBLDJO.js} +2 -2
  182. package/dist/{chunk-VY6BD5KB.js → chunk-ZMO2S5RT.js} +12 -10
  183. package/dist/chunk-ZMO2S5RT.js.map +1 -0
  184. package/dist/{chunk-KRACAE73.js → chunk-ZNRTHYYW.js} +6 -6
  185. package/dist/{chunk-7AIPWNM7.js → chunk-ZSMA67FV.js} +2 -2
  186. package/dist/cli.js +123 -120
  187. package/dist/coding/export-okf-codegraph.js +19 -18
  188. package/dist/coding/export-okf-codegraph.js.map +1 -1
  189. package/dist/coding/pre-action-gate.js +2 -2
  190. package/dist/compounding/engine.js +21 -20
  191. package/dist/config.js +32 -30
  192. package/dist/connectors/codex-materialize-runner.js +20 -19
  193. package/dist/connectors/index.js +20 -19
  194. package/dist/consolidation-provenance-check.js +4 -4
  195. package/dist/consolidation-undo.js +2 -2
  196. package/dist/convergence-refresh.js +22 -21
  197. package/dist/corpus-watermark.js +22 -21
  198. package/dist/correction/passive-correction-notifications.d.ts +1 -1
  199. package/dist/correction/passive-correction-notifications.d.ts.map +1 -1
  200. package/dist/dashboard-runtime.js +2 -2
  201. package/dist/deep-recall-http-glue.js +12 -11
  202. package/dist/deep-recall.js +2 -2
  203. package/dist/embedding-fallback.js +3 -2
  204. package/dist/embedding-generation-marker.d.ts +16 -0
  205. package/dist/embedding-generation-marker.d.ts.map +1 -0
  206. package/dist/embedding-generation-marker.js +19 -0
  207. package/dist/embedding-generation-marker.js.map +1 -0
  208. package/dist/embedding-index-storage.d.ts +2 -4
  209. package/dist/embedding-index-storage.d.ts.map +1 -1
  210. package/dist/embedding-index-storage.js +2 -1
  211. package/dist/{entity-canonical-id-migration-2YOLMOFC.js → entity-canonical-id-migration-ZBNRGUNV.js} +3 -3
  212. package/dist/entity-canonical-id-migration-ZBNRGUNV.js.map +1 -0
  213. package/dist/entity-retrieval.js +22 -21
  214. package/dist/event-order-recall.js +2 -2
  215. package/dist/explicit-capture.js +3 -3
  216. package/dist/external-wiki-access.js +74 -71
  217. package/dist/extraction-span-materialize.js +2 -2
  218. package/dist/extraction.js +30 -29
  219. package/dist/{graph-edge-decay-3HVLMT6U.js → graph-edge-decay-IU75NV42.js} +6 -6
  220. package/dist/graph-edge-decay-IU75NV42.js.map +1 -0
  221. package/dist/graph-jsonl.js +4 -4
  222. package/dist/graph-snapshot.js +4 -4
  223. package/dist/graph.js +5 -5
  224. package/dist/harmonic-retrieval.js +20 -19
  225. package/dist/index.d.ts +2 -1
  226. package/dist/index.d.ts.map +1 -1
  227. package/dist/index.js +230 -218
  228. package/dist/lcm/engine.js +3 -3
  229. package/dist/lcm/index.js +5 -5
  230. package/dist/local-llm.js +2 -2
  231. package/dist/location/index.js +25 -24
  232. package/dist/location/tagging.d.ts +7 -5
  233. package/dist/location/tagging.d.ts.map +1 -1
  234. package/dist/maintenance/memory-governance.js +20 -19
  235. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +20 -19
  236. package/dist/maintenance/rebuild-memory-projection-runner.js +22 -21
  237. package/dist/maintenance/rebuild-memory-projection.js +21 -20
  238. package/dist/memory-browse-operations.js +74 -71
  239. package/dist/memory-browse.js +5 -5
  240. package/dist/namespaces/migrate.js +21 -20
  241. package/dist/namespaces/search.js +6 -6
  242. package/dist/namespaces/storage.js +20 -19
  243. package/dist/offline-sync-changeset-generations.js +5 -4
  244. package/dist/offline-sync-embedding-generation.d.ts +12 -2
  245. package/dist/offline-sync-embedding-generation.d.ts.map +1 -1
  246. package/dist/offline-sync-embedding-generation.js +6 -3
  247. package/dist/offline-sync-file-io.d.ts +15 -0
  248. package/dist/offline-sync-file-io.d.ts.map +1 -1
  249. package/dist/offline-sync-file-io.js +9 -1
  250. package/dist/offline-sync-snapshot-stream.js +9 -8
  251. package/dist/offline-sync-upload-staging.js +2 -2
  252. package/dist/offline-sync.d.ts.map +1 -1
  253. package/dist/offline-sync.js +10 -9
  254. package/dist/operator-doctor-corpus.js +23 -22
  255. package/dist/operator-toolkit.js +45 -43
  256. package/dist/orchestration/maintenance.js +33 -32
  257. package/dist/orchestrator.d.ts +1 -0
  258. package/dist/orchestrator.d.ts.map +1 -1
  259. package/dist/orchestrator.js +170 -167
  260. package/dist/page-versioning.js +2 -2
  261. package/dist/qmd.js +2 -2
  262. package/dist/recall-navigation-operations.js +74 -71
  263. package/dist/recall-navigation.js +73 -70
  264. package/dist/recall-state-view-admission.js +5 -5
  265. package/dist/recall-why-service.js +5 -5
  266. package/dist/resume-bundles.js +33 -31
  267. package/dist/search/factory.js +5 -5
  268. package/dist/search/index.js +9 -9
  269. package/dist/semantic-consolidation.js +25 -24
  270. package/dist/semantic-rule-promotion.js +20 -19
  271. package/dist/semantic-rule-verifier.js +20 -19
  272. package/dist/source-agent-qualifier.js +24 -23
  273. package/dist/standup/build.js +20 -19
  274. package/dist/storage/entity-canonical-id-migration-adapter.d.ts +1 -0
  275. package/dist/storage/entity-canonical-id-migration-adapter.d.ts.map +1 -1
  276. package/dist/storage/entity-canonical-id-migration.d.ts +7 -0
  277. package/dist/storage/entity-canonical-id-migration.d.ts.map +1 -1
  278. package/dist/storage/entity-canonical-id-references.d.ts +2 -0
  279. package/dist/storage/entity-canonical-id-references.d.ts.map +1 -1
  280. package/dist/storage/entity-migration-completion-cache.d.ts +46 -0
  281. package/dist/storage/entity-migration-completion-cache.d.ts.map +1 -0
  282. package/dist/storage/entity-store.d.ts +1 -8
  283. package/dist/storage/entity-store.d.ts.map +1 -1
  284. package/dist/storage/memory-read-store.d.ts +3 -2
  285. package/dist/storage/memory-read-store.d.ts.map +1 -1
  286. package/dist/storage/windowed-memory-read.d.ts +6 -0
  287. package/dist/storage/windowed-memory-read.d.ts.map +1 -1
  288. package/dist/storage.d.ts +2 -0
  289. package/dist/storage.d.ts.map +1 -1
  290. package/dist/storage.js +19 -18
  291. package/dist/summarizer.js +3 -3
  292. package/dist/support-passport/index.js +76 -73
  293. package/dist/transfer/backup.js +2 -2
  294. package/dist/transfer/capsule-export.js +2 -2
  295. package/dist/transfer/capsule-import.js +4 -4
  296. package/dist/transfer/export-okf.js +20 -19
  297. package/dist/verified-recall.js +20 -19
  298. package/dist/who-knows-cli.js +21 -20
  299. package/dist/who-knows.js +20 -19
  300. package/package.json +2 -2
  301. package/src/access-http-briefing.ts +4 -0
  302. package/src/access-http.test.ts +40 -11
  303. package/src/access-http.ts +6 -0
  304. package/src/access-observe-write-category.ts +1 -1
  305. package/src/access-observe-write-surface.ts +24 -19
  306. package/src/access-operations-batch.ts +18 -2
  307. package/src/access-service-peer-capture-backoff.test.ts +236 -0
  308. package/src/access-service.ts +11 -2
  309. package/src/briefing-abort.test.ts +173 -0
  310. package/src/briefing-deadline.test.ts +84 -0
  311. package/src/briefing-deadline.ts +33 -0
  312. package/src/briefing-window-abort.test.ts +47 -0
  313. package/src/briefing-window.ts +33 -4
  314. package/src/briefing.ts +23 -16
  315. package/src/capture-write-lock-scope.test.ts +32 -0
  316. package/src/capture-write-lock-scope.ts +30 -0
  317. package/src/correction/passive-correction-notifications-abort.test.ts +42 -0
  318. package/src/correction/passive-correction-notifications.ts +4 -0
  319. package/src/embedding-generation-marker.ts +51 -0
  320. package/src/embedding-index-storage.ts +13 -29
  321. package/src/entity-lazy-compatibility.test.ts +229 -0
  322. package/src/entity-migration-completion-notification.test.ts +148 -0
  323. package/src/index.ts +2 -2
  324. package/src/location/tagging.ts +14 -12
  325. package/src/offline-sync-embedding-delete-digest.test.ts +58 -0
  326. package/src/offline-sync-embedding-generation-marker.test.ts +245 -0
  327. package/src/offline-sync-embedding-generation.ts +47 -2
  328. package/src/offline-sync-embedding-lock-loss.test.ts +42 -0
  329. package/src/offline-sync-file-io.ts +61 -2
  330. package/src/offline-sync.test.ts +313 -20
  331. package/src/offline-sync.ts +47 -22
  332. package/src/orchestrator-init.test.ts +49 -1
  333. package/src/orchestrator.ts +9 -8
  334. package/src/storage/entity-canonical-id-migration-adapter.ts +16 -1
  335. package/src/storage/entity-canonical-id-migration.ts +17 -8
  336. package/src/storage/entity-canonical-id-references.ts +24 -0
  337. package/src/storage/entity-migration-completion-cache.nofollow.test.ts +223 -0
  338. package/src/storage/entity-migration-completion-cache.ts +153 -0
  339. package/src/storage/entity-store.ts +58 -86
  340. package/src/storage/memory-read-store.ts +9 -3
  341. package/src/storage/windowed-memory-read.ts +8 -0
  342. package/src/storage-startup-nonblocking-migration.test.ts +183 -0
  343. package/src/storage.ts +9 -3
  344. package/src/testing/subjects/entity-migration-completion-cache.test.ts +90 -0
  345. package/dist/chunk-3DKKZVXS.js.map +0 -1
  346. package/dist/chunk-CCTLRRV6.js.map +0 -1
  347. package/dist/chunk-CHSRA76M.js.map +0 -1
  348. package/dist/chunk-FRXS6SC7.js.map +0 -1
  349. package/dist/chunk-FWV2SXSL.js.map +0 -1
  350. package/dist/chunk-L46MG2GE.js.map +0 -1
  351. package/dist/chunk-LWRIGKFM.js.map +0 -1
  352. package/dist/chunk-OXSTKCYK.js.map +0 -1
  353. package/dist/chunk-PKPOO6X5.js.map +0 -1
  354. package/dist/chunk-SUKPM6DV.js.map +0 -1
  355. package/dist/chunk-UXAF4RQM.js.map +0 -1
  356. package/dist/chunk-VY6BD5KB.js.map +0 -1
  357. package/dist/chunk-Y57GJDG5.js.map +0 -1
  358. package/dist/chunk-YBKQAVPZ.js.map +0 -1
  359. package/dist/chunk-YUE7J2HZ.js.map +0 -1
  360. /package/dist/{auto-sync-BNCBMU6H.js.map → auto-sync-UQQ6YJSB.js.map} +0 -0
  361. /package/dist/{capsule-crypto-GWVG7LGC.js.map → briefing-deadline.js.map} +0 -0
  362. /package/dist/{entity-canonical-id-migration-2YOLMOFC.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
  363. /package/dist/{capsule-merge-RNQUP2VL.js.map → capsule-merge-D4BTIJGK.js.map} +0 -0
  364. /package/dist/{graph-edge-decay-3HVLMT6U.js.map → capture-write-lock-scope.js.map} +0 -0
  365. /package/dist/{chunk-FAKRTS3Y.js.map → chunk-2AKIVSHP.js.map} +0 -0
  366. /package/dist/{chunk-EIYJK7OD.js.map → chunk-2M36PR7R.js.map} +0 -0
  367. /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
  368. /package/dist/{chunk-6P6MZDBL.js.map → chunk-3NL4ALUP.js.map} +0 -0
  369. /package/dist/{chunk-6CC2YCKG.js.map → chunk-43TUWQNR.js.map} +0 -0
  370. /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
  371. /package/dist/{chunk-2NLCDNGA.js.map → chunk-564YP3DW.js.map} +0 -0
  372. /package/dist/{chunk-5KGYR5VN.js.map → chunk-5DVOBBTV.js.map} +0 -0
  373. /package/dist/{chunk-RT2GN6KQ.js.map → chunk-5FUDSK6Z.js.map} +0 -0
  374. /package/dist/{chunk-B4XSXFKI.js.map → chunk-5G53JSRO.js.map} +0 -0
  375. /package/dist/{chunk-BGK3SFCC.js.map → chunk-5X2H3X4J.js.map} +0 -0
  376. /package/dist/{chunk-4J7BNL7B.js.map → chunk-6ZQX3R66.js.map} +0 -0
  377. /package/dist/{chunk-JNLYHJG7.js.map → chunk-74AY3S7U.js.map} +0 -0
  378. /package/dist/{chunk-RUAIO5UA.js.map → chunk-7J6A5MV2.js.map} +0 -0
  379. /package/dist/{chunk-A45QXZMU.js.map → chunk-7SAE6T36.js.map} +0 -0
  380. /package/dist/{chunk-QE2XQM3S.js.map → chunk-7YVER7ZO.js.map} +0 -0
  381. /package/dist/{chunk-IJH6METJ.js.map → chunk-A3UFV4K3.js.map} +0 -0
  382. /package/dist/{chunk-LXN737FX.js.map → chunk-AAANTXCQ.js.map} +0 -0
  383. /package/dist/{chunk-I3IPXGFQ.js.map → chunk-AJJPXUE6.js.map} +0 -0
  384. /package/dist/{chunk-2DPJFJFH.js.map → chunk-BNJAVRNJ.js.map} +0 -0
  385. /package/dist/{chunk-YL564QS2.js.map → chunk-CCL2OXFO.js.map} +0 -0
  386. /package/dist/{chunk-ZX5N5D6M.js.map → chunk-DAOMWGO2.js.map} +0 -0
  387. /package/dist/{chunk-23ZMQONL.js.map → chunk-ERMT5WQM.js.map} +0 -0
  388. /package/dist/{chunk-VTCNVGM6.js.map → chunk-EWBXMGXR.js.map} +0 -0
  389. /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
  390. /package/dist/{chunk-XTN54NML.js.map → chunk-G3T6YMBO.js.map} +0 -0
  391. /package/dist/{chunk-2JNBPOZ2.js.map → chunk-GDYLZ6FR.js.map} +0 -0
  392. /package/dist/{chunk-DZPTR2XQ.js.map → chunk-GFAEKSFR.js.map} +0 -0
  393. /package/dist/{chunk-M7LA4QBY.js.map → chunk-GXVXBYRA.js.map} +0 -0
  394. /package/dist/{chunk-JGMJZBFV.js.map → chunk-HPNXS6W6.js.map} +0 -0
  395. /package/dist/{chunk-BFPF5N3H.js.map → chunk-HXFIILGF.js.map} +0 -0
  396. /package/dist/{chunk-CMNL3QSL.js.map → chunk-IN6U2BS5.js.map} +0 -0
  397. /package/dist/{chunk-BWRX322G.js.map → chunk-IUYXCTA7.js.map} +0 -0
  398. /package/dist/{chunk-LU57EEJW.js.map → chunk-JBWD3J5U.js.map} +0 -0
  399. /package/dist/{chunk-2V664H6O.js.map → chunk-JS44PBCM.js.map} +0 -0
  400. /package/dist/{chunk-XKTHJHSQ.js.map → chunk-JZCBMKR5.js.map} +0 -0
  401. /package/dist/{chunk-MXPVNDGO.js.map → chunk-K5QQXVG6.js.map} +0 -0
  402. /package/dist/{chunk-BUKK5SWA.js.map → chunk-KQAFEZQX.js.map} +0 -0
  403. /package/dist/{chunk-WUBGMV3G.js.map → chunk-KRAMCBIW.js.map} +0 -0
  404. /package/dist/{chunk-NDMPRT3Z.js.map → chunk-KW5YZELC.js.map} +0 -0
  405. /package/dist/{chunk-2RQR4TXV.js.map → chunk-LIBVANOF.js.map} +0 -0
  406. /package/dist/{chunk-M7L5A2AT.js.map → chunk-LMMBV7QC.js.map} +0 -0
  407. /package/dist/{chunk-PJBYVJKO.js.map → chunk-LXXIV7Y2.js.map} +0 -0
  408. /package/dist/{chunk-MZCTS3ZG.js.map → chunk-M2DOJBH7.js.map} +0 -0
  409. /package/dist/{chunk-WOPZ2P5Z.js.map → chunk-M4HRYLOA.js.map} +0 -0
  410. /package/dist/{chunk-JCYEDMOY.js.map → chunk-M6TP6UYD.js.map} +0 -0
  411. /package/dist/{chunk-KAUCVTAW.js.map → chunk-MLNXATFG.js.map} +0 -0
  412. /package/dist/{chunk-2NX7JTST.js.map → chunk-MPWOAIIH.js.map} +0 -0
  413. /package/dist/{chunk-RQLTCHUL.js.map → chunk-MWURUSRE.js.map} +0 -0
  414. /package/dist/{chunk-3EGL7XZO.js.map → chunk-N74WJ7B2.js.map} +0 -0
  415. /package/dist/{chunk-DRXTMDAG.js.map → chunk-N7FNCE7F.js.map} +0 -0
  416. /package/dist/{chunk-6CWAY4R7.js.map → chunk-NPLM7AFU.js.map} +0 -0
  417. /package/dist/{chunk-VECRSYQG.js.map → chunk-NRGQ5HJO.js.map} +0 -0
  418. /package/dist/{chunk-PPDNG7WC.js.map → chunk-NSP5PIQH.js.map} +0 -0
  419. /package/dist/{chunk-6HVLHIAB.js.map → chunk-P7OVFGMU.js.map} +0 -0
  420. /package/dist/{chunk-EX27VKU6.js.map → chunk-PDTNQLPC.js.map} +0 -0
  421. /package/dist/{chunk-ME5LVISI.js.map → chunk-PJCVI44H.js.map} +0 -0
  422. /package/dist/{chunk-LJCHDFLP.js.map → chunk-Q3PNQYAC.js.map} +0 -0
  423. /package/dist/{chunk-YFJHFEET.js.map → chunk-QS765SBL.js.map} +0 -0
  424. /package/dist/{chunk-FJ264QBP.js.map → chunk-QTDZ2NYC.js.map} +0 -0
  425. /package/dist/{chunk-Q6UZREJK.js.map → chunk-RKRX4C4H.js.map} +0 -0
  426. /package/dist/{chunk-GLZWOIU3.js.map → chunk-SJTSWG2Z.js.map} +0 -0
  427. /package/dist/{chunk-XM747YJF.js.map → chunk-TFWJXWL6.js.map} +0 -0
  428. /package/dist/{chunk-QFQ4UG3I.js.map → chunk-TXKQBQYW.js.map} +0 -0
  429. /package/dist/{chunk-BMOJFGVX.js.map → chunk-UALXWWGN.js.map} +0 -0
  430. /package/dist/{chunk-B44NFHWI.js.map → chunk-UNOAVHV4.js.map} +0 -0
  431. /package/dist/{chunk-TF5NZGPS.js.map → chunk-UQBOPCDK.js.map} +0 -0
  432. /package/dist/{chunk-5R2IF2KI.js.map → chunk-UXGXJUZ5.js.map} +0 -0
  433. /package/dist/{chunk-J6B6FK2X.js.map → chunk-VCOMACR6.js.map} +0 -0
  434. /package/dist/{chunk-WCGJK4NQ.js.map → chunk-VKQI47DJ.js.map} +0 -0
  435. /package/dist/{chunk-MPJDQC4G.js.map → chunk-WJCXUE2J.js.map} +0 -0
  436. /package/dist/{chunk-BCDECPVO.js.map → chunk-WV4UYDP6.js.map} +0 -0
  437. /package/dist/{chunk-VWJ56T63.js.map → chunk-WXJC2L66.js.map} +0 -0
  438. /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
  439. /package/dist/{chunk-FPANDKMQ.js.map → chunk-XC3H7KON.js.map} +0 -0
  440. /package/dist/{chunk-OOOX5C4X.js.map → chunk-XL2EE5W3.js.map} +0 -0
  441. /package/dist/{chunk-3SL52JKD.js.map → chunk-XVZA6VXC.js.map} +0 -0
  442. /package/dist/{chunk-CZVNOTLR.js.map → chunk-XXR4A33N.js.map} +0 -0
  443. /package/dist/{chunk-2AV2U2SZ.js.map → chunk-YDIOMDBW.js.map} +0 -0
  444. /package/dist/{chunk-XTVH2NAW.js.map → chunk-YECEEJUU.js.map} +0 -0
  445. /package/dist/{chunk-QR6W3FSW.js.map → chunk-Z5277JWF.js.map} +0 -0
  446. /package/dist/{chunk-CTHYR4QK.js.map → chunk-ZFNXJEUG.js.map} +0 -0
  447. /package/dist/{chunk-6Q56WDHG.js.map → chunk-ZLCBLDJO.js.map} +0 -0
  448. /package/dist/{chunk-KRACAE73.js.map → chunk-ZNRTHYYW.js.map} +0 -0
  449. /package/dist/{chunk-7AIPWNM7.js.map → chunk-ZSMA67FV.js.map} +0 -0
package/dist/who-knows.js CHANGED
@@ -9,21 +9,21 @@ import {
9
9
  loadWhoKnowsEntities,
10
10
  tokenizeTopic,
11
11
  validateWhoKnowsInput
12
- } from "./chunk-JGMJZBFV.js";
13
- import "./chunk-L46MG2GE.js";
12
+ } from "./chunk-HPNXS6W6.js";
13
+ import "./chunk-GQIYL7OD.js";
14
14
  import "./chunk-UHVXE24Y.js";
15
15
  import "./chunk-DM5QZ3YU.js";
16
- import "./chunk-VY6BD5KB.js";
16
+ import "./chunk-ZMO2S5RT.js";
17
17
  import "./chunk-G6OFEGUR.js";
18
- import "./chunk-PJBYVJKO.js";
19
- import "./chunk-2V664H6O.js";
18
+ import "./chunk-LXXIV7Y2.js";
19
+ import "./chunk-JS44PBCM.js";
20
+ import "./chunk-5CWH2LKL.js";
20
21
  import "./chunk-XKDQTDXN.js";
21
22
  import "./chunk-CYEPCZN5.js";
22
23
  import "./chunk-XRFLR3XF.js";
23
24
  import "./chunk-7VO6E5UD.js";
24
- import "./chunk-EXYT52NR.js";
25
- import "./chunk-5CWH2LKL.js";
26
25
  import "./chunk-WNEVEMJ3.js";
26
+ import "./chunk-EXYT52NR.js";
27
27
  import "./chunk-Y5NLBXPV.js";
28
28
  import "./chunk-TFA6HPOA.js";
29
29
  import "./chunk-F4TWWUMP.js";
@@ -32,35 +32,37 @@ import "./chunk-A7Q43EUZ.js";
32
32
  import "./chunk-S2V7RUCL.js";
33
33
  import "./chunk-PPUNC7UX.js";
34
34
  import "./chunk-X3724WL4.js";
35
- import "./chunk-MRPOZBJC.js";
36
35
  import "./chunk-S2HLHAZ4.js";
37
- import "./chunk-LDXUBPMO.js";
36
+ import "./chunk-MRPOZBJC.js";
38
37
  import "./chunk-DM2T26WE.js";
38
+ import "./chunk-LDXUBPMO.js";
39
39
  import "./chunk-FF6N7BXC.js";
40
40
  import "./chunk-WXPBDEMW.js";
41
41
  import "./chunk-AAD2ZS6P.js";
42
- import "./chunk-MPJDQC4G.js";
42
+ import "./chunk-WJCXUE2J.js";
43
43
  import "./chunk-ZIKENA2C.js";
44
- import "./chunk-3ONXXHQO.js";
45
- import "./chunk-YXZG5TVN.js";
46
44
  import "./chunk-3OUGSOJP.js";
47
45
  import "./chunk-SCU65EZI.js";
48
- import "./chunk-P4GUQSK3.js";
46
+ import "./chunk-3ONXXHQO.js";
47
+ import "./chunk-YXZG5TVN.js";
49
48
  import "./chunk-3WU7XOFN.js";
50
- import "./chunk-G7D6GZ5J.js";
51
- import "./chunk-2NLCDNGA.js";
49
+ import "./chunk-P4GUQSK3.js";
50
+ import "./chunk-564YP3DW.js";
52
51
  import "./chunk-M5GVCJSJ.js";
53
52
  import "./chunk-RBOJCG4T.js";
54
- import "./chunk-LWRIGKFM.js";
53
+ import "./chunk-A5L5KGDI.js";
55
54
  import "./chunk-5WITETWU.js";
56
55
  import "./chunk-6CIAGZ6X.js";
57
56
  import "./chunk-7CT3AI52.js";
58
- import "./chunk-I3IPXGFQ.js";
57
+ import "./chunk-G7D6GZ5J.js";
58
+ import "./chunk-7VLBZKNB.js";
59
+ import "./chunk-UUZ7KZAO.js";
60
+ import "./chunk-AJJPXUE6.js";
59
61
  import "./chunk-G26YNEOC.js";
62
+ import "./chunk-VILPVT4S.js";
60
63
  import "./chunk-AF2XMJKD.js";
61
64
  import "./chunk-OR42ZI54.js";
62
65
  import "./chunk-IUM3VSHI.js";
63
- import "./chunk-VILPVT4S.js";
64
66
  import "./chunk-23G5P7TA.js";
65
67
  import "./chunk-C64XATK7.js";
66
68
  import "./chunk-42JKGUFJ.js";
@@ -70,7 +72,6 @@ import "./chunk-L2EXJQJP.js";
70
72
  import "./chunk-45GF7Y3V.js";
71
73
  import "./chunk-YIJECSIX.js";
72
74
  import "./chunk-E2AWJ7KQ.js";
73
- import "./chunk-UUZ7KZAO.js";
74
75
  import "./chunk-HADD45AR.js";
75
76
  import "./chunk-RNFMFC37.js";
76
77
  import "./chunk-YCVB7X56.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "10.0.48",
3
+ "version": "10.0.50",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3347,7 +3347,7 @@
3347
3347
  "core"
3348
3348
  ],
3349
3349
  "peerDependencies": {
3350
- "@remnic/coding-graph": "^10.0.48"
3350
+ "@remnic/coding-graph": "^10.0.50"
3351
3351
  },
3352
3352
  "peerDependenciesMeta": {
3353
3353
  "@remnic/coding-graph": {
@@ -9,6 +9,8 @@ export interface BriefingHttpOptions {
9
9
  service: EngramAccessService;
10
10
  principal: string | undefined;
11
11
  respondJson: JsonResponder;
12
+ /** HTTP request lifetime; aborting it stops the briefing (issue #3139). */
13
+ abortSignal?: AbortSignal;
12
14
  }
13
15
 
14
16
  /**
@@ -27,9 +29,11 @@ export async function respondBriefingHttp(options: BriefingHttpOptions): Promise
27
29
  if (!op) {
28
30
  throw new EngramAccessInputError("access-boundary: operation not registered: briefing");
29
31
  }
32
+ // SAFETY: the built-in briefing operation returns { result }; this adapter passes it through unchanged.
30
33
  const output = (await op.run(options.gatedBody, {
31
34
  service: options.service,
32
35
  authenticatedPrincipal: options.principal,
36
+ abortSignal: options.abortSignal,
33
37
  })) as { result: unknown };
34
38
  options.respondJson(200, output.result);
35
39
  }
@@ -15,11 +15,13 @@ import {
15
15
  EngramAccessInputError,
16
16
  type EngramAccessRecallRequest,
17
17
  type EngramAccessService,
18
+ type EngramAccessBriefingRequest,
18
19
  } from "./access-service.js";
19
20
  import {
20
21
  tokenCapabilityStore,
21
22
  type TokenCapabilities,
22
23
  } from "./access-token-capabilities.js";
24
+ import { BriefingTimeoutError } from "./briefing-deadline.js";
23
25
  import { parseConfig } from "./config.js";
24
26
  import { readPair, writePair } from "./contradiction/contradiction-review.js";
25
27
  import { createChatSession } from "./chat/chat-session.js";
@@ -859,17 +861,23 @@ test("HTTP briefing endpoint dispatches through the briefing operation", async (
859
861
  assert.equal(body.format, "markdown");
860
862
  assert.equal(body.markdown, "# Briefing");
861
863
  assert.deepEqual(body.json.sections.activeThreads, []);
862
- assert.deepEqual(calls, [
863
- {
864
- since: "24h",
865
- focus: undefined,
866
- includeLocation: undefined,
867
- namespace: "team",
868
- format: "markdown",
869
- maxFollowups: 5,
870
- principal: "panel-user",
871
- },
872
- ]);
864
+ assert.equal(calls.length, 1);
865
+ // SAFETY: the registered handler builds this request after validating the HTTP body; assertions below check its values.
866
+ const captured = calls[0] as EngramAccessBriefingRequest;
867
+ const { abortSignal, ...briefingRequest } = captured;
868
+ assert.ok(
869
+ abortSignal instanceof AbortSignal,
870
+ "the briefing request carries the HTTP request lifetime signal",
871
+ );
872
+ assert.deepEqual(briefingRequest, {
873
+ since: "24h",
874
+ focus: undefined,
875
+ includeLocation: undefined,
876
+ namespace: "team",
877
+ format: "markdown",
878
+ maxFollowups: 5,
879
+ principal: "panel-user",
880
+ });
873
881
 
874
882
  const invalid = await fetch(
875
883
  `http://127.0.0.1:${status.port}/engram/v1/briefing`,
@@ -890,6 +898,27 @@ test("HTTP briefing endpoint dispatches through the briefing operation", async (
890
898
  }
891
899
  });
892
900
 
901
+ test("HTTP briefing endpoint answers 504 briefing_timeout when the request budget is exhausted", async () => {
902
+ const service: EngramAccessService = Object.assign(Object.create(null), {
903
+ briefing: async () => {
904
+ throw new BriefingTimeoutError(30_000);
905
+ },
906
+ });
907
+ const server = new EngramAccessHttpServer({ service, port: 0, authToken: "test-token", adminConsoleEnabled: false });
908
+ const status = await server.start();
909
+ try {
910
+ const response = await fetch(`http://127.0.0.1:${status.port}/engram/v1/briefing`, {
911
+ method: "POST",
912
+ headers: { authorization: "Bearer test-token", "content-type": "application/json" },
913
+ body: JSON.stringify({}),
914
+ });
915
+ assert.equal(response.status, 504);
916
+ assert.deepEqual(await response.json(), { error: "briefing timed out after 30000ms", code: "briefing_timeout" });
917
+ } finally {
918
+ await server.stop();
919
+ }
920
+ });
921
+
893
922
  test("HTTP contradiction scan uses writable namespace resolver", async () => {
894
923
  const resolverCalls: Array<{
895
924
  namespace: string | undefined;
@@ -10,6 +10,7 @@ import { log } from "./logger.js";
10
10
  import { resolveNamespaceCapabilities } from "./capabilities.js";
11
11
  import { WriteRateLimiter, type WriteRateLimitReservation } from "./write-rate-limiter.js";
12
12
  import { abortError, isAbortError } from "./abort-error.js";
13
+ import { BriefingTimeoutError } from "./briefing-deadline.js";
13
14
  import { EngramAccessForbiddenError } from "./access-errors.js";
14
15
  import {
15
16
  EngramAccessInputError,
@@ -500,6 +501,10 @@ export class EngramAccessHttpServer extends ReviewDeckAccessHttpBase {
500
501
  res.once("close", abortDisconnectedRequest);
501
502
  correlationIdStore.run(correlationId, () => {
502
503
  void this.handle(req, res, correlationId, abortController.signal).catch((err) => {
504
+ if (err instanceof BriefingTimeoutError) {
505
+ this.respondJson(res, 504, { error: err.message, code: "briefing_timeout" });
506
+ return;
507
+ }
503
508
  if (isAbortError(err)) {
504
509
  if (!res.destroyed && !res.writableEnded) {
505
510
  res.end();
@@ -1979,6 +1984,7 @@ export class EngramAccessHttpServer extends ReviewDeckAccessHttpBase {
1979
1984
  service: this.service,
1980
1985
  principal: this.resolveRequestPrincipal(req),
1981
1986
  respondJson: (status, payload) => this.respondJson(res, status, payload),
1987
+ abortSignal,
1982
1988
  });
1983
1989
  return;
1984
1990
  }
@@ -15,7 +15,7 @@ import {
15
15
  } from "./access-schema.js";
16
16
 
17
17
  export { reapplyCategoryCoercion };
18
- export { applyBriefingLocationContext } from "./location/tagging.js";
18
+ export { buildWithBriefingLocation } from "./location/tagging.js";
19
19
 
20
20
  export function splitCanonicalWriteRequest<T extends { rawCategory?: string; category?: string }>(
21
21
  request: T,
@@ -29,8 +29,9 @@ import {
29
29
  type MemoryScopePlan,
30
30
  NamespaceNotWritableError,
31
31
  } from "./access-service.js";
32
- import { applyBriefingLocationContext, reapplyCategoryCoercion, splitCanonicalWriteRequest } from "./access-observe-write-category.js";
32
+ import { buildWithBriefingLocation, reapplyCategoryCoercion, splitCanonicalWriteRequest } from "./access-observe-write-category.js";
33
33
  import { abortError } from "./abort-error.js";
34
+ import { withBriefingDeadline } from "./briefing-deadline.js";
34
35
  import { extractionForceFlush } from "./access-extraction-force-flush.js";
35
36
  import { ObserveTranscriptPersister, observeTranscriptSessionKey } from "./access-observe-transcript.js";
36
37
  import { FileCalendarSource, buildBriefing, parseBriefingFocus, parseBriefingWindow } from "./briefing.js";
@@ -410,7 +411,6 @@ export class AccessObserveWriteSurface {
410
411
  }
411
412
 
412
413
  const namespace = this.deps.resolveReadableNamespace(request.namespace, request.principal);
413
- const storage = await this.deps.orchestrator.getStorage(namespace);
414
414
 
415
415
  const token =
416
416
  typeof request.since === "string" && request.since.trim().length > 0
@@ -457,23 +457,28 @@ export class AccessObserveWriteSurface {
457
457
  ? new FileCalendarSource(config.briefing.calendarSource)
458
458
  : undefined;
459
459
 
460
- const result = await applyBriefingLocationContext(await buildBriefing({
461
- storage,
462
- namespace,
463
- window,
464
- focus,
465
- calendarSource,
466
- maxFollowups,
467
- allowLlm: config.briefing.llmFollowups,
468
- openaiApiKey: config.openaiApiKey,
469
- openaiBaseUrl: config.openaiBaseUrl,
470
- model: config.model,
471
- // Without a direct OpenAI key, route follow-ups through the configured
472
- // LLM chain (gateway model source or local LLM) — same fallback every
473
- // other LLM feature uses. A configured key keeps its precedence so
474
- // existing deployments are unchanged.
475
- followupGenerator: config.openaiApiKey ? undefined : this.deps.orchestrator.briefingChainFollowupGenerator,
476
- }), request.includeLocation, storage.dir, window.from.toISOString(), config.location);
460
+ // Storage acquisition and the briefing body share one request budget.
461
+ const result = await withBriefingDeadline(async (signal) => {
462
+ const storage = await this.deps.orchestrator.getStorage(namespace);
463
+ return buildWithBriefingLocation(request.includeLocation, storage.dir, window.from.toISOString(), config.location, () => buildBriefing({
464
+ storage,
465
+ namespace,
466
+ window,
467
+ focus,
468
+ calendarSource,
469
+ maxFollowups,
470
+ allowLlm: config.briefing.llmFollowups,
471
+ openaiApiKey: config.openaiApiKey,
472
+ openaiBaseUrl: config.openaiBaseUrl,
473
+ model: config.model,
474
+ // Without a direct OpenAI key, route follow-ups through the configured
475
+ // LLM chain (gateway model source or local LLM) — same fallback every
476
+ // other LLM feature uses. A configured key keeps its precedence so
477
+ // existing deployments are unchanged.
478
+ followupGenerator: config.openaiApiKey ? undefined : this.deps.orchestrator.briefingChainFollowupGenerator,
479
+ abortSignal: signal,
480
+ }));
481
+ }, request.abortSignal);
477
482
 
478
483
  return {
479
484
  format,
@@ -23,7 +23,7 @@ import {
23
23
  retainedCategoryAlias,
24
24
  suggestionSubmitRequestSchema,
25
25
  } from "./access-schema.js";
26
- import { EngramAccessInputError, type EngramAccessService } from "./access-service.js";
26
+ import { EngramAccessInputError, type EngramAccessService, type EngramAccessBriefingRequest } from "./access-service.js";
27
27
  import { enforceNamespaceAllowList, tokenCapabilityStore } from "./access-token-capabilities.js";
28
28
  import { projectTagProjectId } from "./coding/coding-namespace.js";
29
29
  import {
@@ -381,7 +381,23 @@ defineOperation({ name: "memory_promote", description: "Promote memory.", schema
381
381
  defineOperation({ name: "memory_outcome", description: "Record outcome.", schema: strictSchema({ memoryId: S.str, outcome: S.str, namespace: S.str, sessionKey: S.str, timestamp: S.str }), handler: async (input, ctx) => { const o = optStr(input.outcome); if (o !== "success" && o !== "failure") throw new EngramAccessInputError("memory_outcome: outcome must be \"success\" or \"failure\"; got " + JSON.stringify(o)); return { result: await ctx.service.memoryOutcome({ memoryId: optStr(input.memoryId) ?? "", outcome: o, namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey), timestamp: optStr(input.timestamp), principal: ctx.authenticatedPrincipal }) }; } });
382
382
  defineOperation({ name: "memory_action_apply", description: "Apply action.", schema: strictSchema({ action: S.str, outcome: S.str, reason: S.str, memoryId: S.str, namespace: S.str, sessionKey: S.str, content: S.str, category: S.str, linkTargetId: S.str, linkType: S.str, linkStrength: S.num, artifactType: S.str, execute: S.bool, sourcePrompt: S.str, dryRun: S.bool }), handler: async (input, ctx) => ({ result: await ctx.service.memoryActionApply({ action: optStr(input.action) ?? "", outcome: optStr(input.outcome), reason: optStr(input.reason), memoryId: optStr(input.memoryId) ?? "", namespace: optStr(input.namespace), sessionKey: optStr(input.sessionKey), content: optStr(input.content), category: optStr(input.category), linkTargetId: optStr(input.linkTargetId), linkType: optStr(input.linkType), linkStrength: optNum(input.linkStrength), artifactType: optStr(input.artifactType), execute: optBool(input.execute), sourcePrompt: optStr(input.sourcePrompt), dryRun: input.dryRun === true, principal: ctx.authenticatedPrincipal }) }) });
383
383
  defineOperation({ name: "context_checkpoint", description: "Context checkpoint.", schema: strictSchema({ sessionKey: S.str, context: S.str, namespace: S.str }), handler: async (input, ctx) => ({ result: await ctx.service.contextCheckpoint({ sessionKey: optStr(input.sessionKey) ?? "", context: optStr(input.context) ?? "", namespace: optStr(input.namespace), principal: ctx.authenticatedPrincipal }) }) });
384
- defineOperation({ name: "briefing", description: "Daily briefing.", schema: strictSchema({ since: S.str, focus: S.str, namespace: S.str, includeLocation: S.bool, format: S.str, maxFollowups: S.num }), handler: async (input, ctx) => { const rf = optStr(input.format); const fe = validateBriefingFormat(rf); if (fe) throw new EngramAccessInputError(fe); return { result: await ctx.service.briefing({ since: optStr(input.since), focus: optStr(input.focus), namespace: optStr(input.namespace), includeLocation: optBool(input.includeLocation), format: rf as "json" | "markdown" | undefined, maxFollowups: optNum(input.maxFollowups), principal: ctx.authenticatedPrincipal }) }; } });
384
+ defineOperation({
385
+ name: "briefing", description: "Daily briefing.",
386
+ schema: strictSchema({ since: S.str, focus: S.str, namespace: S.str, includeLocation: S.bool, format: S.str, maxFollowups: S.num }),
387
+ handler: async (input, ctx) => {
388
+ const rf = optStr(input.format);
389
+ const fe = validateBriefingFormat(rf);
390
+ if (fe) throw new EngramAccessInputError(fe);
391
+ // SAFETY: validateBriefingFormat rejects every format except json, markdown, or undefined.
392
+ const request: EngramAccessBriefingRequest = {
393
+ since: optStr(input.since), focus: optStr(input.focus), namespace: optStr(input.namespace),
394
+ includeLocation: optBool(input.includeLocation), format: rf as "json" | "markdown" | undefined,
395
+ maxFollowups: optNum(input.maxFollowups), principal: ctx.authenticatedPrincipal,
396
+ };
397
+ if (ctx.abortSignal) request.abortSignal = ctx.abortSignal;
398
+ return { result: await ctx.service.briefing(request) };
399
+ },
400
+ });
385
401
 
386
402
  // === CONTRADICTION/REVIEW ===
387
403
  defineOperation({ name: "review_list", description: "List review pairs.", schema: strictSchema({ filter: S.str, namespace: S.str, limit: S.num }),
@@ -0,0 +1,236 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHash } from "node:crypto";
3
+ import { mkdtemp, readFile, rm } from "node:fs/promises";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import test from "node:test";
7
+
8
+ import { EngramAccessService } from "./access-service.js";
9
+ import { CAPTURE_WRITE_LOCK_BUSY_MESSAGE } from "./capture-write-lock-backoff.js";
10
+ import { buildCapturePathLockIdentity, TombstoneBlockedCaptureWriteLock } from "./capture-write-lock.js";
11
+ import { parseConfig } from "./config.js";
12
+ import { Orchestrator } from "./orchestrator.js";
13
+ import { buildExplicitCaptureDedupKey } from "./storage/tombstone-blocked-capture-index.js";
14
+ import { OFFLINE_SYNC_CHANGESET_FORMAT } from "./offline-sync.js";
15
+
16
+ // Real contention exceeds the legacy deadline but fits inside the configured peer budget.
17
+
18
+ /** Longer than the legacy 3s capture-lock deadline, shorter than the converge deadline. */
19
+ const CONTENTION_HOLD_MS = 3_600;
20
+ /** The converge deadline a peer apply is scoped to. */
21
+ const CONVERGE_DEADLINE_MS = 8_000;
22
+ /** An ordinary capture must still give up near the legacy 3s bound. */
23
+ const LEGACY_BOUND_MS = 4_500;
24
+
25
+ const PEER_REL_PATH = "facts/2026-08-13/peer-apply-target.md";
26
+ const ORDINARY_CONTENT = "ordinary capture body";
27
+
28
+ function peerContent(): Buffer {
29
+ return Buffer.from(
30
+ [
31
+ "---",
32
+ "id: peer-apply-target",
33
+ "category: fact",
34
+ "created: 2026-08-13T00:00:00.000Z",
35
+ "---",
36
+ "",
37
+ "Peer applied body",
38
+ "",
39
+ ].join("\n")
40
+ );
41
+ }
42
+
43
+ async function createPeerService(root: string) {
44
+ const orchestrator = new Orchestrator(
45
+ parseConfig({
46
+ memoryDir: root,
47
+ namespacesEnabled: false,
48
+ defaultNamespace: "global",
49
+ converge: {
50
+ conflictPolicy: "newest-wins",
51
+ captureWriteLockInitialDelayMs: 20,
52
+ captureWriteLockMaxDelayMs: 50,
53
+ captureWriteLockDeadlineMs: CONVERGE_DEADLINE_MS,
54
+ },
55
+ })
56
+ );
57
+ const storage = await orchestrator.getStorage();
58
+ await storage.ensureDirectories();
59
+ assert.equal(storage.dir, root, "the fixture uses one cached flat-root storage");
60
+ return { storage, service: new EngramAccessService(orchestrator) };
61
+ }
62
+
63
+ /** Hold a capture lock and release it after `holdMs`. */
64
+ function holdCaptureLock(stateDir: string, identity: string, holdMs: number) {
65
+ const holder = new TombstoneBlockedCaptureWriteLock({ stateDir });
66
+ const released = Promise.withResolvers<void>();
67
+ const acquired = Promise.withResolvers<void>();
68
+ let timer: NodeJS.Timeout | undefined;
69
+ const holding = holder.withCaptureWriteLock(async () => {
70
+ acquired.resolve();
71
+ timer = setTimeout(() => released.resolve(), holdMs);
72
+ await released.promise;
73
+ }, identity);
74
+ return {
75
+ acquired: acquired.promise,
76
+ release: (): void => {
77
+ clearTimeout(timer);
78
+ released.resolve();
79
+ },
80
+ done: holding,
81
+ };
82
+ }
83
+
84
+ function peerApplyRequest(content: Buffer) {
85
+ return {
86
+ sourceId: "remnic-converge",
87
+ path: PEER_REL_PATH,
88
+ sha256: createHash("sha256").update(content).digest("hex"),
89
+ bytes: content.length,
90
+ mtimeMs: 1_700_000_000_000,
91
+ offset: 0,
92
+ content,
93
+ };
94
+ }
95
+
96
+ for (const kind of ["chunk", "changeset"] as const) {
97
+ test(
98
+ `peer ${kind} apply waits out a busy capture lock instead of the legacy deadline`,
99
+ { timeout: 30_000 },
100
+ async () => {
101
+ const root = await mkdtemp(path.join(os.tmpdir(), "remnic-peer-capture-backoff-"));
102
+ const { service } = await createPeerService(root);
103
+ const content = peerContent();
104
+ const holder = holdCaptureLock(
105
+ path.join(root, "state"),
106
+ buildCapturePathLockIdentity(path.resolve(root, PEER_REL_PATH)),
107
+ CONTENTION_HOLD_MS
108
+ );
109
+ try {
110
+ await holder.acquired;
111
+ const startedAt = Date.now();
112
+ const apply =
113
+ kind === "chunk"
114
+ ? service.offlineSyncApplyFileContent(peerApplyRequest(content))
115
+ : service.offlineSyncApply({
116
+ returnCurrentFiles: false,
117
+ changeset: {
118
+ format: OFFLINE_SYNC_CHANGESET_FORMAT,
119
+ schemaVersion: 1,
120
+ createdAt: "2026-08-13T00:00:00.000Z",
121
+ sourceId: "remnic-converge",
122
+ includeTranscripts: false,
123
+ changes: [
124
+ {
125
+ type: "upsert",
126
+ path: PEER_REL_PATH,
127
+ file: {
128
+ path: PEER_REL_PATH,
129
+ sha256: createHash("sha256").update(content).digest("hex"),
130
+ bytes: content.length,
131
+ mtimeMs: 1_700_000_000_000,
132
+ contentBase64: content.toString("base64"),
133
+ },
134
+ },
135
+ ],
136
+ },
137
+ });
138
+ const outcome = await apply.then(
139
+ () => ({ ok: true as const }),
140
+ (error) => ({ ok: false as const, error })
141
+ );
142
+ assert.equal(
143
+ outcome.ok,
144
+ true,
145
+ outcome.ok
146
+ ? ""
147
+ : `peer apply failed: ${outcome.error instanceof Error ? outcome.error.message : String(outcome.error)}`
148
+ );
149
+ assert.ok(Date.now() - startedAt >= 2_500, "peer apply must wait out the capture-lock contention");
150
+ assert.equal(await readFile(path.join(root, PEER_REL_PATH), "utf8"), content.toString("utf8"));
151
+ } finally {
152
+ holder.release();
153
+ await holder.done.catch(() => undefined);
154
+ await rm(root, { recursive: true, force: true });
155
+ }
156
+ }
157
+ );
158
+ }
159
+
160
+ test(
161
+ "an ordinary capture keeps the legacy capture-lock bound while a peer apply is in flight",
162
+ { timeout: 30_000 },
163
+ async () => {
164
+ const root = await mkdtemp(path.join(os.tmpdir(), "remnic-peer-capture-isolation-"));
165
+ const { storage, service } = await createPeerService(root);
166
+ const content = peerContent();
167
+ const stateDir = path.join(root, "state");
168
+ const peerHolder = holdCaptureLock(
169
+ stateDir,
170
+ buildCapturePathLockIdentity(path.resolve(root, PEER_REL_PATH)),
171
+ CONTENTION_HOLD_MS
172
+ );
173
+ const ordinaryHolder = holdCaptureLock(
174
+ stateDir,
175
+ buildExplicitCaptureDedupKey(ORDINARY_CONTENT, "fact", undefined),
176
+ CONTENTION_HOLD_MS
177
+ );
178
+ let peerApply: Promise<{ ok: true; value: unknown } | { ok: false; error: unknown }> | undefined;
179
+ try {
180
+ await Promise.all([peerHolder.acquired, ordinaryHolder.acquired]);
181
+ peerApply = service.offlineSyncApplyFileContent(peerApplyRequest(content)).then(
182
+ (value) => ({ ok: true as const, value }),
183
+ (error) => ({ ok: false as const, error })
184
+ );
185
+ const startedAt = Date.now();
186
+ const outcome = await storage.writeMemory("fact", ORDINARY_CONTENT).then(
187
+ () => ({ ok: true as const }),
188
+ (error) => ({ ok: false as const, error })
189
+ );
190
+ assert.equal(outcome.ok, false, "ordinary capture must not succeed while the capture lock is held");
191
+ assert.equal(
192
+ outcome.ok ? "" : outcome.error instanceof Error ? outcome.error.message : String(outcome.error),
193
+ CAPTURE_WRITE_LOCK_BUSY_MESSAGE
194
+ );
195
+ assert.ok(
196
+ Date.now() - startedAt < LEGACY_BOUND_MS,
197
+ "ordinary capture must keep the legacy capture-lock bound, not the converge deadline"
198
+ );
199
+ } finally {
200
+ peerHolder.release();
201
+ ordinaryHolder.release();
202
+ await Promise.all([peerHolder.done.catch(() => undefined), ordinaryHolder.done.catch(() => undefined)]);
203
+ await peerApply;
204
+ await rm(root, { recursive: true, force: true });
205
+ }
206
+ }
207
+ );
208
+ test("a failed peer apply does not leak converge capture-lock limits", { timeout: 30_000 }, async () => {
209
+ const root = await mkdtemp(path.join(os.tmpdir(), "remnic-peer-capture-error-scope-"));
210
+ const { storage, service } = await createPeerService(root);
211
+ const content = peerContent();
212
+ const holder = holdCaptureLock(
213
+ path.join(root, "state"),
214
+ buildExplicitCaptureDedupKey(ORDINARY_CONTENT, "fact", undefined),
215
+ CONTENTION_HOLD_MS
216
+ );
217
+ try {
218
+ await assert.rejects(
219
+ service.offlineSyncApplyFileContent({
220
+ ...peerApplyRequest(content),
221
+ sha256: "0".repeat(64),
222
+ })
223
+ );
224
+ await holder.acquired;
225
+ const startedAt = Date.now();
226
+ await assert.rejects(storage.writeMemory("fact", ORDINARY_CONTENT), new RegExp(CAPTURE_WRITE_LOCK_BUSY_MESSAGE));
227
+ assert.ok(
228
+ Date.now() - startedAt < LEGACY_BOUND_MS,
229
+ "ordinary capture after a failed peer apply must keep the legacy lock bound"
230
+ );
231
+ } finally {
232
+ holder.release();
233
+ await holder.done.catch(() => undefined);
234
+ await rm(root, { recursive: true, force: true });
235
+ }
236
+ });
@@ -136,6 +136,8 @@ import {
136
136
  applySupportPassportOfflineSyncChangeset,
137
137
  applySupportPassportOfflineSyncFileContent,
138
138
  } from "./support-passport/offline-sync-guard.js";
139
+ import { withCaptureWriteLockBackoff } from "./capture-write-lock-scope.js";
140
+ import { resolveConvergeCaptureWriteLockBackoff } from "./converge-config.js";
139
141
  import type { WearablesService } from "./wearables/service.js";
140
142
  import { exportWorkBoardMarkdown, exportWorkBoardSnapshot, importWorkBoardSnapshot } from "./work/board.js";
141
143
  import { wrapWorkLayerContext } from "./work/boundary.js";
@@ -505,6 +507,11 @@ export interface EngramAccessBriefingRequest extends LocationContextRequestOptio
505
507
  maxFollowups?: number;
506
508
  /** Caller principal for namespace access checks. Transport-bound — never from untrusted payloads. */
507
509
  principal?: string;
510
+ /**
511
+ * Transport request lifetime. When it aborts, the briefing stops and
512
+ * rejects with that AbortError instead of running on (issue #3139).
513
+ */
514
+ abortSignal?: AbortSignal;
508
515
  }
509
516
 
510
517
  /** Response for `remnic_briefing`. */
@@ -5623,7 +5630,8 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
5623
5630
  const resolvedNamespace = this.writableNamespaceFor(options.namespace, undefined, options.principal);
5624
5631
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
5625
5632
  try {
5626
- const result = await applySupportPassportOfflineSyncFileContent(storage, options);
5633
+ const result = await withCaptureWriteLockBackoff(storage, resolveConvergeCaptureWriteLockBackoff(this.orchestrator.config.converge),
5634
+ () => applySupportPassportOfflineSyncFileContent(storage, options));
5627
5635
  return {
5628
5636
  namespace: resolvedNamespace,
5629
5637
  ...result,
@@ -5671,7 +5679,8 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
5671
5679
  const resolvedNamespace = this.writableNamespaceFor(options.namespace, undefined, options.principal);
5672
5680
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
5673
5681
  try {
5674
- const result = await applySupportPassportOfflineSyncChangeset(storage, options);
5682
+ const result = await withCaptureWriteLockBackoff(storage, resolveConvergeCaptureWriteLockBackoff(this.orchestrator.config.converge),
5683
+ () => applySupportPassportOfflineSyncChangeset(storage, options));
5675
5684
  return {
5676
5685
  namespace: resolvedNamespace,
5677
5686
  ...result,