@remnic/core 10.0.29 → 10.0.31

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 (276) hide show
  1. package/dist/access-admin-ops-surface.js +47 -46
  2. package/dist/access-authorization-probe.js +48 -47
  3. package/dist/access-boundary.js +47 -46
  4. package/dist/access-cli.js +107 -107
  5. package/dist/access-extraction-force-flush.d.ts.map +1 -1
  6. package/dist/access-extraction-force-flush.js +47 -46
  7. package/dist/access-http-briefing.js +48 -47
  8. package/dist/access-http-query.js +49 -48
  9. package/dist/access-http.js +65 -64
  10. package/dist/access-identity-continuity-surface.js +47 -46
  11. package/dist/access-lcm-surface.js +47 -46
  12. package/dist/access-mcp.js +57 -56
  13. package/dist/access-namespace-preflight.js +47 -46
  14. package/dist/access-observe-write-surface.d.ts.map +1 -1
  15. package/dist/access-observe-write-surface.js +47 -46
  16. package/dist/access-offline-manifest.js +4 -4
  17. package/dist/access-operations-batch.js +48 -47
  18. package/dist/access-operations.js +55 -54
  19. package/dist/access-recall-concurrency.js +47 -46
  20. package/dist/access-recall-diagnostics.js +2 -2
  21. package/dist/access-recall-response.js +47 -46
  22. package/dist/access-recall-surface.js +47 -46
  23. package/dist/access-schema.d.ts +47 -47
  24. package/dist/access-service.js +47 -46
  25. package/dist/access-surface-catalog.js +49 -48
  26. package/dist/access-surface-catalog.js.map +1 -1
  27. package/dist/active-recall.js +20 -20
  28. package/dist/briefing.js +21 -21
  29. package/dist/buffer-turn-helpers.d.ts +20 -0
  30. package/dist/buffer-turn-helpers.d.ts.map +1 -1
  31. package/dist/buffer-turn-helpers.js +11 -3
  32. package/dist/buffer-turn.d.ts +50 -0
  33. package/dist/buffer-turn.d.ts.map +1 -0
  34. package/dist/buffer-turn.js +1 -0
  35. package/dist/buffer-turn.js.map +1 -0
  36. package/dist/buffer.d.ts +13 -1
  37. package/dist/buffer.d.ts.map +1 -1
  38. package/dist/buffer.js +4 -4
  39. package/dist/causal-consolidation.js +26 -26
  40. package/dist/{chunk-BIE3ZH3N.js → chunk-2IXEKMBJ.js} +143 -112
  41. package/dist/chunk-2IXEKMBJ.js.map +1 -0
  42. package/dist/{chunk-YGVZ4QOZ.js → chunk-3CRE3UZI.js} +2 -2
  43. package/dist/{chunk-YZTFQBYY.js → chunk-3GOPAWA7.js} +3 -3
  44. package/dist/{chunk-NAPHQ2MG.js → chunk-3IDNKOCE.js} +2 -2
  45. package/dist/{chunk-PYCTZ2HX.js → chunk-3VYNGM5A.js} +2 -2
  46. package/dist/{chunk-2XVLY424.js → chunk-42MM5DKK.js} +2 -2
  47. package/dist/{chunk-CKR7LXEK.js → chunk-464QR7WO.js} +255 -63
  48. package/dist/chunk-464QR7WO.js.map +1 -0
  49. package/dist/{chunk-3IXNL6SK.js → chunk-4ZTVOECF.js} +4 -4
  50. package/dist/{chunk-ETZUIRCI.js → chunk-53GYS3GG.js} +2 -2
  51. package/dist/{chunk-ZXTAHSQU.js → chunk-5GPHJ333.js} +2 -2
  52. package/dist/{chunk-AUYFUBBE.js → chunk-5HJCZ7SB.js} +4 -4
  53. package/dist/{chunk-52II7PB6.js → chunk-645WOU5I.js} +4 -4
  54. package/dist/{chunk-2WDMUQOH.js → chunk-64IO6ZEE.js} +2 -2
  55. package/dist/{chunk-OIIAIY7J.js → chunk-7SXUGYPE.js} +3 -3
  56. package/dist/{chunk-74IN6PV5.js → chunk-7WWITD3H.js} +4 -4
  57. package/dist/{chunk-7FZ4YVOH.js → chunk-A5ZY537U.js} +2 -2
  58. package/dist/{chunk-LDXNKEYB.js → chunk-A6PKEU7T.js} +1 -1
  59. package/dist/chunk-A6PKEU7T.js.map +1 -0
  60. package/dist/{chunk-VLBFSD7B.js → chunk-APRGEZQN.js} +2 -2
  61. package/dist/{chunk-XNROYP5E.js → chunk-AQ5XLA36.js} +2 -2
  62. package/dist/{chunk-K2REHR42.js → chunk-BDHYRMJC.js} +2 -2
  63. package/dist/{chunk-GQ7VWY6N.js → chunk-BQ6DGL6A.js} +2 -2
  64. package/dist/{chunk-4OE4UE2Y.js → chunk-D3EXT5KG.js} +2 -2
  65. package/dist/{chunk-MROA6OFU.js → chunk-DGBWPSM6.js} +2 -2
  66. package/dist/{chunk-NOMHXZD7.js → chunk-DNZ2CWPG.js} +2 -2
  67. package/dist/{chunk-HG2VVIKI.js → chunk-DZBMASSI.js} +12 -12
  68. package/dist/{chunk-NB2YX6X2.js → chunk-EXYDKAR6.js} +5 -5
  69. package/dist/{chunk-V4FI2TG6.js → chunk-F5FZ7DB4.js} +2 -2
  70. package/dist/{chunk-IY7DGT2Z.js → chunk-GDPTMK5V.js} +2 -2
  71. package/dist/{chunk-27OJ5G3D.js → chunk-GJBSEMC5.js} +7 -7
  72. package/dist/{chunk-MMBLOJJB.js → chunk-HMON55NJ.js} +85 -44
  73. package/dist/chunk-HMON55NJ.js.map +1 -0
  74. package/dist/{chunk-C2QVDLQV.js → chunk-HNTB7NIE.js} +2 -2
  75. package/dist/{chunk-4HNINU7Q.js → chunk-HSPEVXT5.js} +42 -42
  76. package/dist/{chunk-4QPW6JVI.js → chunk-ID2PLENW.js} +2 -2
  77. package/dist/{chunk-FN6OFDBZ.js → chunk-ID62FNER.js} +2 -2
  78. package/dist/{chunk-GSKW64NB.js → chunk-J6SZXAQ2.js} +2 -2
  79. package/dist/{chunk-3CHHQXAR.js → chunk-JTACUJP3.js} +2 -2
  80. package/dist/{chunk-3SN2D43X.js → chunk-K6RQ2KOX.js} +2 -2
  81. package/dist/{chunk-GWB7ZD2A.js → chunk-K6YJGWJP.js} +2 -2
  82. package/dist/{chunk-OANSZGAG.js → chunk-KFR343VH.js} +2 -2
  83. package/dist/{chunk-WC3V7HHP.js → chunk-KJZKO2M6.js} +2 -1
  84. package/dist/chunk-KJZKO2M6.js.map +1 -0
  85. package/dist/{chunk-T5IF2ZCE.js → chunk-KZMRMKC7.js} +81 -2
  86. package/dist/chunk-KZMRMKC7.js.map +1 -0
  87. package/dist/{chunk-NPO4ZQFY.js → chunk-LDXS746V.js} +3 -3
  88. package/dist/{chunk-UTXYOWDR.js → chunk-LGR54NYT.js} +3 -3
  89. package/dist/{chunk-UTXYOWDR.js.map → chunk-LGR54NYT.js.map} +1 -1
  90. package/dist/{chunk-DDLRKPR2.js → chunk-NKW27NU3.js} +2 -2
  91. package/dist/{chunk-4HYP4OKH.js → chunk-NU247WVX.js} +2 -2
  92. package/dist/{chunk-RRJ462HP.js → chunk-O6YJI5VX.js} +2 -2
  93. package/dist/{chunk-WYLBEJQI.js → chunk-OCWNT322.js} +4 -4
  94. package/dist/{chunk-UUYAW3JH.js → chunk-OIKLZCJD.js} +2 -2
  95. package/dist/{chunk-IO2UQVR2.js → chunk-OTWZXOJI.js} +2 -2
  96. package/dist/{chunk-OXYXMGRH.js → chunk-PGHYQMKZ.js} +11 -11
  97. package/dist/{chunk-LDEKVBVO.js → chunk-PZWW6MDE.js} +2 -2
  98. package/dist/{chunk-TFA6HPOA.js → chunk-QCP75JGO.js} +5 -5
  99. package/dist/{chunk-M236YHUH.js → chunk-RILIWZA6.js} +3 -3
  100. package/dist/{chunk-7VB3Y5OL.js → chunk-RRYN5FFC.js} +4 -4
  101. package/dist/{chunk-PZEADMX4.js → chunk-RU6WB55E.js} +9 -9
  102. package/dist/{chunk-VARNSLUW.js → chunk-SGII36L6.js} +2 -2
  103. package/dist/{chunk-KFKFK6G6.js → chunk-TB2J4PBY.js} +3 -3
  104. package/dist/{chunk-WQIYGYY6.js → chunk-TEUPXKC5.js} +2 -2
  105. package/dist/{chunk-VEB7NEON.js → chunk-U4BNX4R2.js} +3 -3
  106. package/dist/{chunk-7HFTCBCZ.js → chunk-UBBZFODO.js} +2 -2
  107. package/dist/{chunk-654GT5UP.js → chunk-UZDOPJ2P.js} +2 -2
  108. package/dist/{chunk-D4RV54HH.js → chunk-VAPVRDC4.js} +2 -2
  109. package/dist/{chunk-OXX4ORRL.js → chunk-W7X7XT7Z.js} +15 -15
  110. package/dist/{chunk-5NPZFXQH.js → chunk-WK7GFAQ2.js} +2 -2
  111. package/dist/{chunk-G6DAE2LT.js → chunk-WPCK6EJ2.js} +2 -2
  112. package/dist/{chunk-VKQI47DJ.js → chunk-Y7427SL7.js} +4 -4
  113. package/dist/{chunk-ZCRDYQL6.js → chunk-YGBWSKBD.js} +2 -2
  114. package/dist/{chunk-NCPR2FOJ.js → chunk-YXWLQHAW.js} +2 -2
  115. package/dist/{chunk-UM73Q46J.js → chunk-ZEMBRSKK.js} +2 -2
  116. package/dist/{chunk-TTIEXXL3.js → chunk-ZGP2XB4S.js} +16 -16
  117. package/dist/{chunk-UVUBLLM3.js → chunk-ZY4S5WMQ.js} +2 -2
  118. package/dist/cli.js +83 -82
  119. package/dist/coding/export-okf-codegraph.js +20 -20
  120. package/dist/compounding/engine.js +22 -22
  121. package/dist/config.js +20 -20
  122. package/dist/connectors/codex-materialize-runner.js +21 -21
  123. package/dist/connectors/index.js +21 -21
  124. package/dist/convergence-refresh.js +23 -23
  125. package/dist/conversation-index/backend.js +2 -2
  126. package/dist/corpus-watermark.js +23 -23
  127. package/dist/entity-retrieval.js +22 -22
  128. package/dist/event-order-recall.js +3 -3
  129. package/dist/external-wiki-access.js +48 -47
  130. package/dist/extraction.js +31 -31
  131. package/dist/harmonic-retrieval.js +21 -21
  132. package/dist/index.js +126 -126
  133. package/dist/lcm/engine.js +2 -2
  134. package/dist/lcm/index.js +2 -2
  135. package/dist/location/index.js +23 -23
  136. package/dist/maintenance/memory-governance.js +21 -21
  137. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +21 -21
  138. package/dist/maintenance/rebuild-memory-projection-runner.js +23 -23
  139. package/dist/maintenance/rebuild-memory-projection.js +22 -22
  140. package/dist/memory-browse-operations.js +48 -47
  141. package/dist/namespaces/migrate.js +22 -22
  142. package/dist/namespaces/scope-profiles.d.ts +1 -0
  143. package/dist/namespaces/scope-profiles.d.ts.map +1 -1
  144. package/dist/namespaces/search.js +9 -9
  145. package/dist/namespaces/storage.js +21 -21
  146. package/dist/offline-sync-impression-drain.js +3 -3
  147. package/dist/operator-doctor-corpus.js +24 -24
  148. package/dist/operator-toolkit.js +32 -32
  149. package/dist/orchestration/maintenance.js +33 -33
  150. package/dist/orchestration/session-context.d.ts +6 -0
  151. package/dist/orchestration/session-context.d.ts.map +1 -1
  152. package/dist/orchestration/turn-ingestion.d.ts +35 -1
  153. package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
  154. package/dist/orchestrator.d.ts +2 -32
  155. package/dist/orchestrator.d.ts.map +1 -1
  156. package/dist/orchestrator.js +107 -107
  157. package/dist/recall-explain-renderer.js +3 -3
  158. package/dist/recall-navigate-access.js +2 -2
  159. package/dist/recall-navigate-disclosure.js +2 -2
  160. package/dist/recall-navigate.js +2 -2
  161. package/dist/recall-navigation-operations.js +48 -47
  162. package/dist/recall-navigation.js +47 -46
  163. package/dist/recall-xray-cli.js +4 -4
  164. package/dist/recall-xray-renderer.js +3 -3
  165. package/dist/recall-xray.js +2 -2
  166. package/dist/relay/mission.d.ts +2 -2
  167. package/dist/resume-bundles.js +20 -20
  168. package/dist/schemas.d.ts +4 -4
  169. package/dist/search/factory.js +8 -8
  170. package/dist/search/index.js +13 -13
  171. package/dist/search/lancedb-backend.js +2 -2
  172. package/dist/search/meilisearch-backend.js +2 -2
  173. package/dist/search/orama-backend.js +2 -2
  174. package/dist/semantic-consolidation.js +22 -22
  175. package/dist/semantic-rule-promotion.js +21 -21
  176. package/dist/semantic-rule-verifier.js +21 -21
  177. package/dist/source-agent-qualifier.js +24 -24
  178. package/dist/standup/build.js +21 -21
  179. package/dist/storage.js +20 -20
  180. package/dist/support-passport/contracts.d.ts +6 -6
  181. package/dist/support-passport/grant-contracts.d.ts +4 -4
  182. package/dist/support-passport/index.js +50 -49
  183. package/dist/transfer/export-okf.js +21 -21
  184. package/dist/types.d.ts +3 -17
  185. package/dist/types.d.ts.map +1 -1
  186. package/dist/types.js +1 -1
  187. package/dist/verified-recall.js +21 -21
  188. package/dist/who-knows-cli.js +22 -22
  189. package/dist/who-knows.js +21 -21
  190. package/package.json +2 -2
  191. package/src/access-extraction-force-flush.ts +37 -25
  192. package/src/access-observe-acceptance-boundary.test.ts +172 -0
  193. package/src/access-observe-replay-durability.test.ts +2212 -0
  194. package/src/access-observe-write-surface.ts +36 -41
  195. package/src/access-service-observe-lcm-parity.test.ts +63 -39
  196. package/src/access-service-observe-scope.test.ts +3 -2
  197. package/src/buffer-turn-helpers.ts +120 -1
  198. package/src/buffer-turn.ts +50 -0
  199. package/src/buffer.ts +115 -49
  200. package/src/namespaces/scope-profiles.ts +1 -1
  201. package/src/orchestration/extraction-run.ts +1 -1
  202. package/src/orchestration/session-context.ts +117 -49
  203. package/src/orchestration/turn-ingestion.ts +313 -9
  204. package/src/orchestrator-flush.test.ts +16 -3
  205. package/src/orchestrator.ts +2 -32
  206. package/src/types.ts +3 -17
  207. package/dist/chunk-BIE3ZH3N.js.map +0 -1
  208. package/dist/chunk-CKR7LXEK.js.map +0 -1
  209. package/dist/chunk-LDXNKEYB.js.map +0 -1
  210. package/dist/chunk-MMBLOJJB.js.map +0 -1
  211. package/dist/chunk-T5IF2ZCE.js.map +0 -1
  212. package/dist/chunk-WC3V7HHP.js.map +0 -1
  213. /package/dist/{chunk-YGVZ4QOZ.js.map → chunk-3CRE3UZI.js.map} +0 -0
  214. /package/dist/{chunk-YZTFQBYY.js.map → chunk-3GOPAWA7.js.map} +0 -0
  215. /package/dist/{chunk-NAPHQ2MG.js.map → chunk-3IDNKOCE.js.map} +0 -0
  216. /package/dist/{chunk-PYCTZ2HX.js.map → chunk-3VYNGM5A.js.map} +0 -0
  217. /package/dist/{chunk-2XVLY424.js.map → chunk-42MM5DKK.js.map} +0 -0
  218. /package/dist/{chunk-3IXNL6SK.js.map → chunk-4ZTVOECF.js.map} +0 -0
  219. /package/dist/{chunk-ETZUIRCI.js.map → chunk-53GYS3GG.js.map} +0 -0
  220. /package/dist/{chunk-ZXTAHSQU.js.map → chunk-5GPHJ333.js.map} +0 -0
  221. /package/dist/{chunk-AUYFUBBE.js.map → chunk-5HJCZ7SB.js.map} +0 -0
  222. /package/dist/{chunk-52II7PB6.js.map → chunk-645WOU5I.js.map} +0 -0
  223. /package/dist/{chunk-2WDMUQOH.js.map → chunk-64IO6ZEE.js.map} +0 -0
  224. /package/dist/{chunk-OIIAIY7J.js.map → chunk-7SXUGYPE.js.map} +0 -0
  225. /package/dist/{chunk-74IN6PV5.js.map → chunk-7WWITD3H.js.map} +0 -0
  226. /package/dist/{chunk-7FZ4YVOH.js.map → chunk-A5ZY537U.js.map} +0 -0
  227. /package/dist/{chunk-VLBFSD7B.js.map → chunk-APRGEZQN.js.map} +0 -0
  228. /package/dist/{chunk-XNROYP5E.js.map → chunk-AQ5XLA36.js.map} +0 -0
  229. /package/dist/{chunk-K2REHR42.js.map → chunk-BDHYRMJC.js.map} +0 -0
  230. /package/dist/{chunk-GQ7VWY6N.js.map → chunk-BQ6DGL6A.js.map} +0 -0
  231. /package/dist/{chunk-4OE4UE2Y.js.map → chunk-D3EXT5KG.js.map} +0 -0
  232. /package/dist/{chunk-MROA6OFU.js.map → chunk-DGBWPSM6.js.map} +0 -0
  233. /package/dist/{chunk-NOMHXZD7.js.map → chunk-DNZ2CWPG.js.map} +0 -0
  234. /package/dist/{chunk-HG2VVIKI.js.map → chunk-DZBMASSI.js.map} +0 -0
  235. /package/dist/{chunk-NB2YX6X2.js.map → chunk-EXYDKAR6.js.map} +0 -0
  236. /package/dist/{chunk-V4FI2TG6.js.map → chunk-F5FZ7DB4.js.map} +0 -0
  237. /package/dist/{chunk-IY7DGT2Z.js.map → chunk-GDPTMK5V.js.map} +0 -0
  238. /package/dist/{chunk-27OJ5G3D.js.map → chunk-GJBSEMC5.js.map} +0 -0
  239. /package/dist/{chunk-C2QVDLQV.js.map → chunk-HNTB7NIE.js.map} +0 -0
  240. /package/dist/{chunk-4HNINU7Q.js.map → chunk-HSPEVXT5.js.map} +0 -0
  241. /package/dist/{chunk-4QPW6JVI.js.map → chunk-ID2PLENW.js.map} +0 -0
  242. /package/dist/{chunk-FN6OFDBZ.js.map → chunk-ID62FNER.js.map} +0 -0
  243. /package/dist/{chunk-GSKW64NB.js.map → chunk-J6SZXAQ2.js.map} +0 -0
  244. /package/dist/{chunk-3CHHQXAR.js.map → chunk-JTACUJP3.js.map} +0 -0
  245. /package/dist/{chunk-3SN2D43X.js.map → chunk-K6RQ2KOX.js.map} +0 -0
  246. /package/dist/{chunk-GWB7ZD2A.js.map → chunk-K6YJGWJP.js.map} +0 -0
  247. /package/dist/{chunk-OANSZGAG.js.map → chunk-KFR343VH.js.map} +0 -0
  248. /package/dist/{chunk-NPO4ZQFY.js.map → chunk-LDXS746V.js.map} +0 -0
  249. /package/dist/{chunk-DDLRKPR2.js.map → chunk-NKW27NU3.js.map} +0 -0
  250. /package/dist/{chunk-4HYP4OKH.js.map → chunk-NU247WVX.js.map} +0 -0
  251. /package/dist/{chunk-RRJ462HP.js.map → chunk-O6YJI5VX.js.map} +0 -0
  252. /package/dist/{chunk-WYLBEJQI.js.map → chunk-OCWNT322.js.map} +0 -0
  253. /package/dist/{chunk-UUYAW3JH.js.map → chunk-OIKLZCJD.js.map} +0 -0
  254. /package/dist/{chunk-IO2UQVR2.js.map → chunk-OTWZXOJI.js.map} +0 -0
  255. /package/dist/{chunk-OXYXMGRH.js.map → chunk-PGHYQMKZ.js.map} +0 -0
  256. /package/dist/{chunk-LDEKVBVO.js.map → chunk-PZWW6MDE.js.map} +0 -0
  257. /package/dist/{chunk-TFA6HPOA.js.map → chunk-QCP75JGO.js.map} +0 -0
  258. /package/dist/{chunk-M236YHUH.js.map → chunk-RILIWZA6.js.map} +0 -0
  259. /package/dist/{chunk-7VB3Y5OL.js.map → chunk-RRYN5FFC.js.map} +0 -0
  260. /package/dist/{chunk-PZEADMX4.js.map → chunk-RU6WB55E.js.map} +0 -0
  261. /package/dist/{chunk-VARNSLUW.js.map → chunk-SGII36L6.js.map} +0 -0
  262. /package/dist/{chunk-KFKFK6G6.js.map → chunk-TB2J4PBY.js.map} +0 -0
  263. /package/dist/{chunk-WQIYGYY6.js.map → chunk-TEUPXKC5.js.map} +0 -0
  264. /package/dist/{chunk-VEB7NEON.js.map → chunk-U4BNX4R2.js.map} +0 -0
  265. /package/dist/{chunk-7HFTCBCZ.js.map → chunk-UBBZFODO.js.map} +0 -0
  266. /package/dist/{chunk-654GT5UP.js.map → chunk-UZDOPJ2P.js.map} +0 -0
  267. /package/dist/{chunk-D4RV54HH.js.map → chunk-VAPVRDC4.js.map} +0 -0
  268. /package/dist/{chunk-OXX4ORRL.js.map → chunk-W7X7XT7Z.js.map} +0 -0
  269. /package/dist/{chunk-5NPZFXQH.js.map → chunk-WK7GFAQ2.js.map} +0 -0
  270. /package/dist/{chunk-G6DAE2LT.js.map → chunk-WPCK6EJ2.js.map} +0 -0
  271. /package/dist/{chunk-VKQI47DJ.js.map → chunk-Y7427SL7.js.map} +0 -0
  272. /package/dist/{chunk-ZCRDYQL6.js.map → chunk-YGBWSKBD.js.map} +0 -0
  273. /package/dist/{chunk-NCPR2FOJ.js.map → chunk-YXWLQHAW.js.map} +0 -0
  274. /package/dist/{chunk-UM73Q46J.js.map → chunk-ZEMBRSKK.js.map} +0 -0
  275. /package/dist/{chunk-TTIEXXL3.js.map → chunk-ZGP2XB4S.js.map} +0 -0
  276. /package/dist/{chunk-UVUBLLM3.js.map → chunk-ZY4S5WMQ.js.map} +0 -0
