@remnic/core 9.30.0 → 9.31.0

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 (495) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +50 -44
  3. package/dist/access-authorization-probe.d.ts +10 -10
  4. package/dist/access-authorization-probe.js +51 -45
  5. package/dist/access-boundary.d.ts +13 -11
  6. package/dist/access-boundary.js +50 -44
  7. package/dist/access-cli.js +168 -123
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +119 -0
  10. package/dist/access-extraction-force-flush.js +166 -0
  11. package/dist/access-health-types.d.ts +1 -1
  12. package/dist/access-http-lcm-compaction.d.ts +47 -13
  13. package/dist/access-http-lcm-compaction.js +7 -3
  14. package/dist/access-http-lifecycle-flush.d.ts +132 -0
  15. package/dist/access-http-lifecycle-flush.js +9 -0
  16. package/dist/access-http-lifecycle-flush.js.map +1 -0
  17. package/dist/access-http.d.ts +11 -10
  18. package/dist/access-http.js +66 -59
  19. package/dist/access-identity-continuity-surface.d.ts +8 -8
  20. package/dist/access-identity-continuity-surface.js +50 -44
  21. package/dist/access-lcm-surface.d.ts +10 -10
  22. package/dist/access-lcm-surface.js +50 -44
  23. package/dist/access-mcp-output-schemas.js +1 -1
  24. package/dist/access-mcp.d.ts +16 -10
  25. package/dist/access-mcp.js +58 -52
  26. package/dist/access-memory-search-fanout.d.ts +2 -2
  27. package/dist/{access-namespace-preflight-VfXssvoI.d.ts → access-namespace-preflight-D4vW97H1.d.ts} +1 -1
  28. package/dist/access-namespace-preflight.d.ts +3 -3
  29. package/dist/access-namespace-preflight.js +50 -44
  30. package/dist/access-observe-helpers.d.ts +22 -0
  31. package/dist/access-observe-helpers.js +10 -0
  32. package/dist/access-observe-helpers.js.map +1 -0
  33. package/dist/access-observe-write-surface.d.ts +51 -47
  34. package/dist/access-observe-write-surface.js +50 -44
  35. package/dist/access-operations-batch.js +53 -47
  36. package/dist/access-operations.d.ts +11 -11
  37. package/dist/access-operations.js +55 -49
  38. package/dist/access-recall-concurrency.d.ts +10 -10
  39. package/dist/access-recall-concurrency.js +50 -44
  40. package/dist/access-recall-response.d.ts +10 -10
  41. package/dist/access-recall-response.js +50 -44
  42. package/dist/access-recall-surface.d.ts +10 -10
  43. package/dist/access-recall-surface.js +50 -44
  44. package/dist/access-schema.d.ts +37 -7
  45. package/dist/access-schema.js +5 -3
  46. package/dist/{access-service-B5RwVsTV.d.ts → access-service-B6PZ_xUL.d.ts} +44 -20
  47. package/dist/access-service-helpers.d.ts +113 -0
  48. package/dist/access-service-helpers.js +8 -0
  49. package/dist/access-service-helpers.js.map +1 -0
  50. package/dist/access-service.d.ts +10 -10
  51. package/dist/access-service.js +50 -44
  52. package/dist/access-surface-catalog.d.ts +10 -10
  53. package/dist/access-surface-catalog.js +2 -0
  54. package/dist/access-surface-catalog.js.map +1 -1
  55. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  56. package/dist/action-confidence.d.ts +1 -1
  57. package/dist/active-memory-bridge.d.ts +1 -1
  58. package/dist/active-recall.d.ts +1 -1
  59. package/dist/active-recall.js +1 -1
  60. package/dist/adapters/index.js +7 -7
  61. package/dist/adapters/registry.js +3 -3
  62. package/dist/behavior-learner.d.ts +1 -1
  63. package/dist/behavior-signals.d.ts +1 -1
  64. package/dist/bootstrap.d.ts +8 -8
  65. package/dist/briefing.d.ts +2 -2
  66. package/dist/briefing.js +14 -14
  67. package/dist/buffer-surprise-report.d.ts +1 -1
  68. package/dist/buffer-turn-helpers.d.ts +5 -0
  69. package/dist/buffer-turn-helpers.js +24 -0
  70. package/dist/buffer-turn-helpers.js.map +1 -0
  71. package/dist/buffer.d.ts +17 -4
  72. package/dist/buffer.js +21 -1
  73. package/dist/bulk-import/index.d.ts +3 -3
  74. package/dist/calibration.d.ts +1 -1
  75. package/dist/capabilities.d.ts +1 -1
  76. package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
  77. package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
  78. package/dist/{capsule-merge-5KKJQBWQ.js → capsule-merge-2H2IUTBT.js} +4 -4
  79. package/dist/{catalog-V7inUQdp.d.ts → catalog-CGFYmTT8.d.ts} +1 -1
  80. package/dist/causal-behavior.d.ts +1 -1
  81. package/dist/causal-behavior.js +2 -2
  82. package/dist/causal-chain.js +2 -2
  83. package/dist/causal-consolidation.d.ts +1 -1
  84. package/dist/causal-consolidation.js +19 -19
  85. package/dist/causal-retrieval.js +2 -2
  86. package/dist/causal-trajectory-graph.d.ts +1 -1
  87. package/dist/causal-trajectory.js +1 -1
  88. package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
  89. package/dist/{chunk-GIBMDSJ2.js → chunk-27P5YVDU.js} +2 -2
  90. package/dist/{chunk-2SA56WMI.js → chunk-2LTDWSR6.js} +4 -4
  91. package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
  92. package/dist/{chunk-YTSNAUXN.js → chunk-3F2LKUMU.js} +22 -8
  93. package/dist/chunk-3F2LKUMU.js.map +1 -0
  94. package/dist/chunk-3QL24R5Y.js +9 -0
  95. package/dist/chunk-3QL24R5Y.js.map +1 -0
  96. package/dist/chunk-4RNZMRAV.js +60 -0
  97. package/dist/chunk-4RNZMRAV.js.map +1 -0
  98. package/dist/{chunk-6U7F52DE.js → chunk-4XHR3I67.js} +60 -60
  99. package/dist/chunk-5IVLTFOV.js +65 -0
  100. package/dist/chunk-5IVLTFOV.js.map +1 -0
  101. package/dist/{chunk-2EUVEDF5.js → chunk-5XA7PQ5I.js} +2 -2
  102. package/dist/{chunk-ALSGMEJR.js → chunk-65ZPVYTA.js} +7 -7
  103. package/dist/{chunk-5VQJBH2G.js → chunk-6TAUHL33.js} +2 -2
  104. package/dist/{chunk-HUHX2OCX.js → chunk-7DRETLP5.js} +1 -1
  105. package/dist/chunk-7DRETLP5.js.map +1 -0
  106. package/dist/{chunk-RGIWINDN.js → chunk-7G5MH4NT.js} +30 -30
  107. package/dist/{chunk-WVO4G37W.js → chunk-7TEZUUGM.js} +3 -3
  108. package/dist/{chunk-MJCGLM25.js → chunk-7VUAG236.js} +5 -5
  109. package/dist/{chunk-M3C2V3PV.js → chunk-AJEMDQNA.js} +12 -12
  110. package/dist/{chunk-RKNJBZ55.js → chunk-AU7Q3LSC.js} +7 -7
  111. package/dist/{chunk-ACXPX4AG.js → chunk-BR2K43MK.js} +2 -2
  112. package/dist/{chunk-IYZ5K7MU.js → chunk-BUE5E2HL.js} +4 -187
  113. package/dist/chunk-BUE5E2HL.js.map +1 -0
  114. package/dist/{chunk-CZRYLSSW.js → chunk-BUGVGH4N.js} +2 -2
  115. package/dist/{chunk-YTQNQ4KB.js → chunk-C4VQMFVM.js} +3 -3
  116. package/dist/{chunk-ZPSVBSOF.js → chunk-CIVDJD6P.js} +3 -3
  117. package/dist/{chunk-K5GB36ME.js → chunk-CZDOT5I2.js} +2 -2
  118. package/dist/{chunk-VI2JQPNQ.js → chunk-E4PWACUN.js} +2 -2
  119. package/dist/{chunk-D2ANTDGO.js → chunk-E6BMSH7U.js} +2 -2
  120. package/dist/{chunk-P5PXWTW7.js → chunk-EJCAV3QZ.js} +3 -3
  121. package/dist/{chunk-CKMO4RDY.js → chunk-EMDLM3LW.js} +4 -4
  122. package/dist/chunk-ER7W6H4T.js +112 -0
  123. package/dist/chunk-ER7W6H4T.js.map +1 -0
  124. package/dist/{chunk-6FUPCJUL.js → chunk-FI4F5X2V.js} +54 -54
  125. package/dist/chunk-FI4F5X2V.js.map +1 -0
  126. package/dist/{chunk-LGHKJABJ.js → chunk-GOUILH55.js} +40 -18
  127. package/dist/chunk-GOUILH55.js.map +1 -0
  128. package/dist/{chunk-G5R3D5UP.js → chunk-GTTAHHD3.js} +2 -2
  129. package/dist/{chunk-H5CPS5JP.js → chunk-H36LJIPD.js} +3 -3
  130. package/dist/{chunk-AITCS2RC.js → chunk-IJ7HK452.js} +4 -4
  131. package/dist/{chunk-D3LMYTBV.js → chunk-J7WZUL2K.js} +9 -9
  132. package/dist/{chunk-5W4ZLBEZ.js → chunk-JCFTIQBR.js} +2 -2
  133. package/dist/{chunk-XOZ4ALGB.js → chunk-KE353EWI.js} +3 -3
  134. package/dist/{chunk-W5EG6LE3.js → chunk-KIT6M7EB.js} +3 -3
  135. package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
  136. package/dist/{chunk-Z54EM5YZ.js → chunk-MAXVH44E.js} +7 -7
  137. package/dist/{chunk-WZFAPHIK.js → chunk-MU7ZHSZE.js} +2 -2
  138. package/dist/chunk-N5Z4EVOR.js +123 -0
  139. package/dist/chunk-N5Z4EVOR.js.map +1 -0
  140. package/dist/{chunk-66772WBP.js → chunk-NFXQJHJD.js} +5 -5
  141. package/dist/{chunk-AZ5BTEKX.js → chunk-NQUF7XKR.js} +2 -2
  142. package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
  143. package/dist/{chunk-NHWB6HG2.js → chunk-NYCGIQRA.js} +2 -2
  144. package/dist/{chunk-4WKA6I65.js → chunk-OGCNZPKX.js} +1119 -309
  145. package/dist/chunk-OGCNZPKX.js.map +1 -0
  146. package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
  147. package/dist/{chunk-FDAMS4PK.js → chunk-PNPOWBGC.js} +2 -2
  148. package/dist/{chunk-IC6CBHCA.js → chunk-QGENAYVS.js} +2 -2
  149. package/dist/{chunk-GBJ4RDFR.js → chunk-QIHIHZYC.js} +66 -91
  150. package/dist/chunk-QIHIHZYC.js.map +1 -0
  151. package/dist/{chunk-PUS63Q3G.js → chunk-RUYJ7TWU.js} +517 -2011
  152. package/dist/chunk-RUYJ7TWU.js.map +1 -0
  153. package/dist/{chunk-4A6YGWQN.js → chunk-TL4TO3EA.js} +115 -120
  154. package/dist/chunk-TL4TO3EA.js.map +1 -0
  155. package/dist/{chunk-SPJXKAVF.js → chunk-U52AKICI.js} +14 -13
  156. package/dist/chunk-U52AKICI.js.map +1 -0
  157. package/dist/chunk-ULARSG5Z.js +203 -0
  158. package/dist/chunk-ULARSG5Z.js.map +1 -0
  159. package/dist/{chunk-62U4J2GN.js → chunk-UR77VKF7.js} +2 -2
  160. package/dist/{chunk-JCBWCYEJ.js → chunk-VANLTS5F.js} +2 -2
  161. package/dist/{chunk-4Z4XNEWZ.js → chunk-VCD4PSK2.js} +56 -12
  162. package/dist/chunk-VCD4PSK2.js.map +1 -0
  163. package/dist/{chunk-RMMVQQA6.js → chunk-WDISJRMG.js} +2 -2
  164. package/dist/{chunk-B6JDYXL7.js → chunk-WWUVONGW.js} +7 -1
  165. package/dist/chunk-WWUVONGW.js.map +1 -0
  166. package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
  167. package/dist/{chunk-TH2LSRMG.js → chunk-XHDIB4T4.js} +2 -2
  168. package/dist/{chunk-CVILPI77.js → chunk-XOQSEF7X.js} +6 -6
  169. package/dist/{chunk-LBOD4U5B.js → chunk-YFOMN2II.js} +6 -6
  170. package/dist/{chunk-RPW2NOU6.js → chunk-YIAA2X3D.js} +41 -1
  171. package/dist/chunk-YIAA2X3D.js.map +1 -0
  172. package/dist/chunk-YPC7W6GA.js +1604 -0
  173. package/dist/chunk-YPC7W6GA.js.map +1 -0
  174. package/dist/{chunk-I5NLEENJ.js → chunk-Z4SWV4VW.js} +3 -3
  175. package/dist/{chunk-PHWUFPCO.js → chunk-ZCPP5OW6.js} +61 -53
  176. package/dist/chunk-ZCPP5OW6.js.map +1 -0
  177. package/dist/{cli-C4GbETPC.d.ts → cli-BptUDTtp.d.ts} +5 -5
  178. package/dist/cli.d.ts +12 -12
  179. package/dist/cli.js +91 -84
  180. package/dist/compounding/engine.d.ts +2 -2
  181. package/dist/compounding/engine.js +14 -14
  182. package/dist/compounding/preference-consolidator.d.ts +1 -1
  183. package/dist/compression-optimizer.d.ts +1 -1
  184. package/dist/config.d.ts +1 -1
  185. package/dist/config.js +1 -1
  186. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  187. package/dist/connectors/codex-materialize-runner.js +14 -14
  188. package/dist/connectors/codex-materialize.d.ts +1 -1
  189. package/dist/connectors/index.d.ts +1 -1
  190. package/dist/connectors/index.js +17 -17
  191. package/dist/consolidation-provenance-check.d.ts +2 -2
  192. package/dist/consolidation-provenance-check.js +5 -5
  193. package/dist/consolidation-undo.d.ts +2 -2
  194. package/dist/consolidation-undo.js +3 -3
  195. package/dist/contradiction/index.d.ts +2 -2
  196. package/dist/contradiction/index.js +4 -4
  197. package/dist/conversation-index/backend.d.ts +1 -1
  198. package/dist/conversation-index/backend.js +2 -2
  199. package/dist/conversation-index/chunker.d.ts +1 -1
  200. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  201. package/dist/conversation-index/indexer.d.ts +1 -1
  202. package/dist/conversation-index/search.d.ts +1 -1
  203. package/dist/corpus-watermark.d.ts +1 -1
  204. package/dist/corpus-watermark.js +26 -26
  205. package/dist/day-summary.d.ts +1 -1
  206. package/dist/delinearize.d.ts +1 -1
  207. package/dist/direct-answer-wiring.d.ts +1 -1
  208. package/dist/direct-answer.d.ts +1 -1
  209. package/dist/embedding-fallback.d.ts +1 -1
  210. package/dist/enrichment/index.d.ts +1 -1
  211. package/dist/entity-retrieval.d.ts +2 -2
  212. package/dist/entity-retrieval.js +14 -14
  213. package/dist/entity-schema.d.ts +1 -1
  214. package/dist/explicit-capture.d.ts +8 -8
  215. package/dist/extraction-error-classification.d.ts +1 -1
  216. package/dist/extraction-faithfulness.d.ts +1 -1
  217. package/dist/extraction-judge-telemetry.d.ts +1 -1
  218. package/dist/extraction-judge-training.d.ts +1 -1
  219. package/dist/extraction-judge.d.ts +1 -1
  220. package/dist/extraction-liveness.d.ts +1 -1
  221. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  222. package/dist/extraction-source-grounding.d.ts +15 -2
  223. package/dist/extraction-source-grounding.js +10 -1
  224. package/dist/extraction.d.ts +2 -15
  225. package/dist/extraction.js +5 -4
  226. package/dist/fallback-llm.d.ts +1 -1
  227. package/dist/graph-dashboard-diff.d.ts +1 -1
  228. package/dist/graph-dashboard-key.d.ts +1 -1
  229. package/dist/graph-dashboard-parser.d.ts +1 -1
  230. package/dist/graph-edge-reinforcement.d.ts +1 -1
  231. package/dist/graph-snapshot.d.ts +1 -1
  232. package/dist/graph.d.ts +1 -1
  233. package/dist/importance.d.ts +1 -1
  234. package/dist/importers/index.d.ts +1 -1
  235. package/dist/in-flight-reads.d.ts +1 -1
  236. package/dist/index.d.ts +19 -19
  237. package/dist/index.js +215 -207
  238. package/dist/intent.d.ts +1 -1
  239. package/dist/lcm/engine.d.ts +1 -1
  240. package/dist/lcm/engine.js +3 -3
  241. package/dist/lcm/index.d.ts +1 -1
  242. package/dist/lcm/index.js +6 -6
  243. package/dist/lcm/tools.d.ts +1 -1
  244. package/dist/lifecycle.d.ts +1 -1
  245. package/dist/live-connectors-runner.d.ts +1 -1
  246. package/dist/local-llm-helpers.d.ts +7 -0
  247. package/dist/local-llm-helpers.js +16 -0
  248. package/dist/local-llm-helpers.js.map +1 -0
  249. package/dist/local-llm.d.ts +3 -6
  250. package/dist/local-llm.js +2 -1
  251. package/dist/local-model-endpoint.d.ts +1 -1
  252. package/dist/maintenance/memory-governance.d.ts +1 -1
  253. package/dist/maintenance/memory-governance.js +14 -14
  254. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  255. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -14
  256. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  257. package/dist/maintenance/rebuild-memory-projection.js +15 -15
  258. package/dist/{maintenance-CL30NWtc.d.ts → maintenance-b6f92bRz.d.ts} +3 -3
  259. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  260. package/dist/memory-action-policy.d.ts +1 -1
  261. package/dist/memory-cache.d.ts +1 -1
  262. package/dist/memory-corpus-version.js +2 -2
  263. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  264. package/dist/memory-projection-store.d.ts +1 -1
  265. package/dist/memory-provenance.d.ts +1 -1
  266. package/dist/memory-worth-outcomes.d.ts +2 -2
  267. package/dist/models-json.d.ts +1 -1
  268. package/dist/namespaces/migrate.d.ts +3 -3
  269. package/dist/namespaces/migrate.js +24 -24
  270. package/dist/namespaces/principal.d.ts +1 -1
  271. package/dist/namespaces/search.d.ts +1 -1
  272. package/dist/namespaces/search.js +9 -9
  273. package/dist/namespaces/storage.d.ts +3 -3
  274. package/dist/namespaces/storage.js +14 -14
  275. package/dist/native-knowledge.d.ts +1 -1
  276. package/dist/offline-sync-impression-drain.d.ts +1 -1
  277. package/dist/offline-sync-impression-drain.js +6 -5
  278. package/dist/operator-doctor-corpus.d.ts +1 -1
  279. package/dist/operator-doctor-corpus.js +29 -29
  280. package/dist/operator-doctor-replica.d.ts +1 -1
  281. package/dist/operator-doctor-replica.js +3 -3
  282. package/dist/operator-toolkit.d.ts +3 -3
  283. package/dist/operator-toolkit.js +38 -37
  284. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  285. package/dist/orchestration/maintenance.d.ts +4 -4
  286. package/dist/orchestration/maintenance.js +22 -21
  287. package/dist/{orchestrator-CKTCRwWV.d.ts → orchestrator-3uGxC1qO.d.ts} +72 -34
  288. package/dist/orchestrator.d.ts +8 -8
  289. package/dist/orchestrator.js +167 -159
  290. package/dist/page-versioning.js +3 -3
  291. package/dist/patterns-cli.d.ts +1 -1
  292. package/dist/{pipeline-B7wj4rRZ.d.ts → pipeline-DepuNr-m.d.ts} +1 -1
  293. package/dist/policy-runtime.d.ts +1 -1
  294. package/dist/proactive-contention.d.ts +1 -1
  295. package/dist/provenance.d.ts +1 -1
  296. package/dist/{qmd-q9tg4dHp.d.ts → qmd-Dalr3Jby.d.ts} +1 -1
  297. package/dist/qmd-preflight.d.ts +2 -2
  298. package/dist/qmd-recall-cache.d.ts +1 -1
  299. package/dist/qmd.d.ts +2 -2
  300. package/dist/qmd.js +4 -4
  301. package/dist/recall-concurrency-config.d.ts +1 -1
  302. package/dist/recall-disclosure-escalation.d.ts +1 -1
  303. package/dist/recall-explain-renderer.d.ts +1 -1
  304. package/dist/recall-explain-renderer.js +3 -3
  305. package/dist/recall-memory-map.d.ts +1 -1
  306. package/dist/recall-planner-llm.d.ts +1 -1
  307. package/dist/recall-state.d.ts +1 -1
  308. package/dist/recall-tag-filter.d.ts +1 -1
  309. package/dist/recall-timings.d.ts +1 -1
  310. package/dist/recall-xray-cli.d.ts +1 -1
  311. package/dist/recall-xray-cli.js +4 -4
  312. package/dist/recall-xray-renderer.d.ts +1 -1
  313. package/dist/recall-xray-renderer.js +3 -3
  314. package/dist/recall-xray.d.ts +1 -1
  315. package/dist/recall-xray.js +2 -2
  316. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  317. package/dist/replay/normalizers/claude.d.ts +1 -1
  318. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  319. package/dist/replay/normalizers/shared.d.ts +1 -1
  320. package/dist/replay/runner.d.ts +1 -1
  321. package/dist/replay/types.d.ts +1 -1
  322. package/dist/replica-divergence.d.ts +1 -1
  323. package/dist/replica-divergence.js +2 -2
  324. package/dist/replica-peers-config.d.ts +1 -1
  325. package/dist/resolve-auth-token.d.ts +1 -1
  326. package/dist/resume-bundles.js +1 -1
  327. package/dist/retrieval-agents.d.ts +2 -2
  328. package/dist/retrieval-tiers.d.ts +1 -1
  329. package/dist/routing/engine.d.ts +1 -1
  330. package/dist/routing/store.d.ts +1 -1
  331. package/dist/salvage-envelope.d.ts +1 -1
  332. package/dist/{scope-profiles-CWDyglPM.d.ts → scope-profiles-BpiM5hTU.d.ts} +1 -1
  333. package/dist/search/embed-helper.d.ts +1 -1
  334. package/dist/search/factory.d.ts +1 -1
  335. package/dist/search/factory.js +8 -8
  336. package/dist/search/index.d.ts +1 -1
  337. package/dist/search/index.js +12 -12
  338. package/dist/search/lancedb-backend.d.ts +1 -1
  339. package/dist/search/meilisearch-backend.d.ts +1 -1
  340. package/dist/search/noop-backend.d.ts +1 -1
  341. package/dist/search/orama-backend.d.ts +1 -1
  342. package/dist/search/port.d.ts +1 -1
  343. package/dist/search/remote-backend.d.ts +1 -1
  344. package/dist/{semantic-consolidation-BUE3deLn.d.ts → semantic-consolidation-CMtVrf9f.d.ts} +1 -1
  345. package/dist/semantic-consolidation.d.ts +2 -2
  346. package/dist/semantic-consolidation.js +16 -16
  347. package/dist/semantic-rule-promotion.js +14 -14
  348. package/dist/semantic-rule-verifier.d.ts +1 -1
  349. package/dist/semantic-rule-verifier.js +14 -14
  350. package/dist/{service-CXgM0bQG.d.ts → service-DuAxwSgg.d.ts} +2 -2
  351. package/dist/session-observer-bands.d.ts +1 -1
  352. package/dist/session-observer-state.d.ts +1 -1
  353. package/dist/shared-context/manager.d.ts +1 -1
  354. package/dist/signal.d.ts +1 -1
  355. package/dist/{storage-DysJq-XH.d.ts → storage-CF0Ih8GP.d.ts} +1 -1
  356. package/dist/storage.d.ts +2 -2
  357. package/dist/storage.js +13 -13
  358. package/dist/summarizer.d.ts +1 -1
  359. package/dist/summarizer.js +3 -2
  360. package/dist/summary-snapshot.d.ts +1 -1
  361. package/dist/temporal-supersession.d.ts +2 -2
  362. package/dist/temporal-timeline-recall.d.ts +1 -1
  363. package/dist/temporal-validity.d.ts +1 -1
  364. package/dist/threading.d.ts +1 -1
  365. package/dist/tier-migration.d.ts +2 -2
  366. package/dist/tier-routing.d.ts +1 -1
  367. package/dist/tokens.js +2 -2
  368. package/dist/topics.d.ts +1 -1
  369. package/dist/transcript.d.ts +1 -1
  370. package/dist/transfer/backup.js +2 -2
  371. package/dist/transfer/capsule-export.js +2 -2
  372. package/dist/transfer/capsule-import.js +5 -5
  373. package/dist/trust-score-stage.d.ts +1 -1
  374. package/dist/trust-score.d.ts +1 -1
  375. package/dist/{types-aPPzhnjT.d.ts → types-BpaYvJ6v.d.ts} +22 -2
  376. package/dist/types.d.ts +1 -1
  377. package/dist/types.js +1 -1
  378. package/dist/utility-runtime.d.ts +1 -1
  379. package/dist/verified-recall.js +14 -14
  380. package/dist/write-envelope.d.ts +1 -1
  381. package/package.json +2 -2
  382. package/src/access-boundary.ts +3 -0
  383. package/src/access-cli.test.ts +93 -0
  384. package/src/access-cli.ts +56 -2
  385. package/src/access-extraction-force-flush.ts +177 -0
  386. package/src/access-http-extraction-force-flush.test.ts +132 -0
  387. package/src/access-http-lcm-compaction.ts +99 -22
  388. package/src/access-http-lifecycle-flush.ts +81 -0
  389. package/src/access-http.test.ts +227 -0
  390. package/src/access-http.ts +33 -40
  391. package/src/access-mcp-output-schemas.ts +6 -0
  392. package/src/access-mcp.test.ts +40 -0
  393. package/src/access-mcp.ts +32 -1
  394. package/src/access-observe-helpers.ts +180 -0
  395. package/src/access-observe-write-surface.ts +78 -19
  396. package/src/access-operations-batch.ts +2 -1
  397. package/src/access-schema-pi.test.ts +17 -0
  398. package/src/access-schema.ts +28 -11
  399. package/src/access-service-helpers.ts +46 -0
  400. package/src/access-service-observe-lcm-parity.test.ts +781 -31
  401. package/src/access-service-observe-scope.test.ts +88 -0
  402. package/src/access-service.ts +46 -128
  403. package/src/access-surface-catalog.test.ts +32 -0
  404. package/src/access-surface-catalog.ts +2 -0
  405. package/src/buffer-session.test.ts +148 -0
  406. package/src/buffer-turn-helpers.ts +152 -0
  407. package/src/buffer.ts +126 -201
  408. package/src/correction/correction-access-wiring.ts +79 -27
  409. package/src/correction/correction-executor.test.ts +542 -1
  410. package/src/correction/correction-executor.ts +309 -89
  411. package/src/correction/correction-planner.test.ts +35 -1
  412. package/src/correction/correction-planner.ts +50 -3
  413. package/src/correction/correction-service.ts +12 -7
  414. package/src/correction/correction-storage-integration.test.ts +172 -1
  415. package/src/correction/passive-capture.test.ts +35 -0
  416. package/src/correction/passive-capture.ts +17 -3
  417. package/src/extraction-source-grounding.ts +55 -1
  418. package/src/extraction-timeout.test.ts +51 -0
  419. package/src/extraction.ts +64 -90
  420. package/src/local-llm-headers-timeout.test.ts +48 -0
  421. package/src/local-llm-helpers.ts +58 -0
  422. package/src/local-llm.ts +62 -58
  423. package/src/orchestration/extraction-run-helpers.ts +309 -0
  424. package/src/orchestration/extraction-run.test.ts +350 -7
  425. package/src/orchestration/extraction-run.ts +327 -250
  426. package/src/orchestration/recall-internal-deps.ts +385 -0
  427. package/src/orchestration/recall-internal.ts +16 -375
  428. package/src/orchestration/session-context.ts +193 -18
  429. package/src/orchestration/turn-ingestion.ts +61 -11
  430. package/src/orchestrator-flush.test.ts +511 -5
  431. package/src/orchestrator.ts +8 -6
  432. package/src/types.ts +2 -2
  433. package/dist/chunk-4A6YGWQN.js.map +0 -1
  434. package/dist/chunk-4WKA6I65.js.map +0 -1
  435. package/dist/chunk-4Z4XNEWZ.js.map +0 -1
  436. package/dist/chunk-6FUPCJUL.js.map +0 -1
  437. package/dist/chunk-B6JDYXL7.js.map +0 -1
  438. package/dist/chunk-GBJ4RDFR.js.map +0 -1
  439. package/dist/chunk-HUHX2OCX.js.map +0 -1
  440. package/dist/chunk-IYZ5K7MU.js.map +0 -1
  441. package/dist/chunk-LGHKJABJ.js.map +0 -1
  442. package/dist/chunk-PHWUFPCO.js.map +0 -1
  443. package/dist/chunk-PUS63Q3G.js.map +0 -1
  444. package/dist/chunk-RPW2NOU6.js.map +0 -1
  445. package/dist/chunk-SPJXKAVF.js.map +0 -1
  446. package/dist/chunk-YTSNAUXN.js.map +0 -1
  447. /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-extraction-force-flush.js.map} +0 -0
  448. /package/dist/{capsule-merge-5KKJQBWQ.js.map → capsule-merge-2H2IUTBT.js.map} +0 -0
  449. /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
  450. /package/dist/{chunk-GIBMDSJ2.js.map → chunk-27P5YVDU.js.map} +0 -0
  451. /package/dist/{chunk-2SA56WMI.js.map → chunk-2LTDWSR6.js.map} +0 -0
  452. /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
  453. /package/dist/{chunk-6U7F52DE.js.map → chunk-4XHR3I67.js.map} +0 -0
  454. /package/dist/{chunk-2EUVEDF5.js.map → chunk-5XA7PQ5I.js.map} +0 -0
  455. /package/dist/{chunk-ALSGMEJR.js.map → chunk-65ZPVYTA.js.map} +0 -0
  456. /package/dist/{chunk-5VQJBH2G.js.map → chunk-6TAUHL33.js.map} +0 -0
  457. /package/dist/{chunk-RGIWINDN.js.map → chunk-7G5MH4NT.js.map} +0 -0
  458. /package/dist/{chunk-WVO4G37W.js.map → chunk-7TEZUUGM.js.map} +0 -0
  459. /package/dist/{chunk-MJCGLM25.js.map → chunk-7VUAG236.js.map} +0 -0
  460. /package/dist/{chunk-M3C2V3PV.js.map → chunk-AJEMDQNA.js.map} +0 -0
  461. /package/dist/{chunk-RKNJBZ55.js.map → chunk-AU7Q3LSC.js.map} +0 -0
  462. /package/dist/{chunk-ACXPX4AG.js.map → chunk-BR2K43MK.js.map} +0 -0
  463. /package/dist/{chunk-CZRYLSSW.js.map → chunk-BUGVGH4N.js.map} +0 -0
  464. /package/dist/{chunk-YTQNQ4KB.js.map → chunk-C4VQMFVM.js.map} +0 -0
  465. /package/dist/{chunk-ZPSVBSOF.js.map → chunk-CIVDJD6P.js.map} +0 -0
  466. /package/dist/{chunk-K5GB36ME.js.map → chunk-CZDOT5I2.js.map} +0 -0
  467. /package/dist/{chunk-VI2JQPNQ.js.map → chunk-E4PWACUN.js.map} +0 -0
  468. /package/dist/{chunk-D2ANTDGO.js.map → chunk-E6BMSH7U.js.map} +0 -0
  469. /package/dist/{chunk-P5PXWTW7.js.map → chunk-EJCAV3QZ.js.map} +0 -0
  470. /package/dist/{chunk-CKMO4RDY.js.map → chunk-EMDLM3LW.js.map} +0 -0
  471. /package/dist/{chunk-G5R3D5UP.js.map → chunk-GTTAHHD3.js.map} +0 -0
  472. /package/dist/{chunk-H5CPS5JP.js.map → chunk-H36LJIPD.js.map} +0 -0
  473. /package/dist/{chunk-AITCS2RC.js.map → chunk-IJ7HK452.js.map} +0 -0
  474. /package/dist/{chunk-D3LMYTBV.js.map → chunk-J7WZUL2K.js.map} +0 -0
  475. /package/dist/{chunk-5W4ZLBEZ.js.map → chunk-JCFTIQBR.js.map} +0 -0
  476. /package/dist/{chunk-XOZ4ALGB.js.map → chunk-KE353EWI.js.map} +0 -0
  477. /package/dist/{chunk-W5EG6LE3.js.map → chunk-KIT6M7EB.js.map} +0 -0
  478. /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
  479. /package/dist/{chunk-Z54EM5YZ.js.map → chunk-MAXVH44E.js.map} +0 -0
  480. /package/dist/{chunk-WZFAPHIK.js.map → chunk-MU7ZHSZE.js.map} +0 -0
  481. /package/dist/{chunk-66772WBP.js.map → chunk-NFXQJHJD.js.map} +0 -0
  482. /package/dist/{chunk-AZ5BTEKX.js.map → chunk-NQUF7XKR.js.map} +0 -0
  483. /package/dist/{chunk-W4FBGYGK.js.map → chunk-NRV4Y3PM.js.map} +0 -0
  484. /package/dist/{chunk-NHWB6HG2.js.map → chunk-NYCGIQRA.js.map} +0 -0
  485. /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
  486. /package/dist/{chunk-FDAMS4PK.js.map → chunk-PNPOWBGC.js.map} +0 -0
  487. /package/dist/{chunk-IC6CBHCA.js.map → chunk-QGENAYVS.js.map} +0 -0
  488. /package/dist/{chunk-62U4J2GN.js.map → chunk-UR77VKF7.js.map} +0 -0
  489. /package/dist/{chunk-JCBWCYEJ.js.map → chunk-VANLTS5F.js.map} +0 -0
  490. /package/dist/{chunk-RMMVQQA6.js.map → chunk-WDISJRMG.js.map} +0 -0
  491. /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
  492. /package/dist/{chunk-TH2LSRMG.js.map → chunk-XHDIB4T4.js.map} +0 -0
  493. /package/dist/{chunk-CVILPI77.js.map → chunk-XOQSEF7X.js.map} +0 -0
  494. /package/dist/{chunk-LBOD4U5B.js.map → chunk-YFOMN2II.js.map} +0 -0
  495. /package/dist/{chunk-I5NLEENJ.js.map → chunk-Z4SWV4VW.js.map} +0 -0
