@remnic/core 9.3.694 → 9.3.695

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 (330) hide show
  1. package/dist/access-boundary.d.ts +12 -11
  2. package/dist/access-boundary.js +34 -28
  3. package/dist/access-cli.js +60 -59
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +12 -11
  6. package/dist/access-http.js +38 -32
  7. package/dist/access-mcp.d.ts +12 -11
  8. package/dist/access-mcp.js +37 -31
  9. package/dist/access-operations.d.ts +12 -11
  10. package/dist/access-operations.js +36 -30
  11. package/dist/access-schema.js +3 -3
  12. package/dist/{access-service-Ceq4TdPO.d.ts → access-service-BqBQeUJd.d.ts} +15 -2
  13. package/dist/access-service.d.ts +8 -7
  14. package/dist/access-service.js +33 -27
  15. package/dist/access-surface-catalog.d.ts +12 -11
  16. package/dist/action-confidence.d.ts +1 -1
  17. package/dist/active-memory-bridge.d.ts +1 -1
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/active-recall.js +1 -1
  20. package/dist/{auto-sync-RWXT6P5M.js → auto-sync-PFW2NJZY.js} +8 -8
  21. package/dist/behavior-learner.d.ts +1 -1
  22. package/dist/behavior-signals.d.ts +1 -1
  23. package/dist/bootstrap.d.ts +9 -8
  24. package/dist/briefing.d.ts +1 -1
  25. package/dist/briefing.js +12 -5
  26. package/dist/buffer-surprise-report.d.ts +1 -1
  27. package/dist/buffer.d.ts +1 -1
  28. package/dist/calibration.d.ts +1 -1
  29. package/dist/calibration.js +2 -2
  30. package/dist/capabilities.d.ts +1 -1
  31. package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
  32. package/dist/{catalog-Tkb991rg.d.ts → catalog-D7YDNNF7.d.ts} +1 -1
  33. package/dist/causal-behavior.d.ts +1 -1
  34. package/dist/causal-behavior.js +2 -2
  35. package/dist/causal-chain.js +2 -2
  36. package/dist/causal-consolidation.d.ts +1 -1
  37. package/dist/causal-consolidation.js +17 -16
  38. package/dist/causal-consolidation.js.map +1 -1
  39. package/dist/causal-retrieval.js +2 -2
  40. package/dist/causal-trajectory-graph.js +2 -2
  41. package/dist/causal-trajectory.js +1 -1
  42. package/dist/{chunk-UPTZYUYJ.js → chunk-24D66MMN.js} +2 -1
  43. package/dist/chunk-24D66MMN.js.map +1 -0
  44. package/dist/{chunk-FCH766FX.js → chunk-32XTY2DQ.js} +51 -51
  45. package/dist/{chunk-YN4ZT4CW.js → chunk-3LYJIA76.js} +1 -1
  46. package/dist/{chunk-24FCDBJV.js → chunk-3P2XEQSV.js} +2 -2
  47. package/dist/{chunk-JIKBEDSB.js → chunk-4NNDJOAO.js} +8 -8
  48. package/dist/{chunk-EPVIBPVE.js → chunk-52QIAN76.js} +2 -2
  49. package/dist/chunk-5AT62NQH.js +553 -0
  50. package/dist/chunk-5AT62NQH.js.map +1 -0
  51. package/dist/{chunk-TAPSNIMA.js → chunk-5CEJH5ZN.js} +4 -4
  52. package/dist/{chunk-4RGWCRIJ.js → chunk-5TYA4OCF.js} +4 -4
  53. package/dist/{chunk-PILLH262.js → chunk-6GAUF4OU.js} +3 -3
  54. package/dist/{chunk-QXWQ5V24.js → chunk-AF6DSAWD.js} +2 -2
  55. package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
  56. package/dist/{chunk-32KD5IHZ.js → chunk-CLXTDOKV.js} +2 -2
  57. package/dist/{chunk-ARV3AUOM.js → chunk-DL6H3D7S.js} +2 -2
  58. package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
  59. package/dist/{chunk-KCRV3HVN.js → chunk-EC3A6M43.js} +2 -2
  60. package/dist/{chunk-PNW4KKJX.js → chunk-EK6FYL2E.js} +27 -1
  61. package/dist/chunk-EK6FYL2E.js.map +1 -0
  62. package/dist/{chunk-YI3KC2B5.js → chunk-FZMH66NT.js} +2 -2
  63. package/dist/{chunk-DT2ZGQT7.js → chunk-G663XUEG.js} +2 -2
  64. package/dist/{chunk-TYEOAFH3.js → chunk-G6SVZWPB.js} +10 -1
  65. package/dist/chunk-G6SVZWPB.js.map +1 -0
  66. package/dist/{chunk-CDOIDOTQ.js → chunk-HKET3ZOI.js} +4 -4
  67. package/dist/{chunk-YOI3ELXF.js → chunk-IF362TF6.js} +2 -2
  68. package/dist/{chunk-UX5QTAFE.js → chunk-J45OCIVH.js} +2 -2
  69. package/dist/{chunk-UDJLF3BO.js → chunk-JI6HWBYL.js} +2 -2
  70. package/dist/{chunk-ECZPWSB5.js → chunk-JJT3AGL4.js} +4 -4
  71. package/dist/{chunk-6C4WHMKV.js → chunk-JMAKCWJ3.js} +6 -6
  72. package/dist/{chunk-4NFVPDIL.js → chunk-LM6JB2EG.js} +2 -2
  73. package/dist/{chunk-MOGFK2DU.js → chunk-LPIWEKZ3.js} +2 -2
  74. package/dist/{chunk-LD53WPMU.js → chunk-LQ6JI4VH.js} +4 -4
  75. package/dist/{chunk-IZLNJYLX.js → chunk-MNFAGE5D.js} +2 -2
  76. package/dist/{chunk-NXNUG7IA.js → chunk-MOBRVKWE.js} +23 -12
  77. package/dist/chunk-MOBRVKWE.js.map +1 -0
  78. package/dist/{chunk-5A35EGHM.js → chunk-N4PD5IY3.js} +35 -35
  79. package/dist/{chunk-PQP6MFPL.js → chunk-NFMDHE45.js} +2 -2
  80. package/dist/{chunk-WVTNZUER.js → chunk-NLZO5NO6.js} +2 -2
  81. package/dist/{chunk-5S53ZBPH.js → chunk-Q6ZHGGNJ.js} +2 -2
  82. package/dist/{chunk-SN5DFE34.js → chunk-Q7SFJURX.js} +2 -2
  83. package/dist/{chunk-MXZWKOOR.js → chunk-QJM2XAJD.js} +11 -11
  84. package/dist/{chunk-6ZNIUGXB.js → chunk-QQW2LIEA.js} +4 -4
  85. package/dist/{chunk-ZKD3UVEO.js → chunk-QVTSLRKT.js} +3 -3
  86. package/dist/{chunk-C5AOVGVC.js → chunk-RWST6NOL.js} +166 -102
  87. package/dist/chunk-RWST6NOL.js.map +1 -0
  88. package/dist/{chunk-YXZPKBFW.js → chunk-SPVIG2R3.js} +10 -10
  89. package/dist/{chunk-B55EAZNF.js → chunk-TIVZ4MCG.js} +2 -2
  90. package/dist/{chunk-5KBNNUXS.js → chunk-TT7BJWGI.js} +2 -2
  91. package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
  92. package/dist/{chunk-E6BOD3UJ.js → chunk-VPAFWWCL.js} +2 -2
  93. package/dist/{chunk-D7PQ7HZL.js → chunk-W54EAJT4.js} +2 -2
  94. package/dist/{chunk-QVG4LAQO.js → chunk-WR6KFJKA.js} +7 -7
  95. package/dist/{chunk-YQGHW5ML.js → chunk-WRFKZEO6.js} +4 -4
  96. package/dist/{chunk-SJGTY2TW.js → chunk-XUNQLJT2.js} +6 -6
  97. package/dist/{chunk-P7IDNF7H.js → chunk-XWT4JXXA.js} +2 -2
  98. package/dist/{chunk-MSUA4KAK.js → chunk-XXA6T3O4.js} +2 -2
  99. package/dist/{chunk-KF74X62T.js → chunk-YGKUAX2B.js} +4 -4
  100. package/dist/{chunk-YWYZPKK3.js → chunk-YOZNTNNA.js} +2 -2
  101. package/dist/{chunk-U62ZGWU7.js → chunk-ZXUOAFUG.js} +1 -1
  102. package/dist/chunk-ZXUOAFUG.js.map +1 -0
  103. package/dist/{cli-CxtZyBLl.d.ts → cli-DBDgdvh9.d.ts} +3 -3
  104. package/dist/cli.d.ts +11 -10
  105. package/dist/cli.js +56 -50
  106. package/dist/compounding/engine.d.ts +1 -1
  107. package/dist/compounding/engine.js +12 -5
  108. package/dist/compounding/preference-consolidator.d.ts +1 -1
  109. package/dist/compression-optimizer.d.ts +1 -1
  110. package/dist/config.d.ts +1 -1
  111. package/dist/config.js +1 -1
  112. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  113. package/dist/connectors/codex-materialize-runner.js +12 -5
  114. package/dist/connectors/codex-materialize.d.ts +1 -1
  115. package/dist/connectors/index.d.ts +1 -1
  116. package/dist/connectors/index.js +12 -5
  117. package/dist/consolidation-provenance-check.d.ts +3 -3
  118. package/dist/consolidation-undo.d.ts +2 -2
  119. package/dist/contradiction/index.d.ts +1 -1
  120. package/dist/conversation-index/backend.d.ts +1 -1
  121. package/dist/conversation-index/chunker.d.ts +1 -1
  122. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  123. package/dist/conversation-index/indexer.d.ts +1 -1
  124. package/dist/conversation-index/search.d.ts +1 -1
  125. package/dist/day-summary.d.ts +1 -1
  126. package/dist/delinearize.d.ts +1 -1
  127. package/dist/direct-answer-wiring.d.ts +1 -1
  128. package/dist/direct-answer.d.ts +1 -1
  129. package/dist/embedding-fallback.d.ts +1 -1
  130. package/dist/enrichment/index.d.ts +1 -1
  131. package/dist/entity-retrieval.d.ts +1 -1
  132. package/dist/entity-retrieval.js +13 -5
  133. package/dist/entity-schema.d.ts +1 -1
  134. package/dist/explicit-capture.d.ts +9 -8
  135. package/dist/extraction-faithfulness.d.ts +211 -0
  136. package/dist/extraction-faithfulness.js +35 -0
  137. package/dist/extraction-judge-telemetry.d.ts +1 -1
  138. package/dist/extraction-judge-training.d.ts +1 -1
  139. package/dist/extraction-judge.d.ts +1 -1
  140. package/dist/extraction-judge.js +4 -4
  141. package/dist/extraction.d.ts +1 -1
  142. package/dist/extraction.js +7 -7
  143. package/dist/fallback-llm.d.ts +1 -1
  144. package/dist/fallback-llm.js +2 -2
  145. package/dist/{graph-edge-decay-D7OESCBR.js → graph-edge-decay-JLOF3YW4.js} +3 -3
  146. package/dist/graph-snapshot.js +3 -3
  147. package/dist/graph.js +2 -2
  148. package/dist/identity-continuity.d.ts +1 -1
  149. package/dist/importance.d.ts +1 -1
  150. package/dist/index.d.ts +12 -11
  151. package/dist/index.js +96 -95
  152. package/dist/index.js.map +1 -1
  153. package/dist/intent.d.ts +1 -1
  154. package/dist/lcm/engine.d.ts +1 -1
  155. package/dist/lcm/index.d.ts +1 -1
  156. package/dist/lcm/index.js +3 -3
  157. package/dist/lcm/tools.d.ts +1 -1
  158. package/dist/lifecycle.d.ts +1 -1
  159. package/dist/live-connectors-runner.d.ts +1 -1
  160. package/dist/local-llm.d.ts +1 -1
  161. package/dist/local-llm.js +1 -1
  162. package/dist/maintenance/memory-governance.d.ts +1 -1
  163. package/dist/maintenance/memory-governance.js +13 -5
  164. package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -5
  165. package/dist/maintenance/rebuild-memory-projection.js +14 -6
  166. package/dist/mcp-memory-inspector-app.d.ts +12 -11
  167. package/dist/memory-action-policy.d.ts +1 -1
  168. package/dist/memory-cache.d.ts +1 -1
  169. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  170. package/dist/memory-projection-store.d.ts +1 -1
  171. package/dist/memory-provenance.d.ts +1 -1
  172. package/dist/memory-worth-outcomes.d.ts +1 -1
  173. package/dist/models-json.d.ts +1 -1
  174. package/dist/namespaces/migrate.d.ts +2 -2
  175. package/dist/namespaces/migrate.js +20 -12
  176. package/dist/namespaces/principal.d.ts +1 -1
  177. package/dist/namespaces/search.d.ts +1 -1
  178. package/dist/namespaces/search.js +6 -6
  179. package/dist/namespaces/storage.d.ts +2 -2
  180. package/dist/namespaces/storage.js +13 -5
  181. package/dist/native-knowledge.d.ts +1 -1
  182. package/dist/operator-toolkit.d.ts +1 -1
  183. package/dist/operator-toolkit.js +26 -19
  184. package/dist/orchestration/maintenance.d.ts +2 -2
  185. package/dist/orchestration/maintenance.js +15 -7
  186. package/dist/{orchestrator-CnbxRQs8.d.ts → orchestrator-Dv8JQu3-.d.ts} +20 -3
  187. package/dist/orchestrator.d.ts +6 -5
  188. package/dist/orchestrator.js +47 -46
  189. package/dist/patterns-cli.d.ts +1 -1
  190. package/dist/policy-runtime.d.ts +1 -1
  191. package/dist/provenance.d.ts +1 -1
  192. package/dist/qmd-recall-cache.d.ts +1 -1
  193. package/dist/qmd.d.ts +1 -1
  194. package/dist/recall-disclosure-escalation.d.ts +1 -1
  195. package/dist/recall-explain-renderer.d.ts +1 -1
  196. package/dist/recall-explain-renderer.js +3 -3
  197. package/dist/recall-planner-llm.d.ts +1 -1
  198. package/dist/recall-planner-llm.js +2 -2
  199. package/dist/recall-state.d.ts +1 -1
  200. package/dist/recall-tag-filter.d.ts +1 -1
  201. package/dist/recall-xray-cli.d.ts +1 -1
  202. package/dist/recall-xray-cli.js +4 -4
  203. package/dist/recall-xray-renderer.d.ts +1 -1
  204. package/dist/recall-xray-renderer.js +3 -3
  205. package/dist/recall-xray.d.ts +1 -1
  206. package/dist/recall-xray.js +2 -2
  207. package/dist/resolve-auth-token.d.ts +1 -1
  208. package/dist/resume-bundles.js +2 -2
  209. package/dist/retrieval-agents.d.ts +1 -1
  210. package/dist/retrieval-tiers.d.ts +1 -1
  211. package/dist/routing/engine.d.ts +1 -1
  212. package/dist/routing/store.d.ts +1 -1
  213. package/dist/search/embed-helper.d.ts +1 -1
  214. package/dist/search/factory.d.ts +1 -1
  215. package/dist/search/factory.js +5 -5
  216. package/dist/search/index.d.ts +1 -1
  217. package/dist/search/index.js +5 -5
  218. package/dist/search/lancedb-backend.d.ts +1 -1
  219. package/dist/search/lancedb-backend.js +2 -2
  220. package/dist/search/meilisearch-backend.d.ts +1 -1
  221. package/dist/search/meilisearch-backend.js +2 -2
  222. package/dist/search/noop-backend.d.ts +1 -1
  223. package/dist/search/orama-backend.d.ts +1 -1
  224. package/dist/search/orama-backend.js +2 -2
  225. package/dist/search/port.d.ts +1 -1
  226. package/dist/search/remote-backend.d.ts +1 -1
  227. package/dist/{semantic-consolidation-DXmtQ_4B.d.ts → semantic-consolidation-CgREi9E0.d.ts} +1 -1
  228. package/dist/semantic-consolidation.d.ts +2 -2
  229. package/dist/semantic-consolidation.js +13 -6
  230. package/dist/semantic-rule-promotion.js +13 -5
  231. package/dist/semantic-rule-verifier.d.ts +1 -1
  232. package/dist/semantic-rule-verifier.js +13 -5
  233. package/dist/session-observer-bands.d.ts +1 -1
  234. package/dist/session-observer-state.d.ts +1 -1
  235. package/dist/shared-context/manager.d.ts +1 -1
  236. package/dist/signal.d.ts +1 -1
  237. package/dist/{state-NCHQ4TRG.js → state-ITXJKXRE.js} +2 -2
  238. package/dist/storage.d.ts +11 -1
  239. package/dist/storage.js +12 -4
  240. package/dist/summarizer.d.ts +1 -1
  241. package/dist/summarizer.js +6 -6
  242. package/dist/summary-snapshot.d.ts +1 -1
  243. package/dist/temporal-supersession.d.ts +1 -1
  244. package/dist/temporal-validity.d.ts +1 -1
  245. package/dist/threading.d.ts +1 -1
  246. package/dist/tier-migration.d.ts +1 -1
  247. package/dist/tier-routing.d.ts +1 -1
  248. package/dist/topics.d.ts +1 -1
  249. package/dist/{trace-WM7V4CKI.js → trace-ZFVRH4GO.js} +3 -3
  250. package/dist/transcript.d.ts +1 -1
  251. package/dist/transfer/backup.js +2 -2
  252. package/dist/transfer/capsule-export.js +2 -2
  253. package/dist/transfer/capsule-import.js +2 -2
  254. package/dist/{tui-RI7P6PBS.js → tui-55UJMJX7.js} +3 -3
  255. package/dist/tui-55UJMJX7.js.map +1 -0
  256. package/dist/{types-CEWBmjCH.d.ts → types-CeZYSC-E.d.ts} +37 -1
  257. package/dist/types.d.ts +1 -1
  258. package/dist/types.js +1 -1
  259. package/dist/utility-runtime.d.ts +1 -1
  260. package/dist/verified-recall.js +13 -5
  261. package/package.json +2 -2
  262. package/src/config.test.ts +16 -0
  263. package/src/config.ts +30 -0
  264. package/src/console/state.ts +32 -0
  265. package/src/extraction-faithfulness.test.ts +1112 -0
  266. package/src/extraction-faithfulness.ts +993 -0
  267. package/src/faithfulness-graph-guard.test.ts +252 -0
  268. package/src/local-llm.ts +1 -0
  269. package/src/orchestrator.ts +169 -45
  270. package/src/storage.ts +19 -0
  271. package/src/types.ts +47 -0
  272. package/dist/chunk-C5AOVGVC.js.map +0 -1
  273. package/dist/chunk-NXNUG7IA.js.map +0 -1
  274. package/dist/chunk-PNW4KKJX.js.map +0 -1
  275. package/dist/chunk-TYEOAFH3.js.map +0 -1
  276. package/dist/chunk-U62ZGWU7.js.map +0 -1
  277. package/dist/chunk-UPTZYUYJ.js.map +0 -1
  278. /package/dist/{auto-sync-RWXT6P5M.js.map → auto-sync-PFW2NJZY.js.map} +0 -0
  279. /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
  280. /package/dist/{chunk-FCH766FX.js.map → chunk-32XTY2DQ.js.map} +0 -0
  281. /package/dist/{chunk-YN4ZT4CW.js.map → chunk-3LYJIA76.js.map} +0 -0
  282. /package/dist/{chunk-24FCDBJV.js.map → chunk-3P2XEQSV.js.map} +0 -0
  283. /package/dist/{chunk-JIKBEDSB.js.map → chunk-4NNDJOAO.js.map} +0 -0
  284. /package/dist/{chunk-EPVIBPVE.js.map → chunk-52QIAN76.js.map} +0 -0
  285. /package/dist/{chunk-TAPSNIMA.js.map → chunk-5CEJH5ZN.js.map} +0 -0
  286. /package/dist/{chunk-4RGWCRIJ.js.map → chunk-5TYA4OCF.js.map} +0 -0
  287. /package/dist/{chunk-PILLH262.js.map → chunk-6GAUF4OU.js.map} +0 -0
  288. /package/dist/{chunk-QXWQ5V24.js.map → chunk-AF6DSAWD.js.map} +0 -0
  289. /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
  290. /package/dist/{chunk-32KD5IHZ.js.map → chunk-CLXTDOKV.js.map} +0 -0
  291. /package/dist/{chunk-ARV3AUOM.js.map → chunk-DL6H3D7S.js.map} +0 -0
  292. /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
  293. /package/dist/{chunk-KCRV3HVN.js.map → chunk-EC3A6M43.js.map} +0 -0
  294. /package/dist/{chunk-YI3KC2B5.js.map → chunk-FZMH66NT.js.map} +0 -0
  295. /package/dist/{chunk-DT2ZGQT7.js.map → chunk-G663XUEG.js.map} +0 -0
  296. /package/dist/{chunk-CDOIDOTQ.js.map → chunk-HKET3ZOI.js.map} +0 -0
  297. /package/dist/{chunk-YOI3ELXF.js.map → chunk-IF362TF6.js.map} +0 -0
  298. /package/dist/{chunk-UX5QTAFE.js.map → chunk-J45OCIVH.js.map} +0 -0
  299. /package/dist/{chunk-UDJLF3BO.js.map → chunk-JI6HWBYL.js.map} +0 -0
  300. /package/dist/{chunk-ECZPWSB5.js.map → chunk-JJT3AGL4.js.map} +0 -0
  301. /package/dist/{chunk-6C4WHMKV.js.map → chunk-JMAKCWJ3.js.map} +0 -0
  302. /package/dist/{chunk-4NFVPDIL.js.map → chunk-LM6JB2EG.js.map} +0 -0
  303. /package/dist/{chunk-MOGFK2DU.js.map → chunk-LPIWEKZ3.js.map} +0 -0
  304. /package/dist/{chunk-LD53WPMU.js.map → chunk-LQ6JI4VH.js.map} +0 -0
  305. /package/dist/{chunk-IZLNJYLX.js.map → chunk-MNFAGE5D.js.map} +0 -0
  306. /package/dist/{chunk-5A35EGHM.js.map → chunk-N4PD5IY3.js.map} +0 -0
  307. /package/dist/{chunk-PQP6MFPL.js.map → chunk-NFMDHE45.js.map} +0 -0
  308. /package/dist/{chunk-WVTNZUER.js.map → chunk-NLZO5NO6.js.map} +0 -0
  309. /package/dist/{chunk-5S53ZBPH.js.map → chunk-Q6ZHGGNJ.js.map} +0 -0
  310. /package/dist/{chunk-SN5DFE34.js.map → chunk-Q7SFJURX.js.map} +0 -0
  311. /package/dist/{chunk-MXZWKOOR.js.map → chunk-QJM2XAJD.js.map} +0 -0
  312. /package/dist/{chunk-6ZNIUGXB.js.map → chunk-QQW2LIEA.js.map} +0 -0
  313. /package/dist/{chunk-ZKD3UVEO.js.map → chunk-QVTSLRKT.js.map} +0 -0
  314. /package/dist/{chunk-YXZPKBFW.js.map → chunk-SPVIG2R3.js.map} +0 -0
  315. /package/dist/{chunk-B55EAZNF.js.map → chunk-TIVZ4MCG.js.map} +0 -0
  316. /package/dist/{chunk-5KBNNUXS.js.map → chunk-TT7BJWGI.js.map} +0 -0
  317. /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
  318. /package/dist/{chunk-E6BOD3UJ.js.map → chunk-VPAFWWCL.js.map} +0 -0
  319. /package/dist/{chunk-D7PQ7HZL.js.map → chunk-W54EAJT4.js.map} +0 -0
  320. /package/dist/{chunk-QVG4LAQO.js.map → chunk-WR6KFJKA.js.map} +0 -0
  321. /package/dist/{chunk-YQGHW5ML.js.map → chunk-WRFKZEO6.js.map} +0 -0
  322. /package/dist/{chunk-SJGTY2TW.js.map → chunk-XUNQLJT2.js.map} +0 -0
  323. /package/dist/{chunk-P7IDNF7H.js.map → chunk-XWT4JXXA.js.map} +0 -0
  324. /package/dist/{chunk-MSUA4KAK.js.map → chunk-XXA6T3O4.js.map} +0 -0
  325. /package/dist/{chunk-KF74X62T.js.map → chunk-YGKUAX2B.js.map} +0 -0
  326. /package/dist/{chunk-YWYZPKK3.js.map → chunk-YOZNTNNA.js.map} +0 -0
  327. /package/dist/{state-NCHQ4TRG.js.map → extraction-faithfulness.js.map} +0 -0
  328. /package/dist/{graph-edge-decay-D7OESCBR.js.map → graph-edge-decay-JLOF3YW4.js.map} +0 -0
  329. /package/dist/{tui-RI7P6PBS.js.map → state-ITXJKXRE.js.map} +0 -0
  330. /package/dist/{trace-WM7V4CKI.js.map → trace-ZFVRH4GO.js.map} +0 -0
