@remnic/core 9.65.0 → 9.65.2

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 (589) hide show
  1. package/dist/access-admin-ops-surface.d.ts +11 -11
  2. package/dist/access-admin-ops-surface.js +45 -43
  3. package/dist/access-authorization-probe.d.ts +12 -13
  4. package/dist/access-authorization-probe.js +46 -44
  5. package/dist/access-boundary.d.ts +12 -156
  6. package/dist/access-boundary.js +45 -43
  7. package/dist/access-cli.js +120 -116
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-coding-context-resolution.d.ts +1 -1
  10. package/dist/access-extraction-force-flush.d.ts +11 -11
  11. package/dist/access-extraction-force-flush.js +45 -43
  12. package/dist/access-health-types.d.ts +1 -1
  13. package/dist/access-http-lcm-compaction.d.ts +11 -11
  14. package/dist/access-http-lifecycle-flush.d.ts +12 -13
  15. package/dist/access-http-offline-stream.d.ts +11 -11
  16. package/dist/access-http-query.d.ts +2 -2
  17. package/dist/access-http-query.js +47 -45
  18. package/dist/access-http.d.ts +12 -12
  19. package/dist/access-http.js +65 -63
  20. package/dist/access-identity-continuity-surface.d.ts +9 -9
  21. package/dist/access-identity-continuity-surface.js +45 -43
  22. package/dist/access-lcm-surface.d.ts +11 -11
  23. package/dist/access-lcm-surface.js +45 -43
  24. package/dist/access-mcp-admin-tools.js +1 -1
  25. package/dist/access-mcp-output-schemas.js +1 -1
  26. package/dist/access-mcp.d.ts +11 -11
  27. package/dist/access-mcp.js +58 -54
  28. package/dist/access-memory-search-fanout.d.ts +2 -2
  29. package/dist/{access-namespace-preflight-AqlR0w02.d.ts → access-namespace-preflight-Dhvcl-T0.d.ts} +1 -1
  30. package/dist/access-namespace-preflight.d.ts +3 -3
  31. package/dist/access-namespace-preflight.js +45 -43
  32. package/dist/access-observe-write-surface.d.ts +11 -11
  33. package/dist/access-observe-write-surface.js +45 -43
  34. package/dist/access-offline-manifest.d.ts +9 -9
  35. package/dist/access-offline-manifest.js +5 -5
  36. package/dist/access-operations-batch.js +49 -47
  37. package/dist/access-operations.d.ts +18 -19
  38. package/dist/access-operations.js +52 -50
  39. package/dist/access-recall-concurrency.d.ts +11 -11
  40. package/dist/access-recall-concurrency.js +45 -43
  41. package/dist/access-recall-response.d.ts +11 -11
  42. package/dist/access-recall-response.js +45 -43
  43. package/dist/access-recall-surface.d.ts +11 -11
  44. package/dist/access-recall-surface.js +45 -43
  45. package/dist/access-schema.d.ts +118 -118
  46. package/dist/access-schema.js +3 -3
  47. package/dist/{access-service-BHmtl9BA.d.ts → access-service-Bke1alZO.d.ts} +484 -80
  48. package/dist/access-service-helpers.d.ts +11 -11
  49. package/dist/access-service.d.ts +11 -11
  50. package/dist/access-service.js +45 -43
  51. package/dist/access-surface-catalog.d.ts +12 -13
  52. package/dist/access-surface-catalog.js +49 -45
  53. package/dist/access-surface-catalog.js.map +1 -1
  54. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  55. package/dist/action-confidence.d.ts +1 -1
  56. package/dist/active-memory-bridge.d.ts +1 -1
  57. package/dist/active-recall.d.ts +1 -1
  58. package/dist/active-recall.js +6 -1
  59. package/dist/active-recall.js.map +1 -1
  60. package/dist/adapters/index.js +4 -4
  61. package/dist/adapters/registry.js +2 -2
  62. package/dist/ambient-provenance.d.ts +1 -1
  63. package/dist/artifact-search.d.ts +1 -1
  64. package/dist/{auto-sync-5L7EUZ27.js → auto-sync-H64ZCNIR.js} +13 -5
  65. package/dist/{auto-sync-5L7EUZ27.js.map → auto-sync-H64ZCNIR.js.map} +1 -1
  66. package/dist/behavior-learner.d.ts +1 -1
  67. package/dist/behavior-signals.d.ts +1 -1
  68. package/dist/bootstrap.d.ts +9 -9
  69. package/dist/briefing-window.d.ts +2 -2
  70. package/dist/briefing.d.ts +2 -2
  71. package/dist/briefing.js +19 -17
  72. package/dist/buffer-surprise-report.d.ts +1 -1
  73. package/dist/buffer-turn-helpers.d.ts +1 -1
  74. package/dist/buffer.d.ts +2 -2
  75. package/dist/buffer.js +4 -4
  76. package/dist/bulk-import/index.d.ts +3 -3
  77. package/dist/calibration.d.ts +1 -1
  78. package/dist/calibration.js +1 -1
  79. package/dist/capabilities.d.ts +1 -1
  80. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  81. package/dist/{catalog-gBoyN-IW.d.ts → catalog-DV6qnbr7.d.ts} +1 -1
  82. package/dist/causal-behavior.d.ts +1 -1
  83. package/dist/causal-behavior.js +2 -2
  84. package/dist/causal-chain.js +2 -2
  85. package/dist/causal-consolidation.d.ts +1 -1
  86. package/dist/causal-consolidation.js +22 -20
  87. package/dist/causal-consolidation.js.map +1 -1
  88. package/dist/causal-retrieval.js +2 -2
  89. package/dist/causal-trajectory-graph.d.ts +1 -1
  90. package/dist/causal-trajectory-graph.js +2 -2
  91. package/dist/causal-trajectory.js +1 -1
  92. package/dist/{chunk-A6LBDIFS.js → chunk-2E36UXVW.js} +2 -2
  93. package/dist/{chunk-RRJUMSFX.js → chunk-2XDWWPTN.js} +3 -3
  94. package/dist/{chunk-QCNB4BRE.js → chunk-2YI72KM3.js} +3 -3
  95. package/dist/{chunk-3YTTAGPB.js → chunk-3DVBKTSO.js} +2 -2
  96. package/dist/{chunk-IFK3PVM7.js → chunk-3I7ASZN3.js} +2 -2
  97. package/dist/chunk-3WU7XOFN.js +102 -0
  98. package/dist/chunk-3WU7XOFN.js.map +1 -0
  99. package/dist/{chunk-EIR5VLIH.js → chunk-4K7IW3F7.js} +2 -2
  100. package/dist/chunk-4K7IW3F7.js.map +1 -0
  101. package/dist/{chunk-HBKFYXBA.js → chunk-4KYOLI6M.js} +15 -15
  102. package/dist/chunk-573TEZCD.js +88 -0
  103. package/dist/chunk-573TEZCD.js.map +1 -0
  104. package/dist/{chunk-RNKNL5GQ.js → chunk-5NM4OH4P.js} +3 -3
  105. package/dist/{chunk-CESQ4CMC.js → chunk-5YQ63T4B.js} +2 -2
  106. package/dist/{chunk-PMVPCZJZ.js → chunk-6433HV72.js} +2 -2
  107. package/dist/{chunk-4NZHHGVL.js → chunk-7BDZTALN.js} +4 -1
  108. package/dist/chunk-7BDZTALN.js.map +1 -0
  109. package/dist/{chunk-NS5ETDYD.js → chunk-7BEPVIH3.js} +3 -3
  110. package/dist/{chunk-JG22O53B.js → chunk-7CBKAQIG.js} +2 -1
  111. package/dist/chunk-7CBKAQIG.js.map +1 -0
  112. package/dist/{chunk-SHQFYZTD.js → chunk-7YQ4IYS2.js} +2 -2
  113. package/dist/chunk-AAXJNINV.js +55 -0
  114. package/dist/chunk-AAXJNINV.js.map +1 -0
  115. package/dist/{chunk-YMOPYG3K.js → chunk-BIJAWZYW.js} +6 -6
  116. package/dist/{chunk-YQ3CBLL4.js → chunk-BWLRUMOG.js} +78 -8
  117. package/dist/chunk-BWLRUMOG.js.map +1 -0
  118. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  119. package/dist/{chunk-VYEPACWY.js → chunk-C24UZSFW.js} +2 -2
  120. package/dist/{chunk-ZPN7W3OP.js → chunk-CDUUDBWJ.js} +3 -3
  121. package/dist/{chunk-K7JMKLKV.js → chunk-CT56C22C.js} +4 -4
  122. package/dist/{chunk-KWIGDKM2.js → chunk-D2YNNDML.js} +2 -2
  123. package/dist/{chunk-ZFBZ4QTS.js → chunk-DJZWNKFO.js} +10 -10
  124. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  125. package/dist/{chunk-VNIETTMR.js → chunk-DZUJ46DO.js} +2 -2
  126. package/dist/{chunk-T6QMNVMO.js → chunk-EILZG5VC.js} +2 -2
  127. package/dist/{chunk-652S5A5D.js → chunk-EUYWQ7TS.js} +2 -2
  128. package/dist/{chunk-YIZRTHHF.js → chunk-GDFVPUJ5.js} +2 -2
  129. package/dist/{chunk-ML3U4KPR.js → chunk-GIC6BASP.js} +2 -2
  130. package/dist/{chunk-7PWWGYGO.js → chunk-GNCCUR6K.js} +2 -2
  131. package/dist/{chunk-Y5UT73VZ.js → chunk-IID2CMUU.js} +2 -2
  132. package/dist/{chunk-MB6GLPRY.js → chunk-IVKIODHO.js} +4 -4
  133. package/dist/{chunk-ZAI5R6DW.js → chunk-J275IYMG.js} +26 -17
  134. package/dist/chunk-J275IYMG.js.map +1 -0
  135. package/dist/{chunk-UYCIS6V5.js → chunk-JCWY73FK.js} +2 -2
  136. package/dist/{chunk-URS5GSM7.js → chunk-JXN77SGO.js} +1 -1
  137. package/dist/chunk-JXN77SGO.js.map +1 -0
  138. package/dist/{chunk-WHA6ISFX.js → chunk-JYYBA7TF.js} +2 -2
  139. package/dist/{chunk-T42L3S6A.js → chunk-LBWQ65SX.js} +4 -4
  140. package/dist/{chunk-MSTNSVXI.js → chunk-LDBFXD4F.js} +2 -1
  141. package/dist/chunk-LDBFXD4F.js.map +1 -0
  142. package/dist/{chunk-JXMXTV6C.js → chunk-LGO6A7GJ.js} +56 -56
  143. package/dist/{chunk-XBRGJJK7.js → chunk-LUNJ3WFO.js} +10 -8
  144. package/dist/chunk-LUNJ3WFO.js.map +1 -0
  145. package/dist/{chunk-H6B6GPVH.js → chunk-LZH5FR2W.js} +2 -2
  146. package/dist/{chunk-5HERQ5FX.js → chunk-M4AHBM72.js} +10 -10
  147. package/dist/{chunk-GOGHZVY3.js → chunk-MN4KB2A4.js} +3 -3
  148. package/dist/{chunk-OQIRBGUU.js → chunk-N37X5RU7.js} +2 -2
  149. package/dist/{chunk-E6EQTCOQ.js → chunk-NKKD4ZAU.js} +2 -2
  150. package/dist/{chunk-VANZKHTN.js → chunk-NNBZS3DY.js} +2 -2
  151. package/dist/{chunk-IWUN4RZL.js → chunk-NTWN6HB2.js} +5 -5
  152. package/dist/{chunk-2PSX5BJU.js → chunk-NZPFCP5A.js} +2 -2
  153. package/dist/{chunk-U56TGYVS.js → chunk-OCZIYAE5.js} +4 -4
  154. package/dist/{chunk-I2HTKOOP.js → chunk-ODZG724P.js} +2 -2
  155. package/dist/{chunk-LTBKKSCX.js → chunk-OLBZ2WGG.js} +2 -2
  156. package/dist/{chunk-GQ5OJVTM.js → chunk-OTHZWLUD.js} +2 -2
  157. package/dist/{chunk-PD66CVSD.js → chunk-OUKBMQ2O.js} +2 -2
  158. package/dist/{chunk-4E6IJCLC.js → chunk-PE255F4T.js} +2 -2
  159. package/dist/{chunk-GPFZFCRN.js → chunk-PP7R754B.js} +1 -1
  160. package/dist/{chunk-PHX3ET3C.js → chunk-QOS5LBZN.js} +2 -2
  161. package/dist/{chunk-G72IPMR7.js → chunk-R4OCGPSH.js} +2 -2
  162. package/dist/{chunk-VUP47UJI.js → chunk-R7JAM2XF.js} +3 -3
  163. package/dist/{chunk-LCU5R6TQ.js → chunk-RAIUTAZZ.js} +22 -3
  164. package/dist/chunk-RAIUTAZZ.js.map +1 -0
  165. package/dist/chunk-RIAM7DND.js +167 -0
  166. package/dist/chunk-RIAM7DND.js.map +1 -0
  167. package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
  168. package/dist/{chunk-P4CQCL27.js → chunk-S2DPMJXH.js} +2 -2
  169. package/dist/{chunk-YHSNAGN3.js → chunk-SB7D4BT7.js} +548 -126
  170. package/dist/chunk-SB7D4BT7.js.map +1 -0
  171. package/dist/{chunk-VRYEXPRX.js → chunk-SBDCZ2AX.js} +1 -1
  172. package/dist/chunk-SBDCZ2AX.js.map +1 -0
  173. package/dist/{chunk-OXL5QKTV.js → chunk-SIHSCCUQ.js} +1 -1
  174. package/dist/{chunk-KLPVXLQJ.js → chunk-SPUJNJJC.js} +2 -2
  175. package/dist/{chunk-CCP6LXQJ.js → chunk-SQI57UCJ.js} +2 -2
  176. package/dist/{chunk-UIYYS2YI.js → chunk-SVSRPG6M.js} +2 -2
  177. package/dist/{chunk-56BSXSHC.js → chunk-TBOJ76ER.js} +14 -1
  178. package/dist/{chunk-56BSXSHC.js.map → chunk-TBOJ76ER.js.map} +1 -1
  179. package/dist/{chunk-RQYV6M2T.js → chunk-TF77C7SV.js} +14 -7
  180. package/dist/chunk-TF77C7SV.js.map +1 -0
  181. package/dist/{chunk-RNORDDD6.js → chunk-THG4GYIE.js} +2 -2
  182. package/dist/{chunk-CUIAHZPZ.js → chunk-TR7DGXGI.js} +2 -2
  183. package/dist/{chunk-GEULB2VI.js → chunk-TZNQUNKL.js} +7 -1
  184. package/dist/chunk-TZNQUNKL.js.map +1 -0
  185. package/dist/{chunk-PDKBKBC2.js → chunk-UIN2BWDD.js} +2 -2
  186. package/dist/{chunk-4GD7YV4Y.js → chunk-UXO5IMBK.js} +3 -3
  187. package/dist/{chunk-UPIKAT5A.js → chunk-V3MXUL3D.js} +173 -77
  188. package/dist/chunk-V3MXUL3D.js.map +1 -0
  189. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  190. package/dist/{chunk-MUJ4QFUQ.js → chunk-W4BMEGQA.js} +4 -4
  191. package/dist/{chunk-5HK3CJAR.js → chunk-W675UJCZ.js} +2 -2
  192. package/dist/{chunk-MDVBCPOS.js → chunk-XCTXS7VY.js} +2 -2
  193. package/dist/{chunk-NTERJOFA.js → chunk-XRYZRW54.js} +2 -2
  194. package/dist/{chunk-LA2MSK23.js → chunk-Y7DK7HHJ.js} +2 -2
  195. package/dist/{chunk-34BMUGRA.js → chunk-YB42WZCY.js} +2 -2
  196. package/dist/{chunk-LWVG6U7L.js → chunk-YHCBJULX.js} +2 -2
  197. package/dist/{chunk-HDD4RRIX.js → chunk-YLDXWCZP.js} +21 -6
  198. package/dist/chunk-YLDXWCZP.js.map +1 -0
  199. package/dist/{chunk-VYISFWVX.js → chunk-YQNNHLCG.js} +2 -2
  200. package/dist/{chunk-FFPBTNLC.js → chunk-Z7PBQPJ4.js} +2 -2
  201. package/dist/{chunk-MXJU4GCA.js → chunk-ZO6AXLEH.js} +2 -2
  202. package/dist/{chunk-JNSLW2O4.js → chunk-ZQHI2BZB.js} +2 -2
  203. package/dist/{chunk-A4VJKT2H.js → chunk-ZWXJBFZU.js} +11 -11
  204. package/dist/chunk-ZWXJBFZU.js.map +1 -0
  205. package/dist/{cli-BpwTNHTm.d.ts → cli-cShQ13XG.d.ts} +5 -5
  206. package/dist/cli.d.ts +13 -13
  207. package/dist/cli.js +89 -86
  208. package/dist/coding/pre-action-gate.d.ts +1 -1
  209. package/dist/coding/pre-action-gate.js +2 -2
  210. package/dist/compounding/engine.d.ts +2 -2
  211. package/dist/compounding/engine.js +20 -18
  212. package/dist/compounding/preference-consolidator.d.ts +1 -1
  213. package/dist/compression-optimizer.d.ts +1 -1
  214. package/dist/config.d.ts +1 -1
  215. package/dist/config.js +6 -1
  216. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  217. package/dist/connectors/codex-materialize-runner.js +19 -17
  218. package/dist/connectors/codex-materialize.d.ts +1 -1
  219. package/dist/connectors/index.d.ts +1 -1
  220. package/dist/connectors/index.js +19 -17
  221. package/dist/consolidation-provenance-check.d.ts +2 -2
  222. package/dist/consolidation-undo.d.ts +2 -2
  223. package/dist/contradiction/index.d.ts +2 -2
  224. package/dist/contradiction/index.js +10 -2
  225. package/dist/converge-config.d.ts +1 -1
  226. package/dist/convergence-refresh.d.ts +2 -2
  227. package/dist/convergence-refresh.js +21 -19
  228. package/dist/conversation-index/backend.d.ts +1 -1
  229. package/dist/conversation-index/chunker.d.ts +1 -1
  230. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  231. package/dist/conversation-index/indexer.d.ts +1 -1
  232. package/dist/conversation-index/search.d.ts +1 -1
  233. package/dist/corpus-watermark.d.ts +1 -1
  234. package/dist/corpus-watermark.js +21 -19
  235. package/dist/cross-lingual-recall.d.ts +70 -0
  236. package/dist/cross-lingual-recall.js +14 -0
  237. package/dist/day-summary.d.ts +1 -1
  238. package/dist/delinearize.d.ts +1 -1
  239. package/dist/dependency-propagation-config.d.ts +1 -1
  240. package/dist/{dependency-propagation-delivery-QYJ1-c2M.d.ts → dependency-propagation-delivery-CsGg-VwS.d.ts} +1 -1
  241. package/dist/direct-answer-wiring.d.ts +1 -1
  242. package/dist/direct-answer.d.ts +1 -1
  243. package/dist/embedding-fallback.d.ts +1 -1
  244. package/dist/enrichment/index.d.ts +1 -1
  245. package/dist/entity-origin-fields.d.ts +1 -1
  246. package/dist/entity-retrieval.d.ts +2 -2
  247. package/dist/entity-retrieval.js +19 -17
  248. package/dist/entity-schema.d.ts +1 -1
  249. package/dist/episodic-context.d.ts +1 -1
  250. package/dist/explicit-capture.d.ts +9 -9
  251. package/dist/explicit-capture.js +7 -6
  252. package/dist/external-wiki-access.d.ts +12 -13
  253. package/dist/external-wiki-access.js +46 -44
  254. package/dist/external-wiki-collection-registration.d.ts +1 -1
  255. package/dist/external-wiki-collection.d.ts +1 -1
  256. package/dist/external-wiki-mcp-tools.d.ts +11 -11
  257. package/dist/extraction-error-classification.d.ts +1 -1
  258. package/dist/extraction-faithfulness.d.ts +1 -1
  259. package/dist/extraction-judge-telemetry.d.ts +1 -1
  260. package/dist/extraction-judge-training.d.ts +1 -1
  261. package/dist/extraction-judge.d.ts +1 -1
  262. package/dist/extraction-judge.js +2 -2
  263. package/dist/extraction-liveness.d.ts +1 -1
  264. package/dist/extraction-normalization.d.ts +1 -1
  265. package/dist/extraction-normalization.js +2 -2
  266. package/dist/extraction-prompt.d.ts +2 -2
  267. package/dist/extraction-prompt.js +1 -1
  268. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  269. package/dist/extraction-source-grounding.d.ts +1 -1
  270. package/dist/extraction.d.ts +1 -1
  271. package/dist/extraction.js +27 -25
  272. package/dist/fallback-llm.d.ts +1 -1
  273. package/dist/graph-dashboard-diff.d.ts +1 -1
  274. package/dist/graph-dashboard-key.d.ts +1 -1
  275. package/dist/graph-dashboard-parser.d.ts +1 -1
  276. package/dist/{graph-edge-decay-A4SDFMMS.js → graph-edge-decay-FXGELBFA.js} +4 -4
  277. package/dist/graph-edge-reinforcement.d.ts +1 -1
  278. package/dist/graph-path-reconstruction.d.ts +1 -1
  279. package/dist/graph-path-scoring.d.ts +1 -1
  280. package/dist/graph-snapshot.d.ts +1 -1
  281. package/dist/graph-snapshot.js +3 -3
  282. package/dist/graph.d.ts +1 -1
  283. package/dist/graph.js +3 -3
  284. package/dist/harmonic-retrieval.js +1 -1
  285. package/dist/importance.d.ts +1 -1
  286. package/dist/importers/index.d.ts +1 -1
  287. package/dist/in-flight-reads.d.ts +1 -1
  288. package/dist/index.d.ts +718 -701
  289. package/dist/index.js +188 -139
  290. package/dist/intent.d.ts +1 -1
  291. package/dist/lcm/engine.d.ts +1 -1
  292. package/dist/lcm/engine.js +4 -4
  293. package/dist/lcm/index.d.ts +1 -1
  294. package/dist/lcm/index.js +10 -10
  295. package/dist/lcm/tools.d.ts +1 -1
  296. package/dist/lifecycle.d.ts +1 -1
  297. package/dist/live-connectors-runner.d.ts +1 -1
  298. package/dist/local-llm.d.ts +1 -1
  299. package/dist/local-llm.js +2 -2
  300. package/dist/local-model-endpoint.d.ts +1 -1
  301. package/dist/maintenance/memory-governance.d.ts +1 -1
  302. package/dist/maintenance/memory-governance.js +19 -17
  303. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  304. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +19 -17
  305. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  306. package/dist/maintenance/rebuild-memory-projection.js +20 -18
  307. package/dist/{maintenance-BjEr3WKG.d.ts → maintenance-jhMpeGne.d.ts} +3 -3
  308. package/dist/mcp-memory-inspector-app.d.ts +11 -11
  309. package/dist/mcp-read-only-tools.js +1 -1
  310. package/dist/memory-action-policy.d.ts +1 -1
  311. package/dist/memory-cache.d.ts +1 -1
  312. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  313. package/dist/memory-projection-store.d.ts +1 -1
  314. package/dist/memory-provenance.d.ts +1 -1
  315. package/dist/memory-snapshot.d.ts +1 -1
  316. package/dist/memory-subject-cli.d.ts +177 -0
  317. package/dist/memory-subject-cli.js +16 -0
  318. package/dist/memory-subject-cli.js.map +1 -0
  319. package/dist/memory-subject.d.ts +128 -0
  320. package/dist/memory-subject.js +44 -0
  321. package/dist/memory-subject.js.map +1 -0
  322. package/dist/memory-worth-outcomes.d.ts +5 -4
  323. package/dist/memory-worth-outcomes.js +1 -1
  324. package/dist/models-json.d.ts +1 -1
  325. package/dist/namespaces/migrate.d.ts +3 -3
  326. package/dist/namespaces/migrate.js +20 -18
  327. package/dist/namespaces/principal.d.ts +1 -1
  328. package/dist/namespaces/search.d.ts +1 -1
  329. package/dist/namespaces/search.js +9 -9
  330. package/dist/namespaces/storage.d.ts +3 -3
  331. package/dist/namespaces/storage.js +19 -17
  332. package/dist/native-knowledge.d.ts +1 -1
  333. package/dist/offline-sync-impression-drain.d.ts +1 -1
  334. package/dist/operator-doctor-corpus.d.ts +1 -1
  335. package/dist/operator-doctor-corpus.js +22 -20
  336. package/dist/operator-doctor-replica.d.ts +1 -1
  337. package/dist/operator-toolkit.d.ts +3 -3
  338. package/dist/operator-toolkit.js +31 -28
  339. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  340. package/dist/orchestration/maintenance.d.ts +4 -4
  341. package/dist/orchestration/maintenance.js +25 -23
  342. package/dist/{orchestrator-CC4USYcD.d.ts → orchestrator-DyGUC7re.d.ts} +8 -8
  343. package/dist/orchestrator.d.ts +9 -9
  344. package/dist/orchestrator.js +120 -116
  345. package/dist/patterns-cli.d.ts +1 -1
  346. package/dist/{pipeline-DWgAgvJN.d.ts → pipeline-C25Oxtp1.d.ts} +1 -1
  347. package/dist/policy-runtime.d.ts +1 -1
  348. package/dist/proactive-contention.d.ts +1 -1
  349. package/dist/provenance.d.ts +1 -1
  350. package/dist/{public-http-CkQC8VpD.d.ts → public-http-CMe7NQzj.d.ts} +1 -1
  351. package/dist/{qmd-BJGhj4ta.d.ts → qmd-DkDVCbgF.d.ts} +1 -1
  352. package/dist/qmd-preflight.d.ts +2 -2
  353. package/dist/qmd-recall-cache.d.ts +1 -1
  354. package/dist/qmd.d.ts +2 -2
  355. package/dist/qmd.js +2 -2
  356. package/dist/recall-concurrency-config.d.ts +1 -1
  357. package/dist/recall-disclosure-escalation.d.ts +1 -1
  358. package/dist/recall-explain-renderer.d.ts +1 -1
  359. package/dist/recall-explain-renderer.js +3 -3
  360. package/dist/recall-memory-map.d.ts +1 -1
  361. package/dist/recall-planner-llm.d.ts +1 -1
  362. package/dist/recall-state.d.ts +1 -1
  363. package/dist/recall-tag-filter.d.ts +1 -1
  364. package/dist/recall-timings.d.ts +1 -1
  365. package/dist/recall-xray-cli.d.ts +1 -1
  366. package/dist/recall-xray-cli.js +4 -4
  367. package/dist/recall-xray-renderer.d.ts +1 -1
  368. package/dist/recall-xray-renderer.js +3 -3
  369. package/dist/recall-xray.d.ts +1 -1
  370. package/dist/recall-xray.js +2 -2
  371. package/dist/reconcile/cursor.d.ts +1 -1
  372. package/dist/reconcile/manifest.d.ts +1 -1
  373. package/dist/reconcile/manifest.js +3 -3
  374. package/dist/reconcile/plan.d.ts +1 -1
  375. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  376. package/dist/replay/normalizers/claude.d.ts +1 -1
  377. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  378. package/dist/replay/normalizers/shared.d.ts +1 -1
  379. package/dist/replay/runner.d.ts +1 -1
  380. package/dist/replay/types.d.ts +1 -1
  381. package/dist/replica-divergence.d.ts +1 -1
  382. package/dist/replica-peers-config.d.ts +1 -1
  383. package/dist/{resolution-DKMBPXHI.js → resolution-MFY72STR.js} +11 -3
  384. package/dist/resolution-MFY72STR.js.map +1 -0
  385. package/dist/resolve-auth-token.d.ts +1 -1
  386. package/dist/resume-bundles.js +7 -2
  387. package/dist/retrieval-agents.d.ts +2 -2
  388. package/dist/retrieval-tiers.d.ts +1 -1
  389. package/dist/routing/engine.d.ts +1 -1
  390. package/dist/routing/store.d.ts +1 -1
  391. package/dist/salvage-envelope.d.ts +1 -1
  392. package/dist/salvage-envelope.js +10 -2
  393. package/dist/schemas.d.ts +122 -108
  394. package/dist/schemas.js +1 -1
  395. package/dist/{scope-profiles-C4PdBYKc.d.ts → scope-profiles-B9xMoFO-.d.ts} +1 -1
  396. package/dist/search/embed-helper.d.ts +1 -1
  397. package/dist/search/factory.d.ts +1 -1
  398. package/dist/search/factory.js +8 -8
  399. package/dist/search/index.d.ts +1 -1
  400. package/dist/search/index.js +14 -14
  401. package/dist/search/lancedb-backend.d.ts +1 -1
  402. package/dist/search/lancedb-backend.js +2 -2
  403. package/dist/search/meilisearch-backend.d.ts +1 -1
  404. package/dist/search/meilisearch-backend.js +2 -2
  405. package/dist/search/noop-backend.d.ts +1 -1
  406. package/dist/search/orama-backend.d.ts +1 -1
  407. package/dist/search/orama-backend.js +2 -2
  408. package/dist/search/port.d.ts +2 -2
  409. package/dist/search/port.js +1 -1
  410. package/dist/search/remote-backend.d.ts +1 -1
  411. package/dist/search/remote-backend.js +2 -2
  412. package/dist/{semantic-consolidation-5-HOmIhL.d.ts → semantic-consolidation-C4uykW84.d.ts} +1 -1
  413. package/dist/semantic-consolidation.d.ts +2 -2
  414. package/dist/semantic-consolidation.js +20 -18
  415. package/dist/semantic-rule-promotion.js +19 -17
  416. package/dist/semantic-rule-verifier.d.ts +1 -1
  417. package/dist/semantic-rule-verifier.js +19 -17
  418. package/dist/{service-8pDy6w8u.d.ts → service-DCZDZNcV.d.ts} +2 -2
  419. package/dist/session-observer-bands.d.ts +1 -1
  420. package/dist/session-observer-state.d.ts +1 -1
  421. package/dist/shared-context/manager.d.ts +11 -11
  422. package/dist/signal.d.ts +1 -1
  423. package/dist/source-agent-qualifier.d.ts +1 -1
  424. package/dist/source-agent-qualifier.js +21 -19
  425. package/dist/{storage-VpDzURiA.d.ts → storage-CcKmEjL8.d.ts} +3 -2
  426. package/dist/storage.d.ts +2 -2
  427. package/dist/storage.js +21 -19
  428. package/dist/subject-config.d.ts +38 -0
  429. package/dist/subject-config.js +20 -0
  430. package/dist/subject-config.js.map +1 -0
  431. package/dist/summarizer.d.ts +1 -1
  432. package/dist/summarizer.js +3 -3
  433. package/dist/summary-snapshot.d.ts +1 -1
  434. package/dist/support-passport/index.d.ts +14 -14
  435. package/dist/support-passport/index.js +48 -46
  436. package/dist/temporal-supersession.d.ts +2 -2
  437. package/dist/temporal-timeline-recall.d.ts +1 -1
  438. package/dist/temporal-validity.d.ts +1 -1
  439. package/dist/threading.d.ts +1 -1
  440. package/dist/tier-migration.d.ts +2 -2
  441. package/dist/tier-routing.d.ts +1 -1
  442. package/dist/topics.d.ts +1 -1
  443. package/dist/transcript.d.ts +1 -1
  444. package/dist/transfer/backup.js +2 -2
  445. package/dist/transfer/capsule-export.js +2 -2
  446. package/dist/transfer/capsule-import.js +2 -2
  447. package/dist/transfer/types.d.ts +66 -66
  448. package/dist/trust-score-stage.d.ts +1 -1
  449. package/dist/trust-score.d.ts +1 -1
  450. package/dist/{types-D9gKdB79.d.ts → types-Pi0lfaEt.d.ts} +40 -29
  451. package/dist/types.d.ts +1 -1
  452. package/dist/types.js +1 -1
  453. package/dist/utility-runtime.d.ts +1 -1
  454. package/dist/verified-recall.js +19 -17
  455. package/dist/who-knows-cli.d.ts +11 -11
  456. package/dist/who-knows-cli.js +20 -18
  457. package/dist/who-knows.d.ts +11 -11
  458. package/dist/who-knows.js +19 -17
  459. package/dist/write-envelope.d.ts +5 -2
  460. package/dist/write-envelope.js +10 -1
  461. package/package.json +2 -2
  462. package/scripts/build-with-heap.mjs +1 -1
  463. package/src/access-boundary.ts +2 -0
  464. package/src/access-mcp-admin-tools.ts +14 -0
  465. package/src/access-mcp-output-schemas.ts +6 -0
  466. package/src/access-mcp.ts +6 -6
  467. package/src/access-operations-batch.ts +8 -0
  468. package/src/access-service.ts +85 -0
  469. package/src/access-surface-catalog.ts +2 -0
  470. package/src/config.ts +10 -17
  471. package/src/cross-lingual-recall.test.ts +47 -0
  472. package/src/cross-lingual-recall.ts +186 -0
  473. package/src/extraction-prompt.ts +1 -0
  474. package/src/extraction.ts +4 -1
  475. package/src/index.ts +5 -6
  476. package/src/mcp-read-only-tools.ts +1 -0
  477. package/src/memory-subject-cli.ts +135 -0
  478. package/src/memory-subject.test.ts +48 -0
  479. package/src/memory-subject.ts +314 -0
  480. package/src/memory-worth-outcomes.test.ts +6 -2
  481. package/src/memory-worth-outcomes.ts +11 -7
  482. package/src/operator-toolkit.ts +1 -1
  483. package/src/orchestration/extraction-persist.ts +48 -48
  484. package/src/orchestration/recall-internal-deps.ts +2 -0
  485. package/src/orchestration/recall-internal.ts +41 -38
  486. package/src/orchestration/recall-search-pipeline.ts +16 -0
  487. package/src/procedural/library-maintenance.test.ts +582 -0
  488. package/src/procedural/library-maintenance.ts +546 -0
  489. package/src/procedural/maintenance-config.ts +78 -0
  490. package/src/procedural/procedure-recall.ts +29 -1
  491. package/src/procedural/procedure-stats.ts +20 -0
  492. package/src/schemas.ts +7 -0
  493. package/src/search/port.ts +2 -1
  494. package/src/spaces/index.ts +38 -2
  495. package/src/storage.ts +11 -3
  496. package/src/subject-config.ts +80 -0
  497. package/src/types.ts +28 -29
  498. package/src/write-envelope.test.ts +14 -0
  499. package/src/write-envelope.ts +24 -3
  500. package/dist/chunk-4NZHHGVL.js.map +0 -1
  501. package/dist/chunk-A4VJKT2H.js.map +0 -1
  502. package/dist/chunk-EIR5VLIH.js.map +0 -1
  503. package/dist/chunk-GEULB2VI.js.map +0 -1
  504. package/dist/chunk-HDD4RRIX.js.map +0 -1
  505. package/dist/chunk-JG22O53B.js.map +0 -1
  506. package/dist/chunk-LCU5R6TQ.js.map +0 -1
  507. package/dist/chunk-MSTNSVXI.js.map +0 -1
  508. package/dist/chunk-RQYV6M2T.js.map +0 -1
  509. package/dist/chunk-UPIKAT5A.js.map +0 -1
  510. package/dist/chunk-URS5GSM7.js.map +0 -1
  511. package/dist/chunk-VRYEXPRX.js.map +0 -1
  512. package/dist/chunk-XBRGJJK7.js.map +0 -1
  513. package/dist/chunk-YHSNAGN3.js.map +0 -1
  514. package/dist/chunk-YQ3CBLL4.js.map +0 -1
  515. package/dist/chunk-ZAI5R6DW.js.map +0 -1
  516. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  517. /package/dist/{chunk-A6LBDIFS.js.map → chunk-2E36UXVW.js.map} +0 -0
  518. /package/dist/{chunk-RRJUMSFX.js.map → chunk-2XDWWPTN.js.map} +0 -0
  519. /package/dist/{chunk-QCNB4BRE.js.map → chunk-2YI72KM3.js.map} +0 -0
  520. /package/dist/{chunk-3YTTAGPB.js.map → chunk-3DVBKTSO.js.map} +0 -0
  521. /package/dist/{chunk-IFK3PVM7.js.map → chunk-3I7ASZN3.js.map} +0 -0
  522. /package/dist/{chunk-HBKFYXBA.js.map → chunk-4KYOLI6M.js.map} +0 -0
  523. /package/dist/{chunk-RNKNL5GQ.js.map → chunk-5NM4OH4P.js.map} +0 -0
  524. /package/dist/{chunk-CESQ4CMC.js.map → chunk-5YQ63T4B.js.map} +0 -0
  525. /package/dist/{chunk-PMVPCZJZ.js.map → chunk-6433HV72.js.map} +0 -0
  526. /package/dist/{chunk-NS5ETDYD.js.map → chunk-7BEPVIH3.js.map} +0 -0
  527. /package/dist/{chunk-SHQFYZTD.js.map → chunk-7YQ4IYS2.js.map} +0 -0
  528. /package/dist/{chunk-YMOPYG3K.js.map → chunk-BIJAWZYW.js.map} +0 -0
  529. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  530. /package/dist/{chunk-VYEPACWY.js.map → chunk-C24UZSFW.js.map} +0 -0
  531. /package/dist/{chunk-ZPN7W3OP.js.map → chunk-CDUUDBWJ.js.map} +0 -0
  532. /package/dist/{chunk-K7JMKLKV.js.map → chunk-CT56C22C.js.map} +0 -0
  533. /package/dist/{chunk-KWIGDKM2.js.map → chunk-D2YNNDML.js.map} +0 -0
  534. /package/dist/{chunk-ZFBZ4QTS.js.map → chunk-DJZWNKFO.js.map} +0 -0
  535. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  536. /package/dist/{chunk-VNIETTMR.js.map → chunk-DZUJ46DO.js.map} +0 -0
  537. /package/dist/{chunk-T6QMNVMO.js.map → chunk-EILZG5VC.js.map} +0 -0
  538. /package/dist/{chunk-652S5A5D.js.map → chunk-EUYWQ7TS.js.map} +0 -0
  539. /package/dist/{chunk-YIZRTHHF.js.map → chunk-GDFVPUJ5.js.map} +0 -0
  540. /package/dist/{chunk-ML3U4KPR.js.map → chunk-GIC6BASP.js.map} +0 -0
  541. /package/dist/{chunk-7PWWGYGO.js.map → chunk-GNCCUR6K.js.map} +0 -0
  542. /package/dist/{chunk-Y5UT73VZ.js.map → chunk-IID2CMUU.js.map} +0 -0
  543. /package/dist/{chunk-MB6GLPRY.js.map → chunk-IVKIODHO.js.map} +0 -0
  544. /package/dist/{chunk-UYCIS6V5.js.map → chunk-JCWY73FK.js.map} +0 -0
  545. /package/dist/{chunk-WHA6ISFX.js.map → chunk-JYYBA7TF.js.map} +0 -0
  546. /package/dist/{chunk-T42L3S6A.js.map → chunk-LBWQ65SX.js.map} +0 -0
  547. /package/dist/{chunk-JXMXTV6C.js.map → chunk-LGO6A7GJ.js.map} +0 -0
  548. /package/dist/{chunk-H6B6GPVH.js.map → chunk-LZH5FR2W.js.map} +0 -0
  549. /package/dist/{chunk-5HERQ5FX.js.map → chunk-M4AHBM72.js.map} +0 -0
  550. /package/dist/{chunk-GOGHZVY3.js.map → chunk-MN4KB2A4.js.map} +0 -0
  551. /package/dist/{chunk-OQIRBGUU.js.map → chunk-N37X5RU7.js.map} +0 -0
  552. /package/dist/{chunk-E6EQTCOQ.js.map → chunk-NKKD4ZAU.js.map} +0 -0
  553. /package/dist/{chunk-VANZKHTN.js.map → chunk-NNBZS3DY.js.map} +0 -0
  554. /package/dist/{chunk-IWUN4RZL.js.map → chunk-NTWN6HB2.js.map} +0 -0
  555. /package/dist/{chunk-2PSX5BJU.js.map → chunk-NZPFCP5A.js.map} +0 -0
  556. /package/dist/{chunk-U56TGYVS.js.map → chunk-OCZIYAE5.js.map} +0 -0
  557. /package/dist/{chunk-I2HTKOOP.js.map → chunk-ODZG724P.js.map} +0 -0
  558. /package/dist/{chunk-LTBKKSCX.js.map → chunk-OLBZ2WGG.js.map} +0 -0
  559. /package/dist/{chunk-GQ5OJVTM.js.map → chunk-OTHZWLUD.js.map} +0 -0
  560. /package/dist/{chunk-PD66CVSD.js.map → chunk-OUKBMQ2O.js.map} +0 -0
  561. /package/dist/{chunk-4E6IJCLC.js.map → chunk-PE255F4T.js.map} +0 -0
  562. /package/dist/{chunk-GPFZFCRN.js.map → chunk-PP7R754B.js.map} +0 -0
  563. /package/dist/{chunk-PHX3ET3C.js.map → chunk-QOS5LBZN.js.map} +0 -0
  564. /package/dist/{chunk-G72IPMR7.js.map → chunk-R4OCGPSH.js.map} +0 -0
  565. /package/dist/{chunk-VUP47UJI.js.map → chunk-R7JAM2XF.js.map} +0 -0
  566. /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
  567. /package/dist/{chunk-P4CQCL27.js.map → chunk-S2DPMJXH.js.map} +0 -0
  568. /package/dist/{chunk-OXL5QKTV.js.map → chunk-SIHSCCUQ.js.map} +0 -0
  569. /package/dist/{chunk-KLPVXLQJ.js.map → chunk-SPUJNJJC.js.map} +0 -0
  570. /package/dist/{chunk-CCP6LXQJ.js.map → chunk-SQI57UCJ.js.map} +0 -0
  571. /package/dist/{chunk-UIYYS2YI.js.map → chunk-SVSRPG6M.js.map} +0 -0
  572. /package/dist/{chunk-RNORDDD6.js.map → chunk-THG4GYIE.js.map} +0 -0
  573. /package/dist/{chunk-CUIAHZPZ.js.map → chunk-TR7DGXGI.js.map} +0 -0
  574. /package/dist/{chunk-PDKBKBC2.js.map → chunk-UIN2BWDD.js.map} +0 -0
  575. /package/dist/{chunk-4GD7YV4Y.js.map → chunk-UXO5IMBK.js.map} +0 -0
  576. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  577. /package/dist/{chunk-MUJ4QFUQ.js.map → chunk-W4BMEGQA.js.map} +0 -0
  578. /package/dist/{chunk-5HK3CJAR.js.map → chunk-W675UJCZ.js.map} +0 -0
  579. /package/dist/{chunk-MDVBCPOS.js.map → chunk-XCTXS7VY.js.map} +0 -0
  580. /package/dist/{chunk-NTERJOFA.js.map → chunk-XRYZRW54.js.map} +0 -0
  581. /package/dist/{chunk-LA2MSK23.js.map → chunk-Y7DK7HHJ.js.map} +0 -0
  582. /package/dist/{chunk-34BMUGRA.js.map → chunk-YB42WZCY.js.map} +0 -0
  583. /package/dist/{chunk-LWVG6U7L.js.map → chunk-YHCBJULX.js.map} +0 -0
  584. /package/dist/{chunk-VYISFWVX.js.map → chunk-YQNNHLCG.js.map} +0 -0
  585. /package/dist/{chunk-FFPBTNLC.js.map → chunk-Z7PBQPJ4.js.map} +0 -0
  586. /package/dist/{chunk-MXJU4GCA.js.map → chunk-ZO6AXLEH.js.map} +0 -0
  587. /package/dist/{chunk-JNSLW2O4.js.map → chunk-ZQHI2BZB.js.map} +0 -0
  588. /package/dist/{graph-edge-decay-A4SDFMMS.js.map → cross-lingual-recall.js.map} +0 -0
  589. /package/dist/{resolution-DKMBPXHI.js.map → graph-edge-decay-FXGELBFA.js.map} +0 -0
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Memory subject: user-centric vs agent-centric classification (issue #2372).
3
+ *
4
+ * Scope says WHERE a memory lives; subject says WHOM it is about — and that
5
+ * is what determines where it may safely go. `user` memories model one
6
+ * person (preferences, relationships, biography, moments, commitments);
7
+ * `agent` memories model how to operate (procedures, principles,
8
+ * tool-usage lessons, debugging strategies, environment facts with no
9
+ * personal content).
10
+ *
11
+ * This module owns, in one place:
12
+ * - the deterministic write-time classification (category defaults with an
13
+ * optional extractor override),
14
+ * - the promotion guard shared by EVERY promotion surface (spaces promote
15
+ * AND scope-profile promotion targets — AGENTS.md §27 uniform gating),
16
+ * - read-only promotion-candidate surfacing (reuse-signaled agent-subject
17
+ * memories with no equivalent in the target layer), and
18
+ * - the deterministic backfill pass (shadow/apply, no LLM).
19
+ */
20
+
21
+ import { ContentHashIndex } from "./storage/content-hash-index.js";
22
+ import { sanitizeMemoryContent } from "./sanitize.js";
23
+ import type { McpTool } from "./access-mcp.js";
24
+ import type { MemoryCategory, MemoryFile, MemorySubject, SubjectGuardMode } from "./types.js";
25
+
26
+ export const SUBJECT_VALUES = ["user", "agent"] as const;
27
+ export const SUBJECT_GUARD_MODES = ["off", "warn", "enforce"] as const;
28
+
29
+ /** The CLI / per-call override that permits a user-subject promotion. */
30
+ export const SUBJECT_GUARD_OVERRIDE_FLAG = "--allow-user-subject";
31
+
32
+ export function isMemorySubject(value: unknown): value is MemorySubject {
33
+ return value === "user" || value === "agent";
34
+ }
35
+
36
+ export function isSubjectGuardMode(value: unknown): value is SubjectGuardMode {
37
+ return value === "off" || value === "warn" || value === "enforce";
38
+ }
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Write-time classification
42
+ // ---------------------------------------------------------------------------
43
+
44
+ /**
45
+ * Deterministic category defaults (issue #2372 §1):
46
+ * user — preference, relationship, moment, commitment
47
+ * agent — procedure, principle, skill
48
+ * Every other category has no default; the resolver falls back to `"user"`,
49
+ * the most-restrictive value (Review Prevention Checklist §36 — an unsafe
50
+ * enum default is never the convenient one).
51
+ */
52
+ const SUBJECT_CATEGORY_DEFAULTS: Partial<Record<MemoryCategory, MemorySubject>> = {
53
+ preference: "user",
54
+ relationship: "user",
55
+ moment: "user",
56
+ commitment: "user",
57
+ procedure: "agent",
58
+ principle: "agent",
59
+ skill: "agent",
60
+ };
61
+
62
+ export function subjectDefaultForCategory(category: MemoryCategory): MemorySubject {
63
+ return SUBJECT_CATEGORY_DEFAULTS[category] ?? "user";
64
+ }
65
+
66
+ /**
67
+ * Resolve the write-time subject: the extractor's single-token value when it
68
+ * emitted a valid one, else the category default. Never reclassifies on read.
69
+ */
70
+ export function resolveWriteSubject(
71
+ category: MemoryCategory,
72
+ extractorValue: unknown,
73
+ ): MemorySubject {
74
+ return isMemorySubject(extractorValue) ? extractorValue : subjectDefaultForCategory(category);
75
+ }
76
+
77
+ // ---------------------------------------------------------------------------
78
+ // Promotion guard (uniform across every promotion surface — §27)
79
+ // ---------------------------------------------------------------------------
80
+
81
+ /** Scope-profile promotion targets that are shared layers. */
82
+ export function isSharedPromotionTarget(target: string): boolean {
83
+ return target === "teamProject" || target === "serverShared";
84
+ }
85
+
86
+ export interface SubjectGuardDecision {
87
+ action: "allow" | "warn" | "reject";
88
+ /** Effective subject — an absent subject resolves to "user" (fail closed, §36). */
89
+ effectiveSubject: MemorySubject;
90
+ /** Structured reason; empty string when action === "allow". */
91
+ reason: string;
92
+ /** The override that permits this promotion when action is reject/warn. */
93
+ override: typeof SUBJECT_GUARD_OVERRIDE_FLAG;
94
+ }
95
+
96
+ /**
97
+ * Evaluate one promotion against the subject guard. Shared by the spaces
98
+ * promotion workflow and the scope-profile promotion targets so the two
99
+ * surfaces cannot drift (issue #2372 acceptance 2, AGENTS.md §27).
100
+ *
101
+ * - mode "off", non-shared targets, agent-subject memories, and explicit
102
+ * `allowUserSubject` overrides all allow.
103
+ * - a `user`-subject memory (or a memory with NO subject — fail closed)
104
+ * promoted to a shared layer warns under "warn" and rejects under
105
+ * "enforce", with the override named in the reason (§39: never a silent
106
+ * accept).
107
+ */
108
+ export function evaluateSubjectGuard(params: {
109
+ subject: MemorySubject | undefined;
110
+ sharedTarget: boolean;
111
+ mode: SubjectGuardMode;
112
+ allowUserSubject?: boolean;
113
+ }): SubjectGuardDecision {
114
+ const effectiveSubject = params.subject ?? "user";
115
+ const base = { effectiveSubject, override: SUBJECT_GUARD_OVERRIDE_FLAG } as const;
116
+ if (params.mode === "off" || !params.sharedTarget || effectiveSubject === "agent") {
117
+ return { action: "allow", reason: "", ...base };
118
+ }
119
+ if (params.allowUserSubject === true) {
120
+ return { action: "allow", reason: "user-subject promotion override accepted", ...base };
121
+ }
122
+ return {
123
+ action: params.mode === "enforce" ? "reject" : "warn",
124
+ reason:
125
+ `subject=${effectiveSubject} memory targets a shared layer (team/server); ` +
126
+ `user-subject memories model one person and must not be shared; ` +
127
+ `override with ${SUBJECT_GUARD_OVERRIDE_FLAG} (allowUserSubject: true) if intended`,
128
+ ...base,
129
+ };
130
+ }
131
+
132
+ // ---------------------------------------------------------------------------
133
+ // Promotion candidates (read-only surfacing — no auto-promotion)
134
+ // ---------------------------------------------------------------------------
135
+
136
+ export type PromotionReuseSignal = "reinforcement" | "memory_worth" | "access_count";
137
+
138
+ export interface PromotionCandidate {
139
+ id: string;
140
+ path: string;
141
+ category: MemoryCategory;
142
+ content: string;
143
+ accessCount: number;
144
+ reinforcementCount: number;
145
+ mwSuccess: number;
146
+ mwFail: number;
147
+ reuseSignal: PromotionReuseSignal;
148
+ }
149
+
150
+ /** Default reuse-signal threshold for `accessCount` (config `promotionCandidates.minAccessCount`). */
151
+ export const PROMOTION_CANDIDATES_DEFAULT_MIN_ACCESS = 3;
152
+
153
+ /** Canonical content form for target-equivalence checks (same normalize pipeline as dedup). */
154
+ export function promotionCandidateKey(content: string): string {
155
+ return ContentHashIndex.normalizeContent(sanitizeMemoryContent(content).text);
156
+ }
157
+
158
+ /**
159
+ * List `subject: "agent"` memories that (a) are active, (b) show a reuse
160
+ * signal (`reinforcement_count > 0` OR `mw_success > mw_fail` OR
161
+ * `accessCount >= minAccessCount`), and (c) have no equivalent already in
162
+ * the promotion target layer (content-hash check via the dedup normalizer).
163
+ * Pure over the two memory lists; callers resolve namespaces.
164
+ */
165
+ export function computePromotionCandidates(options: {
166
+ memories: MemoryFile[];
167
+ targetMemories: MemoryFile[];
168
+ minAccessCount: number;
169
+ limit?: number;
170
+ }): PromotionCandidate[] {
171
+ if (!Number.isFinite(options.minAccessCount) || options.minAccessCount < 0) {
172
+ throw new Error(
173
+ `computePromotionCandidates: minAccessCount must be a non-negative number (got ${String(options.minAccessCount)})`,
174
+ );
175
+ }
176
+ const targetKeys = new Set(
177
+ options.targetMemories.map((m) => promotionCandidateKey(m.content ?? "")),
178
+ );
179
+ const out: PromotionCandidate[] = [];
180
+ for (const memory of options.memories) {
181
+ const fm = memory.frontmatter;
182
+ if (fm.subject !== "agent") continue;
183
+ if ((fm.status ?? "active") !== "active") continue;
184
+ const reinforcementCount = fm.reinforcement_count ?? 0;
185
+ const mwSuccess = fm.mw_success ?? 0;
186
+ const mwFail = fm.mw_fail ?? 0;
187
+ const accessCount = fm.accessCount ?? 0;
188
+ let reuseSignal: PromotionReuseSignal | undefined;
189
+ if (reinforcementCount > 0) reuseSignal = "reinforcement";
190
+ else if (mwSuccess > mwFail) reuseSignal = "memory_worth";
191
+ else if (accessCount >= options.minAccessCount) reuseSignal = "access_count";
192
+ if (reuseSignal === undefined) continue;
193
+ if (targetKeys.has(promotionCandidateKey(memory.content ?? ""))) continue;
194
+ out.push({
195
+ id: fm.id,
196
+ path: memory.path,
197
+ category: fm.category,
198
+ content: memory.content ?? "",
199
+
200
+ accessCount,
201
+ reinforcementCount,
202
+ mwSuccess,
203
+ mwFail,
204
+ reuseSignal,
205
+ });
206
+ if (options.limit !== undefined && out.length >= options.limit) break;
207
+ }
208
+ return out;
209
+ }
210
+
211
+ export interface PromotionCandidatesResult {
212
+ namespace: string;
213
+ targetNamespace: string;
214
+ minAccessCount: number;
215
+ candidates: PromotionCandidate[];
216
+ }
217
+
218
+ export const PROMOTION_CANDIDATES_MCP_TOOLS: McpTool[] = [
219
+ {
220
+ // Registered as `engram.promotion_candidates`; `withToolAliases` emits
221
+ // the canonical `remnic.promotion_candidates` alias (dual-naming).
222
+ name: "engram.promotion_candidates",
223
+ description:
224
+ "List agent-subject memories in the caller's namespace that are active, show a reuse signal (reinforcement_count > 0, mw_success > mw_fail, or accessCount >= threshold), and have no equivalent in the promotion target layer (default: the shared namespace). Read-only report; promotion itself uses the existing promotion commands (issue #2372).",
225
+ inputSchema: {
226
+ type: "object",
227
+ properties: {
228
+ namespace: {
229
+ type: "string",
230
+ description:
231
+ "Optional source namespace. Enforced against the caller's principal the same way recall is.",
232
+ },
233
+ targetNamespace: {
234
+ type: "string",
235
+ description: "Promotion target layer checked for existing equivalents. Default: the shared namespace.",
236
+ },
237
+ limit: {
238
+ type: "integer",
239
+ minimum: 1,
240
+ maximum: 100,
241
+ description: "Maximum candidates to return (default 20, max 100).",
242
+ },
243
+ },
244
+ additionalProperties: false,
245
+ },
246
+ },
247
+ ];
248
+
249
+ // ---------------------------------------------------------------------------
250
+ // Backfill (governance shadow/apply — deterministic rules only, no LLM)
251
+ // ---------------------------------------------------------------------------
252
+
253
+ /**
254
+ * Storage surface the backfill needs (mirrors pattern-reinforcement's
255
+ * structural interface so tests can pass an in-memory stub).
256
+ * `writeMemoryFrontmatter` invalidates caches and syncs the fact-hash index
257
+ * (§25/§31), so a stamped memory is immediately discoverable.
258
+ */
259
+ export interface SubjectBackfillStorage {
260
+ readAllMemories(): Promise<MemoryFile[]>;
261
+ writeMemoryFrontmatter(memory: MemoryFile, patch: Partial<MemoryFile["frontmatter"]>): Promise<boolean>;
262
+ }
263
+
264
+ export interface SubjectBackfillReport {
265
+ mode: "shadow" | "apply";
266
+ scanned: number;
267
+ stamped: number;
268
+ alreadyStamped: number;
269
+ stamps: Array<{
270
+ id: string;
271
+ category: MemoryCategory;
272
+ subject: MemorySubject;
273
+ path: string;
274
+ }>;
275
+ }
276
+
277
+ /**
278
+ * Stamp `subject` on memories that have none, using ONLY the deterministic
279
+ * category defaults (never an LLM, never reclassifying an existing subject —
280
+ * issue #2372 §1.3). `shadow` reports the intended stamps without writing;
281
+ * `apply` writes through `writeMemoryFrontmatter`, which invalidates the
282
+ * memory caches and re-syncs the fact-hash index.
283
+ */
284
+ export async function backfillMemorySubjects(options: {
285
+ storage: SubjectBackfillStorage;
286
+ mode: "shadow" | "apply";
287
+ }): Promise<SubjectBackfillReport> {
288
+ const memories = await options.storage.readAllMemories();
289
+ const report: SubjectBackfillReport = {
290
+ mode: options.mode,
291
+ scanned: memories.length,
292
+ stamped: 0,
293
+ alreadyStamped: 0,
294
+ stamps: [],
295
+ };
296
+ for (const memory of memories) {
297
+ if (memory.frontmatter.subject !== undefined) {
298
+ report.alreadyStamped++;
299
+ continue;
300
+ }
301
+ const subject = subjectDefaultForCategory(memory.frontmatter.category);
302
+ report.stamps.push({
303
+ id: memory.frontmatter.id,
304
+ category: memory.frontmatter.category,
305
+ subject,
306
+ path: memory.path,
307
+ });
308
+ if (options.mode === "apply") {
309
+ await options.storage.writeMemoryFrontmatter(memory, { subject });
310
+ }
311
+ report.stamped++;
312
+ }
313
+ return report;
314
+ }
@@ -306,11 +306,15 @@ test("concurrent outcomes for the same memory do NOT lose updates", async () =>
306
306
  }
307
307
  });
