@remnic/core 10.0.89 → 10.0.91

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 (382) hide show
  1. package/dist/access-admin-ops-surface.js +88 -88
  2. package/dist/access-authorization-probe.js +89 -89
  3. package/dist/access-boundary.js +88 -88
  4. package/dist/access-cli.js +191 -190
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-extraction-force-flush.js +88 -88
  7. package/dist/access-http-admission.d.ts +14 -0
  8. package/dist/access-http-admission.d.ts.map +1 -0
  9. package/dist/access-http-admission.js +9 -0
  10. package/dist/access-http-briefing.js +89 -89
  11. package/dist/access-http-query.js +90 -90
  12. package/dist/access-http-types.d.ts +145 -0
  13. package/dist/access-http-types.d.ts.map +1 -0
  14. package/dist/access-http-types.js +1 -0
  15. package/dist/access-http.d.ts +3 -142
  16. package/dist/access-http.d.ts.map +1 -1
  17. package/dist/access-http.js +117 -116
  18. package/dist/access-identity-continuity-surface.js +88 -88
  19. package/dist/access-lcm-surface.js +88 -88
  20. package/dist/access-mcp.d.ts.map +1 -1
  21. package/dist/access-mcp.js +104 -104
  22. package/dist/access-namespace-preflight.js +88 -88
  23. package/dist/access-observe-write-category.js +12 -12
  24. package/dist/access-observe-write-surface.js +88 -88
  25. package/dist/access-offline-manifest.js +17 -17
  26. package/dist/access-operations-batch.js +92 -92
  27. package/dist/access-operations.js +99 -99
  28. package/dist/access-recall-concurrency.js +88 -88
  29. package/dist/access-recall-diagnostics.js +6 -6
  30. package/dist/access-recall-response.js +88 -88
  31. package/dist/access-recall-surface.js +88 -88
  32. package/dist/access-schema.js +8 -8
  33. package/dist/access-service.js +88 -88
  34. package/dist/access-surface-catalog.js +90 -90
  35. package/dist/active-memory-bridge.js +6 -6
  36. package/dist/active-recall.js +42 -42
  37. package/dist/adapters/index.js +4 -4
  38. package/dist/adapters/registry.js +2 -2
  39. package/dist/auto-sync-3AZW7MXI.js +3 -3
  40. package/dist/briefing.js +30 -30
  41. package/dist/buffer-admission.d.ts +9 -0
  42. package/dist/buffer-admission.d.ts.map +1 -1
  43. package/dist/buffer-admission.js +3 -1
  44. package/dist/buffer.js +14 -14
  45. package/dist/calibration.js +5 -5
  46. package/dist/causal-behavior.js +2 -2
  47. package/dist/causal-chain.js +2 -2
  48. package/dist/causal-consolidation.js +35 -35
  49. package/dist/causal-retrieval.js +2 -2
  50. package/dist/causal-trajectory-graph.js +2 -2
  51. package/dist/causal-trajectory.js +1 -1
  52. package/dist/{chunk-4XYAWK5H.js → chunk-25BUV3TU.js} +2 -2
  53. package/dist/{chunk-C2HORX76.js → chunk-27XYV2XL.js} +2 -2
  54. package/dist/{chunk-3NF4QUNZ.js → chunk-2JSDPUKD.js} +5 -5
  55. package/dist/{chunk-AJHNXIQU.js → chunk-2LCRG2YV.js} +2 -2
  56. package/dist/{chunk-ARRTLPRC.js → chunk-3UMDRGFS.js} +2 -2
  57. package/dist/{chunk-G54BOKZ6.js → chunk-3XIWW4TB.js} +9 -9
  58. package/dist/{chunk-GCBIXUPT.js → chunk-47F6WWLQ.js} +2 -2
  59. package/dist/{chunk-TSS3D7ZY.js → chunk-4CJTQHEG.js} +3 -3
  60. package/dist/{chunk-4X7HQKAG.js → chunk-4XINO77L.js} +2 -2
  61. package/dist/{chunk-ELHJK7LM.js → chunk-5IYOKDM4.js} +12 -12
  62. package/dist/{chunk-F74G4KIH.js → chunk-5UCMYPVF.js} +2 -2
  63. package/dist/{chunk-3PJEDHLD.js → chunk-63O7LVMN.js} +3 -3
  64. package/dist/{chunk-52II7PB6.js → chunk-645WOU5I.js} +4 -4
  65. package/dist/{chunk-QEZ3DW5O.js → chunk-65AUYLU3.js} +5 -5
  66. package/dist/{chunk-G6HWNPZA.js → chunk-66L5ZRJC.js} +2 -2
  67. package/dist/{chunk-TNW6BOMM.js → chunk-6HM6HARE.js} +2 -2
  68. package/dist/{chunk-GOZXQNIM.js → chunk-6P7U3HWG.js} +3 -3
  69. package/dist/{chunk-CYCEROPR.js → chunk-6QMWECO5.js} +7 -7
  70. package/dist/{chunk-SBRUTD5O.js → chunk-6SRYCJ5I.js} +10 -10
  71. package/dist/{chunk-BLSHFIR6.js → chunk-7HTUYFR3.js} +5 -5
  72. package/dist/{chunk-2N4OUSIA.js → chunk-7L3TODI7.js} +2 -2
  73. package/dist/{chunk-P452SEKO.js → chunk-AH637HZ5.js} +2 -2
  74. package/dist/{chunk-J6GZ2254.js → chunk-AL3TCNSJ.js} +4 -4
  75. package/dist/{chunk-NIVKG3DS.js → chunk-AOFEMUHG.js} +6 -6
  76. package/dist/{chunk-BIVKPQ6Q.js → chunk-AP6NCP3V.js} +8 -8
  77. package/dist/{chunk-25Q52SOT.js → chunk-ATPWMT2E.js} +3 -3
  78. package/dist/{chunk-HXFIILGF.js → chunk-BFPF5N3H.js} +4 -4
  79. package/dist/{chunk-ROKDHO74.js → chunk-BMWMTAQF.js} +4 -4
  80. package/dist/{chunk-4Q26RNSR.js → chunk-CD4BCCNP.js} +2 -2
  81. package/dist/{chunk-5SOSQTVE.js → chunk-CIEEYVUB.js} +2 -2
  82. package/dist/{chunk-TFEHSPGQ.js → chunk-E5PPE4VA.js} +4 -4
  83. package/dist/{chunk-3UZ2VMKD.js → chunk-E6M225BJ.js} +6 -6
  84. package/dist/{chunk-TIGYOZBU.js → chunk-E6Z4FBX6.js} +4 -4
  85. package/dist/{chunk-QKERFEJS.js → chunk-EFYN5I7Z.js} +2 -2
  86. package/dist/{chunk-M3BEJJNV.js → chunk-ENQCH3SW.js} +8 -1
  87. package/dist/chunk-ENQCH3SW.js.map +1 -0
  88. package/dist/{chunk-QD5R6U5J.js → chunk-EV76IZ37.js} +2 -2
  89. package/dist/{chunk-S45INSV3.js → chunk-FF6N7BXC.js} +4 -4
  90. package/dist/{chunk-2U4LMSEX.js → chunk-FRSHF6FU.js} +3 -3
  91. package/dist/{chunk-ZOJUWVAU.js → chunk-GKL6QYZO.js} +1 -1
  92. package/dist/{chunk-ZBFLV657.js → chunk-GNXGJBCA.js} +2 -2
  93. package/dist/{chunk-5UBXIV3N.js → chunk-GRTKLWYX.js} +14 -14
  94. package/dist/{chunk-Q5XJYCFE.js → chunk-HVKUCT3W.js} +2 -2
  95. package/dist/chunk-I3V3JJS7.js +24 -0
  96. package/dist/chunk-I3V3JJS7.js.map +1 -0
  97. package/dist/{chunk-YLTU2DC4.js → chunk-IHCXMYSE.js} +2 -2
  98. package/dist/{chunk-2G4TV2ML.js → chunk-IPT2OY4B.js} +4 -4
  99. package/dist/{chunk-ZANNIXXE.js → chunk-IQMDQJCD.js} +3 -3
  100. package/dist/{chunk-S7GJNA3K.js → chunk-IQWUACVG.js} +2 -2
  101. package/dist/{chunk-QNSZYTSG.js → chunk-ITHZFHST.js} +2 -2
  102. package/dist/{chunk-OXQ7F45O.js → chunk-J4MMPQ7Q.js} +6 -6
  103. package/dist/{chunk-IBDWYRDR.js → chunk-JBCCWVU2.js} +2 -2
  104. package/dist/{chunk-H3WAT6BR.js → chunk-JC36FPQ5.js} +2 -2
  105. package/dist/{chunk-QUMKDRCF.js → chunk-JDY34KBL.js} +4 -4
  106. package/dist/{chunk-77PDJ4OE.js → chunk-KEPXC4KN.js} +2 -2
  107. package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
  108. package/dist/{chunk-M5O2ANZD.js → chunk-KUIRDD74.js} +24 -22
  109. package/dist/chunk-KUIRDD74.js.map +1 -0
  110. package/dist/{chunk-JM2YZKCQ.js → chunk-LJQFJF4J.js} +6 -6
  111. package/dist/{chunk-DC55RIEZ.js → chunk-M4IEZGCK.js} +4 -4
  112. package/dist/{chunk-UWRHHRDK.js → chunk-MKRYQROF.js} +5 -5
  113. package/dist/{chunk-LHGPU6DQ.js → chunk-MVMRUGBH.js} +6 -6
  114. package/dist/{chunk-2XOFVTTT.js → chunk-N74SGESS.js} +2 -2
  115. package/dist/{chunk-TRMZHGIX.js → chunk-NJJMVS5Y.js} +15 -15
  116. package/dist/{chunk-3DAWHP5K.js → chunk-NZSRRVJQ.js} +5 -5
  117. package/dist/{chunk-ROGO7FRA.js → chunk-O55EKIEC.js} +2 -2
  118. package/dist/{chunk-SO4DZIVF.js → chunk-ODL4ZTNI.js} +37 -35
  119. package/dist/chunk-ODL4ZTNI.js.map +1 -0
  120. package/dist/{chunk-IPD5GC7C.js → chunk-OFVCFKDH.js} +2 -2
  121. package/dist/{chunk-J5WI4QRP.js → chunk-OIGJZHDU.js} +4 -4
  122. package/dist/{chunk-K3FH3LAQ.js → chunk-OJXK5C6Z.js} +4 -4
  123. package/dist/{chunk-OL553AWT.js → chunk-P5VZSSYL.js} +12 -12
  124. package/dist/{chunk-3ICAWZUU.js → chunk-PLCYKAWH.js} +4 -4
  125. package/dist/{chunk-PDOOUXCS.js → chunk-PPCLZ4JU.js} +2 -2
  126. package/dist/{chunk-HLN2HOXX.js → chunk-PUEO37QG.js} +6 -6
  127. package/dist/{chunk-32YX7EJ3.js → chunk-QL7RHYK6.js} +13 -13
  128. package/dist/{chunk-TX6EHB2Q.js → chunk-QVMOCJRV.js} +2 -2
  129. package/dist/{chunk-YMJRLT7S.js → chunk-R2DOFBG4.js} +3 -3
  130. package/dist/{chunk-NQP4ZYGG.js → chunk-RGUUBAT5.js} +3 -3
  131. package/dist/{chunk-P4JED3ZL.js → chunk-RMXS4I66.js} +2 -2
  132. package/dist/{chunk-VKILERSL.js → chunk-RO7RUBLD.js} +2 -2
  133. package/dist/{chunk-MTTYIXSU.js → chunk-RRTVGD3J.js} +9 -9
  134. package/dist/{chunk-3TKX2RYK.js → chunk-RSK2WIEM.js} +2 -2
  135. package/dist/{chunk-DT7SNJH6.js → chunk-RYWROSL5.js} +4 -4
  136. package/dist/{chunk-SYKJBS7S.js → chunk-SHUBTAY2.js} +24 -24
  137. package/dist/{chunk-OZNBZJ3S.js → chunk-SLDRXK37.js} +8 -8
  138. package/dist/{chunk-ATWFYXEN.js → chunk-STSLB4HT.js} +139 -139
  139. package/dist/{chunk-G67EUQAB.js → chunk-TG3R2SID.js} +4 -4
  140. package/dist/{chunk-N7EKND7S.js → chunk-TRBGGJKZ.js} +169 -168
  141. package/dist/{chunk-N7EKND7S.js.map → chunk-TRBGGJKZ.js.map} +1 -1
  142. package/dist/{chunk-YAVIBVCU.js → chunk-UA2NDTIU.js} +4 -4
  143. package/dist/{chunk-KVSOEVAF.js → chunk-UE6RRXMF.js} +2 -2
  144. package/dist/{chunk-TAUHAP5J.js → chunk-UXPXOVJI.js} +9 -9
  145. package/dist/{chunk-QKES7GU6.js → chunk-VMVVSZTD.js} +2 -2
  146. package/dist/{chunk-YRZPBN46.js → chunk-VNUOAXWP.js} +2 -2
  147. package/dist/{chunk-EA2LA5RI.js → chunk-VPQFK63H.js} +2 -2
  148. package/dist/{chunk-UH3FPX3L.js → chunk-W7K5BP3M.js} +2 -2
  149. package/dist/{chunk-PKZ274PI.js → chunk-WLBEZZK5.js} +3 -3
  150. package/dist/{chunk-TQ4SCPGQ.js → chunk-WRT7GJ2D.js} +3 -3
  151. package/dist/{chunk-5MF6LMUY.js → chunk-WUUES6CU.js} +2 -2
  152. package/dist/{chunk-CC4V7HNP.js → chunk-WWK6J6SE.js} +53 -53
  153. package/dist/{chunk-LEEAO2TX.js → chunk-XICOH5HT.js} +3 -3
  154. package/dist/{chunk-CN7Q3T2J.js → chunk-XNI3URDR.js} +2 -2
  155. package/dist/{chunk-64S6X4IU.js → chunk-XTN54NML.js} +4 -4
  156. package/dist/{chunk-PWPIERBM.js → chunk-YCNIGRRF.js} +4 -4
  157. package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
  158. package/dist/{chunk-DZ7DPDVW.js → chunk-YODUDA6R.js} +15 -15
  159. package/dist/{chunk-4GMI5HFH.js → chunk-YS2GHSWN.js} +20 -20
  160. package/dist/{chunk-2K3AUDH7.js → chunk-YYOMGOHB.js} +4 -4
  161. package/dist/{chunk-B56LORLY.js → chunk-Z4Q6USKJ.js} +2 -2
  162. package/dist/{chunk-IHJZSRDM.js → chunk-ZCLEYJPB.js} +83 -83
  163. package/dist/{chunk-D5EV6Y2L.js → chunk-ZT6WPSII.js} +2 -2
  164. package/dist/{chunk-3Y5X6YFH.js → chunk-ZZ67UTQX.js} +2 -2
  165. package/dist/cli.js +147 -146
  166. package/dist/coding/export-okf-codegraph.js +30 -30
  167. package/dist/coding/pre-action-gate.js +2 -2
  168. package/dist/compounding/engine.js +31 -31
  169. package/dist/config.js +42 -42
  170. package/dist/connectors/codex-materialize-runner.js +32 -32
  171. package/dist/connectors/codex-materialize.js +2 -2
  172. package/dist/connectors/index.js +36 -36
  173. package/dist/consolidation-provenance-check.js +2 -2
  174. package/dist/contradiction/index.js +6 -6
  175. package/dist/{contradiction-scan-P7KXB5R4.js → contradiction-scan-P2MHYFVG.js} +5 -5
  176. package/dist/convergence-refresh.js +32 -32
  177. package/dist/corpus-watermark.js +33 -33
  178. package/dist/dashboard-runtime.js +2 -2
  179. package/dist/deep-recall-http-glue.js +9 -9
  180. package/dist/deep-recall.js +2 -2
  181. package/dist/embedding-fallback.js +3 -3
  182. package/dist/entity-retrieval.js +31 -31
  183. package/dist/event-order-recall.js +3 -3
  184. package/dist/explicit-capture.js +10 -10
  185. package/dist/external-wiki-access.js +89 -89
  186. package/dist/extraction-evidence-class.js +2 -2
  187. package/dist/extraction-normalization.js +1 -1
  188. package/dist/extraction-source-grounding.js +3 -3
  189. package/dist/extraction.js +46 -46
  190. package/dist/{first-start-migration-A6PHIBUQ.js → first-start-migration-QFI7B5SH.js} +7 -7
  191. package/dist/{graph-edge-decay-EKWXRBWF.js → graph-edge-decay-OEX5OGMI.js} +6 -6
  192. package/dist/graph-edge-decay-OEX5OGMI.js.map +1 -0
  193. package/dist/graph-jsonl.js +3 -3
  194. package/dist/graph-snapshot.js +3 -3
  195. package/dist/graph.js +2 -2
  196. package/dist/harmonic-retrieval.js +29 -29
  197. package/dist/index.js +300 -299
  198. package/dist/lcm/engine.js +3 -3
  199. package/dist/lcm/index.js +8 -8
  200. package/dist/local-llm-config.js +1 -1
  201. package/dist/local-llm.js +2 -2
  202. package/dist/location/index.js +32 -32
  203. package/dist/maintenance/memory-governance.js +30 -30
  204. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +29 -29
  205. package/dist/maintenance/rebuild-memory-projection-runner.js +32 -32
  206. package/dist/maintenance/rebuild-memory-projection.js +31 -31
  207. package/dist/memory-browse-operations.js +89 -89
  208. package/dist/memory-browse.js +10 -10
  209. package/dist/memory-subject.js +1 -1
  210. package/dist/namespaces/migrate.js +31 -31
  211. package/dist/namespaces/search.js +7 -7
  212. package/dist/namespaces/storage.js +30 -30
  213. package/dist/offline-sync-changeset-generations.js +4 -4
  214. package/dist/offline-sync-embedding-generation.js +3 -3
  215. package/dist/offline-sync-impression-drain.js +3 -3
  216. package/dist/offline-sync-snapshot-stream.js +6 -6
  217. package/dist/offline-sync.js +7 -7
  218. package/dist/operator-doctor-corpus.js +34 -34
  219. package/dist/operator-toolkit.js +58 -58
  220. package/dist/orchestration/backlog-scheduler.js +192 -191
  221. package/dist/orchestration/backlog-scheduler.js.map +1 -1
  222. package/dist/orchestration/buffer-drain-runner.js +192 -191
  223. package/dist/orchestration/maintenance.js +48 -48
  224. package/dist/orchestration/turn-ingestion.d.ts +2 -2
  225. package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
  226. package/dist/orchestrator.js +192 -191
  227. package/dist/provenance.js +2 -2
  228. package/dist/qmd.js +6 -6
  229. package/dist/recall-navigation-operations.js +89 -89
  230. package/dist/recall-navigation.js +88 -88
  231. package/dist/recall-state-view-admission.js +7 -7
  232. package/dist/recall-why-service.js +14 -14
  233. package/dist/recall-why.js +5 -5
  234. package/dist/reconcile/cursor.js +2 -2
  235. package/dist/reconcile/manifest.js +6 -6
  236. package/dist/reconcile/plan.js +2 -2
  237. package/dist/{resolution-23ZBDM6A.js → resolution-N7H3F2E4.js} +7 -7
  238. package/dist/resolution-N7H3F2E4.js.map +1 -0
  239. package/dist/resume-bundles.js +44 -44
  240. package/dist/salvage-envelope.js +1 -1
  241. package/dist/search/factory.js +6 -6
  242. package/dist/search/index.js +10 -10
  243. package/dist/semantic-consolidation.js +38 -38
  244. package/dist/semantic-rule-promotion.js +29 -29
  245. package/dist/semantic-rule-verifier.js +29 -29
  246. package/dist/source-agent-qualifier.js +42 -42
  247. package/dist/standup/build.js +29 -29
  248. package/dist/storage.js +28 -28
  249. package/dist/subject-config.js +1 -1
  250. package/dist/summarizer.js +5 -5
  251. package/dist/support-passport/index.js +105 -105
  252. package/dist/tier-routing.js +3 -3
  253. package/dist/{tier-stats-C3IAMS4X.js → tier-stats-FQGQSFET.js} +7 -7
  254. package/dist/transfer/capsule-export.js +2 -2
  255. package/dist/transfer/capsule-import.js +2 -2
  256. package/dist/transfer/export-okf.js +29 -29
  257. package/dist/verified-recall.js +29 -29
  258. package/dist/who-knows-cli.js +30 -30
  259. package/dist/who-knows.js +29 -29
  260. package/dist/write-envelope.js +1 -1
  261. package/package.json +2 -2
  262. package/src/access-http-admission.ts +33 -0
  263. package/src/access-http-types.ts +153 -0
  264. package/src/access-http.test.ts +63 -1
  265. package/src/access-http.ts +26 -148
  266. package/src/access-mcp.test.ts +24 -0
  267. package/src/access-mcp.ts +3 -0
  268. package/src/access-observe-replay-durability.test.ts +4 -1
  269. package/src/access-service-observe-idempotency.test.ts +44 -0
  270. package/src/buffer-admission.ts +13 -0
  271. package/src/orchestration/turn-ingestion.ts +3 -3
  272. package/dist/chunk-M3BEJJNV.js.map +0 -1
  273. package/dist/chunk-M5O2ANZD.js.map +0 -1
  274. package/dist/chunk-SO4DZIVF.js.map +0 -1
  275. /package/dist/{contradiction-scan-P7KXB5R4.js.map → access-http-admission.js.map} +0 -0
  276. /package/dist/{graph-edge-decay-EKWXRBWF.js.map → access-http-types.js.map} +0 -0
  277. /package/dist/{chunk-4XYAWK5H.js.map → chunk-25BUV3TU.js.map} +0 -0
  278. /package/dist/{chunk-C2HORX76.js.map → chunk-27XYV2XL.js.map} +0 -0
  279. /package/dist/{chunk-3NF4QUNZ.js.map → chunk-2JSDPUKD.js.map} +0 -0
  280. /package/dist/{chunk-AJHNXIQU.js.map → chunk-2LCRG2YV.js.map} +0 -0
  281. /package/dist/{chunk-ARRTLPRC.js.map → chunk-3UMDRGFS.js.map} +0 -0
  282. /package/dist/{chunk-G54BOKZ6.js.map → chunk-3XIWW4TB.js.map} +0 -0
  283. /package/dist/{chunk-GCBIXUPT.js.map → chunk-47F6WWLQ.js.map} +0 -0
  284. /package/dist/{chunk-TSS3D7ZY.js.map → chunk-4CJTQHEG.js.map} +0 -0
  285. /package/dist/{chunk-4X7HQKAG.js.map → chunk-4XINO77L.js.map} +0 -0
  286. /package/dist/{chunk-ELHJK7LM.js.map → chunk-5IYOKDM4.js.map} +0 -0
  287. /package/dist/{chunk-F74G4KIH.js.map → chunk-5UCMYPVF.js.map} +0 -0
  288. /package/dist/{chunk-3PJEDHLD.js.map → chunk-63O7LVMN.js.map} +0 -0
  289. /package/dist/{chunk-52II7PB6.js.map → chunk-645WOU5I.js.map} +0 -0
  290. /package/dist/{chunk-QEZ3DW5O.js.map → chunk-65AUYLU3.js.map} +0 -0
  291. /package/dist/{chunk-G6HWNPZA.js.map → chunk-66L5ZRJC.js.map} +0 -0
  292. /package/dist/{chunk-TNW6BOMM.js.map → chunk-6HM6HARE.js.map} +0 -0
  293. /package/dist/{chunk-GOZXQNIM.js.map → chunk-6P7U3HWG.js.map} +0 -0
  294. /package/dist/{chunk-CYCEROPR.js.map → chunk-6QMWECO5.js.map} +0 -0
  295. /package/dist/{chunk-SBRUTD5O.js.map → chunk-6SRYCJ5I.js.map} +0 -0
  296. /package/dist/{chunk-BLSHFIR6.js.map → chunk-7HTUYFR3.js.map} +0 -0
  297. /package/dist/{chunk-2N4OUSIA.js.map → chunk-7L3TODI7.js.map} +0 -0
  298. /package/dist/{chunk-P452SEKO.js.map → chunk-AH637HZ5.js.map} +0 -0
  299. /package/dist/{chunk-J6GZ2254.js.map → chunk-AL3TCNSJ.js.map} +0 -0
  300. /package/dist/{chunk-NIVKG3DS.js.map → chunk-AOFEMUHG.js.map} +0 -0
  301. /package/dist/{chunk-BIVKPQ6Q.js.map → chunk-AP6NCP3V.js.map} +0 -0
  302. /package/dist/{chunk-25Q52SOT.js.map → chunk-ATPWMT2E.js.map} +0 -0
  303. /package/dist/{chunk-HXFIILGF.js.map → chunk-BFPF5N3H.js.map} +0 -0
  304. /package/dist/{chunk-ROKDHO74.js.map → chunk-BMWMTAQF.js.map} +0 -0
  305. /package/dist/{chunk-4Q26RNSR.js.map → chunk-CD4BCCNP.js.map} +0 -0
  306. /package/dist/{chunk-5SOSQTVE.js.map → chunk-CIEEYVUB.js.map} +0 -0
  307. /package/dist/{chunk-TFEHSPGQ.js.map → chunk-E5PPE4VA.js.map} +0 -0
  308. /package/dist/{chunk-3UZ2VMKD.js.map → chunk-E6M225BJ.js.map} +0 -0
  309. /package/dist/{chunk-TIGYOZBU.js.map → chunk-E6Z4FBX6.js.map} +0 -0
  310. /package/dist/{chunk-QKERFEJS.js.map → chunk-EFYN5I7Z.js.map} +0 -0
  311. /package/dist/{chunk-QD5R6U5J.js.map → chunk-EV76IZ37.js.map} +0 -0
  312. /package/dist/{chunk-S45INSV3.js.map → chunk-FF6N7BXC.js.map} +0 -0
  313. /package/dist/{chunk-2U4LMSEX.js.map → chunk-FRSHF6FU.js.map} +0 -0
  314. /package/dist/{chunk-ZOJUWVAU.js.map → chunk-GKL6QYZO.js.map} +0 -0
  315. /package/dist/{chunk-ZBFLV657.js.map → chunk-GNXGJBCA.js.map} +0 -0
  316. /package/dist/{chunk-5UBXIV3N.js.map → chunk-GRTKLWYX.js.map} +0 -0
  317. /package/dist/{chunk-Q5XJYCFE.js.map → chunk-HVKUCT3W.js.map} +0 -0
  318. /package/dist/{chunk-YLTU2DC4.js.map → chunk-IHCXMYSE.js.map} +0 -0
  319. /package/dist/{chunk-2G4TV2ML.js.map → chunk-IPT2OY4B.js.map} +0 -0
  320. /package/dist/{chunk-ZANNIXXE.js.map → chunk-IQMDQJCD.js.map} +0 -0
  321. /package/dist/{chunk-S7GJNA3K.js.map → chunk-IQWUACVG.js.map} +0 -0
  322. /package/dist/{chunk-QNSZYTSG.js.map → chunk-ITHZFHST.js.map} +0 -0
  323. /package/dist/{chunk-OXQ7F45O.js.map → chunk-J4MMPQ7Q.js.map} +0 -0
  324. /package/dist/{chunk-IBDWYRDR.js.map → chunk-JBCCWVU2.js.map} +0 -0
  325. /package/dist/{chunk-H3WAT6BR.js.map → chunk-JC36FPQ5.js.map} +0 -0
  326. /package/dist/{chunk-QUMKDRCF.js.map → chunk-JDY34KBL.js.map} +0 -0
  327. /package/dist/{chunk-77PDJ4OE.js.map → chunk-KEPXC4KN.js.map} +0 -0
  328. /package/dist/{chunk-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
  329. /package/dist/{chunk-JM2YZKCQ.js.map → chunk-LJQFJF4J.js.map} +0 -0
  330. /package/dist/{chunk-DC55RIEZ.js.map → chunk-M4IEZGCK.js.map} +0 -0
  331. /package/dist/{chunk-UWRHHRDK.js.map → chunk-MKRYQROF.js.map} +0 -0
  332. /package/dist/{chunk-LHGPU6DQ.js.map → chunk-MVMRUGBH.js.map} +0 -0
  333. /package/dist/{chunk-2XOFVTTT.js.map → chunk-N74SGESS.js.map} +0 -0
  334. /package/dist/{chunk-TRMZHGIX.js.map → chunk-NJJMVS5Y.js.map} +0 -0
  335. /package/dist/{chunk-3DAWHP5K.js.map → chunk-NZSRRVJQ.js.map} +0 -0
  336. /package/dist/{chunk-ROGO7FRA.js.map → chunk-O55EKIEC.js.map} +0 -0
  337. /package/dist/{chunk-IPD5GC7C.js.map → chunk-OFVCFKDH.js.map} +0 -0
  338. /package/dist/{chunk-J5WI4QRP.js.map → chunk-OIGJZHDU.js.map} +0 -0
  339. /package/dist/{chunk-K3FH3LAQ.js.map → chunk-OJXK5C6Z.js.map} +0 -0
  340. /package/dist/{chunk-OL553AWT.js.map → chunk-P5VZSSYL.js.map} +0 -0
  341. /package/dist/{chunk-3ICAWZUU.js.map → chunk-PLCYKAWH.js.map} +0 -0
  342. /package/dist/{chunk-PDOOUXCS.js.map → chunk-PPCLZ4JU.js.map} +0 -0
  343. /package/dist/{chunk-HLN2HOXX.js.map → chunk-PUEO37QG.js.map} +0 -0
  344. /package/dist/{chunk-32YX7EJ3.js.map → chunk-QL7RHYK6.js.map} +0 -0
  345. /package/dist/{chunk-TX6EHB2Q.js.map → chunk-QVMOCJRV.js.map} +0 -0
  346. /package/dist/{chunk-YMJRLT7S.js.map → chunk-R2DOFBG4.js.map} +0 -0
  347. /package/dist/{chunk-NQP4ZYGG.js.map → chunk-RGUUBAT5.js.map} +0 -0
  348. /package/dist/{chunk-P4JED3ZL.js.map → chunk-RMXS4I66.js.map} +0 -0
  349. /package/dist/{chunk-VKILERSL.js.map → chunk-RO7RUBLD.js.map} +0 -0
  350. /package/dist/{chunk-MTTYIXSU.js.map → chunk-RRTVGD3J.js.map} +0 -0
  351. /package/dist/{chunk-3TKX2RYK.js.map → chunk-RSK2WIEM.js.map} +0 -0
  352. /package/dist/{chunk-DT7SNJH6.js.map → chunk-RYWROSL5.js.map} +0 -0
  353. /package/dist/{chunk-SYKJBS7S.js.map → chunk-SHUBTAY2.js.map} +0 -0
  354. /package/dist/{chunk-OZNBZJ3S.js.map → chunk-SLDRXK37.js.map} +0 -0
  355. /package/dist/{chunk-ATWFYXEN.js.map → chunk-STSLB4HT.js.map} +0 -0
  356. /package/dist/{chunk-G67EUQAB.js.map → chunk-TG3R2SID.js.map} +0 -0
  357. /package/dist/{chunk-YAVIBVCU.js.map → chunk-UA2NDTIU.js.map} +0 -0
  358. /package/dist/{chunk-KVSOEVAF.js.map → chunk-UE6RRXMF.js.map} +0 -0
  359. /package/dist/{chunk-TAUHAP5J.js.map → chunk-UXPXOVJI.js.map} +0 -0
  360. /package/dist/{chunk-QKES7GU6.js.map → chunk-VMVVSZTD.js.map} +0 -0
  361. /package/dist/{chunk-YRZPBN46.js.map → chunk-VNUOAXWP.js.map} +0 -0
  362. /package/dist/{chunk-EA2LA5RI.js.map → chunk-VPQFK63H.js.map} +0 -0
  363. /package/dist/{chunk-UH3FPX3L.js.map → chunk-W7K5BP3M.js.map} +0 -0
  364. /package/dist/{chunk-PKZ274PI.js.map → chunk-WLBEZZK5.js.map} +0 -0
  365. /package/dist/{chunk-TQ4SCPGQ.js.map → chunk-WRT7GJ2D.js.map} +0 -0
  366. /package/dist/{chunk-5MF6LMUY.js.map → chunk-WUUES6CU.js.map} +0 -0
  367. /package/dist/{chunk-CC4V7HNP.js.map → chunk-WWK6J6SE.js.map} +0 -0
  368. /package/dist/{chunk-LEEAO2TX.js.map → chunk-XICOH5HT.js.map} +0 -0
  369. /package/dist/{chunk-CN7Q3T2J.js.map → chunk-XNI3URDR.js.map} +0 -0
  370. /package/dist/{chunk-64S6X4IU.js.map → chunk-XTN54NML.js.map} +0 -0
  371. /package/dist/{chunk-PWPIERBM.js.map → chunk-YCNIGRRF.js.map} +0 -0
  372. /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
  373. /package/dist/{chunk-DZ7DPDVW.js.map → chunk-YODUDA6R.js.map} +0 -0
  374. /package/dist/{chunk-4GMI5HFH.js.map → chunk-YS2GHSWN.js.map} +0 -0
  375. /package/dist/{chunk-2K3AUDH7.js.map → chunk-YYOMGOHB.js.map} +0 -0
  376. /package/dist/{chunk-B56LORLY.js.map → chunk-Z4Q6USKJ.js.map} +0 -0
  377. /package/dist/{chunk-IHJZSRDM.js.map → chunk-ZCLEYJPB.js.map} +0 -0
  378. /package/dist/{chunk-D5EV6Y2L.js.map → chunk-ZT6WPSII.js.map} +0 -0
  379. /package/dist/{chunk-3Y5X6YFH.js.map → chunk-ZZ67UTQX.js.map} +0 -0
  380. /package/dist/{resolution-23ZBDM6A.js.map → contradiction-scan-P2MHYFVG.js.map} +0 -0
  381. /package/dist/{first-start-migration-A6PHIBUQ.js.map → first-start-migration-QFI7B5SH.js.map} +0 -0
  382. /package/dist/{tier-stats-C3IAMS4X.js.map → tier-stats-FQGQSFET.js.map} +0 -0
@@ -22,6 +22,7 @@ import {
22
22
  type TokenCapabilities,
23
23
  } from "./access-token-capabilities.js";
24
24
  import { BriefingTimeoutError } from "./briefing-deadline.js";
25
+ import { initLogger, resetLogger, type LoggerBackend } from "./logger.js";
25
26
  import { parseConfig } from "./config.js";
26
27
  import { readPair, writePair } from "./contradiction/contradiction-review.js";
27
28
  import { createChatSession } from "./chat/chat-session.js";
@@ -815,7 +816,16 @@ test("HTTP coding-context endpoint accepts projectTag shorthand", async () => {
815
816
  }
816
817
  });
