@remnic/core 9.3.729 → 9.3.730

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 (345) hide show
  1. package/dist/access-boundary.d.ts +6 -5
  2. package/dist/access-boundary.js +13 -13
  3. package/dist/access-cli.js +34 -33
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +6 -5
  6. package/dist/access-http.js +19 -19
  7. package/dist/access-mcp.d.ts +6 -5
  8. package/dist/access-mcp.js +18 -18
  9. package/dist/access-operations-batch.js +16 -16
  10. package/dist/access-operations.d.ts +11 -10
  11. package/dist/access-operations.js +17 -17
  12. package/dist/access-schema.d.ts +42 -42
  13. package/dist/{access-service-BXMJqkTA.d.ts → access-service-Byoe3HsT.d.ts} +18 -3
  14. package/dist/access-service.d.ts +6 -5
  15. package/dist/access-service.js +12 -12
  16. package/dist/access-surface-catalog.d.ts +6 -5
  17. package/dist/action-confidence.d.ts +1 -1
  18. package/dist/active-memory-bridge.d.ts +1 -1
  19. package/dist/active-recall.d.ts +1 -1
  20. package/dist/active-recall.js +2 -2
  21. package/dist/{auto-sync-F3KCSQFJ.js → auto-sync-G3V5AN4C.js} +2 -2
  22. package/dist/behavior-learner.d.ts +1 -1
  23. package/dist/behavior-signals.d.ts +1 -1
  24. package/dist/bootstrap.d.ts +5 -4
  25. package/dist/briefing.d.ts +1 -1
  26. package/dist/briefing.js +3 -3
  27. package/dist/buffer-surprise-report.d.ts +1 -1
  28. package/dist/buffer.d.ts +1 -1
  29. package/dist/calibration.d.ts +1 -1
  30. package/dist/capabilities.d.ts +55 -2
  31. package/dist/capabilities.js +5 -1
  32. package/dist/{catalog-bMczlO2G.d.ts → catalog-DM1nk7cM.d.ts} +1 -1
  33. package/dist/causal-behavior.d.ts +1 -1
  34. package/dist/causal-consolidation.d.ts +1 -1
  35. package/dist/causal-consolidation.js +4 -4
  36. package/dist/causal-trajectory-graph.d.ts +1 -1
  37. package/dist/{chunk-4NOI577P.js → chunk-24ZLC5QN.js} +2 -2
  38. package/dist/{chunk-DMQWV6SQ.js → chunk-5RZOFIDL.js} +2 -2
  39. package/dist/{chunk-UM5AWJNQ.js → chunk-646B5ERJ.js} +62 -37
  40. package/dist/chunk-646B5ERJ.js.map +1 -0
  41. package/dist/{chunk-H5BWGCRZ.js → chunk-6TUWSUUD.js} +51 -47
  42. package/dist/{chunk-H5BWGCRZ.js.map → chunk-6TUWSUUD.js.map} +1 -1
  43. package/dist/{chunk-36SEDFAU.js → chunk-C5WN74HH.js} +2 -2
  44. package/dist/{chunk-MLKWJOAJ.js → chunk-CGPHMNL4.js} +2 -2
  45. package/dist/{chunk-R6OVFAX6.js → chunk-DJECGBBM.js} +7 -2
  46. package/dist/{chunk-R6OVFAX6.js.map → chunk-DJECGBBM.js.map} +1 -1
  47. package/dist/{chunk-3RCBIOOJ.js → chunk-ESF7TRYJ.js} +18 -2
  48. package/dist/{chunk-3RCBIOOJ.js.map → chunk-ESF7TRYJ.js.map} +1 -1
  49. package/dist/{chunk-EY6MDMHK.js → chunk-F6OEXJQQ.js} +2 -2
  50. package/dist/{chunk-M4V2JVSZ.js → chunk-FFUCCKPN.js} +2 -2
  51. package/dist/{chunk-O6YH5F47.js → chunk-FYWUNVFZ.js} +8 -8
  52. package/dist/{chunk-37436GML.js → chunk-GEXI357K.js} +2 -2
  53. package/dist/{chunk-YGIQORJ3.js → chunk-GGL34GCW.js} +3 -3
  54. package/dist/{chunk-4H4F3BFL.js → chunk-GXTYEG7Q.js} +3 -3
  55. package/dist/{chunk-4H4F3BFL.js.map → chunk-GXTYEG7Q.js.map} +1 -1
  56. package/dist/{chunk-WAS3NV46.js → chunk-H3MB3F62.js} +2 -2
  57. package/dist/{chunk-UTHQPSRC.js → chunk-HHNSLPX7.js} +11 -8
  58. package/dist/chunk-HHNSLPX7.js.map +1 -0
  59. package/dist/{chunk-76NHR6ZL.js → chunk-HJWQJUKQ.js} +4 -4
  60. package/dist/{chunk-Y4YD5TYW.js → chunk-IIBFCZA7.js} +3 -3
  61. package/dist/{chunk-UVPL565C.js → chunk-IQOEW5YV.js} +2 -2
  62. package/dist/{chunk-V4GNSDFH.js → chunk-KQYGNGON.js} +2 -2
  63. package/dist/{chunk-CBWI22JN.js → chunk-KSJCXXOU.js} +2 -2
  64. package/dist/{chunk-M4AYVEWS.js → chunk-LUCARK4W.js} +12 -11
  65. package/dist/chunk-LUCARK4W.js.map +1 -0
  66. package/dist/{chunk-I5REUWLH.js → chunk-NIZQH6AU.js} +3 -3
  67. package/dist/{chunk-4ESAR77N.js → chunk-NOU77OHX.js} +2 -2
  68. package/dist/{chunk-BQCHEV7O.js → chunk-O4ZIBPIW.js} +3 -3
  69. package/dist/{chunk-HOHVIVDR.js → chunk-OBJUKYDO.js} +2 -2
  70. package/dist/{chunk-YKBHOBJK.js → chunk-OEHCMALU.js} +56 -4
  71. package/dist/chunk-OEHCMALU.js.map +1 -0
  72. package/dist/{chunk-YOLZS7NY.js → chunk-OTQE66IX.js} +2 -2
  73. package/dist/{chunk-HEDZUSCS.js → chunk-OUITHS6V.js} +246 -368
  74. package/dist/chunk-OUITHS6V.js.map +1 -0
  75. package/dist/{chunk-4T3BMHKD.js → chunk-OZECYVGI.js} +20 -7
  76. package/dist/chunk-OZECYVGI.js.map +1 -0
  77. package/dist/{chunk-C2PG7IEH.js → chunk-P3VJCTVE.js} +2 -2
  78. package/dist/{chunk-EH5ED3C6.js → chunk-PMAQRUN4.js} +4 -4
  79. package/dist/chunk-PMAQRUN4.js.map +1 -0
  80. package/dist/{chunk-7RLCCNHU.js → chunk-Q6BAA57B.js} +4 -3
  81. package/dist/chunk-Q6BAA57B.js.map +1 -0
  82. package/dist/{chunk-HGNOCPZX.js → chunk-QZHF4BWN.js} +6 -6
  83. package/dist/chunk-SYX73XD7.js +283 -0
  84. package/dist/chunk-SYX73XD7.js.map +1 -0
  85. package/dist/{chunk-ASKXIAHD.js → chunk-WDJCZQB4.js} +2 -2
  86. package/dist/{chunk-AQLOP5F4.js → chunk-WNGXQMRI.js} +95 -6
  87. package/dist/chunk-WNGXQMRI.js.map +1 -0
  88. package/dist/{chunk-JYLFZWUX.js → chunk-XYUFGHUW.js} +2 -2
  89. package/dist/{chunk-3TSTGI6F.js → chunk-ZQUAVZNG.js} +2 -2
  90. package/dist/{chunk-4NR2PDZ5.js → chunk-ZVHRSR2R.js} +14 -4
  91. package/dist/chunk-ZVHRSR2R.js.map +1 -0
  92. package/dist/{cli-DmAiDd8A.d.ts → cli-Dt-tuiYH.d.ts} +3 -3
  93. package/dist/cli.d.ts +7 -6
  94. package/dist/cli.js +35 -35
  95. package/dist/compounding/engine.d.ts +12 -1
  96. package/dist/compounding/engine.js +3 -3
  97. package/dist/compounding/preference-consolidator.d.ts +1 -1
  98. package/dist/compression-optimizer.d.ts +1 -1
  99. package/dist/config.d.ts +1 -1
  100. package/dist/config.js +2 -2
  101. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  102. package/dist/connectors/codex-materialize-runner.js +3 -3
  103. package/dist/connectors/codex-materialize.d.ts +1 -1
  104. package/dist/connectors/index.d.ts +1 -1
  105. package/dist/connectors/index.js +3 -3
  106. package/dist/consolidation-provenance-check.d.ts +1 -1
  107. package/dist/consolidation-undo.d.ts +1 -1
  108. package/dist/contradiction/index.d.ts +1 -1
  109. package/dist/contradiction/index.js +1 -1
  110. package/dist/conversation-index/backend.d.ts +1 -1
  111. package/dist/conversation-index/chunker.d.ts +1 -1
  112. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  113. package/dist/conversation-index/indexer.d.ts +1 -1
  114. package/dist/conversation-index/search.d.ts +1 -1
  115. package/dist/day-summary.d.ts +1 -1
  116. package/dist/delinearize.d.ts +1 -1
  117. package/dist/direct-answer-wiring.d.ts +1 -1
  118. package/dist/direct-answer.d.ts +1 -1
  119. package/dist/embedding-fallback.d.ts +1 -1
  120. package/dist/embedding-fallback.js +2 -2
  121. package/dist/enrichment/index.d.ts +1 -1
  122. package/dist/entity-retrieval.d.ts +1 -1
  123. package/dist/entity-retrieval.js +3 -3
  124. package/dist/entity-schema.d.ts +1 -1
  125. package/dist/explicit-capture.d.ts +6 -4
  126. package/dist/explicit-capture.js +1 -1
  127. package/dist/extraction-faithfulness.d.ts +1 -1
  128. package/dist/extraction-judge-telemetry.d.ts +1 -1
  129. package/dist/extraction-judge-training.d.ts +1 -1
  130. package/dist/extraction-judge.d.ts +1 -1
  131. package/dist/extraction.d.ts +1 -1
  132. package/dist/extraction.js +3 -3
  133. package/dist/fallback-llm.d.ts +1 -1
  134. package/dist/{first-start-migration-22LPFHD5.js → first-start-migration-OOR57AYR.js} +2 -2
  135. package/dist/graph-dashboard-diff.d.ts +1 -1
  136. package/dist/graph-dashboard-key.d.ts +1 -1
  137. package/dist/graph-dashboard-parser.d.ts +1 -1
  138. package/dist/graph-edge-reinforcement.d.ts +1 -1
  139. package/dist/graph-snapshot.d.ts +1 -1
  140. package/dist/graph.d.ts +1 -1
  141. package/dist/identity-continuity.d.ts +1 -1
  142. package/dist/importance.d.ts +1 -1
  143. package/dist/index.d.ts +296 -11
  144. package/dist/index.js +359 -47
  145. package/dist/index.js.map +1 -1
  146. package/dist/intent.d.ts +1 -1
  147. package/dist/lcm/engine.d.ts +1 -1
  148. package/dist/lcm/index.d.ts +1 -1
  149. package/dist/lcm/tools.d.ts +1 -1
  150. package/dist/lifecycle.d.ts +1 -1
  151. package/dist/live-connectors-runner.d.ts +1 -1
  152. package/dist/local-llm.d.ts +1 -1
  153. package/dist/local-model-endpoint.d.ts +1 -1
  154. package/dist/maintenance/memory-governance.d.ts +1 -1
  155. package/dist/maintenance/memory-governance.js +3 -3
  156. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
  157. package/dist/maintenance/rebuild-memory-projection.js +4 -4
  158. package/dist/mcp-memory-inspector-app.d.ts +6 -5
  159. package/dist/memory-action-policy.d.ts +1 -1
  160. package/dist/memory-cache.d.ts +1 -1
  161. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  162. package/dist/memory-projection-store.d.ts +1 -1
  163. package/dist/memory-provenance.d.ts +1 -1
  164. package/dist/memory-worth-outcomes.d.ts +1 -1
  165. package/dist/models-json.d.ts +1 -1
  166. package/dist/namespaces/migrate.d.ts +2 -2
  167. package/dist/namespaces/migrate.js +9 -9
  168. package/dist/namespaces/principal.d.ts +1 -1
  169. package/dist/namespaces/search.d.ts +1 -1
  170. package/dist/namespaces/search.js +5 -5
  171. package/dist/namespaces/storage.d.ts +2 -2
  172. package/dist/namespaces/storage.js +3 -3
  173. package/dist/native-knowledge.d.ts +1 -1
  174. package/dist/operator-toolkit.d.ts +1 -1
  175. package/dist/operator-toolkit.js +14 -14
  176. package/dist/orchestration/compression-guideline-coordinator.d.ts +105 -0
  177. package/dist/orchestration/compression-guideline-coordinator.js +12 -0
  178. package/dist/orchestration/maintenance.d.ts +2 -2
  179. package/dist/orchestration/maintenance.js +5 -5
  180. package/dist/{orchestrator-BR0sGsME.d.ts → orchestrator-B4KjaOtY.d.ts} +24 -8
  181. package/dist/orchestrator.d.ts +5 -4
  182. package/dist/orchestrator.js +28 -26
  183. package/dist/patterns-cli.d.ts +1 -1
  184. package/dist/policy-runtime.d.ts +1 -1
  185. package/dist/provenance.d.ts +1 -1
  186. package/dist/provenance.js +1 -1
  187. package/dist/qmd-recall-cache.d.ts +1 -1
  188. package/dist/qmd.d.ts +1 -1
  189. package/dist/recall-disclosure-escalation.d.ts +1 -1
  190. package/dist/recall-explain-renderer.d.ts +1 -1
  191. package/dist/recall-planner-llm.d.ts +1 -1
  192. package/dist/recall-state.d.ts +1 -1
  193. package/dist/recall-tag-filter.d.ts +1 -1
  194. package/dist/recall-xray-cli.d.ts +1 -1
  195. package/dist/recall-xray-renderer.d.ts +1 -1
  196. package/dist/recall-xray.d.ts +1 -1
  197. package/dist/{resolution-MN36NW5P.js → resolution-33PIX3TT.js} +2 -2
  198. package/dist/resolution-33PIX3TT.js.map +1 -0
  199. package/dist/resolve-auth-token.d.ts +1 -1
  200. package/dist/resume-bundles.js +3 -3
  201. package/dist/retrieval-agents.d.ts +1 -1
  202. package/dist/retrieval-tiers.d.ts +1 -1
  203. package/dist/routing/engine.d.ts +1 -1
  204. package/dist/routing/store.d.ts +1 -1
  205. package/dist/schemas.d.ts +84 -84
  206. package/dist/search/embed-helper.d.ts +1 -1
  207. package/dist/search/embed-helper.js +2 -2
  208. package/dist/search/factory.d.ts +1 -1
  209. package/dist/search/factory.js +4 -4
  210. package/dist/search/index.d.ts +1 -1
  211. package/dist/search/index.js +8 -8
  212. package/dist/search/lancedb-backend.d.ts +1 -1
  213. package/dist/search/meilisearch-backend.d.ts +1 -1
  214. package/dist/search/noop-backend.d.ts +1 -1
  215. package/dist/search/orama-backend.d.ts +1 -1
  216. package/dist/search/port.d.ts +1 -1
  217. package/dist/search/remote-backend.d.ts +1 -1
  218. package/dist/{semantic-consolidation-Cl15ksZy.d.ts → semantic-consolidation-CstTvHPo.d.ts} +1 -1
  219. package/dist/semantic-consolidation.d.ts +2 -2
  220. package/dist/semantic-consolidation.js +4 -4
  221. package/dist/semantic-rule-promotion.js +3 -3
  222. package/dist/semantic-rule-verifier.d.ts +1 -1
  223. package/dist/semantic-rule-verifier.js +3 -3
  224. package/dist/session-observer-bands.d.ts +1 -1
  225. package/dist/session-observer-state.d.ts +1 -1
  226. package/dist/shared-context/manager.d.ts +3 -3
  227. package/dist/signal.d.ts +1 -1
  228. package/dist/storage.d.ts +22 -3
  229. package/dist/storage.js +2 -2
  230. package/dist/summarizer.d.ts +1 -1
  231. package/dist/summary-snapshot.d.ts +1 -1
  232. package/dist/temporal-supersession.d.ts +1 -1
  233. package/dist/temporal-validity.d.ts +1 -1
  234. package/dist/threading.d.ts +1 -1
  235. package/dist/tier-migration.d.ts +1 -1
  236. package/dist/tier-routing.d.ts +1 -1
  237. package/dist/topics.d.ts +1 -1
  238. package/dist/transcript.d.ts +1 -1
  239. package/dist/transfer/types.d.ts +46 -46
  240. package/dist/trust-score-stage.d.ts +1 -1
  241. package/dist/trust-score.d.ts +1 -1
  242. package/dist/{types-ChQb9D6s.d.ts → types-VkxElCHR.d.ts} +8 -1
  243. package/dist/types.d.ts +1 -1
  244. package/dist/utility-runtime.d.ts +1 -1
  245. package/dist/verified-recall.js +3 -3
  246. package/package.json +12 -2
  247. package/src/access-service-coding-write.test.ts +2 -2
  248. package/src/access-service.ts +33 -14
  249. package/src/bitemporal-dedup-backfill.test.ts +10 -10
  250. package/src/bitemporal-frontmatter.test.ts +3 -3
  251. package/src/capabilities.test.ts +185 -0
  252. package/src/capabilities.ts +110 -0
  253. package/src/cli/creation-ledger-commands.ts +22 -21
  254. package/src/coding/architecture-surfaces.test.ts +25 -1
  255. package/src/coding/architecture-surfaces.ts +47 -19
  256. package/src/coding/decision-surfaces.ts +12 -3
  257. package/src/coding/review-context-structural.test.ts +303 -0
  258. package/src/coding/review-context.ts +79 -0
  259. package/src/coding/structural-context.test.ts +259 -0
  260. package/src/coding/structural-context.ts +315 -0
  261. package/src/coding/structural-subprocess-provider.test.ts +430 -0
  262. package/src/coding/structural-subprocess-provider.ts +355 -0
  263. package/src/compounding/engine.test.ts +90 -0
  264. package/src/compounding/engine.ts +25 -1
  265. package/src/contradiction/contradiction.test.ts +1 -1
  266. package/src/contradiction/resolution.ts +9 -1
  267. package/src/correction/correction-access-wiring.ts +21 -3
  268. package/src/correction/correction-contract.ts +7 -0
  269. package/src/correction/correction-planner.test.ts +231 -0
  270. package/src/correction/correction-planner.ts +73 -0
  271. package/src/correction/correction-service.ts +29 -0
  272. package/src/correction/correction-storage-integration.test.ts +2 -2
  273. package/src/dedup/semantic.test.ts +1 -1
  274. package/src/explicit-capture.ts +7 -4
  275. package/src/extraction-eventtime-wiring.test.ts +3 -3
  276. package/src/extraction-redaction-rules.test.ts +172 -0
  277. package/src/index.ts +29 -0
  278. package/src/maintenance/forget.test.ts +1 -1
  279. package/src/maintenance/memory-governance.test.ts +1 -1
  280. package/src/maintenance/pattern-reinforcement.test.ts +2 -2
  281. package/src/operator-toolkit.ts +4 -3
  282. package/src/orchestration/compression-guideline-coordinator.ts +449 -0
  283. package/src/orchestrator.ts +345 -464
  284. package/src/procedural/procedure-miner.test.ts +2 -2
  285. package/src/provenance-extraction.test.ts +382 -4
  286. package/src/provenance.ts +158 -22
  287. package/src/recall-handles-wiring.test.ts +1 -1
  288. package/src/search/factory.ts +4 -3
  289. package/src/semantic-rule-promotion.ts +1 -1
  290. package/src/source-attribution-roundtrip.test.ts +2 -2
  291. package/src/storage-contract/atomicity.test.ts +1 -1
  292. package/src/storage-contract/cache-coherence.test.ts +2 -2
  293. package/src/storage-contract/content-hash.test.ts +1 -1
  294. package/src/storage-contract/namespace-routing.test.ts +1 -1
  295. package/src/storage-contract/round-trip.test.ts +3 -3
  296. package/src/storage.ts +23 -2
  297. package/src/temporal-supersession.test.ts +12 -11
  298. package/src/temporal-validity.test.ts +11 -11
  299. package/src/wearables/cli.test.ts +30 -0
  300. package/src/wearables/cli.ts +3 -0
  301. package/src/wearables/memory-gen.test.ts +57 -1
  302. package/src/wearables/memory-gen.ts +31 -7
  303. package/src/wearables/pipeline.test.ts +40 -1
  304. package/src/wearables/pipeline.ts +4 -0
  305. package/src/wearables/service.test.ts +2 -2
  306. package/src/wearables/storage-io.test.ts +3 -3
  307. package/src/wearables/types.ts +7 -0
  308. package/dist/chunk-4NR2PDZ5.js.map +0 -1
  309. package/dist/chunk-4T3BMHKD.js.map +0 -1
  310. package/dist/chunk-7RLCCNHU.js.map +0 -1
  311. package/dist/chunk-AQLOP5F4.js.map +0 -1
  312. package/dist/chunk-EH5ED3C6.js.map +0 -1
  313. package/dist/chunk-HEDZUSCS.js.map +0 -1
  314. package/dist/chunk-M4AYVEWS.js.map +0 -1
  315. package/dist/chunk-UM5AWJNQ.js.map +0 -1
  316. package/dist/chunk-UTHQPSRC.js.map +0 -1
  317. package/dist/chunk-YKBHOBJK.js.map +0 -1
  318. /package/dist/{auto-sync-F3KCSQFJ.js.map → auto-sync-G3V5AN4C.js.map} +0 -0
  319. /package/dist/{chunk-4NOI577P.js.map → chunk-24ZLC5QN.js.map} +0 -0
  320. /package/dist/{chunk-DMQWV6SQ.js.map → chunk-5RZOFIDL.js.map} +0 -0
  321. /package/dist/{chunk-36SEDFAU.js.map → chunk-C5WN74HH.js.map} +0 -0
  322. /package/dist/{chunk-MLKWJOAJ.js.map → chunk-CGPHMNL4.js.map} +0 -0
  323. /package/dist/{chunk-EY6MDMHK.js.map → chunk-F6OEXJQQ.js.map} +0 -0
  324. /package/dist/{chunk-M4V2JVSZ.js.map → chunk-FFUCCKPN.js.map} +0 -0
  325. /package/dist/{chunk-O6YH5F47.js.map → chunk-FYWUNVFZ.js.map} +0 -0
  326. /package/dist/{chunk-37436GML.js.map → chunk-GEXI357K.js.map} +0 -0
  327. /package/dist/{chunk-YGIQORJ3.js.map → chunk-GGL34GCW.js.map} +0 -0
  328. /package/dist/{chunk-WAS3NV46.js.map → chunk-H3MB3F62.js.map} +0 -0
  329. /package/dist/{chunk-76NHR6ZL.js.map → chunk-HJWQJUKQ.js.map} +0 -0
  330. /package/dist/{chunk-Y4YD5TYW.js.map → chunk-IIBFCZA7.js.map} +0 -0
  331. /package/dist/{chunk-UVPL565C.js.map → chunk-IQOEW5YV.js.map} +0 -0
  332. /package/dist/{chunk-V4GNSDFH.js.map → chunk-KQYGNGON.js.map} +0 -0
  333. /package/dist/{chunk-CBWI22JN.js.map → chunk-KSJCXXOU.js.map} +0 -0
  334. /package/dist/{chunk-I5REUWLH.js.map → chunk-NIZQH6AU.js.map} +0 -0
  335. /package/dist/{chunk-4ESAR77N.js.map → chunk-NOU77OHX.js.map} +0 -0
  336. /package/dist/{chunk-BQCHEV7O.js.map → chunk-O4ZIBPIW.js.map} +0 -0
  337. /package/dist/{chunk-HOHVIVDR.js.map → chunk-OBJUKYDO.js.map} +0 -0
  338. /package/dist/{chunk-YOLZS7NY.js.map → chunk-OTQE66IX.js.map} +0 -0
  339. /package/dist/{chunk-C2PG7IEH.js.map → chunk-P3VJCTVE.js.map} +0 -0
  340. /package/dist/{chunk-HGNOCPZX.js.map → chunk-QZHF4BWN.js.map} +0 -0
  341. /package/dist/{chunk-ASKXIAHD.js.map → chunk-WDJCZQB4.js.map} +0 -0
  342. /package/dist/{chunk-JYLFZWUX.js.map → chunk-XYUFGHUW.js.map} +0 -0
  343. /package/dist/{chunk-3TSTGI6F.js.map → chunk-ZQUAVZNG.js.map} +0 -0
  344. /package/dist/{first-start-migration-22LPFHD5.js.map → first-start-migration-OOR57AYR.js.map} +0 -0
  345. /package/dist/{resolution-MN36NW5P.js.map → orchestration/compression-guideline-coordinator.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/correction/correction-contract.ts","../src/correction/correction-access-wiring.ts","../src/correction/correction-planner.ts","../src/correction/correction-executor.ts","../src/correction/correction-service.ts","../src/correction/passive-correction-detector.ts","../src/correction/passive-capture.ts","../src/procedural/reinforcement-core.ts"],"sourcesContent":["/**\n * correction/correction-contract.ts — Types for the Correction Contract\n * (issue #1580).\n *\n * The Correction Contract is the SINGLE plan/apply pipeline every memory\n * correction flows through: supersession, invalidation, tombstone, edit,\n * rescope, redaction. A correction arrives as a plain-language statement\n * (\"we migrated to MySQL in March\"); the planner turns it into a structured\n * {@link CorrectionPlan}; the executor applies the plan in non-destructive\n * order through the existing storage/orchestrator chokepoints.\n *\n * This module is PURE types + validation helpers — no I/O, no side effects.\n * The planner and executor live in sibling modules and inject their own\n * collaborators so the contract is testable in isolation (rule 33).\n *\n * Design rules honored (issue #1580 design section):\n * - Plans are per-request state on disk, never module-level (rules 11/47).\n * - Caller-supplied namespaces are NEVER trusted raw — the service\n * resolves them through the normal namespace policy (rule 42).\n * - Bulk operations refuse past maxAffected (no silent truncation, §39).\n * - `never_store` redaction patterns must be bounded and safe (§34).\n */\n\nimport type { MemoryCategory, MemoryFrontmatter } from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Request\n// ---------------------------------------------------------------------------\n\n/**\n * The user-facing input: a plain-language correction plus optional explicit\n * targets. This is what every surface (MCP / HTTP / CLI) collects before\n * handing off to the planner.\n */\nexport interface CorrectionRequest {\n /** Natural-language correction statement. Required, non-empty. */\n text: string;\n /**\n * Explicit target memory ids (or handles via #1582). When present the\n * planner resolves these directly; an unknown id is an explicit error\n * (rule 34), never a silent empty plan. When absent the planner searches.\n */\n targetIds?: string[];\n /** Session key for namespace/principal resolution. */\n sessionKey?: string;\n /** Authenticated principal (resolved by the service, never trusted raw). */\n principal?: string;\n /**\n * Caller-suggested namespace. ALWAYS re-resolved through the namespace\n * policy by the service before reaching the planner (rule 42). The\n * planner only sees the ALREADY-AUTHORIZED namespace.\n */\n namespace?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Classification + actions\n// ---------------------------------------------------------------------------\n\nexport type CorrectionClassification =\n | \"wrong\"\n | \"outdated\"\n | \"incomplete\"\n | \"wrong_scope\"\n | \"never_store\";\n\nexport const CORRECTION_CLASSIFICATIONS: readonly CorrectionClassification[] = [\n \"wrong\",\n \"outdated\",\n \"incomplete\",\n \"wrong_scope\",\n \"never_store\",\n];\n\n/**\n * A draft for a replacement memory (supersede action). Mirrors the subset of\n * {@link MemoryFrontmatter} a correction caller may legitimately set; the\n * executor fills in id/created/updated/source.\n */\nexport interface MemoryDraft {\n content: string;\n category?: MemoryCategory;\n confidence?: number;\n tags?: string[];\n entityRef?: string;\n /** Optional event-time anchor for bi-temporal supersession (#1578). */\n validAt?: string;\n /** Optional observed-at anchor for bi-temporal supersession (#1578). */\n observedAt?: string;\n structuredAttributes?: Record<string, string>;\n}\n\n/**\n * The known {@link MemoryCategory} values. A replacement/rescope category must\n * be one of these — rejecting path-like or unexpected strings before they reach\n * `StorageManager.writeMemory`, which incorporates the category into the\n * generated memory id/path (review thread Of-XJ).\n */\nexport const MEMORY_CATEGORIES: readonly MemoryCategory[] = [\n \"fact\", \"preference\", \"correction\", \"entity\", \"decision\",\n \"relationship\", \"principle\", \"commitment\", \"moment\",\n \"skill\", \"rule\", \"procedure\", \"reasoning_trace\",\n];\n\nexport type CorrectionAction =\n /** Outdated: a new fact replaces the loser. */\n | { kind: \"supersede\"; loserId: string; replacement?: MemoryDraft }\n /** Incomplete / minor-wrong: a versioned edit to an existing memory. */\n | { kind: \"edit\"; memoryId: string; patch: string }\n /** Wrong: retire + tombstone. */\n | { kind: \"retract\"; memoryId: string }\n /** Wrong scope: move to a different namespace. */\n | { kind: \"rescope\"; memoryId: string; toNamespace: string }\n /** Never-store: a future-extraction redaction rule. */\n | { kind: \"redaction_rule\"; pattern: string };\n\nexport const CORRECTION_ACTION_KINDS: readonly CorrectionAction[\"kind\"][] = [\n \"supersede\",\n \"edit\",\n \"retract\",\n \"rescope\",\n \"redaction_rule\",\n];\n\n// ---------------------------------------------------------------------------\n// Plan + outcome\n// ---------------------------------------------------------------------------\n\n/**\n * One affected memory in a plan: where it lives, an excerpt, why it is\n * affected, and (when available) the source quote that supports the\n * correction (#1575 provenance).\n */\nexport interface CorrectionAffectedEntry {\n memoryId: string;\n /** File path relative to the storage dir, for diff rendering. */\n path: string;\n excerpt: string;\n why: string;\n sourceQuote?: string;\n}\n\n/**\n * A persisted, expiring correction plan. Read-only artifact produced by the\n * planner; consumed (once) by the executor.\n */\nexport interface CorrectionPlan {\n planId: string;\n request: CorrectionRequest;\n /** Authorized namespace the plan is scoped to (resolved by the service). */\n namespace: string;\n affected: CorrectionAffectedEntry[];\n classification: CorrectionClassification;\n actions: CorrectionAction[];\n /** Human-readable diff preview rendered via page-versioning. */\n diff: string;\n /** Planner confidence in [0, 1]. `0` means manual selection required. */\n confidence: number;\n warnings: string[];\n createdAt: string;\n /** ISO timestamp after which apply rejects the plan as expired. */\n expiresAt: string;\n /**\n * Lifecycle: `pending` → `applying` → `applied`|`partial` (or `discarded`).\n * The executor flips a plan to `applying` BEFORE running any mutation\n * (review thread OgIqt): if the process dies mid-apply, the plan stays\n * `applying` and is NOT silently retryable — a partially-applied plan must\n * never be re-applied wholesale (it would duplicate succeeded actions).\n */\n status?: \"pending\" | \"applying\" | \"applied\" | \"discarded\" | \"partial\";\n}\n\n/**\n * Per-action outcome recorded by the executor. An action whose new-state\n * write failed is `failed`; the executor never destroys old state for a\n * failed action (rule 25 / checklist §14).\n */\nexport interface CorrectionActionResult {\n action: CorrectionAction;\n status: \"applied\" | \"failed\" | \"skipped\";\n /** For supersede: the new memory id. For edit: the memory id. */\n memoryId?: string;\n /** For supersede/retract: the emitted tombstone id (if any). */\n tombstoneId?: string;\n error?: string;\n}\n\nexport interface CorrectionOutcome {\n planId: string;\n status: \"applied\" | \"partial\";\n results: CorrectionActionResult[];\n /** Audit-record memory id (corrections are themselves memories). */\n auditMemoryId: string;\n /** ISO timestamp of the apply. */\n appliedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// Validation helpers (pure) — shared by planner, executor, and surface tests\n// ---------------------------------------------------------------------------\n\n/** Maximum supported `text` length. Surfaces bound this earlier; the planner\n * re-validates so a direct-service caller cannot bypass. */\nexport const CORRECTION_TEXT_MAX = 10_000;\n\n/** Maximum supported redaction pattern length (§34 — bounded patterns). */\nexport const REDACTION_PATTERN_MAX = 256;\n\n/**\n * Validate a {@link CorrectionRequest}'s invariants. Returns the cleaned\n * request or throws with a field-specific message (rule 51 — list valid\n * options, never silently default).\n */\nexport function validateCorrectionRequest(request: CorrectionRequest): CorrectionRequest {\n if (!request || typeof request !== \"object\") {\n throw new CorrectionContractError(\"CorrectionRequest must be an object.\");\n }\n const text = typeof request.text === \"string\" ? request.text.trim() : \"\";\n if (text.length === 0) {\n throw new CorrectionContractError(\"CorrectionRequest.text is required and must be non-empty.\");\n }\n if (text.length > CORRECTION_TEXT_MAX) {\n throw new CorrectionContractError(\n `CorrectionRequest.text exceeds the ${CORRECTION_TEXT_MAX}-character limit (${text.length}).`,\n );\n }\n const targetIds = Array.isArray(request.targetIds)\n ? request.targetIds.filter((id): id is string => typeof id === \"string\" && id.length > 0)\n : undefined;\n if (targetIds !== undefined && targetIds.length === 0) {\n // An empty array is treated as \"not provided\" so callers can forward\n // optional fields without a separate presence flag.\n return {\n text,\n ...(request.sessionKey ? { sessionKey: request.sessionKey } : {}),\n ...(request.principal ? { principal: request.principal } : {}),\n ...(request.namespace ? { namespace: request.namespace } : {}),\n };\n }\n return {\n text,\n ...(targetIds ? { targetIds } : {}),\n ...(request.sessionKey ? { sessionKey: request.sessionKey } : {}),\n ...(request.principal ? { principal: request.principal } : {}),\n ...(request.namespace ? { namespace: request.namespace } : {}),\n };\n}\n\n/**\n * Validate a redaction pattern (§34 — bounded, literal-or-safe-regex; reject\n * catastrophic patterns). Returns the cleaned pattern or throws.\n */\nexport function validateRedactionPattern(pattern: string): string {\n if (typeof pattern !== \"string\") {\n throw new CorrectionContractError(\"redaction_rule.pattern must be a string.\");\n }\n const trimmed = pattern.trim();\n if (trimmed.length === 0) {\n throw new CorrectionContractError(\"redaction_rule.pattern is required.\");\n }\n if (trimmed.length > REDACTION_PATTERN_MAX) {\n throw new CorrectionContractError(\n `redaction_rule.pattern exceeds the ${REDACTION_PATTERN_MAX}-character bound.`,\n );\n }\n // Reject patterns that could match an unbounded string (overly-broad) OR\n // exhibit catastrophic backtracking (nested quantifiers like `(a+)+`). We do\n // NOT execute the regex (that would be ReDoS itself); we only inspect shape.\n if (isRegexLike(trimmed) && isUnsafeRedactionRegex(trimmed)) {\n throw new CorrectionContractError(\n \"redaction_rule.pattern is unsafe — use a bounded literal or a regex without nested quantifiers / overlapping alternation.\",\n );\n }\n // #1669 P2: reject zero-width regex (empty body or matches empty string)\n // that would withhold every fact.\n if (isRegexLike(trimmed)) {\n const regexBody = trimmed.slice(1, -1);\n if (regexBody.length === 0) {\n throw new CorrectionContractError(\"redaction_rule.pattern body is empty — use a non-empty regex.\");\n }\n try {\n if (new RegExp(regexBody).test(\"\")) {\n throw new CorrectionContractError(\n \"redaction_rule.pattern matches the empty string — it would withhold every fact.\",\n );\n }\n } catch (e) {\n if (e instanceof CorrectionContractError) throw e;\n // Compilation failed — the extraction-time defense handles it.\n }\n }\n return trimmed;\n}\n\n/** Only `/.../`-wrapped patterns are treated as regex; everything else is a\n * literal (review thread P1 — consistent with extraction-redaction-rules.ts). */\nfunction isRegexLike(pattern: string): boolean {\n return pattern.startsWith(\"/\") && pattern.endsWith(\"/\") && pattern.length >= 2;\n}\n\n/**\n * Reject a regex that would either match an arbitrary-length run of any\n * character (overly-broad) OR exhibit catastrophic backtracking (ReDoS).\n * Mirrors the safe-regex heuristic in extraction-redaction-rules.ts so the\n * apply-time chokepoint and the extraction-time defense agree on what is\n * pathological — intentionally not imported to keep the two modules decoupled\n * (contract owns validation; extraction owns consultation).\n */\nfunction isUnsafeRedactionRegex(pattern: string): boolean {\n const body = pattern.startsWith(\"/\") && pattern.endsWith(\"/\")\n ? pattern.slice(1, -1)\n : pattern;\n // `.*`, `.+`, `.`, or `(.*)` etc. anywhere → overly broad.\n if (/(?:^|[^\\\\])\\(\\.\\*\\)|(?:^|[^\\\\])\\.\\*|(?:^|[^\\\\])\\.\\+|^\\.([^*+]?)$/.test(body)) {\n return true;\n }\n // Nested quantifier: a group (...) whose body ends with a quantifier and\n // which is itself quantified → exponential blowup on near-miss inputs\n // (classic ReDoS shapes: (a+)+, (a*)*, (a?)+). Also catches overlapping\n // alternation under repetition: (a|a)+ where branches share a prefix.\n if (body.length > 512) return true;\n for (let i = 0; i < body.length; i++) {\n if (body[i] !== \"(\") continue;\n let depth = 1;\n let j = i + 1;\n while (j < body.length && depth > 0) {\n if (body[j] === \"\\\\\") { j += 2; continue; }\n if (body[j] === \"(\") depth++;\n else if (body[j] === \")\") depth--;\n j++;\n }\n if (depth !== 0) continue;\n const afterGroup = body[j];\n if (afterGroup !== \"+\" && afterGroup !== \"*\" && afterGroup !== \"{\") continue;\n const groupBody = body.slice(i + 1, j - 1);\n if (/[+*?]$/.test(groupBody) || /\\{\\d+,?\\d*\\}[+*?]?$/.test(groupBody)) {\n return true;\n }\n if (groupBody.includes(\"|\")) {\n const branches = groupBody.split(\"|\");\n if (branches.length >= 2) {\n const firstChars = new Set(branches.map((b) => b[0]).filter(Boolean));\n if (firstChars.size < branches.filter((b) => b.length > 0).length) {\n return true;\n }\n }\n }\n i = j;\n }\n return false;\n}\n\n/**\n * Validate the shape of a {@link CorrectionAction}. Used by the executor\n * before applying and by the surface layer to reject malformed client input\n * (rule 51 — list valid kinds).\n */\nexport function validateCorrectionAction(action: unknown): asserts action is CorrectionAction {\n if (!action || typeof action !== \"object\") {\n throw new CorrectionContractError(\"CorrectionAction must be an object.\");\n }\n const a = action as Record<string, unknown>;\n if (typeof a.kind !== \"string\" || !CORRECTION_ACTION_KINDS.includes(a.kind as CorrectionAction[\"kind\"])) {\n throw new CorrectionContractError(\n `CorrectionAction.kind must be one of: ${CORRECTION_ACTION_KINDS.join(\", \")}.`,\n );\n }\n switch (a.kind) {\n case \"supersede\":\n if (typeof a.loserId !== \"string\" || a.loserId.length === 0) {\n throw new CorrectionContractError(\"supersede.loserId is required.\");\n }\n if (a.replacement !== undefined && a.replacement !== null) {\n validateMemoryDraft(a.replacement);\n }\n break;\n case \"edit\":\n if (typeof a.memoryId !== \"string\" || a.memoryId.length === 0) {\n throw new CorrectionContractError(\"edit.memoryId is required.\");\n }\n if (typeof a.patch !== \"string\" || a.patch.length === 0) {\n throw new CorrectionContractError(\"edit.patch is required and must be non-empty.\");\n }\n break;\n case \"retract\":\n if (typeof a.memoryId !== \"string\" || a.memoryId.length === 0) {\n throw new CorrectionContractError(\"retract.memoryId is required.\");\n }\n break;\n case \"rescope\":\n if (typeof a.memoryId !== \"string\" || a.memoryId.length === 0) {\n throw new CorrectionContractError(\"rescope.memoryId is required.\");\n }\n if (typeof a.toNamespace !== \"string\" || a.toNamespace.trim().length === 0) {\n throw new CorrectionContractError(\"rescope.toNamespace is required.\");\n }\n break;\n case \"redaction_rule\":\n if (typeof a.pattern !== \"string\") {\n throw new CorrectionContractError(\"redaction_rule.pattern is required.\");\n }\n validateRedactionPattern(a.pattern);\n break;\n }\n}\n\n/** Validate a {@link MemoryDraft}. Throws on invalid shape. */\nexport function validateMemoryDraft(draft: unknown): asserts draft is MemoryDraft {\n if (!draft || typeof draft !== \"object\") {\n throw new CorrectionContractError(\"MemoryDraft must be an object.\");\n }\n const d = draft as Record<string, unknown>;\n if (typeof d.content !== \"string\" || d.content.trim().length === 0) {\n throw new CorrectionContractError(\"MemoryDraft.content is required and must be non-empty.\");\n }\n if (d.category !== undefined) {\n if (typeof d.category !== \"string\" || !(MEMORY_CATEGORIES as readonly string[]).includes(d.category)) {\n throw new CorrectionContractError(\n `MemoryDraft.category must be one of: ${MEMORY_CATEGORIES.join(\", \")}.`,\n );\n }\n }\n if (d.confidence !== undefined && (typeof d.confidence !== \"number\" || d.confidence < 0 || d.confidence > 1)) {\n throw new CorrectionContractError(\"MemoryDraft.confidence must be a number in [0, 1].\");\n }\n if (d.tags !== undefined && !Array.isArray(d.tags)) {\n throw new CorrectionContractError(\"MemoryDraft.tags must be an array.\");\n }\n if (d.structuredAttributes !== undefined && (typeof d.structuredAttributes !== \"object\" || d.structuredAttributes === null)) {\n throw new CorrectionContractError(\"MemoryDraft.structuredAttributes must be an object.\");\n }\n}\n\n/**\n * Deterministic fallback plan (rule 13): when the planner's LLM is\n * unavailable, the plan degrades to a search result, never an error page.\n * Classification `outdated`, confidence `0`, actions empty.\n */\nexport function deterministicFallbackPlan(args: {\n request: CorrectionRequest;\n namespace: string;\n affected: CorrectionAffectedEntry[];\n warnings: string[];\n createdAt: string;\n expiresAt: string;\n}): CorrectionPlan {\n return {\n planId: newPlanId(),\n request: args.request,\n namespace: args.namespace,\n affected: args.affected,\n classification: \"outdated\",\n actions: [],\n diff: \"\",\n confidence: 0,\n warnings: [...args.warnings, \"planner LLM unavailable — manual action selection required\"],\n createdAt: args.createdAt,\n expiresAt: args.expiresAt,\n status: \"pending\",\n };\n}\n\n/** Generate a stable plan id. Exposed for tests + deterministic fallback. */\nexport function newPlanId(): string {\n return `corr-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\n/** Error class for contract violations. Surfaces map it to a 400 / input error. */\nexport class CorrectionContractError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"CorrectionContractError\";\n }\n}\n","/**\n * correction/correction-access-wiring.ts — wires the CorrectionService to the\n * orchestrator's storage / tombstone / search surfaces (issue #1580 PR 3).\n *\n * Keeps the access-service god-file thin: the service calls `createCorrectionService`\n * with two namespace-policy callbacks and gets back a fully-wired\n * {@link CorrectionService}. All the heavy lifting (search, LLM classify,\n * tombstone emission, audit-record write, propagation) lives here, in a\n * dedicated module, so the only growth in access-service.ts is the four\n * one-line delegators.\n *\n * Design rules honored:\n * - Caller-supplied namespaces are NEVER trusted raw — the service resolves\n * them through the injected policy (rule 42).\n * - Corrections flow through the existing storage chokepoints: writeMemory\n * (catalog/dedup/reindex fire — rule 43), appendTombstone (#1579),\n * writeMemoryFrontmatter (status flip + validUntil — #1578).\n * - The LLM classify+draft adapter routes through the existing extraction\n * engine (Responses API only, gotcha 1). On any LLM failure the adapter\n * returns a deterministic fallback so the planner never throws (rule 13).\n */\n\nimport path from \"node:path\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport type { Orchestrator } from \"../orchestrator.js\";\nimport type { MemoryFile, MemoryStatus, PluginConfig } from \"../types.js\";\nimport { stripAttributesSuffix } from \"../structured-attributes.js\";\nimport { supersessionKeysForFact } from \"../temporal-supersession.js\";\nimport { computeContentHash } from \"../content-hash.js\";\nimport { sanitizeMemoryContent } from \"../sanitize.js\";\nimport {\n CorrectionContractError,\n validateCorrectionAction,\n type CorrectionAction,\n type CorrectionOutcome,\n type CorrectionPlan,\n} from \"./correction-contract.js\";\nimport {\n type LlmClassificationResult,\n type PlannerCandidate,\n type PlannerDeps,\n} from \"./correction-planner.js\";\nimport { type ExecutorDeps, type ExecutorMemory } from \"./correction-executor.js\";\nimport { CorrectionService, type CorrectionServiceDeps } from \"./correction-service.js\";\n\n// ---------------------------------------------------------------------------\n// Public entry: build a fully-wired CorrectionService\n// ---------------------------------------------------------------------------\n\n/**\n * The two namespace-policy callbacks the access-service supplies. These are\n * the ONLY surface-area touch-points between the correction modules and the\n * access-service god-file — everything else is wired from the orchestrator.\n */\nexport interface CorrectionAccessWiring {\n orchestrator: Orchestrator;\n /** Resolve the AUTHORIZED namespace for a plan/apply request (write ACL). */\n resolveAuthorizedNamespace(request: {\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<string>;\n /** Resolve the caller's READABLE namespaces (scopes the planner's search). */\n resolveReadableNamespaces(request: {\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n }): readonly string[];\n /** Whether the caller may WRITE a namespace — authorizes rescope destinations. */\n canWriteNamespace(request: {\n namespace: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<boolean>;\n /**\n * Optional LLM-complete callback (Responses API only — gotcha 1). When\n * absent, the planner's classify+draft step falls back to deterministic\n * mode (rule 13). The access-service wires the orchestrator's extraction\n * LLM here once it exposes a public accessor; until then the contract\n * ships with the safe fallback.\n */\n llmComplete?(request: {\n system: string;\n user: string;\n }): Promise<string>;\n}\n\nexport function createCorrectionService(wiring: CorrectionAccessWiring): CorrectionService {\n const cfg = wiring.orchestrator.config;\n // parseConfig now owns these (review thread Txp): the orchestrator's config\n // carries correctionEnabled / correctionApplyRequiresConfirm /\n // correctionMaxAffected / correctionPlanTtlHours as parsed fields. The\n // loose-read helpers stay as a fallback only for tests that construct a\n // PluginConfig-shaped object without running parseConfig.\n const correctionEnabled = isCorrectionFeatureEnabled(cfg);\n const applyRequiresConfirm =\n typeof cfg.correctionApplyRequiresConfirm === \"boolean\"\n ? cfg.correctionApplyRequiresConfirm\n : readCorrectionFlag(cfg, \"applyRequiresConfirm\", true);\n const maxAffected =\n typeof cfg.correctionMaxAffected === \"number\" && cfg.correctionMaxAffected >= 1\n ? Math.floor(cfg.correctionMaxAffected)\n : readCorrectionNumber(cfg, \"maxAffected\", 10);\n const planTtlHours =\n typeof cfg.correctionPlanTtlHours === \"number\" && cfg.correctionPlanTtlHours > 0\n ? cfg.correctionPlanTtlHours\n : readCorrectionNumber(cfg, \"planTtlHours\", 24);\n const biTemporalEnabled = cfg.temporalBiTemporal === true;\n\n const serviceDeps: CorrectionServiceDeps = {\n policy: {\n resolveAuthorizedNamespace: (req) => wiring.resolveAuthorizedNamespace(req),\n canWriteNamespace: (req) => wiring.canWriteNamespace(req),\n readableNamespaces: (req) =>\n Promise.resolve(wiring.resolveReadableNamespaces(req)),\n },\n plannerDeps: () =>\n makePlannerDeps(wiring, { maxAffected, planTtlHours }),\n executorDeps: () => makeExecutorDeps(wiring, { biTemporalEnabled }),\n isEnabled: () => correctionEnabled,\n applyRequiresConfirm: () => applyRequiresConfirm,\n };\n return new CorrectionService(serviceDeps);\n}\n\n// ---------------------------------------------------------------------------\n// Planner deps\n// ---------------------------------------------------------------------------\n\nfunction makePlannerDeps(\n wiring: CorrectionAccessWiring,\n opts: { maxAffected: number; planTtlHours: number },\n): PlannerDeps {\n return {\n searchCorpus: async ({ text, namespaces, limit }) =>\n searchMemories(wiring, text, namespaces, limit),\n resolveTargets: async ({ targetIds, namespaces }) =>\n resolveTargetMemories(wiring, targetIds, namespaces),\n expandNeighbors: async ({ seedIds, namespaces, limit }) =>\n expandEntityNeighbors(wiring, seedIds, namespaces, limit),\n classifyAndDraft: async ({ text, candidates }) =>\n classifyAndDraft(wiring, text, candidates),\n renderDiff: async ({ candidates, actions }) =>\n renderCorrectionDiff(wiring, candidates, actions),\n storageDir: async (namespace) => (await wiring.orchestrator.getStorage(namespace)).dir,\n maxAffected: opts.maxAffected,\n planTtlHours: opts.planTtlHours,\n now: () => new Date(),\n };\n}\n\nasync function searchMemories(\n wiring: CorrectionAccessWiring,\n text: string,\n namespaces: readonly string[],\n limit: number,\n): Promise<PlannerCandidate[]> {\n // Tokenized keyword search (review thread OgIql): natural-language\n // corrections describe the new truth, not quote the old memory verbatim\n // (\"we migrated from Postgres to MySQL\" vs a memory saying \"Postgres is\n // the database\"). The old 32-char exact-prefix substring missed these.\n // We tokenize the correction into keywords, score each active memory by\n // keyword overlap, and return memories above a minimum threshold. This is\n // deliberately lightweight (no embedding/QMD dependency) — the planner's\n // job is to LOCATE candidates for the LLM classify+draft, not to rank with\n // the full recall pipeline.\n const tokens = tokenize(text);\n if (tokens.length === 0) return [];\n const scored: Array<{ m: MemoryFile; ns: string; score: number }> = [];\n for (const ns of namespaces) {\n const storage = await wiring.orchestrator.getStorage(ns);\n const all = await storage.readAllMemories();\n for (const m of all) {\n if (!isEligibleCorrectionCandidate(m)) continue;\n const hay = `${m.content} ${m.frontmatter.tags?.join(\" \") ?? \"\"}`.toLowerCase();\n let hits = 0;\n for (const tok of tokens) {\n if (hay.includes(tok)) hits++;\n }\n if (hits === 0) continue;\n // Overlap ratio: how many query tokens the memory covers.\n scored.push({ m, ns, score: hits / tokens.length });\n }\n }\n scored.sort((a, b) => b.score - a.score);\n return scored.slice(0, limit).map((s, i) => toCandidate(s.m, s.ns, s.score - i * 0.01));\n}\n\n/** Tokenize correction text into lowercase search keywords (OgIql). */\nfunction tokenize(text: string): string[] {\n const STOP = new Set([\n \"the\", \"a\", \"an\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\n \"to\", \"of\", \"in\", \"on\", \"at\", \"by\", \"for\", \"with\", \"from\", \"into\",\n \"and\", \"or\", \"but\", \"not\", \"no\", \"yes\", \"this\", \"that\", \"these\",\n \"those\", \"it\", \"its\", \"we\", \"you\", \"i\", \"he\", \"she\", \"they\", \"them\",\n \"our\", \"your\", \"my\", \"his\", \"her\", \"their\", \"as\", \"so\", \"if\", \"then\",\n \"than\", \"too\", \"very\", \"can\", \"will\", \"just\", \"should\", \"now\", \"has\",\n \"have\", \"had\", \"do\", \"does\", \"did\", \"about\", \"which\", \"what\", \"who\",\n \"when\", \"where\", \"why\", \"how\", \"all\", \"each\", \"every\", \"both\", \"few\",\n \"more\", \"most\", \"other\", \"some\", \"such\", \"only\", \"own\", \"same\", \"up\",\n ]);\n const raw = text.toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);\n const out = raw.filter((w) => w.length >= 3 && !STOP.has(w));\n // De-dup while preserving order.\n return [...new Set(out)];\n}\n\nasync function resolveTargetMemories(\n wiring: CorrectionAccessWiring,\n targetIds: readonly string[],\n namespaces: readonly string[],\n): Promise<PlannerCandidate[]> {\n const out: PlannerCandidate[] = [];\n const missing: string[] = [];\n for (const id of targetIds) {\n let found: PlannerCandidate | null = null;\n for (const ns of namespaces) {\n const storage = await wiring.orchestrator.getStorage(ns);\n const m = await storage.getMemoryById(id);\n if (m) {\n found = toCandidate(m, ns, 1);\n break;\n }\n }\n if (found) out.push(found);\n else missing.push(id);\n }\n if (missing.length > 0) {\n throw new CorrectionContractError(`target memory not found: ${missing[0]}`);\n }\n return out;\n}\n\nasync function expandEntityNeighbors(\n wiring: CorrectionAccessWiring,\n seedIds: readonly string[],\n namespaces: readonly string[],\n limit: number,\n): Promise<PlannerCandidate[]> {\n // 1-hop entity-graph neighbors via entityRef-tagged siblings. We expand\n // across the AUTHORIZED namespaces the planner supplied (review thread PG8),\n // NOT only `config.defaultNamespace` — a correction planned in a non-default\n // writable namespace must only ever draft siblings from that same authorized\n // scope, or apply will fail as not-found / mutate a same-ID memory in the\n // wrong namespace. The conservative entityRef fallback searches every\n // readable namespace and tags each candidate with the namespace it was read\n // from; a richer graph expansion can ride on top later (rule 57 — additive).\n if (seedIds.length === 0 || limit <= 0 || namespaces.length === 0) return [];\n const out: PlannerCandidate[] = [];\n const seen = new Set<string>(seedIds);\n // Collect the seed entityRefs across every authorized namespace (a seed\n // memory may live in any of them), then surface active siblings sharing one.\n const seedRefs = new Set<string>();\n for (const ns of namespaces) {\n const storage = await wiring.orchestrator.getStorage(ns);\n const all = await storage.readAllMemories();\n for (const m of all) {\n if (seedIds.includes(m.frontmatter.id) && m.frontmatter.entityRef) {\n seedRefs.add(m.frontmatter.entityRef);\n }\n }\n }\n if (seedRefs.size === 0) return [];\n for (const ns of namespaces) {\n if (out.length >= limit) break;\n const storage = await wiring.orchestrator.getStorage(ns);\n const all = await storage.readAllMemories();\n for (const m of all) {\n if (out.length >= limit) break;\n if (seen.has(m.frontmatter.id)) continue;\n if (!isEligibleCorrectionCandidate(m)) continue;\n if (m.frontmatter.entityRef && seedRefs.has(m.frontmatter.entityRef)) {\n out.push(toCandidate(m, ns, 0.5));\n seen.add(m.frontmatter.id);\n }\n }\n }\n return out;\n}\n\nasync function classifyAndDraft(\n wiring: CorrectionAccessWiring,\n text: string,\n candidates: PlannerCandidate[],\n): Promise<LlmClassificationResult> {\n // Route through the injected LLM callback (Responses API only — gotcha 1).\n // On any failure (or when no callback is wired), return the deterministic\n // fallback (rule 13) — the planner never throws on an LLM outage.\n try {\n if (!wiring.llmComplete) {\n return fallbackClassification(candidates, \"no LLM client available\");\n }\n const user = buildClassifyPrompt(text, candidates);\n const raw = await wiring.llmComplete({ system: CLASSIFY_SYSTEM_PROMPT, user });\n return parseClassifyResponse(raw, candidates);\n } catch (err) {\n return fallbackClassification(candidates, `LLM unavailable: ${errMsg(err)}`);\n }\n}\n\nasync function renderCorrectionDiff(\n _wiring: CorrectionAccessWiring,\n candidates: PlannerCandidate[],\n actions: CorrectionAction[],\n): Promise<string> {\n // Render a human-readable unified-diff-style preview. We snapshot each\n // affected memory via page-versioning (reuse, don't fork — rule 23) when\n // versioning is configured; otherwise fall back to a textual summary.\n const lines: string[] = [];\n for (const action of actions) {\n const id =\n action.kind === \"supersede\"\n ? action.loserId\n : action.kind === \"edit\" || action.kind === \"retract\" || action.kind === \"rescope\"\n ? action.memoryId\n : null;\n const candidate = id ? candidates.find((c) => c.memoryId === id) : null;\n const before = candidate?.content ?? \"(new)\";\n const after = describeAfterState(action);\n lines.push(`--- ${id ?? \"redaction-rule\"} (${action.kind})`);\n lines.push(`- ${before.slice(0, 120)}`);\n lines.push(`+ ${after.slice(0, 120)}`);\n }\n return lines.join(\"\\n\");\n}\n\nfunction describeAfterState(action: CorrectionAction): string {\n switch (action.kind) {\n case \"supersede\":\n return action.replacement?.content ?? \"(superseded without replacement)\";\n case \"edit\":\n return action.patch;\n case \"retract\":\n return \"(retracted + tombstoned)\";\n case \"rescope\":\n return `(moved to namespace '${action.toNamespace}')`;\n case \"redaction_rule\":\n return `(redaction rule persisted for pattern '${action.pattern}')`;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Executor deps\n// ---------------------------------------------------------------------------\n\nfunction makeExecutorDeps(\n wiring: CorrectionAccessWiring,\n opts: { biTemporalEnabled: boolean },\n): ExecutorDeps {\n return {\n getMemory: async (namespace, memoryId) => getExecutorMemory(wiring, namespace, memoryId),\n writeReplacement: async (namespace, draft) =>\n writeReplacementMemory(wiring, namespace, draft),\n applyEdit: async (namespace, memoryId, patch) =>\n applyEditMemory(wiring, namespace, memoryId, patch),\n retireMemory: async (namespace, memoryId, retireOpts) =>\n retireMemoryFn(wiring, namespace, memoryId, retireOpts),\n rescopeMemory: async (namespace, memoryId, toNamespace) =>\n rescopeMemoryFn(wiring, namespace, memoryId, toNamespace),\n appendTombstone: async (namespace, input) =>\n appendTombstoneFn(wiring, namespace, input),\n registerRedactionRule: async (namespace, pattern) =>\n registerRedactionRuleFn(wiring, namespace, pattern),\n appendAuditRecord: async (namespace, record) =>\n appendAuditRecordFn(wiring, namespace, record),\n propagate: async (namespace, touchedMemoryIds) =>\n propagateFn(wiring, namespace, touchedMemoryIds),\n biTemporalEnabled: opts.biTemporalEnabled,\n now: () => new Date(),\n };\n}\n\nasync function getExecutorMemory(\n wiring: CorrectionAccessWiring,\n namespace: string,\n memoryId: string,\n): Promise<ExecutorMemory | null> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n const m = await storage.getMemoryById(memoryId);\n if (!m) return null;\n return toExecutorMemory(m);\n}\n\nasync function writeReplacementMemory(\n wiring: CorrectionAccessWiring,\n namespace: string,\n draft: {\n content: string;\n category?: string;\n confidence?: number;\n tags?: string[];\n entityRef?: string;\n validAt?: string;\n observedAt?: string;\n structuredAttributes?: Record<string, string>;\n supersedes?: string;\n },\n): Promise<string> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n // writeMemory is the single storage chokepoint — catalog/dedup/reindex fire\n // here (rule 43). Tombstone blocking also fires here (#1579), so a\n // resurrected fact lands as pending_review rather than silently overwriting.\n const id = await storage.writeMemory(\n (draft.category ?? \"fact\") as Parameters<typeof storage.writeMemory>[0],\n draft.content,\n {\n source: \"correction\",\n confidence: draft.confidence ?? 0.9,\n tags: draft.tags ?? [],\n ...(draft.entityRef ? { entityRef: draft.entityRef } : {}),\n ...(draft.validAt ? { validAt: draft.validAt } : {}),\n ...(draft.observedAt ? { observedAt: draft.observedAt } : {}),\n ...(draft.structuredAttributes ? { structuredAttributes: draft.structuredAttributes } : {}),\n ...(draft.supersedes ? { supersedes: draft.supersedes } : {}),\n },\n );\n return id;\n}\n\nasync function applyEditMemory(\n wiring: CorrectionAccessWiring,\n namespace: string,\n memoryId: string,\n patch: string,\n): Promise<string> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n const existing = await storage.getMemoryById(memoryId);\n if (!existing) throw new CorrectionContractError(`memory not found for edit: ${memoryId}`);\n // Apply the patch by overwriting content through the storage chokepoint.\n // The StorageManager's writeMemoryFrontmatter snapshots the prior version\n // internally when page-versioning is configured (issue #371), so every edit\n // is revertable without the correction layer forking versioning logic.\n //\n // #1672 item 3: recompute the contentHash from the patched body so the\n // dedup index + tombstone exact tier match the NEW content. writeMemory\n // computes this at write time, but writeMemoryFrontmatter preserves the\n // prior frontmatter hash — without this the hash no longer matches the\n // patched body and a later re-extraction of the same fact dedup-misses.\n const contentHashForPatch =\n existing.frontmatter.category === \"fact\"\n ? computeContentHash(sanitizeMemoryContent(patch).text)\n : undefined;\n await storage.writeMemoryFrontmatter(\n { ...existing, content: patch },\n {\n updated: new Date().toISOString(),\n ...(contentHashForPatch ? { contentHash: contentHashForPatch } : {}),\n },\n );\n return memoryId;\n}\n\nasync function retireMemoryFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n memoryId: string,\n opts: { status: \"superseded\" | \"retracted\"; supersededBy?: string; validUntil?: string },\n): Promise<void> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n const memory = await storage.getMemoryById(memoryId);\n if (!memory) throw new CorrectionContractError(`memory not found for retire: ${memoryId}`);\n // Map the correction-domain status to the storage-domain MemoryStatus.\n // `retracted` (a correction concept) becomes `forgotten` — the soft-delete\n // status that excludes the memory from recall/browse/attribution while\n // keeping a page-version snapshot for reversibility (#686). `superseded`\n // maps to itself.\n const storageStatus: MemoryStatus = opts.status === \"retracted\" ? \"forgotten\" : \"superseded\";\n // Flip status + stamp validUntil (when bi-temporal is on, #1578) +\n // link the superseder. writeMemoryFrontmatter is the chokepoint.\n await storage.writeMemoryFrontmatter(memory, {\n status: storageStatus,\n ...(opts.supersededBy ? { supersededBy: opts.supersededBy } : {}),\n ...(opts.status === \"superseded\" ? { supersededAt: new Date().toISOString() } : {}),\n // validUntil is the bi-temporal end; absent when the gate is off.\n ...(opts.validUntil ? { invalid_at: opts.validUntil } : {}),\n });\n}\n\nasync function rescopeMemoryFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n memoryId: string,\n toNamespace: string,\n): Promise<string> {\n // The destination namespace is re-authorized by the service before the\n // executor runs; here we perform the move atomically (write-then-unlink).\n const sourceStorage = await wiring.orchestrator.getStorage(namespace);\n const memory = await sourceStorage.getMemoryById(memoryId);\n if (!memory) throw new CorrectionContractError(`memory not found for rescope: ${memoryId}`);\n if (memory.frontmatter.status && memory.frontmatter.status !== \"active\") {\n // Don't copy a stale source: rescoping a superseded/retracted/archived\n // memory duplicates outdated content into the destination (thread Ohjwb).\n throw new CorrectionContractError(\n `cannot rescope memory ${memoryId}: source is ${memory.frontmatter.status}, not active`,\n );\n }\n const destStorage = await wiring.orchestrator.getStorage(toNamespace);\n const fm = memory.frontmatter;\n // Strip the `[Attributes: …]` suffix writeMemory appended to the source body\n // (review thread Of0p6): we forward `structuredAttributes` separately, so\n // writeMemory will re-append the suffix on the destination. Without this\n // strip the destination would carry the suffix TWICE, producing duplicated\n // attribute text and a different content hash/index entry.\n const destContent = fm.structuredAttributes\n ? stripAttributesSuffix(memory.content)\n : memory.content;\n const destId = await destStorage.writeMemory(fm.category, destContent, {\n source: `correction:rescope:${namespace}`,\n ...(typeof fm.confidence === \"number\" ? { confidence: fm.confidence } : {}),\n ...(Array.isArray(fm.tags) ? { tags: fm.tags } : {}),\n ...(fm.entityRef ? { entityRef: fm.entityRef } : {}),\n ...(fm.structuredAttributes ? { structuredAttributes: fm.structuredAttributes } : {}),\n ...(fm.valid_at ? { validAt: fm.valid_at } : {}),\n ...(fm.observedAt ? { observedAt: fm.observedAt } : {}),\n ...(fm.memoryKind ? { memoryKind: fm.memoryKind } : {}),\n ...(Array.isArray(fm.links) ? { links: fm.links } : {}),\n ...(fm.intentGoal ? { intentGoal: fm.intentGoal } : {}),\n });\n // Unlink the source by archiving (non-destructive — rule 25). If the archive\n // fails AFTER the destination write succeeded, compensate by archiving the\n // destination too so no duplicate ACTIVE fact remains, then re-throw so the\n // executor records the action as failed (review: rescope-duplicates-on-fail).\n try {\n await sourceStorage.writeMemoryFrontmatter(memory, {\n status: \"archived\",\n archivedAt: new Date().toISOString(),\n });\n } catch (err) {\n try {\n const destMem = await destStorage.getMemoryById(destId);\n if (destMem) {\n await destStorage.writeMemoryFrontmatter(destMem, {\n status: \"archived\",\n archivedAt: new Date().toISOString(),\n });\n }\n } catch {\n // best-effort compensation\n }\n throw err;\n }\n return destId;\n}\n\nasync function appendTombstoneFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n input: {\n reason: \"correction\" | \"supersession\" | \"retraction\";\n sourceMemoryId: string;\n rawContent: string;\n entityRef?: string;\n supersessionKey?: string;\n supersessionKeys?: string[];\n contentHash?: string;\n },\n): Promise<string | null> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n // storage.appendTombstone returns null for TWO reasons: tombstones disabled\n // (off = pre-feature behavior) OR a swallowed store error (it catches I/O\n // failures and returns null — review thread OgIqp). The executor writes the\n // tombstone BEFORE retiring the source (PG9), so when tombstones are\n // enabled a null return means persistence failed and the retire must NOT\n // proceed (no tombstone → resurrection window). Distinguish the two cases\n // via the public isTombstonesEnabled() accessor; when disabled, null is the\n // expected pre-feature return and the action may still succeed.\n const enabled =\n typeof storage.isTombstonesEnabled === \"function\"\n ? storage.isTombstonesEnabled()\n : true;\n // #1672 item 4: emit one tombstone per derived supersession key (mirrors\n // temporal-supersession / forget / pattern-reinforcement) so a paraphrased\n // re-observation placing the attribute at a different key position is still\n // blocked at the keyed tier. When no keys are derived, emit a single\n // content-only tombstone. Each carries the canonical contentHash so the\n // exact tier also matches re-extraction.\n const keys =\n input.supersessionKeys && input.supersessionKeys.length > 0\n ? input.supersessionKeys\n : input.supersessionKey\n ? [input.supersessionKey]\n : [undefined];\n const writtenIds: string[] = [];\n let firstId: string | null = null;\n for (const key of keys) {\n const result = await storage.appendTombstone({\n reason: input.reason,\n createdBy: \"user_correction\",\n sourceMemoryId: input.sourceMemoryId,\n rawContent: input.rawContent,\n ...(input.entityRef ? { entityRef: input.entityRef } : {}),\n ...(key ? { supersessionKey: key } : {}),\n ...(input.contentHash ? { contentHash: input.contentHash } : {}),\n });\n if (result === null && enabled) {\n // Rollback already-written tombstones so a partial multi-key failure\n // does not leave incomplete resurrection blocking for the still-active\n // memory (review thread #1). Best-effort — a dangling tombstone is the\n // safer failure mode (false-positive block vs. false-negative leak).\n for (const id of writtenIds) {\n try { await storage.revokeTombstone(id, \"user_correction\"); } catch { /* best-effort */ }\n }\n throw new CorrectionContractError(\n `tombstone persistence failed for memory ${input.sourceMemoryId} (tombstones enabled but store returned null — I/O error swallowed)`,\n );\n }\n if (firstId === null) firstId = result;\n if (result) writtenIds.push(result);\n }\n return firstId;\n}\n\nasync function registerRedactionRuleFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n pattern: string,\n): Promise<void> {\n // Persist the redaction rule under state/ so extraction consults it the\n // same way tombstones are consulted (route through the same chokepoint).\n const storage = await wiring.orchestrator.getStorage(namespace);\n const dir = path.join(storage.dir, \"state\", \"corrections\", \"redaction-rules\");\n await mkdir(dir, { recursive: true });\n // Idempotent: filename is a slug + short hash of the full pattern so\n // re-registering the same pattern overwrites rather than duplicates, while\n // distinct patterns that slug identically (e.g. \"abc+def\" vs \"abc.def\" →\n // \"abc-def\") no longer collide and silently remove each other's enforcement\n // (review thread P1).\n const slugBase = pattern.replace(/[^a-zA-Z0-9]+/g, \"-\").slice(0, 48) || \"rule\";\n const patternHash = createHash(\"sha256\").update(pattern).digest(\"hex\").slice(0, 16);\n const slug = `${slugBase}-${patternHash}`;\n await writeFile(\n path.join(dir, `${slug}.json`),\n `${JSON.stringify({ pattern, namespace, createdAt: new Date().toISOString() })}\\n`,\n \"utf-8\",\n );\n}\n\nasync function appendAuditRecordFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n record: {\n planId: string;\n classification: CorrectionPlan[\"classification\"];\n outcome: CorrectionOutcome;\n requestText: string;\n },\n): Promise<string> {\n const storage = await wiring.orchestrator.getStorage(namespace);\n // Corrections are themselves memories, searchable and namespaced (issue\n // #1580 design §4). Write a correction-category memory capturing the\n // plan + outcome as the audit trail.\n const id = await storage.writeMemory(\"correction\", buildAuditBody(record), {\n source: \"correction-contract\",\n confidence: 1.0,\n tags: [\"correction-audit\", `plan:${record.planId}`, `classification:${record.classification}`],\n });\n return id;\n}\n\nfunction buildAuditBody(record: {\n planId: string;\n classification: CorrectionPlan[\"classification\"];\n outcome: CorrectionOutcome;\n requestText: string;\n}): string {\n // Never-store / redaction corrections carry the very secret/pattern the user\n // asked Remnic NOT to retain — withhold the request text from the durable\n // audit memory so we don't persist it verbatim (#1580 review, P1).\n const sensitive =\n record.classification === \"never_store\" ||\n record.outcome.results.some((r) => r.action.kind === \"redaction_rule\");\n const safeRequest = sensitive\n ? \"[redacted — never-store/redaction correction text withheld from the audit trail]\"\n : record.requestText.slice(0, 200);\n const lines = [\n `Correction plan ${record.planId} applied (${record.outcome.status}).`,\n \"\",\n `Request: ${safeRequest}`,\n `Classification: ${record.classification}`,\n `Applied at: ${record.outcome.appliedAt}`,\n \"\",\n \"Actions:\",\n ];\n for (const r of record.outcome.results) {\n // Never-store/redaction action errors can echo the secret/pattern — withhold\n // the error text for those actions (review thread OhjwW).\n const withhold =\n r.action.kind === \"redaction_rule\" || record.classification === \"never_store\";\n const errPart = r.error ? (withhold ? \" (error withheld)\" : ` (${r.error})`) : \"\";\n lines.push(` - ${r.action.kind}: ${r.status}${errPart}`);\n }\n return lines.join(\"\\n\");\n}\n\nasync function propagateFn(\n wiring: CorrectionAccessWiring,\n namespace: string,\n touchedMemoryIds: readonly string[],\n): Promise<void> {\n // Best-effort post-write propagation. The orchestrator's indexPersistedMemory\n // fires the QMD reindex for a touched file (checklist §31). A failure here\n // is non-fatal — the executor records it as a warning, never a failed action.\n for (const id of touchedMemoryIds) {\n try {\n // indexPersistedMemory is keyed by the namespace's storage, NOT the\n // default namespace (review thread: propagation-hardcodes-default-ns).\n const storage = await wiring.orchestrator.getStorage(namespace);\n const orchestrator = wiring.orchestrator as unknown as {\n indexPersistedMemory?(storage: unknown, memoryId: string): Promise<void>;\n };\n if (typeof orchestrator.indexPersistedMemory === \"function\") {\n await orchestrator.indexPersistedMemory(storage, id);\n }\n } catch {\n // Swallow — propagation is best-effort.\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n\nfunction toCandidate(m: MemoryFile, namespace: string, score: number): PlannerCandidate {\n return {\n memoryId: m.frontmatter.id,\n path: m.path,\n content: m.content,\n excerpt: m.content.slice(0, 160),\n ...(m.frontmatter.entityRef ? { entityRef: m.frontmatter.entityRef } : {}),\n score,\n // namespace is implicit (the planner scopes by namespace); keep it on the\n // candidate for diff rendering if needed.\n } satisfies PlannerCandidate & { namespace?: string };\n}\n\n/**\n * Lifecycle-aware eligibility for a correction candidate (#1672 item 2). A\n * memory is eligible only when it is `status: \"active\"` AND not archived.\n * Planning a correction against a memory that was archived via the\n * `archivedAt`/archive path but still marked active would surface stale\n * content the user already set aside — and apply would reject the rescope\n * (non-active source) or supersede a fact the user intended gone. Both the\n * status flip and the archive timestamp are checked so the candidate set\n * stays consistent with the rescope/retire apply-time guards.\n */\nfunction isEligibleCorrectionCandidate(m: MemoryFile): boolean {\n if (m.frontmatter.status && m.frontmatter.status !== \"active\") return false;\n if (typeof m.frontmatter.archivedAt === \"string\" && m.frontmatter.archivedAt.length > 0) return false;\n return true;\n}\n\nfunction toExecutorMemory(m: MemoryFile): ExecutorMemory {\n const fm = m.frontmatter;\n // The tombstone hash must use the ORIGINAL unsuffixed body: writeMemory\n // appends an `[Attributes: …]` suffix when structuredAttributes are set, so\n // hashing m.content would never match the pre-suffix content hash (thread\n // OhX2N, rule 23). Strip the suffix when attributes are present.\n const rawBody = fm.structuredAttributes ? stripAttributesSuffix(m.content) : m.content;\n // #1672 item 4: derive the full supersession-key set from the memory's\n // structuredAttributes so the tombstone's keyed tier blocks paraphrased\n // re-observations that place the attribute at a different key position\n // (mirrors temporal-supersession's per-key emission). Also forward the\n // canonical contentHash so the exact tier matches re-extraction without\n // recomputing from a citation-annotated body.\n const supersessionKeys = supersessionKeysForFact({\n entityRef: fm.entityRef,\n structuredAttributes: fm.structuredAttributes,\n });\n return {\n memoryId: fm.id,\n content: m.content,\n category: fm.category,\n rawContent: rawBody,\n ...(fm.entityRef ? { entityRef: fm.entityRef } : {}),\n ...(supersessionKeys.length > 0 ? { supersessionKeys } : {}),\n ...(supersessionKeys.length > 0 ? { supersessionKey: supersessionKeys[0] } : {}),\n ...(typeof fm.contentHash === \"string\" && fm.contentHash.length > 0\n ? { contentHash: fm.contentHash }\n : {}),\n } satisfies ExecutorMemory;\n}\n\n/**\n * The single source of truth for whether the Correction Contract feature is\n * enabled. Reads BOTH config shapes so tool visibility and the runtime gate\n * can never drift out of sync (review thread: correction-gate-config-mismatch):\n * - nested: `config.correction.enabled`\n * - flat: the `correctionEnabled` legacy key (ratchet-safe shape)\n * Nested wins when present; both default to `true` (plan is read-only, safe on).\n */\nexport function isCorrectionFeatureEnabled(config: PluginConfig): boolean {\n // parseConfig now resolves this into `config.correctionEnabled` (review\n // thread Txp) — prefer the parsed boolean so operator config actually takes\n // effect. The loose nested/flat read stays as a fallback for PluginConfig-\n // shaped objects built without parseConfig (unit tests).\n if (typeof config.correctionEnabled === \"boolean\") return config.correctionEnabled;\n const nested = (config as unknown as Record<string, unknown>).correction as\n | Record<string, unknown>\n | undefined;\n if (nested && typeof nested.enabled === \"boolean\") return nested.enabled;\n if (nested && typeof nested.enabled === \"string\") return nested.enabled === \"true\" || nested.enabled === \"1\";\n return readCorrectionFlag(config, \"enabled\", true);\n}\n\n/** Read a boolean correction flag from the loosely-typed config (ratchet-safe). */\nfunction readCorrectionFlag(config: PluginConfig, key: string, fallback: boolean): boolean {\n // Nested shape wins: config.correction.<key> (review thread: nested-correction-settings).\n const nested = (config as unknown as Record<string, unknown>).correction as\n | Record<string, unknown>\n | undefined;\n if (nested && typeof nested[key] === \"boolean\") return nested[key] as boolean;\n if (nested && typeof nested[key] === \"string\") return (nested[key] as string) === \"true\" || (nested[key] as string) === \"1\";\n // Flat legacy shape: config.correction<Key>.\n const raw = (config as unknown as Record<string, unknown>)[`correction${capitalize(key)}`];\n if (typeof raw === \"boolean\") return raw;\n if (typeof raw === \"string\") return raw === \"true\" || raw === \"1\";\n return fallback;\n}\n\n/** Read a numeric correction value from the loosely-typed config (ratchet-safe). */\nfunction readCorrectionNumber(config: PluginConfig, key: string, fallback: number): number {\n // Nested shape wins: config.correction.<key> (review thread: nested-correction-settings).\n const nested = (config as unknown as Record<string, unknown>).correction as\n | Record<string, unknown>\n | undefined;\n if (nested) {\n const nv = nested[key];\n if (typeof nv === \"number\" && Number.isFinite(nv)) return nv;\n if (typeof nv === \"string\") {\n const nn = Number(nv);\n if (Number.isFinite(nn)) return nn;\n }\n }\n const raw = (config as unknown as Record<string, unknown>)[`correction${capitalize(key)}`];\n if (typeof raw === \"number\" && Number.isFinite(raw)) return raw;\n if (typeof raw === \"string\") {\n const n = Number(raw);\n if (Number.isFinite(n)) return n;\n }\n return fallback;\n}\n\nfunction capitalize(s: string): string {\n return s.charAt(0).toUpperCase() + s.slice(1);\n}\n\nfunction errMsg(err: unknown): string {\n if (err instanceof Error) return err.message;\n return String(err);\n}\n\n// ---------------------------------------------------------------------------\n// LLM classify+draft (Responses API only — gotcha 1)\n// ---------------------------------------------------------------------------\n\nconst CLASSIFY_SYSTEM_PROMPT = `You classify memory corrections and draft per-memory actions.\n\nGiven a correction statement and candidate memories, respond with a JSON object:\n{\n \"classification\": \"wrong\" | \"outdated\" | \"incomplete\" | \"wrong_scope\" | \"never_store\",\n \"confidence\": <number 0..1>,\n \"actions\": [<one or more correction actions>],\n \"relevance\": [{\"memoryId\": \"<id>\", \"why\": \"<one short sentence>\"}]\n}\n\nAction shapes:\n- {\"kind\":\"supersede\",\"loserId\":\"<id>\",\"replacement\":{\"content\":\"<new fact>\"}}\n- {\"kind\":\"edit\",\"memoryId\":\"<id>\",\"patch\":\"<new full content>\"}\n- {\"kind\":\"retract\",\"memoryId\":\"<id>\"}\n- {\"kind\":\"rescope\",\"memoryId\":\"<id>\",\"toNamespace\":\"<ns>\"}\n- {\"kind\":\"redaction_rule\",\"pattern\":\"<bounded literal or regex>\"}\n\nOnly emit actions you are confident in. If uncertain, return confidence < 0.5 and few actions.`;\n\nfunction buildClassifyPrompt(text: string, candidates: PlannerCandidate[]): string {\n const lines = [\n `Correction: ${text}`,\n \"\",\n \"Candidate memories:\",\n ];\n for (const c of candidates.slice(0, 20)) {\n lines.push(`[${c.memoryId}] ${c.excerpt}`);\n }\n lines.push(\"\", \"Respond with the JSON object only.\");\n return lines.join(\"\\n\");\n}\n\nfunction parseClassifyResponse(\n raw: string,\n candidates: PlannerCandidate[],\n): LlmClassificationResult {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return fallbackClassification(candidates, \"LLM returned non-JSON response\");\n }\n if (!parsed || typeof parsed !== \"object\") {\n return fallbackClassification(candidates, \"LLM returned non-object response\");\n }\n const obj = parsed as Record<string, unknown>;\n const classification = isClassification(obj.classification) ? obj.classification : \"outdated\";\n const confidence = typeof obj.confidence === \"number\" ? Math.min(1, Math.max(0, obj.confidence)) : 0.5;\n const rawActions = Array.isArray(obj.actions) ? obj.actions : [];\n const actions: CorrectionAction[] = [];\n const warnings: string[] = [];\n for (const rawAction of rawActions) {\n try {\n validateCorrectionAction(rawAction);\n actions.push(rawAction);\n } catch (err) {\n warnings.push(`dropped malformed action: ${errMsg(err)}`);\n }\n }\n const relevance = Array.isArray(obj.relevance)\n ? (obj.relevance as unknown[])\n .filter((r): r is Record<string, unknown> => !!r && typeof r === \"object\")\n .map((r) => ({\n memoryId: typeof r.memoryId === \"string\" ? r.memoryId : \"\",\n why: typeof r.why === \"string\" ? r.why : \"\",\n }))\n .filter((r) => r.memoryId.length > 0)\n : [];\n return {\n classification,\n confidence,\n actions,\n relevance,\n warnings,\n };\n}\n\nfunction isClassification(value: unknown): value is CorrectionPlan[\"classification\"] {\n return (\n value === \"wrong\" ||\n value === \"outdated\" ||\n value === \"incomplete\" ||\n value === \"wrong_scope\" ||\n value === \"never_store\"\n );\n}\n\nfunction fallbackClassification(\n candidates: PlannerCandidate[],\n reason: string,\n): LlmClassificationResult {\n return {\n classification: \"outdated\",\n confidence: 0,\n actions: [],\n relevance: candidates.map((c) => ({ memoryId: c.memoryId, why: \"located for review\" })),\n warnings: [reason],\n fallback: true,\n };\n}\n\n// Re-export the local helpers for tests that import this module directly.\n// (deterministicFallbackPlan and newPlanId live in correction-contract.ts and\n// are re-exported by the barrel from there — not duplicated here.)\nexport {\n buildAuditBody,\n buildClassifyPrompt,\n CLASSIFY_SYSTEM_PROMPT,\n parseClassifyResponse,\n // #1672: exported for focused storage-integration regression tests.\n isEligibleCorrectionCandidate,\n applyEditMemory,\n appendTombstoneFn,\n};\n","/**\n * correction/correction-planner.ts — read-only planner (issue #1580 PR 1).\n *\n * The planner turns a {@link CorrectionRequest} into a {@link CorrectionPlan}:\n *\n * 1. LOCATE. `targetIds` present → resolve directly (not-found → explicit\n * error, rule 34). Else: search via the injected search path scoped to\n * the caller's readable namespaces, plus 1-hop entity-graph neighbors of\n * top hits. Cap candidates at `maxAffected`.\n * 2. CLASSIFY + DRAFT via one LLM call (Responses API only, gotcha 1). On\n * LLM failure → deterministic fallback plan (rule 13): classification\n * `outdated`, `confidence: 0`, empty actions, warning set.\n * 3. RENDER DIFF by materializing what each action would do, using the\n * injected diff renderer (page-versioning — reuse, don't fork).\n * 4. PERSIST the plan atomically under\n * `<memoryDir>/state/corrections/pending/<planId>.json` (rule 54). TTL\n * default 24h; expired plans are rejected at apply with a clear error.\n *\n * The planner NEVER writes memory state — that is the executor's job. The\n * only thing it persists is the plan document itself.\n */\n\nimport { mkdir, readFile, rename, unlink, readdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { serializeMutations } from \"../utils/serialize-mutations.js\";\nimport {\n CORRECTION_TEXT_MAX,\n CorrectionContractError,\n deterministicFallbackPlan,\n newPlanId,\n validateCorrectionAction,\n validateCorrectionRequest,\n validateRedactionPattern,\n type CorrectionAction,\n type CorrectionAffectedEntry,\n type CorrectionClassification,\n type CorrectionPlan,\n type CorrectionRequest,\n type MemoryDraft,\n} from \"./correction-contract.js\";\n\n// ---------------------------------------------------------------------------\n// Injected collaborators — kept narrow so the planner is unit-testable.\n// ---------------------------------------------------------------------------\n\n/** A memory the planner located for the user. */\nexport interface PlannerCandidate {\n memoryId: string;\n /** Path relative to the storage dir (for diff rendering). */\n path: string;\n content: string;\n excerpt: string;\n category?: string;\n entityRef?: string;\n /** Provenance source quote (#1575), if available. */\n sourceQuote?: string;\n /** Search relevance / neighbor score, descending. */\n score: number;\n}\n\nexport interface PlannerDeps {\n // readableNamespaces is passed per-call to plan() so a single planner\n // instance serves requests from callers with different read scopes.\n /**\n * Search memories for the correction text. The implementation is supplied\n * by the service and reuses the existing recall/QMD search path scoped to\n * `readableNamespaces`. Returns at most `limit` candidates.\n */\n searchCorpus(request: {\n text: string;\n namespaces: readonly string[];\n limit: number;\n }): Promise<PlannerCandidate[]>;\n /**\n * Resolve explicit `targetIds` to candidates. Not-found is an explicit\n * error (rule 34): the implementation throws with the missing id.\n */\n resolveTargets(request: {\n targetIds: readonly string[];\n namespaces: readonly string[];\n }): Promise<PlannerCandidate[]>;\n /**\n * One-hop entity-graph neighbors of the supplied candidates. Returns the\n * union (deduped by memoryId); neighbors not already in `seedIds` only.\n */\n expandNeighbors(request: {\n seedIds: readonly string[];\n namespaces: readonly string[];\n limit: number;\n }): Promise<PlannerCandidate[]>;\n /**\n * Single LLM call (Responses API). Classifies the correction and drafts\n * per-memory actions. Implementations MUST return a deterministic fallback\n * shape on LLM failure (see {@link LlmClassificationResult.fallback}) so the\n * planner never throws on an LLM outage (rule 13).\n */\n classifyAndDraft(request: {\n text: string;\n candidates: PlannerCandidate[];\n }): Promise<LlmClassificationResult>;\n /**\n * Render a human-readable diff preview for the planned actions, using\n * page-versioning snapshot/diff (reuse, don't fork). Pure — no side effects.\n */\n renderDiff(request: {\n candidates: PlannerCandidate[];\n actions: CorrectionAction[];\n }): Promise<string>;\n /** Per-namespace storage dir root (so the plan lands in the right state/). */\n storageDir(namespace: string): Promise<string>;\n /** Max affected memories per plan (issue config: default 10). */\n readonly maxAffected: number;\n /** Plan TTL in hours (issue config: default 24). */\n readonly planTtlHours: number;\n /** Injected clock for deterministic tests. */\n now(): Date;\n}\n\n/** Result of the single LLM classify+draft call. */\nexport interface LlmClassificationResult {\n classification: CorrectionClassification;\n confidence: number;\n /** Per-memory drafted actions (already validated by the adapter). */\n actions: CorrectionAction[];\n /** Per-memory relevance notes — why each affected memory is in the plan. */\n relevance: ReadonlyArray<{ memoryId: string; why: string }>;\n warnings: string[];\n /** True when the adapter fell back due to an LLM outage (rule 13). */\n fallback?: boolean;\n}\n\n/**\n * Placeholder substituted for the request text when persisting a never-store /\n * redaction-rule plan (#1678 thread Oid8t). Mirrors the durable-audit\n * redaction so the transient pending-plan file never holds the secret.\n */\nconst REDACTED_REQUEST_TEXT = \"[redacted — never-store/redaction correction text withheld from the pending-plan file]\";\n\n// ---------------------------------------------------------------------------\n// Planner\n// ---------------------------------------------------------------------------\n\nexport class CorrectionPlanner {\n constructor(private readonly deps: PlannerDeps) {}\n\n /**\n * Plan a correction. `readableNamespaces` is the AUTHORIZED read scope the\n * service resolved for this caller; the planner never trusts a caller string.\n */\n async plan(\n request: CorrectionRequest,\n readableNamespaces: readonly string[],\n ): Promise<CorrectionPlan> {\n const cleaned = validateCorrectionRequest(request);\n if (cleaned.text.length > CORRECTION_TEXT_MAX) {\n // Defensive double-check; validateCorrectionRequest already throws.\n throw new CorrectionContractError(\"CorrectionRequest.text too long.\");\n }\n\n if (cleaned.targetIds && cleaned.targetIds.length > this.deps.maxAffected) {\n throw new CorrectionContractError(\n `Correction target list (${cleaned.targetIds.length}) exceeds maxAffected (${this.deps.maxAffected}) — narrow the target set.`,\n );\n }\n\n const namespaces = readableNamespaces;\n if (namespaces.length === 0) {\n throw new CorrectionContractError(\n \"Correction requires at least one readable namespace — principal has no read scope.\",\n );\n }\n\n // 1. LOCATE\n const located = await this.locateCandidates(cleaned, namespaces);\n if (located.candidates.length === 0) {\n // No candidates AND no explicit targets → empty plan is valid (the user\n // can still discard). But explicit-target-not-found was already raised\n // inside locateCandidates (rule 34).\n return this.persist(\n this.emptyPlan(cleaned, namespaces[0], \"no matching memories found for the correction text\"),\n );\n }\n\n // 2. CLASSIFY + DRAFT\n const llm = await this.deps.classifyAndDraft({\n text: cleaned.text,\n candidates: located.candidates,\n });\n\n // Validate every action shape before persisting — the adapter is trusted\n // to validate, but a malformed action must never reach the executor\n // (defense in depth, rule 51).\n for (const action of llm.actions) {\n validateCorrectionAction(action);\n if (action.kind === \"redaction_rule\") {\n validateRedactionPattern(action.pattern);\n }\n }\n\n// 3. Map actions → affected entries (only memories the planner located).\n const affected = this.deriveAffected(located.candidates, llm);\n\n // Bulk guard (§39): refuse past maxAffected without silent truncation.\n const touchedCount = new Set(\n llm.actions\n .map((a) =>\n a.kind === \"supersede\"\n ? a.loserId\n : a.kind === \"edit\" || a.kind === \"retract\" || a.kind === \"rescope\"\n ? a.memoryId\n : null,\n )\n .filter((id): id is string => id !== null),\n ).size;\n if (touchedCount > this.deps.maxAffected) {\n throw new CorrectionContractError(\n `Correction touches ${touchedCount} memories, exceeding the maxAffected limit of ${this.deps.maxAffected}. Narrow the correction text or supply explicit targetIds.`,\n );\n }\n\n // Defense in depth (review thread: reject-actions-outside-candidates):\n // an LLM that hallucinates or is prompt-injected must never target a\n // memory the planner did not locate. NOW that the bulk guard has had its\n // chance to reject over-limit plans, drop actions whose target ID is\n // absent from the candidate set and warn.\n const candidateIds = new Set(located.candidates.map((c) => c.memoryId));\n if (llm.actions.length > 0 && candidateIds.size > 0) {\n const filtered = llm.actions.filter((action) => {\n const id =\n action.kind === \"supersede\"\n ? action.loserId\n : action.kind === \"edit\" || action.kind === \"retract\" || action.kind === \"rescope\"\n ? action.memoryId\n : null;\n return id === null || candidateIds.has(id);\n });\n if (filtered.length < llm.actions.length) {\n const dropped = llm.actions.length - filtered.length;\n llm.warnings = [...llm.warnings, `${dropped} action(s) targeted memories outside the located candidate set and were dropped (prompt-injection guard).`];\n llm.actions = filtered;\n }\n }\n\n // 4. RENDER DIFF\n const diff = llm.fallback\n ? \"\"\n : await this.deps.renderDiff({ candidates: located.candidates, actions: llm.actions });\n\n const createdAt = this.deps.now().toISOString();\n const expiresAt = new Date(\n this.deps.now().getTime() + this.deps.planTtlHours * 60 * 60 * 1000,\n ).toISOString();\n\n const plan: CorrectionPlan = llm.fallback\n ? deterministicFallbackPlan({\n request: cleaned,\n namespace: namespaces[0],\n affected,\n warnings: llm.warnings,\n createdAt,\n expiresAt,\n })\n : {\n planId: newPlanId(),\n request: cleaned,\n namespace: namespaces[0],\n affected,\n classification: llm.classification,\n actions: llm.actions,\n diff,\n confidence: clampConfidence(llm.confidence),\n warnings: llm.warnings,\n createdAt,\n expiresAt,\n status: \"pending\",\n };\n\n return this.persist(plan);\n }\n\n private async locateCandidates(\n request: CorrectionRequest,\n namespaces: readonly string[],\n ): Promise<{ candidates: PlannerCandidate[] }> {\n if (request.targetIds && request.targetIds.length > 0) {\n const targets = await this.deps.resolveTargets({\n targetIds: request.targetIds,\n namespaces,\n });\n // Expand 1-hop neighbors and merge (dedup by memoryId, keep highest score).\n const seedIds = targets.map((c) => c.memoryId);\n const neighbors = await this.deps.expandNeighbors({\n seedIds,\n namespaces,\n limit: this.deps.maxAffected,\n });\n return { candidates: mergeCandidates(targets, neighbors).slice(0, this.deps.maxAffected) };\n }\n\n const searched = await this.deps.searchCorpus({\n text: request.text,\n namespaces,\n limit: this.deps.maxAffected,\n });\n if (searched.length === 0) return { candidates: [] };\n const seedIds = searched.slice(0, Math.min(5, searched.length)).map((c) => c.memoryId);\n const neighbors = await this.deps.expandNeighbors({\n seedIds,\n namespaces,\n limit: this.deps.maxAffected,\n });\n return { candidates: mergeCandidates(searched, neighbors).slice(0, this.deps.maxAffected) };\n }\n\n private deriveAffected(\n candidates: PlannerCandidate[],\n llm: LlmClassificationResult,\n ): CorrectionAffectedEntry[] {\n const byId = new Map(candidates.map((c) => [c.memoryId, c]));\n const out: CorrectionAffectedEntry[] = [];\n for (const rel of llm.relevance) {\n const c = byId.get(rel.memoryId);\n if (!c) continue;\n out.push({\n memoryId: c.memoryId,\n path: c.path,\n excerpt: c.excerpt,\n why: rel.why,\n ...(c.sourceQuote ? { sourceQuote: c.sourceQuote } : {}),\n });\n }\n // Include touched memories that the LLM did not annotate but whose actions\n // reference them (e.g. an `edit` drafted against a located candidate).\n const annotated = new Set(out.map((e) => e.memoryId));\n for (const action of llm.actions) {\n const id =\n action.kind === \"supersede\"\n ? action.loserId\n : action.kind === \"edit\" || action.kind === \"retract\" || action.kind === \"rescope\"\n ? action.memoryId\n : null;\n if (id && !annotated.has(id)) {\n const c = byId.get(id);\n if (c) {\n out.push({\n memoryId: c.memoryId,\n path: c.path,\n excerpt: c.excerpt,\n why: \"touched by a drafted action\",\n ...(c.sourceQuote ? { sourceQuote: c.sourceQuote } : {}),\n });\n annotated.add(id);\n }\n }\n }\n return out;\n }\n\n private emptyPlan(request: CorrectionRequest, namespace: string, warning: string): CorrectionPlan {\n const createdAt = this.deps.now().toISOString();\n const expiresAt = new Date(\n this.deps.now().getTime() + this.deps.planTtlHours * 60 * 60 * 1000,\n ).toISOString();\n return {\n planId: newPlanId(),\n request,\n namespace,\n affected: [],\n classification: \"outdated\",\n actions: [],\n diff: \"\",\n confidence: 0,\n warnings: [warning],\n createdAt,\n expiresAt,\n status: \"pending\",\n };\n }\n\n // -------------------------------------------------------------------------\n // Plan persistence — atomic write (rule 54), serialized per plan id (rule 40).\n // -------------------------------------------------------------------------\n\n /** Directory holding pending plans for one namespace. */\n private async pendingDir(namespace: string): Promise<string> {\n return path.join(await this.deps.storageDir(namespace), \"state\", \"corrections\", \"pending\");\n }\n\n private async persist(plan: CorrectionPlan): Promise<CorrectionPlan> {\n const dir = await this.pendingDir(plan.namespace);\n const target = path.join(dir, `${plan.planId}.json`);\n // #1678 (thread Oid8t): never-store/redaction corrections carry the very\n // secret/pattern the user asked Remnic NOT to retain. The durable audit\n // already withholds the text; the TRANSIENT pending-plan file must too,\n // or the secret sits on disk (pending until apply/discard + TTL). Redact\n // the request text in the persisted copy for never_store classifications\n // or any redaction_rule action. The in-memory plan keeps the original\n // text so the executor's audit body (which re-applies its own redaction)\n // is unaffected; only the on-disk JSON is sanitized.\n const sensitive =\n plan.classification === \"never_store\" ||\n plan.actions.some((a) => a.kind === \"redaction_rule\");\n // #1678 (threads vMLN/vZln): redact request.text (the executor does not\n // need the raw request text for redaction_rule actions). The pattern is\n // NOT redacted: the executor's apply flow reloads via loadPlan (disk) and\n // needs the real pattern to call registerRedactionRule. Redacting it would\n // register a placeholder and the extraction redaction (#1669) would never\n // block the intended content. The pattern's transient on-disk exposure is\n // bounded by the pending-plan TTL + consumed-on-apply lifecycle.\n const persistedPlan: CorrectionPlan = sensitive\n ? { ...plan, request: { ...plan.request, text: REDACTED_REQUEST_TEXT } }\n : plan;\n await serializeMutations(`correction-plan:${target}`, async () => {\n await mkdir(dir, { recursive: true });\n const tmp = `${target}.${process.pid}.${Date.now().toString(36)}.tmp`;\n await writeFile(tmp, `${JSON.stringify(persistedPlan)}\\n`, \"utf-8\");\n // rename() is atomic on POSIX for same-filesystem renames (rule 54).\n await rename(tmp, target);\n });\n return plan;\n }\n\n /** Load a pending plan by id (used by the service / executor). */\n async loadPlan(namespace: string, planId: string): Promise<CorrectionPlan | null> {\n assertSafePlanId(planId);\n const file = path.join(await this.pendingDir(namespace), `${planId}.json`);\n return serializeMutations(`correction-plan:${file}`, async () => {\n let raw: string;\n try {\n raw = await readFile(file, \"utf-8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\") return null;\n throw err;\n }\n return parsePlan(raw);\n });\n }\n\n /** List pending plans (newest first), excluding consumed (applied/discarded). */\n async listPending(namespace: string): Promise<CorrectionPlan[]> {\n const dir = await this.pendingDir(namespace);\n let files: string[];\n try {\n files = await readdir(dir);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\") return [];\n throw err;\n }\n const plans: CorrectionPlan[] = [];\n for (const f of files) {\n if (!f.endsWith(\".json\")) continue;\n let plan: CorrectionPlan | null = null;\n try {\n plan = await this.loadPlan(namespace, f.replace(/\\.json$/, \"\"));\n } catch {\n continue; // rule 34 — skip malformed plans with a counter (best-effort).\n }\n if (plan && plan.status === \"pending\") plans.push(plan);\n }\n plans.sort((a, b) => (a.createdAt < b.createdAt ? 1 : a.createdAt > b.createdAt ? -1 : 0));\n return plans;\n }\n\n async markConsumed(namespace: string, planId: string, status: \"applying\" | \"applied\" | \"discarded\" | \"partial\"): Promise<void> {\n assertSafePlanId(planId);\n const file = path.join(await this.pendingDir(namespace), `${planId}.json`);\n await serializeMutations(`correction-plan:${file}`, async () => {\n let raw: string;\n try {\n raw = await readFile(file, \"utf-8\");\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\") return; // idempotent\n throw err;\n }\n const plan = parsePlan(raw);\n if (!plan) return;\n plan.status = status;\n // #1669 thread P1: scrub redaction_rule patterns from consumed plans so\n // a never-store pattern does not persist on disk after apply/discard.\n // The executor reloads via loadPlan only between \"applying\" (step 1) and\n // \"applied\" (step 4), so scrubbing at the terminal status is safe.\n if (status !== \"applying\") {\n plan.actions = plan.actions.map((a) =>\n a.kind === \"redaction_rule\"\n ? { ...a, pattern: \"[redacted — pattern applied]\" }\n : a,\n );\n }\n const tmp = `${file}.${process.pid}.${Date.now().toString(36)}.tmp`;\n await writeFile(tmp, `${JSON.stringify(plan)}\\n`, \"utf-8\");\n await rename(tmp, file);\n });\n }\n\n async deletePlan(namespace: string, planId: string): Promise<void> {\n assertSafePlanId(planId);\n const file = path.join(await this.pendingDir(namespace), `${planId}.json`);\n await serializeMutations(`correction-plan:${file}`, async () => {\n try {\n await unlink(file);\n } catch (err) {\n const code = (err as NodeJS.ErrnoException)?.code;\n if (code === \"ENOENT\") return;\n throw err;\n }\n });\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Reject caller-supplied plan ids that would escape the pending-plan dir\n * (review thread Ug8): `correct --discard --plan-id ../../meta` must not let\n * `path.join(pendingDir, \"../../meta.json\")` unlink arbitrary `.json` files\n * under the storage root. A safe plan id is a bare basename with no path\n * separators and no parent-segment shape. The canonical format is\n * `corr-<base36>-<base36>` (see {@link newPlanId}); this guard accepts any\n * single-segment id so future formats need not touch it, but blocks every\n * traversal vector (`/`, `\\`, `..`, leading dots, NUL).\n */\nfunction assertSafePlanId(planId: string): void {\n if (\n typeof planId !== \"string\" ||\n planId.length === 0 ||\n planId.includes(\"/\") ||\n planId.includes(\"\\\\\") ||\n planId.includes(\"\\0\") ||\n planId === \".\" ||\n planId === \"..\" ||\n planId.startsWith(\".\") ||\n planId.includes(\"..\")\n ) {\n throw new CorrectionContractError(\n `Invalid plan id: ${JSON.stringify(planId)} — must be a bare file basename with no path separators or parent segments.`,\n );\n }\n}\nfunction clampConfidence(n: number): number {\n if (!Number.isFinite(n)) return 0;\n return Math.min(1, Math.max(0, n));\n}\n\n/** Merge two candidate lists, deduping by memoryId and keeping the highest score. */\nfunction mergeCandidates(a: readonly PlannerCandidate[], b: readonly PlannerCandidate[]): PlannerCandidate[] {\n const map = new Map<string, PlannerCandidate>();\n for (const c of a) {\n const existing = map.get(c.memoryId);\n if (!existing || c.score > existing.score) map.set(c.memoryId, c);\n }\n for (const c of b) {\n const existing = map.get(c.memoryId);\n if (!existing || c.score > existing.score) map.set(c.memoryId, c);\n }\n return [...map.values()].sort((x, y) => y.score - x.score);\n}\n\n/** Parse + structurally validate a plan document. Returns null on malformed. */\nexport function parsePlan(raw: string): CorrectionPlan | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!parsed || typeof parsed !== \"object\") return null;\n const p = parsed as Record<string, unknown>;\n if (typeof p.planId !== \"string\" || typeof p.namespace !== \"string\") return null;\n if (typeof p.createdAt !== \"string\" || typeof p.expiresAt !== \"string\") return null;\n if (!Array.isArray(p.actions) || !Array.isArray(p.affected)) return null;\n // Re-validate each action shape; a single malformed action poisons the plan.\n for (const action of p.actions as unknown[]) {\n try {\n validateCorrectionAction(action);\n } catch {\n return null;\n }\n }\n return parsed as CorrectionPlan;\n}\n","/**\n * correction/correction-executor.ts — the only writer for corrections\n * (issue #1580 PR 2).\n *\n * Applies a {@link CorrectionPlan} in NON-DESTRUCTIVE ORDER\n * (rule 25 / checklist §14 — new state confirmed before old state destroyed):\n *\n * 1. Write replacement / edited memories first (through the injected\n * persist pipeline so catalog/reindex/dedup fire — rule 43; edits go\n * through page-versioning so every change is revertable).\n * 2. Then supersede / retract losers: status flip + `validUntil` stamp\n * (#1578, when gated on) + tombstone append (#1579).\n * 3. Then propagation: QMD reindex for touched files, graph edge updates,\n * belief-ledger claim status (optional-package dynamic import, rule 57),\n * profile.md line removal when an affected memory was profile-sourced.\n * 4. Append an audit record to `corrections/` capturing plan + outcome —\n * corrections are themselves memories, searchable and namespaced.\n * 5. Partial failure → tagged partial result (rule 34; checklist §22):\n * never a half-applied plan reported as success, and never old state\n * destroyed for an action whose replacement write failed.\n *\n * Concurrency: a plan may be applied exactly once. A second apply of the same\n * plan is rejected (plan consumed). Backed by the planner's atomic plan-store\n * (`markConsumed`) under `serializeMutations` keyed by plan id (rule 40).\n */\n\nimport { serializeMutations } from \"../utils/serialize-mutations.js\";\nimport type { CorrectionPlanner } from \"./correction-planner.js\";\nimport {\n CorrectionContractError,\n validateCorrectionAction,\n validateRedactionPattern,\n type CorrectionAction,\n type CorrectionActionResult,\n type CorrectionOutcome,\n type CorrectionPlan,\n} from \"./correction-contract.js\";\n\n// ---------------------------------------------------------------------------\n// Injected collaborators\n// ---------------------------------------------------------------------------\n\n/** A memory the executor is operating on (subset of MemoryFile). */\nexport interface ExecutorMemory {\n memoryId: string;\n content: string;\n category: string;\n /** True when the memory has frontmatter provenance (#1575 sourceQuote). */\n sourceQuote?: string;\n /** Structured-attribute supersession key, when one exists (legacy single-key). */\n supersessionKey?: string;\n /**\n * ALL derived supersession keys for the memory's structuredAttributes\n * (#1672 item 4). A paraphrased re-observation may place the tombstoned\n * attribute at a different position in structuredAttributes; without an\n * entry for every matched key the keyed tier misses and the fact\n * resurrects. Mirrors temporal-supersession's per-key emission.\n */\n supersessionKeys?: string[];\n /**\n * Canonical contentHash from the retired memory's frontmatter (#1672 item\n * 4 / #1579). Carried into the tombstone so the exact tier matches\n * re-extraction rather than recomputing from a citation-annotated body.\n */\n contentHash?: string;\n entityRef?: string;\n /** Raw content used for the tombstone hash (rule 23). */\n rawContent: string;\n}\n\nexport interface ExecutorDeps {\n /** Lookup a memory by id within the plan's namespace. null if not found. */\n getMemory(namespace: string, memoryId: string): Promise<ExecutorMemory | null>;\n /**\n * Persist a NEW memory through the orchestrator's normal write pipeline\n * (catalog/reindex/dedup fire — rule 43). Returns the new memory id.\n * Used by `supersede` (the replacement).\n */\n writeReplacement(\n namespace: string,\n draft: {\n content: string;\n category?: string;\n confidence?: number;\n tags?: string[];\n entityRef?: string;\n validAt?: string;\n observedAt?: string;\n structuredAttributes?: Record<string, string>;\n supersedes?: string;\n },\n ): Promise<string>;\n /**\n * Apply a versioned edit to an existing memory (page-versioning — every\n * change revertable). Returns the memory id. The patch is the NEW full\n * content; the implementation snapshots the prior version.\n */\n applyEdit(\n namespace: string,\n memoryId: string,\n patch: string,\n ): Promise<string>;\n /**\n * Flip a memory's status to superseded/retracted and stamp `validUntil`\n * when bi-temporal is gated on (#1578). Idempotent.\n */\n retireMemory(\n namespace: string,\n memoryId: string,\n opts: {\n status: \"superseded\" | \"retracted\";\n supersededBy?: string;\n validUntil?: string;\n },\n ): Promise<void>;\n /**\n * Move a memory to a different namespace (rescope). The destination\n * namespace is re-authorized by the service before the executor runs; the\n * implementation performs the move atomically (write-then-unlink).\n */\n rescopeMemory(namespace: string, memoryId: string, toNamespace: string): Promise<string>;\n /**\n * Append a tombstone (#1579) for a retired memory. Returns the tombstone\n * id, or null if tombstones are disabled (off = pre-feature behavior).\n */\n appendTombstone(\n namespace: string,\n input: {\n reason: \"correction\" | \"supersession\" | \"retraction\";\n sourceMemoryId: string;\n rawContent: string;\n entityRef?: string;\n supersessionKey?: string;\n /**\n * ALL derived supersession keys (#1672 item 4). When present, the\n * implementation emits one tombstone per key so a paraphrased\n * re-observation placing the attribute at a different key position is\n * still blocked at the keyed tier.\n */\n supersessionKeys?: string[];\n /** Canonical contentHash from the retired memory's frontmatter (#1672 item 4). */\n contentHash?: string;\n },\n ): Promise<string | null>;\n /**\n * Persist a redaction rule so extraction consults it the same way tombstones\n * are consulted (route through the same chokepoint check). Idempotent.\n */\n registerRedactionRule(namespace: string, pattern: string): Promise<void>;\n /**\n * Append an audit record under `corrections/` (existing storage category)\n * capturing plan + outcome. Returns the audit memory id.\n */\n appendAuditRecord(\n namespace: string,\n record: {\n planId: string;\n classification: CorrectionPlan[\"classification\"];\n outcome: CorrectionOutcome;\n requestText: string;\n },\n ): Promise<string>;\n /**\n * Post-write propagation: QMD reindex for touched files (checklist §31),\n * graph edge updates, belief-ledger claim status. Best-effort — a failure\n * here is recorded as a warning, never as a failed action (propagation is\n * not part of the §14 non-destructive-order guarantee; it runs after).\n */\n propagate(namespace: string, touchedMemoryIds: readonly string[]): Promise<void>;\n /** Whether the bi-temporal gate (#1578) is on. When off, validUntil is omitted. */\n readonly biTemporalEnabled: boolean;\n /** Injected clock for deterministic tests. */\n now(): Date;\n}\n\n// ---------------------------------------------------------------------------\n// Executor\n// ---------------------------------------------------------------------------\n\nexport class CorrectionExecutor {\n constructor(\n private readonly deps: ExecutorDeps,\n private readonly planner: CorrectionPlanner,\n ) {}\n\n /**\n * Apply a persisted plan by id. Idempotent-once: a second apply of the same\n * plan is rejected. Returns the {@link CorrectionOutcome}.\n */\n async apply(\n namespace: string,\n planId: string,\n opts: {\n confirm: boolean;\n /**\n * Authorize a rescope destination namespace. Bound per-request by the\n * service from the namespace policy + principal so a plan can never\n * write into a namespace the caller lacks write scope for (review\n * thread: authorize-rescope-destination). Defaults to allow when the\n * source namespace already resolves to a writable scope (single-tenant).\n */\n canWriteDestination?: (namespace: string) => Promise<boolean>;\n },\n ): Promise<CorrectionOutcome> {\n if (!opts.confirm) {\n throw new CorrectionContractError(\n \"Correction apply requires explicit confirmation (correction.applyRequiresConfirm).\",\n );\n }\n // serializeMutations on the plan id so two concurrent applies of the SAME\n // plan serialize — the second observes the consumed status and rejects.\n return serializeMutations(`correction-apply:${namespace}:${planId}`, () =>\n this.applyInternal(namespace, planId, opts.canWriteDestination),\n );\n }\n\n private async applyInternal(namespace: string, planId: string, canWriteDestination?: (namespace: string) => Promise<boolean>): Promise<CorrectionOutcome> {\n const plan = await this.planner.loadPlan(namespace, planId);\n if (!plan) {\n throw new CorrectionContractError(`Correction plan not found: ${planId}`);\n }\n if (plan.namespace !== namespace) {\n // Cross-namespace foreign-id guard (rule 42 / checklist §16).\n throw new CorrectionContractError(\n `Correction plan ${planId} belongs to namespace '${plan.namespace}', not '${namespace}'.`,\n );\n }\n if (plan.status === \"applied\" || plan.status === \"partial\" || plan.status === \"applying\") {\n throw new CorrectionContractError(\n `Correction plan ${planId} has already been applied or is in progress (status=${plan.status}).`,\n );\n }\n if (plan.status === \"discarded\") {\n throw new CorrectionContractError(`Correction plan ${planId} has been discarded.`);\n }\n // TTL check — expired plans are rejected with a clear error.\n if (this.deps.now().getTime() > new Date(plan.expiresAt).getTime()) {\n await this.planner.markConsumed(namespace, planId, \"discarded\");\n throw new CorrectionContractError(\n `Correction plan ${planId} expired at ${plan.expiresAt} and has been discarded.`,\n );\n }\n\n // Re-validate every action shape before applying (defense in depth).\n for (const action of plan.actions) {\n validateCorrectionAction(action);\n if (action.kind === \"redaction_rule\") {\n validateRedactionPattern(action.pattern);\n }\n }\n\n // Optimistically mark the plan `applying` BEFORE any mutation (review\n // thread OgIqt). If the process dies mid-apply — or the final\n // markConsumed(\"applied\"|\"partial\") fails — the plan stays `applying`\n // and is NOT silently retryable. A partially-applied plan must never be\n // re-applied wholesale: re-running succeeded actions would duplicate\n // replacements, tombstones, and audits. The operator inspects the\n // outcome and files a NEW plan for any failed actions. This mark runs\n // inside the serializeMutations lock so concurrent applies serialize.\n try {\n await this.planner.markConsumed(namespace, planId, \"applying\");\n } catch {\n // If we cannot even mark the plan in-progress, the filesystem is\n // likely unwritable and mutations would fail too — fail closed now.\n throw new CorrectionContractError(\n `Correction plan ${planId}: cannot mark in-progress (filesystem unwritable?) — aborting before any mutation.`,\n );\n }\n\n const results: CorrectionActionResult[] = [];\n const appliedTouched: string[] = [];\n\n // ── Phase 1: replacement / edit writes (new state first) ───────────────\n // For each supersede with a replacement, write the replacement FIRST. If\n // the write fails, the loser is NOT superseded (§14: never destroy old\n // state for an action whose replacement write failed).\n for (const action of plan.actions) {\n if (action.kind === \"supersede\" && action.replacement) {\n // Preflight the loser BEFORE writing the replacement (review thread\n // Of0pz): if the loser was deleted between plan and apply, writing a\n // replacement creates an orphan fact that supersedes nothing. Phase 2\n // (retireAndTombstone) re-checks via getMemory, so verifying here\n // keeps the two phases in agreement and avoids the orphan write.\n const loser = await this.deps.getMemory(namespace, action.loserId);\n if (!loser) {\n results.push({\n action,\n status: \"failed\",\n error: `supersede loser not found: ${action.loserId}`,\n });\n continue;\n }\n try {\n const newId = await this.deps.writeReplacement(namespace, {\n content: action.replacement.content,\n ...(action.replacement.category ? { category: action.replacement.category } : {}),\n ...(action.replacement.confidence !== undefined ? { confidence: action.replacement.confidence } : {}),\n ...(action.replacement.tags ? { tags: action.replacement.tags } : {}),\n ...(action.replacement.entityRef ? { entityRef: action.replacement.entityRef } : {}),\n ...(action.replacement.validAt ? { validAt: action.replacement.validAt } : {}),\n ...(action.replacement.observedAt ? { observedAt: action.replacement.observedAt } : {}),\n ...(action.replacement.structuredAttributes\n ? { structuredAttributes: action.replacement.structuredAttributes }\n : {}),\n supersedes: action.loserId,\n });\n results.push({ action, status: \"applied\", memoryId: newId });\n appliedTouched.push(newId);\n } catch (err) {\n results.push({\n action,\n status: \"failed\",\n error: errMsg(err),\n });\n }\n } else if (action.kind === \"edit\") {\n try {\n const editedId = await this.deps.applyEdit(namespace, action.memoryId, action.patch);\n results.push({ action, status: \"applied\", memoryId: editedId });\n appliedTouched.push(editedId);\n } catch (err) {\n results.push({ action, status: \"failed\", error: errMsg(err) });\n }\n } else if (action.kind === \"redaction_rule\") {\n try {\n await this.deps.registerRedactionRule(namespace, action.pattern);\n results.push({ action, status: \"applied\" });\n } catch (err) {\n results.push({ action, status: \"failed\", error: errMsg(err) });\n }\n }\n }\n\n // ── Phase 2: retire losers + tombstones ───────────────────────────────\n // Only run for supersede/retract actions whose replacement write (if any)\n // succeeded. A supersede WITHOUT a replacement is a pure retract.\n for (const action of plan.actions) {\n if (action.kind === \"supersede\") {\n const replacementResult = results.find(\n (r) => r.action === action && r.status === \"applied\",\n );\n // If the replacement write failed, skip retirement (§14).\n if (action.replacement && !replacementResult) {\n continue;\n }\n await this.retireAndTombstone(namespace, action, \"supersession\", results, appliedTouched, {\n supersededBy: replacementResult?.memoryId,\n });\n } else if (action.kind === \"retract\") {\n await this.retireAndTombstone(namespace, action, \"retraction\", results, appliedTouched);\n } else if (action.kind === \"rescope\") {\n try {\n // Authorize the destination namespace BEFORE the move — the plan's\n // toNamespace comes from the LLM/persisted plan and must not bypass\n // the write ACL (review thread: authorize-rescope-destination).\n // canWriteDestination defaults to allow when absent (single-tenant,\n // where the source namespace already resolved to a writable scope).\n const allowed = canWriteDestination ? await canWriteDestination(action.toNamespace) : true;\n if (!allowed) {\n results.push({\n action,\n status: \"failed\",\n error: `rescope destination namespace not writable: ${action.toNamespace}`,\n });\n continue;\n }\n const destId = await this.deps.rescopeMemory(namespace, action.memoryId, action.toNamespace);\n // #1678 (thread OiiV6): report the DESTINATION memory id, not the\n // source. The source is archived by the move; callers that re-fetch\n // the reported id need the live (destination) memory, otherwise they\n // observe an archived fact and the correction looks like a no-op.\n results.push({ action, status: \"applied\", memoryId: destId });\n appliedTouched.push(action.memoryId); // source id for source-side propagation\n // Propagate the destination memory in its namespace too (review\n // thread: propagate-rescoped-destination) — best-effort.\n try {\n await this.deps.propagate(action.toNamespace, [destId]);\n } catch {\n // non-fatal — the source propagation still fires.\n }\n } catch (err) {\n results.push({ action, status: \"failed\", error: errMsg(err) });\n }\n }\n }\n\n // ── Phase 3: propagation (post-write reindex + graph) ─────────────────\n // Best-effort: a propagation failure is recorded as a warning on the\n // outcome, never as a failed action (it runs AFTER the §14 guarantee).\n const propagationWarnings: string[] = [];\n if (appliedTouched.length > 0) {\n try {\n await this.deps.propagate(namespace, appliedTouched);\n } catch (err) {\n propagationWarnings.push(`propagation failed (non-fatal): ${errMsg(err)}`);\n }\n }\n\n // ── Phase 4: audit record ─────────────────────────────────────────────\n const anyFailed = results.some((r) => r.status === \"failed\");\n const status: CorrectionOutcome[\"status\"] = anyFailed ? \"partial\" : \"applied\";\n const appliedAt = this.deps.now().toISOString();\n const outcome: CorrectionOutcome = {\n planId,\n status,\n results,\n auditMemoryId: \"\", // filled after the audit write\n appliedAt,\n };\n if (propagationWarnings.length > 0) {\n (outcome as CorrectionOutcome & { warnings?: string[] }).warnings = propagationWarnings;\n }\n try {\n const auditId = await this.deps.appendAuditRecord(namespace, {\n planId,\n classification: plan.classification,\n outcome,\n requestText: plan.request.text,\n });\n outcome.auditMemoryId = auditId;\n } catch (err) {\n // The audit record is part of the contract but a failure to write it\n // must NOT undo the applied corrections. Record as a warning.\n (outcome as CorrectionOutcome & { warnings?: string[] }).warnings = [\n ...propagationWarnings,\n `audit record write failed (non-fatal): ${errMsg(err)}`,\n ];\n }\n\n // ── Phase 5: mark plan consumed ───────────────────────────────────────\n // Corrections are already applied (phases 1-4 succeeded). A markConsumed\n // failure must NOT propagate — that would make a client retry re-apply all\n // corrections (review thread: applyInternal-plan-unconsumed). Record as a\n // warning; the pending plan is reconciled by TTL discard on the next pass.\n try {\n await this.planner.markConsumed(namespace, planId, status);\n } catch (err) {\n const w = outcome as CorrectionOutcome & { warnings?: string[] };\n w.warnings = [...(w.warnings ?? []), `plan mark-consumed failed (non-fatal): ${errMsg(err)}`];\n }\n return outcome;\n }\n\n private async retireAndTombstone(\n namespace: string,\n action: CorrectionAction,\n reason: \"supersession\" | \"retraction\",\n results: CorrectionActionResult[],\n appliedTouched: string[],\n opts: { supersededBy?: string } = {},\n ): Promise<void> {\n const memoryId =\n action.kind === \"supersede\" ? action.loserId : action.kind === \"retract\" ? action.memoryId : null;\n if (!memoryId) return;\n try {\n const memory = await this.deps.getMemory(namespace, memoryId);\n if (!memory) {\n results.push({\n action,\n status: \"failed\",\n error: `memory not found: ${memoryId}`,\n });\n return;\n }\n const validUntil = this.deps.biTemporalEnabled ? this.deps.now().toISOString() : undefined;\n // Write the tombstone BEFORE retiring the source memory (review thread\n // PG9): if appendTombstone throws here, retireMemory has not run yet, so\n // the source stays active, the action fails cleanly, and a retry\n // operates on un-mutated state with no resurrection window. A tombstone\n // for a still-active memory (if retire later fails) is benign — it only\n // blocks re-ingestion of the same content, which is exactly the intent.\n const tombstoneId = await this.deps.appendTombstone(namespace, {\n reason,\n sourceMemoryId: memoryId,\n rawContent: memory.rawContent,\n ...(memory.entityRef ? { entityRef: memory.entityRef } : {}),\n ...(memory.supersessionKey ? { supersessionKey: memory.supersessionKey } : {}),\n // #1672 item 4: carry the canonical contentHash (exact tier) and the\n // full supersession-key set (keyed tier) so paraphrased re-observations\n // of the same supersession identity are blocked, not just the literal\n // body. Without these the tombstone projected from a structured fact\n // dropped both fields and the fact could resurrect.\n ...(memory.contentHash ? { contentHash: memory.contentHash } : {}),\n ...(memory.supersessionKeys && memory.supersessionKeys.length > 0\n ? { supersessionKeys: memory.supersessionKeys }\n : {}),\n });\n await this.deps.retireMemory(namespace, memoryId, {\n status: reason === \"supersession\" ? \"superseded\" : \"retracted\",\n ...(opts.supersededBy ? { supersededBy: opts.supersededBy } : {}),\n ...(validUntil ? { validUntil } : {}),\n });\n results.push({\n action,\n status: \"applied\",\n memoryId,\n ...(tombstoneId ? { tombstoneId } : {}),\n });\n appliedTouched.push(memoryId);\n } catch (err) {\n results.push({ action, status: \"failed\", error: errMsg(err) });\n }\n }\n}\n\n/**\n * Sanitize an error message before it lands in a CorrectionOutcome result\n * (#1678). Outcome results are surfaced to MCP/HTTP/CLI callers and may be\n * persisted in the audit memory, so they must not leak absolute filesystem\n * paths (host layout / usernames / secrets in paths) or unbounded verbosity.\n * Strip absolute paths and cap length; never reveal more than the message's\n * short-form. The original error is still thrown/logged in full internally.\n */\nexport const CORRECTION_ERROR_MAX = 500;\nexport function sanitizeErrorMessage(raw: string): string {\n // Collapse any absolute POSIX path (/Users/foo/..., /.config/..., /tmp/a@b/...) and\n // Windows path (C:\\Users\\...) to a neutral <path> placeholder.\n // Capture the leading delimiter (start/space/quote) in group 1 so the path\n // itself is consumed and replaced — the prior non-capturing prefix bound $1\n // to the path, which survived and had <path> appended AFTER it.\n const stripped = raw\n .replace(/(^|[\\s:'\"(])\\/(?:[^\\s'\">)\\\\]+\\/)+[^\\s'\">)\\\\]*/g, \"$1<path>\")\n .replace(/(^|[\\s:'\"(])[A-Za-z]:\\\\[^\\s'\">)\\\\]+(?:\\\\[^\\s'\">) ]*)*/g, \"$1<path>\");\n const trimmed = stripped.trim();\n return trimmed.length > CORRECTION_ERROR_MAX\n ? `${trimmed.slice(0, CORRECTION_ERROR_MAX)}…`\n : trimmed;\n}\n\nfunction errMsg(err: unknown): string {\n const raw = err instanceof Error ? err.message : String(err);\n return sanitizeErrorMessage(raw);\n}\n","/**\n * correction/correction-service.ts — thin orchestration for the Correction\n * Contract (issue #1580 PR 3).\n *\n * Owns the single plan/apply pipeline every correction surface (MCP / HTTP /\n * CLI) calls. Authorizes the caller through the existing namespace policy,\n * constructs the planner + executor with their collaborators, and exposes\n * `plan` / `apply` / `listPending` / `discard`.\n *\n * The service NEVER accepts a caller-supplied namespace without policy\n * validation (rule 42; checklist §16 foreign-ID guard): a principal may only\n * PLAN against namespaces they can READ and APPLY against namespaces they can\n * WRITE — both resolved through the injected namespace policy.\n */\n\nimport {\n CorrectionContractError,\n type CorrectionOutcome,\n type CorrectionPlan,\n type CorrectionRequest,\n} from \"./correction-contract.js\";\nimport { CorrectionPlanner, type PlannerDeps } from \"./correction-planner.js\";\nimport { CorrectionExecutor, type ExecutorDeps } from \"./correction-executor.js\";\n\n// ---------------------------------------------------------------------------\n// Injected collaborators — the access-service wires these from the orchestrator.\n// ---------------------------------------------------------------------------\n\n/**\n * Namespace policy façade. The access-service already implements these via\n * `resolveWritableNamespace` / `canReadNamespace` / `canWriteNamespace`; the\n * correction service consumes them through this narrow interface so the\n * correction modules stay decoupled from the access-service's surface area.\n */\nexport interface CorrectionNamespacePolicy {\n /**\n * Resolve the AUTHORIZED effective namespace for a plan/apply request.\n * Throws when the caller lacks read+write scope. The returned namespace is\n * the ONE the planner + executor operate in.\n */\n resolveAuthorizedNamespace(request: {\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<string>;\n /**\n * Whether the caller may WRITE a given namespace. Used to authorize rescope\n * destinations before the executor moves a memory across namespaces.\n */\n canWriteNamespace(request: {\n namespace: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<boolean>;\n /** Namespaces the caller may read — scopes the planner's search. */\n readableNamespaces(request: {\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<readonly string[]>;\n}\n\n/**\n * Factory wiring for the planner + executor deps. The service holds ONE\n * planner + ONE executor for its lifetime; both are stateless across requests\n * (per-request scope is threaded through method parameters, rules 11/47).\n */\nexport interface CorrectionServiceDeps {\n readonly policy: CorrectionNamespacePolicy;\n /**\n * Planner collaborators. The planner takes `readableNamespaces` per call to\n * `plan()`, so a single deps instance serves callers with different scopes.\n */\n plannerDeps(): PlannerDeps;\n /** Executor collaborators (one per service). */\n executorDeps(): ExecutorDeps;\n /** Whether the correction feature is enabled (gate). */\n isEnabled(): boolean;\n /** Whether apply requires explicit confirmation (rule 48). */\n applyRequiresConfirm(): boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Service\n// ---------------------------------------------------------------------------\n\nexport class CorrectionService {\n private readonly planner: CorrectionPlanner;\n private readonly executor: CorrectionExecutor;\n\n constructor(private readonly deps: CorrectionServiceDeps) {\n this.planner = new CorrectionPlanner(deps.plannerDeps());\n this.executor = new CorrectionExecutor(deps.executorDeps(), this.planner);\n }\n\n /**\n * Plan a correction. Read-only — produces + persists a {@link CorrectionPlan}.\n * Safe to run with the gate ON (default) since the plan writes no memory state.\n *\n * The plan is stored under the AUTHORIZED (writable) namespace — the same\n * namespace apply/listPending/discard resolve — so the plan is always\n * found by the caller that created it (review threads: plan-stored-wrong-\n * namespace + cross-namespace candidate mismatch). Candidates are located\n * within that single namespace too: a correction can only affect memories\n * the principal can write, so reading from a non-writable namespace to\n * draft a correction that can never be applied would be misleading.\n */\n async plan(request: CorrectionRequest): Promise<CorrectionPlan> {\n this.requireEnabled();\n const authorized = await this.deps.policy.resolveAuthorizedNamespace(request);\n return this.planner.plan(request, [authorized]);\n }\n\n /**\n * Apply a persisted plan by id. Requires `confirm: true` (or interactive\n * yes at the CLI) when `applyRequiresConfirm` is on (default).\n */\n async apply(\n planId: string,\n opts: {\n confirm?: boolean;\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n },\n ): Promise<CorrectionOutcome> {\n this.requireEnabled();\n if (this.deps.applyRequiresConfirm() && opts.confirm !== true) {\n throw new CorrectionContractError(\n \"Correction apply requires explicit confirmation (pass `confirm: true`).\",\n );\n }\n const namespace = await this.deps.policy.resolveAuthorizedNamespace({\n ...(opts.namespace ? { namespace: opts.namespace } : {}),\n ...(opts.sessionKey ? { sessionKey: opts.sessionKey } : {}),\n ...(opts.principal ? { principal: opts.principal } : {}),\n });\n return this.executor.apply(namespace, planId, {\n confirm: true,\n // Authorize rescope destinations through the namespace policy bound to\n // THIS caller's principal (review thread: authorize-rescope-destination).\n canWriteDestination: (dest) =>\n this.deps.policy.canWriteNamespace({\n namespace: dest,\n ...(opts.sessionKey ? { sessionKey: opts.sessionKey } : {}),\n ...(opts.principal ? { principal: opts.principal } : {}),\n }),\n });\n }\n\n /** List pending (not-yet-applied) plans for the caller's namespace. */\n async listPending(opts: {\n namespace?: string;\n sessionKey?: string;\n principal?: string;\n }): Promise<CorrectionPlan[]> {\n this.requireEnabled();\n const namespace = await this.deps.policy.resolveAuthorizedNamespace(opts);\n return this.planner.listPending(namespace);\n }\n\n /** Discard a pending plan. Idempotent. */\n async discard(\n planId: string,\n opts: { namespace?: string; sessionKey?: string; principal?: string },\n ): Promise<void> {\n this.requireEnabled();\n const namespace = await this.deps.policy.resolveAuthorizedNamespace(opts);\n await this.planner.markConsumed(namespace, planId, \"discarded\");\n await this.planner.deletePlan(namespace, planId);\n }\n\n private requireEnabled(): void {\n if (!this.deps.isEnabled()) {\n throw new CorrectionContractError(\n \"Correction Contract is disabled (set correction.enabled = true to enable).\",\n );\n }\n }\n}\n","/**\n * correction/passive-correction-detector.ts — morphology-aware heuristic detector\n * for corrections expressed passively in conversation turns (issue #1581).\n *\n * Users correct their agents constantly in conversation: \"no, we renamed that\n * service\", \"I don't use Vim anymore\", \"the deadline moved to Friday\". This\n * module detects those corrections from turn text — NO extra LLM call — so the\n * passive-capture module can route them to the Correction Contract (#1580).\n *\n * Design:\n * - Pure function: `detectPassiveCorrections(turns)` → `PassiveCorrection[]`.\n * - Only USER turns are scanned (assistants don't correct their own memory).\n * - Morphology-aware: matches conjugations/variants per AGENTS.md intent\n * guardrail (\"heuristics must be morphology-aware and precedence-tested\").\n * - Anti-fixture guards reject: hypotheticals, third-party corrections,\n * quoted-speech corrections, and self-resolving corrections.\n *\n * The detector is deliberately CONSERVATIVE — it prefers false negatives\n * (missing a correction) over false positives (flooding the review queue).\n * The nightly contradiction scan and the interactive correction chat (#1583)\n * catch what passive detection misses.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport type PassiveCorrectionPolarity = \"update\" | \"retract\" | \"stop_storing\";\n\nexport interface PassiveCorrection {\n /** What the user says is wrong (\"Redis\", \"the deadline\", \"my editor preference\"). */\n targetHint: string;\n /** The new truth, or \"\" for pure retractions. */\n correctedAssertion: string;\n polarity: PassiveCorrectionPolarity;\n /** `[m:xxxx]` handle references found verbatim in the turn (#1582). */\n handles: string[];\n /** Heuristic confidence in [0, 1] — influences auto-apply gating. */\n confidence: number;\n /** The verbatim source text that triggered the detection. */\n sourceExcerpt: string;\n /** Index of the turn in the input array that produced this correction. */\n turnIndex: number;\n}\n\nexport interface DetectorTurn {\n role: \"user\" | \"assistant\" | \"other\";\n content: string;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern definitions\n// ---------------------------------------------------------------------------\n\ninterface CorrectionPattern {\n polarity: PassiveCorrectionPolarity;\n /** Regex MUST be case-insensitive and use word boundaries where appropriate. */\n regex: RegExp;\n /** Confidence assigned when this pattern is the sole signal. */\n confidence: number;\n}\n\n/**\n * Strong correction signals — these phrases reliably indicate the user is\n * correcting a stored memory about their own world. Each is morphology-aware\n * (covers present/progressive/past tenses and common variants).\n */\nconst PATTERNS: readonly CorrectionPattern[] = [\n // ── update: new fact replaces / corrects an old one ──────────────────────\n {\n polarity: \"update\",\n // \"actually, it's X not Y\" / \"actually we use X now\"\n regex: /\\bactually[,\\s]+(?:it'?s|we|the|i|our|my|\\[m:)/i,\n confidence: 0.85,\n },\n {\n polarity: \"update\",\n // \"we switched/switching/switched to X\"\n regex: /\\bwe\\b\\s*(?:(?:'re|'ve|are|have)\\s+)?(?:switch(?:ed|ing)?|migrat(?:ed|ing)?|mov(?:ed|ing)?|chang(?:ed|ing)?)\\s+(?:to|over to|from)\\b/i,\n confidence: 0.9,\n },\n {\n polarity: \"update\",\n // \"we renamed X to Y\" / \"i renamed\"\n regex: /\\b(?:we|i)\\s+renam(?:ed|ing)\\b/i,\n confidence: 0.9,\n },\n {\n polarity: \"update\",\n // \"it's now X\" / \"the deadline moved to X\" / \"the date changed to X\"\n regex: /\\b(?:it'?s now|the\\s+(?:deadline|date|meeting|standup|review)\\s+(?:moved|chang(?:ed|ing))?\\s*to)\\b/i,\n confidence: 0.85,\n },\n {\n polarity: \"update\",\n // \"no, \" at the start of a turn or clause — strong correction signal\n regex: /(?:^|\\.\\s+|\\n)\\s*no[,\\s]+(?:we|i|it|the|our|my|that)\\b/i,\n confidence: 0.8,\n },\n {\n polarity: \"update\",\n // \"no longer\" / \"not anymore\" + an activity\n regex: /\\b(?:no longer|not anymore)\\b/i,\n confidence: 0.8,\n },\n {\n polarity: \"update\",\n // Standalone \"outdated\" — catches \"are both outdated\", \"is outdated\", etc.\n regex: /\\boutdated\\b/i,\n confidence: 0.75,\n },\n {\n polarity: \"update\",\n // \"that's outdated\" / \"that's old\"\n regex: /\\bthat'?s\\s+(?:outdated|old|no longer (?:true|correct|accurate))\\b/i,\n confidence: 0.85,\n },\n // ── retract: user says a fact is simply wrong ────────────────────────────\n {\n polarity: \"retract\",\n regex: /\\bthat'?s\\s+(?:wrong|not right|incorrect|not true|false)\\b/i,\n confidence: 0.85,\n },\n {\n polarity: \"retract\",\n // \"we don't use X anymore\" / \"I don't use X anymore\"\n regex: /\\b(?:we|i)\\s+don'?t\\s+use\\s+\\S+\\s+anymore\\b/i,\n confidence: 0.9,\n },\n {\n polarity: \"retract\",\n regex: /\\bforget about\\b/i,\n confidence: 0.8,\n },\n // ── stop_storing: user wants the agent to stop a behavior ────────────────\n {\n polarity: \"stop_storing\",\n regex: /\\bstop\\s+(?:suggesting|bringing\\s+up|recommending|reminding\\s+me\\s+(?:about)?)\\b/i,\n confidence: 0.9,\n },\n {\n polarity: \"stop_storing\",\n regex: /\\b(?:don'?t|never)\\s+(?:mention|suggest|recommend|store|bring\\s+up)\\b/i,\n confidence: 0.85,\n },\n];\n\n// ---------------------------------------------------------------------------\n// Anti-fixture guards\n// ---------------------------------------------------------------------------\n\n/**\n * Hypothetical markers — if present near the correction signal, the turn is\n * discussing a hypothetical scenario, not correcting a stored fact.\n */\nconst HYPOTHETICAL_REGEX =\n /\\b(?:if\\s+(?:we|you|i|they)\\s+(?:ever|were|could|might|should|decide)|what\\s+if|suppose|hypothetically|in\\s+(?:theory|principle)|let'?s\\s+say|imagine\\s+if)\\b/i;\n\n/**\n * Third-party correction markers — the user is correcting someone else, not\n * their agent's memory of their own world.\n */\nconst THIRD_PARTY_REGEX =\n /\\b(?:tell\\s+\\w+\\s+(?:he|she|they|you)'?re?\\s+wrong|he'?s\\s+wrong\\s+about|she'?s\\s+wrong\\s+about|they'?re\\s+wrong\\s+about|correct\\s+\\w+\\s+on)\\b/i;\n\n/**\n * Tool-output correction — the user is saying a tool's output is wrong, not\n * that their stored memory is wrong.\n */\nconst TOOL_OUTPUT_REGEX =\n /\\b(?:the\\s+(?:output|result|response|error|log)|your\\s+(?:output|result|response|code|answer))\\s+(?:is\\s+)?(?:wrong|incorrect|bad|off)\\b/i;\n\n/**\n * Self-resolving correction — the user corrects themselves within the same\n * turn (\"actually wait, no, the original was right\"). These turn back and\n * cancel out.\n */\nconst SELF_RESOLVE_REGEX =\n /(?:actually|wait|no)[,\\s]+(?:never\\s*mind|forget\\s*(?:that|it)|the\\s+(?:original|first)\\s+(?:was|is)\\s+(?:right|correct)|scratch\\s+that|disregard)/i;\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/** Extract `[m:xxxx]` handle references from text (#1582). */\nexport function extractHandles(text: string): string[] {\n const matches = text.match(/\\[m:[0-9a-fA-F]{4,}\\]/g);\n return matches ?? [];\n}\n\n/**\n * Extract a target hint from the matched correction text. Returns a short\n * phrase (≤80 chars) the planner can use to locate the affected memory.\n */\nfunction extractTargetHint(text: string, match: RegExpMatchArray): string {\n const matchStart = match.index ?? 0;\n // Take a window around the match: 20 chars before to 60 chars after.\n const start = Math.max(0, matchStart - 20);\n const end = Math.min(text.length, matchStart + match[0].length + 60);\n const window = text.slice(start, end).replace(/\\s+/g, \" \").trim();\n return window.length > 80 ? window.slice(0, 77) + \"...\" : window;\n}\n\n/**\n * Extract the corrected assertion — the new truth the user is expressing.\n * For \"update\" polarity, this is the full turn text (the planner searches for\n * the old fact and drafts a replacement). For \"retract\", it's \"\" (no\n * replacement). For \"stop_storing\", it's the behavior to suppress.\n */\nfunction extractCorrectedAssertion(\n text: string,\n polarity: PassiveCorrectionPolarity,\n): string {\n if (polarity === \"retract\") return \"\";\n // For update/stop_storing, the full turn IS the assertion (truncated).\n const trimmed = text.replace(/\\s+/g, \" \").trim();\n return trimmed.length > 200 ? trimmed.slice(0, 197) + \"...\" : trimmed;\n}\n\n/**\n * Check whether a regex match at the given index is within quotation marks.\n * Used to reject corrections that are actually quoted speech (someone else's\n * words the user is relaying, not the user correcting their own memory).\n */\nfunction isWithinQuotes(text: string, matchIndex: number): boolean {\n // Only DOUBLE quotes delimit quoted speech. Single quotes (ASCII apostrophe\n // and smart single quotes) are deliberately NOT treated as delimiters: in\n // English they are overwhelmingly contractions/possessives\n // (\"I don't think we switched\"), which would falsely mark a\n // correction as quoted speech and suppress a valid detection (false\n // negative). A contraction before the correction phrase must not flip the\n // detector into quoted mode.\n let inQuote = false;\n for (let i = 0; i < matchIndex && i < text.length; i++) {\n const c = text[i];\n if (c === '\"' || c === '\\u201c' || c === '\\u201d') {\n inQuote = !inQuote;\n }\n }\n return inQuote;\n}\n\n/**\n * Check whether any anti-fixture guard fires on the turn text.\n * Returns the guard name that blocked detection, or null if clean.\n */\nfunction detectAntiFixture(text: string): string | null {\n if (SELF_RESOLVE_REGEX.test(text)) return \"self_resolving\";\n if (HYPOTHETICAL_REGEX.test(text)) return \"hypothetical\";\n if (THIRD_PARTY_REGEX.test(text)) return \"third_party\";\n if (TOOL_OUTPUT_REGEX.test(text)) return \"tool_output\";\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Detect passive corrections in a sequence of conversation turns.\n *\n * Only USER turns are scanned — assistant turns don't express corrections to\n * the agent's stored memory. Each user turn is checked against the correction\n * patterns; anti-fixture guards reject turns that look like hypotheticals,\n * third-party corrections, tool-output complaints, or self-resolving double-\n * corrections.\n *\n * A single turn may produce multiple corrections if different patterns match\n * different parts of the text. Dedup by (turnIndex, targetHint) so overlapping\n * patterns on the same phrase (e.g. \"actually, we don't use Redis anymore\"\n * matching both update + retract) produce one correction.\n */\nexport function detectPassiveCorrections(\n turns: readonly DetectorTurn[],\n): PassiveCorrection[] {\n const results: PassiveCorrection[] = [];\n const seen = new Set<string>();\n\n for (let i = 0; i < turns.length; i++) {\n const turn = turns[i];\n if (turn.role !== \"user\") continue;\n const content = turn.content?.trim();\n if (!content) continue;\n\n // Anti-fixture guards take precedence — one guard kills ALL corrections\n // from this turn (a hypothetical turn can't contain a real correction).\n const guard = detectAntiFixture(content);\n if (guard) continue;\n\n const handles = extractHandles(content);\n\n for (const pattern of PATTERNS) {\n const match = pattern.regex.exec(content);\n if (!match) continue;\n\n // Reject corrections that appear within quotation marks — the user is\n // relaying someone else's words, not correcting their own stored memory.\n if (match.index !== undefined && isWithinQuotes(content, match.index)) {\n continue;\n }\n\n const targetHint = extractTargetHint(content, match);\n const correctedAssertion = extractCorrectedAssertion(content, pattern.polarity);\n // Polarity-agnostic: \"actually, we don't use Redis anymore\" matches\n // both the update (\"actually\") and retract (\"don't use ... anymore\")\n // patterns with the same targetHint — emit one correction, not two\n // (review: \"deduplicate overlapping passive-correction cues\").\n const dedupKey = `${i}:${targetHint}`;\n if (seen.has(dedupKey)) continue;\n seen.add(dedupKey);\n\n results.push({\n targetHint,\n correctedAssertion,\n polarity: pattern.polarity,\n handles,\n confidence: pattern.confidence,\n sourceExcerpt: content.slice(0, 200),\n turnIndex: i,\n });\n }\n }\n\n return results;\n}\n","/**\n * correction/passive-capture.ts — routes detected passive corrections to the\n * Correction Contract (#1580) by mode: queue, auto, or off (issue #1581).\n *\n * This module is the thin handoff between the extraction post-processing step\n * (which calls `detectPassiveCorrections`) and the CorrectionService's\n * `plan()` / `apply()` pipeline. It adds NO parallel correction logic (rule 22)\n * — the planner does all the locating/classifying; this module only decides\n * whether to queue the resulting plan for review or auto-apply it.\n *\n * Guards (auto mode):\n * - plan confidence ≥ confidenceFloor\n * - classification ∈ {outdated, wrong}\n * - affected.length ≤ autoApplyMaxAffected\n * - every action ∈ {supersede, edit, retract} (never auto-apply\n * rescope/redaction_rule/never_store — those are policy changes)\n * If ANY guard fails, the plan falls back to queue.\n *\n * Session scoping (rule 42): a correction detected in session S plans only\n * against S's readable namespaces. The CorrectionService already enforces this\n * through its namespace policy; this module passes the session-scoped context.\n *\n * Dedup: fingerprint detected corrections by `bufferKey + normalizedCorrectionText`\n * so parallel sessions / re-flushes don't double-plan.\n */\n\nimport { log } from \"../logger.js\";\nimport type { PassiveCorrection } from \"./passive-correction-detector.js\";\nimport type {\n CorrectionClassification,\n CorrectionOutcome,\n CorrectionPlan,\n CorrectionRequest,\n CorrectionAction,\n} from \"./correction-contract.js\";\nimport {\n enqueuePassiveCorrectionNotification,\n} from \"./passive-correction-notifications.js\";\n\n// ---------------------------------------------------------------------------\n// Config + context\n// ---------------------------------------------------------------------------\n\nexport type CorrectionCaptureMode = \"off\" | \"queue\" | \"auto\";\n\nexport interface PassiveCaptureConfig {\n mode: CorrectionCaptureMode;\n confidenceFloor: number;\n autoApplyMaxAffected: number;\n}\n\nexport interface PassiveCaptureContext {\n /** The correction feature must be enabled for capture to run. */\n correctionEnabled: boolean;\n /** Whether this is a live session (not replay/import). Auto-apply is\n * live-session only — replayed history may contain corrections the user\n * later re-reverted; queue those. */\n isLiveSession: boolean;\n /** Buffer key for dedup fingerprinting. */\n bufferKey: string;\n /** Session key for namespace/principal resolution. */\n sessionKey?: string;\n /** Authenticated principal. */\n principal?: string;\n /** Authorized namespace the extraction wrote to. */\n namespace: string;\n}\n\n// ---------------------------------------------------------------------------\n// Deps (injected — the orchestrator wires these)\n// ---------------------------------------------------------------------------\n\nexport interface PassiveCaptureDeps {\n /** Plan a correction through the Correction Contract. */\n planCorrection(request: CorrectionRequest): Promise<CorrectionPlan>;\n /** Apply a planned correction (auto mode only). */\n applyCorrection(\n planId: string,\n opts: { confirm: true; namespace?: string; sessionKey?: string; principal?: string },\n ): Promise<CorrectionOutcome>;\n /** Resolve the storage dir for notification enqueue (per namespace). */\n storageDir(namespace: string): Promise<string>;\n /**\n * Resolve a memory handle (`[m:xxxx]`) to a concrete memory id, returning\n * null when the handle is unresolvable in the session (graceful — the\n * planner then falls back to text search). Wired to the orchestrator single\n * shared `resolveMemoryIdOrHandle` helper (#1582) so handle resolution has\n * one path (rule 22). Review: \"memory handles not resolved\".\n */\n resolveHandle?(ref: string, sessionKey?: string): string | null;\n}\n\n// ---------------------------------------------------------------------------\n// Telemetry\n// ---------------------------------------------------------------------------\n\nexport interface PassiveCaptureTelemetry {\n detected: number;\n queued: number;\n autoApplied: number;\n /** Reason → count for auto-apply suppressions. */\n suppressedReasons: Record<string, number>;\n}\n\nexport function emptyTelemetry(): PassiveCaptureTelemetry {\n return { detected: 0, queued: 0, autoApplied: 0, suppressedReasons: {} };\n}\n\n// ---------------------------------------------------------------------------\n// Dedup fingerprint\n// ---------------------------------------------------------------------------\n\n/** Normalize correction text for fingerprinting (case + whitespace + punctuation). */\nfunction normalizeForFingerprint(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s]/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim()\n .slice(0, 200);\n}\n\nfunction correctionFingerprint(bufferKey: string, correction: PassiveCorrection): string {\n return `${bufferKey}::${correction.polarity}::${normalizeForFingerprint(correction.targetHint)}`;\n}\n\n// ---------------------------------------------------------------------------\n// Auto-apply guards\n// ---------------------------------------------------------------------------\n\n/** Action kinds that are safe to auto-apply (state-preserving, not policy changes). */\nconst AUTO_APPLICABLE_ACTION_KINDS = new Set([\"supersede\", \"edit\", \"retract\"]);\n\n/** Classifications safe for auto-apply. */\nconst AUTO_APPLICABLE_CLASSIFICATIONS = new Set<CorrectionClassification>([\"outdated\", \"wrong\"]);\n\nexport type AutoApplySuppressionReason =\n | \"non_live_session\"\n | \"confidence_below_floor\"\n | \"classification_not_allowed\"\n | \"affected_too_large\"\n | \"disallowed_action_kind\"\n | \"empty_plan\";\n\n/**\n * Evaluate all auto-apply guards. Returns the suppression reason (if any), or\n * null if auto-apply may proceed.\n */\nexport function evaluateAutoApplyGuards(\n plan: CorrectionPlan,\n config: PassiveCaptureConfig,\n isLiveSession: boolean,\n): AutoApplySuppressionReason | null {\n if (!isLiveSession) return \"non_live_session\";\n if (plan.confidence < config.confidenceFloor) return \"confidence_below_floor\";\n if (!AUTO_APPLICABLE_CLASSIFICATIONS.has(plan.classification)) {\n return \"classification_not_allowed\";\n }\n if (plan.affected.length > config.autoApplyMaxAffected) {\n return \"affected_too_large\";\n }\n // An empty action list is a no-op plan (review: \"queue plans that contain no\n // actions\"). Auto-applying it would mark a correction as applied, write an\n // audit record + notification, and record the dedup fingerprint — yet nothing\n // changed. Suppress so it queues for human review instead.\n if (plan.actions.length === 0) {\n return \"empty_plan\";\n }\n for (const action of plan.actions) {\n if (!AUTO_APPLICABLE_ACTION_KINDS.has(action.kind)) {\n return \"disallowed_action_kind\";\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Main entry: capture passive corrections\n// ---------------------------------------------------------------------------\n\nexport interface PassiveCaptureResult {\n telemetry: PassiveCaptureTelemetry;\n /** Plans created (both queued and auto-applied). */\n plans: CorrectionPlan[];\n}\n\n/**\n * Process a batch of detected passive corrections. For each correction:\n * 1. Check dedup fingerprint — skip if already processed for this bufferKey.\n * 2. Build a CorrectionRequest and call the planner.\n * 3. Dispatch by mode: queue → plan is left pending; auto → apply if all\n * guards pass, else fall back to queue.\n * 4. Record telemetry.\n *\n * Fail-open: a planning or apply error for ONE correction never blocks the\n * others. The error is logged and the correction is counted as suppressed.\n */\nexport async function capturePassiveCorrections(\n corrections: readonly PassiveCorrection[],\n ctx: PassiveCaptureContext,\n config: PassiveCaptureConfig,\n deps: PassiveCaptureDeps,\n dedupState: Set<string>,\n): Promise<PassiveCaptureResult> {\n const telemetry = emptyTelemetry();\n const plans: CorrectionPlan[] = [];\n telemetry.detected = corrections.length;\n\n for (const correction of corrections) {\n // 1. Dedup — checked before planning, but the fingerprint is only\n // recorded AFTER a successful plan so a transient planning failure\n // can be retried on a later flush (review: \"dedup blocks retry\n // after failure\").\n const fp = correctionFingerprint(ctx.bufferKey, correction);\n if (dedupState.has(fp)) {\n continue;\n }\n\n // 2. Resolve `[m:xxxx]` handles to concrete memory ids (review:\n // \"memory handles not resolved\"). The planner resolveTargetMemories\n // expects memory ids, not raw handle tokens — passing a handle\n // string would throw \"target memory not found\". Unresolvable handles\n // are dropped so the planner falls back to text search (graceful\n // degradation; a correction without a resolved target is still valid).\n let targetIds: string[] | undefined;\n if (correction.handles.length > 0 && deps.resolveHandle && ctx.sessionKey) {\n const resolved: string[] = [];\n for (const handle of correction.handles) {\n const id = deps.resolveHandle(handle, ctx.sessionKey);\n if (id) resolved.push(id);\n }\n if (resolved.length > 0) targetIds = resolved;\n }\n\n // 3. Build + plan\n const request: CorrectionRequest = {\n text: correction.correctedAssertion || correction.sourceExcerpt,\n ...(targetIds ? { targetIds } : {}),\n ...(ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {}),\n ...(ctx.principal ? { principal: ctx.principal } : {}),\n namespace: ctx.namespace,\n };\n\n let plan: CorrectionPlan;\n try {\n plan = await deps.planCorrection(request);\n } catch (err) {\n log.warn(\n `passive-correction: planning failed for \"${correction.targetHint.slice(0, 60)}\": ${err instanceof Error ? err.message : String(err)}`,\n );\n continue;\n }\n plans.push(plan);\n // Record the fingerprint only after a successful plan.\n dedupState.add(fp);\n\n // 3. Dispatch by mode\n if (config.mode === \"queue\") {\n telemetry.queued += 1;\n continue;\n }\n\n // mode === \"auto\"\n const suppression = evaluateAutoApplyGuards(plan, config, ctx.isLiveSession);\n if (suppression) {\n telemetry.suppressedReasons[suppression] =\n (telemetry.suppressedReasons[suppression] ?? 0) + 1;\n telemetry.queued += 1;\n continue;\n }\n\n // Guards passed — auto-apply\n try {\n const outcome = await deps.applyCorrection(plan.planId, {\n confirm: true,\n namespace: ctx.namespace,\n ...(ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {}),\n ...(ctx.principal ? { principal: ctx.principal } : {}),\n });\n // A partial outcome means some actions failed (per-action races or\n // storage failures). Don't count it as auto-applied or notify — queue\n // for human review instead (review: \"partial outcomes as failures\").\n if (outcome.status !== \"applied\") {\n // Partial outcome: some actions applied, some failed. The plan is\n // consumed (status 'partial', not 'pending'), so it won't appear in\n // listPending — do NOT increment queued (review: \"partial not\n // re-queued\"). The audit record captures which actions failed.\n log.warn(\n `passive-correction: plan ${plan.planId} applied partially — some actions failed (see audit record)`,\n );\n continue;\n }\n telemetry.autoApplied += 1;\n\n // Enqueue notification for the next briefing\n try {\n const dir = await deps.storageDir(ctx.namespace);\n await enqueuePassiveCorrectionNotification(dir, {\n planId: plan.planId,\n summary: buildNotificationSummary(plan),\n undoCommand: `auto-applied (plan ${plan.planId})`,\n createdAt: new Date().toISOString(),\n });\n } catch (err) {\n // Notification is best-effort — never block on it.\n log.debug(`passive-correction: notification enqueue failed (non-fatal): ${err}`);\n }\n } catch (err) {\n log.warn(\n `passive-correction: auto-apply failed for plan ${plan.planId}: ${err instanceof Error ? err.message : String(err)} — plan left in queue`,\n );\n telemetry.queued += 1;\n }\n }\n\n return { telemetry, plans };\n}\n\n// ---------------------------------------------------------------------------\n// Notification summary builder\n// ---------------------------------------------------------------------------\n\nfunction buildNotificationSummary(plan: CorrectionPlan): string {\n const action = plan.actions[0];\n if (!action) {\n return plan.request.text.slice(0, 80);\n }\n const target =\n action.kind === \"supersede\"\n ? action.loserId\n : action.kind === \"edit\" || action.kind === \"retract\" || action.kind === \"rescope\"\n ? action.memoryId\n : \"pattern\";\n return `${plan.classification}: ${plan.request.text.slice(0, 60)}${plan.request.text.length > 60 ? \"...\" : \"\"} (${target})`;\n}\n","/**\n * Generic reinforcement-core primitives extracted from `procedure-miner.ts`\n * (issue #687 PR 1/4). Procedure-specific scoring (success rate, step\n * normalization) intentionally stays in the miner — this module only\n * exposes category-agnostic clustering and cluster summarization helpers\n * so future PRs can run reinforcement across non-procedural categories.\n *\n * Pure refactor — no behavior change.\n */\n\n/**\n * Group `items` into clusters keyed by `keyFn(item)`.\n *\n * - Preserves the original input order within each cluster's array.\n * - The returned `Map` insertion order matches first-seen key order, so\n * downstream iteration is deterministic for a given input.\n * - Throws `TypeError` if `keyFn` returns a non-string (e.g. `undefined`,\n * `null`, or a number). Callers must produce a stable string key.\n */\nexport function clusterByKey<T>(items: readonly T[], keyFn: (item: T) => string): Map<string, T[]> {\n const clusters = new Map<string, T[]>();\n for (const item of items) {\n const key = keyFn(item);\n if (typeof key !== \"string\") {\n throw new TypeError(\n `clusterByKey: keyFn must return a string, got ${key === null ? \"null\" : typeof key}`,\n );\n }\n const existing = clusters.get(key);\n if (existing) {\n existing.push(item);\n } else {\n clusters.set(key, [item]);\n }\n }\n return clusters;\n}\n\nexport interface ClusterSummary {\n /** Number of items in the cluster. */\n count: number;\n /** Earliest timestamp seen in the cluster (string min via `localeCompare`). */\n firstSeen: string;\n /** Latest timestamp seen in the cluster (string max via `localeCompare`). */\n lastSeen: string;\n}\n\n/**\n * Summarize a cluster by counting items and tracking earliest/latest\n * timestamps. Timestamp comparison uses `String#localeCompare`, which is\n * correct for ISO-8601 strings (lexicographic order matches chronological\n * order).\n *\n * - Throws `RangeError` on empty clusters — `firstSeen`/`lastSeen` are not\n * meaningful without at least one item.\n * - When all timestamps are equal, `firstSeen === lastSeen`.\n */\nexport function summarizeCluster<T>(\n cluster: readonly T[],\n extractTimestamp: (item: T) => string,\n): ClusterSummary {\n if (cluster.length === 0) {\n throw new RangeError(\"summarizeCluster: cluster must contain at least one item\");\n }\n let firstSeen = extractTimestamp(cluster[0]);\n let lastSeen = firstSeen;\n for (let i = 1; i < cluster.length; i += 1) {\n const ts = extractTimestamp(cluster[i]);\n if (ts.localeCompare(firstSeen) < 0) firstSeen = ts;\n if (ts.localeCompare(lastSeen) > 0) lastSeen = ts;\n }\n return { count: cluster.length, firstSeen, lastSeen };\n}\n"],"mappings":"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","names":["path","mkdir","writeFile","seedIds","neighbors","errMsg","path","mkdir","writeFile"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/explicit-capture.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { Orchestrator } from \"./orchestrator.js\";\nimport { isSafeRouteNamespace } from \"./routing/engine.js\";\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\nimport { ContentHashIndex } from \"./storage.js\";\nimport type { CaptureMode, MemoryCategory, MemoryLifecycleEvent, PluginConfig } from \"./types.js\";\n\nexport type ExplicitCaptureInput = {\n content: string;\n category?: string;\n confidence?: number;\n namespace?: string;\n tags?: string[];\n entityRef?: string;\n ttl?: string;\n sourceReason?: string;\n};\n\nexport type ValidExplicitCapture = {\n content: string;\n category: MemoryCategory;\n confidence: number;\n namespace?: string;\n tags: string[];\n entityRef?: string;\n expiresAt?: string;\n sourceReason?: string;\n /**\n * When true, `namespace` was already resolved AND authorized by the caller\n * (the access service's `resolveCodingScopedWriteNamespace`, which auth-checks\n * the base and derives a session-owned `project-*` overlay). The persist /\n * queue layer then routes to it directly instead of re-validating against the\n * static policy allow-list — which would otherwise reject legitimately-derived\n * dynamic project namespaces (#1434). Callers that do NOT pre-authorize the\n * namespace must leave this unset so the allow-list guard still applies.\n */\n namespacePreResolved?: boolean;\n};\n\nexport type ExplicitCaptureSource = \"memory_store\" | \"memory_capture\" | \"suggestion_submit\" | \"inline\";\ntype ExplicitCaptureValidationMode = \"legacy_tool\" | \"strict_explicit\";\n\n// Bounded body {0,100000} instead of an unbounded lazy *? so scanning for the\n// closing tag cannot backtrack polynomially on unterminated <memory_note>\n// markup in hostile turn text (CodeQL js/polynomial-redos). 100 000 chars far\n// exceeds any real inline note, so matching is behavior-preserving; the outer\n// \\s* groups were also dropped (body absorbs whitespace; captures are trimmed).\nconst INLINE_NOTE_RE = /<memory_note>([\\s\\S]{0,100000}?)<\\/memory_note>/gi;\nconst INLINE_NOTE_MARKUP_RE = /<memory_note>[\\s\\S]{0,100000}?<\\/memory_note>/i;\nconst INLINE_ALLOWED_CATEGORIES = new Set<MemoryCategory>([\n \"fact\",\n \"preference\",\n \"correction\",\n \"entity\",\n \"decision\",\n \"relationship\",\n \"principle\",\n \"commitment\",\n \"moment\",\n \"skill\",\n \"rule\",\n \"procedure\",\n \"reasoning_trace\",\n]);\n\nconst SECRET_PATTERNS: RegExp[] = [\n /\\bsk-[A-Za-z0-9]{16,}\\b/,\n /\\bAKIA[0-9A-Z]{16}\\b/,\n /\\bBearer\\s+[A-Za-z0-9._-]{16,}\\b/i,\n /\\b(?:api[_-]?key|secret|token|password|passwd)\\s*[:=]\\s*[^\\s]{8,}\\b/i,\n /\\b(?:authorization)\\s*:\\s*[^\\s]{8,}\\b/i,\n];\nconst SECRET_REDACTION_PATTERNS: Array<{ pattern: RegExp; replacement: string }> = [\n { pattern: /\\bsk-[A-Za-z0-9]{16,}\\b/g, replacement: \"[redacted openai key]\" },\n { pattern: /\\bAKIA[0-9A-Z]{16}\\b/g, replacement: \"[redacted aws key]\" },\n { pattern: /\\bBearer\\s+[A-Za-z0-9._-]{16,}\\b/gi, replacement: \"Bearer [redacted token]\" },\n {\n pattern: /\\b(?:api[_-]?key|secret|token|password|passwd)\\s*[:=]\\s*[^\\s]{8,}\\b/gi,\n replacement: \"[redacted credential]\",\n },\n {\n pattern: /\\b(?:authorization)\\s*:\\s*[^\\s]{8,}\\b/gi,\n replacement: \"authorization: [redacted credential]\",\n },\n];\nconst EXPLICIT_CAPTURE_REVIEW_TAGS = [\"explicit-capture\", \"queued-review\"];\n\nfunction explicitCaptureActor(source: ExplicitCaptureSource): string {\n switch (source) {\n case \"inline\":\n return \"inline.memory_note\";\n case \"memory_store\":\n return \"tool.memory_store\";\n case \"suggestion_submit\":\n return \"tool.suggestion_submit\";\n default:\n return \"tool.memory_capture\";\n }\n}\n\nfunction asTrimmed(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed && trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction normalizeCaptureContent(value: string): string {\n return value\n .toLowerCase()\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\nfunction redactSecrets(value: string): string {\n let redacted = value;\n for (const { pattern, replacement } of SECRET_REDACTION_PATTERNS) {\n redacted = redacted.replace(pattern, replacement);\n }\n return redacted;\n}\n\nfunction containsSecretLikeValue(value: string): boolean {\n return SECRET_PATTERNS.some((pattern) => pattern.test(value));\n}\n\nfunction assertNoSecretLikeMetadata(field: string, value: string | undefined): void {\n const trimmed = asTrimmed(value);\n if (trimmed && containsSecretLikeValue(trimmed)) {\n throw new Error(`${field} appears to contain a secret or credential`);\n }\n}\n\nfunction assertNoSecretLikeMetadataList(field: string, values: string[] | undefined): void {\n for (const value of values ?? []) {\n assertNoSecretLikeMetadata(field, value);\n }\n}\n\nfunction sanitizeReviewText(value: string | undefined, fallback: string): string {\n const redacted = redactSecrets(asTrimmed(value) ?? fallback);\n const sanitized = sanitizeMemoryContent(redacted);\n const safe = sanitized.text.trim();\n return safe.length > 0 ? safe : fallback;\n}\n\nfunction sanitizeReviewMetadata(value: string | undefined): string | undefined {\n const trimmed = asTrimmed(value);\n if (!trimmed) return undefined;\n return sanitizeReviewText(trimmed, \"[redacted]\");\n}\n\nfunction sanitizeReviewTags(tags: string[] | undefined): string[] {\n return Array.from(new Set((tags ?? [])\n .map((tag) => sanitizeReviewMetadata(tag))\n .filter((tag): tag is string => typeof tag === \"string\" && tag.length > 0)));\n}\n\nfunction normalizeExplicitCaptureError(error: unknown): string {\n if (error instanceof Error && error.message.trim().length > 0) return error.message.trim();\n const rendered = String(error).trim();\n return rendered.length > 0 ? rendered : \"explicit capture failed\";\n}\n\nfunction resolveExplicitCaptureReviewNamespace(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n): string | undefined {\n const normalized = asTrimmed(namespace);\n if (!normalized) return undefined;\n return resolveExplicitCaptureNamespace(orchestrator, normalized);\n}\n\nfunction resolveExplicitCaptureNamespace(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n): string | undefined {\n const normalized = asTrimmed(namespace);\n if (!normalized) return undefined;\n if (!orchestrator.config.namespacesEnabled) {\n if (normalized !== orchestrator.config.defaultNamespace) {\n throw new Error(`unsupported namespace: ${normalized}`);\n }\n return normalized;\n }\n const allowed = new Set([\n orchestrator.config.defaultNamespace,\n orchestrator.config.sharedNamespace,\n ...orchestrator.config.namespacePolicies.map((policy) => policy.name),\n ].map((value) => value.trim()).filter(Boolean));\n if (!allowed.has(normalized)) {\n throw new Error(`unsupported namespace: ${normalized}`);\n }\n return normalized;\n}\n\nfunction parseExplicitCaptureTtl(ttl: string | undefined): string | undefined {\n const raw = asTrimmed(ttl);\n if (!raw) return undefined;\n\n const absoluteMs = Date.parse(raw);\n if (Number.isFinite(absoluteMs)) {\n return new Date(absoluteMs).toISOString();\n }\n\n const relative = raw.match(/^(\\d+)\\s*([mhdw])$/i);\n if (!relative) {\n throw new Error(\"ttl must be an ISO-8601 timestamp or relative duration like 30m, 12h, 7d, or 2w\");\n }\n\n const amount = Number.parseInt(relative[1] ?? \"\", 10);\n const unit = (relative[2] ?? \"\").toLowerCase();\n if (!Number.isFinite(amount) || amount <= 0) {\n throw new Error(\"ttl duration must be a positive integer\");\n }\n\n const multiplier =\n unit === \"m\" ? 60_000\n : unit === \"h\" ? 60 * 60_000\n : unit === \"d\" ? 24 * 60 * 60_000\n : 7 * 24 * 60 * 60_000;\n return new Date(Date.now() + amount * multiplier).toISOString();\n}\n\nfunction parseInlineConfidence(value: string): number {\n const trimmed = value.trim();\n if (!/^[+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(?:e[+-]?\\d+)?$/i.test(trimmed)) {\n return Number.NaN;\n }\n const parsed = Number(trimmed);\n return Number.isFinite(parsed) ? parsed : Number.NaN;\n}\n\nfunction parseInlineNote(block: string): ExplicitCaptureInput | null {\n const lines = block.replace(/\\r/g, \"\").split(\"\\n\");\n const note: Partial<ExplicitCaptureInput> = {};\n let idx = 0;\n\n while (idx < lines.length) {\n const rawLine = lines[idx] ?? \"\";\n const line = rawLine.trim();\n idx += 1;\n if (line.length === 0) continue;\n const colonIdx = line.indexOf(\":\");\n if (colonIdx < 0) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n\n if (key === \"content\" && value === \"|\") {\n const contentLines: string[] = [];\n while (idx < lines.length) {\n const next = lines[idx] ?? \"\";\n if (next.startsWith(\" \") || next.startsWith(\"\\t\")) {\n contentLines.push(next.replace(/^( |\\t)/, \"\"));\n idx += 1;\n continue;\n }\n if (next.trim().length === 0) {\n contentLines.push(\"\");\n idx += 1;\n continue;\n }\n break;\n }\n note.content = contentLines.join(\"\\n\").trim();\n continue;\n }\n\n switch (key) {\n case \"content\":\n note.content = value;\n break;\n case \"category\":\n note.category = value;\n break;\n case \"confidence\":\n note.confidence = parseInlineConfidence(value);\n break;\n case \"namespace\":\n note.namespace = value;\n break;\n case \"tags\":\n note.tags = value\n .split(\",\")\n .map((entry) => entry.trim())\n .filter(Boolean);\n break;\n case \"entityRef\":\n note.entityRef = value;\n break;\n case \"ttl\":\n note.ttl = value;\n break;\n case \"sourceReason\":\n note.sourceReason = value;\n break;\n default:\n break;\n }\n }\n\n return asTrimmed(note.content) ? (note as ExplicitCaptureInput) : null;\n}\n\nexport function parseInlineExplicitCaptureNotes(text: string): ExplicitCaptureInput[] {\n const notes: ExplicitCaptureInput[] = [];\n for (const match of text.matchAll(INLINE_NOTE_RE)) {\n const parsed = parseInlineNote(match[1] ?? \"\");\n if (parsed) notes.push(parsed);\n }\n return notes;\n}\n\nexport function hasInlineExplicitCaptureMarkup(text: string): boolean {\n return INLINE_NOTE_MARKUP_RE.test(text);\n}\n\nexport function stripInlineExplicitCaptureNotes(text: string): string {\n return text.replace(INLINE_NOTE_RE, \"\").trim();\n}\n\nexport function validateExplicitCaptureInput(\n input: ExplicitCaptureInput,\n mode: ExplicitCaptureValidationMode = \"strict_explicit\",\n): ValidExplicitCapture {\n const content = asTrimmed(input.content);\n if (!content) throw new Error(\"content is required\");\n if (mode === \"strict_explicit\") {\n if (content.length < 10) throw new Error(\"content must be at least 10 characters\");\n if (content.length > 4000) throw new Error(\"content must be 4000 characters or fewer\");\n }\n if (/<memory_note>/i.test(content) || /<\\/memory_note>/i.test(content)) {\n throw new Error(\"nested memory_note blocks are not allowed\");\n }\n\n const category = (asTrimmed(input.category) ?? \"fact\") as MemoryCategory;\n if (!INLINE_ALLOWED_CATEGORIES.has(category)) {\n throw new Error(`unsupported category: ${input.category ?? category}`);\n }\n\n const sanitized = sanitizeMemoryContent(content);\n if (!sanitized.clean) {\n throw new Error(\"content failed memory sanitization\");\n }\n for (const pattern of SECRET_PATTERNS) {\n if (pattern.test(content)) {\n throw new Error(\"content appears to contain a secret or credential\");\n }\n }\n assertNoSecretLikeMetadata(\"sourceReason\", input.sourceReason);\n assertNoSecretLikeMetadata(\"entityRef\", input.entityRef);\n assertNoSecretLikeMetadata(\"ttl\", input.ttl);\n assertNoSecretLikeMetadataList(\"tags\", input.tags);\n\n if (input.confidence !== undefined && !Number.isFinite(input.confidence)) {\n throw new Error(\"confidence must be a finite number\");\n }\n const confidence = input.confidence === undefined ? 0.95 : Number(input.confidence);\n if (confidence < 0 || confidence > 1) {\n throw new Error(\"confidence must be between 0 and 1\");\n }\n const requestedNamespace = asTrimmed(input.namespace);\n if (requestedNamespace && !isSafeRouteNamespace(requestedNamespace)) {\n throw new Error(`unsafe namespace: ${requestedNamespace}`);\n }\n const expiresAt = parseExplicitCaptureTtl(input.ttl);\n\n return {\n content,\n category,\n confidence,\n namespace: asTrimmed(input.namespace),\n tags: Array.from(new Set((input.tags ?? []).map((tag) => tag.trim()).filter(Boolean))),\n entityRef: asTrimmed(input.entityRef),\n expiresAt,\n sourceReason: asTrimmed(input.sourceReason),\n };\n}\n\nasync function findDuplicateExplicitCapture(\n orchestrator: Orchestrator,\n resolvedNamespace: string | undefined,\n candidate: ValidExplicitCapture,\n): Promise<string | null> {\n const storage = await orchestrator.getStorage(resolvedNamespace);\n if (\n candidate.category === \"fact\"\n && typeof (storage as { hasFactContentHash?: (content: string) => Promise<boolean> }).hasFactContentHash === \"function\"\n ) {\n try {\n const hasHash = await (storage as { hasFactContentHash: (content: string) => Promise<boolean> }).hasFactContentHash(\n candidate.content,\n );\n if (!hasHash) {\n const authoritative =\n typeof (storage as { isFactContentHashAuthoritative?: () => Promise<boolean> | boolean }).isFactContentHashAuthoritative\n === \"function\"\n ? await (storage as { isFactContentHashAuthoritative: () => Promise<boolean> | boolean })\n .isFactContentHashAuthoritative()\n : false;\n if (authoritative) return null;\n }\n } catch (err) {\n // Fail open: hash index is only an optimization, so fall back to the full corpus scan.\n void err;\n }\n }\n const existing = await storage.readAllMemories();\n const normalizedCandidate = normalizeCaptureContent(candidate.content);\n const match = existing.find((memory) => {\n const status = memory.frontmatter.status ?? \"active\";\n if (status !== \"active\") return false;\n if (memory.frontmatter.category !== candidate.category) return false;\n return normalizeCaptureContent(memory.content) === normalizedCandidate;\n });\n return match?.frontmatter.id ?? null;\n}\n\nexport async function persistExplicitCapture(\n orchestrator: Orchestrator,\n candidate: ValidExplicitCapture,\n source: ExplicitCaptureSource,\n): Promise<{ id: string; duplicateOf?: string }> {\n const resolvedNamespace = candidate.namespacePreResolved\n ? asTrimmed(candidate.namespace)\n : resolveExplicitCaptureNamespace(orchestrator, candidate.namespace);\n const duplicateOf = await findDuplicateExplicitCapture(orchestrator, resolvedNamespace, candidate);\n if (duplicateOf) {\n return { id: duplicateOf, duplicateOf };\n }\n\n const storage = await orchestrator.getStorage(resolvedNamespace);\n const id = await storage.writeMemory(candidate.category, candidate.content, {\n confidence: candidate.confidence,\n tags: candidate.tags,\n entityRef: candidate.entityRef,\n expiresAt: candidate.expiresAt,\n source: source === \"inline\" ? \"explicit-inline\" : \"explicit\",\n });\n // #1522: catalog touch handled at the storage chokepoint — the StorageManager's\n // post-write hook records the namespace touch automatically.\n\n const created = new Date().toISOString();\n const event: MemoryLifecycleEvent = {\n eventId: `mle-${randomUUID()}`,\n memoryId: id,\n eventType: \"explicit_capture_accepted\",\n timestamp: created,\n actor: explicitCaptureActor(source),\n reasonCode: candidate.sourceReason,\n ruleVersion: \"explicit-capture.v1\",\n };\n await storage.appendMemoryLifecycleEvents([event]);\n\n return { id };\n}\n\nfunction buildExplicitCaptureReviewContent(input: ExplicitCaptureInput, reason: string): string {\n const requestedContent = asTrimmed(input.content);\n const safeContent = sanitizeReviewText(requestedContent, \"[empty explicit capture]\");\n const safeCategory = sanitizeReviewMetadata(input.category);\n const safeNamespace = sanitizeReviewMetadata(input.namespace);\n const safeEntityRef = sanitizeReviewMetadata(input.entityRef);\n const safeTtl = sanitizeReviewMetadata(input.ttl);\n const safeSourceReason = sanitizeReviewMetadata(input.sourceReason);\n const safeTags = sanitizeReviewTags(input.tags);\n const lines = [\n \"Explicit capture queued for review.\",\n \"\",\n `Reason: ${reason}`,\n \"\",\n \"Submitted content:\",\n safeContent,\n ];\n const metadata = [\n safeCategory ? `Requested category: ${safeCategory}` : undefined,\n safeNamespace ? `Requested namespace: ${safeNamespace}` : undefined,\n safeEntityRef ? `Requested entityRef: ${safeEntityRef}` : undefined,\n safeTtl ? `Requested ttl: ${safeTtl}` : undefined,\n safeSourceReason ? `Requested sourceReason: ${safeSourceReason}` : undefined,\n safeTags.length > 0 ? `Requested tags: ${safeTags.join(\", \")}` : undefined,\n ].filter((entry): entry is string => typeof entry === \"string\" && entry.length > 0);\n if (metadata.length > 0) {\n lines.push(\"\", ...metadata);\n }\n return lines.join(\"\\n\");\n}\n\nasync function findQueuedExplicitCaptureDuplicate(\n orchestrator: Orchestrator,\n namespace: string | undefined,\n content: string,\n): Promise<string | null> {\n const storage = await orchestrator.getStorage(namespace);\n const existing = await storage.readAllMemories();\n const normalized = normalizeCaptureContent(content);\n const match = existing.find((memory) => {\n const status = memory.frontmatter.status ?? \"active\";\n if (status !== \"pending_review\") return false;\n if (!(memory.frontmatter.tags ?? []).includes(\"queued-review\")) return false;\n return normalizeCaptureContent(memory.content) === normalized;\n });\n return match?.frontmatter.id ?? null;\n}\n\nexport async function queueExplicitCaptureForReview(\n orchestrator: Orchestrator,\n input: ExplicitCaptureInput,\n source: ExplicitCaptureSource,\n error: unknown,\n): Promise<{ id: string; duplicateOf?: string }> {\n const reason = sanitizeReviewText(normalizeExplicitCaptureError(error), \"explicit capture failed\");\n const requestedNamespace = asTrimmed(input.namespace);\n // A caller-pre-authorized namespace (e.g. a session-owned project overlay\n // from the access service) routes directly; otherwise apply the static\n // policy allow-list guard (#1434).\n const queueNamespace = (input as { namespacePreResolved?: boolean }).namespacePreResolved\n ? requestedNamespace\n : resolveExplicitCaptureReviewNamespace(orchestrator, requestedNamespace);\n const content = buildExplicitCaptureReviewContent(input, reason);\n const duplicateOf = await findQueuedExplicitCaptureDuplicate(orchestrator, queueNamespace, content);\n if (duplicateOf) {\n return { id: duplicateOf, duplicateOf };\n }\n\n const requestedCategory = asTrimmed(input.category);\n const reviewCategory = requestedCategory && INLINE_ALLOWED_CATEGORIES.has(requestedCategory as MemoryCategory)\n ? requestedCategory as MemoryCategory\n : \"fact\";\n const requestedTags = sanitizeReviewTags(input.tags);\n const storage = await orchestrator.getStorage(queueNamespace);\n const id = await storage.writeMemory(reviewCategory, content, {\n confidence: 0.2,\n tags: Array.from(new Set([...EXPLICIT_CAPTURE_REVIEW_TAGS, ...requestedTags])),\n entityRef: sanitizeReviewMetadata(input.entityRef),\n source: source === \"inline\" ? \"explicit-inline-review\" : \"explicit-review\",\n });\n try {\n const created = await storage.getMemoryById(id);\n if (created) {\n await storage.writeMemoryFrontmatter(created, {\n status: \"pending_review\",\n updated: new Date().toISOString(),\n }, {\n actor: explicitCaptureActor(source),\n reasonCode: reason,\n ruleVersion: \"explicit-capture.v1\",\n });\n }\n } finally {\n // Record the catalog write touch (issue #1499, round 5/6 codex P2; NIhUg).\n // A queued review capture writes memory to the namespace's root (the DEFAULT\n // root when undefined), so its `lastWriteAt` must reflect the write once\n // `writeMemory` returns an id. If the later pending-review frontmatter update\n // fails, the memory file is still durable and must not disappear from\n // writtenSince/maintenance scheduling. Guarded optional hook (rule #33).\n // #1522: catalog touch handled at the storage chokepoint.\n }\n const event: MemoryLifecycleEvent = {\n eventId: `mle-${randomUUID()}`,\n memoryId: id,\n eventType: \"explicit_capture_queued\",\n timestamp: new Date().toISOString(),\n actor: explicitCaptureActor(source),\n reasonCode: reason,\n ruleVersion: \"explicit-capture.v1\",\n };\n await storage.appendMemoryLifecycleEvents([event]);\n return { id };\n}\n\nexport function shouldSkipImplicitExtraction(cfg: Pick<PluginConfig, \"captureMode\">): boolean {\n return cfg.captureMode === \"explicit\";\n}\n\nexport function shouldProcessInlineExplicitCapture(cfg: Pick<PluginConfig, \"captureMode\">): boolean {\n return cfg.captureMode !== \"implicit\";\n}\n"],"mappings":"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","names":[]}