@remnic/core 10.0.69 → 10.0.71

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 (412) hide show
  1. package/dist/access-admin-ops-surface.js +82 -79
  2. package/dist/access-authorization-probe.js +83 -80
  3. package/dist/access-boundary.js +82 -79
  4. package/dist/access-cli.js +196 -193
  5. package/dist/access-cli.js.map +1 -1
  6. package/dist/access-extraction-force-flush.js +82 -79
  7. package/dist/access-http-briefing.js +83 -80
  8. package/dist/access-http-query.js +84 -81
  9. package/dist/access-http.js +106 -103
  10. package/dist/access-identity-continuity-surface.js +82 -79
  11. package/dist/access-lcm-surface.js +82 -79
  12. package/dist/access-mcp.js +95 -92
  13. package/dist/access-namespace-preflight.js +82 -79
  14. package/dist/access-observe-lcm-archive.d.ts +5 -0
  15. package/dist/access-observe-lcm-archive.d.ts.map +1 -0
  16. package/dist/access-observe-lcm-archive.js +9 -0
  17. package/dist/access-observe-objective-state.d.ts +8 -0
  18. package/dist/access-observe-objective-state.d.ts.map +1 -0
  19. package/dist/access-observe-objective-state.js +17 -0
  20. package/dist/access-observe-stage-timing.d.ts +11 -0
  21. package/dist/access-observe-stage-timing.d.ts.map +1 -0
  22. package/dist/access-observe-stage-timing.js +9 -0
  23. package/dist/access-observe-stage-timing.js.map +1 -0
  24. package/dist/access-observe-write-category.js +13 -13
  25. package/dist/access-observe-write-surface.d.ts.map +1 -1
  26. package/dist/access-observe-write-surface.js +82 -79
  27. package/dist/access-offline-manifest.js +8 -8
  28. package/dist/access-operations-batch.js +85 -82
  29. package/dist/access-operations.js +92 -89
  30. package/dist/access-recall-concurrency.js +82 -79
  31. package/dist/access-recall-response.js +82 -79
  32. package/dist/access-recall-surface.js +82 -79
  33. package/dist/access-schema.js +12 -12
  34. package/dist/access-service.d.ts +1 -0
  35. package/dist/access-service.d.ts.map +1 -1
  36. package/dist/access-service.js +82 -79
  37. package/dist/access-surface-catalog.js +84 -81
  38. package/dist/access-surface-catalog.js.map +1 -1
  39. package/dist/active-recall.js +26 -26
  40. package/dist/adapters/index.js +4 -4
  41. package/dist/adapters/registry.js +2 -2
  42. package/dist/briefing.js +17 -17
  43. package/dist/buffer-turn-helpers.d.ts +10 -1
  44. package/dist/buffer-turn-helpers.d.ts.map +1 -1
  45. package/dist/buffer-turn-helpers.js +3 -1
  46. package/dist/buffer.d.ts +4 -0
  47. package/dist/buffer.d.ts.map +1 -1
  48. package/dist/buffer.js +9 -9
  49. package/dist/calibration.js +4 -4
  50. package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
  51. package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
  52. package/dist/causal-behavior.js +2 -2
  53. package/dist/causal-chain.js +2 -2
  54. package/dist/causal-consolidation.js +22 -22
  55. package/dist/causal-retrieval.js +2 -2
  56. package/dist/causal-trajectory-graph.js +3 -3
  57. package/dist/causal-trajectory.js +1 -1
  58. package/dist/{chunk-6WKWL53V.js → chunk-23BA3USG.js} +128 -122
  59. package/dist/chunk-23BA3USG.js.map +1 -0
  60. package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
  61. package/dist/{chunk-CI3MAAIY.js → chunk-2R44BBPK.js} +2 -2
  62. package/dist/{chunk-QDZWQBLU.js → chunk-2R7OCBRR.js} +2 -2
  63. package/dist/{chunk-B3MWELZ3.js → chunk-2WPWEVAH.js} +2 -2
  64. package/dist/{chunk-PLCYKAWH.js → chunk-3ICAWZUU.js} +4 -4
  65. package/dist/{chunk-R4ZHF4K2.js → chunk-43FLJLT2.js} +4 -4
  66. package/dist/{chunk-PMDOGXA2.js → chunk-4PMFSYH7.js} +2 -2
  67. package/dist/{chunk-HXFIILGF.js → chunk-4RASUAN3.js} +4 -4
  68. package/dist/{chunk-EI6M5NVK.js → chunk-5JBVPJCT.js} +2 -2
  69. package/dist/{chunk-4NV7O76Q.js → chunk-5ORJHH43.js} +2 -2
  70. package/dist/{chunk-74AY3S7U.js → chunk-5RW247F5.js} +10 -10
  71. package/dist/{chunk-4XINO77L.js → chunk-66JOLMWS.js} +2 -2
  72. package/dist/{chunk-AYJQ644F.js → chunk-6KBCUIZP.js} +2 -2
  73. package/dist/{chunk-GKL6QYZO.js → chunk-6L63IN3M.js} +1 -1
  74. package/dist/{chunk-OPFVXM2D.js → chunk-7P5VBRBS.js} +2 -2
  75. package/dist/{chunk-4SOWMA55.js → chunk-7WFY2L5J.js} +3 -3
  76. package/dist/{chunk-GJ4HU6LK.js → chunk-AGRMXXVA.js} +2 -2
  77. package/dist/{chunk-KOLJJN5G.js → chunk-AQNHEDXP.js} +11 -4
  78. package/dist/chunk-AQNHEDXP.js.map +1 -0
  79. package/dist/{chunk-IVUVQPTQ.js → chunk-AZNE2H6D.js} +2 -2
  80. package/dist/{chunk-HPB5TF55.js → chunk-BCBY5GYZ.js} +3 -3
  81. package/dist/{chunk-M4IEZGCK.js → chunk-BFBS7OFQ.js} +7 -7
  82. package/dist/{chunk-4PG5R6BJ.js → chunk-BNU5TQLR.js} +2 -2
  83. package/dist/{chunk-TVE7W67N.js → chunk-BTU77RB5.js} +2 -2
  84. package/dist/{chunk-H6VJSITJ.js → chunk-CIL4GHMD.js} +3 -3
  85. package/dist/{chunk-KZZ5EZ7O.js → chunk-DC3DWF2M.js} +2 -2
  86. package/dist/{chunk-R2BIVU2Z.js → chunk-DE4U5PTV.js} +50 -46
  87. package/dist/chunk-DE4U5PTV.js.map +1 -0
  88. package/dist/{chunk-DDBB55L2.js → chunk-DSSTOV5M.js} +534 -361
  89. package/dist/chunk-DSSTOV5M.js.map +1 -0
  90. package/dist/{chunk-4MPAKYZU.js → chunk-EGKDONTC.js} +12 -6
  91. package/dist/chunk-EGKDONTC.js.map +1 -0
  92. package/dist/{chunk-AUFPPBC3.js → chunk-ENPJX3BB.js} +3 -3
  93. package/dist/{chunk-CTH2CQCB.js → chunk-EQ6EMJRG.js} +2 -2
  94. package/dist/{chunk-63A2BU2B.js → chunk-F4ZHKDBW.js} +5 -5
  95. package/dist/{chunk-3LBDEGQA.js → chunk-FDUCIUQ5.js} +2 -2
  96. package/dist/{chunk-OCK4D5PC.js → chunk-FGGLVCHI.js} +2 -2
  97. package/dist/{chunk-XVZA6VXC.js → chunk-FZVROZKC.js} +4 -4
  98. package/dist/{chunk-3RHU5MD7.js → chunk-GXAZ4Q2S.js} +2 -2
  99. package/dist/{chunk-UVVFPCPX.js → chunk-H2X32F2K.js} +2 -2
  100. package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
  101. package/dist/{chunk-W7K5BP3M.js → chunk-HQPFACXO.js} +2 -2
  102. package/dist/{chunk-TECK5IVY.js → chunk-HZNURRDS.js} +2 -2
  103. package/dist/{chunk-U2CAGMUD.js → chunk-ICBUTKLL.js} +2 -2
  104. package/dist/{chunk-B4DXREWC.js → chunk-IQXQ3KWR.js} +2 -2
  105. package/dist/{chunk-AL3TCNSJ.js → chunk-J6GZ2254.js} +4 -4
  106. package/dist/{chunk-5MGKGEL7.js → chunk-J72ZY7NU.js} +2 -2
  107. package/dist/{chunk-OH55F76C.js → chunk-JEX2JL3U.js} +2 -2
  108. package/dist/{chunk-Y3XPSGNF.js → chunk-JGLZ46JS.js} +2 -2
  109. package/dist/{chunk-EXQJMFRF.js → chunk-JY4LXMZR.js} +2 -2
  110. package/dist/{chunk-6P7U3HWG.js → chunk-K36RMINQ.js} +3 -3
  111. package/dist/{chunk-BUKK5SWA.js → chunk-KQAFEZQX.js} +2 -2
  112. package/dist/{chunk-LN4X2NDA.js → chunk-KY3KJUNN.js} +10 -10
  113. package/dist/chunk-L3E7MLMK.js +20 -0
  114. package/dist/chunk-L3E7MLMK.js.map +1 -0
  115. package/dist/{chunk-H5DIRCZP.js → chunk-LHMCZ6VW.js} +18 -18
  116. package/dist/{chunk-GGD2YDS6.js → chunk-LN7CWLAU.js} +2 -2
  117. package/dist/{chunk-GHHQLSSY.js → chunk-LYOCAUI6.js} +3 -3
  118. package/dist/{chunk-VA3GNAWQ.js → chunk-LZIOY7ZU.js} +4 -5
  119. package/dist/chunk-LZIOY7ZU.js.map +1 -0
  120. package/dist/{chunk-W26D2USW.js → chunk-MUH7RR6T.js} +6 -6
  121. package/dist/{chunk-IAGVM7EY.js → chunk-N2Y6COEM.js} +2 -2
  122. package/dist/{chunk-64JLBFCQ.js → chunk-N7NAGECH.js} +2 -2
  123. package/dist/{chunk-5Y6VA6X2.js → chunk-OGQGDOYK.js} +2 -2
  124. package/dist/{chunk-U7MIMS2Y.js → chunk-OUBEJWVI.js} +17 -1
  125. package/dist/chunk-OUBEJWVI.js.map +1 -0
  126. package/dist/{chunk-JLMOH5JA.js → chunk-OWZXDBV4.js} +2 -2
  127. package/dist/{chunk-ZORS5BG5.js → chunk-PJAMFIDE.js} +10 -10
  128. package/dist/chunk-QCFZDYYG.js +34 -0
  129. package/dist/chunk-QCFZDYYG.js.map +1 -0
  130. package/dist/{chunk-SXTVZ6JL.js → chunk-QIOQI7QZ.js} +2 -2
  131. package/dist/{chunk-MMCO4SRG.js → chunk-QNN4FYBD.js} +19 -11
  132. package/dist/chunk-QNN4FYBD.js.map +1 -0
  133. package/dist/{chunk-75DCOS6I.js → chunk-QUPTDKSX.js} +67 -67
  134. package/dist/{chunk-HH73M65H.js → chunk-QVZZE6VH.js} +3 -3
  135. package/dist/{chunk-XWE3EOWX.js → chunk-RZED7FAU.js} +2 -2
  136. package/dist/{chunk-IZBIDPMY.js → chunk-S37O4S6E.js} +2 -2
  137. package/dist/{chunk-NHWDTOBN.js → chunk-S73ZVU37.js} +21 -21
  138. package/dist/{chunk-YSATDEBY.js → chunk-SBRUTD5O.js} +5 -5
  139. package/dist/{chunk-WVP2I6C5.js → chunk-SDL22RRW.js} +50 -11
  140. package/dist/chunk-SDL22RRW.js.map +1 -0
  141. package/dist/{chunk-PRKNAIGZ.js → chunk-T6T2RMWW.js} +5 -5
  142. package/dist/{chunk-CIEEYVUB.js → chunk-TPX7XXY4.js} +2 -2
  143. package/dist/{chunk-L334PSLW.js → chunk-U2A56LLF.js} +8 -8
  144. package/dist/{chunk-P4TV3TQ2.js → chunk-U6IL4724.js} +5 -5
  145. package/dist/{chunk-5UM4H64E.js → chunk-UAOJVQXC.js} +2 -2
  146. package/dist/{chunk-MOIJWWNA.js → chunk-UE5JYPU6.js} +13 -13
  147. package/dist/{chunk-TGQW3AMK.js → chunk-UIFWZMO7.js} +23 -23
  148. package/dist/{chunk-UW6LBFYN.js → chunk-USX5YIKB.js} +6 -6
  149. package/dist/{chunk-QGFR73SN.js → chunk-VK5HKVQ7.js} +2 -2
  150. package/dist/{chunk-ZOBYTRBU.js → chunk-VNTQU6KB.js} +47 -2
  151. package/dist/chunk-VNTQU6KB.js.map +1 -0
  152. package/dist/{chunk-IHCXMYSE.js → chunk-VPEIWMUT.js} +2 -2
  153. package/dist/{chunk-O5ZINWW3.js → chunk-VSJ3ARFS.js} +2 -2
  154. package/dist/{chunk-RLVI2M5Q.js → chunk-W4V7P5HP.js} +2 -2
  155. package/dist/{chunk-ELHJK7LM.js → chunk-WBN66HPI.js} +6 -6
  156. package/dist/{chunk-BJLCV2P3.js → chunk-WGRAB3KB.js} +2 -2
  157. package/dist/{chunk-5KDDAQ6K.js → chunk-WN2DASTS.js} +10 -10
  158. package/dist/{chunk-IG3EZ3TF.js → chunk-WNQ3B3Q5.js} +2 -2
  159. package/dist/{chunk-V6SBA5O7.js → chunk-WYOHQJKC.js} +7 -7
  160. package/dist/chunk-WZU5AGO6.js +38 -0
  161. package/dist/chunk-WZU5AGO6.js.map +1 -0
  162. package/dist/{chunk-WHROVQ5Q.js → chunk-X4DHAXFO.js} +3 -3
  163. package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
  164. package/dist/{chunk-JLGBJ4AX.js → chunk-XPZM7GP6.js} +10 -10
  165. package/dist/{chunk-64S6X4IU.js → chunk-XTN54NML.js} +4 -4
  166. package/dist/{chunk-UYUFDTIX.js → chunk-YIXWY4OZ.js} +2 -2
  167. package/dist/{chunk-NCZGGGWI.js → chunk-YPYSC3TX.js} +12 -12
  168. package/dist/{chunk-AVGDYYMA.js → chunk-ZBET3W26.js} +3 -3
  169. package/dist/{chunk-Y7427SL7.js → chunk-ZG4GNPRE.js} +216 -50
  170. package/dist/chunk-ZG4GNPRE.js.map +1 -0
  171. package/dist/chunk-ZODKV27J.js +443 -0
  172. package/dist/chunk-ZODKV27J.js.map +1 -0
  173. package/dist/cli.js +133 -130
  174. package/dist/coding/export-okf-codegraph.js +16 -16
  175. package/dist/coding/pre-action-gate.js +2 -2
  176. package/dist/compounding/engine.js +18 -18
  177. package/dist/config.js +26 -26
  178. package/dist/connectors/codex-materialize-runner.js +19 -19
  179. package/dist/connectors/codex-materialize.js +2 -2
  180. package/dist/connectors/index.js +20 -20
  181. package/dist/consolidation-provenance-check.js +2 -2
  182. package/dist/convergence-refresh.js +20 -20
  183. package/dist/corpus-watermark.js +20 -20
  184. package/dist/deep-recall-http-glue.js +13 -13
  185. package/dist/deep-recall.js +2 -2
  186. package/dist/embedding-fallback.js +2 -2
  187. package/dist/entity-retrieval.js +20 -20
  188. package/dist/event-order-recall.js +2 -2
  189. package/dist/external-wiki-access.js +83 -80
  190. package/dist/extraction-span-materialize.js +2 -2
  191. package/dist/extraction-window-drain.d.ts.map +1 -1
  192. package/dist/extraction-window-drain.js +1 -1
  193. package/dist/extraction.js +32 -32
  194. package/dist/{graph-edge-decay-OEX5OGMI.js → graph-edge-decay-CXTNJ7IQ.js} +6 -6
  195. package/dist/graph-edge-decay-CXTNJ7IQ.js.map +1 -0
  196. package/dist/graph-jsonl.js +4 -4
  197. package/dist/graph-snapshot.js +4 -4
  198. package/dist/graph.js +3 -3
  199. package/dist/harmonic-retrieval.js +17 -17
  200. package/dist/index.js +281 -278
  201. package/dist/lcm/archive.d.ts +12 -2
  202. package/dist/lcm/archive.d.ts.map +1 -1
  203. package/dist/lcm/archive.js +2 -2
  204. package/dist/lcm/engine.d.ts +59 -8
  205. package/dist/lcm/engine.d.ts.map +1 -1
  206. package/dist/lcm/engine.js +6 -6
  207. package/dist/lcm/index.js +16 -16
  208. package/dist/lcm/queue.d.ts +7 -3
  209. package/dist/lcm/queue.d.ts.map +1 -1
  210. package/dist/lcm/queue.js +1 -1
  211. package/dist/lcm/summarizer.d.ts +8 -1
  212. package/dist/lcm/summarizer.d.ts.map +1 -1
  213. package/dist/lcm/summarizer.js +3 -3
  214. package/dist/local-llm.js +4 -4
  215. package/dist/location/index.js +19 -19
  216. package/dist/maintenance/memory-governance.js +18 -18
  217. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +17 -17
  218. package/dist/maintenance/rebuild-memory-projection-runner.js +20 -20
  219. package/dist/maintenance/rebuild-memory-projection.js +19 -19
  220. package/dist/memory-browse-operations.js +83 -80
  221. package/dist/memory-browse.js +6 -6
  222. package/dist/namespaces/migrate.js +18 -18
  223. package/dist/namespaces/search.js +7 -7
  224. package/dist/namespaces/storage.js +17 -17
  225. package/dist/offline-sync-changeset-generations.js +5 -5
  226. package/dist/offline-sync-embedding-generation.js +4 -4
  227. package/dist/offline-sync-snapshot-stream.js +7 -7
  228. package/dist/offline-sync.js +9 -9
  229. package/dist/operator-doctor-corpus.js +21 -21
  230. package/dist/operator-toolkit.js +41 -41
  231. package/dist/orchestration/backlog-scheduler.d.ts +151 -0
  232. package/dist/orchestration/backlog-scheduler.d.ts.map +1 -0
  233. package/dist/orchestration/backlog-scheduler.js +891 -0
  234. package/dist/orchestration/backlog-scheduler.js.map +1 -0
  235. package/dist/orchestration/buffer-drain-runner.d.ts +31 -27
  236. package/dist/orchestration/buffer-drain-runner.d.ts.map +1 -1
  237. package/dist/orchestration/buffer-drain-runner.js +202 -404
  238. package/dist/orchestration/buffer-drain-runner.js.map +1 -1
  239. package/dist/orchestration/extraction-drain.d.ts +50 -17
  240. package/dist/orchestration/extraction-drain.d.ts.map +1 -1
  241. package/dist/orchestration/extraction-queue-coordinator.d.ts +19 -1
  242. package/dist/orchestration/extraction-queue-coordinator.d.ts.map +1 -1
  243. package/dist/orchestration/extraction-run.d.ts +8 -0
  244. package/dist/orchestration/extraction-run.d.ts.map +1 -1
  245. package/dist/orchestration/extraction-task-queueing.d.ts +44 -0
  246. package/dist/orchestration/extraction-task-queueing.d.ts.map +1 -0
  247. package/dist/orchestration/maintenance.js +33 -33
  248. package/dist/orchestration/turn-ingestion.d.ts +11 -5
  249. package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
  250. package/dist/orchestrator.d.ts +13 -0
  251. package/dist/orchestrator.d.ts.map +1 -1
  252. package/dist/orchestrator.js +196 -193
  253. package/dist/qmd.js +4 -4
  254. package/dist/recall-navigation-operations.js +83 -80
  255. package/dist/recall-navigation.js +82 -79
  256. package/dist/recall-state-view-admission.js +6 -6
  257. package/dist/recall-why-service.js +6 -6
  258. package/dist/resume-bundles.js +29 -29
  259. package/dist/search/factory.js +6 -6
  260. package/dist/search/index.js +12 -12
  261. package/dist/semantic-consolidation.js +25 -25
  262. package/dist/semantic-rule-promotion.js +17 -17
  263. package/dist/semantic-rule-verifier.js +17 -17
  264. package/dist/source-agent-qualifier.js +24 -24
  265. package/dist/standup/build.js +17 -17
  266. package/dist/storage/buffer-drain-claims.d.ts +15 -0
  267. package/dist/storage/buffer-drain-claims.d.ts.map +1 -1
  268. package/dist/storage/buffer-drain-claims.js +2 -2
  269. package/dist/storage/buffer-session-files.js +2 -2
  270. package/dist/storage.js +16 -16
  271. package/dist/summarizer.js +6 -6
  272. package/dist/support-passport/index.js +85 -82
  273. package/dist/transfer/backup.js +2 -2
  274. package/dist/transfer/capsule-export.js +2 -2
  275. package/dist/transfer/capsule-import.js +2 -2
  276. package/dist/transfer/export-okf.js +17 -17
  277. package/dist/verified-recall.js +17 -17
  278. package/dist/who-knows-cli.js +18 -18
  279. package/dist/who-knows.js +17 -17
  280. package/package.json +12 -2
  281. package/src/access-observe-lcm-archive.ts +30 -0
  282. package/src/access-observe-lcm-fail-closed.test.ts +118 -0
  283. package/src/access-observe-objective-state.ts +40 -0
  284. package/src/access-observe-stage-timing.test.ts +246 -0
  285. package/src/access-observe-stage-timing.ts +58 -0
  286. package/src/access-observe-write-surface.ts +45 -45
  287. package/src/access-service.ts +1 -0
  288. package/src/backlog-scheduler.test.ts +806 -0
  289. package/src/buffer-drain-handover.test.ts +363 -18
  290. package/src/buffer-drain-inprocess.test.ts +355 -0
  291. package/src/buffer-drain-model-boundary.test.ts +1062 -0
  292. package/src/buffer-drop-extraction-chunk.test.ts +237 -22
  293. package/src/buffer-turn-helpers.ts +26 -1
  294. package/src/buffer.ts +8 -0
  295. package/src/extraction-window-drain.ts +7 -7
  296. package/src/lcm/archive.ts +59 -7
  297. package/src/lcm/engine.ts +256 -53
  298. package/src/lcm/queue.test.ts +32 -14
  299. package/src/lcm/queue.ts +24 -16
  300. package/src/lcm/summarizer.ts +15 -2
  301. package/src/lcm-durability.test.ts +856 -0
  302. package/src/lcm-engine.test.ts +12 -3
  303. package/src/orchestration/backlog-scheduler.ts +481 -0
  304. package/src/orchestration/buffer-drain-runner.ts +545 -180
  305. package/src/orchestration/extraction-drain.ts +287 -108
  306. package/src/orchestration/extraction-queue-coordinator.ts +51 -3
  307. package/src/orchestration/extraction-run.test.ts +41 -0
  308. package/src/orchestration/extraction-run.ts +24 -5
  309. package/src/orchestration/extraction-task-queueing.ts +87 -0
  310. package/src/orchestration/turn-ingestion.ts +46 -59
  311. package/src/orchestrator-extraction-queue.test.ts +46 -2
  312. package/src/orchestrator-flush.test.ts +4 -1
  313. package/src/orchestrator.ts +47 -21
  314. package/src/storage/buffer-drain-claims.ts +55 -0
  315. package/dist/chunk-4MPAKYZU.js.map +0 -1
  316. package/dist/chunk-6WKWL53V.js.map +0 -1
  317. package/dist/chunk-DDBB55L2.js.map +0 -1
  318. package/dist/chunk-KOLJJN5G.js.map +0 -1
  319. package/dist/chunk-MMCO4SRG.js.map +0 -1
  320. package/dist/chunk-R2BIVU2Z.js.map +0 -1
  321. package/dist/chunk-U7MIMS2Y.js.map +0 -1
  322. package/dist/chunk-VA3GNAWQ.js.map +0 -1
  323. package/dist/chunk-WVP2I6C5.js.map +0 -1
  324. package/dist/chunk-Y7427SL7.js.map +0 -1
  325. package/dist/chunk-ZOBYTRBU.js.map +0 -1
  326. /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-observe-lcm-archive.js.map} +0 -0
  327. /package/dist/{graph-edge-decay-OEX5OGMI.js.map → access-observe-objective-state.js.map} +0 -0
  328. /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
  329. /package/dist/{chunk-CI3MAAIY.js.map → chunk-2R44BBPK.js.map} +0 -0
  330. /package/dist/{chunk-QDZWQBLU.js.map → chunk-2R7OCBRR.js.map} +0 -0
  331. /package/dist/{chunk-B3MWELZ3.js.map → chunk-2WPWEVAH.js.map} +0 -0
  332. /package/dist/{chunk-PLCYKAWH.js.map → chunk-3ICAWZUU.js.map} +0 -0
  333. /package/dist/{chunk-R4ZHF4K2.js.map → chunk-43FLJLT2.js.map} +0 -0
  334. /package/dist/{chunk-PMDOGXA2.js.map → chunk-4PMFSYH7.js.map} +0 -0
  335. /package/dist/{chunk-HXFIILGF.js.map → chunk-4RASUAN3.js.map} +0 -0
  336. /package/dist/{chunk-EI6M5NVK.js.map → chunk-5JBVPJCT.js.map} +0 -0
  337. /package/dist/{chunk-4NV7O76Q.js.map → chunk-5ORJHH43.js.map} +0 -0
  338. /package/dist/{chunk-74AY3S7U.js.map → chunk-5RW247F5.js.map} +0 -0
  339. /package/dist/{chunk-4XINO77L.js.map → chunk-66JOLMWS.js.map} +0 -0
  340. /package/dist/{chunk-AYJQ644F.js.map → chunk-6KBCUIZP.js.map} +0 -0
  341. /package/dist/{chunk-GKL6QYZO.js.map → chunk-6L63IN3M.js.map} +0 -0
  342. /package/dist/{chunk-OPFVXM2D.js.map → chunk-7P5VBRBS.js.map} +0 -0
  343. /package/dist/{chunk-4SOWMA55.js.map → chunk-7WFY2L5J.js.map} +0 -0
  344. /package/dist/{chunk-GJ4HU6LK.js.map → chunk-AGRMXXVA.js.map} +0 -0
  345. /package/dist/{chunk-IVUVQPTQ.js.map → chunk-AZNE2H6D.js.map} +0 -0
  346. /package/dist/{chunk-HPB5TF55.js.map → chunk-BCBY5GYZ.js.map} +0 -0
  347. /package/dist/{chunk-M4IEZGCK.js.map → chunk-BFBS7OFQ.js.map} +0 -0
  348. /package/dist/{chunk-4PG5R6BJ.js.map → chunk-BNU5TQLR.js.map} +0 -0
  349. /package/dist/{chunk-TVE7W67N.js.map → chunk-BTU77RB5.js.map} +0 -0
  350. /package/dist/{chunk-H6VJSITJ.js.map → chunk-CIL4GHMD.js.map} +0 -0
  351. /package/dist/{chunk-KZZ5EZ7O.js.map → chunk-DC3DWF2M.js.map} +0 -0
  352. /package/dist/{chunk-AUFPPBC3.js.map → chunk-ENPJX3BB.js.map} +0 -0
  353. /package/dist/{chunk-CTH2CQCB.js.map → chunk-EQ6EMJRG.js.map} +0 -0
  354. /package/dist/{chunk-63A2BU2B.js.map → chunk-F4ZHKDBW.js.map} +0 -0
  355. /package/dist/{chunk-3LBDEGQA.js.map → chunk-FDUCIUQ5.js.map} +0 -0
  356. /package/dist/{chunk-OCK4D5PC.js.map → chunk-FGGLVCHI.js.map} +0 -0
  357. /package/dist/{chunk-XVZA6VXC.js.map → chunk-FZVROZKC.js.map} +0 -0
  358. /package/dist/{chunk-3RHU5MD7.js.map → chunk-GXAZ4Q2S.js.map} +0 -0
  359. /package/dist/{chunk-UVVFPCPX.js.map → chunk-H2X32F2K.js.map} +0 -0
  360. /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
  361. /package/dist/{chunk-W7K5BP3M.js.map → chunk-HQPFACXO.js.map} +0 -0
  362. /package/dist/{chunk-TECK5IVY.js.map → chunk-HZNURRDS.js.map} +0 -0
  363. /package/dist/{chunk-U2CAGMUD.js.map → chunk-ICBUTKLL.js.map} +0 -0
  364. /package/dist/{chunk-B4DXREWC.js.map → chunk-IQXQ3KWR.js.map} +0 -0
  365. /package/dist/{chunk-AL3TCNSJ.js.map → chunk-J6GZ2254.js.map} +0 -0
  366. /package/dist/{chunk-5MGKGEL7.js.map → chunk-J72ZY7NU.js.map} +0 -0
  367. /package/dist/{chunk-OH55F76C.js.map → chunk-JEX2JL3U.js.map} +0 -0
  368. /package/dist/{chunk-Y3XPSGNF.js.map → chunk-JGLZ46JS.js.map} +0 -0
  369. /package/dist/{chunk-EXQJMFRF.js.map → chunk-JY4LXMZR.js.map} +0 -0
  370. /package/dist/{chunk-6P7U3HWG.js.map → chunk-K36RMINQ.js.map} +0 -0
  371. /package/dist/{chunk-BUKK5SWA.js.map → chunk-KQAFEZQX.js.map} +0 -0
  372. /package/dist/{chunk-LN4X2NDA.js.map → chunk-KY3KJUNN.js.map} +0 -0
  373. /package/dist/{chunk-H5DIRCZP.js.map → chunk-LHMCZ6VW.js.map} +0 -0
  374. /package/dist/{chunk-GGD2YDS6.js.map → chunk-LN7CWLAU.js.map} +0 -0
  375. /package/dist/{chunk-GHHQLSSY.js.map → chunk-LYOCAUI6.js.map} +0 -0
  376. /package/dist/{chunk-W26D2USW.js.map → chunk-MUH7RR6T.js.map} +0 -0
  377. /package/dist/{chunk-IAGVM7EY.js.map → chunk-N2Y6COEM.js.map} +0 -0
  378. /package/dist/{chunk-64JLBFCQ.js.map → chunk-N7NAGECH.js.map} +0 -0
  379. /package/dist/{chunk-5Y6VA6X2.js.map → chunk-OGQGDOYK.js.map} +0 -0
  380. /package/dist/{chunk-JLMOH5JA.js.map → chunk-OWZXDBV4.js.map} +0 -0
  381. /package/dist/{chunk-ZORS5BG5.js.map → chunk-PJAMFIDE.js.map} +0 -0
  382. /package/dist/{chunk-SXTVZ6JL.js.map → chunk-QIOQI7QZ.js.map} +0 -0
  383. /package/dist/{chunk-75DCOS6I.js.map → chunk-QUPTDKSX.js.map} +0 -0
  384. /package/dist/{chunk-HH73M65H.js.map → chunk-QVZZE6VH.js.map} +0 -0
  385. /package/dist/{chunk-XWE3EOWX.js.map → chunk-RZED7FAU.js.map} +0 -0
  386. /package/dist/{chunk-IZBIDPMY.js.map → chunk-S37O4S6E.js.map} +0 -0
  387. /package/dist/{chunk-NHWDTOBN.js.map → chunk-S73ZVU37.js.map} +0 -0
  388. /package/dist/{chunk-YSATDEBY.js.map → chunk-SBRUTD5O.js.map} +0 -0
  389. /package/dist/{chunk-PRKNAIGZ.js.map → chunk-T6T2RMWW.js.map} +0 -0
  390. /package/dist/{chunk-CIEEYVUB.js.map → chunk-TPX7XXY4.js.map} +0 -0
  391. /package/dist/{chunk-L334PSLW.js.map → chunk-U2A56LLF.js.map} +0 -0
  392. /package/dist/{chunk-P4TV3TQ2.js.map → chunk-U6IL4724.js.map} +0 -0
  393. /package/dist/{chunk-5UM4H64E.js.map → chunk-UAOJVQXC.js.map} +0 -0
  394. /package/dist/{chunk-MOIJWWNA.js.map → chunk-UE5JYPU6.js.map} +0 -0
  395. /package/dist/{chunk-TGQW3AMK.js.map → chunk-UIFWZMO7.js.map} +0 -0
  396. /package/dist/{chunk-UW6LBFYN.js.map → chunk-USX5YIKB.js.map} +0 -0
  397. /package/dist/{chunk-QGFR73SN.js.map → chunk-VK5HKVQ7.js.map} +0 -0
  398. /package/dist/{chunk-IHCXMYSE.js.map → chunk-VPEIWMUT.js.map} +0 -0
  399. /package/dist/{chunk-O5ZINWW3.js.map → chunk-VSJ3ARFS.js.map} +0 -0
  400. /package/dist/{chunk-RLVI2M5Q.js.map → chunk-W4V7P5HP.js.map} +0 -0
  401. /package/dist/{chunk-ELHJK7LM.js.map → chunk-WBN66HPI.js.map} +0 -0
  402. /package/dist/{chunk-BJLCV2P3.js.map → chunk-WGRAB3KB.js.map} +0 -0
  403. /package/dist/{chunk-5KDDAQ6K.js.map → chunk-WN2DASTS.js.map} +0 -0
  404. /package/dist/{chunk-IG3EZ3TF.js.map → chunk-WNQ3B3Q5.js.map} +0 -0
  405. /package/dist/{chunk-V6SBA5O7.js.map → chunk-WYOHQJKC.js.map} +0 -0
  406. /package/dist/{chunk-WHROVQ5Q.js.map → chunk-X4DHAXFO.js.map} +0 -0
  407. /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
  408. /package/dist/{chunk-JLGBJ4AX.js.map → chunk-XPZM7GP6.js.map} +0 -0
  409. /package/dist/{chunk-64S6X4IU.js.map → chunk-XTN54NML.js.map} +0 -0
  410. /package/dist/{chunk-UYUFDTIX.js.map → chunk-YIXWY4OZ.js.map} +0 -0
  411. /package/dist/{chunk-NCZGGGWI.js.map → chunk-YPYSC3TX.js.map} +0 -0
  412. /package/dist/{chunk-AVGDYYMA.js.map → chunk-ZBET3W26.js.map} +0 -0
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Noncontent stage timing for slow/failed observe requests (25s incident).
3
+ * A failed request must record which stage blocked it (phase attribution) in
4
+ * the `access-observe-failed` log line without leaking message content,
5
+ * session keys, namespaces or principals, and must still throw unchanged.
6
+ */
7
+ import assert from "node:assert/strict";
8
+ import { mkdtemp, rm } from "node:fs/promises";
9
+ import { tmpdir } from "node:os";
10
+ import path from "node:path";
11
+ import test from "node:test";
12
+
13
+ import { EngramAccessService, NamespaceNotWritableError } from "./access-service.js";
14
+ import { initLogger, resetLogger, type LoggerBackend } from "./logger.js";
15
+ import { Orchestrator } from "./orchestrator.js";
16
+ import { parseConfig } from "./config.js";
17
+ import type { EngramAccessObserveRequest } from "./access-service.js";
18
+ import type { CodingContext, PluginConfig } from "./types.js";
19
+
20
+ interface OrchestratorInternals {
21
+ config: PluginConfig;
22
+ _codingContextBySession: Map<string, CodingContext>;
23
+ }
24
+
25
+ function makeService(memoryDir: string): EngramAccessService {
26
+ // SAFETY: the probe drives only the observe scope path on this orchestrator.
27
+ const orch = Object.create(Orchestrator.prototype) as Orchestrator;
28
+ // SAFETY: the probe sets exactly these two internal fields.
29
+ const internals: OrchestratorInternals = {
30
+ config: parseConfig({
31
+ namespacesEnabled: true,
32
+ defaultNamespace: "default",
33
+ sharedNamespace: "shared",
34
+ namespacePolicies: [],
35
+ codingMode: { projectScope: true },
36
+ transcriptEnabled: false,
37
+ memoryDir,
38
+ }),
39
+ _codingContextBySession: new Map(),
40
+ };
41
+ Object.assign(orch, internals);
42
+ return new EngramAccessService(orch);
43
+ }
44
+
45
+ test("a rejected observe logs phase attribution with stage durations and still throws", async () => {
46
+ const dir = await mkdtemp(path.join(tmpdir(), "remnic-observe-timing-"));
47
+ const lines: string[] = [];
48
+ const backend: LoggerBackend = {
49
+ info(msg) {
50
+ lines.push(msg);
51
+ },
52
+ warn(msg) {
53
+ lines.push(msg);
54
+ },
55
+ error(msg) {
56
+ lines.push(msg);
57
+ },
58
+ };
59
+ initLogger(backend, false, { timestamps: false });
60
+ try {
61
+ const service = makeService(dir);
62
+ // SAFETY: the literal sets the request fields the scope path reads.
63
+ const rejectedRequest = {
64
+ sessionKey: "sess-timing-1",
65
+ authenticatedPrincipal: "alice",
66
+ namespace: "victim-secret",
67
+ messages: [
68
+ { role: "user", content: "first secret message body" },
69
+ { role: "assistant", content: "second secret message body" },
70
+ ],
71
+ } as EngramAccessObserveRequest;
72
+ await assert.rejects(
73
+ service.observe(rejectedRequest),
74
+ NamespaceNotWritableError
75
+ );
76
+
77
+ const failed = lines.filter((l) => l.includes("access-observe-failed"));
78
+ assert.equal(failed.length, 1, `expected exactly one access-observe-failed line, got: ${failed}`);
79
+ const line = failed[0] ?? "";
80
+ // Phase attribution: the blocked stage (scope) plus total and message count.
81
+ assert.match(line, /totalMs=\d+/);
82
+ assert.match(line, /messages=2/);
83
+ assert.match(line, /scopeMs=\d+/);
84
+ // Noncontent: no message bodies, session key, namespace or principal.
85
+ assert.ok(!line.includes("secret"), `leaked content in: ${line}`);
86
+ assert.ok(!line.includes("sess-timing-1"), `leaked session key in: ${line}`);
87
+ assert.ok(!line.includes("victim-secret"), `leaked namespace in: ${line}`);
88
+ assert.ok(!line.includes("alice"), `leaked principal in: ${line}`);
89
+ } finally {
90
+ resetLogger();
91
+ await rm(dir, { recursive: true, force: true });
92
+ }
93
+ });
94
+
95
+ // Plain-object orchestrator for full observe success/failure paths (mirrors
96
+ // the access-service-observe-lcm-parity harness).
97
+ function makeProbe(options: {
98
+ enqueueObserveMessages: (sessionKey: string, messages: unknown[]) => Promise<void> | void;
99
+ }) {
100
+ const config = parseConfig({
101
+ namespacesEnabled: true,
102
+ defaultNamespace: "default",
103
+ sharedNamespace: "shared",
104
+ namespacePolicies: [],
105
+ defaultRecallNamespaces: ["self", "shared"],
106
+ codingMode: { projectScope: true },
107
+ transcriptEnabled: false,
108
+ memoryDir: "/synthetic/remnic-observe-timing",
109
+ objectiveStateMemoryEnabled: false,
110
+ objectiveStateSnapshotWritesEnabled: false,
111
+ principalFromSessionKeyMode: "prefix",
112
+ principalFromSessionKeyRules: [],
113
+ recallCrossNamespaceBudgetEnabled: false,
114
+ recallCrossNamespaceBudgetWindowMs: 60_000,
115
+ recallCrossNamespaceBudgetSoftLimit: 10,
116
+ recallCrossNamespaceBudgetHardLimit: 30,
117
+ });
118
+ const contexts = new Map<string, CodingContext>();
119
+ const extractionCalls: string[][] = [];
120
+ // SAFETY: the probe exercises the observe surface; the rest of Orchestrator
121
+ // is unused on this path.
122
+ const orch = {
123
+ config,
124
+ getCodingContextForSession: (sk: string | undefined) => (sk ? contexts.get(sk) : null) ?? null,
125
+ setCodingContextForSession: (sk: string, ctx: CodingContext | null) => {
126
+ if (ctx === null) contexts.delete(sk);
127
+ else contexts.set(sk, ctx);
128
+ },
129
+ applyCodingNamespaceOverlay: (sk: string | undefined, base: string) =>
130
+ Orchestrator.prototype.applyCodingNamespaceOverlay.call(orch, sk, base),
131
+ resolvePrincipal: (sk?: string) => Orchestrator.prototype.resolvePrincipal.call(orch, sk),
132
+ resolveSelfNamespace: (sk?: string) => Orchestrator.prototype.resolveSelfNamespace.call(orch, sk),
133
+ lcmEngine: {
134
+ enabled: true,
135
+ enqueueObserveMessages: options.enqueueObserveMessages,
136
+ },
137
+ ingestReplayBatch: async (turns: Array<{ sessionKey: string }>) => {
138
+ extractionCalls.push(turns.map((t) => t.sessionKey));
139
+ },
140
+ } as any;
141
+ return { orch, extractionCalls };
142
+ }
143
+
144
+ test("a slow successful observe logs access-observe-slow with per-stage durations", async () => {
145
+ const lines: string[] = [];
146
+ const backend: LoggerBackend = {
147
+ info(msg) {
148
+ lines.push(msg);
149
+ },
150
+ warn(msg) {
151
+ lines.push(msg);
152
+ },
153
+ error(msg) {
154
+ lines.push(msg);
155
+ },
156
+ };
157
+ initLogger(backend, false, { timestamps: false });
158
+ // Deterministic monotonic clock: every read advances 6s, so each timed
159
+ // stage records exactly 6000ms and the total exceeds the slow threshold.
160
+ let now = 0;
161
+ const realPerformanceNow = performance.now;
162
+ performance.now = () => (now += 6000);
163
+ try {
164
+ const { orch } = makeProbe({
165
+ enqueueObserveMessages: (_sessionKey) => {},
166
+ });
167
+ const service = new EngramAccessService(orch);
168
+ // SAFETY: the literal sets the request fields the observe path reads.
169
+ const slowRequest = {
170
+ sessionKey: "alice:sess-slow",
171
+ authenticatedPrincipal: "alice",
172
+ messages: [
173
+ { role: "user", content: "slow path message body" },
174
+ { role: "assistant", content: "reply body" },
175
+ ],
176
+ } as EngramAccessObserveRequest;
177
+ const res = await service.observe(slowRequest);
178
+ assert.equal(res.accepted, 2);
179
+
180
+ const slow = lines.filter((l) => l.includes("access-observe-slow"));
181
+ assert.equal(slow.length, 1, `expected one access-observe-slow line, got: ${lines}`);
182
+ const line = slow[0] ?? "";
183
+ assert.match(line, /totalMs=(\d+)/);
184
+ const totalMs = Number(/totalMs=(\d+)/.exec(line)?.[1]);
185
+ assert.ok(totalMs >= 10_000, `slow line must exceed threshold, got totalMs=${totalMs}`);
186
+ assert.match(line, /messages=2/);
187
+ // Real stages are attributed, including the durable-buffer terminal stage.
188
+ assert.match(line, /scopeMs=6000/);
189
+ assert.match(line, /durable-bufferMs=6000/);
190
+ assert.ok(!line.includes("sess-slow") && !line.includes("alice") && !line.includes("body"));
191
+ } finally {
192
+ performance.now = realPerformanceNow;
193
+ resetLogger();
194
+ }
195
+ });
196
+
197
+ test("a failed awaited LCM archival records the lcm-accept phase and still throws", async () => {
198
+ const lines: string[] = [];
199
+ const backend: LoggerBackend = {
200
+ info(msg) {
201
+ lines.push(msg);
202
+ },
203
+ warn(msg) {
204
+ lines.push(msg);
205
+ },
206
+ error(msg) {
207
+ lines.push(msg);
208
+ },
209
+ };
210
+ initLogger(backend, false, { timestamps: false });
211
+ try {
212
+ const { orch } = makeProbe({
213
+ enqueueObserveMessages: async () => {
214
+ throw new Error("lcm archival append failed");
215
+ },
216
+ });
217
+ const service = new EngramAccessService(orch);
218
+ // SAFETY: the literal sets the request fields the observe path reads.
219
+ const failedLcmRequest = {
220
+ sessionKey: "alice:sess-lcmfail",
221
+ authenticatedPrincipal: "alice",
222
+ messages: [
223
+ { role: "user", content: "lcm failure message body" },
224
+ { role: "assistant", content: "reply body" },
225
+ ],
226
+ } as EngramAccessObserveRequest;
227
+ await assert.rejects(
228
+ service.observe(failedLcmRequest),
229
+ /lcm archival append failed/
230
+ );
231
+
232
+ const failed = lines.filter((l) => l.includes("access-observe-failed"));
233
+ assert.equal(failed.length, 1, `expected exactly one access-observe-failed line, got: ${failed}`);
234
+ const line = failed[0] ?? "";
235
+ assert.match(line, /totalMs=\d+/);
236
+ assert.match(line, /messages=2/);
237
+ // The rejected LCM accept is attributed with its duration, alongside earlier stages.
238
+ assert.match(line, /scopeMs=\d+/);
239
+ assert.match(line, /lcm-acceptMs=\d+/);
240
+ assert.ok(!line.includes("sess-lcmfail"), `leaked session key in: ${line}`);
241
+ assert.ok(!line.includes("alice"), `leaked principal in: ${line}`);
242
+ assert.ok(!line.includes("body"), `leaked content in: ${line}`);
243
+ } finally {
244
+ resetLogger();
245
+ }
246
+ });
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Noncontent stage timing for the observe surface.
3
+ *
4
+ * Durations only — never message content, session keys, namespaces or
5
+ * principals. A monotonic clock (`performance.now`) keeps phase durations
6
+ * sane under wall-clock corrections.
7
+ *
8
+ * A slow observe logs `access-observe-slow`; a failed observe always logs
9
+ * `access-observe-failed`, so a 25s-class stall attributes to a phase
10
+ * instead of a guess.
11
+ */
12
+ import { log } from "./logger.js";
13
+
14
+ /** Observes slower than this log `access-observe-slow` with per-stage durations. */
15
+ const OBSERVE_SLOW_LOG_MS = 10_000;
16
+
17
+ export interface ObserveStageTimer {
18
+ /** Run one stage, recording its duration even when the stage rejects. */
19
+ timed<T>(stage: string, fn: () => Promise<T>): Promise<T>;
20
+ /** Log a slow successful observe with per-stage durations. */
21
+ logSlow(messages: number): void;
22
+ /** Log a failed observe with per-stage durations. */
23
+ logFailed(messages: number): void;
24
+ }
25
+
26
+ /** Timer for one observe request. */
27
+ export function createObserveStageTimer(): ObserveStageTimer {
28
+ const startedAtMs = performance.now();
29
+ const stageMs: Record<string, number> = {};
30
+
31
+ const formatStages = (): string =>
32
+ Object.entries(stageMs)
33
+ .map(([stage, ms]) => `${stage}Ms=${Math.round(ms)}`)
34
+ .join(" ");
35
+
36
+ return {
37
+ async timed<T>(stage: string, fn: () => Promise<T>): Promise<T> {
38
+ const stageStartMs = performance.now();
39
+ try {
40
+ return await fn();
41
+ } finally {
42
+ stageMs[stage] = (stageMs[stage] ?? 0) + (performance.now() - stageStartMs);
43
+ }
44
+ },
45
+ logSlow(messages: number): void {
46
+ const totalMs = Math.round(performance.now() - startedAtMs);
47
+ if (totalMs < OBSERVE_SLOW_LOG_MS) return;
48
+ log.warn(
49
+ `access-observe-slow totalMs=${totalMs} messages=${messages} ${formatStages()}`,
50
+ );
51
+ },
52
+ logFailed(messages: number): void {
53
+ log.warn(
54
+ `access-observe-failed totalMs=${Math.round(performance.now() - startedAtMs)} messages=${messages} ${formatStages()}`,
55
+ );
56
+ },
57
+ };
58
+ }
@@ -34,6 +34,9 @@ import { abortError } from "./abort-error.js";
34
34
  import { withBriefingDeadline } from "./briefing-deadline.js";
