@remnic/core 9.3.683 → 9.3.685
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 +5 -4
- package/dist/access-boundary.js +27 -26
- package/dist/access-cli.js +75 -75
- package/dist/access-http.d.ts +5 -4
- package/dist/access-http.js +32 -31
- package/dist/access-mcp.d.ts +5 -4
- package/dist/access-mcp.js +29 -28
- package/dist/access-operations.d.ts +5 -4
- package/dist/access-operations.js +28 -27
- package/dist/{access-service-DvA6jyHL.d.ts → access-service-DeKrlYU_.d.ts} +2 -11
- package/dist/access-service.d.ts +5 -4
- package/dist/access-service.js +26 -25
- package/dist/access-surface-catalog.d.ts +5 -4
- 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 +3 -3
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-5CJBJMPZ.js → auto-sync-NUQWSFQD.js} +7 -7
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +4 -3
- package/dist/bootstrap.js +2 -2
- package/dist/boxes.js +2 -2
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +5 -4
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +2 -2
- package/dist/calibration.d.ts +1 -1
- package/dist/calibration.js +4 -4
- package/dist/capabilities.d.ts +1 -1
- package/dist/catalog-COqWZlZ6.d.ts +456 -0
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-behavior.js +4 -4
- package/dist/causal-chain.js +4 -4
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +13 -12
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +4 -4
- package/dist/causal-trajectory-graph.js +1 -1
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-UJDV2NLT.js → chunk-2KAYTPPT.js} +12 -12
- package/dist/{chunk-QUA2JPH2.js → chunk-2SJCWLQD.js} +3 -3
- package/dist/{chunk-YTWNKQ2G.js → chunk-3FC6LW6T.js} +2 -2
- package/dist/{chunk-I75DF4FZ.js → chunk-4FE2K57M.js} +3 -3
- package/dist/{chunk-L5MUA6Q7.js → chunk-4N3TFFPH.js} +2 -2
- package/dist/{chunk-BTVX7ZXZ.js → chunk-4NFVPDIL.js} +4 -4
- package/dist/{chunk-OUWAQVDJ.js → chunk-5CEJH5ZN.js} +2 -2
- package/dist/{chunk-IUZWBCJX.js → chunk-6GJS4BFH.js} +10 -7
- package/dist/chunk-6GJS4BFH.js.map +1 -0
- package/dist/{chunk-UAODC6GJ.js → chunk-6O6A6YUO.js} +4 -4
- package/dist/{chunk-HQ6NIBL6.js → chunk-7FL4CNPV.js} +2 -2
- package/dist/{chunk-5VDJMYTF.js → chunk-7WWURLG6.js} +3 -3
- package/dist/{chunk-QWRC7GIO.js → chunk-A4HH2EWA.js} +5 -5
- package/dist/{chunk-4SKKVWLQ.js → chunk-AGJH5ISO.js} +2 -2
- package/dist/{chunk-APJQ6UEA.js → chunk-AGNBY3VG.js} +4 -4
- package/dist/{chunk-I3HSKQT7.js → chunk-B43NZNMG.js} +68 -106
- package/dist/chunk-B43NZNMG.js.map +1 -0
- package/dist/{chunk-NQMBSSWW.js → chunk-B4XVLHJA.js} +3 -3
- package/dist/{chunk-GSTYVG5L.js → chunk-BFVPIKDY.js} +3 -3
- package/dist/{chunk-TY5NT3T3.js → chunk-BLIWOONZ.js} +51 -43
- package/dist/chunk-BLIWOONZ.js.map +1 -0
- package/dist/{chunk-AJU4PJGY.js → chunk-BVKCV2ZY.js} +2 -2
- package/dist/{chunk-QVWM4C24.js → chunk-BZISAF67.js} +9 -10
- package/dist/chunk-BZISAF67.js.map +1 -0
- package/dist/{chunk-EG4TCVMU.js → chunk-CTOQEZSN.js} +2 -2
- package/dist/{chunk-7OGJQP7T.js → chunk-DCWIQFNA.js} +4 -4
- package/dist/{chunk-MHQC2WU2.js → chunk-DKTSR7EK.js} +2 -2
- package/dist/{chunk-RN7MUWON.js → chunk-EHISUJFN.js} +2 -2
- package/dist/{chunk-WLEB7WCG.js → chunk-EO5QWINU.js} +2 -2
- package/dist/{chunk-XKXKSQU7.js → chunk-EXM3CQTZ.js} +2 -2
- package/dist/{chunk-TOQEZ63C.js → chunk-FE6DQUNJ.js} +9 -9
- package/dist/{chunk-LCC5EZTT.js → chunk-FIVDN2SM.js} +4 -4
- package/dist/{chunk-452WDNFO.js → chunk-GG6AJN7A.js} +2 -2
- package/dist/{chunk-O2WELT5C.js → chunk-GS55WYRL.js} +3 -3
- package/dist/{chunk-OHX52AOS.js → chunk-GTDH3IUH.js} +2 -2
- package/dist/{chunk-IBTZEBUD.js → chunk-HYNHLBKA.js} +2 -2
- package/dist/{chunk-V254FAT5.js → chunk-IIDSFFE5.js} +2 -2
- package/dist/{chunk-EVWIEEKZ.js → chunk-IQ7WCZRW.js} +2 -2
- package/dist/{chunk-B5XMS73R.js → chunk-IQVQJJL7.js} +2 -2
- package/dist/{chunk-M4I3TREG.js → chunk-JPCKLFWK.js} +29 -30
- package/dist/{chunk-M4I3TREG.js.map → chunk-JPCKLFWK.js.map} +1 -1
- package/dist/{chunk-6RHNCKHG.js → chunk-K43PI6DQ.js} +2 -2
- package/dist/{chunk-OIF36KGD.js → chunk-KCQA46NR.js} +2 -2
- package/dist/{chunk-2LDBXPLB.js → chunk-KF74X62T.js} +1 -1
- package/dist/{chunk-MAV46GWQ.js → chunk-KYYL4U6X.js} +2 -2
- package/dist/{chunk-6GC5SGFE.js → chunk-L24JROPR.js} +2 -2
- package/dist/{chunk-6VP3YUCS.js → chunk-LLONI6PY.js} +2 -2
- package/dist/{chunk-Q5ZU3RNY.js → chunk-LQ6JI4VH.js} +2 -2
- package/dist/{chunk-ODWI5XU2.js → chunk-MCQDSY4G.js} +3 -3
- package/dist/{chunk-HP5FMB6L.js → chunk-MDJURR27.js} +2 -2
- package/dist/{chunk-FMSDA2D3.js → chunk-NGFEWFNK.js} +1 -1
- package/dist/chunk-NGFEWFNK.js.map +1 -0
- package/dist/{chunk-2ODBA7MQ.js → chunk-NU3CSQ4H.js} +5 -5
- package/dist/chunk-NU3CSQ4H.js.map +1 -0
- package/dist/{chunk-T2PO5MUF.js → chunk-O7GOFAM3.js} +2 -2
- package/dist/{chunk-Z2OXSMZK.js → chunk-OBXTMFZQ.js} +3 -3
- package/dist/{chunk-FDSOMA6M.js → chunk-OFUULUSY.js} +8 -9
- package/dist/{chunk-FDSOMA6M.js.map → chunk-OFUULUSY.js.map} +1 -1
- package/dist/{chunk-KV6CX4ON.js → chunk-OV4D5T7V.js} +3 -3
- package/dist/{chunk-KACIOX42.js → chunk-PH3HOKYW.js} +2 -2
- package/dist/{chunk-NHFXF4ZO.js → chunk-PK6RGRSD.js} +2 -2
- package/dist/{chunk-C3IW2F5Z.js → chunk-PLBIPT6I.js} +2 -2
- package/dist/{chunk-QY7YA7OL.js → chunk-PNLCEFE4.js} +2 -2
- package/dist/{chunk-AGRPGAKR.js → chunk-PONNZ54D.js} +2 -2
- package/dist/{chunk-XZ4WBBB5.js → chunk-PWFWCGOO.js} +2 -2
- package/dist/{chunk-G7Z3C2X6.js → chunk-QANVLERJ.js} +4 -4
- package/dist/{chunk-W4RVMTHR.js → chunk-QRDOSYOR.js} +2 -2
- package/dist/{chunk-6IMKOIZ6.js → chunk-R6OVFAX6.js} +2 -2
- package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
- package/dist/{chunk-JOASJWQR.js → chunk-SANZHXY2.js} +2 -2
- package/dist/{chunk-7DTASS5T.js → chunk-SJHM6I4J.js} +2 -2
- package/dist/{chunk-H4BDNIKQ.js → chunk-SQGPGC76.js} +14 -24
- package/dist/{chunk-H4BDNIKQ.js.map → chunk-SQGPGC76.js.map} +1 -1
- package/dist/{chunk-B2B2IHUH.js → chunk-STOEE37X.js} +4 -4
- package/dist/{chunk-GKKAXVAJ.js → chunk-U33LWTQQ.js} +1 -7
- package/dist/chunk-U33LWTQQ.js.map +1 -0
- package/dist/{chunk-GNAMDNGT.js → chunk-U7D7NP4J.js} +5 -5
- package/dist/{chunk-DRD2Q7HQ.js → chunk-UFS7OXGL.js} +2 -2
- package/dist/{chunk-H3HDXD3U.js → chunk-UPTZYUYJ.js} +2 -2
- package/dist/{chunk-3IND7N4X.js → chunk-UTYBJR7M.js} +2 -2
- package/dist/{chunk-LN4YGHTM.js → chunk-UUH4YQOF.js} +2 -2
- package/dist/{chunk-6VF75M3X.js → chunk-VGUOEDTU.js} +2 -2
- package/dist/{chunk-44VFF3BB.js → chunk-VILEUJXC.js} +2 -2
- package/dist/{chunk-7SI52C65.js → chunk-VL7DP3OW.js} +2 -2
- package/dist/{chunk-7DHTMOND.js → chunk-VQ34TERH.js} +2 -2
- package/dist/{chunk-H6PMGMNP.js → chunk-VX6OBUDW.js} +2 -2
- package/dist/{chunk-EW5KFXHL.js → chunk-WDXCNJSF.js} +7 -7
- package/dist/{chunk-ARLRTZZZ.js → chunk-WIHPNY65.js} +79 -3
- package/dist/chunk-WIHPNY65.js.map +1 -0
- package/dist/{chunk-X6IRLNOO.js → chunk-WIWPSQYU.js} +2 -2
- package/dist/{chunk-DOCTITOP.js → chunk-WRFKZEO6.js} +2 -2
- package/dist/{chunk-E6ZDCOHM.js → chunk-XBZQRZ6G.js} +2 -2
- package/dist/{chunk-7YX23JBA.js → chunk-XHYGJVXL.js} +2 -2
- package/dist/{chunk-JD4SCARD.js → chunk-YN4ZT4CW.js} +1 -1
- package/dist/{chunk-YXWAILM4.js → chunk-YOI3ELXF.js} +2 -2
- package/dist/{chunk-XCAZF7KQ.js → chunk-ZA2S2VLL.js} +2 -2
- package/dist/{chunk-BEUDU7Y4.js → chunk-ZCWIH4LH.js} +2 -2
- package/dist/chunk-ZPQVJEVQ.js +184 -0
- package/dist/chunk-ZPQVJEVQ.js.map +1 -0
- package/dist/{chunk-WEPMT6SC.js → chunk-ZPTISBQU.js} +8 -8
- package/dist/{cli-feUe-x3I.d.ts → cli-D3-Q5Uod.d.ts} +3 -3
- package/dist/cli.d.ts +6 -5
- package/dist/cli.js +54 -54
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +6 -5
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compounding/preference-consolidator.js +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +3 -3
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +6 -5
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/codex-materialize.js +2 -2
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +9 -9
- 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/contradiction/index.js +3 -3
- package/dist/{contradiction-scan-AZTGFMPY.js → contradiction-scan-HWGEOUDS.js} +3 -3
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/backend.js +5 -5
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/cleanup.js +2 -2
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.js +2 -2
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/indexer.js +2 -2
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/conversation-index/search.js +2 -2
- package/dist/day-summary.d.ts +1 -1
- package/dist/day-summary.js +2 -2
- 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/embedding-fallback.js +2 -2
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +7 -5
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +4 -3
- package/dist/explicit-capture.js +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-telemetry.js +2 -2
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge-training.js +2 -2
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-judge.js +5 -5
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +9 -9
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/fallback-llm.js +4 -4
- package/dist/{first-start-migration-FF7YFGRP.js → first-start-migration-PG5HBC3K.js} +4 -4
- package/dist/{graph-edge-decay-KSVJGCZW.js → graph-edge-decay-D7OESCBR.js} +2 -2
- package/dist/graph-snapshot.js +2 -2
- package/dist/graph.js +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +9 -8
- package/dist/index.js +112 -112
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/archive.js +2 -2
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +5 -5
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +8 -8
- package/dist/lcm/schema.js +2 -2
- package/dist/lcm/summarizer.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 +2 -2
- package/dist/logger.js +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +6 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +6 -4
- package/dist/maintenance/rebuild-memory-projection.js +8 -6
- package/dist/mcp-memory-inspector-app.d.ts +5 -4
- 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/model-registry.js +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/models-json.js +2 -2
- package/dist/namespaces/migrate.d.ts +2 -1
- package/dist/namespaces/migrate.js +18 -17
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +13 -13
- package/dist/namespaces/storage.d.ts +43 -2
- package/dist/namespaces/storage.js +6 -4
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/native-knowledge.js +2 -2
- package/dist/negative.js +2 -2
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +24 -24
- package/dist/{orchestrator-7zPqGupX.d.ts → orchestrator-CA6ouzBn.d.ts} +5 -466
- package/dist/orchestrator.d.ts +4 -3
- package/dist/orchestrator.js +68 -67
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/profiling.js +2 -2
- package/dist/provenance.d.ts +94 -0
- package/dist/provenance.js +17 -0
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/qmd.js +2 -2
- 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 +4 -4
- package/dist/recall-qos.js +2 -2
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-state.js +2 -2
- 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/relevance.js +2 -2
- package/dist/{resolution-IDTEBJFS.js → resolution-MN36NW5P.js} +3 -3
- package/dist/resolution-MN36NW5P.js.map +1 -0
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resolve-provider-secret.js +2 -2
- package/dist/resume-bundles.js +5 -5
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-agents.js +2 -2
- 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/routing/store.js +2 -2
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/embed-helper.js +2 -2
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +12 -12
- 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/search/remote-backend.js +2 -2
- package/dist/{semantic-consolidation-BX9Z9_aK.d.ts → semantic-consolidation-CWch5uM7.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +7 -6
- package/dist/semantic-rule-promotion.js +6 -4
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +6 -4
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/session-observer-state.js +2 -2
- package/dist/session-transcript-migration.js +2 -2
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/shared-context/manager.js +2 -2
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +5 -1
- package/dist/storage.js +5 -3
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +7 -7
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-supersession.js +2 -2
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/threading.js +2 -2
- 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/transcript.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/{types-D3pm4NhH.d.ts → types-Dm5xxVrr.d.ts} +61 -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 +7 -5
- package/package.json +2 -2
- package/src/access-http.ts +1 -1
- package/src/access-mcp.ts +1 -1
- package/src/access-service.ts +1 -11
- package/src/cli.ts +1 -1
- package/src/config.test.ts +112 -0
- package/src/config.ts +5 -5
- package/src/explicit-capture.ts +3 -12
- package/src/logger.ts +13 -4
- package/src/namespaces/catalog.test.ts +2 -2
- package/src/namespaces/storage.ts +81 -0
- package/src/orchestrator.ts +22 -64
- package/src/provenance-frontmatter.test.ts +596 -0
- package/src/provenance.ts +305 -0
- package/src/storage.ts +41 -41
- package/src/types.ts +76 -0
- package/dist/chunk-2ODBA7MQ.js.map +0 -1
- package/dist/chunk-ARLRTZZZ.js.map +0 -1
- package/dist/chunk-FMSDA2D3.js.map +0 -1
- package/dist/chunk-GKKAXVAJ.js.map +0 -1
- package/dist/chunk-I3HSKQT7.js.map +0 -1
- package/dist/chunk-IUZWBCJX.js.map +0 -1
- package/dist/chunk-PHK3HARR.js +0 -32
- package/dist/chunk-PHK3HARR.js.map +0 -1
- package/dist/chunk-QVWM4C24.js.map +0 -1
- package/dist/chunk-TY5NT3T3.js.map +0 -1
- /package/dist/{auto-sync-5CJBJMPZ.js.map → auto-sync-NUQWSFQD.js.map} +0 -0
- /package/dist/{chunk-UJDV2NLT.js.map → chunk-2KAYTPPT.js.map} +0 -0
- /package/dist/{chunk-QUA2JPH2.js.map → chunk-2SJCWLQD.js.map} +0 -0
- /package/dist/{chunk-YTWNKQ2G.js.map → chunk-3FC6LW6T.js.map} +0 -0
- /package/dist/{chunk-I75DF4FZ.js.map → chunk-4FE2K57M.js.map} +0 -0
- /package/dist/{chunk-L5MUA6Q7.js.map → chunk-4N3TFFPH.js.map} +0 -0
- /package/dist/{chunk-BTVX7ZXZ.js.map → chunk-4NFVPDIL.js.map} +0 -0
- /package/dist/{chunk-OUWAQVDJ.js.map → chunk-5CEJH5ZN.js.map} +0 -0
- /package/dist/{chunk-UAODC6GJ.js.map → chunk-6O6A6YUO.js.map} +0 -0
- /package/dist/{chunk-HQ6NIBL6.js.map → chunk-7FL4CNPV.js.map} +0 -0
- /package/dist/{chunk-5VDJMYTF.js.map → chunk-7WWURLG6.js.map} +0 -0
- /package/dist/{chunk-QWRC7GIO.js.map → chunk-A4HH2EWA.js.map} +0 -0
- /package/dist/{chunk-4SKKVWLQ.js.map → chunk-AGJH5ISO.js.map} +0 -0
- /package/dist/{chunk-APJQ6UEA.js.map → chunk-AGNBY3VG.js.map} +0 -0
- /package/dist/{chunk-NQMBSSWW.js.map → chunk-B4XVLHJA.js.map} +0 -0
- /package/dist/{chunk-GSTYVG5L.js.map → chunk-BFVPIKDY.js.map} +0 -0
- /package/dist/{chunk-AJU4PJGY.js.map → chunk-BVKCV2ZY.js.map} +0 -0
- /package/dist/{chunk-EG4TCVMU.js.map → chunk-CTOQEZSN.js.map} +0 -0
- /package/dist/{chunk-7OGJQP7T.js.map → chunk-DCWIQFNA.js.map} +0 -0
- /package/dist/{chunk-MHQC2WU2.js.map → chunk-DKTSR7EK.js.map} +0 -0
- /package/dist/{chunk-RN7MUWON.js.map → chunk-EHISUJFN.js.map} +0 -0
- /package/dist/{chunk-WLEB7WCG.js.map → chunk-EO5QWINU.js.map} +0 -0
- /package/dist/{chunk-XKXKSQU7.js.map → chunk-EXM3CQTZ.js.map} +0 -0
- /package/dist/{chunk-TOQEZ63C.js.map → chunk-FE6DQUNJ.js.map} +0 -0
- /package/dist/{chunk-LCC5EZTT.js.map → chunk-FIVDN2SM.js.map} +0 -0
- /package/dist/{chunk-452WDNFO.js.map → chunk-GG6AJN7A.js.map} +0 -0
- /package/dist/{chunk-O2WELT5C.js.map → chunk-GS55WYRL.js.map} +0 -0
- /package/dist/{chunk-OHX52AOS.js.map → chunk-GTDH3IUH.js.map} +0 -0
- /package/dist/{chunk-IBTZEBUD.js.map → chunk-HYNHLBKA.js.map} +0 -0
- /package/dist/{chunk-V254FAT5.js.map → chunk-IIDSFFE5.js.map} +0 -0
- /package/dist/{chunk-EVWIEEKZ.js.map → chunk-IQ7WCZRW.js.map} +0 -0
- /package/dist/{chunk-B5XMS73R.js.map → chunk-IQVQJJL7.js.map} +0 -0
- /package/dist/{chunk-6RHNCKHG.js.map → chunk-K43PI6DQ.js.map} +0 -0
- /package/dist/{chunk-OIF36KGD.js.map → chunk-KCQA46NR.js.map} +0 -0
- /package/dist/{chunk-2LDBXPLB.js.map → chunk-KF74X62T.js.map} +0 -0
- /package/dist/{chunk-MAV46GWQ.js.map → chunk-KYYL4U6X.js.map} +0 -0
- /package/dist/{chunk-6GC5SGFE.js.map → chunk-L24JROPR.js.map} +0 -0
- /package/dist/{chunk-6VP3YUCS.js.map → chunk-LLONI6PY.js.map} +0 -0
- /package/dist/{chunk-Q5ZU3RNY.js.map → chunk-LQ6JI4VH.js.map} +0 -0
- /package/dist/{chunk-ODWI5XU2.js.map → chunk-MCQDSY4G.js.map} +0 -0
- /package/dist/{chunk-HP5FMB6L.js.map → chunk-MDJURR27.js.map} +0 -0
- /package/dist/{chunk-T2PO5MUF.js.map → chunk-O7GOFAM3.js.map} +0 -0
- /package/dist/{chunk-Z2OXSMZK.js.map → chunk-OBXTMFZQ.js.map} +0 -0
- /package/dist/{chunk-KV6CX4ON.js.map → chunk-OV4D5T7V.js.map} +0 -0
- /package/dist/{chunk-KACIOX42.js.map → chunk-PH3HOKYW.js.map} +0 -0
- /package/dist/{chunk-NHFXF4ZO.js.map → chunk-PK6RGRSD.js.map} +0 -0
- /package/dist/{chunk-C3IW2F5Z.js.map → chunk-PLBIPT6I.js.map} +0 -0
- /package/dist/{chunk-QY7YA7OL.js.map → chunk-PNLCEFE4.js.map} +0 -0
- /package/dist/{chunk-AGRPGAKR.js.map → chunk-PONNZ54D.js.map} +0 -0
- /package/dist/{chunk-XZ4WBBB5.js.map → chunk-PWFWCGOO.js.map} +0 -0
- /package/dist/{chunk-G7Z3C2X6.js.map → chunk-QANVLERJ.js.map} +0 -0
- /package/dist/{chunk-W4RVMTHR.js.map → chunk-QRDOSYOR.js.map} +0 -0
- /package/dist/{chunk-6IMKOIZ6.js.map → chunk-R6OVFAX6.js.map} +0 -0
- /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-JOASJWQR.js.map → chunk-SANZHXY2.js.map} +0 -0
- /package/dist/{chunk-7DTASS5T.js.map → chunk-SJHM6I4J.js.map} +0 -0
- /package/dist/{chunk-B2B2IHUH.js.map → chunk-STOEE37X.js.map} +0 -0
- /package/dist/{chunk-GNAMDNGT.js.map → chunk-U7D7NP4J.js.map} +0 -0
- /package/dist/{chunk-DRD2Q7HQ.js.map → chunk-UFS7OXGL.js.map} +0 -0
- /package/dist/{chunk-H3HDXD3U.js.map → chunk-UPTZYUYJ.js.map} +0 -0
- /package/dist/{chunk-3IND7N4X.js.map → chunk-UTYBJR7M.js.map} +0 -0
- /package/dist/{chunk-LN4YGHTM.js.map → chunk-UUH4YQOF.js.map} +0 -0
- /package/dist/{chunk-6VF75M3X.js.map → chunk-VGUOEDTU.js.map} +0 -0
- /package/dist/{chunk-44VFF3BB.js.map → chunk-VILEUJXC.js.map} +0 -0
- /package/dist/{chunk-7SI52C65.js.map → chunk-VL7DP3OW.js.map} +0 -0
- /package/dist/{chunk-7DHTMOND.js.map → chunk-VQ34TERH.js.map} +0 -0
- /package/dist/{chunk-H6PMGMNP.js.map → chunk-VX6OBUDW.js.map} +0 -0
- /package/dist/{chunk-EW5KFXHL.js.map → chunk-WDXCNJSF.js.map} +0 -0
- /package/dist/{chunk-X6IRLNOO.js.map → chunk-WIWPSQYU.js.map} +0 -0
- /package/dist/{chunk-DOCTITOP.js.map → chunk-WRFKZEO6.js.map} +0 -0
- /package/dist/{chunk-E6ZDCOHM.js.map → chunk-XBZQRZ6G.js.map} +0 -0
- /package/dist/{chunk-7YX23JBA.js.map → chunk-XHYGJVXL.js.map} +0 -0
- /package/dist/{chunk-JD4SCARD.js.map → chunk-YN4ZT4CW.js.map} +0 -0
- /package/dist/{chunk-YXWAILM4.js.map → chunk-YOI3ELXF.js.map} +0 -0
- /package/dist/{chunk-XCAZF7KQ.js.map → chunk-ZA2S2VLL.js.map} +0 -0
- /package/dist/{chunk-BEUDU7Y4.js.map → chunk-ZCWIH4LH.js.map} +0 -0
- /package/dist/{chunk-WEPMT6SC.js.map → chunk-ZPTISBQU.js.map} +0 -0
- /package/dist/{contradiction-scan-AZTGFMPY.js.map → contradiction-scan-HWGEOUDS.js.map} +0 -0
- /package/dist/{first-start-migration-FF7YFGRP.js.map → first-start-migration-PG5HBC3K.js.map} +0 -0
- /package/dist/{graph-edge-decay-KSVJGCZW.js.map → graph-edge-decay-D7OESCBR.js.map} +0 -0
- /package/dist/{resolution-IDTEBJFS.js.map → provenance.js.map} +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claim-level provenance spans (issue #1575 PR 1).
|
|
3
|
+
*
|
|
4
|
+
* Centralizes the parse/serialize logic for the `sources` array and the
|
|
5
|
+
* coarse `provenance` strength tag, plus the `provenance` config-block
|
|
6
|
+
* parser. Extracted from `storage.ts` and `config.ts` so those files keep
|
|
7
|
+
* only thin delegation call-sites — the frontmatter round-trip and config
|
|
8
|
+
* parsing growth lives here (issue #1520 ratchet discipline).
|
|
9
|
+
*
|
|
10
|
+
* Contract:
|
|
11
|
+
* - When no provenance fields are present, output is byte-identical to
|
|
12
|
+
* pre-feature behavior (rule 39).
|
|
13
|
+
* - Corrupt `sources` lines / unknown `provenance` tags drop to
|
|
14
|
+
* `undefined` on read so a malformed frontmatter never poisons
|
|
15
|
+
* downstream readers (rule 34 spirit — drop corrupt rather than poison).
|
|
16
|
+
* - Validation lives on the write path; this module only parses.
|
|
17
|
+
* - Invariant (review round 5, cursor thread KQN): a `verified` or
|
|
18
|
+
* `unverified` tag is NEVER persisted/read without surviving sources —
|
|
19
|
+
* without excerpts the tag is indistinguishable from a grounded fact to
|
|
20
|
+
* downstream faithfulness/correction/TrustScore surfaces. The invariant
|
|
21
|
+
* is enforced symmetrically: `serializeProvenanceFields` (write) and
|
|
22
|
+
* `reconcileProvenanceRead` (read) both downgrade the tag to `none`
|
|
23
|
+
* when no source survives.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
|
|
28
|
+
import { coerceBool, coerceNumber } from "./connectors/coerce.js";
|
|
29
|
+
import { readEnvVar } from "./runtime/env.js";
|
|
30
|
+
import type { MemoryFrontmatter, ProvenanceConfig, ProvenanceSource } from "./types.js";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Canonical key order for a serialized `ProvenanceSource` (issue #1575).
|
|
34
|
+
* Deterministic emission (rule 38) — readers and the byte-identical-when-off
|
|
35
|
+
* contract (rule 39) depend on this order never drifting.
|
|
36
|
+
*/
|
|
37
|
+
const PROVENANCE_SOURCE_KEY_ORDER = [
|
|
38
|
+
"sessionKey",
|
|
39
|
+
"turnId",
|
|
40
|
+
"observedAt",
|
|
41
|
+
"quote",
|
|
42
|
+
"charStart",
|
|
43
|
+
"charEnd",
|
|
44
|
+
] as const;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build a single `ProvenanceSource` object whose keys appear in the canonical
|
|
48
|
+
* order, omitting absent optional fields. The result is what gets fed to
|
|
49
|
+
* `JSON.stringify` so the on-disk line is deterministic.
|
|
50
|
+
*/
|
|
51
|
+
function canonicalProvenanceSource(src: ProvenanceSource): Record<string, unknown> {
|
|
52
|
+
const out: Record<string, unknown> = {};
|
|
53
|
+
for (const key of PROVENANCE_SOURCE_KEY_ORDER) {
|
|
54
|
+
const value = src[key];
|
|
55
|
+
if (value !== undefined) out[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Serialize the `sources` array (issue #1575) as a single JSON line, matching
|
|
62
|
+
* the `structuredAttributes` precedent. Each entry is rebuilt in canonical key
|
|
63
|
+
* order (rule 38) so the output is byte-stable. The `provenance` enum is
|
|
64
|
+
* emitted bare (same style as `status`) — only the three documented values
|
|
65
|
+
* are ever written.
|
|
66
|
+
*
|
|
67
|
+
* Verified-requires-evidence invariant (review round 5, cursor thread KQN):
|
|
68
|
+
* a `verified`/`unverified` tag is downgraded to `none` whenever no source
|
|
69
|
+
* survives write validation — whether sources were absent, an empty array,
|
|
70
|
+
* or all entries failed the schema. This covers all three failure shapes the
|
|
71
|
+
* earlier 3-branch logic left open (`{provenance:"verified"}`,
|
|
72
|
+
* `{sources:[],provenance:"verified"}`, `{sources:[invalid…],provenance:"verified"}`).
|
|
73
|
+
*/
|
|
74
|
+
export function serializeProvenanceFields(fm: MemoryFrontmatter, lines: string[]): void {
|
|
75
|
+
let hasValidSources = false;
|
|
76
|
+
if (fm.sources && fm.sources.length > 0) {
|
|
77
|
+
// Validate each entry against the same schema used on read so invalid
|
|
78
|
+
// in-memory sources are dropped at write time, not silently lost on the
|
|
79
|
+
// next read (review thread 4 — write-path validation parity).
|
|
80
|
+
const canonical: Record<string, unknown>[] = [];
|
|
81
|
+
for (const src of fm.sources) {
|
|
82
|
+
const result = ProvenanceSourceSchema.safeParse(src);
|
|
83
|
+
if (result.success) canonical.push(canonicalProvenanceSource(result.data));
|
|
84
|
+
}
|
|
85
|
+
if (canonical.length > 0) {
|
|
86
|
+
lines.push(`sources: ${JSON.stringify(canonical)}`);
|
|
87
|
+
hasValidSources = true;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// A verified/unverified tag requires surviving evidence; without it the
|
|
91
|
+
// tag is meaningless downstream (faithfulness/TrustScore cannot distinguish
|
|
92
|
+
// it from a grounded fact). Downgrade to "none" regardless of WHY no source
|
|
93
|
+
// survived (absent / empty / all-invalid) — single invariant, all cases.
|
|
94
|
+
const tag =
|
|
95
|
+
(fm.provenance === "verified" || fm.provenance === "unverified") && !hasValidSources
|
|
96
|
+
? "none"
|
|
97
|
+
: fm.provenance;
|
|
98
|
+
if (tag) {
|
|
99
|
+
lines.push(`provenance: ${tag}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Parse the coarse `provenance` strength tag (issue #1575). Returns
|
|
105
|
+
* `undefined` for missing/blank/unknown values so a corrupt or hand-edited
|
|
106
|
+
* field fails safely to the legacy-equivalent `"none"` semantics on read
|
|
107
|
+
* (rule 34 spirit — drop corrupt rather than poison).
|
|
108
|
+
*/
|
|
109
|
+
export function parseProvenanceTag(
|
|
110
|
+
raw: string | undefined,
|
|
111
|
+
): "verified" | "unverified" | "none" | undefined {
|
|
112
|
+
if (raw === undefined) return undefined;
|
|
113
|
+
const trimmed = raw.trim();
|
|
114
|
+
if (trimmed.length === 0) return undefined;
|
|
115
|
+
if (trimmed === "verified" || trimmed === "unverified" || trimmed === "none") {
|
|
116
|
+
return trimmed;
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Enforce the verified-requires-evidence invariant on the READ path.
|
|
123
|
+
* `parseProvenanceTag` and `parseProvenanceSources` are independent (they
|
|
124
|
+
* parse separate frontmatter lines), so a hand-edited or imported memory may
|
|
125
|
+
* carry `provenance: verified` with no surviving `sources` — a corrupt line,
|
|
126
|
+
* an empty array, or all-invalid entries. Downgrade such a tag to `none` so
|
|
127
|
+
* the in-memory object never exposes an ungrounded "verified" fact
|
|
128
|
+
* (review round 5, cursor thread KQN — read-path parity with the write-path
|
|
129
|
+
* downgrade in `serializeProvenanceFields`). `none`/`undefined` tags pass
|
|
130
|
+
* through unchanged.
|
|
131
|
+
*/
|
|
132
|
+
export function reconcileProvenanceRead(
|
|
133
|
+
tag: "verified" | "unverified" | "none" | undefined,
|
|
134
|
+
sources: ProvenanceSource[] | undefined,
|
|
135
|
+
): "verified" | "unverified" | "none" | undefined {
|
|
136
|
+
if ((tag === "verified" || tag === "unverified") && (!sources || sources.length === 0)) {
|
|
137
|
+
return "none";
|
|
138
|
+
}
|
|
139
|
+
return tag;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Strict ISO-8601 timestamp check (review round 6, codex thread OXPAp).
|
|
144
|
+
* `Date.parse` accepts non-ISO strings (bare years like `"123"`) and
|
|
145
|
+
* silently normalizes calendar overflow (`2026-02-30` -> March 2, hour 25
|
|
146
|
+
* -> next day), so malformed provenance survives as if valid. Require the
|
|
147
|
+
* full `YYYY-MM-DDTHH:MM:SS[.fff](Z|±HH:MM)` shape and reject overflow via a
|
|
148
|
+
* `Date.UTC` round-trip component check — the offset does not affect whether
|
|
149
|
+
* a wall-clock field overflows, so this is correct for any timezone suffix.
|
|
150
|
+
*/
|
|
151
|
+
function isStrictIsoTimestamp(s: string): boolean {
|
|
152
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.exec(s);
|
|
153
|
+
if (!m) return false;
|
|
154
|
+
const y = Number(m[1]), mo = Number(m[2]), da = Number(m[3]);
|
|
155
|
+
const h = Number(m[4]), mi = Number(m[5]), se = Number(m[6]);
|
|
156
|
+
// Date.UTC normalizes overflow (Feb 30 -> Mar 2); a component round-trip
|
|
157
|
+
// catches what Date.parse silently accepts.
|
|
158
|
+
const d = new Date(Date.UTC(y, mo - 1, da, h, mi, se));
|
|
159
|
+
// The component round-trip validates wall-clock overflow (Feb 30 -> Mar 2);
|
|
160
|
+
// Date.parse additionally rejects impossible timezone offsets such as
|
|
161
|
+
// +99:99, which the regex accepts but the runtime treats as NaN
|
|
162
|
+
// (codex thread OXQ0e).
|
|
163
|
+
return (
|
|
164
|
+
!Number.isNaN(Date.parse(s)) &&
|
|
165
|
+
d.getUTCFullYear() === y &&
|
|
166
|
+
d.getUTCMonth() === mo - 1 &&
|
|
167
|
+
d.getUTCDate() === da &&
|
|
168
|
+
d.getUTCHours() === h &&
|
|
169
|
+
d.getUTCMinutes() === mi &&
|
|
170
|
+
d.getUTCSeconds() === se
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Zod schema for a single `ProvenanceSource` entry (issue #1575). Parsed
|
|
176
|
+
* JSON from frontmatter is external data, so each entry is validated here
|
|
177
|
+
* rather than trusted via a cast (rule: no inline-cast-access on parsed
|
|
178
|
+
* blobs). `safeParse` lets us drop corrupt entries individually instead of
|
|
179
|
+
* failing the whole field.
|
|
180
|
+
*/
|
|
181
|
+
const ProvenanceSourceSchema = z
|
|
182
|
+
.object({
|
|
183
|
+
sessionKey: z.string().min(1),
|
|
184
|
+
observedAt: z
|
|
185
|
+
.string()
|
|
186
|
+
.min(1)
|
|
187
|
+
.refine(isStrictIsoTimestamp, "must be a valid ISO 8601 timestamp (YYYY-MM-DDTHH:MM:SS[Z|±HH:MM], no calendar overflow)"),
|
|
188
|
+
quote: z.string().min(1),
|
|
189
|
+
turnId: z.string().min(1).optional(),
|
|
190
|
+
charStart: z.number().finite().nonnegative().int().optional(),
|
|
191
|
+
charEnd: z.number().finite().nonnegative().int().optional(),
|
|
192
|
+
})
|
|
193
|
+
.refine(
|
|
194
|
+
(src) => src.charStart === undefined || src.charEnd === undefined || src.charEnd >= src.charStart,
|
|
195
|
+
{ message: "charEnd must be >= charStart (half-open interval, rule 35)" },
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Parse the `sources` array (issue #1575) from its single-line JSON form.
|
|
200
|
+
* Mirrors `parseStructuredAttributes` (JSON.parse) but validates each entry
|
|
201
|
+
* against `ProvenanceSourceSchema` and DROPS corrupt ones rather than
|
|
202
|
+
* poisoning downstream readers — the same "drop corrupt rather than poison"
|
|
203
|
+
* contract as `parseMemoryWorthCounterField`. If no entry survives, the
|
|
204
|
+
* whole field is `undefined` (legacy-equivalent).
|
|
205
|
+
*/
|
|
206
|
+
export function parseProvenanceSources(raw: string | undefined): ProvenanceSource[] | undefined {
|
|
207
|
+
if (raw === undefined) return undefined;
|
|
208
|
+
const trimmed = raw.trim();
|
|
209
|
+
if (trimmed.length === 0) return undefined;
|
|
210
|
+
let parsed: unknown;
|
|
211
|
+
try {
|
|
212
|
+
parsed = JSON.parse(trimmed);
|
|
213
|
+
} catch {
|
|
214
|
+
return undefined;
|
|
215
|
+
}
|
|
216
|
+
if (!Array.isArray(parsed)) return undefined;
|
|
217
|
+
const sources: ProvenanceSource[] = [];
|
|
218
|
+
for (const entry of parsed) {
|
|
219
|
+
const result = ProvenanceSourceSchema.safeParse(entry);
|
|
220
|
+
if (result.success) sources.push(result.data);
|
|
221
|
+
}
|
|
222
|
+
return sources.length > 0 ? sources : undefined;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Parse the `provenance` config block (issue #1575 PR 1). Validates the
|
|
227
|
+
* shape before applying defaults — a shorthand like `provenance: false` must
|
|
228
|
+
* reject loudly rather than normalize to `{}` and silently enable the feature
|
|
229
|
+
* (rule 51). Booleans coerce via `coerceBool` (rule 36); numeric cap clamps
|
|
230
|
+
* at 1 (rule 28). `REMNIC_PROVENANCE_ENABLED` / `ENGRAM_PROVENANCE_ENABLED`
|
|
231
|
+
* are honored only when the `enabled` key is omitted (explicit config wins).
|
|
232
|
+
*
|
|
233
|
+
* Schema-default note (review rounds 1–3, settled): `provenance.enabled` has
|
|
234
|
+
* NO `"default"` in any plugin.json schema. OpenClaw's loader runs
|
|
235
|
+
* `applyDefaults: true` before exposing `api.pluginConfig` (src/index.ts:1345,
|
|
236
|
+
* PR #1593 round 8), so a schema default would be materialized into the
|
|
237
|
+
* merged config and mask the `REMNIC_`/`ENGRAM_` env override. The code-level
|
|
238
|
+
* default-on here (`return true` when `enabled` is omitted) supplies the
|
|
239
|
+
* default-on behavior without that materialization. This matches the
|
|
240
|
+
* emitLegacyTools/namespaceCatalogEnabled precedent, which omits the env
|
|
241
|
+
* override only after a raw-vs-effective split — overkill for a single
|
|
242
|
+
* boolean, so this field uses the simpler omit-the-default approach.
|
|
243
|
+
*/
|
|
244
|
+
export function parseProvenanceConfig(raw: unknown): ProvenanceConfig {
|
|
245
|
+
if (
|
|
246
|
+
raw !== undefined &&
|
|
247
|
+
(raw === null || typeof raw !== "object" || Array.isArray(raw))
|
|
248
|
+
) {
|
|
249
|
+
throw new Error(
|
|
250
|
+
`provenance must be an object (got ${JSON.stringify(raw)}). Use provenance: { enabled: false } to opt out; omit the key to use the default-on behavior (issue #1575).`,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
const rawProvenance =
|
|
254
|
+
raw && typeof raw === "object" && !Array.isArray(raw)
|
|
255
|
+
? (raw as Record<string, unknown>)
|
|
256
|
+
: {};
|
|
257
|
+
return {
|
|
258
|
+
enabled: (() => {
|
|
259
|
+
if (rawProvenance.enabled === undefined) {
|
|
260
|
+
const envEnabled =
|
|
261
|
+
readEnvVar("REMNIC_PROVENANCE_ENABLED") ?? readEnvVar("ENGRAM_PROVENANCE_ENABLED");
|
|
262
|
+
if (envEnabled !== undefined) {
|
|
263
|
+
const coerced = coerceBool(envEnabled);
|
|
264
|
+
if (coerced === undefined) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
`REMNIC_PROVENANCE_ENABLED must be a boolean-like value (true/false/1/0/yes/no/on/off); got ${JSON.stringify(envEnabled)}`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
return coerced;
|
|
270
|
+
}
|
|
271
|
+
return true;
|
|
272
|
+
}
|
|
273
|
+
const coerced = coerceBool(rawProvenance.enabled);
|
|
274
|
+
if (coerced === undefined) {
|
|
275
|
+
throw new Error(
|
|
276
|
+
`provenance.enabled must be a boolean or one of "true"/"false"/"1"/"0"/"yes"/"no"/"on"/"off" (got ${JSON.stringify(rawProvenance.enabled)}). Omit the key to use the default-on behavior (issue #1575).`,
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
return coerced;
|
|
280
|
+
})(),
|
|
281
|
+
maxQuoteChars: (() => {
|
|
282
|
+
if (rawProvenance.maxQuoteChars === undefined) return 300;
|
|
283
|
+
const rawCap = coerceNumber(rawProvenance.maxQuoteChars);
|
|
284
|
+
// Reject present-but-invalid rather than silently widening the cap
|
|
285
|
+
// (AGENTS.md input-validation rule — a typo should not persist more
|
|
286
|
+
// text than the operator configured).
|
|
287
|
+
if (rawCap === undefined || !Number.isFinite(rawCap) || rawCap < 1 || !Number.isInteger(rawCap)) {
|
|
288
|
+
throw new Error(
|
|
289
|
+
`provenance.maxQuoteChars must be a positive integer >= 1 (got ${JSON.stringify(rawProvenance.maxQuoteChars)}).`,
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
return rawCap;
|
|
293
|
+
})(),
|
|
294
|
+
requireSpans: (() => {
|
|
295
|
+
if (rawProvenance.requireSpans === undefined) return false;
|
|
296
|
+
const coerced = coerceBool(rawProvenance.requireSpans);
|
|
297
|
+
if (coerced === undefined) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
`provenance.requireSpans must be a boolean or one of "true"/"false"/"1"/"0"/"yes"/"no"/"on"/"off" (got ${JSON.stringify(rawProvenance.requireSpans)}).`,
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
return coerced;
|
|
303
|
+
})(),
|
|
304
|
+
};
|
|
305
|
+
}
|
package/src/storage.ts
CHANGED
|
@@ -9,6 +9,7 @@ import { assertPathInsideRoot } from "./utils/path-containment.js";
|
|
|
9
9
|
import { getCachedEntities, invalidateAllForDir, setCachedEntities } from "./memory-cache.js";
|
|
10
10
|
import { rotateMarkdownFileToArchive } from "./hygiene.js";
|
|
11
11
|
import { sanitizeMemoryContent } from "./sanitize.js";
|
|
12
|
+
import { serializeProvenanceFields, parseProvenanceSources, parseProvenanceTag, reconcileProvenanceRead } from "./provenance.js";
|
|
12
13
|
import { createVersion as createPageVersion, type VersioningConfig, type VersionTrigger } from "./page-versioning.js";
|
|
13
14
|
import { isValidTranscriptDate, WEARABLES_DIR_NAME } from "./wearables/day-store.js";
|
|
14
15
|
import {
|
|
@@ -440,6 +441,7 @@ function serializeFrontmatter(fm: MemoryFrontmatter): string {
|
|
|
440
441
|
if (fm.last_reinforced_at) {
|
|
441
442
|
lines.push(`last_reinforced_at: ${fm.last_reinforced_at}`);
|
|
442
443
|
}
|
|
444
|
+
serializeProvenanceFields(fm, lines);
|
|
443
445
|
lines.push("---");
|
|
444
446
|
return lines.join("\n");
|
|
445
447
|
}
|
|
@@ -843,13 +845,11 @@ function parseFrontmatter(
|
|
|
843
845
|
// PR; no code produces these fields yet.
|
|
844
846
|
derived_from,
|
|
845
847
|
derived_via,
|
|
846
|
-
// Pattern-reinforcement metadata (issue #687 PR 2/4).
|
|
847
|
-
// permissively: invalid values (negative, non-integer, blank
|
|
848
|
-
// ISO-strings) are dropped to undefined so a corrupt frontmatter
|
|
849
|
-
// never poisons downstream scoring. Validation lives on the
|
|
850
|
-
// write path in serializeFrontmatter.
|
|
848
|
+
// Pattern-reinforcement metadata (issue #687 PR 2/4) — drop corrupt values on read (rule 34).
|
|
851
849
|
reinforcement_count: parseReinforcementCountField(fm.reinforcement_count),
|
|
852
850
|
last_reinforced_at: fm.last_reinforced_at || undefined,
|
|
851
|
+
sources: parseProvenanceSources(fm.sources),
|
|
852
|
+
provenance: reconcileProvenanceRead(parseProvenanceTag(fm.provenance), parseProvenanceSources(fm.sources)),
|
|
853
853
|
},
|
|
854
854
|
content,
|
|
855
855
|
};
|
|
@@ -2238,24 +2238,12 @@ export class StorageManager {
|
|
|
2238
2238
|
|
|
2239
2239
|
// Cache for readAllColdMemories() — keyed by cold root directory path.
|
|
2240
2240
|
// Prevents an uncached full-tree directory scan on every structured-attribute
|
|
2241
|
-
// write (Finding UOGi, PR #402 round-6).
|
|
2242
|
-
//
|
|
2243
|
-
//
|
|
2244
|
-
//
|
|
2245
|
-
//
|
|
2246
|
-
//
|
|
2247
|
-
// sentinel that is bumped (via a file-size counter in state/cold-write.log)
|
|
2248
|
-
// on every write that modifies cold-tier content. Before serving a cached
|
|
2249
|
-
// result, readAllColdMemories() reads the sentinel from disk and compares.
|
|
2250
|
-
// If they differ the entry is dropped and the cold tree is re-scanned. This
|
|
2251
|
-
// makes the cache correct across process boundaries (gateway + CLI): a second
|
|
2252
|
-
// process that writes a new cold memory bumps the sentinel on disk, so the
|
|
2253
|
-
// first process's next readAllColdMemories() sees the change within one call
|
|
2254
|
-
// (rather than waiting up to 30s for TTL expiry).
|
|
2255
|
-
//
|
|
2256
|
-
// After Finding UTsP broadened readAllColdMemories to scan the entire cold/
|
|
2257
|
-
// subtree (not just facts/+corrections/), amortizing this I/O across
|
|
2258
|
-
// back-to-back writes in the same burst is even more important.
|
|
2241
|
+
// write (Finding UOGi, PR #402 round-6). Invalidated when cold-tier content
|
|
2242
|
+
// changes (via invalidateColdMemoriesCache) and expires after COLD_SCAN_CACHE_TTL_MS.
|
|
2243
|
+
// Entries carry a `coldVersion` sentinel (Finding UvUy, PR #402 round-11) bumped
|
|
2244
|
+
// on every cold-tier write, making the cache correct across process boundaries
|
|
2245
|
+
// (gateway + CLI). After Finding UTsP broadened the scan to the entire cold/
|
|
2246
|
+
// subtree, amortizing across back-to-back writes is even more important.
|
|
2259
2247
|
private static readonly COLD_SCAN_CACHE_TTL_MS = 30_000; // 30 seconds
|
|
2260
2248
|
private static readonly coldMemoriesCache = new Map<string, { memories: MemoryFile[]; loadedAt: number; coldVersion: number }>();
|
|
2261
2249
|
|
|
@@ -2289,6 +2277,11 @@ export class StorageManager {
|
|
|
2289
2277
|
private offlineSyncDigestCacheWriteTimer: ReturnType<typeof setTimeout> | null = null;
|
|
2290
2278
|
/** Optional: set by the orchestrator after construction to enable template-aware citation stripping during legacy hash rebuild. */
|
|
2291
2279
|
citationTemplate: string = DEFAULT_CITATION_FORMAT;
|
|
2280
|
+
/** Post-write catalog hook (#1522). Installed by the namespace router; fire-and-forget. */
|
|
2281
|
+
onCatalogWrite?: () => void;
|
|
2282
|
+
private notifyCatalogWrite(): void {
|
|
2283
|
+
try { this.onCatalogWrite?.(); } catch { /* gotcha #13 */ }
|
|
2284
|
+
}
|
|
2292
2285
|
|
|
2293
2286
|
/** Page-versioning configuration. Set by the orchestrator after construction. */
|
|
2294
2287
|
private _versioningConfig: VersioningConfig | null = null;
|
|
@@ -2576,7 +2569,7 @@ export class StorageManager {
|
|
|
2576
2569
|
): Promise<void> {
|
|
2577
2570
|
const targetPath = this.wearableTranscriptPath(sourceId, date);
|
|
2578
2571
|
// writeMaybeEncryptedFile handles mkdir + atomic temp→rename.
|
|
2579
|
-
await
|
|
2572
|
+
await this.writeStorageSecureFile(targetPath, serialized);
|
|
2580
2573
|
}
|
|
2581
2574
|
|
|
2582
2575
|
/** Read a stored day transcript; null when the day has no file. */
|
|
@@ -2747,8 +2740,13 @@ export class StorageManager {
|
|
|
2747
2740
|
private readStorageSecureFile(filePath: string): Promise<string> {
|
|
2748
2741
|
return readMaybeEncryptedFile(filePath, this._secureStoreKey, this.baseDir);
|
|
2749
2742
|
}
|
|
2750
|
-
private writeStorageSecureFile(filePath: string, content: string): Promise<void> {
|
|
2751
|
-
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir)
|
|
2743
|
+
private writeStorageSecureFile(filePath: string, content: string | Buffer): Promise<void> {
|
|
2744
|
+
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir)
|
|
2745
|
+
.then(() => this.notifyCatalogWrite());
|
|
2746
|
+
}
|
|
2747
|
+
private writeStorageSecureFileChunks(filePath: string, chunks: AsyncIterable<Buffer>): Promise<void> {
|
|
2748
|
+
return writeMaybeEncryptedFileFromChunks(filePath, chunks, this.resolveWriteKey(), {}, this.baseDir)
|
|
2749
|
+
.then(() => this.notifyCatalogWrite());
|
|
2752
2750
|
}
|
|
2753
2751
|
|
|
2754
2752
|
private assertManagedStoragePath(filePath: string, method: string): string {
|
|
@@ -2929,18 +2927,18 @@ export class StorageManager {
|
|
|
2929
2927
|
|
|
2930
2928
|
async writeOfflineSyncFile(filePath: string, content: Buffer): Promise<void> {
|
|
2931
2929
|
const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncFile");
|
|
2932
|
-
await
|
|
2930
|
+
await this.writeStorageSecureFile(target, content);
|
|
2933
2931
|
await this.invalidateAfterOfflineSyncMutation(target);
|
|
2934
2932
|
}
|
|
2935
2933
|
|
|
2936
2934
|
async writeOfflineSyncStagingFile(filePath: string, content: Buffer): Promise<void> {
|
|
2937
2935
|
const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncStagingFile");
|
|
2938
|
-
await
|
|
2936
|
+
await this.writeStorageSecureFile(target, content);
|
|
2939
2937
|
}
|
|
2940
2938
|
|
|
2941
2939
|
async writeOfflineSyncFileChunks(filePath: string, chunks: AsyncIterable<Buffer>): Promise<void> {
|
|
2942
2940
|
const target = this.assertManagedStoragePath(filePath, "storage.writeOfflineSyncFileChunks");
|
|
2943
|
-
await
|
|
2941
|
+
await this.writeStorageSecureFileChunks(target, chunks);
|
|
2944
2942
|
await this.invalidateAfterOfflineSyncMutation(target);
|
|
2945
2943
|
}
|
|
2946
2944
|
|
|
@@ -3005,12 +3003,14 @@ export class StorageManager {
|
|
|
3005
3003
|
if (isEncryptedFile(await readFile(filePath))) {
|
|
3006
3004
|
const existing = await this.readStorageSecureFile(filePath);
|
|
3007
3005
|
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, null, {}, this.baseDir);
|
|
3006
|
+
this.notifyCatalogWrite();
|
|
3008
3007
|
return;
|
|
3009
3008
|
}
|
|
3010
3009
|
} catch (err) {
|
|
3011
3010
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
3012
3011
|
}
|
|
3013
3012
|
await appendFile(filePath, content, "utf-8");
|
|
3013
|
+
this.notifyCatalogWrite();
|
|
3014
3014
|
return;
|
|
3015
3015
|
}
|
|
3016
3016
|
|
|
@@ -3021,6 +3021,7 @@ export class StorageManager {
|
|
|
3021
3021
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
3022
3022
|
}
|
|
3023
3023
|
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, writeKey, {}, this.baseDir);
|
|
3024
|
+
this.notifyCatalogWrite();
|
|
3024
3025
|
}
|
|
3025
3026
|
private get stateDir(): string {
|
|
3026
3027
|
return path.join(this.baseDir, "state");
|
|
@@ -3465,7 +3466,7 @@ export class StorageManager {
|
|
|
3465
3466
|
const filePath = await this.resolveCategoryWritePath(category, id, today);
|
|
3466
3467
|
|
|
3467
3468
|
await this.snapshotBeforeWrite(filePath, "write");
|
|
3468
|
-
await
|
|
3469
|
+
await this.writeStorageSecureFile(filePath, fileContent);
|
|
3469
3470
|
this.invalidateAllMemoriesCache();
|
|
3470
3471
|
await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.writeMemory", {
|
|
3471
3472
|
memoryId: id,
|
|
@@ -3638,7 +3639,7 @@ export class StorageManager {
|
|
|
3638
3639
|
return "";
|
|
3639
3640
|
}
|
|
3640
3641
|
const filePath = path.join(dir, `${id}.md`);
|
|
3641
|
-
await
|
|
3642
|
+
await this.writeStorageSecureFile(filePath, `${serializeFrontmatter(fm)}\n\n${sanitized.text}\n`);
|
|
3642
3643
|
const actor =
|
|
3643
3644
|
typeof options.actor === "string" && options.actor.length > 0
|
|
3644
3645
|
? options.actor
|
|
@@ -3876,7 +3877,7 @@ export class StorageManager {
|
|
|
3876
3877
|
async writeProfile(content: string): Promise<void> {
|
|
3877
3878
|
await this.ensureDirectories();
|
|
3878
3879
|
await this.snapshotBeforeWrite(this.profilePath, "consolidation");
|
|
3879
|
-
await
|
|
3880
|
+
await this.writeStorageSecureFile(this.profilePath, content);
|
|
3880
3881
|
log.debug("updated profile.md");
|
|
3881
3882
|
}
|
|
3882
3883
|
|
|
@@ -4601,10 +4602,9 @@ export class StorageManager {
|
|
|
4601
4602
|
|
|
4602
4603
|
private async writeMemoryFileAtomic(targetPath: string, memory: MemoryFile): Promise<void> {
|
|
4603
4604
|
const fileContent = `${serializeFrontmatter(memory.frontmatter)}\n\n${memory.content}\n`;
|
|
4604
|
-
// writeMaybeEncryptedFile handles atomic temp→rename internally and
|
|
4605
|
-
// calls mkdir on the parent directory — no need to duplicate here.
|
|
4606
4605
|
await writeMaybeEncryptedFile(targetPath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
4607
4606
|
this.invalidateAllMemoriesCache();
|
|
4607
|
+
this.notifyCatalogWrite();
|
|
4608
4608
|
}
|
|
4609
4609
|
|
|
4610
4610
|
async moveMemoryToPath(memory: MemoryFile, targetPath: string): Promise<void> {
|
|
@@ -4694,7 +4694,7 @@ export class StorageManager {
|
|
|
4694
4694
|
const destPath = path.join(destDir, path.basename(memory.path));
|
|
4695
4695
|
|
|
4696
4696
|
// Write to archive location first (encrypted if applicable), then remove original.
|
|
4697
|
-
await
|
|
4697
|
+
await this.writeStorageSecureFile(destPath, fileContent);
|
|
4698
4698
|
await unlink(memory.path);
|
|
4699
4699
|
this.invalidateAllMemoriesCache();
|
|
4700
4700
|
await this.appendGeneratedMemoryLifecycleEventFailOpen(
|
|
@@ -4851,7 +4851,7 @@ export class StorageManager {
|
|
|
4851
4851
|
log.warn(`updated memory content sanitized for ${id}; violations=${sanitized.violations.join(", ")}`);
|
|
4852
4852
|
}
|
|
4853
4853
|
const fileContent = `${serializeFrontmatter(updated)}\n\n${sanitized.text}\n`;
|
|
4854
|
-
await
|
|
4854
|
+
await this.writeStorageSecureFile(memory.path, fileContent);
|
|
4855
4855
|
this.invalidateAllMemoriesCache();
|
|
4856
4856
|
await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.updateMemory", {
|
|
4857
4857
|
memoryId: id,
|
|
@@ -4886,7 +4886,7 @@ export class StorageManager {
|
|
|
4886
4886
|
const afterStatus = updated.status ?? "active";
|
|
4887
4887
|
|
|
4888
4888
|
const fileContent = `${serializeFrontmatter(updated)}\n\n${memory.content}\n`;
|
|
4889
|
-
await
|
|
4889
|
+
await this.writeStorageSecureFile(memory.path, fileContent);
|
|
4890
4890
|
this.invalidateAllMemoriesCache();
|
|
4891
4891
|
// If the target file lives in cold/, bump the cold-version sentinel so
|
|
4892
4892
|
// other processes detect the change on their next readAllColdMemories()
|
|
@@ -5826,7 +5826,7 @@ export class StorageManager {
|
|
|
5826
5826
|
const content = `---\n${Object.entries(frontmatter).map(([k, v]) => `${k}: ${JSON.stringify(v)}`).join("\n")}\n---\n\n${question}\n\n**Context:** ${context}\n`;
|
|
5827
5827
|
|
|
5828
5828
|
const filePath = path.join(this.questionsDir, `${id}.md`);
|
|
5829
|
-
await
|
|
5829
|
+
await this.writeStorageSecureFile(filePath, content);
|
|
5830
5830
|
|
|
5831
5831
|
log.debug(`wrote question ${id} to ${filePath}`);
|
|
5832
5832
|
this.invalidateQuestionsCache();
|
|
@@ -5942,13 +5942,13 @@ export class StorageManager {
|
|
|
5942
5942
|
const q = questions.find((q) => q.id === id);
|
|
5943
5943
|
if (!q) return false;
|
|
5944
5944
|
|
|
5945
|
-
let raw = await
|
|
5945
|
+
let raw = await this.readStorageSecureFile(q.filePath);
|
|
5946
5946
|
raw = raw.replace(/resolved: false/, "resolved: true");
|
|
5947
5947
|
raw = raw.replace(
|
|
5948
5948
|
/---\n\n/,
|
|
5949
5949
|
`resolvedAt: "${new Date().toISOString()}"\n---\n\n`,
|
|
5950
5950
|
);
|
|
5951
|
-
await
|
|
5951
|
+
await this.writeStorageSecureFile(q.filePath, raw);
|
|
5952
5952
|
log.debug(`resolved question ${id}`);
|
|
5953
5953
|
return true;
|
|
5954
5954
|
}
|
|
@@ -7080,7 +7080,7 @@ export class StorageManager {
|
|
|
7080
7080
|
const fileContent = `${serializeFrontmatter(updatedFm)}\n\n${oldMemory.content}\n`;
|
|
7081
7081
|
|
|
7082
7082
|
try {
|
|
7083
|
-
await
|
|
7083
|
+
await this.writeStorageSecureFile(oldMemory.path, fileContent);
|
|
7084
7084
|
await this.appendGeneratedMemoryLifecycleEventFailOpen("storage.supersedeMemory", {
|
|
7085
7085
|
memoryId: oldMemoryId,
|
|
7086
7086
|
eventType: "superseded",
|
package/src/types.ts
CHANGED
|
@@ -387,6 +387,29 @@ export interface ProceduralConfig {
|
|
|
387
387
|
recallMaxProcedures: number;
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
+
/**
|
|
391
|
+
* Claim-level provenance spans (issue #1575). Controls whether extracted
|
|
392
|
+
* facts carry verbatim source-utterance excerpts and the strength tag that
|
|
393
|
+
* downstream features (faithfulness gate #1576, correction UX #1580/#1583,
|
|
394
|
+
* tombstone matching #1579, TrustScore #1577) consume.
|
|
395
|
+
*
|
|
396
|
+
* PR 1 parses the block + schema only; the extraction prompt and validator
|
|
397
|
+
* land in PR 2. When `enabled` is false, extraction prompt/output are
|
|
398
|
+
* byte-identical to pre-feature behavior (rule 39).
|
|
399
|
+
*/
|
|
400
|
+
export interface ProvenanceConfig {
|
|
401
|
+
/** Emit provenance spans on new extractions. Default true. */
|
|
402
|
+
enabled: boolean;
|
|
403
|
+
/** Maximum characters stored per quote; longer quotes truncate at a word boundary. Default 300. */
|
|
404
|
+
maxQuoteChars: number;
|
|
405
|
+
/**
|
|
406
|
+
* When true, facts whose quote cannot be located are routed to
|
|
407
|
+
* `pending_review` instead of `active`. Stays false until #1576 lands and
|
|
408
|
+
* the bench shows the gate is safe (rule 48).
|
|
409
|
+
*/
|
|
410
|
+
requireSpans: boolean;
|
|
411
|
+
}
|
|
412
|
+
|
|
390
413
|
/**
|
|
391
414
|
* Coding-agent mode config (issue #569).
|
|
392
415
|
*
|
|
@@ -951,6 +974,12 @@ export interface PluginConfig {
|
|
|
951
974
|
*/
|
|
952
975
|
dreamsPhases: DreamsPhasesConfig;
|
|
953
976
|
procedural: ProceduralConfig;
|
|
977
|
+
/**
|
|
978
|
+
* Claim-level provenance spans (issue #1575). Parsed from the
|
|
979
|
+
* `provenance` config block; see `ProvenanceConfig` for the documented
|
|
980
|
+
* defaults. PR 1 parses + persists only; extraction wiring lands in PR 2.
|
|
981
|
+
*/
|
|
982
|
+
provenance: ProvenanceConfig;
|
|
954
983
|
/**
|
|
955
984
|
* Wearable transcript ingestion (Limitless / Bee / Omi connectors).
|
|
956
985
|
* Disabled by default; see docs/wearables.md.
|
|
@@ -2514,6 +2543,28 @@ export interface MemoryFrontmatter {
|
|
|
2514
2543
|
* is absent.
|
|
2515
2544
|
*/
|
|
2516
2545
|
last_reinforced_at?: string;
|
|
2546
|
+
// Claim-level provenance spans (issue #1575).
|
|
2547
|
+
//
|
|
2548
|
+
// Verbatim source-utterance excerpts that ground each extracted fact, plus
|
|
2549
|
+
// a coarse `provenance` tag recording whether the span was located in the
|
|
2550
|
+
// buffered turn text. Absent on legacy memories written before #1575;
|
|
2551
|
+
// readers MUST treat both `undefined` (legacy) and `provenance: "none"`
|
|
2552
|
+
// uniformly — never crash, never drop the fact (rule 34 spirit).
|
|
2553
|
+
//
|
|
2554
|
+
// `charStart` / `charEnd` are best-effort debugging aids — consumers MUST
|
|
2555
|
+
// tolerate their absence (turn text is not persisted forever). The span
|
|
2556
|
+
// interval is half-open [charStart, charEnd) per rule 35.
|
|
2557
|
+
//
|
|
2558
|
+
// PR 1 wires only the schema + storage round-trip — no extraction prompt,
|
|
2559
|
+
// validator, or read surfaces yet.
|
|
2560
|
+
/** Literal source-utterance excerpts backing this fact (issue #1575). */
|
|
2561
|
+
sources?: ProvenanceSource[];
|
|
2562
|
+
/**
|
|
2563
|
+
* Coarse provenance strength: `"verified"` (span located in source text),
|
|
2564
|
+
* `"unverified"` (span present but not locatable), or `"none"` (no span
|
|
2565
|
+
* recorded). Readers treat absent as `"none"` for legacy memories.
|
|
2566
|
+
*/
|
|
2567
|
+
provenance?: "verified" | "unverified" | "none";
|
|
2517
2568
|
}
|
|
2518
2569
|
|
|
2519
2570
|
/** Memory link relationship types */
|
|
@@ -2527,6 +2578,31 @@ export interface MemoryLink {
|
|
|
2527
2578
|
reason?: string;
|
|
2528
2579
|
}
|
|
2529
2580
|
|
|
2581
|
+
/**
|
|
2582
|
+
* A verbatim source-utterance excerpt that grounds an extracted fact
|
|
2583
|
+
* (issue #1575). Emitted by the PR 2 extraction validator; round-tripped
|
|
2584
|
+
* through storage in PR 1.
|
|
2585
|
+
*
|
|
2586
|
+
* `quote` is the only strictly-required field — without it the entry is
|
|
2587
|
+
* meaningless and is dropped on read. `charStart` / `charEnd` are
|
|
2588
|
+
* best-effort offsets within the buffered turn text at write time and
|
|
2589
|
+
* form a half-open interval [charStart, charEnd) (rule 35).
|
|
2590
|
+
*/
|
|
2591
|
+
export interface ProvenanceSource {
|
|
2592
|
+
/** Session key of the source turn (e.g. `project/<name>/<ts>`). */
|
|
2593
|
+
sessionKey: string;
|
|
2594
|
+
/** Host-supplied turn identifier, when one was provided. */
|
|
2595
|
+
turnId?: string;
|
|
2596
|
+
/** ISO 8601 timestamp of the source turn. */
|
|
2597
|
+
observedAt: string;
|
|
2598
|
+
/** Verbatim utterance excerpt, capped at `provenance.maxQuoteChars`. */
|
|
2599
|
+
quote: string;
|
|
2600
|
+
/** Offset within the buffered turn text where the quote begins, when located. */
|
|
2601
|
+
charStart?: number;
|
|
2602
|
+
/** Half-open end offset within the buffered turn text (rule 35). */
|
|
2603
|
+
charEnd?: number;
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2530
2606
|
// Conversation Threading (Phase 3B)
|
|
2531
2607
|
export interface ConversationThread {
|
|
2532
2608
|
id: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/logger.ts"],"sourcesContent":["export interface LoggerBackend {\n info(msg: string, ...args: unknown[]): void;\n warn(msg: string, ...args: unknown[]): void;\n error(msg: string, ...args: unknown[]): void;\n debug?(msg: string, ...args: unknown[]): void;\n}\n\nconst NOOP_LOGGER: LoggerBackend = {\n info() {},\n warn() {},\n error() {},\n debug() {},\n};\n\nlet _backend: LoggerBackend = NOOP_LOGGER;\nlet _debug = false;\n\nconst CONSOLE_LOGGER: LoggerBackend = {\n info: console.info.bind(console),\n warn: console.warn.bind(console),\n error: console.error.bind(console),\n debug: console.debug.bind(console),\n};\n\nexport function initLogger(backend?: LoggerBackend, debug?: boolean): void {\n _backend = backend ?? CONSOLE_LOGGER;\n _debug = debug ?? false;\n}\n\nexport const log = {\n info(msg: string, ...args: unknown[]): void {\n _backend.info(`remnic: ${msg}`, ...args);\n },\n warn(msg: string, ...args: unknown[]): void {\n _backend.warn(`remnic: ${msg}`, ...args);\n },\n error(msg: string, err?: unknown): void {\n const detail =\n err instanceof Error ? err.message : err ? String(err) : \"\";\n _backend.error(\n `remnic: ${msg}${detail ? ` — ${detail}` : \"\"}`,\n );\n },\n debug(msg: string, ...args: unknown[]): void {\n if (!_debug) return;\n const fn = _backend.debug ?? _backend.info;\n fn(`remnic [debug]: ${msg}`, ...args);\n },\n};\n"],"mappings":";AAOA,IAAM,cAA6B;AAAA,EACjC,OAAO;AAAA,EAAC;AAAA,EACR,OAAO;AAAA,EAAC;AAAA,EACR,QAAQ;AAAA,EAAC;AAAA,EACT,QAAQ;AAAA,EAAC;AACX;AAEA,IAAI,WAA0B;AAC9B,IAAI,SAAS;AAEb,IAAM,iBAAgC;AAAA,EACpC,MAAM,QAAQ,KAAK,KAAK,OAAO;AAAA,EAC/B,MAAM,QAAQ,KAAK,KAAK,OAAO;AAAA,EAC/B,OAAO,QAAQ,MAAM,KAAK,OAAO;AAAA,EACjC,OAAO,QAAQ,MAAM,KAAK,OAAO;AACnC;AAEO,SAAS,WAAW,SAAyB,OAAuB;AACzE,aAAW,WAAW;AACtB,WAAS,SAAS;AACpB;AAEO,IAAM,MAAM;AAAA,EACjB,KAAK,QAAgB,MAAuB;AAC1C,aAAS,KAAK,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,EACzC;AAAA,EACA,KAAK,QAAgB,MAAuB;AAC1C,aAAS,KAAK,WAAW,GAAG,IAAI,GAAG,IAAI;AAAA,EACzC;AAAA,EACA,MAAM,KAAa,KAAqB;AACtC,UAAM,SACJ,eAAe,QAAQ,IAAI,UAAU,MAAM,OAAO,GAAG,IAAI;AAC3D,aAAS;AAAA,MACP,WAAW,GAAG,GAAG,SAAS,WAAM,MAAM,KAAK,EAAE;AAAA,IAC/C;AAAA,EACF;AAAA,EACA,MAAM,QAAgB,MAAuB;AAC3C,QAAI,CAAC,OAAQ;AACb,UAAM,KAAK,SAAS,SAAS,SAAS;AACtC,OAAG,mBAAmB,GAAG,IAAI,GAAG,IAAI;AAAA,EACtC;AACF;","names":[]}
|