817
818
 
818
- test("HTTP observe answers 503 buffer_admission_refused when durable capture hits the entry cap", async () => {
819
+ test("HTTP observe answers 503 buffer_admission_refused when durable capture hits the entry cap", async (t) => {
820
+ const warns: string[] = [];
821
+ const backend: LoggerBackend = {
822
+ info() {},
823
+ warn(msg) { warns.push(msg); },
824
+ error() {},
825
+ debug() {},
826
+ };
827
+ initLogger(backend, false, { timestamps: false });
828
+ t.after(() => resetLogger());
819
829
  const refusal = new Error("buffer at session-entry cap");
820
830
  refusal.name = "ReplayAdmissionRefusedError";
821
831
  // SAFETY: this fixture drives only the observe route; the remaining service members are unreachable.
@@ -852,6 +862,58 @@ test("HTTP observe answers 503 buffer_admission_refused when durable capture hit
852
862
  error: "buffer at session-entry cap",
853
863
  code: "buffer_admission_refused",
854
864
  });
865
+ assert.equal(response.headers.get("retry-after"), "5", "503 must carry the advisory backpressure hint");
866
+ const requestId = response.headers.get("x-request-id");
867
+ assert.ok(requestId, "the response must expose the correlation id");
868
+ assert.ok(
869
+ warns.some((line) => line.includes(requestId) && line.includes("buffer admission refused")),
870
+ `capacity refusal must log a correlated warn, got ${JSON.stringify(warns)}`,
871
+ );
872
+ } finally {
873
+ await server.stop();
874
+ }
875
+ });
876
+
877
+ test("HTTP observe missing-storage-target refusal is a non-retryable request fault, not 503 backpressure", async () => {
878
+ const refusal = new Error(
879
+ "accepted capture requires an explicit storage target (writeNamespaceOverride or scopeProfileWritePlan.writeNamespace)",
880
+ );
881
+ refusal.name = "StorageTargetRequiredError";
882
+ // SAFETY: this fixture drives only the observe route; the remaining service members are unreachable.
883
+ const service = Object.assign({} as EngramAccessService, {
884
+ observe: async () => {
885
+ throw refusal;
886
+ },
887
+ });
888
+ const server = new EngramAccessHttpServer({
889
+ service,
890
+ port: 0,
891
+ authToken: "test-token",
892
+ adminConsoleEnabled: false,
893
+ });
894
+
895
+ const status = await server.start();
896
+ try {
897
+ const response = await fetch(
898
+ `http://127.0.0.1:${status.port}/engram/v1/observe`,
899
+ {
900
+ method: "POST",
901
+ headers: {
902
+ authorization: "Bearer test-token",
903
+ "content-type": "application/json",
904
+ },
905
+ body: JSON.stringify({
906
+ sessionKey: "missing-target-test-session",
907
+ messages: [{ role: "user", content: "no target" }],
908
+ }),
909
+ },
910
+ );
911
+ assert.equal(response.status, 400, "a request with no storage target cannot succeed on retry");
912
+ assert.deepEqual(await response.json(), {
913
+ error: refusal.message,
914
+ code: "storage_target_required",
915
+ });
916
+ assert.equal(response.headers.get("retry-after"), null, "no backpressure hint on a permanent fault");
855
917
  } finally {
856
918
  await server.stop();
857
919
  }
@@ -7,6 +7,7 @@ import path from "node:path";
7
7
  import { fileURLToPath, URL } from "node:url";
8
8
  import { gunzipSync } from "node:zlib";
9
9
  import { log } from "./logger.js";
10
+ import { respondBufferAdmissionError } from "./access-http-admission.js";
10
11
  import { resolveNamespaceCapabilities } from "./capabilities.js";
11
12
  import { WriteRateLimiter, type WriteRateLimitReservation } from "./write-rate-limiter.js";
12
13
  import { abortError, isAbortError } from "./abort-error.js";
@@ -81,149 +82,30 @@ import { ReviewDeckAccessHttpBase } from "./review/review-deck-http-base.js";
81
82
  import { serializeInlineScriptValue } from "./inline-script.js";
82
83
  import { toDottedRemnicName } from "./access-mcp-tool-names.js";
83
84
  import type { SupportPassportExternalRequestHandler } from "./support-passport/public-http.js";
84
- export interface AccessHttpReadinessState {
85
- ready: boolean;
86
- warmupAttempts: number;
87
- lastError?: string | null;
88
- /**
89
- * True when the standalone init gate opened before search warm-up completed
90
- * (issue #2215): the service is functional (recall serves via fallback
91
- * retrieval), so health answers 200 with degraded info instead of 503.
92
- */
93
- degraded?: boolean;
94
- }
95
- export interface EngramAccessHttpServerOptions {
96
- service: EngramAccessService;
97
- host?: string;
98
- port?: number;
99
- authToken?: string;
100
- /** Additional valid tokens (for multi-connector auth). Checked alongside authToken. */
101
- authTokens?: string[];
102
- /** Dynamic token loader — called on each auth check so new/revoked tokens take effect without restart. */
103
- authTokensGetter?: () => string[];
104
- /**
105
- * Dynamic token-ENTRY loader ({token, connector} pairs from one coherent
106
- * snapshot). Preferred over `authTokensGetter` when a `tokenPathPolicy`
107
- * is set: the connector used for the policy decision comes from the SAME
108
- * entry that validated, so identity can never lag validation.
109
- */
110
- authTokenEntriesGetter?: () => ReadonlyArray<{ token: string; connector?: string; capabilities?: TokenCapabilities }>;
111
- /**
112
- * Optional per-request scope policy for tokens sourced from
113
- * `authTokenEntriesGetter`. Return false to deny the (validated) token
114
- * for this pathname. Static `authToken`/`authTokens` (operator-supplied)
115
- * bypass the policy. Entries whose connector is missing FAIL CLOSED when
116
- * a policy is configured.
117
- */
118
- tokenPathPolicy?: (connector: string, pathname: string | undefined) => boolean;
119
- principal?: string;
120
- maxBodyBytes?: number;
121
- /**
122
- * Max non-replayed write requests per rolling window before 429
123
- * `write_rate_limited` (issue #1937). Positive integer; defaults to 30.
124
- */
125
- writeRateLimitMaxRequests?: number;
126
- /** Rolling window for the write rate limit, in ms. Positive integer; defaults to 60000. */
127
- writeRateLimitWindowMs?: number;
128
- adminConsoleEnabled?: boolean;
129
- adminConsolePublicDir?: string;
130
- /** Inject the primary auth token into the admin console shell for trusted launch surfaces. */
131
- adminConsolePrefillToken?: boolean;
132
- trustPrincipalHeader?: boolean;
133
- /** Enable adapter-based identity resolution from request headers */
134
- enableAdapters?: boolean;
135
- /** Custom adapter registry (defaults to built-in adapters) */
136
- adapterRegistry?: AdapterRegistry;
137
- /** Enable oai-mem-citation blocks in recall responses (issue #379). */
138
- citationsEnabled?: boolean;
139
- /** Auto-enable citations for Codex adapter connections (issue #379). */
140
- citationsAutoDetect?: boolean;
141
- /** Advertise legacy engram.* tool aliases on tools/list (issue #1427). Default true. */
142
- emitLegacyTools?: boolean;
143
- /** Optional authenticated admin dashboard/config controls supplied by the host server. */
144
- adminControls?: RemnicAdminControls;
145
- /**
146
- * Standalone readiness state. Defaults to ready so embedded hosts keep their
147
- * existing health behavior.
148
- */
149
- readiness?: () => AccessHttpReadinessState;
150
- /**
151
- * When set, every 401 response includes
152
- * `WWW-Authenticate: Bearer resource_metadata="<value>"` so MCP clients
153
- * can discover the OAuth 2.0 protected-resource metadata document
154
- * (RFC 9728). Must be an absolute http(s) URL; constructor throws on
155
- * anything else. Unset → bare `Bearer`.
156
- */
157
- resourceMetadataUrl?: string;
158
- /**
159
- * Optional pre-auth request handler (e.g. OAuth facade mounted by
160
- * `@remnic/server`). Runs after the admin-console handler and BEFORE
161
- * bearer authorization. Return true if the request was fully handled
162
- * (response ended). `ctx.authorized` reports whether the request
163
- * carries a valid operator bearer token, so the handler can gate
164
- * operator-only endpoints without owning token validation.
165
- * Errors thrown by the handler flow into the existing error handling.
166
- */
167
- externalRequestHandler?: SupportPassportExternalRequestHandler;
168
- }
169
-
170
- export interface EngramAccessHttpServerStatus {
171
- running: boolean;
172
- host: string;
173
- port: number;
174
- maxBodyBytes: number;
175
- }
176
-
177
- export interface RemnicAdminHarnessStatus {
178
- id: string;
179
- label: string;
180
- detected: boolean;
181
- enabled: boolean;
182
- source?: string;
183
- detail?: string;
184
- }
185
-
186
- export interface RemnicAdminModelOption {
187
- id: string;
188
- label: string;
189
- provider: string;
190
- detected: boolean;
191
- enabled: boolean;
192
- default?: boolean;
193
- source?: string;
194
- endpoint?: string;
195
- }
196
-
197
- export interface RemnicAdminFeatureStatus {
198
- key: string;
199
- label: string;
200
- enabled: boolean;
201
- writable: boolean;
202
- restartRequired?: boolean;
203
- }
204
-
205
- export interface RemnicAdminConfigStatus {
206
- path: string;
207
- exists: boolean;
208
- writable: boolean;
209
- restartRequired: boolean;
210
- values: Record<string, string | number | boolean | null>;
211
- }
212
-
213
- export interface RemnicAdminDashboardStatus {
214
- config: RemnicAdminConfigStatus;
215
- harnesses: RemnicAdminHarnessStatus[];
216
- providers?: RemnicAdminHarnessStatus[];
217
- models: RemnicAdminModelOption[];
218
- features: RemnicAdminFeatureStatus[];
219
- }
220
-
221
- export type RemnicAdminConfigPatch = Record<string, unknown>;
222
-
223
- export interface RemnicAdminControls {
224
- status: () => Promise<RemnicAdminDashboardStatus>;
225
- update?: (patch: RemnicAdminConfigPatch) => Promise<RemnicAdminDashboardStatus>;
226
- }
85
+ import type {
86
+ AccessHttpReadinessState,
87
+ EngramAccessHttpServerOptions,
88
+ EngramAccessHttpServerStatus,
89
+ RemnicAdminHarnessStatus,
90
+ RemnicAdminModelOption,
91
+ RemnicAdminFeatureStatus,
92
+ RemnicAdminConfigStatus,
93
+ RemnicAdminDashboardStatus,
94
+ RemnicAdminConfigPatch,
95
+ RemnicAdminControls,
96
+ } from "./access-http-types.js";
97
+ export type {
98
+ AccessHttpReadinessState,
99
+ EngramAccessHttpServerOptions,
100
+ EngramAccessHttpServerStatus,
101
+ RemnicAdminHarnessStatus,
102
+ RemnicAdminModelOption,
103
+ RemnicAdminFeatureStatus,
104
+ RemnicAdminConfigStatus,
105
+ RemnicAdminDashboardStatus,
106
+ RemnicAdminConfigPatch,
107
+ RemnicAdminControls,
108
+ } from "./access-http-types.js";
227
109
 
228
110
  export function resolveDefaultAdminConsolePublicDir(sourceUrl = import.meta.url): string {
229
111
  const thisDir = path.dirname(fileURLToPath(sourceUrl));
@@ -549,11 +431,7 @@ export class EngramAccessHttpServer extends ReviewDeckAccessHttpBase {
549
431
  });
550
432
  return;
551
433
  }
552
- if (err.name === "ReplayAdmissionRefusedError") {
553
- // Durable-capture backpressure (#3251/#1908): the request was
554
- // never accepted — the buffer is at entry capacity. Retryable,
555
- // not a server fault (503, not 500).
556
- this.respondJson(res, 503, { error: err.message, code: "buffer_admission_refused" });
434
+ if (respondBufferAdmissionError(err, res, correlationId, (status, body) => this.respondJson(res, status, body))) {
557
435
  return;
558
436
  }
559
437
  if (res.headersSent) {
@@ -150,6 +150,30 @@ test("MCP reports buffer admission refusal as retryable and does not return succ
150
150
  });
151
151
 
152
152
 
153
+ test("MCP reports a missing storage target as a non-retryable storage_target_required error", async () => {
154
+ const failure = new Error("accepted capture requires an explicit storage target");
155
+ failure.name = "StorageTargetRequiredError";
156
+ // SAFETY: the mock overrides only observe; every other MCP dispatch path is unreachable in this test.
157
+ const service = Object.assign({} as EngramAccessService, {
158
+ observe: async () => {
159
+ throw failure;
160
+ },
161
+ });
162
+ const server = new EngramMcpServer(service);
163
+ const response = await server.handleRequest(
164
+ makeToolRequest("engram.observe", {
165
+ sessionKey: "no-target-session",
166
+ messages: [{ role: "user", content: "cannot succeed on retry" }],
167
+ }),
168
+ );
169
+ // SAFETY: a tools/call request always resolves to a JSON-RPC result envelope; only isError and structuredContent are asserted.
170
+ const result = response as {
171
+ result?: { isError?: boolean; structuredContent?: { code?: string; retryable?: boolean } };
172
+ };
173
+ assert.equal(result.result?.isError, true);
174
+ assert.deepEqual(result.result?.structuredContent, { code: "storage_target_required", retryable: false }, JSON.stringify(response));
175
+ });
176
+
153
177
  // ──────────────────────────────────────────────────────────────────────────
154
178
  // Finding 2 (#396 new): invalid MCP briefing format values must be rejected
155
179
  // ──────────────────────────────────────────────────────────────────────────
package/src/access-mcp.ts CHANGED
@@ -2434,6 +2434,9 @@ export class EngramMcpServer {
2434
2434
  };
2435
2435
  if (admissionBackpressure) {
2436
2436
  result.structuredContent = { code: "buffer_admission_refused", retryable: true };
2437
+ } else if (err instanceof Error && err.name === "StorageTargetRequiredError") {
2438
+ // A permanent property of the request: tell clients not to retry it.
2439
+ result.structuredContent = { code: "storage_target_required", retryable: false };
2437
2440
  }
2438
2441
  return { jsonrpc: "2.0", id, result };
2439
2442
  }
@@ -1600,7 +1600,10 @@ test("#3251 namespaced buffered admission without writeNamespaceOverride or plan
1600
1600
  [makeReplayTurn("no-target-sess", "capture without target")],
1601
1601
  bufferedObserveOptions({ sessionOwnerPrincipal: "alice" }),
1602
1602
  ),
1603
- /requires an explicit storage target/,
1603
+ (err: Error) =>
1604
+ err.name === "StorageTargetRequiredError" &&
1605
+ /requires an explicit storage target/.test(err.message),
1606
+ "the missing-target refusal must be its own non-retryable class, never ReplayAdmissionRefusedError",
1604
1607
  );