35
35
  import { extractionForceFlush } from "./access-extraction-force-flush.js";
36
36
  import { ObserveTranscriptPersister, observeTranscriptSessionKey } from "./access-observe-transcript.js";
37
+ import { createObserveStageTimer } from "./access-observe-stage-timing.js";
38
+ import { archiveObservedTurns } from "./access-observe-lcm-archive.js";
39
+ import { recordObserveObjectiveState } from "./access-observe-objective-state.js";
37
40
  import { FileCalendarSource, buildBriefing, parseBriefingFocus, parseBriefingWindow } from "./briefing.js";
38
41
  import {
39
42
  resolveCompressionCapabilities,
@@ -708,10 +711,16 @@ export class AccessObserveWriteSurface {
708
711
  request.sessionKey,
709
712
  pendingObserveScopeHint(request)
710
713
  );
714
+ // Noncontent stage timing for slow/failed observes: durations only, logged
715
+ // in the `access-observe-failed` line (always) and `access-observe-slow`
716
+ // (successes at or above the slow threshold). Never message content,
717
+ // session keys, namespaces or principals.
718
+ const stageTimer = createObserveStageTimer();
719
+ const timed = stageTimer.timed.bind(stageTimer);
711
720
  try {
712
721
  let scope: MemoryScopePlan;
713
722
  try {
714
- scope = await this.deps.resolveMemoryScopePlan(request);
723
+ scope = await timed("scope", () => this.deps.resolveMemoryScopePlan(request));
715
724
  } catch (err) {
716
725
  // A replay re-submit sets suppressQuarantine so a still-unwritable target
717
726
  // propagates instead of re-parking (#1888); observe has no dryRun path.
@@ -749,10 +758,12 @@ export class AccessObserveWriteSurface {
749
758
  // on the same session is project-scoped (rule 42: same namespace layer as
750
759
  // recall). Done AFTER the scope plan authorized the write, so a rejected
751
760
  // request never leaves orphaned context on the session.
752
- await this.deps.maybeAttachCodingContext(request.sessionKey, {
753
- cwd: request.cwd,
754
- projectTag: request.projectTag,
755
- });
761
+ await timed("context", () =>
762
+ this.deps.maybeAttachCodingContext(request.sessionKey, {
763
+ cwd: request.cwd,
764
+ projectTag: request.projectTag,
765
+ })
766
+ );
756
767
 
757
768
  // Prefix sessionKey with the EFFECTIVE write namespace for LCM archival so
758
769
  // observed turns are scoped to the same namespace project-scoped recall
@@ -771,51 +782,35 @@ export class AccessObserveWriteSurface {
771
782
  // (#928 contract, already auth-checked inside the scope plan), not the
772
783
  // general default-store write namespace.
773
784
  if (shouldWriteObjectiveState) {
774
- try {
775
- const objectiveStateLocation = await this.deps.objectiveStateStoreLocationForNamespace(
776
- scope.objectiveStateNamespace
777
- );
778
- await recordObjectiveStateSnapshotsFromObservedMessages({
779
- memoryDir: objectiveStateLocation.memoryDir,
780
- objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
781
- objectiveStateMemoryEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
782
- .objectiveStateMemory,
783
- objectiveStateSnapshotWritesEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config)
784
- .objectiveStateSnapshotWrites,
785
- sessionKey: request.sessionKey,
786
- recordedAt: new Date().toISOString(),
787
- messages: request.messages,
788
- });
789
- } catch (err) {
790
- log.error(`access-observe objective-state snapshot write failed: ${err}`);
791
- }
785
+ await timed("objective", () =>
786
+ recordObserveObjectiveState(
787
+ this.deps.orchestrator,
788
+ this.deps.objectiveStateStoreLocationForNamespace,
789
+ scope,
790
+ request,
791
+ ),
792
+ );
792
793
  }
793
794
 
794
795
  // 5. LCM archival → effective write namespace.
795
- // lcmArchived in the response means "LCM archival was queued" (not
796
- // "completed"), matching extractionQueued semantics. Both run async.
797
- let lcmArchived = false;
798
- if (this.deps.orchestrator.lcmEngine && this.deps.orchestrator.lcmEngine.enabled) {
799
- // Fire-and-forget: LCM archival writes to SQLite and builds summary
800
- // DAGs, which can take tens of seconds for large sessions. Don't
801
- // block the HTTP response — the caller only needs acknowledgment.
802
- try {
803
- this.deps.orchestrator.lcmEngine.enqueueObserveMessages(lcmSessionKey, request.messages);
804
- lcmArchived = true;
805
- } catch (err) {
806
- log.error(`access-observe LCM enqueue failed: ${err}`);
807
- }
808
- }
796
+ // The archival append is durable before this returns: the queue holds
797
+ // only a session reference, and summary DAGs are built in the
798
+ // background, so the caller is never blocked on inference.
799
+ const lcmArchived = await timed("lcm-accept", () =>
800
+ archiveObservedTurns(this.deps.orchestrator.lcmEngine, lcmSessionKey, request.messages),
801
+ );
809
802
 
810
803
  // 5b. Transcript persistence → the per-session transcript store the
811
- // hourly summarizer reads (issue #2783). Best-effort like the LCM
812
- // enqueue above: a transcript failure must not fail the observe.
804
+ // hourly summarizer reads (issue #2783). Best-effort: a transcript
805
+ // failure must not fail the observe.
813
806
  const transcriptPersisted = resolvePresentationCapabilities(this.deps.orchestrator.config).transcript
814
- ? await this.observeTranscriptPersister.persist(
815
- this.deps.orchestrator,
816
- observeTranscriptSessionKey(request.sessionKey, writeNamespace, this.deps.orchestrator.config),
817
- request.messages,
818
- request.sessionKey
807
+ ? await timed("transcript", () =>
808
+ this.observeTranscriptPersister.persist(
809
+ this.deps.orchestrator,
810
+ observeTranscriptSessionKey(request.sessionKey, writeNamespace, this.deps.orchestrator.config),
811
+ request.messages,
812
+ request.sessionKey
813
+ )
819
814
  )
820
815
  : false;
821
816
 
@@ -895,10 +890,11 @@ export class AccessObserveWriteSurface {
895
890
  extractionQueued = true;
896
891
  };
897
892
  }
898
- await this.deps.orchestrator.ingestReplayBatch(turns, ingestOptions);
893
+ await timed("durable-buffer", () => this.deps.orchestrator.ingestReplayBatch(turns, ingestOptions));
899
894
  // A native trigger may leave the durable capture pending rather than queued.
900
895
  }
901
896
 
897
+ stageTimer.logSlow(request.messages.length);
902
898
  log.info(
903
899
  `access-observe namespace=${namespace} effectiveNamespace=${writeNamespace} sessionKey=${request.sessionKey} messages=${request.messages.length} lcm=${lcmArchived} extraction=${extractionQueued} transcript=${transcriptPersisted}`
904
900
  );
@@ -924,6 +920,10 @@ export class AccessObserveWriteSurface {
924
920
  extractionQueued,
925
921
  transcriptPersisted,
926
922
  };
923
+ } catch (err) {
924
+ // Failed requests always get phase attribution (noncontent), regardless of duration.
925
+ stageTimer.logFailed(request.messages.length);
926
+ throw err;
927
927
  } finally {
928
928
  observePreparation.release();
929
929
  }
@@ -1079,6 +1079,7 @@ export interface EngramAccessObserveResponse {
1079
1079
  effectiveNamespace: string;
1080
1080
  /** Additive diagnostic view of the resolved scope plan (#1495). */
1081
1081
  scopeDebug?: EngramAccessScopeDebug;
1082
+ /** True when the observed turns are durably archived in LCM — the archive append completed before the response was produced. */
1082
1083
  lcmArchived: boolean;
1083
1084
  extractionQueued: boolean;
1084
1085
  /** True when at least one observe-derived turn was appended to the transcript store (issue #2783). False when the transcript capability is off, every message was filtered/deduped, or every append failed. */