@@ -121,31 +121,9 @@ export async function extractionForceFlush(
121
121
  }
122
122
  abortHandler = cancelScopedPendingObserveExtractions;
123
123
  request.abortSignal?.addEventListener("abort", abortHandler, { once: true });
124
- await awaitSessionFlushPhase(
125
- () =>
126
- deps.orchestrator.flushSession(request.sessionKey, {
127
- reason: "access_force_flush",
128
- abortSignal: request.abortSignal,
129
- failOnExtractionFailure: true,
130
- extractionDeadlineMs: deadlineAt,
131
- writeNamespaceOverride: scope.writeNamespace,
132
- principalOverride:
133
- typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : undefined,
134
- scopeProfileWritePlan: scope.scopeProfilePlan,
135
- onCommitted: markCommitted,
136
- }),
137
- {
138
- abortSignal: request.abortSignal,
139
- extractionDeadlineMs: deadlineAt,
140
- reason: "access_force_flush",
141
- deadlineStage: "buffer_drain",
142
- onDeadline: cancelScopedPendingObserveExtractions,
143
- }
144
- );
145
- // A flush with no buffered turns still consumes the lifecycle write;
146
- // durable drains already invoked this idempotent callback.
147
- markCommitted();
148
-
124
+ // #3251: wait for in-flight observe extractions BEFORE draining —
125
+ // drain-first could queue the same accepted turns twice. Scoped key, so
126
+ // never waits on another scope.
149
127
  if (waitForPendingObserveExtraction) {
150
128
  let cancelPendingObserveExtraction: (() => void) | undefined;
151
129
  await awaitSessionFlushPhase(
@@ -172,6 +150,33 @@ export async function extractionForceFlush(
172
150
  }
173
151
  );
174
152
  }
