@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.
- package/dist/access-boundary.d.ts +12 -11
- package/dist/access-boundary.js +34 -28
- package/dist/access-cli.js +60 -59
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +12 -11
- package/dist/access-http.js +38 -32
- package/dist/access-mcp.d.ts +12 -11
- package/dist/access-mcp.js +37 -31
- package/dist/access-operations.d.ts +12 -11
- package/dist/access-operations.js +36 -30
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-Ceq4TdPO.d.ts → access-service-BqBQeUJd.d.ts} +15 -2
- package/dist/access-service.d.ts +8 -7
- package/dist/access-service.js +33 -27
- package/dist/access-surface-catalog.d.ts +12 -11
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +1 -1
- package/dist/{auto-sync-RWXT6P5M.js → auto-sync-PFW2NJZY.js} +8 -8
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +9 -8
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +12 -5
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/calibration.js +2 -2
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
- package/dist/{catalog-Tkb991rg.d.ts → catalog-D7YDNNF7.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +17 -16
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-UPTZYUYJ.js → chunk-24D66MMN.js} +2 -1
- package/dist/chunk-24D66MMN.js.map +1 -0
- package/dist/{chunk-FCH766FX.js → chunk-32XTY2DQ.js} +51 -51
- package/dist/{chunk-YN4ZT4CW.js → chunk-3LYJIA76.js} +1 -1
- package/dist/{chunk-24FCDBJV.js → chunk-3P2XEQSV.js} +2 -2
- package/dist/{chunk-JIKBEDSB.js → chunk-4NNDJOAO.js} +8 -8
- package/dist/{chunk-EPVIBPVE.js → chunk-52QIAN76.js} +2 -2
- package/dist/chunk-5AT62NQH.js +553 -0
- package/dist/chunk-5AT62NQH.js.map +1 -0
- package/dist/{chunk-TAPSNIMA.js → chunk-5CEJH5ZN.js} +4 -4
- package/dist/{chunk-4RGWCRIJ.js → chunk-5TYA4OCF.js} +4 -4
- package/dist/{chunk-PILLH262.js → chunk-6GAUF4OU.js} +3 -3
- package/dist/{chunk-QXWQ5V24.js → chunk-AF6DSAWD.js} +2 -2
- package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
- package/dist/{chunk-32KD5IHZ.js → chunk-CLXTDOKV.js} +2 -2
- package/dist/{chunk-ARV3AUOM.js → chunk-DL6H3D7S.js} +2 -2
- package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
- package/dist/{chunk-KCRV3HVN.js → chunk-EC3A6M43.js} +2 -2
- package/dist/{chunk-PNW4KKJX.js → chunk-EK6FYL2E.js} +27 -1
- package/dist/chunk-EK6FYL2E.js.map +1 -0
- package/dist/{chunk-YI3KC2B5.js → chunk-FZMH66NT.js} +2 -2
- package/dist/{chunk-DT2ZGQT7.js → chunk-G663XUEG.js} +2 -2
- package/dist/{chunk-TYEOAFH3.js → chunk-G6SVZWPB.js} +10 -1
- package/dist/chunk-G6SVZWPB.js.map +1 -0
- package/dist/{chunk-CDOIDOTQ.js → chunk-HKET3ZOI.js} +4 -4
- package/dist/{chunk-YOI3ELXF.js → chunk-IF362TF6.js} +2 -2
- package/dist/{chunk-UX5QTAFE.js → chunk-J45OCIVH.js} +2 -2
- package/dist/{chunk-UDJLF3BO.js → chunk-JI6HWBYL.js} +2 -2
- package/dist/{chunk-ECZPWSB5.js → chunk-JJT3AGL4.js} +4 -4
- package/dist/{chunk-6C4WHMKV.js → chunk-JMAKCWJ3.js} +6 -6
- package/dist/{chunk-4NFVPDIL.js → chunk-LM6JB2EG.js} +2 -2
- package/dist/{chunk-MOGFK2DU.js → chunk-LPIWEKZ3.js} +2 -2
- package/dist/{chunk-LD53WPMU.js → chunk-LQ6JI4VH.js} +4 -4
- package/dist/{chunk-IZLNJYLX.js → chunk-MNFAGE5D.js} +2 -2
- package/dist/{chunk-NXNUG7IA.js → chunk-MOBRVKWE.js} +23 -12
- package/dist/chunk-MOBRVKWE.js.map +1 -0
- package/dist/{chunk-5A35EGHM.js → chunk-N4PD5IY3.js} +35 -35
- package/dist/{chunk-PQP6MFPL.js → chunk-NFMDHE45.js} +2 -2
- package/dist/{chunk-WVTNZUER.js → chunk-NLZO5NO6.js} +2 -2
- package/dist/{chunk-5S53ZBPH.js → chunk-Q6ZHGGNJ.js} +2 -2
- package/dist/{chunk-SN5DFE34.js → chunk-Q7SFJURX.js} +2 -2
- package/dist/{chunk-MXZWKOOR.js → chunk-QJM2XAJD.js} +11 -11
- package/dist/{chunk-6ZNIUGXB.js → chunk-QQW2LIEA.js} +4 -4
- package/dist/{chunk-ZKD3UVEO.js → chunk-QVTSLRKT.js} +3 -3
- package/dist/{chunk-C5AOVGVC.js → chunk-RWST6NOL.js} +166 -102
- package/dist/chunk-RWST6NOL.js.map +1 -0
- package/dist/{chunk-YXZPKBFW.js → chunk-SPVIG2R3.js} +10 -10
- package/dist/{chunk-B55EAZNF.js → chunk-TIVZ4MCG.js} +2 -2
- package/dist/{chunk-5KBNNUXS.js → chunk-TT7BJWGI.js} +2 -2
- package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
- package/dist/{chunk-E6BOD3UJ.js → chunk-VPAFWWCL.js} +2 -2
- package/dist/{chunk-D7PQ7HZL.js → chunk-W54EAJT4.js} +2 -2
- package/dist/{chunk-QVG4LAQO.js → chunk-WR6KFJKA.js} +7 -7
- package/dist/{chunk-YQGHW5ML.js → chunk-WRFKZEO6.js} +4 -4
- package/dist/{chunk-SJGTY2TW.js → chunk-XUNQLJT2.js} +6 -6
- package/dist/{chunk-P7IDNF7H.js → chunk-XWT4JXXA.js} +2 -2
- package/dist/{chunk-MSUA4KAK.js → chunk-XXA6T3O4.js} +2 -2
- package/dist/{chunk-KF74X62T.js → chunk-YGKUAX2B.js} +4 -4
- package/dist/{chunk-YWYZPKK3.js → chunk-YOZNTNNA.js} +2 -2
- package/dist/{chunk-U62ZGWU7.js → chunk-ZXUOAFUG.js} +1 -1
- package/dist/chunk-ZXUOAFUG.js.map +1 -0
- package/dist/{cli-CxtZyBLl.d.ts → cli-DBDgdvh9.d.ts} +3 -3
- package/dist/cli.d.ts +11 -10
- package/dist/cli.js +56 -50
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +12 -5
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +12 -5
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +12 -5
- package/dist/consolidation-provenance-check.d.ts +3 -3
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +13 -5
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -8
- package/dist/extraction-faithfulness.d.ts +211 -0
- package/dist/extraction-faithfulness.js +35 -0
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-judge.js +4 -4
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +7 -7
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/fallback-llm.js +2 -2
- package/dist/{graph-edge-decay-D7OESCBR.js → graph-edge-decay-JLOF3YW4.js} +3 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +12 -11
- package/dist/index.js +96 -95
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +3 -3
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-llm.js +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +13 -5
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -5
- package/dist/maintenance/rebuild-memory-projection.js +14 -6
- package/dist/mcp-memory-inspector-app.d.ts +12 -11
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +20 -12
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +13 -5
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +26 -19
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +15 -7
- package/dist/{orchestrator-CnbxRQs8.d.ts → orchestrator-Dv8JQu3-.d.ts} +20 -3
- package/dist/orchestrator.d.ts +6 -5
- package/dist/orchestrator.js +47 -46
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-planner-llm.js +2 -2
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +5 -5
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +5 -5
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-DXmtQ_4B.d.ts → semantic-consolidation-CgREi9E0.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +13 -6
- package/dist/semantic-rule-promotion.js +13 -5
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +13 -5
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{state-NCHQ4TRG.js → state-ITXJKXRE.js} +2 -2
- package/dist/storage.d.ts +11 -1
- package/dist/storage.js +12 -4
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +6 -6
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/{trace-WM7V4CKI.js → trace-ZFVRH4GO.js} +3 -3
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/{tui-RI7P6PBS.js → tui-55UJMJX7.js} +3 -3
- package/dist/tui-55UJMJX7.js.map +1 -0
- package/dist/{types-CEWBmjCH.d.ts → types-CeZYSC-E.d.ts} +37 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +13 -5
- package/package.json +2 -2
- package/src/config.test.ts +16 -0
- package/src/config.ts +30 -0
- package/src/console/state.ts +32 -0
- package/src/extraction-faithfulness.test.ts +1112 -0
- package/src/extraction-faithfulness.ts +993 -0
- package/src/faithfulness-graph-guard.test.ts +252 -0
- package/src/local-llm.ts +1 -0
- package/src/orchestrator.ts +169 -45
- package/src/storage.ts +19 -0
- package/src/types.ts +47 -0
- package/dist/chunk-C5AOVGVC.js.map +0 -1
- package/dist/chunk-NXNUG7IA.js.map +0 -1
- package/dist/chunk-PNW4KKJX.js.map +0 -1
- package/dist/chunk-TYEOAFH3.js.map +0 -1
- package/dist/chunk-U62ZGWU7.js.map +0 -1
- package/dist/chunk-UPTZYUYJ.js.map +0 -1
- /package/dist/{auto-sync-RWXT6P5M.js.map → auto-sync-PFW2NJZY.js.map} +0 -0
- /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
- /package/dist/{chunk-FCH766FX.js.map → chunk-32XTY2DQ.js.map} +0 -0
- /package/dist/{chunk-YN4ZT4CW.js.map → chunk-3LYJIA76.js.map} +0 -0
- /package/dist/{chunk-24FCDBJV.js.map → chunk-3P2XEQSV.js.map} +0 -0
- /package/dist/{chunk-JIKBEDSB.js.map → chunk-4NNDJOAO.js.map} +0 -0
- /package/dist/{chunk-EPVIBPVE.js.map → chunk-52QIAN76.js.map} +0 -0
- /package/dist/{chunk-TAPSNIMA.js.map → chunk-5CEJH5ZN.js.map} +0 -0
- /package/dist/{chunk-4RGWCRIJ.js.map → chunk-5TYA4OCF.js.map} +0 -0
- /package/dist/{chunk-PILLH262.js.map → chunk-6GAUF4OU.js.map} +0 -0
- /package/dist/{chunk-QXWQ5V24.js.map → chunk-AF6DSAWD.js.map} +0 -0
- /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
- /package/dist/{chunk-32KD5IHZ.js.map → chunk-CLXTDOKV.js.map} +0 -0
- /package/dist/{chunk-ARV3AUOM.js.map → chunk-DL6H3D7S.js.map} +0 -0
- /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
- /package/dist/{chunk-KCRV3HVN.js.map → chunk-EC3A6M43.js.map} +0 -0
- /package/dist/{chunk-YI3KC2B5.js.map → chunk-FZMH66NT.js.map} +0 -0
- /package/dist/{chunk-DT2ZGQT7.js.map → chunk-G663XUEG.js.map} +0 -0
- /package/dist/{chunk-CDOIDOTQ.js.map → chunk-HKET3ZOI.js.map} +0 -0
- /package/dist/{chunk-YOI3ELXF.js.map → chunk-IF362TF6.js.map} +0 -0
- /package/dist/{chunk-UX5QTAFE.js.map → chunk-J45OCIVH.js.map} +0 -0
- /package/dist/{chunk-UDJLF3BO.js.map → chunk-JI6HWBYL.js.map} +0 -0
- /package/dist/{chunk-ECZPWSB5.js.map → chunk-JJT3AGL4.js.map} +0 -0
- /package/dist/{chunk-6C4WHMKV.js.map → chunk-JMAKCWJ3.js.map} +0 -0
- /package/dist/{chunk-4NFVPDIL.js.map → chunk-LM6JB2EG.js.map} +0 -0
- /package/dist/{chunk-MOGFK2DU.js.map → chunk-LPIWEKZ3.js.map} +0 -0
- /package/dist/{chunk-LD53WPMU.js.map → chunk-LQ6JI4VH.js.map} +0 -0
- /package/dist/{chunk-IZLNJYLX.js.map → chunk-MNFAGE5D.js.map} +0 -0
- /package/dist/{chunk-5A35EGHM.js.map → chunk-N4PD5IY3.js.map} +0 -0
- /package/dist/{chunk-PQP6MFPL.js.map → chunk-NFMDHE45.js.map} +0 -0
- /package/dist/{chunk-WVTNZUER.js.map → chunk-NLZO5NO6.js.map} +0 -0
- /package/dist/{chunk-5S53ZBPH.js.map → chunk-Q6ZHGGNJ.js.map} +0 -0
- /package/dist/{chunk-SN5DFE34.js.map → chunk-Q7SFJURX.js.map} +0 -0
- /package/dist/{chunk-MXZWKOOR.js.map → chunk-QJM2XAJD.js.map} +0 -0
- /package/dist/{chunk-6ZNIUGXB.js.map → chunk-QQW2LIEA.js.map} +0 -0
- /package/dist/{chunk-ZKD3UVEO.js.map → chunk-QVTSLRKT.js.map} +0 -0
- /package/dist/{chunk-YXZPKBFW.js.map → chunk-SPVIG2R3.js.map} +0 -0
- /package/dist/{chunk-B55EAZNF.js.map → chunk-TIVZ4MCG.js.map} +0 -0
- /package/dist/{chunk-5KBNNUXS.js.map → chunk-TT7BJWGI.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
- /package/dist/{chunk-E6BOD3UJ.js.map → chunk-VPAFWWCL.js.map} +0 -0
- /package/dist/{chunk-D7PQ7HZL.js.map → chunk-W54EAJT4.js.map} +0 -0
- /package/dist/{chunk-QVG4LAQO.js.map → chunk-WR6KFJKA.js.map} +0 -0
- /package/dist/{chunk-YQGHW5ML.js.map → chunk-WRFKZEO6.js.map} +0 -0
- /package/dist/{chunk-SJGTY2TW.js.map → chunk-XUNQLJT2.js.map} +0 -0
- /package/dist/{chunk-P7IDNF7H.js.map → chunk-XWT4JXXA.js.map} +0 -0
- /package/dist/{chunk-MSUA4KAK.js.map → chunk-XXA6T3O4.js.map} +0 -0
- /package/dist/{chunk-KF74X62T.js.map → chunk-YGKUAX2B.js.map} +0 -0
- /package/dist/{chunk-YWYZPKK3.js.map → chunk-YOZNTNNA.js.map} +0 -0
- /package/dist/{state-NCHQ4TRG.js.map → extraction-faithfulness.js.map} +0 -0
- /package/dist/{graph-edge-decay-D7OESCBR.js.map → graph-edge-decay-JLOF3YW4.js.map} +0 -0
- /package/dist/{tui-RI7P6PBS.js.map → state-ITXJKXRE.js.map} +0 -0
- /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",
|
package/src/orchestrator.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15149
|
-
|
|
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
|
-
|
|
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
|
-
|
|
15347
|
-
|
|
15348
|
-
|
|
15349
|
-
|
|
15350
|
-
|
|
15351
|
-
|
|
15352
|
-
|
|
15353
|
-
|
|
15354
|
-
|
|
15355
|
-
|
|
15356
|
-
|
|
15357
|
-
|
|
15358
|
-
|
|
15359
|
-
|
|
15360
|
-
|
|
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
|
-
|
|
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
|
|
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 !== "
|
|
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
|
-
|
|
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
|
}
|