1605
1608
  assert.equal(lcmCalls.length, 0, "zero LCM archival on rejected admission");
1606
1609
  assert.equal(queued.length, 0, "zero extraction queued on rejected admission");
@@ -22,6 +22,7 @@ import { EngramAccessService } from "./access-service.js";
22
22
  import { EngramAccessInputError } from "./access-service.js";
23
23
  import { initLogger } from "./logger.js";
24
24
  import { Orchestrator } from "./orchestrator.js";
25
+ import { ReplayAdmissionRefusedError } from "./orchestration/turn-ingestion.js";
25
26
  import type { EngramAccessObserveRequest } from "./access-service.js";
26
27
  import type { CodingContext, PluginConfig } from "./types.js";
27
28
 
@@ -328,6 +329,49 @@ test("#2206 project-scope-off ignores ambient coding context in observe idempote
328
329
  }
329
330
  });
330
331
 
332
+ test("#1649 a capacity-refused observe does not consume its idempotencyKey", async () => {
333
+ const memoryDir = mkdtempSync(join(tmpdir(), "remnic-observe-cap-idem-"));
334
+ try {
335
+ const probe = makeObserveProbe(memoryDir);
336
+ const service = new EngramAccessService(probe.orch);
337
+ const orch: Orchestrator = probe.orch;
338
+ const realIngest = orch.ingestReplayBatch.bind(orch);
339
+ type IngestFn = Orchestrator["ingestReplayBatch"];
340
+ let armed = true;
341
+ orch.ingestReplayBatch = async (...args: Parameters<IngestFn>): Promise<void> => {
342
+ if (armed) {
343
+ armed = false;
344
+ throw new ReplayAdmissionRefusedError(
345
+ "durable observe capture refused: extraction buffer at entry capacity for batch containing pi-geek:abc123",
346
+ );
347
+ }
348
+ return realIngest(...args);
349
+ };
350
+ const key = "observe-capacity-pi-geek-abc123-#1";
351
+
352
+ // First attempt refuses at entry capacity — the key must stay unused.
353
+ await assert.rejects(
354
+ service.observe(observeRequest({ idempotencyKey: key })),
355
+ (err: Error) => err instanceof ReplayAdmissionRefusedError,
356
+ "the seeded first attempt must refuse with the capacity backpressure error",
357
+ );
358
+ assert.equal(probe.extractionCalls.length, 0, "refused attempt must not ingest");
359
+
360
+ // Identical retry, same key: a REAL miss once capacity exists, not a replay
361
+ // of a response that never happened.
362
+ const retry = await service.observe(observeRequest({ idempotencyKey: key }));
363
+ assert.equal(retry.idempotencyReplay, undefined, "refusal must not have cached a response");
364
+ assert.equal(probe.extractionCalls.length, 1, "retry is admitted exactly once");
365
+
366
+ // Third identical request replays — the success bound the key, not the refusal.
367
+ const replay = await service.observe(observeRequest({ idempotencyKey: key }));
368
+ assert.equal(replay.idempotencyReplay, true, "post-success identical request replays");
369
+ assert.equal(probe.extractionCalls.length, 1, "replay must not ingest again");
370
+ } finally {
371
+ rmSync(memoryDir, { recursive: true, force: true });
372
+ }
373
+ });
374
+
331
375
  test("#1649 review fix: projectTag observe replays correctly despite scope resolution side effects", async () => {
332
376
  // The fingerprint folds in the RESOLVED writeNamespace (not the raw ambient
333
377
  // context). resolveMemoryScopePlan seeds the session context from projectTag
@@ -26,6 +26,19 @@ export class ReplayAdmissionRefusedError extends Error {
26
26
  }
27
27
  }
28
28
 
29
+ /**
30
+ * Durable observe capture rejected because the request resolves to no storage
31
+ * target (namespaces ON with neither writeNamespaceOverride nor a plan's
32
+ * writeNamespace). A property of the request — retrying cannot fix it — so it
33
+ * must never be classified as retryable backpressure.
34
+ */
35
+ export class StorageTargetRequiredError extends Error {
36
+ constructor(message: string) {
37
+ super(message);
38
+ this.name = "StorageTargetRequiredError";
39
+ }
40
+ }
41
+
29
42
  /**
30
43
  * Live-admission bound (#1908 policy, backlog-safe): a NEW session enters
31
44
  * only while under the cap or when an EMPTY entry can be reclaimed. Buffered
@@ -59,8 +59,8 @@ import {
59
59
 
60
60
  // The class lives in ../buffer-admission.js next to BufferAdmissionRefusedError;
61
61
  // re-exported here so existing importers keep their import path.
62
- import { ReplayAdmissionRefusedError } from "../buffer-admission.js";
63
- export { ReplayAdmissionRefusedError };
62
+ import { ReplayAdmissionRefusedError, StorageTargetRequiredError } from "../buffer-admission.js";
63
+ export { ReplayAdmissionRefusedError, StorageTargetRequiredError };
64
64
 
65
65
  export interface TurnIngestionDeps {
66
66
  readonly buffer: SmartBuffer;
@@ -428,7 +428,7 @@ export class TurnIngestionCoordinator {
428
428
  ? options.scopeProfileWritePlan?.writeNamespace
429
429
  : this.deps.config.defaultNamespace);
430
430
  if (!resolvedWriteTarget) {
431
- throw new ReplayAdmissionRefusedError(
431
+ throw new StorageTargetRequiredError(
432
432
  "accepted capture requires an explicit storage target (writeNamespaceOverride or scopeProfileWritePlan.writeNamespace)",
433
433
  );
434
434
  }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/buffer-admission.ts"],"sourcesContent":["/** Buffer session-entry admission: refusal errors and the live-admission probe. */\n\nimport { selectEvictedBufferKeys, type BufferEvictionHooks } from \"./buffer-eviction.js\";\nimport type { BufferEntryState } from \"./types.js\";\n\n/**\n * Raised when a NEW live-capture session cannot be admitted because the\n * session-entry cap is full of non-evictable backlog. The turn was never\n * accepted; the request is retryable once extraction drains an entry.\n */\nexport class BufferAdmissionRefusedError extends Error {\n constructor(bufferKey: string, maxSessionEntries: number) {\n super(\n `buffer[${bufferKey}]: live capture refused at the session-entry cap (${maxSessionEntries}); ` +\n \"buffered backlog is no longer evicted to admit new sessions. Retry after extraction frees an entry\",\n );\n this.name = \"BufferAdmissionRefusedError\";\n }\n}\n\n/** Durable observe capture refused at the entry cap; the request is retryable. */\nexport class ReplayAdmissionRefusedError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ReplayAdmissionRefusedError\";\n }\n}\n\n/**\n * Live-admission bound (#1908 policy, backlog-safe): a NEW session enters\n * only while under the cap or when an EMPTY entry can be reclaimed. Buffered\n * backlog is never dropped for a live capture; the caller refuses instead.\n */\nexport function canAdmitNewEntryUnlocked(\n entries: Readonly<Record<string, BufferEntryState>>,\n bufferKey: string,\n maxSessionEntries: number,\n hooks: BufferEvictionHooks,\n): boolean {\n const count = Object.keys(entries).length;\n if (count < maxSessionEntries) return true;\n // Probe post-admission (as if this key had landed): admission is safe\n // exactly when an EMPTY entry could then be reclaimed.\n return selectEvictedBufferKeys(entries, [bufferKey], Math.max(0, count - 1), hooks).length > 0;\n}\n"],"mappings":";;;;;AAUO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EACrD,YAAY,WAAmB,mBAA2B;AACxD;AAAA,MACE,UAAU,SAAS,qDAAqD,iBAAiB;AAAA,IAE3F;AACA,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,8BAAN,cAA0C,MAAM;AAAA,EACrD,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAOO,SAAS,yBACd,SACA,WACA,mBACA,OACS;AACT,QAAM,QAAQ,OAAO,KAAK,OAAO,EAAE;AACnC,MAAI,QAAQ,kBAAmB,QAAO;AAGtC,SAAO,wBAAwB,SAAS,CAAC,SAAS,GAAG,KAAK,IAAI,GAAG,QAAQ,CAAC,GAAG,KAAK,EAAE,SAAS;AAC/F;","names":[]}