@remnic/core 9.69.16 → 9.69.17

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 (280) hide show
  1. package/dist/access-admin-ops-surface.d.ts +1 -1
  2. package/dist/access-admin-ops-surface.js +43 -39
  3. package/dist/access-authorization-probe.d.ts +1 -1
  4. package/dist/access-authorization-probe.js +44 -40
  5. package/dist/access-boundary.d.ts +1 -1
  6. package/dist/access-boundary.js +43 -39
  7. package/dist/access-cli.js +103 -102
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.js +43 -39
  11. package/dist/access-http-lcm-compaction.d.ts +1 -1
  12. package/dist/access-http-lifecycle-flush.d.ts +1 -1
  13. package/dist/access-http-offline-stream.d.ts +1 -1
  14. package/dist/access-http-query.js +45 -41
  15. package/dist/access-http.d.ts +2 -2
  16. package/dist/access-http.js +63 -59
  17. package/dist/access-identity-continuity-surface.js +43 -39
  18. package/dist/access-lcm-surface.d.ts +1 -1
  19. package/dist/access-lcm-surface.js +43 -39
  20. package/dist/access-mcp-output-schemas.js +1 -1
  21. package/dist/access-mcp.d.ts +1 -1
  22. package/dist/access-mcp.js +54 -50
  23. package/dist/access-namespace-preflight.js +43 -39
  24. package/dist/access-observe-transcript.d.ts +147 -0
  25. package/dist/access-observe-transcript.js +16 -0
  26. package/dist/access-observe-write-surface.d.ts +2 -1
  27. package/dist/access-observe-write-surface.js +43 -39
  28. package/dist/access-offline-manifest.js +3 -3
  29. package/dist/access-operations-batch.js +46 -42
  30. package/dist/access-operations.d.ts +2 -2
  31. package/dist/access-operations.js +51 -47
  32. package/dist/access-recall-concurrency.d.ts +1 -1
  33. package/dist/access-recall-concurrency.js +43 -39
  34. package/dist/access-recall-response.d.ts +1 -1
  35. package/dist/access-recall-response.js +43 -39
  36. package/dist/access-recall-surface.d.ts +1 -1
  37. package/dist/access-recall-surface.js +43 -39
  38. package/dist/access-schema.d.ts +4 -4
  39. package/dist/access-schema.js +5 -5
  40. package/dist/{access-service-tcC_jK6C.d.ts → access-service-DmDS8Y5P.d.ts} +9 -0
  41. package/dist/access-service-helpers.d.ts +1 -1
  42. package/dist/access-service.d.ts +1 -1
  43. package/dist/access-service.js +43 -39
  44. package/dist/access-surface-catalog.d.ts +1 -1
  45. package/dist/access-surface-catalog.js +45 -41
  46. package/dist/access-surface-catalog.js.map +1 -1
  47. package/dist/active-recall.js +6 -6
  48. package/dist/adapters/index.js +4 -4
  49. package/dist/adapters/registry.js +2 -2
  50. package/dist/{auto-sync-Q6Q2FVSC.js → auto-sync-GRUJFD2F.js} +3 -3
  51. package/dist/briefing.js +13 -13
  52. package/dist/causal-behavior.js +2 -2
  53. package/dist/causal-chain.js +2 -2
  54. package/dist/causal-consolidation.js +15 -15
  55. package/dist/causal-retrieval.js +2 -2
  56. package/dist/causal-trajectory-graph.js +2 -2
  57. package/dist/causal-trajectory.js +1 -1
  58. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  59. package/dist/{chunk-AU7Q3LSC.js → chunk-2QSZNTDO.js} +4 -4
  60. package/dist/{chunk-P6GKRT2H.js → chunk-2Z3DG5CQ.js} +1 -1
  61. package/dist/{chunk-MSDIETFC.js → chunk-376CEAYL.js} +53 -44
  62. package/dist/chunk-376CEAYL.js.map +1 -0
  63. package/dist/{chunk-XMIAU4CO.js → chunk-3ZAZ77WB.js} +2 -2
  64. package/dist/{chunk-3TSU662L.js → chunk-46QMN7I7.js} +5 -5
  65. package/dist/{chunk-LF6SHWVV.js → chunk-5CX3NSR7.js} +2 -2
  66. package/dist/{chunk-QRDSXR3V.js → chunk-5DRBG5U6.js} +2 -2
  67. package/dist/{chunk-I4QAH4SY.js → chunk-5J36BYRI.js} +3 -3
  68. package/dist/{chunk-7JV4JST3.js → chunk-5Z6JYMK4.js} +44 -44
  69. package/dist/{chunk-JGXMA6HL.js → chunk-6FUMA6AA.js} +2 -2
  70. package/dist/{chunk-K2IJH4D3.js → chunk-7RRUHJPG.js} +7 -7
  71. package/dist/{chunk-NNBZS3DY.js → chunk-AG46P24C.js} +4 -4
  72. package/dist/{chunk-QUVWFZOU.js → chunk-AYHPGLG6.js} +2 -2
  73. package/dist/{chunk-S35IIP5P.js → chunk-B67W7CBL.js} +2 -2
  74. package/dist/{chunk-OLBZ2WGG.js → chunk-C2JCVZWX.js} +2 -2
  75. package/dist/{chunk-S5G2LAL7.js → chunk-CHWUICVY.js} +4 -4
  76. package/dist/{chunk-XQGFIAG7.js → chunk-CM3JBYD4.js} +2 -2
  77. package/dist/{chunk-F2ERDKY2.js → chunk-CWPVXVIT.js} +16 -16
  78. package/dist/{chunk-BE4Y6GK6.js → chunk-D35XLYQ7.js} +11 -11
  79. package/dist/{chunk-P7LVYPIX.js → chunk-DBLVQROL.js} +3 -3
  80. package/dist/{chunk-5H2G5X4R.js → chunk-DGKQVGLC.js} +3 -3
  81. package/dist/{chunk-M7DGN6JZ.js → chunk-EQEP23JK.js} +2 -2
  82. package/dist/{chunk-I6DUKBUI.js → chunk-EYKDBZB3.js} +2 -2
  83. package/dist/{chunk-LUDXSSTW.js → chunk-FCL6ENLF.js} +2 -2
  84. package/dist/{chunk-LJAP4KSW.js → chunk-FK2SJX27.js} +2 -2
  85. package/dist/{chunk-4WIKMOE3.js → chunk-GF7QLY6E.js} +1 -1
  86. package/dist/{chunk-B64IVEOH.js → chunk-GI726D4G.js} +2 -2
  87. package/dist/{chunk-NHLEFBE2.js → chunk-I4Y6TBD7.js} +3 -3
  88. package/dist/{chunk-BO4PWIJY.js → chunk-I672YBXY.js} +3 -3
  89. package/dist/{chunk-HODFGQGT.js → chunk-IDZU6I4H.js} +2 -2
  90. package/dist/{chunk-OAKATRAN.js → chunk-IO4OJ73B.js} +10 -10
  91. package/dist/{chunk-CTCGHNWN.js → chunk-J2R275FN.js} +4 -4
  92. package/dist/{chunk-C25N5HWX.js → chunk-J6HRJ37H.js} +2 -2
  93. package/dist/{chunk-XJJYSX6F.js → chunk-JCUG7AXZ.js} +4 -4
  94. package/dist/{chunk-BX6GW4KC.js → chunk-JMAG7WZ7.js} +2 -2
  95. package/dist/{chunk-7LCGFUMB.js → chunk-KQAFEZQX.js} +4 -4
  96. package/dist/{chunk-BEXFNGQ3.js → chunk-LE7B5ETE.js} +3 -3
  97. package/dist/chunk-LVE64P5Y.js +80 -0
  98. package/dist/chunk-LVE64P5Y.js.map +1 -0
  99. package/dist/{chunk-VAMZYOOV.js → chunk-MAIBNEB6.js} +2 -2
  100. package/dist/{chunk-VYD63IFH.js → chunk-N3DSSCOR.js} +2 -2
  101. package/dist/{chunk-IEZ6CGTW.js → chunk-N3SS45OW.js} +115 -55
  102. package/dist/chunk-N3SS45OW.js.map +1 -0
  103. package/dist/{chunk-SXHBZXHK.js → chunk-NAOAZASM.js} +5 -5
  104. package/dist/{chunk-3BS2OGDT.js → chunk-NCUODVUI.js} +5 -5
  105. package/dist/{chunk-63I7LMLG.js → chunk-NISCAOSR.js} +2 -2
  106. package/dist/{chunk-YWN3GYI2.js → chunk-NYFWBYY4.js} +2 -2
  107. package/dist/{chunk-BIJAWZYW.js → chunk-OLT3YTDH.js} +4 -4
  108. package/dist/{chunk-BFDOBESV.js → chunk-QFMFZILG.js} +2 -2
  109. package/dist/{chunk-G7VEQEMG.js → chunk-QVSRE355.js} +65 -39
  110. package/dist/chunk-QVSRE355.js.map +1 -0
  111. package/dist/{chunk-N37X5RU7.js → chunk-RACZB5HT.js} +4 -4
  112. package/dist/{chunk-5JQV4T5Q.js → chunk-ROHBPMWD.js} +2 -2
  113. package/dist/{chunk-ZKZCJRRO.js → chunk-S6ZZOFVJ.js} +2 -2
  114. package/dist/{chunk-KLSPKMIO.js → chunk-SJ5JGIBT.js} +2 -2
  115. package/dist/{chunk-JHTF22NQ.js → chunk-TA7UZZMW.js} +2 -2
  116. package/dist/{chunk-2XJDAEAM.js → chunk-V5RWV5DK.js} +5 -5
  117. package/dist/{chunk-2EHDPHMD.js → chunk-W7M7NKR7.js} +2 -2
  118. package/dist/{chunk-4UVDLNHQ.js → chunk-WHO6ITU7.js} +2 -2
  119. package/dist/{chunk-7ZMU4XQT.js → chunk-WMZ6F7GY.js} +2 -2
  120. package/dist/{chunk-W6GEMUZM.js → chunk-WOEKJPJG.js} +13 -13
  121. package/dist/{chunk-5YQ7RFSO.js → chunk-WP37SBRE.js} +2 -2
  122. package/dist/{chunk-RJ57OOCD.js → chunk-X66BHMAU.js} +2 -2
  123. package/dist/{chunk-W272SWN7.js → chunk-X73YCO3E.js} +6 -6
  124. package/dist/{chunk-PAWIY5OQ.js → chunk-XAJWPB2V.js} +6 -6
  125. package/dist/{chunk-QVI63XSO.js → chunk-XR6LLNLU.js} +48 -48
  126. package/dist/{chunk-GIC6BASP.js → chunk-XZBXINXZ.js} +4 -4
  127. package/dist/{chunk-APZXA4WI.js → chunk-Y7E5SUZ6.js} +2 -2
  128. package/dist/{chunk-LDOQE34V.js → chunk-YCJASQMN.js} +2 -2
  129. package/dist/{chunk-H5IIBGDM.js → chunk-YYE5MKRX.js} +2 -2
  130. package/dist/{chunk-TRLCMLX7.js → chunk-YYP5GM6J.js} +2 -2
  131. package/dist/{chunk-OUKBMQ2O.js → chunk-Z3SQEEB6.js} +2 -2
  132. package/dist/{chunk-NN5CQTAJ.js → chunk-ZEBRENA6.js} +2 -2
  133. package/dist/{cli-BI9YYpKx.d.ts → cli-CYQIKncA.d.ts} +1 -1
  134. package/dist/cli.d.ts +2 -2
  135. package/dist/cli.js +85 -81
  136. package/dist/coding/export-okf-codegraph.js +12 -12
  137. package/dist/coding/pre-action-gate.js +2 -2
  138. package/dist/compounding/engine.js +12 -12
  139. package/dist/config.js +6 -6
  140. package/dist/connectors/codex-materialize-runner.js +12 -12
  141. package/dist/connectors/index.js +12 -12
  142. package/dist/convergence-refresh.js +14 -14
  143. package/dist/conversation-index/backend.js +2 -2
  144. package/dist/corpus-watermark.js +14 -14
  145. package/dist/deep-recall-http-glue.d.ts +1 -1
  146. package/dist/deep-recall-http-glue.js +6 -6
  147. package/dist/deep-recall-mcp-tools.d.ts +1 -1
  148. package/dist/deep-recall.js +2 -2
  149. package/dist/entity-retrieval.js +12 -12
  150. package/dist/external-wiki-access.d.ts +1 -1
  151. package/dist/external-wiki-access.js +44 -40
  152. package/dist/external-wiki-mcp-tools.d.ts +1 -1
  153. package/dist/extraction.js +15 -15
  154. package/dist/{graph-edge-decay-FXGELBFA.js → graph-edge-decay-DGTBFALQ.js} +4 -4
  155. package/dist/graph-edge-decay-DGTBFALQ.js.map +1 -0
  156. package/dist/graph-snapshot.js +3 -3
  157. package/dist/graph.js +2 -2
  158. package/dist/harmonic-retrieval.js +1 -1
  159. package/dist/index.d.ts +4 -4
  160. package/dist/index.js +119 -118
  161. package/dist/location/index.js +14 -14
  162. package/dist/maintenance/memory-governance.js +12 -12
  163. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -12
  164. package/dist/maintenance/rebuild-memory-projection.js +13 -13
  165. package/dist/mcp-memory-inspector-app.d.ts +1 -1
  166. package/dist/memory-subject-cli.d.ts +1 -1
  167. package/dist/memory-subject.d.ts +1 -1
  168. package/dist/namespaces/migrate.js +13 -13
  169. package/dist/namespaces/search.js +9 -9
  170. package/dist/namespaces/storage.js +12 -12
  171. package/dist/offline-sync.js +2 -2
  172. package/dist/operator-doctor-corpus.js +15 -15
  173. package/dist/operator-toolkit.js +28 -28
  174. package/dist/orchestration/maintenance.js +20 -20
  175. package/dist/orchestrator.js +103 -102
  176. package/dist/{public-http-Bocro5ZU.d.ts → public-http-C_hWt6I8.d.ts} +1 -1
  177. package/dist/resume-bundles.js +7 -7
  178. package/dist/search/factory.js +8 -8
  179. package/dist/search/index.js +13 -13
  180. package/dist/search/lancedb-backend.js +2 -2
  181. package/dist/search/meilisearch-backend.js +2 -2
  182. package/dist/search/orama-backend.js +2 -2
  183. package/dist/semantic-consolidation.js +13 -13
  184. package/dist/semantic-rule-promotion.js +12 -12
  185. package/dist/semantic-rule-verifier.js +12 -12
  186. package/dist/source-agent-qualifier.js +12 -12
  187. package/dist/standup/build.js +12 -12
  188. package/dist/storage.js +11 -11
  189. package/dist/summarizer.d.ts +29 -3
  190. package/dist/summarizer.js +6 -4
  191. package/dist/support-passport/index.d.ts +4 -4
  192. package/dist/support-passport/index.js +46 -42
  193. package/dist/transfer/capsule-export.js +2 -2
  194. package/dist/transfer/capsule-import.js +2 -2
  195. package/dist/transfer/export-okf.js +13 -13
  196. package/dist/verified-recall.js +12 -12
  197. package/dist/who-knows-cli.d.ts +1 -1
  198. package/dist/who-knows-cli.js +13 -13
  199. package/dist/who-knows.d.ts +1 -1
  200. package/dist/who-knows.js +12 -12
  201. package/package.json +2 -2
  202. package/src/access-mcp-output-schemas.ts +60 -34
  203. package/src/access-observe-transcript-persistence.test.ts +252 -0
  204. package/src/access-observe-transcript.ts +153 -0
  205. package/src/access-observe-write-surface.ts +234 -224
  206. package/src/access-service.ts +33 -28
  207. package/src/summarizer.ts +217 -111
  208. package/src/summary-snapshot.test.ts +8 -6
  209. package/dist/chunk-G7VEQEMG.js.map +0 -1
  210. package/dist/chunk-IEZ6CGTW.js.map +0 -1
  211. package/dist/chunk-MSDIETFC.js.map +0 -1
  212. /package/dist/{graph-edge-decay-FXGELBFA.js.map → access-observe-transcript.js.map} +0 -0
  213. /package/dist/{auto-sync-Q6Q2FVSC.js.map → auto-sync-GRUJFD2F.js.map} +0 -0
  214. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  215. /package/dist/{chunk-AU7Q3LSC.js.map → chunk-2QSZNTDO.js.map} +0 -0
  216. /package/dist/{chunk-P6GKRT2H.js.map → chunk-2Z3DG5CQ.js.map} +0 -0
  217. /package/dist/{chunk-XMIAU4CO.js.map → chunk-3ZAZ77WB.js.map} +0 -0
  218. /package/dist/{chunk-3TSU662L.js.map → chunk-46QMN7I7.js.map} +0 -0
  219. /package/dist/{chunk-LF6SHWVV.js.map → chunk-5CX3NSR7.js.map} +0 -0
  220. /package/dist/{chunk-QRDSXR3V.js.map → chunk-5DRBG5U6.js.map} +0 -0
  221. /package/dist/{chunk-I4QAH4SY.js.map → chunk-5J36BYRI.js.map} +0 -0
  222. /package/dist/{chunk-7JV4JST3.js.map → chunk-5Z6JYMK4.js.map} +0 -0
  223. /package/dist/{chunk-JGXMA6HL.js.map → chunk-6FUMA6AA.js.map} +0 -0
  224. /package/dist/{chunk-K2IJH4D3.js.map → chunk-7RRUHJPG.js.map} +0 -0
  225. /package/dist/{chunk-NNBZS3DY.js.map → chunk-AG46P24C.js.map} +0 -0
  226. /package/dist/{chunk-QUVWFZOU.js.map → chunk-AYHPGLG6.js.map} +0 -0
  227. /package/dist/{chunk-S35IIP5P.js.map → chunk-B67W7CBL.js.map} +0 -0
  228. /package/dist/{chunk-OLBZ2WGG.js.map → chunk-C2JCVZWX.js.map} +0 -0
  229. /package/dist/{chunk-S5G2LAL7.js.map → chunk-CHWUICVY.js.map} +0 -0
  230. /package/dist/{chunk-XQGFIAG7.js.map → chunk-CM3JBYD4.js.map} +0 -0
  231. /package/dist/{chunk-F2ERDKY2.js.map → chunk-CWPVXVIT.js.map} +0 -0
  232. /package/dist/{chunk-BE4Y6GK6.js.map → chunk-D35XLYQ7.js.map} +0 -0
  233. /package/dist/{chunk-P7LVYPIX.js.map → chunk-DBLVQROL.js.map} +0 -0
  234. /package/dist/{chunk-5H2G5X4R.js.map → chunk-DGKQVGLC.js.map} +0 -0
  235. /package/dist/{chunk-M7DGN6JZ.js.map → chunk-EQEP23JK.js.map} +0 -0
  236. /package/dist/{chunk-I6DUKBUI.js.map → chunk-EYKDBZB3.js.map} +0 -0
  237. /package/dist/{chunk-LUDXSSTW.js.map → chunk-FCL6ENLF.js.map} +0 -0
  238. /package/dist/{chunk-LJAP4KSW.js.map → chunk-FK2SJX27.js.map} +0 -0
  239. /package/dist/{chunk-4WIKMOE3.js.map → chunk-GF7QLY6E.js.map} +0 -0
  240. /package/dist/{chunk-B64IVEOH.js.map → chunk-GI726D4G.js.map} +0 -0
  241. /package/dist/{chunk-NHLEFBE2.js.map → chunk-I4Y6TBD7.js.map} +0 -0
  242. /package/dist/{chunk-BO4PWIJY.js.map → chunk-I672YBXY.js.map} +0 -0
  243. /package/dist/{chunk-HODFGQGT.js.map → chunk-IDZU6I4H.js.map} +0 -0
  244. /package/dist/{chunk-OAKATRAN.js.map → chunk-IO4OJ73B.js.map} +0 -0
  245. /package/dist/{chunk-CTCGHNWN.js.map → chunk-J2R275FN.js.map} +0 -0
  246. /package/dist/{chunk-C25N5HWX.js.map → chunk-J6HRJ37H.js.map} +0 -0
  247. /package/dist/{chunk-XJJYSX6F.js.map → chunk-JCUG7AXZ.js.map} +0 -0
  248. /package/dist/{chunk-BX6GW4KC.js.map → chunk-JMAG7WZ7.js.map} +0 -0
  249. /package/dist/{chunk-7LCGFUMB.js.map → chunk-KQAFEZQX.js.map} +0 -0
  250. /package/dist/{chunk-BEXFNGQ3.js.map → chunk-LE7B5ETE.js.map} +0 -0
  251. /package/dist/{chunk-VAMZYOOV.js.map → chunk-MAIBNEB6.js.map} +0 -0
  252. /package/dist/{chunk-VYD63IFH.js.map → chunk-N3DSSCOR.js.map} +0 -0
  253. /package/dist/{chunk-SXHBZXHK.js.map → chunk-NAOAZASM.js.map} +0 -0
  254. /package/dist/{chunk-3BS2OGDT.js.map → chunk-NCUODVUI.js.map} +0 -0
  255. /package/dist/{chunk-63I7LMLG.js.map → chunk-NISCAOSR.js.map} +0 -0
  256. /package/dist/{chunk-YWN3GYI2.js.map → chunk-NYFWBYY4.js.map} +0 -0
  257. /package/dist/{chunk-BIJAWZYW.js.map → chunk-OLT3YTDH.js.map} +0 -0
  258. /package/dist/{chunk-BFDOBESV.js.map → chunk-QFMFZILG.js.map} +0 -0
  259. /package/dist/{chunk-N37X5RU7.js.map → chunk-RACZB5HT.js.map} +0 -0
  260. /package/dist/{chunk-5JQV4T5Q.js.map → chunk-ROHBPMWD.js.map} +0 -0
  261. /package/dist/{chunk-ZKZCJRRO.js.map → chunk-S6ZZOFVJ.js.map} +0 -0
  262. /package/dist/{chunk-KLSPKMIO.js.map → chunk-SJ5JGIBT.js.map} +0 -0
  263. /package/dist/{chunk-JHTF22NQ.js.map → chunk-TA7UZZMW.js.map} +0 -0
  264. /package/dist/{chunk-2XJDAEAM.js.map → chunk-V5RWV5DK.js.map} +0 -0
  265. /package/dist/{chunk-2EHDPHMD.js.map → chunk-W7M7NKR7.js.map} +0 -0
  266. /package/dist/{chunk-4UVDLNHQ.js.map → chunk-WHO6ITU7.js.map} +0 -0
  267. /package/dist/{chunk-7ZMU4XQT.js.map → chunk-WMZ6F7GY.js.map} +0 -0
  268. /package/dist/{chunk-W6GEMUZM.js.map → chunk-WOEKJPJG.js.map} +0 -0
  269. /package/dist/{chunk-5YQ7RFSO.js.map → chunk-WP37SBRE.js.map} +0 -0
  270. /package/dist/{chunk-RJ57OOCD.js.map → chunk-X66BHMAU.js.map} +0 -0
  271. /package/dist/{chunk-W272SWN7.js.map → chunk-X73YCO3E.js.map} +0 -0
  272. /package/dist/{chunk-PAWIY5OQ.js.map → chunk-XAJWPB2V.js.map} +0 -0
  273. /package/dist/{chunk-QVI63XSO.js.map → chunk-XR6LLNLU.js.map} +0 -0
  274. /package/dist/{chunk-GIC6BASP.js.map → chunk-XZBXINXZ.js.map} +0 -0
  275. /package/dist/{chunk-APZXA4WI.js.map → chunk-Y7E5SUZ6.js.map} +0 -0
  276. /package/dist/{chunk-LDOQE34V.js.map → chunk-YCJASQMN.js.map} +0 -0
  277. /package/dist/{chunk-H5IIBGDM.js.map → chunk-YYE5MKRX.js.map} +0 -0
  278. /package/dist/{chunk-TRLCMLX7.js.map → chunk-YYP5GM6J.js.map} +0 -0
  279. /package/dist/{chunk-OUKBMQ2O.js.map → chunk-Z3SQEEB6.js.map} +0 -0
  280. /package/dist/{chunk-NN5CQTAJ.js.map → chunk-ZEBRENA6.js.map} +0 -0