@@ -8,16 +8,10 @@ import {
8
8
  } from "./chunk-GDB4J2H3.js";
9
9
  import {
10
10
  importCapsule
11
- } from "./chunk-ALSGMEJR.js";
11
+ } from "./chunk-65ZPVYTA.js";
12
12
  import {
13
13
  WriteQuarantineStore
14
14
  } from "./chunk-PJSK6OJM.js";
15
- import {
16
- trustResultFor
17
- } from "./chunk-GNVZQ5JN.js";
18
- import {
19
- renderEpistemicHedge
20
- } from "./chunk-YN2UN7N3.js";
21
15
  import {
22
16
  getTrustZoneStoreStatus,
23
17
  isTrustZoneName,
@@ -27,22 +21,28 @@ import {
27
21
  seedTrustZoneDemoDataset,
28
22
  summarizeTrustZonePromotionReadiness
29
23
  } from "./chunk-JGSKJHF7.js";
24
+ import {
25
+ trustResultFor
26
+ } from "./chunk-GNVZQ5JN.js";
27
+ import {
28
+ renderEpistemicHedge
29
+ } from "./chunk-YN2UN7N3.js";
30
30
  import {
31
31
  planSessionTranscriptMigration
32
32
  } from "./chunk-P5FPO2BR.js";
33
- import {
34
- boundRecallContextComposition,
35
- composeRecallContext
36
- } from "./chunk-AHVEHR6K.js";
37
33
  import {
38
34
  decideDisclosureEscalation
39
35
  } from "./chunk-H7XKCNR6.js";
40
36
  import {
41
37
  toRecallExplainJson
42
- } from "./chunk-K5GB36ME.js";
38
+ } from "./chunk-CZDOT5I2.js";
43
39
  import {
44
40
  estimateRecallTokens
45
- } from "./chunk-ACXPX4AG.js";
41
+ } from "./chunk-BR2K43MK.js";
42
+ import {
43
+ boundRecallContextComposition,
44
+ composeRecallContext
45
+ } from "./chunk-AHVEHR6K.js";
46
46
  import {
47
47
  buildProposedActions,
48
48
  buildQualityScore,
@@ -50,10 +50,7 @@ import {
50
50
  listMemoryGovernanceRuns,
51
51
  readMemoryGovernanceRunArtifact,
52
52
  runMemoryGovernance
53
- } from "./chunk-W5EG6LE3.js";
54
- import {
55
- ReplicaDivergenceMonitor
56
- } from "./chunk-CVILPI77.js";
53
+ } from "./chunk-KIT6M7EB.js";
57
54
  import {
58
55
  recordObjectiveStateSnapshotsFromObservedMessages
59
56
  } from "./chunk-ICP53SKG.js";