308
308
 
309
- test("eligible-category set is exactly {fact}", () => {
309
+ test("eligible-category set is exactly {fact, procedure}", () => {
310
310
  // Pinning this keeps PR 3 in lockstep with the PR 1 doctor allowlist in
311
311
  // operator-toolkit.ts (MEMORY_WORTH_ELIGIBLE_CATEGORIES). If either side
312
312
  // expands, this test and the doctor test must both be updated.
313
+ // `procedure` joined in issue #2370: the procedure library-health loop
314
+ // retires on failure-dominant mw_* counters, so injected procedures must
315
+ // accrue outcomes.
313
316
  const eligible = memoryWorthOutcomeEligibleCategories();
314
- assert.equal(eligible.size, 1);
317
+ assert.equal(eligible.size, 2);
315
318
  assert.ok(eligible.has("fact"));
319
+ assert.ok(eligible.has("procedure"));
316
320
  });
@@ -20,8 +20,9 @@
20
20
  * preserved. The PR 1 serializer rejects negative / non-integer counters,
21
21
  * so we rely on that for defensive validation rather than duplicating it.
22
22
  * - Only instruments categories in `MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES`
23
- * (currently `fact`, matching `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in
24
- * operator-toolkit.ts for the doctor audit). Non-eligible memories return
23
+ * (currently `fact` and `procedure` — procedures joined in issue #2370 —
24
+ * matching `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in operator-toolkit.ts for
25
+ * the doctor audit). Non-eligible memories return
25
26
  * `{ ok: false, reason: "ineligible_category" }` rather than throwing so
26
27
  * the caller — typically a ledger consumer draining heterogeneous events
27
28
  * — doesn't need to pre-filter by category.
@@ -94,14 +95,17 @@ function runSerialized<T>(key: string, task: () => Promise<T>): Promise<T> {
94
95
  }
95
96
 
96
97
  /**
97
- * Categories currently instrumented for Memory Worth counters. Must be kept
98
- * in sync with `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in `operator-toolkit.ts`.
99
- * Declared here (not imported) to avoid a circular dep with operator-toolkit,
100
- * which imports from this file's peers. The two constants are validated by a
98
+ * Categories currently instrumented for Memory Worth counters. `procedure`
99
+ * joined in issue #2370 the procedure library-health maintenance loop
100
+ * retires on failure-dominant `mw_*` counters, so injected procedures must
101
+ * be able to accrue outcomes. Must be kept in sync with
102
+ * `MEMORY_WORTH_ELIGIBLE_CATEGORIES` in `operator-toolkit.ts`. Declared
103
+ * here (not imported) to avoid a circular dep with operator-toolkit, which
104
+ * imports from this file's peers. The two constants are validated by a
101
105
  * test to stay in lockstep.
102
106
  */
103
107
  const MEMORY_WORTH_OUTCOME_ELIGIBLE_CATEGORIES: ReadonlySet<MemoryFrontmatter["category"]> =
104
- new Set(["fact"]);
108
+ new Set(["fact", "procedure"]);
105
109
 
106
110
  /**
107
111
  * Exported so downstream tests / operators can query the allowlist without
@@ -1580,7 +1580,7 @@ export async function runOperatorDoctor(options: OperatorDoctorOptions): Promise
1580
1580
  * alongside the scoring/increment logic so the doctor audit stays in sync.
1581
1581
  */
1582
1582
  const MEMORY_WORTH_ELIGIBLE_CATEGORIES: ReadonlySet<MemoryFile["frontmatter"]["category"]> =
1583
- new Set(["fact"]);
1583
+ new Set(["fact", "procedure"]);
1584
1584
 
1585
1585
  /**
1586
1586
  * Count memories that pre-date the Memory Worth counters introduced in issue
@@ -74,6 +74,7 @@ import {
74
74
  } from "../behavior-signals.js";
75
75
  import { buildProcedurePersistBody } from "../procedural/procedure-types.js";
76
76
  import { stripAttributesSuffix } from "../structured-attributes.js";
77
+ import { evaluateSubjectGuard, isSharedPromotionTarget, resolveWriteSubject } from "../memory-subject.js";
77
78
  import { LocalLlmClient } from "../local-llm.js";
78
79
  import type { ExtractionEngine } from "../extraction.js";
79
80
  import {
@@ -94,6 +95,7 @@ import type {
94
95
  MemoryFile,
95
96
  MemoryFrontmatter,
96
97
  MemoryLink,
98
+ MemorySubject,
97
99
  PluginConfig,
98
100
  ProvenanceSource,
99
101
  MemoryCategory,
@@ -338,6 +340,19 @@ export class ExtractionPersistCoordinator {
338
340
  // introduced (ratchet scatteredConfigFlagReads; see #1523).
339
341
  const namespacesEnabled = resolveNamespaceCapabilities(this.deps.config).namespaces;
340
342
  const sourceConnector = sourceContext?.sourceConnector; const origin = classifyExtractionOrigin(sourceContext);
343
+ // Subject guard (issue #2372): the ONE gate shared by every extraction-side
344
+ // promotion path so behavior matches the spaces surface (§27).
345
+ const subjectGuardAllows = (subject: MemorySubject | undefined, target: string, label: string): boolean => {
346
+ const decision = evaluateSubjectGuard({
347
+ subject,
348
+ sharedTarget: isSharedPromotionTarget(target),
349
+ mode: this.deps.config.subjectGuard,
350
+ });
351
+ if (decision.action !== "allow") {
352
+ log.warn(`subject-guard(${decision.action}) ${label}: ${decision.reason}`);
353
+ }
354
+ return decision.action !== "reject";
355
+ };
341
356
  const promoteMemoryToProfileTargets = async (options: {
342
357
  sourceStorage: StorageManager;
343
358
  category: string;
@@ -353,8 +368,7 @@ export class ExtractionPersistCoordinator {
353
368
  intentEntityTypes?: string[];
354
369
  memoryKind?: MemoryFrontmatter["memoryKind"];
355
370
  validAt?: string;
356
- // #1578 — bi-temporal bounds + ingestion provenance forwarded to profile-
357
- // target copies (same defect class as shared promotion; cursor bugbot).
371
+ // #1578 — bi-temporal bounds + provenance forwarded to profile-target copies.
358
372
  invalidAt?: string;
359
373
  observedAt?: string;
360
374
  eventTimeSource?: "extracted" | "assumed";
@@ -362,6 +376,7 @@ export class ExtractionPersistCoordinator {
362
376
  sources?: ProvenanceSource[];
363
377
  provenance?: "verified" | "unverified" | "none";
364
378
  toolScoped?: true;
379
+ subject?: MemorySubject;
365
380
  harmonicFact?: Omit<
366
381
  HarmonicConstructionInput["persistedFacts"][number],
367
382
  "memoryId"
@@ -392,6 +407,7 @@ export class ExtractionPersistCoordinator {
392
407
  try {
393
408
  const targetStorage = await this.deps.getStorageRouter().storageFor(target.namespace);
394
409
  if (targetStorage.dir === options.sourceStorage.dir) continue;
410
+ if (!subjectGuardAllows(options.subject, target.target, `profile promotion to ${target.target}`)) continue;
395
411
  // Compose BEFORE the dedup gate (#2014 round 2): salvage mode may
396
412
  // drop or clamp attributes, and the dedup hash, contentHashSource,
397
413
  // and supersession keys below must all describe the SURVIVING
@@ -406,6 +422,7 @@ export class ExtractionPersistCoordinator {
406
422
  structuredAttributes: options.structuredAttributes,
407
423
  validAt: options.validAt,
408
424
  ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
425
+ ...(options.subject !== undefined ? { subject: options.subject } : {}),
409
426
  },
410
427
  { source: `${options.source}-${target.target}-promotion` },
411
428
  );
@@ -557,8 +574,7 @@ export class ExtractionPersistCoordinator {
557
574
  memoryKind?: MemoryFrontmatter["memoryKind"];
558
575
  validAt?: string;
559
576
  // #1578 — bi-temporal bounds + ingestion provenance forwarded to the
560
- // shared-namespace copy so shared recall honours the same invalid_at
561
- // window as the source fact (cursor bugbot).
577
+ // shared-namespace copy (cursor bugbot).
562
578
  invalidAt?: string;
563
579
  observedAt?: string;
564
580
  eventTimeSource?: "extracted" | "assumed";
@@ -568,6 +584,7 @@ export class ExtractionPersistCoordinator {
568
584
  /** Claim-level provenance spans (issue #1575 PR 2). */
569
585
  sources?: ProvenanceSource[];
570
586
  provenance?: "verified" | "unverified" | "none";
587
+ subject?: MemorySubject;
571
588
  harmonicFact?: Omit<
572
589
  HarmonicConstructionInput["persistedFacts"][number],
573
590
  "memoryId"
@@ -591,43 +608,19 @@ export class ExtractionPersistCoordinator {
591
608
  )
592
609
  )
593
610
  return;
611
+ if (!subjectGuardAllows(options.subject, "serverShared", "shared promotion")) return;
594
612
  try {
595
613
  const sharedStorage = await this.deps.getStorageRouter().storageFor(
596
614
  this.deps.config.sharedNamespace,
597
615
  );
598
- // Dedup gate: canonicalize content before hashing.
599
- // Issue #369 (PR #401): When inline attribution is enabled,
600
- // `applyInlineCitation` appends a timestamp-bearing marker (e.g.
601
- // `[Source: ..., ts=2026-04-11T...]`). Because the timestamp changes
602
- // on every call, hashing cited content produces a unique hash each
603
- // time defeating dedup entirely and allowing the same logical fact to
604
- // be promoted repeatedly. Also, both promotion call sites pass
605
- // `fact.content`, which can already carry an inline citation (e.g. a
606
- // relayed or reprocessed fact). Strip any pre-existing citation so the
607
- // dedup key matches the hash stored from the original un-cited write.
608
- // PR #402 round-6 (Fix #2 / chatgpt-codex P1 PRRT_kwDORJXyws56U74n):
609
- // Compute the enriched content before the hash-dedup check so the
610
- // lookup uses the same content that writeMemory will actually store.
611
- // When structuredAttributes are present, writeMemory appends an
612
- // "[Attributes: ...]" suffix before hashing; hasFactContentHash must
613
- // receive the same enriched body or the check is against a different
614
- // hash and dedup fails to fire (letting duplicates through) or fires
615
- // when it shouldn't (collapsing memories with different enrichments).
616
- // Fix #1 (P2 PRRT_kwDORJXyws56VHZc): use normalizeAttributePairs so
617
- // key order and casing are canonical — identical to the enrichment
618
- // applied by storage.writeMemory — preventing spurious hash misses
619
- // when attribute maps arrive with different insertion orders or casing.
620
- // Fix #4 (Low PRRT_kwDORJXyws56VHth): sanitize the base content before
621
- // building dedupContent. writeMemory runs sanitizeMemoryContent on the
622
- // enriched body before hashing; if sanitization redacts the content to
623
- // REDACTED_PLACEHOLDER the stored hash is for the redacted form, not
624
- // the raw form. Computing dedupContent from sanitized.text here ensures
625
- // the hash lookup and the normalizedIncoming comparison both use the
626
- // same content that writeMemory will actually store.
627
- // Combined fix: strip any pre-existing citation FIRST to obtain
628
- // rawContent (the canonical body), then sanitize rawContent (not
629
- // options.content) when building dedupContent, so that citation
630
- // stripping and sanitization are applied in a consistent order.
616
+ // Dedup gate: canonicalize content before hashing. Strip any
617
+ // pre-existing citation FIRST (applyInlineCitation appends a
618
+ // timestamped marker, so hashing cited content defeats dedup and
619
+ // call sites may pass already-cited content), then sanitize the base
620
+ // and build the attribute-enriched body with normalizeAttributePairs
621
+ // — the same canonicalization writeMemory applies so the hash
622
+ // lookup uses the exact body writeMemory stores (#369/#401, #402
623
+ // round-6 fixes; PRRT_kwDORJXyws56VHZc / VHth).
631
624
  const rawContent =
632
625
  citationEnabled &&
633
626
  hasCitationForTemplate(options.content, citationTemplate)
@@ -649,6 +642,7 @@ export class ExtractionPersistCoordinator {
649
642
  structuredAttributes: options.structuredAttributes,
650
643
  validAt: options.validAt,
651
644
  ...(sourceContext?.sourceConnector ? { sourceConnector: sourceContext.sourceConnector } : {}),
645
+ ...(options.subject !== undefined ? { subject: options.subject } : {}),
652
646
  },
653
647
  { source: `${options.source}-shared-promotion` },
654
648
  );
@@ -1330,7 +1324,8 @@ export class ExtractionPersistCoordinator {
1330
1324
  profileAllowsSharedWrites &&
1331
1325
  this.deps.storageDirNamespace(storage.dir) !== this.deps.config.sharedNamespace &&
1332
1326
  shouldPromoteGlobalFactToShared({ scope: f.scope, content: f.content,
1333
- sourceConnector, procedureSteps: f.procedureSteps })
1327
+ sourceConnector, procedureSteps: f.procedureSteps }) &&
1328
+ subjectGuardAllows(f.subject, "serverShared", "pre-judge shared routing")
1334
1329
  ) {
1335
1330
  factNs = this.deps.config.sharedNamespace;
1336
1331
  }