@@ -30,11 +30,13 @@ import {
30
30
  NamespaceNotWritableError,
31
31
  } from "./access-service.js";
32
32
  import { extractionForceFlush } from "./access-extraction-force-flush.js";
33
+ import { ObserveTranscriptPersister, observeTranscriptSessionKey } from "./access-observe-transcript.js";
33
34
  import { FileCalendarSource, buildBriefing, parseBriefingFocus, parseBriefingWindow } from "./briefing.js";
34
35
  import {
35
36
  resolveCompressionCapabilities,
36
37
  resolveNamespaceCapabilities,
37
38
  resolveObjectiveStateCapabilities,
39
+ resolvePresentationCapabilities,
38
40
  } from "./capabilities.js";
39
41
  import { lcmSessionKeyForNamespace } from "./coding/coding-namespace.js";
40
42
  import {
@@ -110,15 +112,12 @@ export interface AccessObserveWriteSurfaceDeps {
110
112
  authenticatedPrincipal?: string;
111
113
  }
112
114
  ): Promise<MemoryScopePlan>;
113
- cancelPendingObservePreparations?(
114
- sessionKey: string,
115
- scopeHint?: string,
116
- ): void;
115
+ cancelPendingObservePreparations?(sessionKey: string, scopeHint?: string): void;
117
116
  cancelPendingObserveExtractions?(
118
117
  sessionKey: string,
119
118
  principal?: string,
120
119
  namespace?: string,
121
- scopeHint?: string,
120
+ scopeHint?: string
122
121
  ): void;