@@ -62,21 +59,15 @@ import {
62
59
  } from "./chunk-6HMYUWXR.js";
63
60
  import {
64
61
  offlineSyncStorageForSnapshot
65
- } from "./chunk-WVO4G37W.js";
62
+ } from "./chunk-7TEZUUGM.js";
66
63
  import {
67
- combineNamespaces,
68
- defaultGitInvoker,
69
- expandScopeProfileReadNamespaces,
70
- lcmSessionKeyForNamespace,
71
- projectTagProjectId,
72
- resolveCodingNamespaceOverlay,
73
- resolveGitContext,
74
64
  resolveScopePlan,
75
- resolveScopeProfilePlan,
76
65
  resolveScopedWritableNamespaceValue,
77
- resolveWritableNamespaceValue,
78
- sanitizeFragment
79
- } from "./chunk-IYZ5K7MU.js";
66
+ resolveWritableNamespaceValue
67
+ } from "./chunk-ULARSG5Z.js";
68
+ import {
69
+ ReplicaDivergenceMonitor
70
+ } from "./chunk-XOQSEF7X.js";
80
71
  import {
81
72
  recordMemoryOutcome
82
73
  } from "./chunk-EIR5VLIH.js";
@@ -104,34 +95,55 @@ import {
104
95
  import {
105
96
  CorpusWatermarkCache,
106
97
  computeServiceCorpusCensus
107
- } from "./chunk-GIBMDSJ2.js";
98
+ } from "./chunk-27P5YVDU.js";
108
99
  import {
109
100
  namespaceCollectionName
110
- } from "./chunk-D2ANTDGO.js";
101
+ } from "./chunk-E6BMSH7U.js";
111
102
  import {
112
103
  CrossNamespaceBudget,
113
104
  toBudgetWarning
114
105
  } from "./chunk-UFGFMWAD.js";
106
+ import {
107
+ ExtractionDeadlineError
108
+ } from "./chunk-YPC7W6GA.js";
109
+ import {
110
+ combineNamespaces,
111
+ defaultGitInvoker,
112
+ expandScopeProfileReadNamespaces,
113
+ lcmSessionKeyForNamespace,
114
+ projectTagProjectId,
115
+ resolveCodingNamespaceOverlay,
116
+ resolveGitContext,
117
+ resolveScopeProfilePlan,
118
+ sanitizeFragment
119
+ } from "./chunk-BUE5E2HL.js";
120
+ import {
121
+ defaultCapsulesDir
122
+ } from "./chunk-ZY2MNJR6.js";
123
+ import {
124
+ filterTrajectoriesByLookbackDays,
125
+ readCausalTrajectoryRecords
126
+ } from "./chunk-NRV4Y3PM.js";
115
127
  import {
116
128
  FileCalendarSource,
117
129
  buildBriefing,
118
130
  enqueuePassiveCorrectionNotification,
119
131
  parseBriefingFocus,
120
132
  parseBriefingWindow
121
- } from "./chunk-CZRYLSSW.js";
133
+ } from "./chunk-BUGVGH4N.js";
122
134
  import {
123
135
  parseEntityFile,
124
136
  qmdCollectionPathParts,
125
137
  qmdResultPathCandidates,
126
138
  selfDeps
127
- } from "./chunk-RGIWINDN.js";
139
+ } from "./chunk-7G5MH4NT.js";
128
140
  import {
129
141
  supersessionKeysForFact
130
142
  } from "./chunk-DNHVPZOD.js";
131
143
  import {
132
144
  DEFAULT_RECALL_DISCLOSURE,
133
145
  isRecallDisclosure
134
- } from "./chunk-HUHX2OCX.js";
146
+ } from "./chunk-7DRETLP5.js";
135
147
  import {
136
148
  namespaceIdentityFromToken
137
149
  } from "./chunk-EGGE52UU.js";
@@ -169,17 +181,27 @@ import {
169
181
  } from "./chunk-BT7NVCML.js";
170
182
  import {
171
183
  createVersion
172
- } from "./chunk-5VQJBH2G.js";
184
+ } from "./chunk-6TAUHL33.js";
173
185
  import {
174
186
  computeContentHash
175
187
  } from "./chunk-W5H6ZRPT.js";
176
188
  import {
177
- defaultCapsulesDir
178
- } from "./chunk-ZY2MNJR6.js";
189
+ assertOperationAuthorizationAllowed,
190
+ capabilityAllowsOp,
191
+ enforceNamespaceAllowList,
192
+ isNamespaceAllowed,
193
+ tokenCapabilityStore
194
+ } from "./chunk-MZWSOLMT.js";
179
195
  import {
180
- filterTrajectoriesByLookbackDays,
181
- readCausalTrajectoryRecords
182
- } from "./chunk-W4FBGYGK.js";
196
+ meetingsBuild,
197
+ meetingsGet,
198
+ meetingsList,
199
+ wearablesStatus,
200
+ wearablesSync,
201
+ wearablesTranscriptDay,
202
+ wearablesTranscriptMemories,
203
+ wearablesTranscriptSearch
204
+ } from "./chunk-SYOIVK7K.js";
183
205
  import {
184
206
  ExtractionLivenessWarnThrottle,
185
207
  computeExtractionLivenessStatus
@@ -196,7 +218,7 @@ import {
196
218
  } from "./chunk-JAKIDQB2.js";
197
219
  import {
198
220
  exportCapsule
199
- } from "./chunk-5W7CTZ2E.js";
221
+ } from "./chunk-KQAFEZQX.js";
200
222
  import {
201
223
  evaluateActionConfidence
202
224
  } from "./chunk-Z2YFLXHU.js";
@@ -212,22 +234,8 @@ import {
212
234
  readOfflineSyncFileContentChunk
213
235
  } from "./chunk-7XC2HX75.js";