153
+ await awaitSessionFlushPhase(
154
+ () =>
155
+ deps.orchestrator.flushSession(request.sessionKey, {
156
+ reason: "access_force_flush",
157
+ abortSignal: request.abortSignal,
158
+ failOnExtractionFailure: true,
159
+ extractionDeadlineMs: deadlineAt,
160
+ writeNamespaceOverride: scope.writeNamespace,
161
+ principalOverride:
162
+ scope.principal !== undefined && scope.principal.length > 0 ? scope.principal : undefined,
163
+ scopeProfileWritePlan: scope.scopeProfilePlan,
164
+ // #3251: the session's original coding binding — plan-pinned flushes
165
+ // drain only captures bound to the same project identity.
166
+ codingContext: deps.orchestrator.getCodingContextForSession(request.sessionKey) ?? undefined,
167
+ onCommitted: markCommitted,
168
+ }),
169
+ {
170
+ abortSignal: request.abortSignal,
171
+ extractionDeadlineMs: deadlineAt,
172
+ reason: "access_force_flush",
173
+ deadlineStage: "buffer_drain",
174
+ onDeadline: cancelScopedPendingObserveExtractions,
175
+ }
176
+ );
177
+ // A flush with no buffered turns still consumes the lifecycle write;
178
+ // durable drains already invoked this idempotent callback.
179
+ markCommitted();
175
180
 