@@ -1577,10 +1572,13 @@ export class ExtractionPersistCoordinator {
1577
1572
  );
1578
1573
  }
1579
1574
  }
1580
-
1581
- // Scope-based namespace routing: a `global` fact (scope classification
1582
- // on, no explicit routing-rule namespace) is promoted to the shared
1583
- // namespace unless the tool-scope guard withholds it (#2183).
1575
+ // Write-time subject stamp (issue #2372): extractor token over the
1576
+ // category default; absent when classification is disabled (byte-identical).
1577
+ const factSubject = this.deps.config.subjectClassification?.enabled === true
1578
+ ? resolveWriteSubject(writeCategory, fact.subject)
1579
+ : undefined;
1580
+ // Scope-based namespace routing: a `global` fact (no explicit routing
1581
+ // rule) promotes to the shared namespace unless a guard withholds it.
1584
1582
  if (
1585
1583
  lifecycleCaps.extractionScopeClassification &&
1586
1584
  namespacesEnabled &&
@@ -1590,7 +1588,7 @@ export class ExtractionPersistCoordinator {
1590
1588
  const currentNs = this.deps.storageDirNamespace(targetStorage.dir);
1591
1589
  if (currentNs !== this.deps.config.sharedNamespace && profileAllowsSharedWrites) {
1592
1590
  if (shouldPromoteGlobalFactToShared({ scope: fact.scope, content: fact.content,
1593
- sourceConnector, procedureSteps: fact.procedureSteps })) {
1591
+ sourceConnector, procedureSteps: fact.procedureSteps }) && subjectGuardAllows(fact.subject, "serverShared", "scope-routing")) {
1594
1592
  try {
1595
1593
  targetStorage = await this.deps.getStorageRouter().storageFor(
1596
1594
  this.deps.config.sharedNamespace,
@@ -2383,6 +2381,7 @@ export class ExtractionPersistCoordinator {
2383
2381
  sourceStorage: targetStorage,
2384
2382
  category: writeCategory,
2385
2383
  content: fact.content,
2384
+ subject: factSubject,
2386
2385
  confidence: fact.confidence,
2387
2386
  tags: fact.tags,
2388
2387
  entityRef: fact.entityRef,
@@ -2579,6 +2578,7 @@ export class ExtractionPersistCoordinator {
2579
2578
  structuredAttributes: fact.structuredAttributes,
2580
2579
  validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,
2581
2580
  ...(extractionSourceConnector ? { sourceConnector: extractionSourceConnector } : {}),
2581
+ ...(factSubject !== undefined ? { subject: factSubject } : {}),
2582
2582
  },
2583
2583
  { source: extractionWriteSource },
2584
2584
  );
@@ -2697,6 +2697,7 @@ export class ExtractionPersistCoordinator {
2697
2697
  category: writeCategory,
2698
2698
  content: fact.content,
2699
2699
  confidence: fact.confidence,
2700
+ subject: factSubject,
2700
2701
  tags: fact.tags,
2701
2702
  entityRef:
2702
2703
  typeof (fact as any).entityRef === "string"
@@ -2822,11 +2823,10 @@ export class ExtractionPersistCoordinator {
2822
2823
  }
2823
2824
  }
2824
2825
 
2825
- // Tracks whether THIS extraction persisted any durable, non-fact output to the
2826
- // BASE namespace's storage (entity / relationship / profile / question). The
2827
- // per-fact catalog touch (storage chokepoint #1522) only fires inside the fact write loop, so a
2828
- // fact-less extraction that still persists durable data must record exactly one
2829
- // base-namespace catalog touch after all writes complete (NHZEZ, codex P2).
2826
+ // Tracks whether THIS extraction persisted any durable, non-fact output
2827
+ // (entity / relationship / profile / question) to the BASE namespace.
2828
+ // A fact-less extraction still records exactly one base-namespace catalog
2829
+ // touch after all writes complete (NHZEZ, codex P2).
2830
2830
  let durableNonFactWritten = false;
2831
2831
  let durableNonFactTouchRecorded = false;
2832
2832
  const touchBaseNonFactNamespace = () => {
@@ -219,6 +219,8 @@ export interface RecallInternalDeps {
219
219
  searchOptions?: SearchQueryOptions;
220
220
  onDebugSnapshot?: (snapshot: QmdRecallSnapshot) => Promise<void>;
221
221
  /** Backend degradation observer, threaded into every QMD call (#1536). */
222
+ /** Cross-lingual plan flag (#2197): supplement the lexical page with vector-tier hits. */
223
+ crossScript?: boolean;
222
224
  onDegradation?: (degradation: SearchDegradation) => void;
223
225
  abortSignal?: AbortSignal;
224
226
  },