@@ -0,0 +1,252 @@
1
+ /**
2
+ * Issue #1576 — pending-review facts must NOT originate graph edges.
3
+ *
4
+ * When `extractionFaithfulnessGate="enforce"` routes an unsupported or
5
+ * contradicted fact to `pending_review`, the persist path still builds entity
6
+ * edges via `GraphIndex.onMemoryWritten`, so an unfaithful extraction in the
7
+ * review queue could change graph traversal/ranking for active memories even
8
+ * though direct recall filters later drop the pending file. The guard mirrors
9
+ * the existing supersession/promotion/artifact guards (codex P2
10
+ * PRRT_kwDORJXyws6OblI1's sibling thread PRRT_kwDORJXyws6OblI0).
11
+ *
12
+ * These tests exercise the real `persistExtraction` path end-to-end (no LLM
13
+ * network — the local LLM is stubbed to return controlled verdicts) and read
14
+ * the entity graph JSONL directly to prove the guard.
15
+ */
16
+
17
+ import assert from "node:assert/strict";
18
+ import os from "node:os";
19
+ import path from "node:path";
20
+ import { mkdtemp, rm } from "node:fs/promises";
21
+ import test from "node:test";
22
+
23
+ import { parseConfig } from "./config.js";
24
+ import { Orchestrator } from "./orchestrator.js";
25
+ import { readEdges } from "./graph.js";
26
+ import type { ExtractionResult, PluginConfig } from "./types.js";
27
+ import type { LocalLlmClient } from "./local-llm.js";
28
+
29
+ /**
30
+ * Stub local LLM whose `chatCompletion` only answers faithfulness-gate calls
31
+ * (operation === "extraction-faithfulness"). The verdict is chosen by a marker
32
+ * in the fact text so each persisted fact gets a deterministic, controllable
33
+ * verdict with no network. Non-faithfulness calls return null (fail-open skip).
34
+ */
35
+ function faithfulnessStubLocalLlm(
36
+ verdictForFactContent: (factContent: string) => "entailed" | "unsupported",
37
+ ): LocalLlmClient {
38
+ return {
39
+ chatCompletion: async (
40
+ messages: Array<{ role: string; content: string }>,
41
+ options: { operation?: string } = {},
42
+ ) => {
43
+ if (options.operation !== "extraction-faithfulness") return null;
44
+ const userMsg = messages.find((m) => m.role === "user");
45
+ // The prompt emits `FACT: "<text>"` — fact text never contains a raw
46
+ // double-quote, so capture up to the closing quote.
47
+ const match = userMsg?.content.match(/FACT: "([^"]*)"/);
48
+ const factContent = match ? (match[1] ?? "") : "";
49
+ const verdict = verdictForFactContent(factContent);
50
+ return {
51
+ content: JSON.stringify([
52
+ { index: 0, verdict, rationale: "stub verdict" },
53
+ ]),
54
+ };
55
+ },
56
+ } as unknown as LocalLlmClient;
57
+ }
58
+
59
+ interface OrchHarness {
60
+ orchestrator: Orchestrator;
61
+ memoryDir: string;
62
+ }
63
+
64
+ async function makeHarness(): Promise<OrchHarness> {
65
+ const memoryDir = await mkdtemp(
66
+ path.join(os.tmpdir(), "remnic-faithfulness-graph-"),
67
+ );
68
+ const config: PluginConfig = parseConfig({
69
+ openaiApiKey: "sk-test",
70
+ memoryDir,
71
+ workspaceDir: path.join(memoryDir, "workspace"),
72
+ // Graph: entity only (isolate the assertion; time/causal off).
73
+ multiGraphMemoryEnabled: true,
74
+ entityGraphEnabled: true,
75
+ timeGraphEnabled: false,
76
+ causalGraphEnabled: false,
77
+ // Faithfulness gate in enforce mode.
78
+ extractionFaithfulnessGate: "enforce",
79
+ extractionFaithfulnessContextChars: 400,
80
+ extractionFaithfulnessTimeoutMs: 2000,
81
+ // Minimize competing gates so the fact reaches the write + graph stage.
82
+ extractionJudgeEnabled: false,
83
+ temporalSupersessionEnabled: false,
84
+ contradictionDetectionEnabled: false,
85
+ chunkingEnabled: false,
86
+ embeddingFallbackEnabled: false,
87
+ qmdEnabled: false,
88
+ extractionMinChars: 0,
89
+ extractionMinImportanceLevel: "trivial",
90
+ inlineSourceAttributionEnabled: false,
91
+ });
92
+ const orchestrator = new Orchestrator(config);
93
+ return { orchestrator, memoryDir };
94
+ }
95
+
96
+ function factResult(content: string, entityRef: string): ExtractionResult {
97
+ return {
98
+ facts: [
99
+ {
100
+ content,
101
+ category: "fact",
102
+ tags: [],
103
+ confidence: 0.9,
104
+ entityRef,
105
+ },
106
+ ],
107
+ entities: [],
108
+ relationships: [],
109
+ questions: [],
110
+ profileUpdates: [],
111
+ } as unknown as ExtractionResult;
112
+ }
113
+
114
+ test("pending_review fact gets no graph edge; an active fact with the same entityRef does (faithfulness #1576 guard)", async () => {
115
+ const { orchestrator, memoryDir } = await makeHarness();
116
+ try {
117
+ // fact0 → entailed (active). Establishes entityRef "widget-factory" so the
118
+ // next E1 fact has a sibling to edge to. Alone, fact0 has no sibling yet.
119
+ (orchestrator as unknown as { localLlm: LocalLlmClient }).localLlm =
120
+ faithfulnessStubLocalLlm((c) =>
121
+ c.includes("closed permanently") ? "unsupported" : "entailed",
122
+ );
123
+ const storage = await (orchestrator as unknown as {
124
+ getStorage: (ns: string) => Promise<{
125
+ ensureDirectories: () => Promise<void>;
126
+ readAllMemories: () => Promise<
127
+ Array<{
128
+ path: string;
129
+ frontmatter: { id: string; status?: string };
130
+ }>
131
+ >;
132
+ }>;
133
+ }).getStorage("default");
134
+ await storage.ensureDirectories();
135
+
136
+ const sourceText =
137
+ "The widget factory produces widgets. It launched last year. The team is small.";
138
+
139
+ const ids0 = await (orchestrator as unknown as {
140
+ persistExtraction: (
141
+ r: ExtractionResult,
142
+ s: unknown,
143
+ t: unknown,
144
+ ctx: unknown,
145
+ bn: unknown,
146
+ plan: unknown,
147
+ src: string,
148
+ ) => Promise<string[]>;
149
+ }).persistExtraction(
150
+ factResult("The widget factory produces widgets daily.", "widget-factory"),
151
+ storage,
152
+ null,
153
+ { sessionKey: "agent:test:main", principal: "test" },
154
+ undefined,
155
+ null,
156
+ sourceText,
157
+ );
158
+ const id0 = ids0[0];
159
+ assert.ok(id0, "fact0 persisted");
160
+
161
+ // fact1 → unsupported (pending_review). Under the bug it would originate an
162
+ // entity edge to fact0; under the guard it must NOT.
163
+ const ids1 = await (orchestrator as unknown as {
164
+ persistExtraction: (
165
+ r: ExtractionResult,
166
+ s: unknown,
167
+ t: unknown,
168
+ ctx: unknown,
169
+ bn: unknown,
170
+ plan: unknown,
171
+ src: string,
172
+ ) => Promise<string[]>;
173
+ }).persistExtraction(
174
+ factResult(
175
+ "The widget factory closed permanently.",
176
+ "widget-factory",
177
+ ),
178
+ storage,
179
+ null,
180
+ { sessionKey: "agent:test:main", principal: "test" },
181
+ undefined,
182
+ null,
183
+ sourceText,
184
+ );
185
+ const id1 = ids1[0];
186
+ assert.ok(id1, "fact1 persisted");
187
+
188
+ // fact1 must be written with status pending_review (the gate ran).
189
+ const memsAfter1 = await storage.readAllMemories();
190
+ const mem1 = memsAfter1.find((m) => m.frontmatter.id === id1);
191
+ assert.ok(mem1, "fact1 memory readable");
192
+ assert.equal(
193
+ mem1!.frontmatter.status,
194
+ "pending_review",
195
+ "unsupported fact must be pending_review under enforce",
196
+ );
197
+
198
+ // After fact0 + fact1: NO entity edges at all. fact0 had no E1 sibling when
199
+ // written; fact1 is pending_review and must be guarded out of the graph.
200
+ const edgesAfter1 = await readEdges(memoryDir, "entity");
201
+ assert.equal(
202
+ edgesAfter1.length,
203
+ 0,
204
+ `pending_review fact must originate no graph edge (got ${edgesAfter1.length} entity edges)`,
205
+ );
206
+ assert.ok(
207
+ !edgesAfter1.some((e) => e.from.includes(id1!) || e.from.includes(id0!)),
208
+ "neither fact0 nor fact1 originates an entity edge",
209
+ );
210
+
211
+ // Control: an ACTIVE fact with the same entityRef DOES create entity edges
212
+ // (proving the graph is wired and only pending_review is excluded).
213
+ const ids2 = await (orchestrator as unknown as {
214
+ persistExtraction: (
215
+ r: ExtractionResult,
216
+ s: unknown,
217
+ t: unknown,
218
+ ctx: unknown,
219
+ bn: unknown,
220
+ plan: unknown,
221
+ src: string,
222
+ ) => Promise<string[]>;
223
+ }).persistExtraction(
224
+ factResult("The widget factory reopened this quarter.", "widget-factory"),
225
+ storage,
226
+ null,
227
+ { sessionKey: "agent:test:main", principal: "test" },
228
+ undefined,
229
+ null,
230
+ sourceText,
231
+ );
232
+ const id2 = ids2[0];
233
+ assert.ok(id2, "fact2 persisted");
234
+
235
+ const edgesAfter2 = await readEdges(memoryDir, "entity");
236
+ assert.ok(
237
+ edgesAfter2.length > 0,
238
+ "active fact with a shared entityRef must create entity edges (control)",
239
+ );
240
+ // fact2 (active) originates edges; fact1 (pending_review) never does.
241
+ assert.ok(
242
+ edgesAfter2.some((e) => e.from.includes(id2!)),
243
+ "active fact2 must be the source of an entity edge",
244
+ );
245
+ assert.ok(
246
+ !edgesAfter2.some((e) => e.from.includes(id1!)),
247
+ "pending_review fact1 must never originate an entity edge even after a later active fact",
248
+ );
249
+ } finally {
250
+ await rm(memoryDir, { recursive: true, force: true });
251
+ }
252
+ });
package/src/local-llm.ts CHANGED
@@ -131,6 +131,7 @@ const THINKING_COMPATIBLE_BACKENDS: ReadonlySet<LocalLlmType> = new Set([
131
131
  const THINKING_SUPPRESSED_OPERATIONS: ReadonlySet<string> = new Set([
132
132
  "extraction",
133
133
  "extraction-judge",
134
+ "extraction-faithfulness",
134
135
  "contradiction-judge",
135
136
  "contradiction_verification",
136
137
  "link_suggestion",
@@ -35,6 +35,12 @@ import {
35
35
  type JudgeCandidate,
36
36
  type JudgeVerdict,
37
37
  } from "./extraction-judge.js";
38
+ import {
39
+ applyFaithfulnessVerdict,
40
+ createFaithfulnessCounters,
41
+ runFaithfulnessGateBatch,
42
+ } from "./extraction-faithfulness.js";
43
+ import type { FaithfulnessGateCounters } from "./extraction-faithfulness.js";
38
44
  import {
39
45
  EXTRACTION_JUDGE_VERDICT_CATEGORY,
40
46
  recordJudgeVerdict,
@@ -1828,6 +1834,12 @@ export class Orchestrator {
1828
1834
  * hash so the defer cap can be enforced.
1829
1835
  */
1830
1836
  private readonly judgeDeferCounts: Map<string, number>;
1837
+ /**
1838
+ * Faithfulness gate distribution counters (issue #1576). Per-orchestrator
1839
+ * running tally surfaced via console_state telemetry. No module-level state
1840
+ * (rule 11) — these hang off the orchestrator instance.
1841
+ */
1842
+ private faithfulnessCounters: FaithfulnessGateCounters = createFaithfulnessCounters();
1831
1843
  /**
1832
1844
  * Side-channel: number of facts deferred in the most recent
1833
1845
  * `persistExtraction` call (issue #562, PR 2). The caller reads this after
@@ -1841,6 +1853,20 @@ export class Orchestrator {
1841
1853
  get fastGatewayLlm(): FallbackLlmClient | null {
1842
1854
  return this._fastGatewayLlm;
1843
1855
  }
1856
+
1857
+ /**
1858
+ * Faithfulness gate verdict distribution (issue #1576). Consumed by the
1859
+ * console-state aggregator so `remnic doctor` can render how the gate is
1860
+ * performing. Returns a fresh object so callers cannot mutate the
1861
+ * internal counters. Returns `undefined` when the gate is off so the
1862
+ * console-state snapshot omits the faithfulness block entirely (cursor
1863
+ * review: an all-zero block would otherwise always be truthy and leak
1864
+ * into snapshots that document it as absent-when-off).
1865
+ */
1866
+ getConsoleFaithfulnessDistribution(): FaithfulnessGateCounters | undefined {
1867
+ if (this.config.extractionFaithfulnessGate === "off") return undefined;
1868
+ return { ...this.faithfulnessCounters };
1869
+ }
1844
1870
  readonly modelRegistry: ModelRegistry;
1845
1871
  readonly relevance: RelevanceStore;
1846
1872
  readonly negatives: NegativeExampleStore;
@@ -13247,6 +13273,9 @@ export class Orchestrator {
13247
13273
  // real namespace rather than a guess decoded from the storage dir.
13248
13274
  selfNamespace,
13249
13275
  scopeProfileGatePlan,
13276
+ // Verbatim source turns for the faithfulness gate (#1576) so it can
13277
+ // locate a quote per fact when #1575 spans are absent.
13278
+ normalizedTurns.map((t) => t.content).join("\n\n"),
13250
13279
  );
13251
13280
  let postPersistMetadataFailed = false;
13252
13281
  meta ??= await storage.loadMeta();
@@ -13693,6 +13722,8 @@ export class Orchestrator {
13693
13722
  sourceContext?: { sessionKey?: string; principal?: string; validAt?: string },
13694
13723
  baseNamespace?: string,
13695
13724
  scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,
13725
+ /** Verbatim source turn text the facts were extracted from (faithfulness gate #1576). */
13726
+ sourceText?: string,
13696
13727
  graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),
13697
13728
  ): Promise<string[]> {
13698
13729
  // Inline source attribution (issue #369). When enabled, every extracted
@@ -14577,6 +14608,29 @@ export class Orchestrator {
14577
14608
  }
14578
14609
  }
14579
14610
 
14611
+ // Faithfulness gate (issue #1576). Entailment-verification of extracted
14612
+ // facts against their verified source spans from #1575. Placement: after
14613
+ // parse + provenance validation, BEFORE persist/index (rule 44). The
14614
+ // substantive batch logic lives in the pure module; this is thin
14615
+ // delegation (ground rule 4). off → null map (byte-identical pre-feature
14616
+ // pipeline, rule 39); shadow → record only; enforce → pending_review.
14617
+ const faithfulnessMode = this.config.extractionFaithfulnessGate;
14618
+ const faithfulnessResultsByFactIndex =
14619
+ faithfulnessMode === "shadow" || faithfulnessMode === "enforce"
14620
+ ? await runFaithfulnessGateBatch(
14621
+ facts,
14622
+ faithfulnessMode,
14623
+ this.config,
14624
+ this.localLlm,
14625
+ new FallbackLlmClient(
14626
+ this.config.gatewayConfig,
14627
+ fallbackLlmRuntimeContextFromConfig(this.config),
14628
+ ),
14629
+ this.faithfulnessCounters,
14630
+ sourceText,
14631
+ )
14632
+ : null;
14633
+
14580
14634
  let factLoopIndex = -1;
14581
14635
  for (const fact of facts) {
14582
14636
  factLoopIndex++;
@@ -14813,6 +14867,19 @@ export class Orchestrator {
14813
14867
  }
14814
14868
  }
14815
14869
 
14870
+ // Faithfulness gate verdict application (issue #1576). Look up the
14871
+ // pre-computed verdict for this fact and translate it to frontmatter +
14872
+ // an optional enforce-mode pending_review status. Logic lives in the
14873
+ // pure module; this is thin read-through (ground rule 4).
14874
+ const { faithfulness: faithfulnessFm, enforceStatus: faithfulnessEnforceStatus } =
14875
+ applyFaithfulnessVerdict(
14876
+ faithfulnessResultsByFactIndex,
14877
+ factLoopIndex,
14878
+ faithfulnessMode,
14879
+ fact.content,
14880
+ this.faithfulnessCounters,
14881
+ );
14882
+
14816
14883
  // Issue #373 — write-time semantic similarity guard. Hook runs after
14817
14884
  // the exact content-hash miss and the importance gate so that:
14818
14885
  // (a) paraphrased near-duplicates never reach writeMemory(), and
@@ -14903,7 +14970,14 @@ export class Orchestrator {
14903
14970
  // memory without user confirmation).
14904
14971
  let contradictionDetected = false;
14905
14972
 
14906
- if (this.config.contradictionDetectionEnabled && this.qmd.isAvailable()) {
14973
+ // Faithfulness gate (#1576, chatgpt P2): skip contradiction detection
14974
+ // for a pending_review fact — an unfaithful extraction in the review queue
14975
+ // must not trigger auto-resolve and retire an existing active memory.
14976
+ if (
14977
+ this.config.contradictionDetectionEnabled &&
14978
+ this.qmd.isAvailable() &&
14979
+ faithfulnessEnforceStatus !== "pending_review"
14980
+ ) {
14907
14981
  const targetNamespace = this.namespaceFromStorageDir(targetStorage.dir);
14908
14982
  const contradiction = await this.checkForContradiction(
14909
14983
  fact.content,
@@ -14968,7 +15042,16 @@ export class Orchestrator {
14968
15042
  // dropped, leaving a stale fact active. writeCategory (not fact.category)
14969
15043
  // is used because routing rules may have overridden the raw category.
14970
15044
  const isCorrection = writeCategory === "correction";
14971
- if (pendingSemanticSkip && !contradictionDetected && !isCorrection) {
15045
+ // Faithfulness gate (#1576, cursor High): a pending_review fact must
15046
+ // bypass the semantic-dedup skip so it reaches the review queue — the
15047
+ // gate's contract is "persists with status: pending_review, never
15048
+ // silently dropped" (issue #1576).
15049
+ if (
15050
+ pendingSemanticSkip &&
15051
+ !contradictionDetected &&
15052
+ !isCorrection &&
15053
+ faithfulnessEnforceStatus !== "pending_review"
15054
+ ) {
14972
15055
  log.debug(
14973
15056
  `dedup: skipping semantic near-duplicate fact "${fact.content
14974
15057
  .slice(0, 60)
@@ -15067,6 +15150,9 @@ export class Orchestrator {
15067
15150
  structuredAttributes: fact.structuredAttributes,
15068
15151
  validAt: sourceContext?.validAt,
15069
15152
  contentHashSource: rawChunkedContent,
15153
+ // Faithfulness gate (issue #1576).
15154
+ ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
15155
+ ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
15070
15156
  },
15071
15157
  );
15072
15158
  try {
@@ -15102,6 +15188,11 @@ export class Orchestrator {
15102
15188
  intentEntityTypes: inferredIntent?.entityTypes,
15103
15189
  memoryKind,
15104
15190
  validAt: sourceContext?.validAt,
15191
+ // Faithfulness gate (issue #1576): propagate the parent
15192
+ // fact's verdict + enforce status so a pending_review fact
15193
+ // is not indexed as active through its chunks (chatgpt P2).
15194
+ ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
15195
+ ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
15105
15196
  },
15106
15197
  );
15107
15198
  }
@@ -15122,7 +15213,9 @@ export class Orchestrator {
15122
15213
  `chunked memory ${parentId} into ${chunkResult.chunks.length} chunks`,
15123
15214
  );
15124
15215
  trackPersistedId(targetStorage, parentId);
15216
+ // #1576 (cursor Medium): keep pending_review ids out of threadEpisodeIdsForGraph — else later active facts build thread-predecessor edges to an unfaithful memory.
15125
15217
  if (
15218
+ faithfulnessEnforceStatus !== "pending_review" &&
15126
15219
  threadEpisodeIdsForGraph &&
15127
15220
  !threadEpisodeIdsForGraph.includes(parentId)
15128
15221
  ) {
@@ -15132,23 +15225,31 @@ export class Orchestrator {
15132
15225
  // PR #402 Thread 1 fix: run source-namespace temporal supersession for
15133
15226
  // chunked writes, matching the non-chunked path. Without this the
15134
15227
  // source namespace retains stale facts that should have been superseded.
15135
- try {
15136
- const supersessionEntityRef =
15137
- typeof (fact as any).entityRef === "string"
15138
- ? ((fact as any).entityRef as string)
15139
- : undefined;
15140
- await applyTemporalSupersession({
15141
- storage: targetStorage,
15142
- newMemoryId: parentId,
15143
- entityRef: supersessionEntityRef,
15144
- structuredAttributes: fact.structuredAttributes,
15145
- createdAt: supersessionOrderingAt(sourceContext?.validAt),
15146
- enabled: this.config.temporalSupersessionEnabled,
15147
- });
15148
- } catch (err) {
15149
- log.warn(`temporal-supersession (chunked): unexpected error: ${err}`);
15228
+ // Faithfulness gate (#1576, cursor High): skip supersession for a
15229
+ // pending_review fact — an unfaithful extraction in the review queue
15230
+ // must NOT retire older active memories.
15231
+ if (faithfulnessEnforceStatus !== "pending_review") {
15232
+ try {
15233
+ const supersessionEntityRef =
15234
+ typeof (fact as any).entityRef === "string"
15235
+ ? ((fact as any).entityRef as string)
15236
+ : undefined;
15237
+ await applyTemporalSupersession({
15238
+ storage: targetStorage,
15239
+ newMemoryId: parentId,
15240
+ entityRef: supersessionEntityRef,
15241
+ structuredAttributes: fact.structuredAttributes,
15242
+ createdAt: supersessionOrderingAt(sourceContext?.validAt),
15243
+ enabled: this.config.temporalSupersessionEnabled,
15244
+ });
15245
+ } catch (err) {
15246
+ log.warn(`temporal-supersession (chunked): unexpected error: ${err}`);
15247
+ }
15150
15248
  }
15151
- await promoteMemoryToShared({
15249
+ // Faithfulness gate (#1576, chatgpt P2): do not promote a
15250
+ // pending_review fact to shared/profile — it must enter the review
15251
+ // queue without active copies that bypass the gate.
15252
+ if (faithfulnessEnforceStatus !== "pending_review") await promoteMemoryToShared({
15152
15253
  sourceStorage: targetStorage,
15153
15254
  category: writeCategory,
15154
15255
  content: fact.content,
@@ -15193,7 +15294,8 @@ export class Orchestrator {
15193
15294
  if (
15194
15295
  this.config.verbatimArtifactsEnabled &&
15195
15296
  this.config.verbatimArtifactCategories.includes(writeCategory) &&
15196
- fact.confidence >= this.config.verbatimArtifactsMinConfidence
15297
+ fact.confidence >= this.config.verbatimArtifactsMinConfidence &&
15298
+ faithfulnessEnforceStatus !== "pending_review"
15197
15299
  ) {
15198
15300
  // Reuse citedChunkedContent so the artifact carries the same citation
15199
15301
  // timestamp as the parent memory write above (Fix #3 — duplicate-citation).
@@ -15207,8 +15309,8 @@ export class Orchestrator {
15207
15309
  intentEntityTypes: inferredIntent?.entityTypes,
15208
15310
  });
15209
15311
  }
15210
- // v8.2: graph edge building for chunked memories
15211
- if (graphCaps.multiGraphMemory) {
15312
+ // v8.2: graph edge building for chunked memories. #1576: skip pending_review.
15313
+ if (graphCaps.multiGraphMemory && faithfulnessEnforceStatus !== "pending_review") {
15212
15314
  try {
15213
15315
  const graphContext = await ensureGraphContext(targetStorage);
15214
15316
  const entityRef =
@@ -15333,6 +15435,9 @@ export class Orchestrator {
15333
15435
  structuredAttributes: fact.structuredAttributes,
15334
15436
  validAt: sourceContext?.validAt,
15335
15437
  contentHashSource: writeCategory === "fact" ? fact.content : undefined,
15438
+ // Faithfulness gate (issue #1576).
15439
+ ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),
15440
+ ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),
15336
15441
  },
15337
15442
  );
15338
15443
  if (routedRuleId) {
@@ -15342,22 +15447,26 @@ export class Orchestrator {
15342
15447
  }
15343
15448
  // Temporal supersession (issue #375): when the new fact has structured
15344
15449
  // attributes, retire any older fact with the same entity + attribute
15345
- // key that has a conflicting value.
15346
- try {
15347
- const supersessionEntityRef =
15348
- typeof (fact as any).entityRef === "string"
15349
- ? ((fact as any).entityRef as string)
15350
- : undefined;
15351
- await applyTemporalSupersession({
15352
- storage: targetStorage,
15353
- newMemoryId: memoryId,
15354
- entityRef: supersessionEntityRef,
15355
- structuredAttributes: fact.structuredAttributes,
15356
- createdAt: supersessionOrderingAt(sourceContext?.validAt),
15357
- enabled: this.config.temporalSupersessionEnabled,
15358
- });
15359
- } catch (err) {
15360
- log.warn(`temporal-supersession: unexpected error: ${err}`);
15450
+ // key that has a conflicting value. Faithfulness gate (#1576, cursor
15451
+ // High): skip for a pending_review fact — an unfaithful extraction in
15452
+ // the review queue must NOT retire older active memories.
15453
+ if (faithfulnessEnforceStatus !== "pending_review") {
15454
+ try {
15455
+ const supersessionEntityRef =
15456
+ typeof (fact as any).entityRef === "string"
15457
+ ? ((fact as any).entityRef as string)
15458
+ : undefined;
15459
+ await applyTemporalSupersession({
15460
+ storage: targetStorage,
15461
+ newMemoryId: memoryId,
15462
+ entityRef: supersessionEntityRef,
15463
+ structuredAttributes: fact.structuredAttributes,
15464
+ createdAt: supersessionOrderingAt(sourceContext?.validAt),
15465
+ enabled: this.config.temporalSupersessionEnabled,
15466
+ });
15467
+ } catch (err) {
15468
+ log.warn(`temporal-supersession: unexpected error: ${err}`);
15469
+ }
15361
15470
  }
15362
15471
  try {
15363
15472
  trackBehaviorSignals(
@@ -15372,14 +15481,18 @@ export class Orchestrator {
15372
15481
  }),
15373
15482
  );
15374
15483
  trackPersistedId(targetStorage, memoryId);
15484
+ // #1576 (cursor Medium): same thread-episode guard on the non-chunked path.
15375
15485
  if (
15486
+ faithfulnessEnforceStatus !== "pending_review" &&
15376
15487
  threadEpisodeIdsForGraph &&
15377
15488
  !threadEpisodeIdsForGraph.includes(memoryId)
15378
15489
  ) {
15379
15490
  threadEpisodeIdsForGraph.push(memoryId);
15380
15491
  }
15381
15492
  await this.indexPersistedMemory(targetStorage, memoryId);
15382
- await promoteMemoryToShared({
15493
+ // Faithfulness gate (#1576, chatgpt P2): skip promotion for a
15494
+ // pending_review fact so no active shared/profile copy bypasses the gate.
15495
+ if (faithfulnessEnforceStatus !== "pending_review") await promoteMemoryToShared({
15383
15496
  sourceStorage: targetStorage,
15384
15497
  category: writeCategory,
15385
15498
  content: fact.content,
@@ -15399,8 +15512,8 @@ export class Orchestrator {
15399
15512
  validAt: sourceContext?.validAt,
15400
15513
  source: extractionWriteSource,
15401
15514
  });
15402
- // v8.2: graph edge building (fail-open errors caught inside GraphIndex)
15403
- if (graphCaps.multiGraphMemory) {
15515
+ // v8.2: graph edge building (fail-open). #1576: skip pending_review facts.
15516
+ if (graphCaps.multiGraphMemory && faithfulnessEnforceStatus !== "pending_review") {
15404
15517
  try {
15405
15518
  const graphContext = await ensureGraphContext(targetStorage);
15406
15519
  const entityRef =
@@ -15443,7 +15556,8 @@ export class Orchestrator {
15443
15556
  if (
15444
15557
  this.config.verbatimArtifactsEnabled &&
15445
15558
  this.config.verbatimArtifactCategories.includes(writeCategory) &&
15446
- fact.confidence >= this.config.verbatimArtifactsMinConfidence
15559
+ fact.confidence >= this.config.verbatimArtifactsMinConfidence &&
15560
+ faithfulnessEnforceStatus !== "pending_review"
15447
15561
  ) {
15448
15562
  // Reuse citedFactContent so the artifact carries the same citation
15449
15563
  // timestamp as the memory write above (Fix #3 — duplicate-citation).
@@ -16296,9 +16410,8 @@ export class Orchestrator {
16296
16410
  const tmtEntries = allMemories
16297
16411
  .filter(
16298
16412
  (m) =>
16299
- m.frontmatter.status !== "superseded" &&
16300
- m.frontmatter.status !== "archived" &&
16301
- m.frontmatter.status !== "forgotten",
16413
+ m.frontmatter.status !== "superseded" && m.frontmatter.status !== "archived" &&
16414
+ m.frontmatter.status !== "forgotten" && m.frontmatter.status !== "pending_review", // #1576: unfaithful queue items must not feed TMT clusters
16302
16415
  )
16303
16416
  .map((m) => ({
16304
16417
  path: m.path,
@@ -18965,7 +19078,18 @@ export class Orchestrator {
18965
19078
  }
18966
19079
  const memory = memoryByPath.get(r.path);
18967
19080
  if (memory) {
18968
- if (memory.frontmatter.status === "forgotten") {
19081
+ // Review-lifecycle statuses never enter active recall injection
19082
+ // (forgotten, pending_review, rejected, quarantined). Superseded and
19083
+ // archived have dedicated filters below. #1576: the faithfulness gate
19084
+ // routes unsupported/contradicted facts to pending_review — they must
19085
+ // not leak back via the QMD/embedding path. chatgpt P2.
19086
+ const recallStatus = memory.frontmatter.status;
19087
+ if (
19088
+ recallStatus === "forgotten" ||
19089
+ recallStatus === "pending_review" ||
19090
+ recallStatus === "rejected" ||
19091
+ recallStatus === "quarantined"
19092
+ ) {
18969
19093
  forgottenFilteredCount += 1;
18970
19094
  continue;
18971
19095
  }