214
236
  import {
215
- assertOperationAuthorizationAllowed,
216
- capabilityAllowsOp,
217
- enforceNamespaceAllowList,
218
- isNamespaceAllowed,
219
- tokenCapabilityStore
220
- } from "./chunk-MZWSOLMT.js";
221
- import {
222
- meetingsBuild,
223
- meetingsGet,
224
- meetingsList,
225
- wearablesStatus,
226
- wearablesSync,
227
- wearablesTranscriptDay,
228
- wearablesTranscriptMemories,
229
- wearablesTranscriptSearch
230
- } from "./chunk-SYOIVK7K.js";
237
+ delegateExtractionForceFlush
238
+ } from "./chunk-3QL24R5Y.js";
231
239
  import {
232
240
  defaultNamespaceAtFlatRoot,
233
241
  mergeMemorySearchDefaultFallback,
@@ -257,6 +265,10 @@ import {
257
265
  resolveRecallEnhancementCapabilities,
258
266
  resolveSecurityCapabilities
259
267
  } from "./chunk-2XRE6FLM.js";
268
+ import {
269
+ PendingObserveExtractionTracker,
270
+ pendingObserveScopeHint
271
+ } from "./chunk-N5Z4EVOR.js";
260
272
  import {
261
273
  EngramAccessForbiddenError,
262
274
  EngramAccessInputError,
@@ -268,6 +280,7 @@ import {
268
280
  } from "./chunk-VFUEZZBS.js";
269
281
  import {
270
282
  abortError,
283
+ isAbortError,
271
284
  throwIfAborted
272
285
  } from "./chunk-PVGDJXVK.js";
273
286
  import {
@@ -2853,7 +2866,9 @@ var CorrectionPlanner = class _CorrectionPlanner {
2853
2866
  * Plan a correction. `readableNamespaces` is the AUTHORIZED read scope the
2854
2867
  * service resolved for this caller; the planner never trusts a caller string.
2855
2868
  */
2856
- async plan(request, readableNamespaces) {
2869
+ async plan(request, readableNamespaces, opts) {
2870
+ const abortSignal = opts?.abortSignal;
2871
+ throwIfAborted(abortSignal, "correction planning aborted");
2857
2872
  const cleaned = validateCorrectionRequest(request);
2858
2873
  if (cleaned.text.length > CORRECTION_TEXT_MAX) {
2859
2874
  throw new CorrectionContractError("CorrectionRequest.text too long.");
@@ -2869,16 +2884,19 @@ var CorrectionPlanner = class _CorrectionPlanner {
2869
2884
  "Correction requires at least one readable namespace \u2014 principal has no read scope."
2870
2885
  );
2871
2886
  }
2872
- const located = await this.locateCandidates(cleaned, namespaces);
2887
+ const located = await this.locateCandidates(cleaned, namespaces, abortSignal);
2888
+ throwIfAborted(abortSignal, "correction planning aborted");
2873
2889
  if (located.candidates.length === 0) {
2874
2890
  return this.persist(
2875
- this.emptyPlan(cleaned, namespaces[0], "no matching memories found for the correction text")
2891
+ this.emptyPlan(cleaned, namespaces[0], "no matching memories found for the correction text"),
2892
+ abortSignal
2876
2893
  );
2877
2894
  }
2878
2895
  const llm = await this.deps.classifyAndDraft({
2879
2896
  text: cleaned.text,
2880
2897
  candidates: located.candidates
2881
2898
  });
2899
+ throwIfAborted(abortSignal, "correction planning aborted");
2882
2900
  for (const action of llm.actions) {
2883
2901
  validateCorrectionAction(action);
2884
2902
  if (action.kind === "redaction_rule") {
@@ -2909,6 +2927,7 @@ var CorrectionPlanner = class _CorrectionPlanner {
2909
2927
  }
2910
2928
  }
2911
2929
  const diff = llm.fallback ? "" : await this.deps.renderDiff({ candidates: located.candidates, actions: llm.actions });
2930
+ throwIfAborted(abortSignal, "correction planning aborted");
2912
2931
  const createdAt = this.deps.now().toISOString();
2913
2932
  const expiresAt = new Date(
2914
2933
  this.deps.now().getTime() + this.deps.planTtlHours * 60 * 60 * 1e3
@@ -2934,20 +2953,23 @@ var CorrectionPlanner = class _CorrectionPlanner {
2934
2953
  expiresAt,
2935
2954
  status: "pending"
2936
2955
  };
2937
- return this.persist(plan);
2956
+ throwIfAborted(abortSignal, "correction planning aborted");
2957
+ return this.persist(plan, abortSignal);
2938
2958
  }
2939
- async locateCandidates(request, namespaces) {
2959
+ async locateCandidates(request, namespaces, abortSignal) {
2940
2960
  if (request.targetIds && request.targetIds.length > 0) {
2941
2961
  const targets = await this.deps.resolveTargets({
2942
2962
  targetIds: request.targetIds,
2943
2963
  namespaces
2944
2964
  });
2965
+ throwIfAborted(abortSignal, "correction planning aborted");
2945
2966
  const seedIds2 = targets.map((c) => c.memoryId);
2946
2967
  const neighbors2 = await this.deps.expandNeighbors({
2947
2968
  seedIds: seedIds2,
2948
2969
  namespaces,
2949
2970
  limit: this.deps.maxAffected
2950
2971
  });
2972
+ throwIfAborted(abortSignal, "correction planning aborted");
2951
2973
  return { candidates: mergeCandidates(targets, neighbors2).slice(0, this.deps.maxAffected) };
2952
2974
  }
2953
2975
  const searched = await this.deps.searchCorpus({
@@ -2955,6 +2977,7 @@ var CorrectionPlanner = class _CorrectionPlanner {
2955
2977
  namespaces,
2956
2978
  limit: this.deps.maxAffected
2957
2979
  });
2980
+ throwIfAborted(abortSignal, "correction planning aborted");
2958
2981
  if (searched.length === 0) return { candidates: [] };
2959
2982
  const seedIds = searched.slice(0, Math.min(5, searched.length)).map((c) => c.memoryId);
2960
2983
  const neighbors = await this.deps.expandNeighbors({
@@ -2962,6 +2985,7 @@ var CorrectionPlanner = class _CorrectionPlanner {
2962
2985
  namespaces,
2963
2986
  limit: this.deps.maxAffected
2964
2987
  });
2988
+ throwIfAborted(abortSignal, "correction planning aborted");
2965
2989
  return { candidates: mergeCandidates(searched, neighbors).slice(0, this.deps.maxAffected) };
2966
2990
  }
2967
2991
  deriveAffected(candidates, llm) {
@@ -3024,16 +3048,21 @@ var CorrectionPlanner = class _CorrectionPlanner {
3024
3048
  async pendingDir(namespace) {
3025
3049
  return path4.join(await this.deps.storageDir(namespace), "state", "corrections", "pending");
3026
3050
  }
3027
- async persist(plan) {
3051
+ async persist(plan, abortSignal) {
3052
+ throwIfAborted(abortSignal, "correction planning aborted");
3028
3053
  const dir = await this.pendingDir(plan.namespace);
3054
+ throwIfAborted(abortSignal, "correction planning aborted");
3029
3055
  const target = path4.join(dir, `${plan.planId}.json`);
3030
3056
  const sensitive = plan.classification === "never_store" || plan.actions.some((a) => a.kind === "redaction_rule");
3031
3057
  const persistedPlan = sensitive ? { ...plan, request: { ...plan.request, text: REDACTED_REQUEST_TEXT } } : plan;
3032
3058
  await serializeMutations(`correction-plan:${target}`, async () => {
3059
+ throwIfAborted(abortSignal, "correction planning aborted");
3033
3060
  await mkdir2(dir, { recursive: true });
3034
3061
  const tmp = `${target}.${process.pid}.${Date.now().toString(36)}.tmp`;
3062
+ throwIfAborted(abortSignal, "correction planning aborted");
3035
3063
  await writeFile2(tmp, `${JSON.stringify(persistedPlan)}
3036
3064
  `, "utf-8");
3065
+ throwIfAborted(abortSignal, "correction planning aborted");
3037
3066
  await rename2(tmp, target);
3038
3067
  });
3039
3068
  return plan;
@@ -3106,6 +3135,32 @@ var CorrectionPlanner = class _CorrectionPlanner {
3106
3135
  }
3107
3136
  const tmp = `${file}.${process.pid}.${Date.now().toString(36)}.tmp`;
3108
3137
  await writeFile2(tmp, `${JSON.stringify(plan)}
3138
+ `, "utf-8");
3139
+ await rename2(tmp, file);
3140
+ });
3141
+ }
3142
+ /**
3143
+ * Return an applying plan to the pending queue when cancellation arrives
3144
+ * before its first correction mutation.
3145
+ */
3146
+ async resetApplying(namespace, planId) {
3147
+ assertSafePlanId(planId);
3148
+ const file = path4.join(await this.pendingDir(namespace), `${planId}.json`);
3149
+ await serializeMutations(`correction-plan:${file}`, async () => {
3150
+ let raw;
3151
+ try {
3152
+ raw = await readFile4(file, "utf-8");
3153
+ } catch (err) {
3154
+ const code = err?.code;
3155
+ if (code === "ENOENT") return;
3156
+ throw err;
3157
+ }
3158
+ const plan = parsePlan(raw);
3159
+ if (!plan || plan.status !== "applying") return;
3160
+ plan.status = "pending";
3161
+ delete plan.applyingAt;
3162
+ const tmp = `${file}.${process.pid}.${Date.now().toString(36)}.tmp`;
3163
+ await writeFile2(tmp, `${JSON.stringify(plan)}
3109
3164
  `, "utf-8");
3110
3165
  await rename2(tmp, file);
3111
3166
  });
@@ -3234,6 +3289,7 @@ var CorrectionExecutor = class {
3234
3289
  * plan is rejected. Returns the {@link CorrectionOutcome}.
3235
3290
  */
3236
3291
  async apply(namespace, planId, opts) {
3292
+ throwIfAborted(opts.abortSignal, "correction apply aborted");
3237
3293
  if (!opts.confirm) {
3238
3294
  throw new CorrectionContractError(
3239
3295
  "Correction apply requires explicit confirmation (correction.applyRequiresConfirm)."
@@ -3241,11 +3297,13 @@ var CorrectionExecutor = class {
3241
3297
  }
3242
3298
  return serializeMutations(
3243
3299
  `correction-apply:${namespace}:${planId}`,
3244
- () => this.applyInternal(namespace, planId, opts.canWriteDestination)
3300
+ () => this.applyInternal(namespace, planId, opts.canWriteDestination, opts.abortSignal)
3245
3301
  );
3246
3302
  }
3247
- async applyInternal(namespace, planId, canWriteDestination) {
3303
+ async applyInternal(namespace, planId, canWriteDestination, abortSignal) {
3304
+ throwIfAborted(abortSignal, "correction apply aborted");
3248
3305
  const plan = await this.planner.loadPlan(namespace, planId);
3306
+ throwIfAborted(abortSignal, "correction apply aborted");
3249
3307
  if (!plan) {
3250
3308
  throw new CorrectionContractError(`Correction plan not found: ${planId}`);
3251
3309
  }
@@ -3274,6 +3332,7 @@ var CorrectionExecutor = class {
3274
3332
  validateRedactionPattern(action.pattern);
3275
3333
  }
3276
3334
  }
3335
+ throwIfAborted(abortSignal, "correction apply aborted");
3277
3336
  try {
3278
3337
  await this.planner.markConsumed(namespace, planId, "applying");
3279
3338
  } catch {
@@ -3281,11 +3340,79 @@ var CorrectionExecutor = class {
3281
3340
  `Correction plan ${planId}: cannot mark in-progress (filesystem unwritable?) \u2014 aborting before any mutation.`
3282
3341
  );
3283
3342
  }
3343
+ const resetApplying = async () => {
3344
+ try {
3345
+ await this.planner.resetApplying(namespace, planId);
3346
+ } catch (resetError) {
3347
+ log.warn(
3348
+ `Correction plan ${planId}: cancellation reset failed; leaving plan applying: ${resetError instanceof Error ? resetError.message : String(resetError)}`
3349
+ );
3350
+ }
3351
+ };
3352
+ try {
3353
+ throwIfAborted(abortSignal, "correction apply aborted");
3354
+ } catch (error) {
3355
+ await resetApplying();
3356
+ throw error;
3357
+ }
3284
3358
  const results = [];
3285
3359
  const appliedTouched = [];
3360
+ const retiredReplacementActions = /* @__PURE__ */ new Set();
3361
+ const removeFailedResultsFor = (action) => {
3362
+ for (let i = results.length - 1; i >= 0; i -= 1) {
3363
+ if (results[i]?.action === action && results[i]?.status === "failed") {
3364
+ results.splice(i, 1);
3365
+ }
3366
+ }
3367
+ };
3368
+ let mutationCommitted = false;
3369
+ let cancellationSafeAfterCommit = false;
3370
+ let cancellationRequestedAfterCommit = false;
3371
+ const throwIfAbortedBeforeCommit = () => {
3372
+ if (!mutationCommitted || !cancellationSafeAfterCommit) {
3373
+ throwIfAborted(abortSignal, "correction apply aborted");
3374
+ }
3375
+ };
3376
+ const stopBeforeNewAction = async () => {
3377
+ if (!abortSignal?.aborted) return false;
3378
+ if (!mutationCommitted) {
3379
+ try {
3380
+ throwIfAborted(abortSignal, "correction apply aborted");
3381
+ } catch (error) {
3382
+ await resetApplying();
3383
+ throw error;
3384
+ }
3385
+ }
3386
+ cancellationRequestedAfterCommit = true;
3387
+ return true;
3388
+ };
3389
+ const throwIfAbortedBeforeCommitAndReset = async () => {
3390
+ try {
3391
+ throwIfAbortedBeforeCommit();
3392
+ } catch (error) {
3393
+ if (!mutationCommitted) await resetApplying();
3394
+ const reason = abortSignal?.reason;
3395
+ if (reason instanceof Error && reason.name !== "AbortError") throw reason;
3396
+ throw error;
3397
+ }
3398
+ };
3286
3399
  for (const action of plan.actions) {
3400
+ if (await stopBeforeNewAction()) break;
3287
3401
  if (action.kind === "supersede" && action.replacement) {
3288
- const loser = await this.deps.getMemory(namespace, action.loserId);
3402
+ let loser;
3403
+ try {
3404
+ loser = await this.deps.getMemory(namespace, action.loserId, abortSignal);
3405
+ } catch (error) {
3406
+ if (abortSignal?.aborted) {
3407
+ if (!mutationCommitted) {
3408
+ await resetApplying();
3409
+ throwIfAborted(abortSignal, "correction apply aborted");
3410
+ }
3411
+ cancellationRequestedAfterCommit = true;
3412
+ break;
3413
+ }
3414
+ throw error;
3415
+ }
3289
3416
  if (!loser) {
3290
3417
  results.push({
3291
3418
  action,
@@ -3295,20 +3422,42 @@ var CorrectionExecutor = class {
3295
3422
  continue;
3296
3423
  }
3297
3424
  try {
3298
- const newId = await this.deps.writeReplacement(namespace, {
3299
- content: action.replacement.content,
3300
- ...action.replacement.category ? { category: action.replacement.category } : {},
3301
- ...action.replacement.confidence !== void 0 ? { confidence: action.replacement.confidence } : {},
3302
- ...action.replacement.tags ? { tags: action.replacement.tags } : {},
3303
- ...action.replacement.entityRef ? { entityRef: action.replacement.entityRef } : {},
3304
- ...action.replacement.validAt ? { validAt: action.replacement.validAt } : {},
3305
- ...action.replacement.observedAt ? { observedAt: action.replacement.observedAt } : {},
3306
- ...action.replacement.structuredAttributes ? { structuredAttributes: action.replacement.structuredAttributes } : {},
3307
- supersedes: action.loserId
3308
- });
3425
+ const newId = await this.deps.writeReplacement(
3426
+ namespace,
3427
+ {
3428
+ content: action.replacement.content,
3429
+ ...action.replacement.category ? { category: action.replacement.category } : {},
3430
+ ...action.replacement.confidence !== void 0 ? { confidence: action.replacement.confidence } : {},
3431
+ ...action.replacement.tags ? { tags: action.replacement.tags } : {},
3432
+ ...action.replacement.entityRef ? { entityRef: action.replacement.entityRef } : {},
3433
+ ...action.replacement.validAt ? { validAt: action.replacement.validAt } : {},
3434
+ ...action.replacement.observedAt ? { observedAt: action.replacement.observedAt } : {},
3435
+ ...action.replacement.structuredAttributes ? { structuredAttributes: action.replacement.structuredAttributes } : {},
3436
+ supersedes: action.loserId
3437
+ },
3438
+ abortSignal
3439
+ );
3440
+ mutationCommitted = true;
3309
3441
  results.push({ action, status: "applied", memoryId: newId });
3310
3442
  appliedTouched.push(newId);
3443
+ const retirementResultBeforePhase2 = results.at(-1);
3444
+ await this.retireAndTombstone(namespace, action, "supersession", results, appliedTouched, {
3445
+ supersededBy: newId
3446
+ });
3447
+ const retirementResult = results.at(-1);
3448
+ if (retirementResult !== retirementResultBeforePhase2 && retirementResult?.action === action && retirementResult.status === "applied") {
3449
+ retiredReplacementActions.add(action);
3450
+ cancellationSafeAfterCommit = true;
3451
+ }
3311
3452
  } catch (err) {
3453
+ if (abortSignal?.aborted) {
3454
+ if (!mutationCommitted) {
3455
+ await resetApplying();
3456
+ throw err;
3457
+ }
3458
+ cancellationRequestedAfterCommit = true;
3459
+ break;
3460
+ }
3312
3461
  results.push({
3313
3462
  action,
3314
3463
  status: "failed",
@@ -3317,67 +3466,152 @@ var CorrectionExecutor = class {
3317
3466
  }
3318
3467
  } else if (action.kind === "edit") {
3319
3468
  try {
3320
- const editedId = await this.deps.applyEdit(namespace, action.memoryId, action.patch);
3469
+ const editedId = await this.deps.applyEdit(
3470
+ namespace,
3471
+ action.memoryId,
3472
+ action.patch,
3473
+ abortSignal
3474
+ );
3475
+ mutationCommitted = true;
3476
+ cancellationSafeAfterCommit = true;
3321
3477
  results.push({ action, status: "applied", memoryId: editedId });
3322
3478
  appliedTouched.push(editedId);
3323
3479
  } catch (err) {
3480
+ if (abortSignal?.aborted) {
3481
+ if (!mutationCommitted) {
3482
+ await resetApplying();
3483
+ throw err;
3484
+ }
3485
+ cancellationRequestedAfterCommit = true;
3486
+ break;
3487
+ }
3324
3488
  results.push({ action, status: "failed", error: errMsg(err) });
3325
3489
  }
3326
3490
  } else if (action.kind === "redaction_rule") {
3327
3491
  try {
3328
- await this.deps.registerRedactionRule(namespace, action.pattern);
3492
+ await this.deps.registerRedactionRule(
3493
+ namespace,
3494
+ action.pattern,
3495
+ abortSignal
3496
+ );
3497
+ mutationCommitted = true;
3498
+ cancellationSafeAfterCommit = true;
3329
3499
  results.push({ action, status: "applied" });
3330
3500
  } catch (err) {
3501
+ if (abortSignal?.aborted) {
3502
+ if (!mutationCommitted) {
3503
+ await resetApplying();
3504
+ throw err;
3505
+ }
3506
+ cancellationRequestedAfterCommit = true;
3507
+ break;
3508
+ }
3331
3509
  results.push({ action, status: "failed", error: errMsg(err) });
3332
3510
  }
3333
3511
  }
3334
3512
  }
3335
3513
  for (const action of plan.actions) {
3336
- if (action.kind === "supersede") {
3337
- const replacementResult = results.find(
3338
- (r) => r.action === action && r.status === "applied"
3339
- );
3340
- if (action.replacement && !replacementResult) {
3341
- continue;
3342
- }
3343
- await this.retireAndTombstone(namespace, action, "supersession", results, appliedTouched, {
3344
- supersededBy: replacementResult?.memoryId
3345
- });
3346
- } else if (action.kind === "retract") {
3347
- await this.retireAndTombstone(namespace, action, "retraction", results, appliedTouched);
3348
- } else if (action.kind === "rescope") {
3349
- try {
3350
- const allowed = canWriteDestination ? await canWriteDestination(action.toNamespace) : true;
3351
- if (!allowed) {
3352
- results.push({
3353
- action,
3354
- status: "failed",
3355
- error: `rescope destination namespace not writable: ${action.toNamespace}`
3356
- });
3514
+ const needsPhase2Work = action.kind === "retract" || action.kind === "rescope" || action.kind === "supersede" && !retiredReplacementActions.has(action);
3515
+ if (needsPhase2Work && await stopBeforeNewAction()) break;
3516
+ try {
3517
+ if (action.kind === "supersede" && retiredReplacementActions.has(action)) continue;
3518
+ if (action.kind === "supersede") {
3519
+ const replacementResult = results.find((r) => r.action === action && r.status === "applied");
3520
+ if (action.replacement && !replacementResult) {
3357
3521
  continue;
3358
3522
  }
3359
- const destId = await this.deps.rescopeMemory(namespace, action.memoryId, action.toNamespace);
3360
- results.push({ action, status: "applied", memoryId: destId });
3361
- appliedTouched.push(action.memoryId);
3523
+ await this.retireAndTombstone(
3524
+ namespace,
3525
+ action,
3526
+ "supersession",
3527
+ results,
3528
+ appliedTouched,
3529
+ { supersededBy: replacementResult?.memoryId },
3530
+ abortSignal
3531
+ );
3532
+ if (results.at(-1)?.status === "applied") {
3533
+ mutationCommitted = true;
3534
+ cancellationSafeAfterCommit = true;
3535
+ }
3536
+ if (results.at(-1)?.action === action && results.at(-1)?.status === "applied") {
3537
+ removeFailedResultsFor(action);
3538
+ }
3539
+ } else if (action.kind === "retract") {
3540
+ await this.retireAndTombstone(
3541
+ namespace,
3542
+ action,
3543
+ "retraction",
3544
+ results,
3545
+ appliedTouched,
3546
+ {},
3547
+ abortSignal
3548
+ );
3549
+ if (results.at(-1)?.status === "applied") {
3550
+ mutationCommitted = true;
3551
+ cancellationSafeAfterCommit = true;
3552
+ }
3553
+ if (results.at(-1)?.action === action && results.at(-1)?.status === "applied") {
3554
+ removeFailedResultsFor(action);
3555
+ }
3556
+ } else if (action.kind === "rescope") {
3362
3557
  try {
3363
- await this.deps.propagate(action.toNamespace, [destId]);
3364
- } catch {
3558
+ const allowed = canWriteDestination ? await canWriteDestination(action.toNamespace) : true;
3559
+ if (!allowed) {
3560
+ results.push({
3561
+ action,
3562
+ status: "failed",
3563
+ error: `rescope destination namespace not writable: ${action.toNamespace}`
3564
+ });
3565
+ continue;
3566
+ }
3567
+ const destId = await this.deps.rescopeMemory(
3568
+ namespace,
3569
+ action.memoryId,
3570
+ action.toNamespace,
3571
+ abortSignal
3572
+ );
3573
+ mutationCommitted = true;
3574
+ cancellationSafeAfterCommit = true;
3575
+ results.push({ action, status: "applied", memoryId: destId });
3576
+ appliedTouched.push(action.memoryId);
3577
+ try {
3578
+ await this.deps.propagate(action.toNamespace, [destId], void 0);
3579
+ } catch {
3580
+ }
3581
+ } catch (err) {
3582
+ if (abortSignal?.aborted) {
3583
+ if (!mutationCommitted) throw err;
3584
+ cancellationRequestedAfterCommit = true;
3585
+ break;
3586
+ }
3587
+ results.push({ action, status: "failed", error: errMsg(err) });
3365
3588
  }
3366
- } catch (err) {
3367
- results.push({ action, status: "failed", error: errMsg(err) });
3368
3589
  }
3590
+ } catch (err) {
3591
+ if (abortSignal?.aborted) {
3592
+ if (!mutationCommitted) {
3593
+ await resetApplying();
3594
+ throw err;
3595
+ }
3596
+ cancellationRequestedAfterCommit = true;
3597
+ break;
3598
+ }
3599
+ throw err;
3369
3600
  }
3370
3601
  }
3602
+ await throwIfAbortedBeforeCommitAndReset();
3371
3603
  const propagationWarnings = [];
3372
3604
  if (appliedTouched.length > 0) {
3373
3605
  try {
3374
- await this.deps.propagate(namespace, appliedTouched);
3606
+ await this.deps.propagate(namespace, appliedTouched, cancellationSafeAfterCommit ? void 0 : abortSignal);
3375
3607
  } catch (err) {
3608
+ if ((!mutationCommitted || !cancellationSafeAfterCommit) && abortSignal?.aborted) throw err;
3376
3609
  propagationWarnings.push(`propagation failed (non-fatal): ${errMsg(err)}`);
3377
3610
  }
3378
3611
  }
3612
+ await throwIfAbortedBeforeCommitAndReset();
3379
3613
  const anyFailed = results.some((r) => r.status === "failed");
3380
- const status = anyFailed ? "partial" : "applied";
3614
+ const status = anyFailed || cancellationRequestedAfterCommit ? "partial" : "applied";
3381
3615
  const appliedAt = this.deps.now().toISOString();
3382
3616
  const outcome = {
3383
3617
  planId,
@@ -3391,19 +3625,25 @@ var CorrectionExecutor = class {
3391
3625
  outcome.warnings = propagationWarnings;
3392
3626
  }
3393
3627
  try {
3394
- const auditId = await this.deps.appendAuditRecord(namespace, {
3395
- planId,
3396
- classification: plan.classification,
3397
- outcome,
3398
- requestText: plan.request.text
3399
- });
3628
+ const auditId = await this.deps.appendAuditRecord(
3629
+ namespace,
3630
+ {
3631
+ planId,
3632
+ classification: plan.classification,
3633
+ outcome,
3634
+ requestText: plan.request.text
3635
+ },
3636
+ cancellationSafeAfterCommit ? void 0 : abortSignal
3637
+ );
3400
3638
  outcome.auditMemoryId = auditId;
3401
3639
  } catch (err) {
3640
+ if ((!mutationCommitted || !cancellationSafeAfterCommit) && abortSignal?.aborted) throw err;
3402
3641
  outcome.warnings = [
3403
3642
  ...propagationWarnings,
3404
3643
  `audit record write failed (non-fatal): ${errMsg(err)}`
3405
3644
  ];
3406
3645
  }
3646
+ await throwIfAbortedBeforeCommitAndReset();
3407
3647
  try {
3408
3648
  await this.planner.markConsumed(namespace, planId, status);
3409
3649
  } catch (err) {
@@ -3412,11 +3652,11 @@ var CorrectionExecutor = class {
3412
3652
  }
3413
3653
  return outcome;
3414
3654
  }
3415
- async retireAndTombstone(namespace, action, reason, results, appliedTouched, opts = {}) {
3655
+ async retireAndTombstone(namespace, action, reason, results, appliedTouched, opts = {}, abortSignal) {
3416
3656
  const memoryId = action.kind === "supersede" ? action.loserId : action.kind === "retract" ? action.memoryId : null;
3417
3657
  if (!memoryId) return;
3418
3658
  try {
3419
- const memory = await this.deps.getMemory(namespace, memoryId);
3659
+ const memory = await this.deps.getMemory(namespace, memoryId, abortSignal);
3420
3660
  if (!memory) {
3421
3661
  results.push({
3422
3662
  action,
@@ -3426,25 +3666,34 @@ var CorrectionExecutor = class {
3426
3666
  return;
3427
3667
  }
3428
3668
  const validUntil = this.deps.biTemporalEnabled ? this.deps.now().toISOString() : void 0;
3429
- const tombstoneId = await this.deps.appendTombstone(namespace, {
3430
- reason,
3431
- sourceMemoryId: memoryId,
3432
- rawContent: memory.rawContent,
3433
- ...memory.entityRef ? { entityRef: memory.entityRef } : {},
3434
- ...memory.supersessionKey ? { supersessionKey: memory.supersessionKey } : {},
3435
- // #1672 item 4: carry the canonical contentHash (exact tier) and the
3436
- // full supersession-key set (keyed tier) so paraphrased re-observations
3437
- // of the same supersession identity are blocked, not just the literal
3438
- // body. Without these the tombstone projected from a structured fact
3439
- // dropped both fields and the fact could resurrect.
3440
- ...memory.contentHash ? { contentHash: memory.contentHash } : {},
3441
- ...memory.supersessionKeys && memory.supersessionKeys.length > 0 ? { supersessionKeys: memory.supersessionKeys } : {}
3442
- });
3443
- await this.deps.retireMemory(namespace, memoryId, {
3444
- status: reason === "supersession" ? "superseded" : "retracted",
3445
- ...opts.supersededBy ? { supersededBy: opts.supersededBy } : {},
3446
- ...validUntil ? { validUntil } : {}
3447
- });
3669
+ const tombstoneId = await this.deps.appendTombstone(
3670
+ namespace,
3671
+ {
3672
+ reason,
3673
+ sourceMemoryId: memoryId,
3674
+ rawContent: memory.rawContent,
3675
+ ...memory.entityRef ? { entityRef: memory.entityRef } : {},
3676
+ ...memory.supersessionKey ? { supersessionKey: memory.supersessionKey } : {},
3677
+ // #1672 item 4: carry the canonical contentHash (exact tier) and the
3678
+ // full supersession-key set (keyed tier) so paraphrased re-observations
3679
+ // of the same supersession identity are blocked, not just the literal
3680
+ // body. Without these the tombstone projected from a structured fact
3681
+ // dropped both fields and the fact could resurrect.
3682
+ ...memory.contentHash ? { contentHash: memory.contentHash } : {},
3683
+ ...memory.supersessionKeys && memory.supersessionKeys.length > 0 ? { supersessionKeys: memory.supersessionKeys } : {}
3684
+ },
3685
+ abortSignal
3686
+ );
3687
+ await this.deps.retireMemory(
3688
+ namespace,
3689
+ memoryId,
3690
+ {
3691
+ status: reason === "supersession" ? "superseded" : "retracted",
3692
+ ...opts.supersededBy ? { supersededBy: opts.supersededBy } : {},
3693
+ ...validUntil ? { validUntil } : {}
3694
+ },
3695
+ tombstoneId === null ? abortSignal : void 0
3696
+ );
3448
3697
  results.push({
3449
3698
  action,
3450
3699
  status: "applied",
@@ -3453,6 +3702,7 @@ var CorrectionExecutor = class {
3453
3702
  });
3454
3703
  appliedTouched.push(memoryId);
3455
3704
  } catch (err) {
3705
+ if (abortSignal?.aborted) throw err;
3456
3706
  results.push({ action, status: "failed", error: errMsg(err) });
3457
3707
  }
3458
3708
  }
@@ -3490,17 +3740,16 @@ var CorrectionService = class {
3490
3740
  * the principal can write, so reading from a non-writable namespace to
3491
3741
  * draft a correction that can never be applied would be misleading.
3492
3742
  */
3493
- async plan(request) {
3743
+ async plan(request, opts) {
3494
3744
  this.requireEnabled();
3745
+ throwIfAborted(opts?.abortSignal, "correction planning aborted");
3495
3746
  const authorized = await this.deps.policy.resolveAuthorizedNamespace(request);
3496
- return this.planner.plan(request, [authorized]);
3747
+ throwIfAborted(opts?.abortSignal, "correction planning aborted");
3748
+ return this.planner.plan(request, [authorized], opts);
3497
3749
  }
3498
- /**
3499
- * Apply a persisted plan by id. Requires `confirm: true` (or interactive
3500
- * yes at the CLI) when `applyRequiresConfirm` is on (default).
3501
- */
3502
3750
  async apply(planId, opts) {
3503
3751
  this.requireEnabled();
3752
+ throwIfAborted(opts.abortSignal, "correction apply aborted");
3504
3753
  if (this.deps.applyRequiresConfirm() && opts.confirm !== true) {
3505
3754
  throw new CorrectionContractError(
3506
3755
  "Correction apply requires explicit confirmation (pass `confirm: true`)."
@@ -3511,8 +3760,10 @@ var CorrectionService = class {
3511
3760
  ...opts.sessionKey ? { sessionKey: opts.sessionKey } : {},
3512
3761
  ...opts.principal ? { principal: opts.principal } : {}
3513
3762
  });
3763
+ throwIfAborted(opts.abortSignal, "correction apply aborted");
3514
3764
  return this.executor.apply(namespace, planId, {
3515
3765
  confirm: true,
3766
+ abortSignal: opts.abortSignal,
3516
3767
  // Authorize rescope destinations through the namespace policy bound to
3517
3768
  // THIS caller's principal (review thread: authorize-rescope-destination).
3518
3769
  canWriteDestination: (dest) => this.deps.policy.canWriteNamespace({
@@ -3809,27 +4060,32 @@ function describeAfterState(action) {
3809
4060
  }
3810
4061
  function makeExecutorDeps(wiring, opts) {
3811
4062
  return {
3812
- getMemory: async (namespace, memoryId) => getExecutorMemory(wiring, namespace, memoryId),
3813
- writeReplacement: async (namespace, draft) => writeReplacementMemory(wiring, namespace, draft),
3814
- applyEdit: async (namespace, memoryId, patch) => applyEditMemory(wiring, namespace, memoryId, patch),
3815
- retireMemory: async (namespace, memoryId, retireOpts) => retireMemoryFn(wiring, namespace, memoryId, retireOpts),
3816
- rescopeMemory: async (namespace, memoryId, toNamespace) => rescopeMemoryFn(wiring, namespace, memoryId, toNamespace),
3817
- appendTombstone: async (namespace, input) => appendTombstoneFn(wiring, namespace, input),
3818
- registerRedactionRule: async (namespace, pattern) => registerRedactionRuleFn(wiring, namespace, pattern),
3819
- appendAuditRecord: async (namespace, record) => appendAuditRecordFn(wiring, namespace, record),
3820
- propagate: async (namespace, touchedMemoryIds) => propagateFn(wiring, namespace, touchedMemoryIds),
4063
+ getMemory: async (namespace, memoryId, abortSignal) => getExecutorMemory(wiring, namespace, memoryId, abortSignal),
4064
+ writeReplacement: async (namespace, draft, abortSignal) => writeReplacementMemory(wiring, namespace, draft, abortSignal),
4065
+ applyEdit: async (namespace, memoryId, patch, abortSignal) => applyEditMemory(wiring, namespace, memoryId, patch, abortSignal),
4066
+ retireMemory: async (namespace, memoryId, retireOpts, abortSignal) => retireMemoryFn(wiring, namespace, memoryId, retireOpts, abortSignal),
4067
+ rescopeMemory: async (namespace, memoryId, toNamespace, abortSignal) => rescopeMemoryFn(wiring, namespace, memoryId, toNamespace, abortSignal),
4068
+ appendTombstone: async (namespace, input, abortSignal) => appendTombstoneFn(wiring, namespace, input, abortSignal),
4069
+ registerRedactionRule: async (namespace, pattern, abortSignal) => registerRedactionRuleFn(wiring, namespace, pattern, abortSignal),
4070
+ appendAuditRecord: async (namespace, record, abortSignal) => appendAuditRecordFn(wiring, namespace, record, abortSignal),
4071
+ propagate: async (namespace, touchedMemoryIds, abortSignal) => propagateFn(wiring, namespace, touchedMemoryIds, abortSignal),
3821
4072
  biTemporalEnabled: opts.biTemporalEnabled,
3822
4073
  now: () => /* @__PURE__ */ new Date()
3823
4074
  };
3824
4075
  }
3825
- async function getExecutorMemory(wiring, namespace, memoryId) {
4076
+ async function getExecutorMemory(wiring, namespace, memoryId, abortSignal) {
4077
+ throwIfAborted(abortSignal, "correction apply aborted");
3826
4078
  const storage = await wiring.orchestrator.getStorage(namespace);
4079
+ throwIfAborted(abortSignal, "correction apply aborted");
3827
4080
  const m = await storage.getMemoryById(memoryId);
4081
+ throwIfAborted(abortSignal, "correction apply aborted");
3828
4082
  if (!m) return null;
3829
4083
  return toExecutorMemory(m);
3830
4084
  }
3831
- async function writeReplacementMemory(wiring, namespace, draft) {
4085
+ async function writeReplacementMemory(wiring, namespace, draft, abortSignal) {
4086
+ throwIfAborted(abortSignal, "correction apply aborted");
3832
4087
  const storage = await wiring.orchestrator.getStorage(namespace);
4088
+ throwIfAborted(abortSignal, "correction apply aborted");
3833
4089
  if (draft.category !== void 0 && !isMemoryCategory(draft.category)) {
3834
4090
  throw new CorrectionContractError(
3835
4091
  `correction draft carries unrecognized category ${JSON.stringify(draft.category)} \u2014 expected a valid memory category`
@@ -3852,6 +4108,7 @@ async function writeReplacementMemory(wiring, namespace, draft) {
3852
4108
  if (draftEnvelope.salvageNotes.length > 0) {
3853
4109
  log.warn(`correction write salvaged invalid fields: ${draftEnvelope.salvageNotes.join("; ")}`);
3854
4110
  }
4111
+ throwIfAborted(abortSignal, "correction apply aborted");
3855
4112
  const { id, tombstoneBlocked } = await storage.writeSealedMemory(draftEnvelope, {
3856
4113
  ...draft.observedAt ? { observedAt: draft.observedAt } : {},
3857
4114
  ...draft.supersedes ? { supersedes: draft.supersedes } : {}
@@ -3863,11 +4120,15 @@ async function writeReplacementMemory(wiring, namespace, draft) {
3863
4120
  }
3864
4121
  return id;
3865
4122
  }
3866
- async function applyEditMemory(wiring, namespace, memoryId, patch) {
4123
+ async function applyEditMemory(wiring, namespace, memoryId, patch, abortSignal) {
4124
+ throwIfAborted(abortSignal, "correction apply aborted");
3867
4125
  const storage = await wiring.orchestrator.getStorage(namespace);
4126
+ throwIfAborted(abortSignal, "correction apply aborted");
3868
4127
  const existing = await storage.getMemoryById(memoryId);
4128
+ throwIfAborted(abortSignal, "correction apply aborted");
3869
4129
  if (!existing) throw new CorrectionContractError(`memory not found for edit: ${memoryId}`);
3870
4130
  const contentHashForPatch = existing.frontmatter.category === "fact" ? computeContentHash(sanitizeMemoryContent(patch).text) : void 0;
4131
+ throwIfAborted(abortSignal, "correction apply aborted");
3871
4132
  await storage.writeMemoryFrontmatter(
3872
4133
  { ...existing, content: patch },
3873
4134
  {
@@ -3877,29 +4138,37 @@ async function applyEditMemory(wiring, namespace, memoryId, patch) {
3877
4138
  );
3878
4139
  return memoryId;
3879
4140
  }
3880
- async function retireMemoryFn(wiring, namespace, memoryId, opts) {
4141
+ async function retireMemoryFn(wiring, namespace, memoryId, opts, abortSignal) {
4142
+ throwIfAborted(abortSignal, "correction apply aborted");
3881
4143
  const storage = await wiring.orchestrator.getStorage(namespace);
4144
+ throwIfAborted(abortSignal, "correction apply aborted");
3882
4145
  const memory = await storage.getMemoryById(memoryId);
4146
+ throwIfAborted(abortSignal, "correction apply aborted");
3883
4147
  if (!memory) throw new CorrectionContractError(`memory not found for retire: ${memoryId}`);
3884
4148
  const storageStatus = opts.status === "retracted" ? "forgotten" : "superseded";
4149
+ throwIfAborted(abortSignal, "correction apply aborted");
3885
4150
  await storage.writeMemoryFrontmatter(memory, {
3886
4151
  status: storageStatus,
3887
4152
  ...opts.supersededBy ? { supersededBy: opts.supersededBy } : {},
3888
4153
  ...opts.status === "superseded" ? { supersededAt: (/* @__PURE__ */ new Date()).toISOString() } : {},
3889
- // validUntil is the bi-temporal end; absent when the gate is off.
3890
4154
  ...opts.validUntil ? { invalid_at: opts.validUntil } : {}
3891
4155
  });
3892
4156
  }
3893
- async function rescopeMemoryFn(wiring, namespace, memoryId, toNamespace) {
4157
+ async function rescopeMemoryFn(wiring, namespace, memoryId, toNamespace, abortSignal) {
4158
+ throwIfAborted(abortSignal, "correction apply aborted");
3894
4159
  const sourceStorage = await wiring.orchestrator.getStorage(namespace);
4160
+ throwIfAborted(abortSignal, "correction apply aborted");
3895
4161
  const memory = await sourceStorage.getMemoryById(memoryId);
4162
+ throwIfAborted(abortSignal, "correction apply aborted");
3896
4163
  if (!memory) throw new CorrectionContractError(`memory not found for rescope: ${memoryId}`);
3897
4164
  if (memory.frontmatter.status && memory.frontmatter.status !== "active") {
3898
4165
  throw new CorrectionContractError(
3899
4166
  `cannot rescope memory ${memoryId}: source is ${memory.frontmatter.status}, not active`
3900
4167
  );
3901
4168
  }
4169
+ throwIfAborted(abortSignal, "correction apply aborted");
3902
4170
  const destStorage = await wiring.orchestrator.getStorage(toNamespace);
4171
+ throwIfAborted(abortSignal, "correction apply aborted");
3903
4172
  const fm = memory.frontmatter;
3904
4173
  const destContent = fm.structuredAttributes ? stripAttributesSuffix(memory.content) : memory.content;
3905
4174
  const rescopeEnvelope = composeMemoryEnvelope(
@@ -3918,6 +4187,7 @@ async function rescopeMemoryFn(wiring, namespace, memoryId, toNamespace) {
3918
4187
  if (rescopeEnvelope.salvageNotes.length > 0) {
3919
4188
  log.warn(`rescope write salvaged invalid fields: ${rescopeEnvelope.salvageNotes.join("; ")}`);
3920
4189
  }
4190
+ throwIfAborted(abortSignal, "correction apply aborted");
3921
4191
  const { id: destId, tombstoneBlocked: destBlocked } = await destStorage.writeSealedMemory(rescopeEnvelope, {
3922
4192
  ...fm.observedAt ? { observedAt: fm.observedAt } : {},
3923
4193
  ...fm.memoryKind ? { memoryKind: fm.memoryKind } : {},
@@ -3949,13 +4219,17 @@ async function rescopeMemoryFn(wiring, namespace, memoryId, toNamespace) {
3949
4219
  }
3950
4220
  return destId;
3951
4221
  }
3952
- async function appendTombstoneFn(wiring, namespace, input) {
4222
+ async function appendTombstoneFn(wiring, namespace, input, abortSignal) {
4223
+ throwIfAborted(abortSignal, "correction apply aborted");
3953
4224
  const storage = await wiring.orchestrator.getStorage(namespace);
4225
+ throwIfAborted(abortSignal, "correction apply aborted");
3954
4226
  const enabled = typeof storage.isTombstonesEnabled === "function" ? storage.isTombstonesEnabled() : true;
3955
4227
  const keys = input.supersessionKeys && input.supersessionKeys.length > 0 ? input.supersessionKeys : input.supersessionKey ? [input.supersessionKey] : [void 0];
3956
4228
  const writtenIds = [];
3957
4229
  let firstId = null;
4230
+ let committed = false;
3958
4231
  for (const key of keys) {
4232
+ if (!committed) throwIfAborted(abortSignal, "correction apply aborted");
3959
4233
  const result = await storage.appendTombstone({
3960
4234
  reason: input.reason,
3961
4235
  createdBy: "user_correction",
@@ -3977,26 +4251,37 @@ async function appendTombstoneFn(wiring, namespace, input) {
3977
4251
  );
3978
4252
  }
3979
4253
  if (firstId === null) firstId = result;
3980
- if (result) writtenIds.push(result);
4254
+ if (result) {
4255
+ writtenIds.push(result);
4256
+ committed = true;
4257
+ }
3981
4258
  }
3982
4259
  return firstId;
3983
4260
  }
3984
- async function registerRedactionRuleFn(wiring, namespace, pattern) {
4261
+ async function registerRedactionRuleFn(wiring, namespace, pattern, abortSignal) {
4262
+ throwIfAborted(abortSignal, "correction apply aborted");
3985
4263
  const storage = await wiring.orchestrator.getStorage(namespace);
4264
+ throwIfAborted(abortSignal, "correction apply aborted");
3986
4265
  const dir = path5.join(storage.dir, "state", "corrections", "redaction-rules");
3987
4266
  await mkdir3(dir, { recursive: true });
4267
+ throwIfAborted(abortSignal, "correction apply aborted");
3988
4268
  const slugBase = pattern.replace(/[^a-zA-Z0-9]+/g, "-").slice(0, 48) || "rule";
3989
4269
  const patternHash = createHash2("sha256").update(pattern).digest("hex").slice(0, 16);
3990
4270
  const slug = `${slugBase}-${patternHash}`;
4271
+ throwIfAborted(abortSignal, "correction apply aborted");
3991
4272
  await writeFile3(
3992
4273
  path5.join(dir, `${slug}.json`),
3993
4274
  `${JSON.stringify({ pattern, namespace, createdAt: (/* @__PURE__ */ new Date()).toISOString() })}
3994
4275
  `,
3995
4276
  "utf-8"
3996
4277
  );
4278
+ throwIfAborted(abortSignal, "correction apply aborted");
3997
4279
  }
3998
- async function appendAuditRecordFn(wiring, namespace, record) {
4280
+ async function appendAuditRecordFn(wiring, namespace, record, abortSignal) {
4281
+ throwIfAborted(abortSignal, "correction apply aborted");
3999
4282
  const storage = await wiring.orchestrator.getStorage(namespace);
4283
+ throwIfAborted(abortSignal, "correction apply aborted");
4284
+ throwIfAborted(abortSignal, "correction apply aborted");
4000
4285
  const { id } = await storage.writeSealedMemory(
4001
4286
  composeMemoryEnvelope(
4002
4287
  {
@@ -4009,6 +4294,7 @@ async function appendAuditRecordFn(wiring, namespace, record) {
4009
4294
  ),
4010
4295
  {}
4011
4296
  );
4297
+ throwIfAborted(abortSignal, "correction apply aborted");
4012
4298
  return id;
4013
4299
  }
4014
4300
  function buildAuditBody(record) {
@@ -4030,15 +4316,19 @@ function buildAuditBody(record) {
4030
4316
  }
4031
4317
  return lines.join("\n");
4032
4318
  }
4033
- async function propagateFn(wiring, namespace, touchedMemoryIds) {
4319
+ async function propagateFn(wiring, namespace, touchedMemoryIds, abortSignal) {
4034
4320
  for (const id of touchedMemoryIds) {
4321
+ throwIfAborted(abortSignal, "correction apply aborted");
4035
4322
  try {
4036
4323
  const storage = await wiring.orchestrator.getStorage(namespace);
4324
+ throwIfAborted(abortSignal, "correction apply aborted");
4037
4325
  const orchestrator = wiring.orchestrator;
4038
4326
  if (typeof orchestrator.indexPersistedMemory === "function") {
4039
4327
  await orchestrator.indexPersistedMemory(storage, id);
4328
+ throwIfAborted(abortSignal, "correction apply aborted");
4040
4329
  }
4041
- } catch {
4330
+ } catch (err) {
4331
+ if (abortSignal?.aborted) throw err;
4042
4332
  }
4043
4333
  }
4044
4334
  }
@@ -4387,6 +4677,7 @@ async function capturePassiveCorrections(corrections, ctx, config, deps, dedupSt
4387
4677
  const plans = [];
4388
4678
  telemetry.detected = corrections.length;
4389
4679
  for (const correction of corrections) {
4680
+ if (ctx.abortSignal?.aborted) return { telemetry, plans };
4390
4681
  const fp = correctionFingerprint(ctx.bufferKey, correction);
4391
4682
  if (dedupState.has(fp)) {
4392
4683
  continue;
@@ -4409,13 +4700,14 @@ async function capturePassiveCorrections(corrections, ctx, config, deps, dedupSt
4409
4700
  };
4410
4701
  let plan;
4411
4702
  try {
4412
- plan = await deps.planCorrection(request);
4703
+ plan = await deps.planCorrection(request, { abortSignal: ctx.abortSignal });
4413
4704
  } catch (err) {
4414
4705
  log.warn(
4415
4706
  `passive-correction: planning failed for "${correction.targetHint.slice(0, 60)}": ${err instanceof Error ? err.message : String(err)}`
4416
4707
  );
4417
4708
  continue;
4418
4709
  }
4710
+ if (ctx.abortSignal?.aborted) return { telemetry, plans };
4419
4711
  plans.push(plan);
4420
4712
  dedupState.add(fp);
4421
4713
  if (config.mode === "queue") {
@@ -4433,7 +4725,8 @@ async function capturePassiveCorrections(corrections, ctx, config, deps, dedupSt
4433
4725
  confirm: true,
4434
4726
  namespace: ctx.namespace,
4435
4727
  ...ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {},
4436
- ...ctx.principal ? { principal: ctx.principal } : {}
4728
+ ...ctx.principal ? { principal: ctx.principal } : {},
4729
+ abortSignal: ctx.abortSignal
4437
4730
  });
4438
4731
  if (outcome.status !== "applied") {
4439
4732
  log.warn(
@@ -4878,6 +5171,7 @@ var OPERATION_NAMES = [
4878
5171
  "observe",
4879
5172
  "lcm_search",
4880
5173
  "lcm_compaction_flush",
5174
+ "extraction_force_flush",
4881
5175
  "lcm_compaction_record",
4882
5176
  "continuity_audit_generate",
4883
5177
  "continuity_incident_open",
@@ -5581,12 +5875,524 @@ import * as nodePath3 from "path";
5581
5875
 
5582
5876
  // src/access-observe-write-surface.ts
5583
5877
  import { createHash as createHash4 } from "crypto";
5878
+
5879
+ // src/orchestration/session-context.ts
5880
+ var SessionOwnershipError = class extends Error {
5881
+ constructor(message) {
5882
+ super(message);
5883
+ this.name = "SessionOwnershipError";
5884
+ }
5885
+ };
5886
+ var MAX_SET_TIMEOUT_MS = 2147483647;
5887
+ async function awaitSessionFlushPhase(task, options) {
5888
+ const abortMessage = options.reason === "access_force_flush" ? "extraction force-flush aborted" : "session flush aborted";
5889
+ throwIfAborted(options.abortSignal, abortMessage);
5890
+ const deadline = options.extractionDeadlineMs;
5891
+ if (typeof deadline === "number" && Date.now() >= deadline) {
5892
+ options.onDeadline?.();
5893
+ throw new ExtractionDeadlineError(options.deadlineStage ?? "before_buffer_flush");
5894
+ }
5895
+ const taskPromise = Promise.resolve().then(task);
5896
+ if (!options.abortSignal && typeof deadline !== "number") return taskPromise;
5897
+ let abortHandler;
5898
+ let deadlineTimer;
5899
+ const abortPromise = options.abortSignal === void 0 ? void 0 : new Promise((_resolve, reject) => {
5900
+ abortHandler = () => reject(abortError(abortMessage));
5901
+ options.abortSignal?.addEventListener("abort", abortHandler, { once: true });
5902
+ });
5903
+ const deadlinePromise = typeof deadline !== "number" ? void 0 : new Promise((_resolve, reject) => {
5904
+ const schedule = () => {
5905
+ const remainingMs = deadline - Date.now();
5906
+ if (remainingMs <= 0) {
5907
+ options.onDeadline?.();
5908
+ reject(new ExtractionDeadlineError(options.deadlineStage ?? "before_buffer_flush"));
5909
+ return;
5910
+ }
5911
+ deadlineTimer = setTimeout(schedule, Math.min(remainingMs, MAX_SET_TIMEOUT_MS));
5912
+ deadlineTimer.unref?.();
5913
+ };
5914
+ schedule();
5915
+ });
5916
+ const races = [taskPromise];
5917
+ if (abortPromise) races.push(abortPromise);
5918
+ if (deadlinePromise) races.push(deadlinePromise);
5919
+ try {
5920
+ return await Promise.race(races);
5921
+ } finally {
5922
+ if (abortHandler && options.abortSignal) {
5923
+ options.abortSignal.removeEventListener("abort", abortHandler);
5924
+ }
5925
+ if (deadlineTimer) clearTimeout(deadlineTimer);
5926
+ }
5927
+ }
5928
+ var SessionContextCoordinator = class {
5929
+ constructor(deps) {
5930
+ this.deps = deps;
5931
+ }
5932
+ deps;
5933
+ /**
5934
+ * Effective namespace a same-session LCM/structured-history READER must use
5935
+ * to find what the access `observe` surface WROTE (#1495 thread 2).
5936
+ *
5937
+ * This MUST mirror the `observe` scope plan's write-namespace resolution, NOT
5938
+ * `resolveSelfNamespace`: when no coding overlay applies, `observe` archives
5939
+ * under `config.defaultNamespace` (an unqualified observed turn is NOT moved
5940
+ * to the principal self namespace — identical to
5941
+ * `resolveCodingScopedWriteNamespace`/`memory_store`, rule 39). Only when a
5942
+ * coding overlay actually changes the namespace does the writer (and so the
5943
+ * reader) use the overlaid `project-*` namespace. Returning the self base for
5944
+ * the no-overlay case would prefix the read key with a namespace the writer
5945
+ * never used, so the reader would miss its own evidence.
5946
+ *
5947
+ * Honours the access-surface `principalOverride` (#1505 thread 2, codex): when
5948
+ * a recall supplies an authenticated principal NOT encoded in the raw
5949
+ * `sessionKey`, `observe` archived LCM under THAT principal's base namespace.
5950
+ * Deriving the base from `resolvePrincipal(sessionKey)` alone could fall back
5951
+ * to `default`, so principal `alice` observing `sess-1` would write under
5952
+ * `alice` but READ under `default`. Threading the override here keeps the read
5953
+ * base identical to the write base.
5954
+ *
5955
+ * READ-AUTHORIZATION gate (#1505 round 3, codex P2 "Gate LCM recall keys by
5956
+ * readable namespaces"): the overlay LCM read key is a `<principal>-project-*`
5957
+ * sub-namespace of the principal SELF base. The normal recall namespace set
5958
+ * below only substitutes the coding overlay when the principal SELF base is
5959
+ * actually in the readable recall set (`recallNamespacesForPrincipal` — gated
5960
+ * by `defaultRecallNamespaces.includes("self")` AND `canReadNamespace`). If a
5961
+ * principal can WRITE but not READ its self namespace (or `defaultRecall-
5962
+ * Namespaces` omits `self`), QMD/file recall never touches those overlay rows,
5963
+ * so neither may the LCM read key. When the self base is NOT readable, fall
5964
+ * back to the default store — exactly what an unqualified, unauthorized recall
5965
+ * resolves to — rather than injecting overlay rows the rest of recall excludes
5966
+ * (rule 42 read/write parity; rule 48 least-privilege).
5967
+ */
5968
+ lcmReadNamespaceForSession(sessionKey, principalOverride) {
5969
+ const principal = typeof principalOverride === "string" && principalOverride.length > 0 ? principalOverride : this.deps.resolvePrincipal(sessionKey);
5970
+ const base = defaultNamespaceForPrincipal(principal, this.deps.config);
5971
+ const overlaid = this.deps.applyCodingNamespaceOverlay(sessionKey, base);
5972
+ if (overlaid === base) return this.deps.config.defaultNamespace;
5973
+ const selfReadableInRecall = recallNamespacesForPrincipal(
5974
+ principal,
5975
+ this.deps.config
5976
+ ).includes(base);
5977
+ return selfReadableInRecall ? overlaid : this.deps.config.defaultNamespace;
5978
+ }
5979
+ /**
5980
+ * Attach a coding-agent context to a session (issue #569). Called by the
5981
+ * Claude Code / Codex / Cursor connectors at session start after
5982
+ * `resolveGitContext(cwd)`. The context is consulted by the recall path
5983
+ * and the write path so that memories route to a project- (and optionally
5984
+ * branch-) scoped namespace.
5985
+ *
5986
+ * Pass `null` to clear.
5987
+ */
5988
+ setCodingContextForSession(sessionKey, codingContext) {
5989
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
5990
+ this.deps.ensureSessionBindingMaps();
5991
+ if (codingContext === null) {
5992
+ this.deps._codingContextBySession.delete(sessionKey);
5993
+ return;
5994
+ }
5995
+ this.deps._codingContextBySession.set(sessionKey, codingContext);
5996
+ }
5997
+ /**
5998
+ * Read-only accessor for the coding context attached to a session. Returns
5999
+ * `null` when none is set. Used by `remnic doctor` and by tests.
6000
+ *
6001
+ * Defensive `_codingContextBySession` lookup — legacy orchestrator-flush
6002
+ * tests use `Object.create(Orchestrator.prototype)` which does not run
6003
+ * class-field initializers, so the Map may be undefined on stubs.
6004
+ */
6005
+ getCodingContextForSession(sessionKey) {
6006
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
6007
+ return this.deps._codingContextBySession?.get(sessionKey) ?? null;
6008
+ }
6009
+ /**
6010
+ * Shared helper used by both the recall path and the write path (rule 42).
6011
+ *
6012
+ * Given a base namespace computed from the principal, returns the overlaid
6013
+ * coding namespace when the session has a coding context AND
6014
+ * `codingMode.projectScope` is true AND `namespacesEnabled` is true.
6015
+ * Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.
6016
+ *
6017
+ * Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with
6018
+ * the principal-derived `baseNamespace` rather than replacing it, so two
6019
+ * principals working in the same repository do not share memories through
6020
+ * a common `project-*` namespace.
6021
+ *
6022
+ * Namespaces-disabled gate: when `namespacesEnabled` is false, the
6023
+ * storage router maps every namespace to the same `memoryDir`. Returning
6024
+ * `project-*` in that mode would create apparent route separation with
6025
+ * no actual storage isolation — a false-isolation trap. In that mode we
6026
+ * return `baseNamespace` unchanged so coding mode degrades to the existing
6027
+ * unscoped behavior.
6028
+ *
6029
+ * @internal
6030
+ */
6031
+ applyCodingNamespaceOverlay(sessionKey, baseNamespace) {
6032
+ if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return baseNamespace;
6033
+ const codingContext = this.deps.getCodingContextForSession(sessionKey);
6034
+ const overlay = resolveCodingNamespaceOverlay(codingContext, this.deps.config.codingMode, this.deps.config.defaultNamespace);
6035
+ if (!overlay) return baseNamespace;
6036
+ return combineNamespaces(baseNamespace, overlay.namespace);
6037
+ }
6038
+ /**
6039
+ * Register a peer ID for a session so recall can inject the peer's
6040
+ * profile into context (issue #679 PR 3/5). Pass `null` to clear.
6041
+ *
6042
+ * Connectors and the `before_agent_start` hook call this when the
6043
+ * session's counter-party is known. The ID is validated against
6044
+ * `PEER_ID_PATTERN` before storing.
6045
+ *
6046
+ * Fail-closed (Codex P1 review): an invalid peerId clears any
6047
+ * previously registered mapping for the session rather than silently
6048
+ * keeping stale data. This prevents a malformed metadata update from
6049
+ * mixing one peer's profile context into another session.
6050
+ *
6051
+ * Defensive init (Cursor review + rule 16): `Object.create(
6052
+ * Orchestrator.prototype)` stubs in legacy tests skip class-field
6053
+ * initializers, so `_peerIdBySession` may be undefined. Mirror the
6054
+ * same guard used by `setCodingContextForSession`.
6055
+ */
6056
+ setPeerIdForSession(sessionKey, peerId) {
6057
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return;
6058
+ this.deps.ensureSessionBindingMaps();
6059
+ if (peerId === null) {
6060
+ this.deps._peerIdBySession.delete(sessionKey);
6061
+ return;
6062
+ }
6063
+ if (typeof peerId !== "string" || peerId.length === 0 || peerId.length > 64 || !/^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/.test(peerId)) {
6064
+ log.warn(`setPeerIdForSession: invalid peerId \u2014 clearing session mapping`);
6065
+ this.deps._peerIdBySession.delete(sessionKey);
6066
+ return;
6067
+ }
6068
+ this.deps._peerIdBySession.set(sessionKey, peerId);
6069
+ }
6070
+ /**
6071
+ * Return the peer ID registered for a session, or `null` when none
6072
+ * is set. Used by `recallInternal` to inject the peer profile section.
6073
+ * Defensive `_peerIdBySession` lookup — legacy orchestrator-flush tests
6074
+ * use `Object.create(Orchestrator.prototype)` which skips class-field
6075
+ * initializers, so the Map may be undefined on stubs.
6076
+ */
6077
+ getPeerIdForSession(sessionKey) {
6078
+ if (typeof sessionKey !== "string" || sessionKey.length === 0) return null;
6079
+ return this.deps._peerIdBySession?.get(sessionKey) ?? null;
6080
+ }
6081
+ async runDeepSleepGovernanceNow(options) {
6082
+ const targetStorage = options?.storage ?? this.deps.storage;
6083
+ const { runMemoryGovernance: runMemoryGovernance3 } = await import("./maintenance/memory-governance.js");
6084
+ const { summarizeGovernanceResultForDreams } = await import("./dreams-ledger-567VKVOU.js");
6085
+ const govResult = await runMemoryGovernance3({
6086
+ memoryDir: targetStorage.dir,
6087
+ mode: options?.dryRun === true ? "shadow" : "apply"
6088
+ });
6089
+ if (options?.dryRun !== true) {
6090
+ try {
6091
+ await this.deps.entitySynthesisCoordinator.processQueue(
6092
+ this.deps.storageDirNamespace(targetStorage.dir),
6093
+ 5
6094
+ );
6095
+ } catch (error) {
6096
+ log.debug(`deep-sleep governance: entity synthesis refresh failed after apply: ${error}`);
6097
+ }
6098
+ }
6099
+ return summarizeGovernanceResultForDreams(govResult, options?.dryRun === true);
6100
+ }
6101
+ async generateDaySummary(memories) {
6102
+ if (this.deps.initPromise) {
6103
+ let initGateTimeoutHandle;
6104
+ try {
6105
+ await Promise.race([
6106
+ this.deps.initPromise.catch(() => void 0),
6107
+ new Promise((resolve4) => {
6108
+ initGateTimeoutHandle = setTimeout(
6109
+ resolve4,
6110
+ this.deps.config.initGateTimeoutMs
6111
+ );
6112
+ })
6113
+ ]);
6114
+ } finally {
6115
+ if (initGateTimeoutHandle) clearTimeout(initGateTimeoutHandle);
6116
+ }
6117
+ }
6118
+ return this.deps.extraction.generateDaySummary(memories);
6119
+ }
6120
+ async flushSession(sessionKey, options) {
6121
+ if (typeof this.deps.buffer.flushPendingSave === "function") {
6122
+ await awaitSessionFlushPhase(
6123
+ () => this.deps.buffer.flushPendingSave({ throwOnFailure: true }),
6124
+ options
6125
+ );
6126
+ } else {
6127
+ throwIfAborted(
6128
+ options.abortSignal,
6129
+ options.reason === "access_force_flush" ? "extraction force-flush aborted" : "session flush aborted"
6130
+ );
6131
+ if (typeof options.extractionDeadlineMs === "number" && Date.now() >= options.extractionDeadlineMs) {
6132
+ throw new ExtractionDeadlineError("before_buffer_flush");
6133
+ }
6134
+ }
6135
+ const explicitBufferKey = typeof options.bufferKey === "string" && options.bufferKey.length > 0 ? options.bufferKey : null;
6136
+ const discoveredBufferKeys = explicitBufferKey || typeof sessionKey !== "string" || sessionKey.length === 0 || typeof this.deps.buffer.findBufferKeysForSession !== "function" ? [] : await awaitSessionFlushPhase(
6137
+ () => this.deps.buffer.findBufferKeysForSession(sessionKey),
6138
+ options
6139
+ );
6140
+ const bufferKeys = explicitBufferKey ? [explicitBufferKey] : discoveredBufferKeys.length > 0 ? discoveredBufferKeys : typeof sessionKey === "string" && sessionKey.length > 0 ? [sessionKey] : ["default"];
6141
+ const namespacesEnabled = this.deps.config === void 0 || resolveNamespaceCapabilities(this.deps.config).namespaces === true;
6142
+ const scopedRequest = typeof options.writeNamespaceOverride === "string" || typeof options.principalOverride === "string";
6143
+ const ownershipEnforced = namespacesEnabled && scopedRequest;
6144
+ const ownerPrincipal = typeof options.principalOverride === "string" && options.principalOverride.trim().length > 0 ? options.principalOverride.trim() : void 0;
6145
+ const resolvedSessionPrincipal = ownershipEnforced && ownerPrincipal !== void 0 && this.deps.config ? resolvePrincipal(sessionKey, this.deps.config) : void 0;
6146
+ const opaqueScopedSession = ownershipEnforced && ownerPrincipal !== void 0 && (resolvedSessionPrincipal === void 0 || resolvedSessionPrincipal === "default");
6147
+ const belongsToSession = (turn) => {
6148
+ if (turn.sessionKey !== sessionKey) return false;
6149
+ if (!ownershipEnforced || ownerPrincipal === void 0) return true;
6150
+ if (turn.sessionOwnerPrincipal === ownerPrincipal) return true;
6151
+ return turn.sessionOwnerPrincipal === void 0 && this.deps.config !== void 0 && resolvePrincipal(turn.sessionKey, this.deps.config) === ownerPrincipal;
6152
+ };
6153
+ if (opaqueScopedSession && bufferKeys.some(
6154
+ (bufferKey) => this.deps.buffer.getTurns(bufferKey).some((turn) => turn.sessionKey === sessionKey && turn.sessionOwnerPrincipal === void 0)
6155
+ )) {
6156
+ throw new SessionOwnershipError(
6157
+ `session ${sessionKey} has buffered turns without trusted ownership`
6158
+ );
6159
+ }
6160
+ for (const bufferKey of bufferKeys) {
6161
+ const turns = this.deps.buffer.getTurns(bufferKey);
6162
+ const turnsForSession = scopedRequest ? turns.filter(belongsToSession) : turns;
6163
+ if (turnsForSession.length === 0) continue;
6164
+ const retainedTurnsForOtherSessions = scopedRequest && typeof this.deps.buffer.getRetainedDeferredTurns === "function" ? this.deps.buffer.getRetainedDeferredTurns(bufferKey).filter((turn) => !belongsToSession(turn)) : [];
6165
+ try {
6166
+ await new Promise((resolve4, reject) => {
6167
+ void this.deps.queueBufferedExtraction(turnsForSession, "trigger_mode", {
6168
+ bufferKey,
6169
+ clearBufferAfterExtraction: true,
6170
+ skipDedupeCheck: true,
6171
+ skipCharThreshold: true,
6172
+ skipUserTurnThreshold: true,
6173
+ failOnExtractionFailure: options.failOnExtractionFailure === true,
6174
+ forceExtractionAttempt: true,
6175
+ abortSignal: options.abortSignal,
6176
+ extractionDeadlineMs: options.extractionDeadlineMs,
6177
+ writeNamespaceOverride: options.writeNamespaceOverride,
6178
+ principalOverride: options.principalOverride,
6179
+ scopeProfileWritePlan: options.scopeProfileWritePlan,
6180
+ clearMatchingTurns: options.clearMatchingTurns ?? scopedRequest,
6181
+ onDurableCommit: options.onCommitted,
6182
+ onTaskSettled: (error) => error ? reject(error) : resolve4()
6183
+ }).catch(reject);
6184
+ });
6185
+ } finally {
6186
+ if (retainedTurnsForOtherSessions.length > 0 && typeof this.deps.buffer.retainDeferredTurns === "function") {
6187
+ const retainedAfterExtraction = this.deps.buffer.getRetainedDeferredTurns(bufferKey);
6188
+ await this.deps.buffer.retainDeferredTurns(
6189
+ bufferKey,
6190
+ [
6191
+ ...retainedAfterExtraction.filter((turn) => belongsToSession(turn)),
6192
+ ...retainedTurnsForOtherSessions
6193
+ ],
6194
+ 10
6195
+ ).catch((error) => {
6196
+ log.warn(
6197
+ `session flush could not restore retained turns for other sessions in ${bufferKey}`,
6198
+ error
6199
+ );
6200
+ });
6201
+ }
6202
+ }
6203
+ }
6204
+ }
6205
+ /** Lazily construct the CorrectionService for passive capture. Stateless
6206
+ * across requests (per #1580 design); cached for the orchestrator's life. */
6207
+ passiveCorrectionService() {
6208
+ if (this.deps._passiveCorrectionService) return this.deps._passiveCorrectionService;
6209
+ this.deps._passiveCorrectionService = createCorrectionService({
6210
+ orchestrator: this.deps.orchestratorSelf,
6211
+ // Session-scoped write ACL (review: "passive capture bypasses write
6212
+ // ACL"). A correction detected in session S plans only against S readable
6213
+ // namespaces and applies only to writable ones (rule 42) — passive
6214
+ // capture never becomes a cross-tenant mutation vector. Mirrors the
6215
+ // access-service createCorrectionService wiring rather than bypassing it.
6216
+ resolveAuthorizedNamespace: async (req) => {
6217
+ const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
6218
+ const ns = req.namespace ?? defaultNamespaceForPrincipal(principal, this.deps.config);
6219
+ if (!canWriteNamespace(principal, ns, this.deps.config)) {
6220
+ throw new Error(
6221
+ `passive correction: namespace "${ns}" is not writable for principal ${principal ?? "(none)"}`
6222
+ );
6223
+ }
6224
+ return ns;
6225
+ },
6226
+ resolveReadableNamespaces: (req) => {
6227
+ const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
6228
+ return recallNamespacesForPrincipal(principal, this.deps.config);
6229
+ },
6230
+ canWriteNamespace: async (req) => {
6231
+ const principal = req.principal || resolvePrincipal(req.sessionKey, this.deps.config);
6232
+ return canWriteNamespace(principal, req.namespace, this.deps.config);
6233
+ },
6234
+ llmComplete: async ({ system, user }) => {
6235
+ const llmResult = await this.deps.localLlm.chatCompletion(
6236
+ [
6237
+ { role: "system", content: system },
6238
+ { role: "user", content: user }
6239
+ ],
6240
+ { operation: "correction-classify", priority: "background" }
6241
+ );
6242
+ if (!llmResult) {
6243
+ throw new Error(
6244
+ "passive correction classify+draft: local LLM unavailable (disabled or in cooldown)"
6245
+ );
6246
+ }
6247
+ return llmResult.content;
6248
+ }
6249
+ });
6250
+ return this.deps._passiveCorrectionService;
6251
+ }
6252
+ };
6253
+
6254
+ // src/access-extraction-force-flush.ts
6255
+ async function extractionForceFlush(deps, request, waitForPendingObserveExtraction) {
6256
+ if (!request.sessionKey || typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
6257
+ throw new EngramAccessInputError("sessionKey is required and must be a non-empty string");
6258
+ }
6259
+ if (request.deadlineMs !== void 0 && (!Number.isFinite(request.deadlineMs) || request.deadlineMs < 0)) {
6260
+ throw new EngramAccessInputError("deadlineMs must be a finite non-negative number");
6261
+ }
6262
+ const authenticatedPrincipal = request.authenticatedPrincipal?.trim();
6263
+ throwIfAborted(request.abortSignal, "extraction force-flush aborted");
6264
+ const namespacesEnabled = resolveNamespaceCapabilities(deps.orchestrator.config).namespaces === true;
6265
+ const sessionPrincipal = namespacesEnabled ? resolvePrincipal(request.sessionKey, deps.orchestrator.config) : void 0;
6266
+ if (namespacesEnabled) {
6267
+ if (!authenticatedPrincipal || sessionPrincipal !== void 0 && sessionPrincipal !== "default" && sessionPrincipal !== authenticatedPrincipal) {
6268
+ throw new EngramAccessInputError("sessionKey is not owned by authenticated principal");
6269
+ }
6270
+ }
6271
+ let committed = false;
6272
+ const markCommitted = () => {
6273
+ if (committed) return;
6274
+ committed = true;
6275
+ request.onCommitted?.();
6276
+ };
6277
+ let abortHandler;
6278
+ try {
6279
+ const scope = await deps.resolveMemoryScopePlan(request);
6280
+ const reservationScopeHint = pendingObserveScopeHint(request);
6281
+ const cancelScopedPendingObserveExtractions = () => {
6282
+ deps.cancelPendingObserveExtractions?.(
6283
+ request.sessionKey,
6284
+ scope.principal,
6285
+ scope.writeNamespace,
6286
+ reservationScopeHint
6287
+ );
6288
+ };
6289
+ if (request.abortSignal?.aborted) cancelScopedPendingObserveExtractions();
6290
+ throwIfAborted(request.abortSignal, "extraction force-flush aborted");
6291
+ if (typeof request.deadlineMs === "number" && request.deadlineMs <= Date.now()) {
6292
+ cancelScopedPendingObserveExtractions();
6293
+ throw new EngramAccessInputError("extraction force-flush deadline exceeded before buffer drain");
6294
+ }
6295
+ abortHandler = cancelScopedPendingObserveExtractions;
6296
+ request.abortSignal?.addEventListener("abort", abortHandler, { once: true });
6297
+ await awaitSessionFlushPhase(
6298
+ () => deps.orchestrator.flushSession(request.sessionKey, {
6299
+ reason: "access_force_flush",
6300
+ abortSignal: request.abortSignal,
6301
+ failOnExtractionFailure: true,
6302
+ extractionDeadlineMs: request.deadlineMs,
6303
+ writeNamespaceOverride: scope.writeNamespace,
6304
+ principalOverride: typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : void 0,
6305
+ scopeProfileWritePlan: scope.scopeProfilePlan,
6306
+ onCommitted: markCommitted
6307
+ }),
6308
+ {
6309
+ abortSignal: request.abortSignal,
6310
+ extractionDeadlineMs: request.deadlineMs,
6311
+ reason: "access_force_flush",
6312
+ deadlineStage: "buffer_drain",
6313
+ onDeadline: cancelScopedPendingObserveExtractions
6314
+ }
6315
+ );
6316
+ markCommitted();
6317
+ if (waitForPendingObserveExtraction) {
6318
+ let cancelPendingObserveExtraction;
6319
+ await awaitSessionFlushPhase(
6320
+ () => waitForPendingObserveExtraction(
6321
+ request.sessionKey,
6322
+ scope.principal,
6323
+ scope.writeNamespace,
6324
+ request.abortSignal,
6325
+ (cancel) => {
6326
+ cancelPendingObserveExtraction = cancel;
6327
+ },
6328
+ reservationScopeHint
6329
+ ),
6330
+ {
6331
+ abortSignal: request.abortSignal,
6332
+ extractionDeadlineMs: request.deadlineMs,
6333
+ reason: "access_force_flush",
6334
+ deadlineStage: "pending_observe_extraction",
6335
+ onDeadline: () => {
6336
+ cancelScopedPendingObserveExtractions();
6337
+ cancelPendingObserveExtraction?.();
6338
+ }
6339
+ }
6340
+ );
6341
+ }
6342
+ const buffer = deps.orchestrator.buffer;
6343
+ if (buffer && typeof buffer.clearRetainedTurnsForSession === "function") {
6344
+ try {
6345
+ await awaitSessionFlushPhase(
6346
+ () => buffer.clearRetainedTurnsForSession(request.sessionKey, namespacesEnabled ? scope.principal : void 0, {
6347
+ abortSignal: request.abortSignal,
6348
+ deadlineMs: request.deadlineMs
6349
+ }),
6350
+ {
6351
+ abortSignal: request.abortSignal,
6352
+ extractionDeadlineMs: request.deadlineMs,
6353
+ reason: "access_force_flush",
6354
+ deadlineStage: "retained_turn_cleanup"
6355
+ }
6356
+ );
6357
+ } catch (cleanupError) {
6358
+ if (isAbortError(cleanupError) || cleanupError instanceof ExtractionDeadlineError) {
6359
+ throw cleanupError;
6360
+ }
6361
+ log.warn(
6362
+ `extractionForceFlush: retained-turn cleanup failed after a successful flush, continuing: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}`
6363
+ );
6364
+ }
6365
+ }
6366
+ return {
6367
+ flushed: true,
6368
+ sessionKey: request.sessionKey,
6369
+ namespace: deps.legacyResponseNamespaceForScope(scope),
6370
+ effectiveNamespace: scope.writeNamespace
6371
+ };
6372
+ } catch (error) {
6373
+ if (error instanceof SessionOwnershipError) {
6374
+ throw new EngramAccessForbiddenError(error.message);
6375
+ }
6376
+ if (error instanceof ExtractionDeadlineError) {
6377
+ throw new EngramAccessInputError(error.message);
6378
+ }
6379
+ throw error;
6380
+ } finally {
6381
+ if (abortHandler) request.abortSignal?.removeEventListener("abort", abortHandler);
6382
+ }
6383
+ }
6384
+
6385
+ // src/access-observe-write-surface.ts
5584
6386
  var AccessObserveWriteSurface = class {
5585
6387
  constructor(deps) {
5586
6388
  this.deps = deps;
5587
6389
  }
5588
6390
  deps;
5589
6391
  quarantineStoreInstance;
6392
+ pendingObserveExtractions = new PendingObserveExtractionTracker();
6393
+ cancelPendingObserveExtractions(sessionKey, principal, namespace, scopeHint) {
6394
+ this.pendingObserveExtractions.cancel(sessionKey, principal, namespace, scopeHint);
6395
+ }
5590
6396
  quarantineStore() {
5591
6397
  if (!this.quarantineStoreInstance) {
5592
6398
  this.quarantineStoreInstance = new WriteQuarantineStore(
@@ -5991,111 +6797,144 @@ var AccessObserveWriteSurface = class {
5991
6797
  throw new EngramAccessInputError(`invalid message role: ${msg.role} (expected 'user' or 'assistant')`);
5992
6798
  }
5993
6799
  }
5994
- let scope;
6800
+ const observePreparation = this.pendingObserveExtractions.reserve(
6801
+ request.sessionKey,
6802
+ pendingObserveScopeHint(request)
6803
+ );
5995
6804
  try {
5996
- scope = await this.deps.resolveMemoryScopePlan(request);
5997
- } catch (err) {
5998
- if (request.suppressQuarantine !== true) {
5999
- await this.parkRejectedWrite(err, "observe", request);
6000
- }
6001
- throw err;
6002
- }
6003
- const writeNamespace = scope.writeNamespace;
6004
- const namespace = this.deps.legacyResponseNamespaceForScope(scope);
6005
- const shouldWriteObjectiveState = resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory === true && resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites === true;
6006
- await this.deps.maybeAttachCodingContext(request.sessionKey, {
6007
- cwd: request.cwd,
6008
- projectTag: request.projectTag
6009
- });
6010
- const lcmSessionKey = lcmSessionKeyForNamespace(writeNamespace, request.sessionKey, this.deps.orchestrator.config.defaultNamespace) ?? request.sessionKey;
6011
- if (shouldWriteObjectiveState) {
6805
+ let scope;
6012
6806
  try {
6013
- const objectiveStateLocation = await this.deps.objectiveStateStoreLocationForNamespace(
6014
- scope.objectiveStateNamespace
6015
- );
6016
- await recordObjectiveStateSnapshotsFromObservedMessages({
6017
- memoryDir: objectiveStateLocation.memoryDir,
6018
- objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
6019
- objectiveStateMemoryEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory,
6020
- objectiveStateSnapshotWritesEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites,
6021
- sessionKey: request.sessionKey,
6022
- recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
6023
- messages: request.messages
6024
- });
6807
+ scope = await this.deps.resolveMemoryScopePlan(request);
6025
6808
  } catch (err) {
6026
- log.error(`access-observe objective-state snapshot write failed: ${err}`);
6809
+ if (request.suppressQuarantine !== true) {
6810
+ await this.parkRejectedWrite(err, "observe", request);
6811
+ }
6812
+ throw err;
6027
6813
  }
6028
- }
6029
- let lcmArchived = false;
6030
- if (this.deps.orchestrator.lcmEngine && this.deps.orchestrator.lcmEngine.enabled) {
6031
- try {
6032
- this.deps.orchestrator.lcmEngine.enqueueObserveMessages(lcmSessionKey, request.messages);
6033
- lcmArchived = true;
6034
- } catch (err) {
6035
- log.error(`access-observe LCM enqueue failed: ${err}`);
6036
- }
6037
- }
6038
- let extractionQueued = false;
6039
- if (request.skipExtraction !== true) {
6040
- const turns = request.messages.map((m) => ({
6041
- source: "openclaw",
6042
- // Identity-vs-routing separation (#1505 thread 1, cursor): extraction
6043
- // derives the provenance principal via `resolvePrincipal(turn.sessionKey)`
6044
- // and threads `turn.sessionKey` into conversation threading. Feeding the
6045
- // namespace-PREFIXED `lcmSessionKey` here mis-derived the principal to
6046
- // `default` (a `<ns>:<key>` string matches no prefix/map rule and fails
6047
- // the `agent:` heuristic). Pass the ORIGINAL sessionKey so identity is
6048
- // correct; storage routing is pinned separately via
6049
- // writeNamespaceOverride below, and the authenticated principal is pinned
6050
- // via principalOverride.
6051
- sessionKey: request.sessionKey,
6052
- role: m.role,
6053
- content: m.content,
6054
- parts: m.parts,
6055
- rawContent: m.rawContent,
6056
- sourceFormat: m.sourceFormat,
6057
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6058
- ...request.sourceConnector ? { sourceConnector: request.sourceConnector } : {}
6059
- }));
6060
- const writeNamespaceOverride = resolveNamespaceCapabilities(this.deps.orchestrator.config).namespaces === true ? writeNamespace : void 0;
6061
- const principalOverride = typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : void 0;
6062
- try {
6063
- const extractionPromise = this.deps.orchestrator.ingestReplayBatch(turns, {
6064
- archiveLcm: false,
6065
- writeNamespaceOverride,
6066
- principalOverride
6067
- });
6068
- extractionPromise.catch((err) => {
6069
- log.error(`access-observe background extraction failed: ${err}`);
6070
- });
6071
- extractionQueued = true;
6072
- } catch (err) {
6073
- log.error(`access-observe extraction enqueue failed: ${err}`);
6814
+ const writeNamespace = scope.writeNamespace;
6815
+ observePreparation.setScope(scope.principal, writeNamespace);
6816
+ const namespace = this.deps.legacyResponseNamespaceForScope(scope);
6817
+ const shouldWriteObjectiveState = resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory === true && resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites === true;
6818
+ await this.deps.maybeAttachCodingContext(request.sessionKey, {
6819
+ cwd: request.cwd,
6820
+ projectTag: request.projectTag
6821
+ });
6822
+ const lcmSessionKey = lcmSessionKeyForNamespace(writeNamespace, request.sessionKey, this.deps.orchestrator.config.defaultNamespace) ?? request.sessionKey;
6823
+ if (shouldWriteObjectiveState) {
6824
+ try {
6825
+ const objectiveStateLocation = await this.deps.objectiveStateStoreLocationForNamespace(
6826
+ scope.objectiveStateNamespace
6827
+ );
6828
+ await recordObjectiveStateSnapshotsFromObservedMessages({
6829
+ memoryDir: objectiveStateLocation.memoryDir,
6830
+ objectiveStateStoreDir: objectiveStateLocation.objectiveStateStoreDir,
6831
+ objectiveStateMemoryEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateMemory,
6832
+ objectiveStateSnapshotWritesEnabled: resolveObjectiveStateCapabilities(this.deps.orchestrator.config).objectiveStateSnapshotWrites,
6833
+ sessionKey: request.sessionKey,
6834
+ recordedAt: (/* @__PURE__ */ new Date()).toISOString(),
6835
+ messages: request.messages
6836
+ });
6837
+ } catch (err) {
6838
+ log.error(`access-observe objective-state snapshot write failed: ${err}`);
6839
+ }
6840
+ }
6841
+ let lcmArchived = false;
6842
+ if (this.deps.orchestrator.lcmEngine && this.deps.orchestrator.lcmEngine.enabled) {
6843
+ try {
6844
+ this.deps.orchestrator.lcmEngine.enqueueObserveMessages(lcmSessionKey, request.messages);
6845
+ lcmArchived = true;
6846
+ } catch (err) {
6847
+ log.error(`access-observe LCM enqueue failed: ${err}`);
6848
+ }
6849
+ }
6850
+ let extractionQueued = false;
6851
+ if (request.skipExtraction !== true) {
6852
+ const turns = request.messages.map((m) => ({
6853
+ source: "openclaw",
6854
+ // Identity-vs-routing separation (#1505 thread 1, cursor): extraction
6855
+ // derives the provenance principal via `resolvePrincipal(turn.sessionKey)`
6856
+ // and threads `turn.sessionKey` into conversation threading. Feeding the
6857
+ // namespace-PREFIXED `lcmSessionKey` here mis-derived the principal to
6858
+ // `default` (a `<ns>:<key>` string matches no prefix/map rule and fails
6859
+ // the `agent:` heuristic). Pass the ORIGINAL sessionKey so identity is
6860
+ // correct; storage routing is pinned separately via
6861
+ // writeNamespaceOverride below, and the authenticated principal is pinned
6862
+ // via principalOverride.
6863
+ sessionKey: request.sessionKey,
6864
+ role: m.role,
6865
+ content: m.content,
6866
+ parts: m.parts,
6867
+ rawContent: m.rawContent,
6868
+ sourceFormat: m.sourceFormat,
6869
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
6870
+ ...request.sourceConnector ? { sourceConnector: request.sourceConnector } : {}
6871
+ }));
6872
+ const writeNamespaceOverride = resolveNamespaceCapabilities(this.deps.orchestrator.config).namespaces === true ? writeNamespace : void 0;
6873
+ const principalOverride = typeof scope.principal === "string" && scope.principal.length > 0 ? scope.principal : void 0;
6874
+ if (!observePreparation.isCancelled()) {
6875
+ try {
6876
+ const observeAbortController = new AbortController();
6877
+ const extractionPromise = this.deps.orchestrator.ingestReplayBatch(turns, {
6878
+ archiveLcm: false,
6879
+ writeNamespaceOverride,
6880
+ principalOverride,
6881
+ abortSignal: observeAbortController.signal,
6882
+ ...typeof request.authenticatedPrincipal === "string" && request.authenticatedPrincipal.trim().length > 0 ? { sessionOwnerPrincipal: request.authenticatedPrincipal.trim() } : {}
6883
+ });
6884
+ extractionPromise.catch((err) => {
6885
+ log.error(`access-observe background extraction failed: ${err}`);
6886
+ });
6887
+ this.pendingObserveExtractions.track(
6888
+ this.pendingObserveExtractions.key(request.sessionKey, scope.principal, writeNamespace),
6889
+ extractionPromise,
6890
+ observeAbortController
6891
+ );
6892
+ extractionQueued = true;
6893
+ } catch (err) {
6894
+ log.error(`access-observe extraction enqueue failed: ${err}`);
6895
+ }
6896
+ }
6074
6897
  }
6898
+ log.info(
6899
+ `access-observe namespace=${namespace} effectiveNamespace=${writeNamespace} sessionKey=${request.sessionKey} messages=${request.messages.length} lcm=${lcmArchived} extraction=${extractionQueued}`
6900
+ );
6901
+ return {
6902
+ accepted: request.messages.length,
6903
+ sessionKey: request.sessionKey,
6904
+ namespace,
6905
+ effectiveNamespace: writeNamespace,
6906
+ scopeDebug: {
6907
+ principal: scope.principal,
6908
+ explicitNamespace: scope.explicitNamespace,
6909
+ baseNamespace: scope.baseNamespace,
6910
+ writeNamespace: scope.writeNamespace,
6911
+ codingOverlayApplied: scope.codingOverlayApplied,
6912
+ readNamespaces: scope.readNamespaces,
6913
+ scopeProfile: scope.scopeProfile,
6914
+ writeLayer: scope.writeLayer,
6915
+ layers: scope.layers,
6916
+ promotionTargets: scope.promotionTargets
6917
+ },
6918
+ lcmArchived,
6919
+ extractionQueued
6920
+ };
6921
+ } finally {
6922
+ observePreparation.release();
6075
6923
  }
6076
- log.info(
6077
- `access-observe namespace=${namespace} effectiveNamespace=${writeNamespace} sessionKey=${request.sessionKey} messages=${request.messages.length} lcm=${lcmArchived} extraction=${extractionQueued}`
6924
+ }
6925
+ async extractionForceFlush(request) {
6926
+ return extractionForceFlush(
6927
+ this.deps,
6928
+ request,
6929
+ (sessionKey, principal, namespace, abortSignal, registerCancellation, scopeHint) => this.pendingObserveExtractions.wait(
6930
+ sessionKey,
6931
+ principal,
6932
+ namespace,
6933
+ abortSignal,
6934
+ registerCancellation,
6935
+ scopeHint
6936
+ )
6078
6937
  );
6079
- return {
6080
- accepted: request.messages.length,
6081
- sessionKey: request.sessionKey,
6082
- namespace,
6083
- effectiveNamespace: writeNamespace,
6084
- scopeDebug: {
6085
- principal: scope.principal,
6086
- explicitNamespace: scope.explicitNamespace,
6087
- baseNamespace: scope.baseNamespace,
6088
- writeNamespace: scope.writeNamespace,
6089
- codingOverlayApplied: scope.codingOverlayApplied,
6090
- readNamespaces: scope.readNamespaces,
6091
- scopeProfile: scope.scopeProfile,
6092
- writeLayer: scope.writeLayer,
6093
- layers: scope.layers,
6094
- promotionTargets: scope.promotionTargets
6095
- },
6096
- lcmArchived,
6097
- extractionQueued
6098
- };
6099
6938
  }
6100
6939
  async workTask(request) {
6101
6940
  const STATUSES = /* @__PURE__ */ new Set(["todo", "in_progress", "blocked", "done", "cancelled"]);
@@ -9189,54 +10028,19 @@ var EngramAccessService = class {
9189
10028
  principal,
9190
10029
  this.orchestrator.config
9191
10030
  );
9192
- const hasSession = typeof request.sessionKey === "string" && request.sessionKey.length > 0;
9193
- const overlayEligible = hasSession && resolveNamespaceCapabilities(this.orchestrator.config).namespaces === true && this.orchestrator.config.codingMode?.projectScope === true;
9194
- let attachedContext = hasSession ? this.orchestrator.getCodingContextForSession(request.sessionKey) : null;
9195
- let seededContext = false;
9196
- if (overlayEligible && !attachedContext) {
9197
- attachedContext = await this.resolveCodingContextFromOptions(request);
9198
- if (attachedContext) {
9199
- this.orchestrator.setCodingContextForSession(
9200
- request.sessionKey,
9201
- attachedContext
9202
- );
9203
- seededContext = true;
9204
- }
9205
- }
9206
- const clearSeededContext = () => {
9207
- if (seededContext && hasSession) {
9208
- this.orchestrator.setCodingContextForSession(request.sessionKey, null);
9209
- }
9210
- };
10031
+ const {
10032
+ overlay: codingOverlay,
10033
+ profilePlan
10034
+ } = await this.resolveCodingScopeInputs(request);
10035
+ const overlaidBase = codingOverlay ? combineNamespaces(baseNamespace, codingOverlay.namespace) : baseNamespace;
10036
+ const codingOverlayApplied = overlaidBase !== baseNamespace;
9211
10037
  const assertWriteNamespaceAllowed = (namespace) => {
9212
- try {
9213
- this.assertTokenCanWriteNamespace(namespace);
9214
- } catch (error) {
9215
- clearSeededContext();
9216
- throw error;
9217
- }
10038
+ this.assertTokenCanWriteNamespace(namespace);
9218
10039
  };
9219
- const overlaidBase = this.orchestrator.applyCodingNamespaceOverlay(
9220
- request.sessionKey,
9221
- baseNamespace
9222
- );
9223
- const codingOverlayApplied = overlaidBase !== baseNamespace;
9224
- const codingOverlay = overlayEligible ? resolveCodingNamespaceOverlay(
9225
- attachedContext,
9226
- this.orchestrator.config.codingMode,
9227
- this.orchestrator.config.defaultNamespace
9228
- ) : null;
9229
- const profilePlan = resolveScopeProfilePlan({
9230
- config: this.orchestrator.config,
9231
- principal,
9232
- codingContext: attachedContext,
9233
- codingOverlay
9234
- });
9235
10040
  if (profilePlan) {
9236
10041
  const selectedLayer = profilePlan.layers.find((layer) => layer.id === profilePlan.writeLayer);
9237
10042
  const writeNamespaceReadable = profilePlan.writeNamespace.length > 0 && profilePlan.readNamespaces.includes(profilePlan.writeNamespace);
9238
10043
  if (!selectedLayer?.writable || !writeNamespaceReadable) {
9239
- clearSeededContext();
9240
10044
  throw new NamespaceNotWritableError(
9241
10045
  profilePlan.writeNamespace,
9242
10046
  principal,
@@ -9266,6 +10070,7 @@ var EngramAccessService = class {
9266
10070
  objectiveStateNamespace: profilePlan.writeNamespace,
9267
10071
  readNamespaces: readNamespaces2,
9268
10072
  scopeProfile: profilePlan.profileId,
10073
+ scopeProfilePlan: profilePlan,
9269
10074
  writeLayer: profilePlan.writeLayer,
9270
10075
  layers: profilePlan.layers,
9271
10076
  promotionTargets: profilePlan.promotionTargets,
@@ -9281,7 +10086,6 @@ var EngramAccessService = class {
9281
10086
  );
9282
10087
  const willWriteObjectiveState = resolveObjectiveStateCapabilities(this.orchestrator.config).objectiveStateMemory === true && resolveObjectiveStateCapabilities(this.orchestrator.config).objectiveStateSnapshotWrites === true;
9283
10088
  if (willWriteObjectiveState && resolveNamespaceCapabilities(this.orchestrator.config).namespaces === true && !canWriteNamespace(principal, baseNamespace, this.orchestrator.config)) {
9284
- clearSeededContext();
9285
10089
  throw new NamespaceNotWritableError(baseNamespace, principal);
9286
10090
  }
9287
10091
  assertWriteNamespaceAllowed(writeNamespace2);
@@ -9304,7 +10108,6 @@ var EngramAccessService = class {
9304
10108
  };
9305
10109
  }
9306
10110
  if (!canWriteNamespace(principal, baseNamespace, this.orchestrator.config)) {
9307
- clearSeededContext();
9308
10111
  throw new NamespaceNotWritableError(baseNamespace, principal);
9309
10112
  }
9310
10113
  const writeNamespace = overlaidBase;
@@ -11055,6 +11858,12 @@ var EngramAccessService = class {
11055
11858
  namespace
11056
11859
  };
11057
11860
  }
11861
+ async extractionForceFlush(request) {
11862
+ return delegateExtractionForceFlush(this.accessObserveWriteSurface, request);
11863
+ }
11864
+ cancelPendingObserveExtractions(sessionKey, principal, namespace, scopeHint) {
11865
+ this.accessObserveWriteSurface.cancelPendingObserveExtractions(sessionKey, principal, namespace, scopeHint);
11866
+ }
11058
11867
  async lcmCompactionRecord(request) {
11059
11868
  if (!request.sessionKey || typeof request.sessionKey !== "string" || request.sessionKey.trim().length === 0) {
11060
11869
  throw new EngramAccessInputError("sessionKey is required and must be a non-empty string");
@@ -12464,7 +13273,6 @@ export {
12464
13273
  isCodegraphToolName,
12465
13274
  DELTA_SUBCOMMANDS,
12466
13275
  CorrectionContractError,
12467
- createCorrectionService,
12468
13276
  detectPassiveCorrections,
12469
13277
  capturePassiveCorrections,
12470
13278
  clusterByKey,
@@ -12486,6 +13294,8 @@ export {
12486
13294
  resolveNamespaceWritablePreflight,
12487
13295
  resolveAuthorizedNamespaceWritablePreflight,
12488
13296
  resolveQueryNamespaceWritablePreflight,
13297
+ SessionContextCoordinator,
13298
+ extractionForceFlush,
12489
13299
  AccessObserveWriteSurface,
12490
13300
  AccessLcmSurface,
12491
13301
  hasIdentityRecoveryIntent,
@@ -12501,4 +13311,4 @@ export {
12501
13311
  EngramAccessService,
12502
13312
  AccessAdminOpsSurface
12503
13313
  };
12504
- //# sourceMappingURL=chunk-4WKA6I65.js.map
13314
+ //# sourceMappingURL=chunk-OGCNZPKX.js.map