123
122
  resolveReadableNamespace(namespace: string | undefined, principal?: string): string;
124
123
  validateWriteCandidate(
@@ -135,6 +134,7 @@ export interface AccessObserveWriteSurfaceDeps {
135
134
  export class AccessObserveWriteSurface {
136
135
  private quarantineStoreInstance?: WriteQuarantineStore;
137
136
  private readonly pendingObserveExtractions = new PendingObserveExtractionTracker();
137
+ private readonly observeTranscriptPersister = new ObserveTranscriptPersister();
138
138
 
139
139
  public cancelPendingObservePreparations(sessionKey: string, scopeHint?: string): void {
140
140
  this.pendingObserveExtractions.cancelPreparations(sessionKey, scopeHint);
@@ -144,7 +144,7 @@ export class AccessObserveWriteSurface {
144
144
  sessionKey: string,
145
145
  principal?: string,
146
146
  namespace?: string,
147
- scopeHint?: string,
147
+ scopeHint?: string
148
148
  ): void {
149
149
  this.pendingObserveExtractions.cancel(sessionKey, principal, namespace, scopeHint);
150
150
  }
@@ -152,9 +152,7 @@ export class AccessObserveWriteSurface {
152
152
 
153
153
  private quarantineStore(): WriteQuarantineStore {
154
154
  if (!this.quarantineStoreInstance) {
155
- this.quarantineStoreInstance = new WriteQuarantineStore(
156
- this.deps.orchestrator.config.memoryDir,
157
- );
155
+ this.quarantineStoreInstance = new WriteQuarantineStore(this.deps.orchestrator.config.memoryDir);
158
156
  }
159
157
  return this.quarantineStoreInstance;
160
158
  }
@@ -167,11 +165,7 @@ export class AccessObserveWriteSurface {
167
165
  * the caller re-throws. The ACL placement is unchanged; the payload simply
168
166
  * stops being destroyed.
169
167
  */
170
- private async parkRejectedWrite(
171
- err: unknown,
172
- operation: QuarantineOperation,
173
- payload: unknown,
174
- ): Promise<void> {
168
+ private async parkRejectedWrite(err: unknown, operation: QuarantineOperation, payload: unknown): Promise<void> {
175
169
  if (!(err instanceof NamespaceNotWritableError)) return;
176
170
  try {
177
171
  await this.quarantineStore().quarantine({
@@ -181,11 +175,11 @@ export class AccessObserveWriteSurface {
181
175
  payload,
182
176
  });
183
177
  log.warn(
184
- `quarantine: parked rejected ${operation} write for principal=${err.principal ?? "-"} attemptedNamespace=${err.attemptedNamespace} (namespace not writable); replay after fixing config`,
178
+ `quarantine: parked rejected ${operation} write for principal=${err.principal ?? "-"} attemptedNamespace=${err.attemptedNamespace} (namespace not writable); replay after fixing config`
185
179
  );
186
180
  } catch (quarantineErr) {
187
181
  log.warn(
188
- `quarantine: failed to park rejected ${operation} write: ${quarantineErr instanceof Error ? quarantineErr.message : String(quarantineErr)}`,
182
+ `quarantine: failed to park rejected ${operation} write: ${quarantineErr instanceof Error ? quarantineErr.message : String(quarantineErr)}`
189
183
  );
190
184
  }
191
185
  }
@@ -272,14 +266,20 @@ export class AccessObserveWriteSurface {
272
266
  if (typeof (qmd as { status?: unknown }).status === "function") {
273
267
  try {
274
268
  const statusReport = await Promise.race([
275
- (qmd as unknown as { status: () => Promise<{ pendingEmbeddings: number | null; oldestPendingAgeMs: number | null }> }).status(),
269
+ (
270
+ qmd as unknown as {
271
+ status: () => Promise<{ pendingEmbeddings: number | null; oldestPendingAgeMs: number | null }>;
272
+ }
273
+ ).status(),
276
274
  new Promise<null>((resolve) => setTimeout(() => resolve(null), 5_000).unref?.()),
277
275
  ]);
278
276
  if (statusReport) {
279
277
  pendingEmbeddings = statusReport.pendingEmbeddings;
280
278
  oldestPendingAgeMs = statusReport.oldestPendingAgeMs;
281
279
  }
282
- } catch { /* status probe failed — non-fatal */ }
280
+ } catch {
281
+ /* status probe failed — non-fatal */
282
+ }
283
283
  }
284
284
  if (threshold > 0 && pendingEmbeddings !== null && pendingEmbeddings > threshold) {
285
285
  degraded = true;
@@ -682,230 +682,240 @@ export class AccessObserveWriteSurface {
682
682
  // session mutation.
683
683
  const observePreparation = this.pendingObserveExtractions.reserve(
684
684
  request.sessionKey,
685
- pendingObserveScopeHint(request),
685
+ pendingObserveScopeHint(request)
686
686
  );
687
687
  try {
688
-
689
- let scope: MemoryScopePlan;
690
- try {
691
- scope = await this.deps.resolveMemoryScopePlan(request);
692
- } catch (err) {
693
- // A replay re-submit sets suppressQuarantine so a still-unwritable target
694
- // propagates instead of re-parking (#1888); observe has no dryRun path.
695
- if (request.suppressQuarantine !== true) {
696
- await this.parkRejectedWrite(err, "observe", request);
688
+ let scope: MemoryScopePlan;
689
+ try {
690
+ scope = await this.deps.resolveMemoryScopePlan(request);
691
+ } catch (err) {
692
+ // A replay re-submit sets suppressQuarantine so a still-unwritable target
693
+ // propagates instead of re-parking (#1888); observe has no dryRun path.
694
+ if (request.suppressQuarantine !== true) {
695
+ await this.parkRejectedWrite(err, "observe", request);
696
+ }
697
+ throw err;
697
698
  }
698
- throw err;
699
- }
700
- const writeNamespace = scope.writeNamespace;
701
- observePreparation.setScope(scope.principal, writeNamespace);
699
+ const writeNamespace = scope.writeNamespace;
700
+ observePreparation.setScope(scope.principal, writeNamespace);
702
701
 
703
- // Backward-compatible BASE writable namespace (pre-#1495 response semantics)
704
- // for the legacy `namespace` response field. DERIVED from the already-resolved
705
- // scope plan — NOT a second writable-namespace resolution call
706
- // call (#1505 thread jvO). The fresh call re-authorized `undefined ⇒
707
- // config.defaultNamespace` a SECOND time; under a restrictive default-namespace
708
- // write policy that re-auth could REJECT an otherwise valid project-scoped
709
- // observe whose effective self/project write target the scope plan already
710
- // authorized (the same target memory_store/suggestion_submit accept). Worse,
711
- // that post-plan rejection fired AFTER `resolveMemoryScopePlan` may have seeded
712
- // the coding context, leaving an orphaned session binding behind. The plan is
713
- // the single authorization point (rule 22 / 39); the legacy field must reuse it
714
- // and never re-authorize. Pre-#1495 semantics were exactly
715
- // the writable-namespace resolver (overlay-agnostic): the explicit
716
- // namespace when supplied, else `config.defaultNamespace` for user-project
717
- // coding overlays. Hosted scope-profile layers such as `teamProject` report
718
- // their effective profile write namespace because there is no legacy
719
- // overlay-compatible base namespace for those writes.
720
- const namespace = this.deps.legacyResponseNamespaceForScope(scope);
721
- const shouldWriteObjectiveState =
722
- resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory === true &&
723
- resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites === true;
702
+ // Backward-compatible BASE writable namespace (pre-#1495 response semantics)
703
+ // for the legacy `namespace` response field. DERIVED from the already-resolved
704
+ // scope plan — NOT a second writable-namespace resolution call
705
+ // call (#1505 thread jvO). The fresh call re-authorized `undefined ⇒
706
+ // config.defaultNamespace` a SECOND time; under a restrictive default-namespace
707
+ // write policy that re-auth could REJECT an otherwise valid project-scoped
708
+ // observe whose effective self/project write target the scope plan already
709
+ // authorized (the same target memory_store/suggestion_submit accept). Worse,
710
+ // that post-plan rejection fired AFTER `resolveMemoryScopePlan` may have seeded
711
+ // the coding context, leaving an orphaned session binding behind. The plan is
712
+ // the single authorization point (rule 22 / 39); the legacy field must reuse it
713
+ // and never re-authorize. Pre-#1495 semantics were exactly
714
+ // the writable-namespace resolver (overlay-agnostic): the explicit
715
+ // namespace when supplied, else `config.defaultNamespace` for user-project
716
+ // coding overlays. Hosted scope-profile layers such as `teamProject` report
717
+ // their effective profile write namespace because there is no legacy
718
+ // overlay-compatible base namespace for those writes.
719
+ const namespace = this.deps.legacyResponseNamespaceForScope(scope);
720
+ const shouldWriteObjectiveState =
721
+ resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory === true &&
722
+ resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites === true;
724
723
 
725
- // 2. Auto-resolve coding context from cwd/projectTag so a LATER bare recall
726
- // on the same session is project-scoped (rule 42: same namespace layer as
727
- // recall). Done AFTER the scope plan authorized the write, so a rejected
728
- // request never leaves orphaned context on the session.
729
- await this.deps.maybeAttachCodingContext(request.sessionKey, {
730
- cwd: request.cwd,
731
- projectTag: request.projectTag,
732
- });
724
+ // 2. Auto-resolve coding context from cwd/projectTag so a LATER bare recall
725
+ // on the same session is project-scoped (rule 42: same namespace layer as
726
+ // recall). Done AFTER the scope plan authorized the write, so a rejected
727
+ // request never leaves orphaned context on the session.
728
+ await this.deps.maybeAttachCodingContext(request.sessionKey, {
729
+ cwd: request.cwd,
730
+ projectTag: request.projectTag,
731
+ });
733
732
 
734
- // Prefix sessionKey with the EFFECTIVE write namespace for LCM archival so
735
- // observed turns are scoped to the same namespace project-scoped recall
736
- // reads. The SAME `lcmSessionKeyForNamespace` helper is used by the
737
- // orchestrator recall readers and by compaction flush/record, so the LCM
738
- // write key and every read/flush key agree (#1495, rule 42). Only prefixes
739
- // when the namespace diverges from the default store; a single-store
740
- // deployment keeps the raw sessionKey unchanged.
741
- const lcmSessionKey =
742
- lcmSessionKeyForNamespace(writeNamespace, request.sessionKey, this.deps.orchestrator.config.defaultNamespace) ??
743
- request.sessionKey;
733
+ // Prefix sessionKey with the EFFECTIVE write namespace for LCM archival so
734
+ // observed turns are scoped to the same namespace project-scoped recall
735
+ // reads. The SAME `lcmSessionKeyForNamespace` helper is used by the
736
+ // orchestrator recall readers and by compaction flush/record, so the LCM
737
+ // write key and every read/flush key agree (#1495, rule 42). Only prefixes
738
+ // when the namespace diverges from the default store; a single-store
739
+ // deployment keeps the raw sessionKey unchanged.
740
+ const lcmSessionKey =
741
+ lcmSessionKeyForNamespace(writeNamespace, request.sessionKey, this.deps.orchestrator.config.defaultNamespace) ??
742
+ request.sessionKey;
744
743
 
745
- // 4. Objective-state snapshots → the scope plan's objective-state namespace.
746
- // For explicit-namespace and coding-overlay writes this equals
747
- // writeNamespace; for an IMPLICIT write it is the principal SELF base
748
- // (#928 contract, already auth-checked inside the scope plan), not the
749
- // general default-store write namespace.
750
- if (shouldWriteObjectiveState) {
751
- try {
752
- const objectiveStateLocation = await this.deps.objectiveStateStoreLocationForNamespace(
753
- scope.objectiveStateNamespace
754
- );
755
- await recordObjectiveStateSnapshotsFromObservedMessages({
756
- memoryDir: objectiveStateLocation.memoryDir,
757
- objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
758
- objectiveStateMemoryEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
759
- .objectiveStateMemory,
760
- objectiveStateSnapshotWritesEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
761
- .objectiveStateSnapshotWrites,
762
- sessionKey: request.sessionKey,
763
- recordedAt: new Date().toISOString(),
764
- messages: request.messages,
765
- });
766
- } catch (err) {
767
- log.error(`access-observe objective-state snapshot write failed: ${err}`);
744
+ // 4. Objective-state snapshots → the scope plan's objective-state namespace.
745
+ // For explicit-namespace and coding-overlay writes this equals
746
+ // writeNamespace; for an IMPLICIT write it is the principal SELF base
747
+ // (#928 contract, already auth-checked inside the scope plan), not the
748
+ // general default-store write namespace.
749
+ if (shouldWriteObjectiveState) {
750
+ try {
751
+ const objectiveStateLocation = await this.deps.objectiveStateStoreLocationForNamespace(
752
+ scope.objectiveStateNamespace
753
+ );
754
+ await recordObjectiveStateSnapshotsFromObservedMessages({
755
+ memoryDir: objectiveStateLocation.memoryDir,
756
+ objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
757
+ objectiveStateMemoryEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
758
+ .objectiveStateMemory,
759
+ objectiveStateSnapshotWritesEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
760
+ .objectiveStateSnapshotWrites,
761
+ sessionKey: request.sessionKey,
762
+ recordedAt: new Date().toISOString(),
763
+ messages: request.messages,
764
+ });
765
+ } catch (err) {
766
+ log.error(`access-observe objective-state snapshot write failed: ${err}`);
767
+ }
768
768
  }
769
- }
770
769
 
771
- // 5. LCM archival → effective write namespace.
772
- // lcmArchived in the response means "LCM archival was queued" (not
773
- // "completed"), matching extractionQueued semantics. Both run async.
774
- let lcmArchived = false;
775
- if (this.deps.orchestrator.lcmEngine && this.deps.orchestrator.lcmEngine.enabled) {
776
- // Fire-and-forget: LCM archival writes to SQLite and builds summary
777
- // DAGs, which can take tens of seconds for large sessions. Don't
778
- // block the HTTP response — the caller only needs acknowledgment.
779
- try {
780
- this.deps.orchestrator.lcmEngine.enqueueObserveMessages(lcmSessionKey, request.messages);
781
- lcmArchived = true;
782
- } catch (err) {
783
- log.error(`access-observe LCM enqueue failed: ${err}`);
770
+ // 5. LCM archival → effective write namespace.
771
+ // lcmArchived in the response means "LCM archival was queued" (not
772
+ // "completed"), matching extractionQueued semantics. Both run async.
773
+ let lcmArchived = false;
774
+ if (this.deps.orchestrator.lcmEngine && this.deps.orchestrator.lcmEngine.enabled) {
775
+ // Fire-and-forget: LCM archival writes to SQLite and builds summary
776
+ // DAGs, which can take tens of seconds for large sessions. Don't
777
+ // block the HTTP response — the caller only needs acknowledgment.
778
+ try {
779
+ this.deps.orchestrator.lcmEngine.enqueueObserveMessages(lcmSessionKey, request.messages);
780
+ lcmArchived = true;
781
+ } catch (err) {
782
+ log.error(`access-observe LCM enqueue failed: ${err}`);
783
+ }
784
784
  }
785
- }
786
785
 
787
- // 6. Extraction/replayeffective write namespace for STORAGE, ORIGINAL
788
- // sessionKey for IDENTITY (provenance + threading).
789
- let extractionQueued = false;
790
- if (request.skipExtraction !== true) {
791
- const turns = request.messages.map((m) => ({
792
- source: "openclaw" as const,
793
- // Identity-vs-routing separation (#1505 thread 1, cursor): extraction
794
- // derives the provenance principal via `resolvePrincipal(turn.sessionKey)`
795
- // and threads `turn.sessionKey` into conversation threading. Feeding the
796
- // namespace-PREFIXED `lcmSessionKey` here mis-derived the principal to
797
- // `default` (a `<ns>:<key>` string matches no prefix/map rule and fails
798
- // the `agent:` heuristic). Pass the ORIGINAL sessionKey so identity is
799
- // correct; storage routing is pinned separately via
800
- // writeNamespaceOverride below, and the authenticated principal is pinned
801
- // via principalOverride.
802
- sessionKey: request.sessionKey,
803
- role: m.role,
804
- content: m.content,
805
- parts: m.parts,
806
- rawContent: m.rawContent,
807
- sourceFormat: m.sourceFormat,
808
- timestamp: new Date().toISOString(),
809
- ...(request.sourceConnector ? { sourceConnector: request.sourceConnector } : {}),
810
- }));
811
- // Pin extraction STORAGE to the effective namespace rather than letting the
812
- // orchestrator re-derive one from the session key + coding overlay — that
813
- // re-derivation would have to reparse identity and could miss the overlay
814
- // (the #1495 drift). Passing writeNamespaceOverride makes the extraction
815
- // target deterministic and identical to LCM/objective-state (rule 39).
816
- //
817
- // Pin WHENEVER namespaces are enabled, not only when writeNamespace differs
818
- // from the default store (#1505 round 3, codex "Pin default-store extraction
819
- // writes too"). For an unqualified/no-overlay observe by a principal that
820
- // HAS a self namespace, writeNamespace is `config.defaultNamespace` but an
821
- // unpinned `runExtraction` would fall back to
822
- // `defaultNamespaceForPrincipal(principal)` = the SELF namespace — diverging
823
- // from where LCM/objective-state/response wrote (`default`). Pinning the
824
- // resolved writeNamespace forces all side effects onto the one scope-plan
825
- // namespace. When namespaces are DISABLED the router collapses every
826
- // namespace to one store, so leaving the override undefined preserves the
827
- // existing single-store routing byte-for-byte.
828
- const writeNamespaceOverride =
829
- resolveNamespaceCapabilities(this.deps.orchestrator.config).namespaces === true ? writeNamespace : undefined;
830
- // Pin provenance PRINCIPAL to the scope plan's resolved principal (#1505
831
- // thread 1). The scope plan already applied auth precedence
832
- // (authenticatedPrincipal/principalOverride > resolvePrincipal(original
833
- // sessionKey)), so this is the same identity the surface authorized — never
834
- // a `default` fallback parsed from a prefixed key. Omitted when no principal
835
- // resolved (namespaces-disabled / unauthenticated single-store), preserving
836
- // existing behavior.
837
- const principalOverride =
838
- typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : undefined;
839
- // Fire-and-forget: queue extraction in the background so the HTTP
840
- // response returns immediately. LCM archival (above) is also
841
- // enqueue-only; extraction involves LLM calls that can take
842
- // minutes under load and should not block the caller.
843
- //
844
- // Backpressure: the orchestrator's own extraction queue already
845
- // limits concurrency (one extraction at a time per session via
846
- // queueBufferedExtraction). Fire-and-forget here just decouples
847
- // the HTTP response from the queue drain.
848
- if (!observePreparation.isCancelled()) {
786
+ // 5b. Transcript persistence the per-session transcript store the
787
+ // hourly summarizer reads (issue #2783). Best-effort like the LCM
788
+ // enqueue above: a transcript failure must not fail the observe.
789
+ const transcriptPersisted = resolvePresentationCapabilities(this.deps.orchestrator.config).transcript
790
+ ? await this.observeTranscriptPersister.persist(
791
+ this.deps.orchestrator,
792
+ observeTranscriptSessionKey(request.sessionKey, writeNamespace, this.deps.orchestrator.config),
793
+ request.messages,
794
+ request.sessionKey
795
+ )
796
+ : false;
849
797
 
850
- try {
851
- const observeAbortController = new AbortController();
852
- const extractionPromise = this.deps.orchestrator.ingestReplayBatch(turns, {
853
- archiveLcm: false,
854
- writeNamespaceOverride,
855
- principalOverride,
856
- abortSignal: observeAbortController.signal,
857
- ...(typeof request.authenticatedPrincipal === "string" && request.authenticatedPrincipal.trim().length > 0
858
- ? { sessionOwnerPrincipal: request.authenticatedPrincipal.trim() }
859
- : {}),
860
- });
861
- extractionPromise.catch((err) => {
862
- log.error(`access-observe background extraction failed: ${err}`);
863
- });
864
- this.pendingObserveExtractions.track(
865
- this.pendingObserveExtractions.key(request.sessionKey, scope.principal, writeNamespace),
866
- extractionPromise,
867
- observeAbortController,
868
- );
869
- extractionQueued = true;
870
- } catch (err) {
871
- // Synchronous enqueue failure (e.g. orchestrator disposed)
872
- log.error(`access-observe extraction enqueue failed: ${err}`);
873
- }
874
- }
798
+ // 6. Extraction/replay → effective write namespace for STORAGE, ORIGINAL
799
+ // sessionKey for IDENTITY (provenance + threading).
800
+ let extractionQueued = false;
801
+ if (request.skipExtraction !== true) {
802
+ const turns = request.messages.map((m) => ({
803
+ source: "openclaw" as const,
804
+ // Identity-vs-routing separation (#1505 thread 1, cursor): extraction
805
+ // derives the provenance principal via `resolvePrincipal(turn.sessionKey)`
806
+ // and threads `turn.sessionKey` into conversation threading. Feeding the
807
+ // namespace-PREFIXED `lcmSessionKey` here mis-derived the principal to
808
+ // `default` (a `<ns>:<key>` string matches no prefix/map rule and fails
809
+ // the `agent:` heuristic). Pass the ORIGINAL sessionKey so identity is
810
+ // correct; storage routing is pinned separately via
811
+ // writeNamespaceOverride below, and the authenticated principal is pinned
812
+ // via principalOverride.
813
+ sessionKey: request.sessionKey,
814
+ role: m.role,
815
+ content: m.content,
816
+ parts: m.parts,
817
+ rawContent: m.rawContent,
818
+ sourceFormat: m.sourceFormat,
819
+ timestamp: new Date().toISOString(),
820
+ ...(request.sourceConnector ? { sourceConnector: request.sourceConnector } : {}),
821
+ }));
822
+ // Pin extraction STORAGE to the effective namespace rather than letting the
823
+ // orchestrator re-derive one from the session key + coding overlay — that
824
+ // re-derivation would have to reparse identity and could miss the overlay
825
+ // (the #1495 drift). Passing writeNamespaceOverride makes the extraction
826
+ // target deterministic and identical to LCM/objective-state (rule 39).
827
+ //
828
+ // Pin WHENEVER namespaces are enabled, not only when writeNamespace differs
829
+ // from the default store (#1505 round 3, codex "Pin default-store extraction
830
+ // writes too"). For an unqualified/no-overlay observe by a principal that
831
+ // HAS a self namespace, writeNamespace is `config.defaultNamespace` but an
832
+ // unpinned `runExtraction` would fall back to
833
+ // `defaultNamespaceForPrincipal(principal)` = the SELF namespace — diverging
834
+ // from where LCM/objective-state/response wrote (`default`). Pinning the
835
+ // resolved writeNamespace forces all side effects onto the one scope-plan
836
+ // namespace. When namespaces are DISABLED the router collapses every
837
+ // namespace to one store, so leaving the override undefined preserves the
838
+ // existing single-store routing byte-for-byte.
839
+ const writeNamespaceOverride =
840
+ resolveNamespaceCapabilities(this.deps.orchestrator.config).namespaces === true ? writeNamespace : undefined;
841
+ // Pin provenance PRINCIPAL to the scope plan's resolved principal (#1505
842
+ // thread 1). The scope plan already applied auth precedence
843
+ // (authenticatedPrincipal/principalOverride > resolvePrincipal(original
844
+ // sessionKey)), so this is the same identity the surface authorized — never
845
+ // a `default` fallback parsed from a prefixed key. Omitted when no principal
846
+ // resolved (namespaces-disabled / unauthenticated single-store), preserving
847
+ // existing behavior.
848
+ const principalOverride =
849
+ typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : undefined;
850
+ // Fire-and-forget: queue extraction in the background so the HTTP
851
+ // response returns immediately. LCM archival (above) is also
852
+ // enqueue-only; extraction involves LLM calls that can take
853
+ // minutes under load and should not block the caller.
854
+ //
855
+ // Backpressure: the orchestrator's own extraction queue already
856
+ // limits concurrency (one extraction at a time per session via
857
+ // queueBufferedExtraction). Fire-and-forget here just decouples
858
+ // the HTTP response from the queue drain.
859
+ if (!observePreparation.isCancelled()) {
860
+ try {
861
+ const observeAbortController = new AbortController();
862
+ const extractionPromise = this.deps.orchestrator.ingestReplayBatch(turns, {
863
+ archiveLcm: false,
864
+ writeNamespaceOverride,
865
+ principalOverride,
866
+ abortSignal: observeAbortController.signal,
867
+ ...(typeof request.authenticatedPrincipal === "string" && request.authenticatedPrincipal.trim().length > 0
868
+ ? { sessionOwnerPrincipal: request.authenticatedPrincipal.trim() }
869
+ : {}),
870
+ });
871
+ extractionPromise.catch((err) => {
872
+ log.error(`access-observe background extraction failed: ${err}`);
873
+ });
874
+ this.pendingObserveExtractions.track(
875
+ this.pendingObserveExtractions.key(request.sessionKey, scope.principal, writeNamespace),
876
+ extractionPromise,
877
+ observeAbortController
878
+ );
879
+ extractionQueued = true;
880
+ } catch (err) {
881
+ // Synchronous enqueue failure (e.g. orchestrator disposed)
882
+ log.error(`access-observe extraction enqueue failed: ${err}`);
883
+ }
884
+ }
875
885
  }
876
886
 
887
+ log.info(
888
+ `access-observe namespace=${namespace} effectiveNamespace=${writeNamespace} sessionKey=${request.sessionKey} messages=${request.messages.length} lcm=${lcmArchived} extraction=${extractionQueued} transcript=${transcriptPersisted}`
889
+ );
877
890
 
878
- log.info(
879
- `access-observe namespace=${namespace} effectiveNamespace=${writeNamespace} sessionKey=${request.sessionKey} messages=${request.messages.length} lcm=${lcmArchived} extraction=${extractionQueued}`
880
- );
881
-
882
- return {
883
- accepted: request.messages.length,
884
- sessionKey: request.sessionKey,
885
- namespace,
886
- effectiveNamespace: writeNamespace,
887
- scopeDebug: {
888
- principal: scope.principal,
889
- explicitNamespace: scope.explicitNamespace,
890
- baseNamespace: scope.baseNamespace,
891
- writeNamespace: scope.writeNamespace,
892
- codingOverlayApplied: scope.codingOverlayApplied,
893
- readNamespaces: scope.readNamespaces,
894
- scopeProfile: scope.scopeProfile,
895
- writeLayer: scope.writeLayer,
896
- layers: scope.layers,
897
- promotionTargets: scope.promotionTargets,
898
- },
899
- lcmArchived,
900
- extractionQueued,
901
- };
891
+ return {
892
+ accepted: request.messages.length,
893
+ sessionKey: request.sessionKey,
894
+ namespace,
895
+ effectiveNamespace: writeNamespace,
896
+ scopeDebug: {
897
+ principal: scope.principal,
898
+ explicitNamespace: scope.explicitNamespace,
899
+ baseNamespace: scope.baseNamespace,
900
+ writeNamespace: scope.writeNamespace,
901
+ codingOverlayApplied: scope.codingOverlayApplied,
902
+ readNamespaces: scope.readNamespaces,
903
+ scopeProfile: scope.scopeProfile,
904
+ writeLayer: scope.writeLayer,
905
+ layers: scope.layers,
906
+ promotionTargets: scope.promotionTargets,
907
+ },
908
+ lcmArchived,
909
+ extractionQueued,
910
+ transcriptPersisted,
911
+ };
902
912
  } finally {
903
913
  observePreparation.release();
904
- }
914
+ }
905
915
  }
906
916
 
907
917
  async extractionForceFlush(
908
- request: EngramAccessExtractionForceFlushRequest,
918
+ request: EngramAccessExtractionForceFlushRequest
909
919
  ): Promise<EngramAccessExtractionForceFlushResponse> {
910
920
  return extractionForceFlush(
911
921
  this.deps,
@@ -917,8 +927,8 @@ export class AccessObserveWriteSurface {
917
927
  namespace,
918
928
  abortSignal,
919
929
  registerCancellation,
920
- scopeHint,
921
- ),
930
+ scopeHint
931
+ )
922
932
  );
923
933
  }
924
934
  async workTask(request: {