@remnic/core 9.3.719 → 9.3.721
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 +10 -7
- package/dist/access-boundary.js +37 -34
- package/dist/access-cli.js +71 -66
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +11 -8
- package/dist/access-http.js +44 -41
- package/dist/access-mcp.d.ts +11 -8
- package/dist/access-mcp.js +40 -37
- package/dist/access-operations-batch.js +38 -35
- package/dist/access-operations.d.ts +11 -8
- package/dist/access-operations.js +39 -36
- package/dist/access-schema.d.ts +19 -19
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-CZbnt0t2.d.ts → access-service-Dj3I-VBS.d.ts} +3 -3
- package/dist/access-service.d.ts +11 -8
- package/dist/access-service.js +36 -33
- package/dist/access-surface-catalog.d.ts +10 -7
- 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 +4 -2
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/{auto-sync-24NNS3GU.js → auto-sync-F3KCSQFJ.js} +5 -5
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +11 -8
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +12 -10
- 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 +30 -2
- package/dist/capabilities.js +3 -1
- package/dist/{catalog-CEYlMs9X.d.ts → catalog-F-OEVbRQ.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 +15 -13
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +4 -0
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-TH7WMHVK.js → chunk-3NN73CM7.js} +2 -2
- package/dist/{chunk-A5TUPZ3N.js → chunk-4SF232E6.js} +60 -30
- package/dist/chunk-4SF232E6.js.map +1 -0
- package/dist/{chunk-DGTDRIUO.js → chunk-4T3BMHKD.js} +2 -2
- package/dist/{chunk-EH27LHML.js → chunk-5O42UKXI.js} +2 -2
- package/dist/{chunk-KRGC4EDX.js → chunk-6FAMMBQ3.js} +2 -2
- package/dist/{chunk-FEB7W5JG.js → chunk-6OIDDKAA.js} +27 -6
- package/dist/chunk-6OIDDKAA.js.map +1 -0
- package/dist/{chunk-67HG7KFE.js → chunk-6YKIYQU7.js} +2 -2
- package/dist/{chunk-LXSG4L55.js → chunk-7CTNUVHZ.js} +2 -2
- package/dist/{chunk-UCJ5CDTK.js → chunk-A5XNBK2D.js} +22 -14
- package/dist/chunk-A5XNBK2D.js.map +1 -0
- package/dist/{chunk-7EEVXW7X.js → chunk-A7TJZLPK.js} +2 -2
- package/dist/{chunk-P5IPFZVH.js → chunk-B7WISIAJ.js} +5 -5
- package/dist/chunk-BCDKBDSY.js +173 -0
- package/dist/chunk-BCDKBDSY.js.map +1 -0
- package/dist/{chunk-JAKYZGV4.js → chunk-BXEOHV7K.js} +3 -3
- package/dist/chunk-C4X4QGIO.js +60 -0
- package/dist/chunk-C4X4QGIO.js.map +1 -0
- package/dist/{chunk-S3OPGGZB.js → chunk-D7EBTQ24.js} +2 -2
- package/dist/{chunk-IO5NQEGZ.js → chunk-DKT3X5C3.js} +2 -2
- package/dist/{chunk-PBH4JUAB.js → chunk-DVRHLN2O.js} +18 -3
- package/dist/chunk-DVRHLN2O.js.map +1 -0
- package/dist/{chunk-S35FX6MU.js → chunk-EBDA5TYA.js} +2 -2
- package/dist/{chunk-2PTBLS2S.js → chunk-EDOQM4E4.js} +2 -2
- package/dist/{chunk-YTZLBBEB.js → chunk-EEJMD2L2.js} +3 -3
- package/dist/{chunk-YGKUAX2B.js → chunk-EHQ5HO5T.js} +11 -11
- package/dist/chunk-EHQ5HO5T.js.map +1 -0
- package/dist/{chunk-JIZGYQYH.js → chunk-EM2LDXJ2.js} +4 -4
- package/dist/{chunk-YYOK4GVF.js → chunk-EVPNWN7Z.js} +10 -10
- package/dist/{chunk-HLIR3RJ7.js → chunk-EXUCUPV2.js} +2 -2
- package/dist/{chunk-F3PVXKHP.js → chunk-GDUOCHCD.js} +27 -21
- package/dist/chunk-GDUOCHCD.js.map +1 -0
- package/dist/{chunk-L5ASZA2F.js → chunk-GJSL4WG2.js} +17 -2
- package/dist/chunk-GJSL4WG2.js.map +1 -0
- package/dist/{chunk-2SXMCQEQ.js → chunk-GZQXOQQ2.js} +3 -3
- package/dist/{chunk-2KAYTPPT.js → chunk-HCVWF657.js} +12 -12
- package/dist/{chunk-N3DUH6OO.js → chunk-ILFSEIRT.js} +1 -1
- package/dist/chunk-ILFSEIRT.js.map +1 -0
- package/dist/{chunk-4KZGLDJJ.js → chunk-J3JPB7ZI.js} +2 -2
- package/dist/{chunk-3JJWNZTT.js → chunk-L2B3EE7B.js} +102 -42
- package/dist/chunk-L2B3EE7B.js.map +1 -0
- package/dist/{chunk-NFRBADNR.js → chunk-LA3HZKES.js} +610 -369
- package/dist/chunk-LA3HZKES.js.map +1 -0
- package/dist/{chunk-LQ6JI4VH.js → chunk-LD53WPMU.js} +4 -4
- package/dist/{chunk-URM3HW2R.js → chunk-LLUGAZ3B.js} +2 -2
- package/dist/{chunk-RVLB4E6N.js → chunk-MDBZTH7N.js} +5 -32
- package/dist/chunk-MDBZTH7N.js.map +1 -0
- package/dist/{chunk-U5H7WHTS.js → chunk-N77ELJ2D.js} +4 -4
- package/dist/{chunk-2VHMVWPU.js → chunk-NXRUUDUF.js} +2 -2
- package/dist/{chunk-DIFU33GU.js → chunk-OHTOPFRF.js} +2 -2
- package/dist/{chunk-74MYJSKB.js → chunk-ORAK3LNZ.js} +2 -2
- package/dist/{chunk-REWQAFSA.js → chunk-PD42EYQN.js} +2 -2
- package/dist/chunk-PHK3HARR.js +32 -0
- package/dist/chunk-PHK3HARR.js.map +1 -0
- package/dist/{chunk-773DPI6T.js → chunk-PKMQK2WY.js} +4 -4
- package/dist/{chunk-72VDBALG.js → chunk-QD6QP5P6.js} +63 -54
- package/dist/chunk-QD6QP5P6.js.map +1 -0
- package/dist/{chunk-CTOQEZSN.js → chunk-QR67FU5G.js} +2 -2
- package/dist/{chunk-AU7Q3LSC.js → chunk-RKNJBZ55.js} +7 -7
- package/dist/{chunk-YI7RZO7Y.js → chunk-SQNED75R.js} +1 -1
- package/dist/{chunk-5CEJH5ZN.js → chunk-TAPSNIMA.js} +4 -4
- package/dist/{chunk-IF362TF6.js → chunk-TQT3USCG.js} +2 -2
- package/dist/chunk-TQT3USCG.js.map +1 -0
- package/dist/{chunk-5RHM43BJ.js → chunk-TXQCG6SE.js} +3 -3
- package/dist/{chunk-ANI5DUAE.js → chunk-UIXXE6NI.js} +7 -7
- package/dist/{chunk-2COL35PK.js → chunk-UO5ZHIIH.js} +2 -2
- package/dist/{chunk-OJU73BUX.js → chunk-VCLGUIFM.js} +2 -2
- package/dist/{chunk-5J4OL7TJ.js → chunk-VUA4S7P6.js} +4 -4
- package/dist/{chunk-A66YRSOS.js → chunk-WQYSDPMA.js} +2 -2
- package/dist/chunk-XGTBNVIU.js +79 -0
- package/dist/chunk-XGTBNVIU.js.map +1 -0
- package/dist/{chunk-OZ2KQ7HF.js → chunk-YEE5KJQQ.js} +2 -2
- package/dist/chunk-YN2UN7N3.js +217 -0
- package/dist/chunk-YN2UN7N3.js.map +1 -0
- package/dist/{chunk-WRFKZEO6.js → chunk-YQGHW5ML.js} +4 -4
- package/dist/{chunk-APUJIMDM.js → chunk-Z4RU5VPM.js} +2 -2
- package/dist/{chunk-DCWIQFNA.js → chunk-ZUDM75KG.js} +4 -4
- package/dist/{cli-1orcdXOY.d.ts → cli-P_GaYcCY.d.ts} +3 -3
- package/dist/cli.d.ts +9 -6
- package/dist/cli.js +67 -63
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +12 -10
- 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 +4 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +12 -10
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +13 -11
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/backend.js +2 -2
- 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 +12 -10
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +11 -8
- package/dist/extraction-faithfulness.d.ts +8 -2
- package/dist/extraction-faithfulness.js +4 -3
- 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 +3 -3
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +5 -4
- package/dist/faithfulness-config.d.ts +55 -0
- package/dist/faithfulness-config.js +11 -0
- package/dist/faithfulness-config.js.map +1 -0
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/fallback-llm.js +2 -2
- package/dist/{forget-U66KPDPY.js → forget-OEE5OELK.js} +2 -2
- package/dist/graph-dashboard-diff.d.ts +4 -0
- package/dist/graph-dashboard-key.d.ts +4 -0
- package/dist/graph-dashboard-parser.d.ts +4 -0
- package/dist/{graph-edge-decay-JLOF3YW4.js → graph-edge-decay-QPRJQ7DL.js} +3 -3
- package/dist/graph-edge-reinforcement.d.ts +4 -0
- package/dist/graph-snapshot.d.ts +7 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.d.ts +7 -1
- 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 +571 -570
- package/dist/index.js +104 -99
- 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/engine.js +2 -2
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +4 -4
- 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-model-endpoint.d.ts +96 -0
- package/dist/local-model-endpoint.js +12 -0
- package/dist/local-model-endpoint.js.map +1 -0
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +12 -10
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +12 -10
- package/dist/maintenance/rebuild-memory-projection.js +13 -11
- package/dist/mcp-memory-inspector-app.d.ts +11 -8
- 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 +22 -20
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +12 -10
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -2
- package/dist/operator-toolkit.js +32 -28
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +14 -12
- package/dist/{orchestrator-kOxredSr.d.ts → orchestrator-f5xv19kp.d.ts} +178 -81
- package/dist/orchestrator.d.ts +8 -5
- package/dist/orchestrator.js +56 -52
- 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/provenance.js +2 -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 +18 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +5 -3
- 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 +8 -8
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +14 -14
- 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-B58v3S-a.d.ts → semantic-consolidation-BQm1e1Pn.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +13 -11
- package/dist/semantic-rule-promotion.js +12 -10
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +12 -10
- 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/storage.d.ts +45 -1
- package/dist/storage.js +11 -9
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- 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/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 +1 -1
- package/dist/trust-score-stage.d.ts +178 -0
- package/dist/trust-score-stage.js +18 -0
- package/dist/trust-score-stage.js.map +1 -0
- package/dist/trust-score.d.ts +164 -0
- package/dist/trust-score.js +22 -0
- package/dist/trust-score.js.map +1 -0
- package/dist/{types-ACmDOScJ.d.ts → types-DwO1Ot4n.d.ts} +56 -2
- 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 +12 -10
- package/package.json +2 -2
- package/src/access-service.ts +8 -5
- package/src/capabilities-cluster-b.test.ts +78 -0
- package/src/capabilities.test.ts +11 -1
- package/src/capabilities.ts +58 -0
- package/src/cli/research-status-commands.ts +7 -3
- package/src/cli.ts +11 -6
- package/src/config.ts +60 -30
- package/src/extraction-faithfulness.test.ts +175 -0
- package/src/extraction-faithfulness.ts +53 -1
- package/src/faithfulness-config.test.ts +96 -0
- package/src/faithfulness-config.ts +138 -0
- package/src/graph-snapshot.ts +3 -3
- package/src/graph.ts +8 -7
- package/src/lifecycle/tombstones.test.ts +242 -1
- package/src/lifecycle/tombstones.ts +157 -70
- package/src/local-model-endpoint.test.ts +155 -0
- package/src/local-model-endpoint.ts +189 -0
- package/src/operator-toolkit.ts +24 -7
- package/src/orchestration/tier-migration-coordinator.ts +286 -0
- package/src/orchestrator.ts +331 -222
- package/src/recall-xray.test.ts +62 -0
- package/src/recall-xray.ts +34 -0
- package/src/trust-score-recall-paths.test.ts +157 -0
- package/src/trust-score-stage.test.ts +350 -0
- package/src/trust-score-stage.ts +398 -0
- package/src/trust-score.test.ts +282 -0
- package/src/trust-score.ts +449 -0
- package/src/types.ts +61 -1
- package/dist/chunk-3JJWNZTT.js.map +0 -1
- package/dist/chunk-72VDBALG.js.map +0 -1
- package/dist/chunk-A5TUPZ3N.js.map +0 -1
- package/dist/chunk-F3PVXKHP.js.map +0 -1
- package/dist/chunk-FEB7W5JG.js.map +0 -1
- package/dist/chunk-IF362TF6.js.map +0 -1
- package/dist/chunk-L5ASZA2F.js.map +0 -1
- package/dist/chunk-N3DUH6OO.js.map +0 -1
- package/dist/chunk-NFRBADNR.js.map +0 -1
- package/dist/chunk-PBH4JUAB.js.map +0 -1
- package/dist/chunk-RVLB4E6N.js.map +0 -1
- package/dist/chunk-UCJ5CDTK.js.map +0 -1
- package/dist/chunk-YGKUAX2B.js.map +0 -1
- /package/dist/{auto-sync-24NNS3GU.js.map → auto-sync-F3KCSQFJ.js.map} +0 -0
- /package/dist/{chunk-TH7WMHVK.js.map → chunk-3NN73CM7.js.map} +0 -0
- /package/dist/{chunk-DGTDRIUO.js.map → chunk-4T3BMHKD.js.map} +0 -0
- /package/dist/{chunk-EH27LHML.js.map → chunk-5O42UKXI.js.map} +0 -0
- /package/dist/{chunk-KRGC4EDX.js.map → chunk-6FAMMBQ3.js.map} +0 -0
- /package/dist/{chunk-67HG7KFE.js.map → chunk-6YKIYQU7.js.map} +0 -0
- /package/dist/{chunk-LXSG4L55.js.map → chunk-7CTNUVHZ.js.map} +0 -0
- /package/dist/{chunk-7EEVXW7X.js.map → chunk-A7TJZLPK.js.map} +0 -0
- /package/dist/{chunk-P5IPFZVH.js.map → chunk-B7WISIAJ.js.map} +0 -0
- /package/dist/{chunk-JAKYZGV4.js.map → chunk-BXEOHV7K.js.map} +0 -0
- /package/dist/{chunk-S3OPGGZB.js.map → chunk-D7EBTQ24.js.map} +0 -0
- /package/dist/{chunk-IO5NQEGZ.js.map → chunk-DKT3X5C3.js.map} +0 -0
- /package/dist/{chunk-S35FX6MU.js.map → chunk-EBDA5TYA.js.map} +0 -0
- /package/dist/{chunk-2PTBLS2S.js.map → chunk-EDOQM4E4.js.map} +0 -0
- /package/dist/{chunk-YTZLBBEB.js.map → chunk-EEJMD2L2.js.map} +0 -0
- /package/dist/{chunk-JIZGYQYH.js.map → chunk-EM2LDXJ2.js.map} +0 -0
- /package/dist/{chunk-YYOK4GVF.js.map → chunk-EVPNWN7Z.js.map} +0 -0
- /package/dist/{chunk-HLIR3RJ7.js.map → chunk-EXUCUPV2.js.map} +0 -0
- /package/dist/{chunk-2SXMCQEQ.js.map → chunk-GZQXOQQ2.js.map} +0 -0
- /package/dist/{chunk-2KAYTPPT.js.map → chunk-HCVWF657.js.map} +0 -0
- /package/dist/{chunk-4KZGLDJJ.js.map → chunk-J3JPB7ZI.js.map} +0 -0
- /package/dist/{chunk-LQ6JI4VH.js.map → chunk-LD53WPMU.js.map} +0 -0
- /package/dist/{chunk-URM3HW2R.js.map → chunk-LLUGAZ3B.js.map} +0 -0
- /package/dist/{chunk-U5H7WHTS.js.map → chunk-N77ELJ2D.js.map} +0 -0
- /package/dist/{chunk-2VHMVWPU.js.map → chunk-NXRUUDUF.js.map} +0 -0
- /package/dist/{chunk-DIFU33GU.js.map → chunk-OHTOPFRF.js.map} +0 -0
- /package/dist/{chunk-74MYJSKB.js.map → chunk-ORAK3LNZ.js.map} +0 -0
- /package/dist/{chunk-REWQAFSA.js.map → chunk-PD42EYQN.js.map} +0 -0
- /package/dist/{chunk-773DPI6T.js.map → chunk-PKMQK2WY.js.map} +0 -0
- /package/dist/{chunk-CTOQEZSN.js.map → chunk-QR67FU5G.js.map} +0 -0
- /package/dist/{chunk-AU7Q3LSC.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-YI7RZO7Y.js.map → chunk-SQNED75R.js.map} +0 -0
- /package/dist/{chunk-5CEJH5ZN.js.map → chunk-TAPSNIMA.js.map} +0 -0
- /package/dist/{chunk-5RHM43BJ.js.map → chunk-TXQCG6SE.js.map} +0 -0
- /package/dist/{chunk-ANI5DUAE.js.map → chunk-UIXXE6NI.js.map} +0 -0
- /package/dist/{chunk-2COL35PK.js.map → chunk-UO5ZHIIH.js.map} +0 -0
- /package/dist/{chunk-OJU73BUX.js.map → chunk-VCLGUIFM.js.map} +0 -0
- /package/dist/{chunk-5J4OL7TJ.js.map → chunk-VUA4S7P6.js.map} +0 -0
- /package/dist/{chunk-A66YRSOS.js.map → chunk-WQYSDPMA.js.map} +0 -0
- /package/dist/{chunk-OZ2KQ7HF.js.map → chunk-YEE5KJQQ.js.map} +0 -0
- /package/dist/{chunk-WRFKZEO6.js.map → chunk-YQGHW5ML.js.map} +0 -0
- /package/dist/{chunk-APUJIMDM.js.map → chunk-Z4RU5VPM.js.map} +0 -0
- /package/dist/{chunk-DCWIQFNA.js.map → chunk-ZUDM75KG.js.map} +0 -0
- /package/dist/{forget-U66KPDPY.js.map → forget-OEE5OELK.js.map} +0 -0
- /package/dist/{graph-edge-decay-JLOF3YW4.js.map → graph-edge-decay-QPRJQ7DL.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createSearchBackend
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-HCVWF657.js";
|
|
4
4
|
import {
|
|
5
5
|
namespaceIdentityToken,
|
|
6
6
|
normalizeNamespaceIdentity
|
|
@@ -401,4 +401,4 @@ export {
|
|
|
401
401
|
namespaceCollectionName,
|
|
402
402
|
NamespaceSearchRouter
|
|
403
403
|
};
|
|
404
|
-
//# sourceMappingURL=chunk-
|
|
404
|
+
//# sourceMappingURL=chunk-QR67FU5G.js.map
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HermesAdapter
|
|
3
|
-
} from "./chunk-42NQ7AVG.js";
|
|
4
|
-
import {
|
|
5
|
-
ReplitAdapter
|
|
6
|
-
} from "./chunk-TMSXWOBZ.js";
|
|
7
1
|
import {
|
|
8
2
|
ClaudeCodeAdapter
|
|
9
3
|
} from "./chunk-J64TK33U.js";
|
|
10
4
|
import {
|
|
11
5
|
CodexAdapter
|
|
12
6
|
} from "./chunk-RSUYKGGZ.js";
|
|
7
|
+
import {
|
|
8
|
+
HermesAdapter
|
|
9
|
+
} from "./chunk-42NQ7AVG.js";
|
|
10
|
+
import {
|
|
11
|
+
ReplitAdapter
|
|
12
|
+
} from "./chunk-TMSXWOBZ.js";
|
|
13
13
|
|
|
14
14
|
// src/adapters/registry.ts
|
|
15
15
|
var AdapterRegistry = class {
|
|
@@ -53,4 +53,4 @@ var AdapterRegistry = class {
|
|
|
53
53
|
export {
|
|
54
54
|
AdapterRegistry
|
|
55
55
|
};
|
|
56
|
-
//# sourceMappingURL=chunk-
|
|
56
|
+
//# sourceMappingURL=chunk-RKNJBZ55.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
scanMemoryDir
|
|
3
|
-
} from "./chunk-AER6MT24.js";
|
|
4
1
|
import {
|
|
5
2
|
isSearchAborted,
|
|
6
3
|
throwIfSearchAborted
|
|
7
4
|
} from "./chunk-CINZGPSJ.js";
|
|
5
|
+
import {
|
|
6
|
+
scanMemoryDir
|
|
7
|
+
} from "./chunk-AER6MT24.js";
|
|
8
8
|
import {
|
|
9
9
|
resolveEnsureCollectionArgs
|
|
10
10
|
} from "./chunk-YNQ6DFSV.js";
|
|
@@ -491,4 +491,4 @@ function isMissingVectorProviderColumnError(err) {
|
|
|
491
491
|
export {
|
|
492
492
|
LanceDbBackend
|
|
493
493
|
};
|
|
494
|
-
//# sourceMappingURL=chunk-
|
|
494
|
+
//# sourceMappingURL=chunk-TAPSNIMA.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
readAllEdges
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-EHQ5HO5T.js";
|
|
4
4
|
import {
|
|
5
5
|
readEdgeConfidence
|
|
6
6
|
} from "./chunk-2LSZVONP.js";
|
|
@@ -162,4 +162,4 @@ export {
|
|
|
162
162
|
parseGraphSnapshotSince,
|
|
163
163
|
buildGraphSnapshot
|
|
164
164
|
};
|
|
165
|
-
//# sourceMappingURL=chunk-
|
|
165
|
+
//# sourceMappingURL=chunk-TQT3USCG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/graph-snapshot.ts"],"sourcesContent":["/**\n * Graph snapshot — read-only view of the multi-graph memory adjacency\n * (issue #691 PR 2/5).\n *\n * Composes the JSONL edge store from `graph.ts` with optional node-metadata\n * loading so HTTP / MCP / future CLI surfaces can return a consistent\n * `{ nodes, edges, generatedAt }` shape suitable for the admin pane scaffold\n * shipped in PR 1/5.\n *\n * All inputs are validated and clamped at this layer so the access surface\n * (which is responsible for HTTP/MCP-flavored errors) can keep the wiring\n * thin. The module is pure async I/O — no global state, no caches.\n */\n\nimport type { GraphEdge, GraphType } from \"./graph.js\";\nimport { readAllEdges } from \"./graph.js\";\nimport { readEdgeConfidence } from \"./graph-edge-reinforcement.js\";\nimport * as path from \"path\";\n\n/** Default `limit` when the caller omits it. */\nexport const GRAPH_SNAPSHOT_DEFAULT_LIMIT = 500;\n\n/** Hard upper bound on `limit` to keep responses sized for the admin pane. */\nexport const GRAPH_SNAPSHOT_MAX_LIMIT = 5000;\n\n/** Categories accepted by the `categories` filter; matches `MemoryFile.frontmatter.category`. */\nexport type GraphSnapshotCategory = string;\n\nexport interface GraphSnapshotNode {\n /** Stable identifier — relative memory path (matches `GraphEdge.from` / `to`). */\n id: string;\n /** Short human label. Falls back to the basename when no metadata is available. */\n label: string;\n /** Memory category (e.g. `fact`, `decision`, `entity`). `\"unknown\"` when metadata is missing. */\n kind: string;\n /** Aggregate edge confidence touching this node, used for sizing in the admin pane. */\n score: number;\n /** Most recent edge timestamp (ISO) touching this node — best-effort recency signal. */\n lastUpdated: string | null;\n}\n\nexport interface GraphSnapshotEdge {\n source: string;\n target: string;\n kind: GraphType;\n /** Edge confidence in [0, 1]; legacy edges without confidence return 1.0. */\n confidence: number;\n}\n\nexport interface GraphSnapshotResponse {\n nodes: GraphSnapshotNode[];\n edges: GraphSnapshotEdge[];\n generatedAt: string;\n}\n\nexport interface GraphSnapshotRequest {\n /** Max number of edges to include (after filtering). Default 500, max 5000. */\n limit?: number;\n /** Inclusive lower bound on edge `ts` (ISO string). Edges older than this are dropped. */\n since?: string;\n /** When set, restrict the snapshot to the focus node and its direct neighbors. */\n focusNodeId?: string;\n /**\n * Optional category allow-list. Edges are kept only when both endpoints\n * resolve to nodes whose category falls in this set; nodes are kept only\n * when their category matches. When omitted, no category filter is applied.\n */\n categories?: GraphSnapshotCategory[];\n}\n\n/**\n * Loader contract: given a relative memory path, return `{ category, label,\n * updated }` or `null` when the memory cannot be resolved. Implementations\n * typically wrap `StorageManager.readMemoryByPath`; the snapshot module stays\n * agnostic so tests can pass a synchronous in-memory map.\n */\nexport type GraphSnapshotNodeLoader = (\n relPath: string,\n) => Promise<GraphSnapshotNodeMetadata | null>;\n\nexport interface GraphSnapshotNodeMetadata {\n /** Memory category, e.g. `fact` / `decision` / `entity`. */\n category: string;\n /** Display label — usually the memory id or the entity name. */\n label: string;\n /** ISO `updated` timestamp from frontmatter, when available. */\n updated?: string;\n}\n\n/**\n * Coerce a caller-supplied limit into the `[1, GRAPH_SNAPSHOT_MAX_LIMIT]` range.\n *\n * - `undefined` / `null` → `GRAPH_SNAPSHOT_DEFAULT_LIMIT`.\n * - non-finite or non-integer → throws `Error` (callers translate to 400).\n * - `<= 0` → throws.\n * - `> GRAPH_SNAPSHOT_MAX_LIMIT` → clamped to the max (no error — admin\n * panel callers send liberal limits).\n */\nexport function normalizeGraphSnapshotLimit(raw: unknown): number {\n if (raw === undefined || raw === null) return GRAPH_SNAPSHOT_DEFAULT_LIMIT;\n if (typeof raw !== \"number\" || !Number.isFinite(raw) || !Number.isInteger(raw)) {\n throw new Error(\"graphSnapshot: limit must be a positive integer\");\n }\n if (raw <= 0) {\n throw new Error(\"graphSnapshot: limit must be a positive integer\");\n }\n if (raw > GRAPH_SNAPSHOT_MAX_LIMIT) return GRAPH_SNAPSHOT_MAX_LIMIT;\n return raw;\n}\n\n/**\n * Validate and parse an ISO timestamp into a millisecond epoch. Throws\n * when the input cannot be parsed; callers translate to a 400. `undefined`\n * input yields `undefined`.\n */\nexport function parseGraphSnapshotSince(raw: string | undefined): number | undefined {\n if (raw === undefined || raw === null || raw === \"\") return undefined;\n const ms = Date.parse(raw);\n if (!Number.isFinite(ms)) {\n throw new Error(\"graphSnapshot: since must be a parseable ISO timestamp\");\n }\n return ms;\n}\n\n/**\n * Build a `GraphSnapshotResponse` from the raw edge JSONL on disk plus an\n * optional node-metadata loader.\n *\n * The function is split into pure subroutines so HTTP / MCP / tests can\n * exercise the same logic without spinning up a full `StorageManager`.\n */\nexport async function buildGraphSnapshot(opts: {\n memoryDir: string;\n graphConfig: {\n entityGraph: boolean;\n timeGraph: boolean;\n causalGraph: boolean;\n };\n request: GraphSnapshotRequest;\n loadNode: GraphSnapshotNodeLoader;\n /** Override clock for deterministic tests. */\n now?: () => Date;\n}): Promise<GraphSnapshotResponse> {\n const limit = normalizeGraphSnapshotLimit(opts.request.limit);\n const sinceMs = parseGraphSnapshotSince(opts.request.since);\n const focusNodeId = opts.request.focusNodeId?.trim();\n const categoryFilter = normalizeCategoryFilter(opts.request.categories);\n\n const allEdges = await readAllEdges(opts.memoryDir, opts.graphConfig);\n\n // Time-window filter (CLAUDE.md rule 35 — half-open `[since, +∞)`; equality\n // is treated as inclusive because callers expect a single-point pin to\n // surface edges stamped exactly at that instant).\n const timeFiltered = sinceMs === undefined\n ? allEdges\n : allEdges.filter((edge) => {\n const ts = Date.parse(edge.ts);\n return Number.isFinite(ts) && ts >= sinceMs;\n });\n\n // Focus-node neighborhood filter — restrict to edges incident on the node.\n const focusFiltered = focusNodeId\n ? timeFiltered.filter((edge) => edge.from === focusNodeId || edge.to === focusNodeId)\n : timeFiltered;\n\n // Sort newest-first so the limit window keeps the most recent edges. `ts`\n // is an ISO string, so a string comparison agrees with chronological order\n // for any well-formed timestamp; we still parse to avoid surprising\n // ordering when timezones drift, falling back to lexicographic compare on\n // tie / parse failure for stable ordering (CLAUDE.md rule 19).\n const sortedEdges = [...focusFiltered].sort((a, b) => {\n const aMs = Date.parse(a.ts);\n const bMs = Date.parse(b.ts);\n if (Number.isFinite(aMs) && Number.isFinite(bMs) && aMs !== bMs) {\n return bMs - aMs;\n }\n if (a.ts !== b.ts) return a.ts < b.ts ? 1 : -1;\n // Stable secondary key: from/to/type so identical-ts edges have a\n // deterministic order across runs.\n const aKey = `${a.from}|${a.to}|${a.type}`;\n const bKey = `${b.from}|${b.to}|${b.type}`;\n if (aKey === bKey) return 0;\n return aKey < bKey ? -1 : 1;\n });\n\n // Streaming category + limit pass. Metadata is loaded lazily per\n // endpoint with a memoization cache (`metadata`) so we never re-read the\n // same memory file twice, never read more than `2 × limit` files, and\n // never silently drop matching edges because a static cap fired before\n // the category filter saw them — the bug Cursor flagged on PR #734\n // when the pre-limit edge set referenced more than `2 × MAX_LIMIT`\n // unique nodes.\n const metadata = new Map<string, GraphSnapshotNodeMetadata | null>();\n const trimmedEdges: GraphEdge[] = [];\n\n const ensureMetadata = async (relPath: string): Promise<GraphSnapshotNodeMetadata | null> => {\n if (metadata.has(relPath)) return metadata.get(relPath) ?? null;\n let resolved: GraphSnapshotNodeMetadata | null = null;\n try {\n resolved = await opts.loadNode(relPath);\n } catch {\n // Loader errors are best-effort — leave the path absent so it\n // falls through to the basename label / \"unknown\" category.\n resolved = null;\n }\n metadata.set(relPath, resolved);\n return resolved;\n };\n\n for (const edge of sortedEdges) {\n if (trimmedEdges.length >= limit) break;\n if (categoryFilter !== null) {\n const fromMeta = await ensureMetadata(edge.from);\n const toMeta = await ensureMetadata(edge.to);\n if (!fromMeta || !toMeta) continue;\n if (\n !categoryFilter.has(fromMeta.category)\n || !categoryFilter.has(toMeta.category)\n ) {\n continue;\n }\n } else {\n // Even without a category filter we still want labels / kinds for\n // the surfaced nodes, so warm the metadata cache for this edge.\n // The cache is bounded by `2 × limit` because we stop iterating\n // once `trimmedEdges` reaches `limit`.\n await ensureMetadata(edge.from);\n await ensureMetadata(edge.to);\n }\n trimmedEdges.push(edge);\n }\n\n const resolvedMetadata = new Map<string, GraphSnapshotNodeMetadata>();\n for (const [key, value] of metadata) {\n if (value) resolvedMetadata.set(key, value);\n }\n\n const nodes = buildNodeIndex(trimmedEdges, resolvedMetadata);\n const edges: GraphSnapshotEdge[] = trimmedEdges.map((edge) => ({\n source: edge.from,\n target: edge.to,\n kind: edge.type,\n confidence: readEdgeConfidence(edge),\n }));\n\n const generatedAt = (opts.now ? opts.now() : new Date()).toISOString();\n return { nodes, edges, generatedAt };\n}\n\nfunction normalizeCategoryFilter(\n raw: GraphSnapshotCategory[] | undefined,\n): Set<string> | null {\n if (raw === undefined || raw === null) return null;\n if (!Array.isArray(raw)) {\n throw new Error(\"graphSnapshot: categories must be an array of strings\");\n }\n const cleaned = new Set<string>();\n for (const value of raw) {\n if (typeof value !== \"string\") {\n throw new Error(\"graphSnapshot: categories must be an array of strings\");\n }\n const trimmed = value.trim();\n if (trimmed.length > 0) cleaned.add(trimmed);\n }\n // Empty allow-list → reject everything. We surface this as a 400 because\n // the admin pane should never send `categories=` with no values.\n if (cleaned.size === 0) {\n throw new Error(\"graphSnapshot: categories must contain at least one non-empty value\");\n }\n return cleaned;\n}\n\nfunction buildNodeIndex(\n edges: GraphEdge[],\n metadata: Map<string, GraphSnapshotNodeMetadata>,\n): GraphSnapshotNode[] {\n type Aggregate = {\n score: number;\n lastUpdatedMs: number | null;\n lastUpdatedIso: string | null;\n };\n const aggregates = new Map<string, Aggregate>();\n\n function bump(id: string, edge: GraphEdge): void {\n const current = aggregates.get(id) ?? {\n score: 0,\n lastUpdatedMs: null,\n lastUpdatedIso: null,\n };\n current.score += readEdgeConfidence(edge);\n const ms = Date.parse(edge.ts);\n if (Number.isFinite(ms) && (current.lastUpdatedMs === null || ms > current.lastUpdatedMs)) {\n current.lastUpdatedMs = ms;\n current.lastUpdatedIso = edge.ts;\n }\n aggregates.set(id, current);\n }\n\n for (const edge of edges) {\n bump(edge.from, edge);\n bump(edge.to, edge);\n }\n\n // Stable order: descending score, then ascending id for determinism.\n const ids = Array.from(aggregates.keys()).sort((a, b) => {\n const aScore = aggregates.get(a)?.score ?? 0;\n const bScore = aggregates.get(b)?.score ?? 0;\n if (aScore !== bScore) return bScore - aScore;\n if (a === b) return 0;\n return a < b ? -1 : 1;\n });\n\n return ids.map((id) => {\n const meta = metadata.get(id);\n const aggregate = aggregates.get(id);\n return {\n id,\n label: meta?.label ?? defaultLabelFromPath(id),\n kind: meta?.category ?? \"unknown\",\n score: Number((aggregate?.score ?? 0).toFixed(4)),\n lastUpdated: aggregate?.lastUpdatedIso ?? null,\n };\n });\n}\n\nfunction defaultLabelFromPath(relPath: string): string {\n const base = path.basename(relPath, path.extname(relPath));\n return base.length > 0 ? base : relPath;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
listMemoryGovernanceRuns,
|
|
12
12
|
readMemoryGovernanceRunArtifact
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-EDOQM4E4.js";
|
|
14
14
|
import {
|
|
15
15
|
StorageManager
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-EVPNWN7Z.js";
|
|
17
17
|
import {
|
|
18
18
|
MEMORY_LIFECYCLE_EVENT_SORT_ORDER,
|
|
19
19
|
buildLifecycleEventsForMemory,
|
|
@@ -929,4 +929,4 @@ export {
|
|
|
929
929
|
verifyMemoryProjection,
|
|
930
930
|
repairMemoryProjection
|
|
931
931
|
};
|
|
932
|
-
//# sourceMappingURL=chunk-
|
|
932
|
+
//# sourceMappingURL=chunk-TXQCG6SE.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AdapterRegistry
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RKNJBZ55.js";
|
|
4
4
|
import {
|
|
5
5
|
WearablesInputError
|
|
6
6
|
} from "./chunk-7WV3F5DQ.js";
|
|
@@ -17,19 +17,19 @@ import {
|
|
|
17
17
|
markPlanResolved,
|
|
18
18
|
markPromotionResolved,
|
|
19
19
|
sessionBelongsToPrincipal
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-B7WISIAJ.js";
|
|
21
21
|
import {
|
|
22
22
|
validateRequest
|
|
23
23
|
} from "./chunk-FVZ2ISIX.js";
|
|
24
24
|
import {
|
|
25
25
|
getOperation
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-LLUGAZ3B.js";
|
|
27
27
|
import {
|
|
28
28
|
EngramAccessInputError
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-GDUOCHCD.js";
|
|
30
30
|
import {
|
|
31
31
|
CorrectionContractError
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-VCLGUIFM.js";
|
|
33
33
|
import {
|
|
34
34
|
isTrustZoneName
|
|
35
35
|
} from "./chunk-JGSKJHF7.js";
|
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
} from "./chunk-DEUNUKTD.js";
|
|
42
42
|
import {
|
|
43
43
|
isRecallDisclosure
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-ILFSEIRT.js";
|
|
45
45
|
import {
|
|
46
46
|
OFFLINE_SYNC_APPLY_MAX_BODY_BYTES,
|
|
47
47
|
OFFLINE_SYNC_FILE_CONTENT_MAX_CHUNK_BYTES,
|
|
@@ -2528,4 +2528,4 @@ function positiveIntQueryParam(value, label) {
|
|
|
2528
2528
|
export {
|
|
2529
2529
|
EngramAccessHttpServer
|
|
2530
2530
|
};
|
|
2531
|
-
//# sourceMappingURL=chunk-
|
|
2531
|
+
//# sourceMappingURL=chunk-UIXXE6NI.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
StorageManager,
|
|
3
3
|
normalizeEntityName
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-EVPNWN7Z.js";
|
|
5
5
|
import {
|
|
6
6
|
serializeMutations
|
|
7
7
|
} from "./chunk-LTJAMRGI.js";
|
|
@@ -956,4 +956,4 @@ export {
|
|
|
956
956
|
resolveBriefingSaveDir,
|
|
957
957
|
briefingFilename
|
|
958
958
|
};
|
|
959
|
-
//# sourceMappingURL=chunk-
|
|
959
|
+
//# sourceMappingURL=chunk-UO5ZHIIH.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
enqueuePassiveCorrectionNotification
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UO5ZHIIH.js";
|
|
4
4
|
import {
|
|
5
5
|
stripAttributesSuffix
|
|
6
6
|
} from "./chunk-SVOZFLIQ.js";
|
|
@@ -1685,4 +1685,4 @@ export {
|
|
|
1685
1685
|
capturePassiveCorrections,
|
|
1686
1686
|
clusterByKey
|
|
1687
1687
|
};
|
|
1688
|
-
//# sourceMappingURL=chunk-
|
|
1688
|
+
//# sourceMappingURL=chunk-VCLGUIFM.js.map
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
getGatewayRuntimeAuthForModel,
|
|
3
3
|
resolveProviderApiKey
|
|
4
4
|
} from "./chunk-IQVQJJL7.js";
|
|
5
|
-
import {
|
|
6
|
-
loadModelsJsonProviders
|
|
7
|
-
} from "./chunk-VL7DP3OW.js";
|
|
8
5
|
import {
|
|
9
6
|
buildChatCompletionTemperature,
|
|
10
7
|
buildChatCompletionTokenLimit,
|
|
11
8
|
shouldAssumeOpenAiChatCompletions
|
|
12
9
|
} from "./chunk-L2EXJQJP.js";
|
|
10
|
+
import {
|
|
11
|
+
loadModelsJsonProviders
|
|
12
|
+
} from "./chunk-VL7DP3OW.js";
|
|
13
13
|
import {
|
|
14
14
|
extractJsonCandidates
|
|
15
15
|
} from "./chunk-RGMVMVMF.js";
|
|
@@ -698,4 +698,4 @@ export {
|
|
|
698
698
|
fallbackLlmRuntimeContextFromConfig,
|
|
699
699
|
FallbackLlmClient
|
|
700
700
|
};
|
|
701
|
-
//# sourceMappingURL=chunk-
|
|
701
|
+
//# sourceMappingURL=chunk-VUA4S7P6.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-UFS7OXGL.js";
|
|
5
5
|
import {
|
|
6
6
|
StorageManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EVPNWN7Z.js";
|
|
8
8
|
import {
|
|
9
9
|
parseContinuityImprovementLoops
|
|
10
10
|
} from "./chunk-LDXUBPMO.js";
|
|
@@ -1261,4 +1261,4 @@ export {
|
|
|
1261
1261
|
defaultTierMigrationCycleBudget,
|
|
1262
1262
|
CompoundingEngine
|
|
1263
1263
|
};
|
|
1264
|
-
//# sourceMappingURL=chunk-
|
|
1264
|
+
//# sourceMappingURL=chunk-WQYSDPMA.js.map
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/local-model-endpoint.ts
|
|
2
|
+
function resolveFaithfulnessGateEndpoint(config) {
|
|
3
|
+
const baseUrl = config.extractionFaithfulnessBaseUrl.trim();
|
|
4
|
+
const model = config.extractionFaithfulnessModel.trim();
|
|
5
|
+
if (!baseUrl || !model) return null;
|
|
6
|
+
return { baseUrl, model };
|
|
7
|
+
}
|
|
8
|
+
function resolveCorrectionIntentEndpoint(config) {
|
|
9
|
+
const baseUrl = config.correctionIntentBaseUrl.trim();
|
|
10
|
+
const model = config.correctionIntentModel.trim();
|
|
11
|
+
if (!baseUrl || !model) return null;
|
|
12
|
+
return { baseUrl, model };
|
|
13
|
+
}
|
|
14
|
+
async function callOpenAiCompatibleChat(endpoint, messages, options, fetchImpl = fetch) {
|
|
15
|
+
const url = joinBaseUrl(endpoint.baseUrl, "/chat/completions");
|
|
16
|
+
const controller = new AbortController();
|
|
17
|
+
const timer = setTimeout(() => controller.abort(), options.timeoutMs);
|
|
18
|
+
try {
|
|
19
|
+
const body = {
|
|
20
|
+
model: endpoint.model,
|
|
21
|
+
messages,
|
|
22
|
+
temperature: options.temperature ?? 0.1
|
|
23
|
+
};
|
|
24
|
+
if (typeof options.maxTokens === "number") {
|
|
25
|
+
body.max_tokens = options.maxTokens;
|
|
26
|
+
}
|
|
27
|
+
if (options.responseFormatJson) {
|
|
28
|
+
body.response_format = { type: "json_object" };
|
|
29
|
+
}
|
|
30
|
+
let response;
|
|
31
|
+
try {
|
|
32
|
+
response = await fetchImpl(url, {
|
|
33
|
+
method: "POST",
|
|
34
|
+
headers: { "content-type": "application/json" },
|
|
35
|
+
body: JSON.stringify(body),
|
|
36
|
+
signal: controller.signal
|
|
37
|
+
});
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!response.ok) return null;
|
|
42
|
+
const parsed = await response.json().catch(() => null);
|
|
43
|
+
const content = extractFirstChoiceContent(parsed);
|
|
44
|
+
if (content === null) return null;
|
|
45
|
+
return { content, modelUsed: extractModel(parsed) ?? endpoint.model };
|
|
46
|
+
} finally {
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function joinBaseUrl(base, path) {
|
|
51
|
+
return base.endsWith("/") ? `${base.slice(0, -1)}${path}` : `${base}${path}`;
|
|
52
|
+
}
|
|
53
|
+
function extractFirstChoiceContent(data) {
|
|
54
|
+
if (!data || typeof data !== "object") return null;
|
|
55
|
+
if (!("choices" in data) || !Array.isArray(data.choices)) return null;
|
|
56
|
+
const choices = data.choices;
|
|
57
|
+
for (const choice of choices) {
|
|
58
|
+
if (!choice || typeof choice !== "object") continue;
|
|
59
|
+
if (!("message" in choice)) continue;
|
|
60
|
+
const message = choice.message;
|
|
61
|
+
if (!message || typeof message !== "object") continue;
|
|
62
|
+
if (!("content" in message)) continue;
|
|
63
|
+
const content = message.content;
|
|
64
|
+
if (typeof content === "string" && content.length > 0) return content;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
function extractModel(data) {
|
|
69
|
+
if (!data || typeof data !== "object" || !("model" in data)) return null;
|
|
70
|
+
const model = data.model;
|
|
71
|
+
return typeof model === "string" && model.length > 0 ? model : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
resolveFaithfulnessGateEndpoint,
|
|
76
|
+
resolveCorrectionIntentEndpoint,
|
|
77
|
+
callOpenAiCompatibleChat
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=chunk-XGTBNVIU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/local-model-endpoint.ts"],"sourcesContent":["/**\n * Local fine-tuned model endpoint resolver + openai-compatible caller\n * (issue #1585 model-lab integration).\n *\n * Remnic's two classification workloads — the extraction faithfulness gate\n * (#1576) and passive-correction intent detection (#1581) — can run on small\n * fine-tuned models served locally (Ollama / vLLM) instead of prompted\n * frontier LLMs. The model-lab (`model-lab/`) produces those models; this\n * module is the config-side half: it resolves the optional local endpoint\n * pointer from config and, when set, makes a minimal openai-compatible\n * chat-completions call to it.\n *\n * Design:\n * - **Pointers are optional.** Empty defaults preserve the existing routing\n * chain exactly (rule 39 / byte-identical pre-feature). A resolver returns\n * `null` when the pointer is unset, so callers short-circuit before any\n * network.\n * - **Graceful degradation.** A local-endpoint failure (network, non-2xx,\n * malformed body, timeout) returns `null`; callers fall back to the\n * configured chain (checklist §4 — never block writes on a classifier).\n * - **No inline casts.** The fetch JSON is narrowed with `in` / `typeof`\n * guards (project rule: never assert a shape to read one property).\n * - **Injectable fetch.** `callOpenAiCompatibleChat` takes an optional\n * `fetchImpl` so the caller is unit-testable without a live server.\n */\n\nimport type { PluginConfig } from \"./types.js\";\n\n/** A resolved local endpoint: where to call + which model to name. */\nexport interface LocalModelEndpoint {\n /** Base URL, e.g. `http://localhost:11434/v1` (no trailing slash required). */\n baseUrl: string;\n /** Model name the server expects, e.g. `remnic-faithfulness-gate-v1`. */\n model: string;\n}\n\n/** A chat message in the openai-compatible shape this caller sends. */\nexport interface EndpointChatMessage {\n role: \"system\" | \"user\" | \"assistant\";\n content: string;\n}\n\n/** Options for a single local-endpoint chat call. */\nexport interface EndpointChatOptions {\n /** Per-call timeout in ms. The caller's batch AbortSignal is NOT forwarded\n * (matches the local-LLM precedent: each attempt is bounded by its own\n * timer so one slow server can't starve the batch). */\n timeoutMs: number;\n /** Sampling temperature — classification wants low entropy (0.0–0.2). */\n temperature?: number;\n /** Max output tokens. */\n maxTokens?: number;\n /** Request JSON-object output (the gate emits a JSON verdict array). */\n responseFormatJson?: boolean;\n}\n\n/** Result of a local-endpoint chat call. */\nexport interface EndpointChatResult {\n content: string;\n /** The model the server reports it used (falls back to the requested name). */\n modelUsed: string;\n}\n\n/**\n * Resolve the faithfulness-gate local endpoint from config (issue #1585).\n *\n * Returns the endpoint only when BOTH a base URL and a model name are\n * configured; otherwise `null` (gate uses its existing routing chain). The\n * gate's verifier needs a model identity, so a base URL alone is intentionally\n * insufficient — silently calling whatever the server's default model is would\n * be an unreviewed behavioral change.\n */\nexport function resolveFaithfulnessGateEndpoint(\n config: Pick<PluginConfig, \"extractionFaithfulnessModel\" | \"extractionFaithfulnessBaseUrl\">,\n): LocalModelEndpoint | null {\n const baseUrl = config.extractionFaithfulnessBaseUrl.trim();\n const model = config.extractionFaithfulnessModel.trim();\n if (!baseUrl || !model) return null;\n return { baseUrl, model };\n}\n\n/**\n * Resolve the correction-intent local endpoint from config (issue #1581/#1585).\n *\n * Same contract as the gate resolver. Consumption by the model-backed\n * detector is the consuming child's job — the rule-based\n * `detectPassiveCorrections` remains the default path; this pointer lets a\n * future model-backed detector route to a fine-tuned local classifier when an\n * operator configures one.\n */\nexport function resolveCorrectionIntentEndpoint(\n config: Pick<PluginConfig, \"correctionIntentModel\" | \"correctionIntentBaseUrl\">,\n): LocalModelEndpoint | null {\n const baseUrl = config.correctionIntentBaseUrl.trim();\n const model = config.correctionIntentModel.trim();\n if (!baseUrl || !model) return null;\n return { baseUrl, model };\n}\n\ntype FetchLike = typeof fetch;\n\n/**\n * Make an openai-compatible chat-completions call to a local endpoint.\n *\n * POSTs to `${baseUrl}/chat/completions` with `{ model, messages, ... }` and\n * returns the first choice's content. Any failure (non-2xx, network error,\n * malformed body, timeout) returns `null` so callers fall back gracefully.\n *\n * The response is narrowed with runtime guards — never an unchecked cast — so\n * a surprising server response fails closed (`null`) rather than reading a\n * fabricated field.\n */\nexport async function callOpenAiCompatibleChat(\n endpoint: LocalModelEndpoint,\n messages: EndpointChatMessage[],\n options: EndpointChatOptions,\n fetchImpl: FetchLike = fetch,\n): Promise<EndpointChatResult | null> {\n const url = joinBaseUrl(endpoint.baseUrl, \"/chat/completions\");\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), options.timeoutMs);\n try {\n const body: Record<string, unknown> = {\n model: endpoint.model,\n messages,\n temperature: options.temperature ?? 0.1,\n };\n if (typeof options.maxTokens === \"number\") {\n body.max_tokens = options.maxTokens;\n }\n if (options.responseFormatJson) {\n body.response_format = { type: \"json_object\" };\n }\n let response: Response;\n try {\n response = await fetchImpl(url, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n } catch {\n // Network error or abort — fail closed, let the caller fall back.\n return null;\n }\n if (!response.ok) return null;\n const parsed: unknown = await response.json().catch(() => null);\n const content = extractFirstChoiceContent(parsed);\n if (content === null) return null;\n return { content, modelUsed: extractModel(parsed) ?? endpoint.model };\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** Join a base URL and a path, tolerating a trailing slash on the base. */\nfunction joinBaseUrl(base: string, path: string): string {\n return base.endsWith(\"/\") ? `${base.slice(0, -1)}${path}` : `${base}${path}`;\n}\n\n/**\n * Narrow the openai-compatible response and pull the first choice's content.\n *\n * `in` / `typeof` guards only — no `as` cast (project rule). Returns `null`\n * for any shape that isn't `{ choices: [{ message: { content: string } }, …] }`.\n */\nfunction extractFirstChoiceContent(data: unknown): string | null {\n if (!data || typeof data !== \"object\") return null;\n // After `in`, TS narrows the property to `unknown` — read it directly, no cast.\n if (!(\"choices\" in data) || !Array.isArray(data.choices)) return null;\n const choices: unknown[] = data.choices;\n for (const choice of choices) {\n if (!choice || typeof choice !== \"object\") continue;\n if (!(\"message\" in choice)) continue;\n const message = choice.message;\n if (!message || typeof message !== \"object\") continue;\n if (!(\"content\" in message)) continue;\n const content = message.content;\n if (typeof content === \"string\" && content.length > 0) return content;\n }\n return null;\n}\n\n/** Narrow the `model` field from the response (best-effort, may be absent). */\nfunction extractModel(data: unknown): string | null {\n if (!data || typeof data !== \"object\" || !(\"model\" in data)) return null;\n const model = data.model;\n return typeof model === \"string\" && model.length > 0 ? model : null;\n}\n"],"mappings":";AAwEO,SAAS,gCACd,QAC2B;AAC3B,QAAM,UAAU,OAAO,8BAA8B,KAAK;AAC1D,QAAM,QAAQ,OAAO,4BAA4B,KAAK;AACtD,MAAI,CAAC,WAAW,CAAC,MAAO,QAAO;AAC/B,SAAO,EAAE,SAAS,MAAM;AAC1B;AAWO,SAAS,gCACd,QAC2B;AAC3B,QAAM,UAAU,OAAO,wBAAwB,KAAK;AACpD,QAAM,QAAQ,OAAO,sBAAsB,KAAK;AAChD,MAAI,CAAC,WAAW,CAAC,MAAO,QAAO;AAC/B,SAAO,EAAE,SAAS,MAAM;AAC1B;AAeA,eAAsB,yBACpB,UACA,UACA,SACA,YAAuB,OACa;AACpC,QAAM,MAAM,YAAY,SAAS,SAAS,mBAAmB;AAC7D,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,QAAQ,WAAW,MAAM,WAAW,MAAM,GAAG,QAAQ,SAAS;AACpE,MAAI;AACF,UAAM,OAAgC;AAAA,MACpC,OAAO,SAAS;AAAA,MAChB;AAAA,MACA,aAAa,QAAQ,eAAe;AAAA,IACtC;AACA,QAAI,OAAO,QAAQ,cAAc,UAAU;AACzC,WAAK,aAAa,QAAQ;AAAA,IAC5B;AACA,QAAI,QAAQ,oBAAoB;AAC9B,WAAK,kBAAkB,EAAE,MAAM,cAAc;AAAA,IAC/C;AACA,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,UAAU,KAAK;AAAA,QAC9B,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAAA,IACH,QAAQ;AAEN,aAAO;AAAA,IACT;AACA,QAAI,CAAC,SAAS,GAAI,QAAO;AACzB,UAAM,SAAkB,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AAC9D,UAAM,UAAU,0BAA0B,MAAM;AAChD,QAAI,YAAY,KAAM,QAAO;AAC7B,WAAO,EAAE,SAAS,WAAW,aAAa,MAAM,KAAK,SAAS,MAAM;AAAA,EACtE,UAAE;AACA,iBAAa,KAAK;AAAA,EACpB;AACF;AAGA,SAAS,YAAY,MAAc,MAAsB;AACvD,SAAO,KAAK,SAAS,GAAG,IAAI,GAAG,KAAK,MAAM,GAAG,EAAE,CAAC,GAAG,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;AAC5E;AAQA,SAAS,0BAA0B,MAA8B;AAC/D,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,MAAI,EAAE,aAAa,SAAS,CAAC,MAAM,QAAQ,KAAK,OAAO,EAAG,QAAO;AACjE,QAAM,UAAqB,KAAK;AAChC,aAAW,UAAU,SAAS;AAC5B,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,QAAI,EAAE,aAAa,QAAS;AAC5B,UAAM,UAAU,OAAO;AACvB,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU;AAC7C,QAAI,EAAE,aAAa,SAAU;AAC7B,UAAM,UAAU,QAAQ;AACxB,QAAI,OAAO,YAAY,YAAY,QAAQ,SAAS,EAAG,QAAO;AAAA,EAChE;AACA,SAAO;AACT;AAGA,SAAS,aAAa,MAA8B;AAClD,MAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,EAAE,WAAW,MAAO,QAAO;AACpE,QAAM,QAAQ,KAAK;AACnB,SAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ;AACjE;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-ZBJMUXZH.js";
|
|
5
5
|
import {
|
|
6
6
|
StorageManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-EVPNWN7Z.js";
|
|
8
8
|
import {
|
|
9
9
|
getCachedRuleMemories,
|
|
10
10
|
setCachedRuleMemories
|
|
@@ -117,4 +117,4 @@ export {
|
|
|
117
117
|
compareVerifiedSemanticRuleResults,
|
|
118
118
|
searchVerifiedSemanticRules
|
|
119
119
|
};
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
120
|
+
//# sourceMappingURL=chunk-YEE5KJQQ.js.map
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
// src/trust-score.ts
|
|
2
|
+
var DEFAULT_TRUST_WEIGHTS = {
|
|
3
|
+
memoryWorth: 0.28,
|
|
4
|
+
provenance: 0.16,
|
|
5
|
+
faithfulness: 0.2,
|
|
6
|
+
corroboration: 0.12,
|
|
7
|
+
contradiction: 0.1,
|
|
8
|
+
domainCalibration: 0.04,
|
|
9
|
+
feedback: 0.05,
|
|
10
|
+
recency: 0.05
|
|
11
|
+
};
|
|
12
|
+
var TRUST_BAND_THRESHOLDS = {
|
|
13
|
+
high: 0.7,
|
|
14
|
+
medium: 0.45,
|
|
15
|
+
low: 0.2
|
|
16
|
+
};
|
|
17
|
+
var NEUTRAL_TRUST_SCORE = 0.5;
|
|
18
|
+
function sanitizeWeight(value) {
|
|
19
|
+
if (value === void 0) return void 0;
|
|
20
|
+
if (typeof value !== "number") return void 0;
|
|
21
|
+
if (!Number.isFinite(value)) return void 0;
|
|
22
|
+
if (value < 0 || value > 1) return void 0;
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
function resolveTrustWeights(override) {
|
|
26
|
+
const out = { ...DEFAULT_TRUST_WEIGHTS };
|
|
27
|
+
if (!override) return out;
|
|
28
|
+
Object.keys(DEFAULT_TRUST_WEIGHTS).forEach((key) => {
|
|
29
|
+
const v = sanitizeWeight(override[key]);
|
|
30
|
+
if (v !== void 0) out[key] = v;
|
|
31
|
+
});
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
function clampUnit(value) {
|
|
35
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return NEUTRAL_TRUST_SCORE;
|
|
36
|
+
if (value < 0) return 0;
|
|
37
|
+
if (value > 1) return 1;
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function unitValue(value) {
|
|
41
|
+
if (value === void 0) return void 0;
|
|
42
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
|
|
43
|
+
if (value < 0 || value > 1) return void 0;
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
function provenanceValue(tag) {
|
|
47
|
+
if (tag === void 0) return void 0;
|
|
48
|
+
if (tag === "verified") return 1;
|
|
49
|
+
if (tag === "unverified") return 0.5;
|
|
50
|
+
if (tag === "none") return 0.25;
|
|
51
|
+
return void 0;
|
|
52
|
+
}
|
|
53
|
+
function faithfulnessValue(verdict) {
|
|
54
|
+
if (verdict === void 0) return void 0;
|
|
55
|
+
if (verdict === "entailed") return 1;
|
|
56
|
+
if (verdict === "unchecked") return void 0;
|
|
57
|
+
if (verdict === "unsupported") return 0.35;
|
|
58
|
+
if (verdict === "contradicted") return 0;
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
function contradictionValue(status) {
|
|
62
|
+
if (status === void 0) return void 0;
|
|
63
|
+
if (status === "none") return NEUTRAL_TRUST_SCORE;
|
|
64
|
+
if (status === "resolved_kept") return 0.7;
|
|
65
|
+
if (status === "resolved_superseded") return 0.1;
|
|
66
|
+
if (status === "pending_review") return 0.15;
|
|
67
|
+
return void 0;
|
|
68
|
+
}
|
|
69
|
+
function feedbackValue(fb) {
|
|
70
|
+
if (fb === void 0) return void 0;
|
|
71
|
+
const up = typeof fb.up === "number" && Number.isFinite(fb.up) && fb.up >= 0 ? fb.up : 0;
|
|
72
|
+
const down = typeof fb.down === "number" && Number.isFinite(fb.down) && fb.down >= 0 ? fb.down : 0;
|
|
73
|
+
if (up === 0 && down === 0) return void 0;
|
|
74
|
+
return clampUnit((up + 1) / (up + down + 2));
|
|
75
|
+
}
|
|
76
|
+
function corroborationValue(count) {
|
|
77
|
+
if (count === void 0) return void 0;
|
|
78
|
+
if (typeof count !== "number" || !Number.isFinite(count) || count < 0) return void 0;
|
|
79
|
+
if (count === 0) return 0.3;
|
|
80
|
+
return clampUnit(Math.log2(1 + count) / 2);
|
|
81
|
+
}
|
|
82
|
+
function recencyValue(signals) {
|
|
83
|
+
if (signals.ageDays === void 0) return void 0;
|
|
84
|
+
if (typeof signals.ageDays !== "number" || !Number.isFinite(signals.ageDays) || signals.ageDays < 0)
|
|
85
|
+
return void 0;
|
|
86
|
+
const halfLife = signals.recencyHalfLifeDays;
|
|
87
|
+
if (typeof halfLife !== "number" || !Number.isFinite(halfLife) || halfLife <= 0) return void 0;
|
|
88
|
+
return clampUnit(Math.pow(2, -signals.ageDays / halfLife));
|
|
89
|
+
}
|
|
90
|
+
function isHardNegative(signals) {
|
|
91
|
+
if (signals.faithfulness === "contradicted") return true;
|
|
92
|
+
if (signals.contradiction === "pending_review") return true;
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
function computeTrustScore(signals = {}, weights = DEFAULT_TRUST_WEIGHTS) {
|
|
96
|
+
const resolved = resolveTrustWeights(weights);
|
|
97
|
+
const candidates = [];
|
|
98
|
+
const push = (key, value) => {
|
|
99
|
+
if (value === void 0) return;
|
|
100
|
+
candidates.push({ key, value: clampUnit(value) });
|
|
101
|
+
};
|
|
102
|
+
push("memoryWorth", signals.memoryWorth ? clampUnit(signals.memoryWorth.score) : void 0);
|
|
103
|
+
push("provenance", provenanceValue(signals.provenance));
|
|
104
|
+
push("faithfulness", faithfulnessValue(signals.faithfulness));
|
|
105
|
+
push("corroboration", corroborationValue(signals.corroborationCount));
|
|
106
|
+
push("contradiction", contradictionValue(signals.contradiction));
|
|
107
|
+
push("domainCalibration", unitValue(signals.domainCalibration));
|
|
108
|
+
push("feedback", feedbackValue(signals.feedback));
|
|
109
|
+
push("recency", recencyValue(signals));
|
|
110
|
+
if (candidates.length === 0) {
|
|
111
|
+
return {
|
|
112
|
+
score: NEUTRAL_TRUST_SCORE,
|
|
113
|
+
band: "medium",
|
|
114
|
+
components: {},
|
|
115
|
+
neutral: true
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
const activeWeightSum = candidates.reduce((acc, c) => acc + resolved[c.key], 0);
|
|
119
|
+
if (activeWeightSum <= 0) {
|
|
120
|
+
return {
|
|
121
|
+
score: NEUTRAL_TRUST_SCORE,
|
|
122
|
+
band: "medium",
|
|
123
|
+
components: {},
|
|
124
|
+
neutral: true
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const safeWeightSum = activeWeightSum;
|
|
128
|
+
let blended = 0;
|
|
129
|
+
const components = {};
|
|
130
|
+
for (const c of candidates) {
|
|
131
|
+
const w = resolved[c.key] / safeWeightSum;
|
|
132
|
+
blended += c.value * w;
|
|
133
|
+
components[c.key] = { value: c.value, weight: w };
|
|
134
|
+
}
|
|
135
|
+
const score = clampUnit(blended);
|
|
136
|
+
const band = bandForScore(score, isHardNegative(signals));
|
|
137
|
+
return { score, band, components, neutral: false };
|
|
138
|
+
}
|
|
139
|
+
function bandForScore(score, hardNegative) {
|
|
140
|
+
if (hardNegative) return "quarantine";
|
|
141
|
+
const s = clampUnit(score);
|
|
142
|
+
if (s >= TRUST_BAND_THRESHOLDS.high) return "high";
|
|
143
|
+
if (s >= TRUST_BAND_THRESHOLDS.medium) return "medium";
|
|
144
|
+
if (s >= TRUST_BAND_THRESHOLDS.low) return "low";
|
|
145
|
+
return "low";
|
|
146
|
+
}
|
|
147
|
+
function trustMultiplier(score, minMultiplier = 0.5, maxMultiplier = 1.25) {
|
|
148
|
+
const min = typeof minMultiplier === "number" && Number.isFinite(minMultiplier) ? minMultiplier : 0.5;
|
|
149
|
+
const max = typeof maxMultiplier === "number" && Number.isFinite(maxMultiplier) ? maxMultiplier : 1.25;
|
|
150
|
+
const lo = Math.min(min, max);
|
|
151
|
+
const hi = Math.max(min, max);
|
|
152
|
+
const s = clampUnit(score);
|
|
153
|
+
if (s === NEUTRAL_TRUST_SCORE) return 1;
|
|
154
|
+
if (s < NEUTRAL_TRUST_SCORE) {
|
|
155
|
+
const t2 = s / NEUTRAL_TRUST_SCORE;
|
|
156
|
+
return lo + (1 - lo) * t2;
|
|
157
|
+
}
|
|
158
|
+
const t = (s - NEUTRAL_TRUST_SCORE) / (1 - NEUTRAL_TRUST_SCORE);
|
|
159
|
+
return 1 + (hi - 1) * t;
|
|
160
|
+
}
|
|
161
|
+
function renderEpistemicHedge(result) {
|
|
162
|
+
if (result.neutral) return "";
|
|
163
|
+
switch (result.band) {
|
|
164
|
+
case "high":
|
|
165
|
+
return "";
|
|
166
|
+
case "quarantine":
|
|
167
|
+
case "low":
|
|
168
|
+
return `(low confidence \u2014 ${describeWeakness(result.components)})`;
|
|
169
|
+
case "medium":
|
|
170
|
+
return `(unconfirmed \u2014 ${describeWeakness(result.components)})`;
|
|
171
|
+
default:
|
|
172
|
+
return "";
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function describeWeakness(components) {
|
|
176
|
+
const parts = [];
|
|
177
|
+
const f = components.faithfulness;
|
|
178
|
+
if (f && f.value <= 0.35) parts.push(f.value === 0 ? "contradicted" : "unsupported");
|
|
179
|
+
const c = components.contradiction;
|
|
180
|
+
if (c && c.value <= 0.2) parts.push("under review");
|
|
181
|
+
const cor = components.corroboration;
|
|
182
|
+
if (cor && cor.value <= 0.4) parts.push("single mention");
|
|
183
|
+
const prov = components.provenance;
|
|
184
|
+
if (prov && prov.value <= 0.3) parts.push("unprovenanced");
|
|
185
|
+
const rec = components.recency;
|
|
186
|
+
if (rec && rec.value <= 0.3) parts.push("stale");
|
|
187
|
+
if (parts.length === 0) {
|
|
188
|
+
let weakest = null;
|
|
189
|
+
for (const [key, comp] of Object.entries(components)) {
|
|
190
|
+
if (!weakest || comp.value < weakest.value) weakest = { key, value: comp.value };
|
|
191
|
+
}
|
|
192
|
+
if (weakest) parts.push(`weak ${humanizeComponentName(weakest.key)}`);
|
|
193
|
+
}
|
|
194
|
+
return parts.slice(0, 2).join(", ");
|
|
195
|
+
}
|
|
196
|
+
function humanizeComponentName(key) {
|
|
197
|
+
switch (key) {
|
|
198
|
+
case "memoryWorth":
|
|
199
|
+
return "outcome history";
|
|
200
|
+
case "domainCalibration":
|
|
201
|
+
return "domain calibration";
|
|
202
|
+
default:
|
|
203
|
+
return key;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export {
|
|
208
|
+
DEFAULT_TRUST_WEIGHTS,
|
|
209
|
+
TRUST_BAND_THRESHOLDS,
|
|
210
|
+
NEUTRAL_TRUST_SCORE,
|
|
211
|
+
resolveTrustWeights,
|
|
212
|
+
computeTrustScore,
|
|
213
|
+
bandForScore,
|
|
214
|
+
trustMultiplier,
|
|
215
|
+
renderEpistemicHedge
|
|
216
|
+
};
|
|
217
|
+
//# sourceMappingURL=chunk-YN2UN7N3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/trust-score.ts"],"sourcesContent":["/**\n * trust-score.ts — unified TrustScore pure module (issue #1577 PR 1).\n *\n * Combines the trust-relevant signals Remnic already computes — memory worth\n * (Laplace-smoothed outcome probability + recency decay), provenance strength,\n * faithfulness verdict, corroboration count, contradiction status, and optional\n * domain calibration — into ONE deterministic score in `[0, 1]` plus a band\n * (`high` / `medium` / `low` / `quarantine`) and a fully-explained component\n * breakdown for X-ray.\n *\n * Contract rules (mirror the battle-tested `memory-worth.ts` \"corrupt inputs\n * fail safely\" header — read it before changing anything here):\n *\n * 1. **No signals → neutral.** An empty `TrustSignals` yields score `0.5`,\n * band `medium`, and a recall multiplier of exactly `1.0`. Uninstrumented\n * memories are NEVER penalized (rule 39 — byte-identical ranking when the\n * feature is off; neutral prior when on but a memory has no data).\n * 2. **Corrupt / out-of-range component → that component collapses to\n * neutral**, never to an extreme. A `NaN` weight or a `corroborationCount`\n * of `-3` is treated as \"no signal\", not as damning evidence. Precedent:\n * `memory-worth.ts` `classifyCounter`.\n * 3. **Deterministic.** Same inputs → identical result. All weights come from\n * the caller (config); no wall clock, no RNG, no hidden constants.\n * 4. **Explainable.** Every active component is echoed in the result with its\n * normalized weight and contribution, so X-ray can render the basis\n * without re-deriving the math.\n * 5. **`quarantine` is reserved for hard negatives** — `faithfulness:\n * \"contradicted\"` or `contradiction: \"pending_review\"`. Quarantined items\n * are excluded from injection but MUST stay visible in X-ray with the\n * reason (rule 34 — exclusion must never look like \"no result\").\n *\n * This module is deliberately framework-free: it takes already-collected\n * signals and config weights, returns a score. The signal ADAPTERS (reading\n * frontmatter / counters / review queues) live in `trust-score-stage.ts` so\n * this file stays pure and trivially property-testable.\n */\n\n/**\n * Per-component weights. Defined canonically in `types.ts` (the PluginConfig\n * home) and re-exported here so callers of the pure scorer don't need a second\n * import path. Every field is optional and defaults to\n * `DEFAULT_TRUST_WEIGHTS`; weights are sum-normalized at score time, so only\n * their relative magnitudes matter (rule 51: invalid weight rejected at config\n * parse, here we only defend against runtime corruption).\n */\nexport type { TrustWeights } from \"./types.js\";\nimport type { TrustWeights } from \"./types.js\";\n\n/**\n * Default per-component weights. Chosen so that, with all signals at neutral,\n * the score is exactly `0.5`. Sum-normalized at compute time. These are the\n * documented defaults; operators override via `trustScore.weights.*` config.\n */\nexport const DEFAULT_TRUST_WEIGHTS: Required<TrustWeights> = {\n memoryWorth: 0.28,\n provenance: 0.16,\n faithfulness: 0.20,\n corroboration: 0.12,\n contradiction: 0.10,\n domainCalibration: 0.04,\n feedback: 0.05,\n recency: 0.05,\n};\n\n/**\n * All trust-relevant signals for ONE memory. Every field is optional — the\n * scorer degrades to neutral for any absent or corrupt signal (rule 34).\n */\nexport interface TrustSignals {\n /** Memory-worth result (Laplace success prob + confidence). */\n memoryWorth?: { score: number; confidence: number };\n /** Thumbs feedback tallies. */\n feedback?: { up: number; down: number };\n /** Contradiction review queue status. */\n contradiction?: \"none\" | \"pending_review\" | \"resolved_kept\" | \"resolved_superseded\";\n /** Claim-level provenance strength (#1575). */\n provenance?: \"verified\" | \"unverified\" | \"none\";\n /** Faithfulness gate verdict (#1576). */\n faithfulness?: \"entailed\" | \"contradicted\" | \"unsupported\" | \"unchecked\";\n /** Count of distinct source turns/sessions corroborating the fact. */\n corroborationCount?: number;\n /** Belief-ledger accuracy for the memory's domain, `0..1`. */\n domainCalibration?: number;\n /** Age in days vs a per-category half-life (caller computes). */\n ageDays?: number;\n /** Half-life (days) for recency decay; the caller supplies the per-category value. */\n recencyHalfLifeDays?: number;\n}\n\n/** Trust band, coarse-grained for injection hedging and X-ray grouping. */\nexport type TrustBand = \"high\" | \"medium\" | \"low\" | \"quarantine\";\n\n/**\n * One component's contribution to the final score, for full explainability.\n * `value` is the normalized `[0,1]` signal contribution; `weight` is the\n * sum-normalized weight that was applied.\n */\nexport interface TrustScoreComponent {\n value: number;\n weight: number;\n}\n\n/**\n * Full TrustScore result. `score` is the weighted blend in `[0,1]`; `band` is\n * the coarse category; `components` echoes every active component so X-ray /\n * epistemic rendering can explain the basis without re-deriving it.\n */\nexport interface TrustScoreResult {\n score: number;\n band: TrustBand;\n components: Record<string, TrustScoreComponent>;\n /**\n * `true` when the result is the neutral prior (no usable signals). Lets the\n * multiplier short-circuit to exactly `1.0` and the epistemic renderer skip\n * the hedge for the common uninstrumented case.\n */\n neutral: boolean;\n}\n\n/** Band thresholds on the blended score. */\nexport const TRUST_BAND_THRESHOLDS = {\n high: 0.7,\n medium: 0.45,\n low: 0.2,\n} as const;\n\n/** Neutral prior: the score an empty-signal memory receives. */\nexport const NEUTRAL_TRUST_SCORE = 0.5;\n\n/**\n * Validate a single weight: a finite number in `[0, 1]`. Returns the value or\n * `undefined` when corrupt (the caller falls back to the default).\n */\nfunction sanitizeWeight(value: number | undefined): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"number\") return undefined;\n if (!Number.isFinite(value)) return undefined;\n if (value < 0 || value > 1) return undefined;\n return value;\n}\n\n/**\n * Merge caller weights over the defaults, dropping corrupt entries. Exposed for\n * config parse so an invalid weight is rejected once at the boundary (rule 51\n * spirit) — but the scorer defends again here so a hand-built bench fixture\n * cannot poison the math.\n */\nexport function resolveTrustWeights(\n override: Readonly<TrustWeights> | undefined,\n): Required<TrustWeights> {\n const out: Required<TrustWeights> = { ...DEFAULT_TRUST_WEIGHTS };\n if (!override) return out;\n (Object.keys(DEFAULT_TRUST_WEIGHTS) as Array<keyof TrustWeights>).forEach((key) => {\n const v = sanitizeWeight(override[key]);\n if (v !== undefined) out[key] = v;\n });\n return out;\n}\n\n/** Clamp a value to `[0,1]`; NaN/Infinity collapse to the neutral `0.5`. */\nfunction clampUnit(value: number): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) return NEUTRAL_TRUST_SCORE;\n if (value < 0) return 0;\n if (value > 1) return 1;\n return value;\n}\n\n/**\n * Coerce an already-`[0,1]` signal (domain calibration, etc.) for the scorer.\n * Returns `undefined` when absent or corrupt so the component is DROPPED — a\n * single corrupt signal must not be read as damning evidence nor as a neutral\n * contribution that masquerades as \"we measured this\". Mirrors the\n * `classifyCounter` precedent from `memory-worth.ts`.\n */\nfunction unitValue(value: number | undefined): number | undefined {\n if (value === undefined) return undefined;\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n if (value < 0 || value > 1) return undefined;\n return value;\n}\n\n/** Map a provenance tag to a `[0,1]` contribution. Absent → neutral. */\nfunction provenanceValue(tag: TrustSignals[\"provenance\"]): number | undefined {\n if (tag === undefined) return undefined;\n if (tag === \"verified\") return 1;\n if (tag === \"unverified\") return 0.5;\n // \"none\" is meaningful negative evidence (no surviving source span), not\n // neutral. It pulls toward 0 but gently so a single unprovenanced fact is\n // not damned on its own.\n if (tag === \"none\") return 0.25;\n return undefined;\n}\n\n/** Map a faithfulness verdict to a `[0,1]` contribution. Absent → dropped. */\nfunction faithfulnessValue(verdict: TrustSignals[\"faithfulness\"]): number | undefined {\n if (verdict === undefined) return undefined;\n if (verdict === \"entailed\") return 1;\n // \"unchecked\" means the gate ran but could not verify — it carries NO signal.\n // Return undefined (absent) so a memory whose ONLY signal is unchecked\n // faithfulness scores truly neutral, not \"active 0.5\". This stops the\n // epistemic hedge from spuriously firing on unverifiable memories (review\n // Oqg_0: unchecked-as-absent for hedging) and stops the component from\n // masquerading as measured evidence.\n if (verdict === \"unchecked\") return undefined;\n if (verdict === \"unsupported\") return 0.35;\n // \"contradicted\" is a hard negative — it also forces quarantine (see below),\n // but as a component it contributes 0 so the blended score sinks.\n if (verdict === \"contradicted\") return 0;\n return undefined;\n}\n\n/** Map contradiction review status to a `[0,1]` contribution. */\nfunction contradictionValue(\n status: TrustSignals[\"contradiction\"],\n): number | undefined {\n if (status === undefined) return undefined;\n if (status === \"none\") return NEUTRAL_TRUST_SCORE;\n if (status === \"resolved_kept\") return 0.7;\n if (status === \"resolved_superseded\") return 0.1;\n if (status === \"pending_review\") return 0.15;\n return undefined;\n}\n\n/** Feedback balance → `[0,1]` via Laplace smoothing (mirrors memory-worth). */\nfunction feedbackValue(fb: TrustSignals[\"feedback\"]): number | undefined {\n if (fb === undefined) return undefined;\n const up = typeof fb.up === \"number\" && Number.isFinite(fb.up) && fb.up >= 0 ? fb.up : 0;\n const down =\n typeof fb.down === \"number\" && Number.isFinite(fb.down) && fb.down >= 0 ? fb.down : 0;\n if (up === 0 && down === 0) return undefined;\n // Laplace: (up+1)/(up+down+2). Clamped defensively.\n return clampUnit((up + 1) / (up + down + 2));\n}\n\n/** Corroboration count → `[0,1]` via log-saturation (3+ sources ≈ 1.0). */\nfunction corroborationValue(count: TrustSignals[\"corroborationCount\"]): number | undefined {\n if (count === undefined) return undefined;\n if (typeof count !== \"number\" || !Number.isFinite(count) || count < 0) return undefined;\n if (count === 0) return 0.3; // single mention is mild negative evidence vs neutral\n // log2(1 + count) saturates: 1→0.5, 2→0.63, 3→0.66, 4→0.68 ... capped at 1.\n return clampUnit(Math.log2(1 + count) / 2);\n}\n\n/** Recency decay vs a half-life, mapped so \"fresh\" → high, \"stale\" → low. */\nfunction recencyValue(signals: TrustSignals): number | undefined {\n if (signals.ageDays === undefined) return undefined;\n if (typeof signals.ageDays !== \"number\" || !Number.isFinite(signals.ageDays) || signals.ageDays < 0)\n return undefined;\n const halfLife = signals.recencyHalfLifeDays;\n if (typeof halfLife !== \"number\" || !Number.isFinite(halfLife) || halfLife <= 0) return undefined;\n // 2^(-age/halfLife): age 0 → 1, age=halfLife → 0.5, age≫halfLife → ~0.\n return clampUnit(Math.pow(2, -signals.ageDays / halfLife));\n}\n\n/**\n * Determine whether the signals warrant the `quarantine` band: a hard negative\n * that excludes the item from injection (but never from X-ray — rule 34).\n */\nfunction isHardNegative(signals: TrustSignals): boolean {\n if (signals.faithfulness === \"contradicted\") return true;\n if (signals.contradiction === \"pending_review\") return true;\n return false;\n}\n\n/**\n * Compute the unified TrustScore for one memory.\n *\n * Returns the neutral prior (`0.5`, band `medium`, `neutral: true`) when no\n * usable signal is present, so uninstrumented memories are untouched.\n */\nexport function computeTrustScore(\n signals: TrustSignals = {},\n weights: Readonly<TrustWeights> = DEFAULT_TRUST_WEIGHTS,\n): TrustScoreResult {\n const resolved = resolveTrustWeights(weights);\n\n // Build the (component → value) map, skipping absent/corrupt signals.\n // Each value is already clamped to [0,1] by its mapper.\n const candidates: Array<{ key: keyof TrustWeights; value: number }> = [];\n const push = (key: keyof TrustWeights, value: number | undefined) => {\n if (value === undefined) return;\n candidates.push({ key, value: clampUnit(value) });\n };\n\n push(\"memoryWorth\", signals.memoryWorth ? clampUnit(signals.memoryWorth.score) : undefined);\n push(\"provenance\", provenanceValue(signals.provenance));\n push(\"faithfulness\", faithfulnessValue(signals.faithfulness));\n push(\"corroboration\", corroborationValue(signals.corroborationCount));\n push(\"contradiction\", contradictionValue(signals.contradiction));\n push(\"domainCalibration\", unitValue(signals.domainCalibration));\n push(\"feedback\", feedbackValue(signals.feedback));\n push(\"recency\", recencyValue(signals));\n\n // No usable signal → neutral prior, multiplier exactly 1.0.\n if (candidates.length === 0) {\n return {\n score: NEUTRAL_TRUST_SCORE,\n band: \"medium\",\n components: {},\n neutral: true,\n };\n }\n\n // Sum-normalize the active weights so absent components redistribute their\n // weight to the present ones (a memory with only memory-worth data is scored\n // purely on memory-worth, not half-scored because other signals are absent).\n const activeWeightSum = candidates.reduce((acc, c) => acc + resolved[c.key], 0);\n // When every present signal's weight is 0 (operator explicitly disabled\n // the only components the memory has), fall back to the neutral prior\n // rather than damning the memory to score 0. A disabled signal is not a\n // negative signal — it carries no information (review P2: zero-weight).\n if (activeWeightSum <= 0) {\n return {\n score: NEUTRAL_TRUST_SCORE,\n band: \"medium\",\n components: {},\n neutral: true,\n };\n }\n const safeWeightSum = activeWeightSum;\n\n let blended = 0;\n const components: Record<string, TrustScoreComponent> = {};\n for (const c of candidates) {\n const w = resolved[c.key] / safeWeightSum;\n blended += c.value * w;\n components[c.key] = { value: c.value, weight: w };\n }\n\n // Clamp the blend: floating-point noise can drift a hair outside [0,1].\n const score = clampUnit(blended);\n\n // Hard negatives are quarantined regardless of the blended score, so a\n // corroborated-but-contradicted fact is still excluded from injection.\n const band = bandForScore(score, isHardNegative(signals));\n\n return { score, band, components, neutral: false };\n}\n\n/**\n * Resolve the band from the blended score, accounting for hard-negative\n * quarantine. Extracted so the thresholds live in ONE place (X-ray, injection,\n * and tests all agree on the mapping).\n */\nexport function bandForScore(score: number, hardNegative: boolean): TrustBand {\n if (hardNegative) return \"quarantine\";\n const s = clampUnit(score);\n if (s >= TRUST_BAND_THRESHOLDS.high) return \"high\";\n if (s >= TRUST_BAND_THRESHOLDS.medium) return \"medium\";\n if (s >= TRUST_BAND_THRESHOLDS.low) return \"low\";\n return \"low\";\n}\n\n/**\n * Map a `[0,1]` trust score to a recall multiplier in\n * `[minMultiplier, maxMultiplier]`. The neutral prior (`0.5`) maps to exactly\n * `1.0` so uninstrumented memories are untouched. Linear interpolation centered\n * at neutral:\n *\n * score < 0.5 → multiplier in [min, 1)\n * score = 0.5 → 1.0\n * score > 0.5 → multiplier in (1, max]\n */\nexport function trustMultiplier(\n score: number,\n minMultiplier: number = 0.5,\n maxMultiplier: number = 1.25,\n): number {\n const min = typeof minMultiplier === \"number\" && Number.isFinite(minMultiplier) ? minMultiplier : 0.5;\n const max = typeof maxMultiplier === \"number\" && Number.isFinite(maxMultiplier) ? maxMultiplier : 1.25;\n // Defend against an inverted contract (min > max): pick the tighter bound.\n const lo = Math.min(min, max);\n const hi = Math.max(min, max);\n const s = clampUnit(score);\n if (s === NEUTRAL_TRUST_SCORE) return 1;\n if (s < NEUTRAL_TRUST_SCORE) {\n // Map [0, 0.5) → [lo, 1). score 0 → lo, score →0.5 → 1.\n const t = s / NEUTRAL_TRUST_SCORE; // [0,1)\n return lo + (1 - lo) * t;\n }\n // Map (0.5, 1] → (1, hi]. score 0.5 → 1, score 1 → hi.\n const t = (s - NEUTRAL_TRUST_SCORE) / (1 - NEUTRAL_TRUST_SCORE); // (0,1]\n return 1 + (hi - 1) * t;\n}\n\n/**\n * Deterministic epistemic hedge suffix for an injected memory line, generated\n * from the trust components (template, not LLM). Returns the empty string for\n * the `high` band and for neutral results so the common case wastes no tokens.\n *\n * Examples:\n * high → \"\"\n * medium → \"(unconfirmed — single mention, 2025-11)\"\n * low → \"(low confidence — contradicted once, uncorroborated)\"\n */\nexport function renderEpistemicHedge(result: TrustScoreResult): string {\n if (result.neutral) return \"\";\n switch (result.band) {\n case \"high\":\n return \"\";\n case \"quarantine\":\n case \"low\":\n return `(low confidence — ${describeWeakness(result.components)})`;\n case \"medium\":\n return `(unconfirmed — ${describeWeakness(result.components)})`;\n default:\n return \"\";\n }\n}\n\n/**\n * Build a short, deterministic weakness description from the components. Reads\n * the lowest-contributing signals so the hedge names the actual reason the\n * model should hedge. Pure and order-stable.\n */\nfunction describeWeakness(components: Record<string, TrustScoreComponent>): string {\n const parts: string[] = [];\n const f = components.faithfulness;\n if (f && f.value <= 0.35) parts.push(f.value === 0 ? \"contradicted\" : \"unsupported\");\n const c = components.contradiction;\n if (c && c.value <= 0.2) parts.push(\"under review\");\n const cor = components.corroboration;\n if (cor && cor.value <= 0.4) parts.push(\"single mention\");\n const prov = components.provenance;\n if (prov && prov.value <= 0.3) parts.push(\"unprovenanced\");\n const rec = components.recency;\n if (rec && rec.value <= 0.3) parts.push(\"stale\");\n if (parts.length === 0) {\n // No single component is weak but the blend is below high — name the\n // weakest one explicitly so the hedge is never vacuous.\n let weakest: { key: string; value: number } | null = null;\n for (const [key, comp] of Object.entries(components)) {\n if (!weakest || comp.value < weakest.value) weakest = { key, value: comp.value };\n }\n if (weakest) parts.push(`weak ${humanizeComponentName(weakest.key)}`);\n }\n return parts.slice(0, 2).join(\", \");\n}\n\nfunction humanizeComponentName(key: string): string {\n switch (key) {\n case \"memoryWorth\":\n return \"outcome history\";\n case \"domainCalibration\":\n return \"domain calibration\";\n default:\n return key;\n }\n}\n"],"mappings":"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","names":["t"]}
|