176
181
  const buffer = deps.orchestrator.buffer;
177
182
  if (buffer && typeof buffer.clearRetainedTurnsForSession === "function") {
@@ -181,6 +186,13 @@ export async function extractionForceFlush(
181
186
  buffer.clearRetainedTurnsForSession(request.sessionKey, namespacesEnabled ? scope.principal : undefined, {
182
187
  abortSignal: request.abortSignal,
183
188
  deadlineMs: deadlineAt,
189
+ // #3251: only clear retained turns accepted under THIS scope —
190
+ // namespace, plan identity, and original project binding.
191
+ writeNamespaceOverride: namespacesEnabled ? scope.writeNamespace : undefined,
192
+ scopeProfileWritePlan: namespacesEnabled ? scope.scopeProfilePlan : undefined,
193
+ codingContext: namespacesEnabled
194
+ ? deps.orchestrator.getCodingContextForSession(request.sessionKey) ?? undefined
195
+ : undefined,
184
196
  }),
185
197
  {
186
198
  abortSignal: request.abortSignal,
@@ -0,0 +1,172 @@
1
+ /**
2
+ * #3251 acceptance boundary at the access-service surface: the 202
3
+ * acknowledges a DURABLE capture. A capture failure must reject the request
4
+ * (never 202) and must NOT commit the idempotency success reservation, so a
5
+ * client retry with the same key re-executes instead of replaying a success
6
+ * that never happened. Durability itself is proven against the real buffer in
7
+ * access-observe-replay-durability.test.ts; this file pins the HTTP-facing
8
+ * accept/reject semantics with the house observe-probe harness.
9
+ */
10
+
11
+ import assert from "node:assert/strict";
12
+ import { mkdtempSync, rmSync } from "node:fs";
13
+ import { tmpdir } from "node:os";
14
+ import { join } from "node:path";
15
+ import test from "node:test";
16
+
17
+ import { EngramAccessService, type EngramAccessObserveRequest } from "./access-service.js";
18
+ import { parseConfig } from "./config.js";
19
+ import { Orchestrator } from "./orchestrator.js";
20
+ import type { CodingContext, PluginConfig } from "./types.js";
21
+
22
+ interface BoundaryProbeIngestBehavior {
23
+ failNext: Error | null;
24
+ queued?: (onExtractionQueued: (extraction: Promise<void>) => void) => void;
25
+ calls: Array<{ sessionKeys: Array<string | undefined>; extractionMode?: string }>;
26
+ }
27
+
28
+ interface BoundaryProbe {
29
+ orch: Orchestrator;
30
+ ingestBehavior: BoundaryProbeIngestBehavior;
31
+ }
32
+
33
+ function makeBoundaryProbe(memoryDir: string): BoundaryProbe {
34
+ const contexts = new Map<string, CodingContext>();
35
+ const ingestBehavior: BoundaryProbeIngestBehavior = {
36
+ failNext: null,
37
+ queued: undefined,
38
+ calls: [],
39
+ };
40
+ const config = parseConfig({
41
+ memoryDir,
42
+ transcriptEnabled: false,
43
+ namespacesEnabled: true,
44
+ defaultNamespace: "default",
45
+ sharedNamespace: "shared",
46
+ namespacePolicies: [{ name: "pi-geek", readPrincipals: ["pi-geek"], writePrincipals: ["pi-geek"] }],
47
+ codingMode: { projectScope: true },
48
+ objectiveStateMemoryEnabled: false,
49
+ objectiveStateSnapshotWritesEnabled: false,
50
+ principalFromSessionKeyMode: "prefix",
51
+ principalFromSessionKeyRules: [{ match: "pi-geek:", principal: "pi-geek" }],
52
+ recallCrossNamespaceBudgetEnabled: false,
53
+ });
54
+ // SAFETY: the probe exercises observe + force-flush with these exact members
55
+ // (scope resolution, coding context, LCM off-switch, replay capture); the
56
+ // rest of Orchestrator is unused on this surface.
57
+ const orch = {
58
+ config,
59
+ getCodingContextForSession: (sessionKey: string | undefined) =>
60
+ (sessionKey ? contexts.get(sessionKey) : null) ?? null,
61
+ setCodingContextForSession: (sessionKey: string, ctx: CodingContext | null) => {
62
+ if (ctx === null) contexts.delete(sessionKey);
63
+ else contexts.set(sessionKey, ctx);
64
+ },
65
+ applyCodingNamespaceOverlay: (sessionKey: string | undefined, base: string) =>
66
+ Orchestrator.prototype.applyCodingNamespaceOverlay.call(orch, sessionKey, base),
67
+ getStorage: async (namespace: string) => ({ dir: join(memoryDir, "storage", namespace) }),
68
+ lcmEngine: {
69
+ enabled: true,
70
+ enqueueObserveMessages: () => {},
71
+ },
72
+ ingestReplayBatch: async (
73
+ turns: Array<{ sessionKey: string }>,
74
+ options: {
75
+ extractionMode?: string;
76
+ onExtractionQueued?: (extraction: Promise<void>) => void;
77
+ } = {},
78
+ ) => {
79
+ if (ingestBehavior.failNext) {
80
+ const err = ingestBehavior.failNext;
81
+ ingestBehavior.failNext = null;
82
+ throw err;
83
+ }
84
+ ingestBehavior.calls.push({
85
+ sessionKeys: turns.map((turn) => turn.sessionKey),
86
+ extractionMode: options.extractionMode,
87
+ });
88
+ ingestBehavior.queued?.((extraction) => options.onExtractionQueued?.(extraction));
89
+ },
90
+ };
91
+ // SAFETY: the probe exercises only the observe/force-flush surface used here.
92
+ const probeOrch = orch as any;
93
+ return { orch: probeOrch, ingestBehavior };
94
+ }
95
+
96
+ function observeRequest(overrides: Partial<EngramAccessObserveRequest>): EngramAccessObserveRequest {
97
+ // SAFETY: observeRequest builds a minimal valid request; the full schema
98
+ // is enforced by the service at runtime.
99
+ return {
100
+ sessionKey: "pi-geek:abc123",
101
+ messages: [{ role: "user", content: "the release train slips to friday" }],
102
+ ...overrides,
103
+ } as EngramAccessObserveRequest;
104
+ }
105
+
106
+ test("#3251 a failed durable capture rejects the observe and never commits idempotency success", async () => {
107
+ const memoryDir = mkdtempSync(join(tmpdir(), "remnic-observe-accept-"));
108
+ try {
109
+ const probe = makeBoundaryProbe(memoryDir);
110
+ const service = new EngramAccessService(probe.orch);
111
+ const key = "accept-boundary-pi-geek-#1";
112
+
113
+ probe.ingestBehavior.failNext = new Error("simulated durable capture failure");
114
+ await assert.rejects(
115
+ service.observe(observeRequest({ idempotencyKey: key })),
116
+ /simulated durable capture failure/,
117
+ );
118
+ assert.equal(probe.ingestBehavior.calls.length, 0, "failed capture ingested nothing");
119
+
120
+ // Retry with the SAME key must re-execute: no success reservation exists.
121
+ const second = await service.observe(observeRequest({ idempotencyKey: key }));
122
+ assert.equal(second.idempotencyReplay, undefined, "retry after failure is a fresh write, not a replay");
123
+ assert.equal(probe.ingestBehavior.calls.length, 1, "retry executes the capture exactly once");
124
+ assert.equal(probe.ingestBehavior.calls[0]?.extractionMode, "buffered");
125
+ } finally {
126
+ rmSync(memoryDir, { recursive: true, force: true });
127
+ }
128
+ });
129
+
130
+ test("#3251 every trigger-queued extraction is tracked: a rejected one surfaces to force-flush, none crash", async () => {
131
+ const memoryDir = mkdtempSync(join(tmpdir(), "remnic-observe-multi-"));
132
+ const unhandled: unknown[] = [];
133
+ const onUnhandled = (reason: Error): void => {
134
+ unhandled.push(reason);
135
+ };
136
+ process.on("unhandledRejection", onUnhandled);
137
+ try {
138
+ const probe = makeBoundaryProbe(memoryDir);
139
+ const service = new EngramAccessService(probe.orch);
140
+ const first = Promise.reject(new Error("first queued extraction failed"));
141
+ first.catch(() => {});
142
+ const second = Promise.withResolvers<void>();
143
+ probe.ingestBehavior.queued = (onExtractionQueued) => {
144
+ onExtractionQueued(first);
145
+ onExtractionQueued(second.promise);
146
+ };
147
+
148
+ await service.observe(observeRequest({}));
149
+
150
+ // BOTH promises must be tracked (never last-write-wins): a scoped
151
+ // force-flush wait surfaces the FIRST rejection once the still-pending
152
+ // one settles. With the last-write-wins bug only `second` was tracked
153
+ // and the flush resolved cleanly.
154
+ second.resolve();
155
+ await assert.rejects(
156
+ service.extractionForceFlush({
157
+ sessionKey: "pi-geek:abc123",
158
+ authenticatedPrincipal: "pi-geek",
159
+ deadlineMs: 5000,
160
+ }),
161
+ /first queued extraction failed/,
162
+ );
163
+ assert.deepEqual(
164
+ unhandled.filter((reason) => reason instanceof Error && /first queued extraction failed/.test(reason.message)),
165
+ [],
166
+ "tracked rejections must be handled, never crash the process",
167
+ );
168
+ } finally {
169
+ process.off("unhandledRejection", onUnhandled);
170
+ rmSync(memoryDir, { recursive: true, force: true });
171
+ }
172
+ });