@remnic/core 9.69.35 → 9.69.37
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-admin-ops-surface.d.ts +12 -12
- package/dist/access-admin-ops-surface.js +35 -35
- package/dist/access-authorization-probe.d.ts +12 -12
- package/dist/access-authorization-probe.js +36 -36
- package/dist/access-boundary.d.ts +12 -12
- package/dist/access-boundary.js +35 -35
- package/dist/access-cli.js +116 -111
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +12 -12
- package/dist/access-extraction-force-flush.js +35 -35
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-briefing.d.ts +12 -12
- package/dist/access-http-briefing.js +36 -36
- package/dist/access-http-lcm-compaction.d.ts +12 -12
- package/dist/access-http-lifecycle-flush.d.ts +12 -12
- package/dist/access-http-offline-stream.d.ts +12 -12
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +37 -37
- package/dist/access-http.d.ts +13 -13
- package/dist/access-http.js +55 -55
- package/dist/access-identity-continuity-surface.d.ts +10 -10
- package/dist/access-identity-continuity-surface.js +35 -35
- package/dist/access-lcm-surface.d.ts +12 -12
- package/dist/access-lcm-surface.js +35 -35
- package/dist/access-mcp.d.ts +12 -12
- package/dist/access-mcp.js +44 -44
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-D8qri11P.d.ts → access-namespace-preflight-CV5cHujx.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +35 -35
- package/dist/access-observe-transcript.d.ts +10 -10
- package/dist/access-observe-write-surface.d.ts +12 -12
- package/dist/access-observe-write-surface.js +35 -35
- package/dist/access-offline-manifest.d.ts +10 -10
- package/dist/access-offline-manifest.js +2 -2
- package/dist/access-operations-batch.js +38 -38
- package/dist/access-operations.d.ts +16 -16
- package/dist/access-operations.js +43 -43
- package/dist/access-recall-concurrency.d.ts +12 -12
- package/dist/access-recall-concurrency.js +35 -35
- package/dist/access-recall-response.d.ts +12 -12
- package/dist/access-recall-response.js +35 -35
- package/dist/access-recall-surface.d.ts +12 -12
- package/dist/access-recall-surface.js +35 -35
- package/dist/access-schema.d.ts +94 -94
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-CKu5ixg9.d.ts → access-service-DwHC7lcV.d.ts} +71 -71
- package/dist/access-service-helpers.d.ts +12 -12
- package/dist/access-service.d.ts +12 -12
- package/dist/access-service.js +35 -35
- package/dist/access-surface-catalog.d.ts +12 -12
- package/dist/access-surface-catalog.js +37 -37
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- 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 -3
- package/dist/active-recall.js.map +1 -1
- package/dist/activity/digest.d.ts +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/{auto-sync-4YFATLFQ.js → auto-sync-FSRJDU63.js} +4 -4
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +10 -10
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +9 -9
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/calibration.js +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-YO5QJ6L3.js} +2 -2
- package/dist/{catalog-Bq1AxZwF.d.ts → catalog-Cl4H8N89.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 +12 -12
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-RUXPVSML.js → chunk-2AR5JFD7.js} +2 -2
- package/dist/{chunk-YNN26CIZ.js → chunk-2JGGZICG.js} +2 -2
- package/dist/{chunk-A7GQBJP5.js → chunk-2L5FSNPC.js} +10 -10
- package/dist/{chunk-XPJNT6PI.js → chunk-2PUE5P7C.js} +7 -3
- package/dist/chunk-2PUE5P7C.js.map +1 -0
- package/dist/{chunk-27IOSH2W.js → chunk-375ARKRS.js} +32 -11
- package/dist/chunk-375ARKRS.js.map +1 -0
- package/dist/{chunk-ZTG4P7NZ.js → chunk-3IXB77DA.js} +67 -67
- package/dist/{chunk-WHHEPAO3.js → chunk-3K6UFW5B.js} +3 -3
- package/dist/{chunk-UBG4GAEP.js → chunk-3OHISDDW.js} +5 -1
- package/dist/chunk-3OHISDDW.js.map +1 -0
- package/dist/chunk-3SL52JKD.js +160 -0
- package/dist/chunk-3SL52JKD.js.map +1 -0
- package/dist/{chunk-EEBQFG5E.js → chunk-3YMDY3ZF.js} +10 -10
- package/dist/{chunk-5JG5EBVL.js → chunk-4DPDIOVA.js} +2 -2
- package/dist/{chunk-UDZYNIDJ.js → chunk-4WGAMREC.js} +2 -2
- package/dist/{chunk-HXSAWV3A.js → chunk-57GDHV2D.js} +3 -3
- package/dist/{chunk-Z7ACR6MJ.js → chunk-5LLQAUMI.js} +2 -2
- package/dist/{chunk-P3ONDDIJ.js → chunk-5SYI2F47.js} +2 -2
- package/dist/{chunk-DGS34QSY.js → chunk-6E5GYDIE.js} +2 -2
- package/dist/{chunk-J7PB5UQ4.js → chunk-6Z3WW2MW.js} +2 -2
- package/dist/{chunk-GLZH5VEN.js → chunk-76DRU7C4.js} +2 -2
- package/dist/{chunk-L2QLDZJC.js → chunk-7MJBKZPU.js} +2 -2
- package/dist/{chunk-Y63ZFP4X.js → chunk-7RKBPXY6.js} +2 -2
- package/dist/chunk-A6CXG5WI.js +51 -0
- package/dist/chunk-A6CXG5WI.js.map +1 -0
- package/dist/{chunk-JSRVXI6E.js → chunk-B2YKTE7P.js} +4 -4
- package/dist/{chunk-Z3O53WZR.js → chunk-BICNRVEC.js} +2 -2
- package/dist/{chunk-BNGHPYZU.js → chunk-BLHX5FQW.js} +2 -2
- package/dist/{chunk-7CBKAQIG.js → chunk-BOADKFN4.js} +28 -4
- package/dist/chunk-BOADKFN4.js.map +1 -0
- package/dist/{chunk-2NLLXCJG.js → chunk-BXLOS5AJ.js} +2 -2
- package/dist/{chunk-776GVKL7.js → chunk-CD3C4BJN.js} +2 -2
- package/dist/{chunk-LMCD5W5B.js → chunk-CIYUWSMZ.js} +2 -2
- package/dist/{chunk-YJ6VCDMZ.js → chunk-CQ7SSBO4.js} +2 -2
- package/dist/{chunk-CNV2A557.js → chunk-CYEMS2PG.js} +2 -2
- package/dist/{chunk-DVOBLPSQ.js → chunk-D2DIYEFW.js} +6 -6
- package/dist/chunk-D2DIYEFW.js.map +1 -0
- package/dist/{chunk-OQ7SSRXP.js → chunk-DOKKRZPH.js} +21 -17
- package/dist/chunk-DOKKRZPH.js.map +1 -0
- package/dist/{chunk-UYUCCQ46.js → chunk-DOQLHCSS.js} +2 -2
- package/dist/{chunk-X7Y7WX73.js → chunk-DQEMWVMT.js} +1 -1
- package/dist/{chunk-RRZKTSFG.js → chunk-FCFAYMTU.js} +2 -2
- package/dist/{chunk-R4OCGPSH.js → chunk-FJMYMJLR.js} +2 -2
- package/dist/{chunk-TKFSXDOB.js → chunk-FLLORID2.js} +2 -2
- package/dist/{chunk-QATYVTP7.js → chunk-FPQDZCUX.js} +2 -2
- package/dist/{chunk-L2WQVSKP.js → chunk-G5MO3VQA.js} +2 -2
- package/dist/{chunk-LNDLXMH6.js → chunk-GDDSXVWR.js} +2 -2
- package/dist/{chunk-JZ2CHRLB.js → chunk-GHX5PNXW.js} +2 -2
- package/dist/{chunk-2BQ4ZIWC.js → chunk-GNR6YEWZ.js} +5 -5
- package/dist/{chunk-5FAGCOZD.js → chunk-GWK7FEUL.js} +4 -4
- package/dist/{chunk-SCXURCVT.js → chunk-GWQVMKUJ.js} +3 -3
- package/dist/{chunk-QBLDCI6E.js → chunk-HHDTBYDJ.js} +2 -2
- package/dist/{chunk-2YLMUME2.js → chunk-IQZ6ISFX.js} +2 -2
- package/dist/chunk-JE26AUX6.js +16 -0
- package/dist/chunk-JE26AUX6.js.map +1 -0
- package/dist/{chunk-AJTG3CP7.js → chunk-JHU4EYDV.js} +11 -1
- package/dist/chunk-JHU4EYDV.js.map +1 -0
- package/dist/{chunk-JHZCXUQI.js → chunk-JLXWRQNR.js} +33 -33
- package/dist/{chunk-FVJ4D6L7.js → chunk-JMPYZJQN.js} +1 -1
- package/dist/{chunk-HC4GFLMQ.js → chunk-JO5TQAKW.js} +3 -3
- package/dist/{chunk-ZBEGS7OB.js → chunk-JPKZTCWZ.js} +3 -3
- package/dist/{chunk-AZSKROVQ.js → chunk-JYR4LH76.js} +2 -2
- package/dist/{chunk-ECKG5WSI.js → chunk-JZYECQWN.js} +2 -2
- package/dist/{chunk-NPNSKE76.js → chunk-KTRXQQFN.js} +2 -2
- package/dist/{chunk-LEMD7WZJ.js → chunk-KUK56OPR.js} +62 -17
- package/dist/chunk-KUK56OPR.js.map +1 -0
- package/dist/{chunk-HUT2JR6I.js → chunk-L5OXE4PX.js} +2 -2
- package/dist/{chunk-B3O3IRZN.js → chunk-LMMQKZK3.js} +1 -1
- package/dist/{chunk-QURNMKME.js → chunk-LSDEIZ76.js} +2 -2
- package/dist/{chunk-XCOV45MO.js → chunk-MR6LQVZ5.js} +2 -2
- package/dist/chunk-OEBLZZKK.js +53 -0
- package/dist/chunk-OEBLZZKK.js.map +1 -0
- package/dist/{chunk-6J6K3STG.js → chunk-OTPXEE6W.js} +6 -6
- package/dist/{chunk-LYDJRF45.js → chunk-PNEDMJ53.js} +2 -2
- package/dist/{chunk-MPAJFFP3.js → chunk-PPTOAHTZ.js} +4 -4
- package/dist/{chunk-MPAJFFP3.js.map → chunk-PPTOAHTZ.js.map} +1 -1
- package/dist/{chunk-JRWW7GM6.js → chunk-Q6D7EUSQ.js} +7 -7
- package/dist/{chunk-VYXDUPYE.js → chunk-Q7JK6YEB.js} +2 -2
- package/dist/chunk-QJ2AX6DU.js +19 -0
- package/dist/chunk-QJ2AX6DU.js.map +1 -0
- package/dist/{chunk-4MDKNUV4.js → chunk-RN3MVLW3.js} +1 -1
- package/dist/chunk-RN3MVLW3.js.map +1 -0
- package/dist/{chunk-YXLUTALO.js → chunk-SAKA6PPL.js} +2 -2
- package/dist/{chunk-HWLIMQE2.js → chunk-SF6RFI5Z.js} +2 -2
- package/dist/{chunk-OS2AT2JU.js → chunk-SROIT6QY.js} +5 -5
- package/dist/{chunk-S5G2LAL7.js → chunk-SV4Z2S67.js} +4 -4
- package/dist/{chunk-DK4X5B6I.js → chunk-TFRDUD3M.js} +2 -2
- package/dist/{chunk-JR6H5CYS.js → chunk-TL7NLM2L.js} +2 -2
- package/dist/{chunk-NN4JEFON.js → chunk-TRU6JBOI.js} +2 -2
- package/dist/{chunk-PHP3MUGF.js → chunk-UYVXIY6C.js} +2 -2
- package/dist/{chunk-KQAFEZQX.js → chunk-VDX2J7OX.js} +2 -2
- package/dist/{chunk-ZHXSOMYH.js → chunk-VVX5PZFS.js} +2 -2
- package/dist/{chunk-BJETIR53.js → chunk-WS3WNLST.js} +3 -3
- package/dist/{chunk-3FJKJ5UZ.js → chunk-X7BCM2NA.js} +2 -2
- package/dist/{chunk-Q4AUIFUA.js → chunk-XAITGGX5.js} +4 -4
- package/dist/{chunk-WPDKBUWX.js → chunk-XCF3SFHD.js} +2 -2
- package/dist/{chunk-LO4UKPKX.js → chunk-YHU5XUF4.js} +2 -2
- package/dist/{chunk-F6IVBYFS.js → chunk-YIZ2EUUL.js} +51 -51
- package/dist/{chunk-EZ25VE3G.js → chunk-YNDLCWXS.js} +4 -4
- package/dist/{chunk-5VAF4ID4.js → chunk-ZEPVWLCN.js} +9 -9
- package/dist/{cli-Bk7Ctql4.d.ts → cli-1mzd5TM4.d.ts} +5 -5
- package/dist/cli.d.ts +14 -14
- package/dist/cli.js +79 -78
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +8 -8
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +9 -9
- 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 -3
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +9 -9
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +9 -9
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +3 -3
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +11 -11
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +11 -11
- package/dist/cross-lingual-recall.d.ts +1 -1
- package/dist/dashboard-runtime.js +2 -2
- package/dist/day-summary.d.ts +1 -1
- package/dist/deep-recall-http-glue.d.ts +12 -12
- package/dist/deep-recall-http-glue.js +4 -4
- package/dist/deep-recall-mcp-tools.d.ts +12 -12
- package/dist/deep-recall-policy-llm.d.ts +1 -1
- package/dist/deep-recall-seeds.d.ts +1 -1
- package/dist/deep-recall.js +2 -2
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-DLiAtj25.d.ts → dependency-propagation-delivery-Bua2ApHV.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-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +9 -9
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/explicit-capture.d.ts +10 -10
- package/dist/external-wiki-access.d.ts +12 -12
- package/dist/external-wiki-access.js +36 -36
- package/dist/external-wiki-collection-registration.d.ts +1 -1
- package/dist/external-wiki-collection.d.ts +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +12 -12
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- 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 +2 -2
- package/dist/extraction-liveness.d.ts +1 -1
- package/dist/extraction-normalization.d.ts +1 -1
- package/dist/extraction-normalization.js +2 -2
- package/dist/extraction-prompt.d.ts +11 -2
- package/dist/extraction-prompt.js +7 -3
- package/dist/extraction-source-grounding-rules.d.ts +3 -2
- package/dist/extraction-source-grounding-rules.js +1 -1
- package/dist/extraction-source-grounding.d.ts +2 -2
- package/dist/extraction-source-grounding.js +2 -2
- package/dist/extraction-span-config.d.ts +15 -0
- package/dist/extraction-span-config.js +15 -0
- package/dist/extraction-span-materialize.d.ts +105 -0
- package/dist/extraction-span-materialize.js +30 -0
- package/dist/extraction-span-materialize.js.map +1 -0
- package/dist/extraction-span-slice.js +3 -12
- package/dist/extraction-span-slice.js.map +1 -1
- package/dist/extraction-span-source-hash.js +4 -46
- package/dist/extraction-span-source-hash.js.map +1 -1
- package/dist/extraction-span-validate.js +3 -15
- package/dist/extraction-span-validate.js.map +1 -1
- package/dist/extraction.d.ts +7 -1
- package/dist/extraction.js +20 -16
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{first-start-migration-L3UFX5CU.js → first-start-migration-GZ45G5FS.js} +4 -4
- package/dist/{generic-recall-paths-DbitKJI5.d.ts → generic-recall-paths-DJBADojG.d.ts} +1 -1
- package/dist/graph-append-error.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/{graph-edge-decay-MKIRZ762.js → graph-edge-decay-ROSUPDX3.js} +5 -5
- package/dist/graph-edge-decay-ROSUPDX3.js.map +1 -0
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-jsonl.d.ts +1 -1
- package/dist/graph-jsonl.js +3 -3
- package/dist/graph-path-reconstruction.d.ts +1 -1
- package/dist/graph-path-scoring.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.d.ts +1 -1
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/importers/test-utils.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/{index-BINUgPFo.d.ts → index-Bsy8ygLL.d.ts} +2 -2
- package/dist/index.d.ts +700 -700
- package/dist/index.js +147 -142
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +4 -4
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +9 -9
- 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 +1 -1
- package/dist/location/index.d.ts +3 -3
- package/dist/location/index.js +11 -11
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +9 -9
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +9 -9
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +10 -10
- package/dist/{maintenance-ag1gYztC.d.ts → maintenance-DItyBwTC.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +12 -12
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-controller.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-snapshot.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +12 -12
- package/dist/memory-subject.d.ts +12 -12
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +10 -10
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +5 -5
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +9 -9
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +12 -12
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +23 -22
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +17 -17
- package/dist/{orchestrator-Cf3G-3Ed.d.ts → orchestrator-DBUX-aAM.d.ts} +9 -9
- package/dist/orchestrator.d.ts +10 -10
- package/dist/orchestrator.js +117 -112
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-AwB03fw_.d.ts → pipeline-BqgcOk1Z.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-BetSQn7q.d.ts → public-http-CqtZ5kv3.d.ts} +1 -1
- package/dist/{qmd-Bfaydrfm.d.ts → qmd-BD0ikV_Y.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/recall-concurrency-config.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-memory-map.d.ts +1 -1
- package/dist/recall-navigate-access.d.ts +1 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.d.ts +1 -1
- package/dist/recall-navigate-disclosure.js +1 -1
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state-view-admission.d.ts +2 -2
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.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/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +11 -2
- package/dist/reconcile/manifest.js +5 -3
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +5 -4
- package/dist/retrieval-agents.d.ts +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/salvage-envelope.d.ts +1 -1
- package/dist/schemas.d.ts +386 -176
- package/dist/schemas.js +1 -1
- package/dist/{scope-profiles-nxTKvjE-.d.ts → scope-profiles-BIJMsd0B.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 +4 -4
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +10 -10
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-C83DVakV.d.ts → semantic-consolidation-D7sJocll.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +10 -10
- package/dist/semantic-rule-promotion.js +9 -9
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +9 -9
- package/dist/{service-q-xtOoAr.d.ts → service-fwgEngUj.d.ts} +2 -2
- 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 +7 -7
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +12 -12
- package/dist/standup/build.js +9 -9
- package/dist/{storage-Ca0MbTfm.d.ts → storage-Cbll3-Tk.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +8 -8
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +15 -15
- package/dist/support-passport/index.js +38 -38
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.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 +2 -2
- 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 +2 -2
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +9 -9
- package/dist/transfer/types.d.ts +98 -98
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-yDgWDkrJ.d.ts → types-48sPkWB0.d.ts} +49 -10
- 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 +9 -9
- package/dist/who-knows-cli.d.ts +12 -12
- package/dist/who-knows-cli.js +10 -10
- package/dist/who-knows.d.ts +12 -12
- package/dist/who-knows.js +9 -9
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +42 -2
- package/src/access-http.test.ts +43 -5
- package/src/access-http.ts +2 -0
- package/src/config.ts +2 -2
- package/src/extraction-prompt.ts +37 -3
- package/src/extraction-source-grounding-rules.ts +46 -9
- package/src/extraction-source-grounding.ts +2 -1
- package/src/extraction-span-config.ts +81 -0
- package/src/extraction-span-materialize.test.ts +376 -0
- package/src/extraction-span-materialize.ts +241 -0
- package/src/extraction.ts +70 -25
- package/src/reconcile/manifest.test.ts +11 -1
- package/src/reconcile/manifest.ts +12 -0
- package/src/schemas.ts +14 -0
- package/src/source-agent-qualifier.ts +5 -1
- package/src/testing/subjects/extraction-lifecycle.test.ts +27 -10
- package/src/types.ts +9 -9
- package/dist/chunk-27IOSH2W.js.map +0 -1
- package/dist/chunk-4MDKNUV4.js.map +0 -1
- package/dist/chunk-7CBKAQIG.js.map +0 -1
- package/dist/chunk-AJTG3CP7.js.map +0 -1
- package/dist/chunk-DVOBLPSQ.js.map +0 -1
- package/dist/chunk-LEMD7WZJ.js.map +0 -1
- package/dist/chunk-OQ7SSRXP.js.map +0 -1
- package/dist/chunk-UBG4GAEP.js.map +0 -1
- package/dist/chunk-XPJNT6PI.js.map +0 -1
- /package/dist/{auto-sync-4YFATLFQ.js.map → auto-sync-FSRJDU63.js.map} +0 -0
- /package/dist/{capsule-crypto-7FJQINUR.js.map → capsule-crypto-YO5QJ6L3.js.map} +0 -0
- /package/dist/{chunk-RUXPVSML.js.map → chunk-2AR5JFD7.js.map} +0 -0
- /package/dist/{chunk-YNN26CIZ.js.map → chunk-2JGGZICG.js.map} +0 -0
- /package/dist/{chunk-A7GQBJP5.js.map → chunk-2L5FSNPC.js.map} +0 -0
- /package/dist/{chunk-ZTG4P7NZ.js.map → chunk-3IXB77DA.js.map} +0 -0
- /package/dist/{chunk-WHHEPAO3.js.map → chunk-3K6UFW5B.js.map} +0 -0
- /package/dist/{chunk-EEBQFG5E.js.map → chunk-3YMDY3ZF.js.map} +0 -0
- /package/dist/{chunk-5JG5EBVL.js.map → chunk-4DPDIOVA.js.map} +0 -0
- /package/dist/{chunk-UDZYNIDJ.js.map → chunk-4WGAMREC.js.map} +0 -0
- /package/dist/{chunk-HXSAWV3A.js.map → chunk-57GDHV2D.js.map} +0 -0
- /package/dist/{chunk-Z7ACR6MJ.js.map → chunk-5LLQAUMI.js.map} +0 -0
- /package/dist/{chunk-P3ONDDIJ.js.map → chunk-5SYI2F47.js.map} +0 -0
- /package/dist/{chunk-DGS34QSY.js.map → chunk-6E5GYDIE.js.map} +0 -0
- /package/dist/{chunk-J7PB5UQ4.js.map → chunk-6Z3WW2MW.js.map} +0 -0
- /package/dist/{chunk-GLZH5VEN.js.map → chunk-76DRU7C4.js.map} +0 -0
- /package/dist/{chunk-L2QLDZJC.js.map → chunk-7MJBKZPU.js.map} +0 -0
- /package/dist/{chunk-Y63ZFP4X.js.map → chunk-7RKBPXY6.js.map} +0 -0
- /package/dist/{chunk-JSRVXI6E.js.map → chunk-B2YKTE7P.js.map} +0 -0
- /package/dist/{chunk-Z3O53WZR.js.map → chunk-BICNRVEC.js.map} +0 -0
- /package/dist/{chunk-BNGHPYZU.js.map → chunk-BLHX5FQW.js.map} +0 -0
- /package/dist/{chunk-2NLLXCJG.js.map → chunk-BXLOS5AJ.js.map} +0 -0
- /package/dist/{chunk-776GVKL7.js.map → chunk-CD3C4BJN.js.map} +0 -0
- /package/dist/{chunk-LMCD5W5B.js.map → chunk-CIYUWSMZ.js.map} +0 -0
- /package/dist/{chunk-YJ6VCDMZ.js.map → chunk-CQ7SSBO4.js.map} +0 -0
- /package/dist/{chunk-CNV2A557.js.map → chunk-CYEMS2PG.js.map} +0 -0
- /package/dist/{chunk-UYUCCQ46.js.map → chunk-DOQLHCSS.js.map} +0 -0
- /package/dist/{chunk-X7Y7WX73.js.map → chunk-DQEMWVMT.js.map} +0 -0
- /package/dist/{chunk-RRZKTSFG.js.map → chunk-FCFAYMTU.js.map} +0 -0
- /package/dist/{chunk-R4OCGPSH.js.map → chunk-FJMYMJLR.js.map} +0 -0
- /package/dist/{chunk-TKFSXDOB.js.map → chunk-FLLORID2.js.map} +0 -0
- /package/dist/{chunk-QATYVTP7.js.map → chunk-FPQDZCUX.js.map} +0 -0
- /package/dist/{chunk-L2WQVSKP.js.map → chunk-G5MO3VQA.js.map} +0 -0
- /package/dist/{chunk-LNDLXMH6.js.map → chunk-GDDSXVWR.js.map} +0 -0
- /package/dist/{chunk-JZ2CHRLB.js.map → chunk-GHX5PNXW.js.map} +0 -0
- /package/dist/{chunk-2BQ4ZIWC.js.map → chunk-GNR6YEWZ.js.map} +0 -0
- /package/dist/{chunk-5FAGCOZD.js.map → chunk-GWK7FEUL.js.map} +0 -0
- /package/dist/{chunk-SCXURCVT.js.map → chunk-GWQVMKUJ.js.map} +0 -0
- /package/dist/{chunk-QBLDCI6E.js.map → chunk-HHDTBYDJ.js.map} +0 -0
- /package/dist/{chunk-2YLMUME2.js.map → chunk-IQZ6ISFX.js.map} +0 -0
- /package/dist/{chunk-JHZCXUQI.js.map → chunk-JLXWRQNR.js.map} +0 -0
- /package/dist/{chunk-FVJ4D6L7.js.map → chunk-JMPYZJQN.js.map} +0 -0
- /package/dist/{chunk-HC4GFLMQ.js.map → chunk-JO5TQAKW.js.map} +0 -0
- /package/dist/{chunk-ZBEGS7OB.js.map → chunk-JPKZTCWZ.js.map} +0 -0
- /package/dist/{chunk-AZSKROVQ.js.map → chunk-JYR4LH76.js.map} +0 -0
- /package/dist/{chunk-ECKG5WSI.js.map → chunk-JZYECQWN.js.map} +0 -0
- /package/dist/{chunk-NPNSKE76.js.map → chunk-KTRXQQFN.js.map} +0 -0
- /package/dist/{chunk-HUT2JR6I.js.map → chunk-L5OXE4PX.js.map} +0 -0
- /package/dist/{chunk-B3O3IRZN.js.map → chunk-LMMQKZK3.js.map} +0 -0
- /package/dist/{chunk-QURNMKME.js.map → chunk-LSDEIZ76.js.map} +0 -0
- /package/dist/{chunk-XCOV45MO.js.map → chunk-MR6LQVZ5.js.map} +0 -0
- /package/dist/{chunk-6J6K3STG.js.map → chunk-OTPXEE6W.js.map} +0 -0
- /package/dist/{chunk-LYDJRF45.js.map → chunk-PNEDMJ53.js.map} +0 -0
- /package/dist/{chunk-JRWW7GM6.js.map → chunk-Q6D7EUSQ.js.map} +0 -0
- /package/dist/{chunk-VYXDUPYE.js.map → chunk-Q7JK6YEB.js.map} +0 -0
- /package/dist/{chunk-YXLUTALO.js.map → chunk-SAKA6PPL.js.map} +0 -0
- /package/dist/{chunk-HWLIMQE2.js.map → chunk-SF6RFI5Z.js.map} +0 -0
- /package/dist/{chunk-OS2AT2JU.js.map → chunk-SROIT6QY.js.map} +0 -0
- /package/dist/{chunk-S5G2LAL7.js.map → chunk-SV4Z2S67.js.map} +0 -0
- /package/dist/{chunk-DK4X5B6I.js.map → chunk-TFRDUD3M.js.map} +0 -0
- /package/dist/{chunk-JR6H5CYS.js.map → chunk-TL7NLM2L.js.map} +0 -0
- /package/dist/{chunk-NN4JEFON.js.map → chunk-TRU6JBOI.js.map} +0 -0
- /package/dist/{chunk-PHP3MUGF.js.map → chunk-UYVXIY6C.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-VDX2J7OX.js.map} +0 -0
- /package/dist/{chunk-ZHXSOMYH.js.map → chunk-VVX5PZFS.js.map} +0 -0
- /package/dist/{chunk-BJETIR53.js.map → chunk-WS3WNLST.js.map} +0 -0
- /package/dist/{chunk-3FJKJ5UZ.js.map → chunk-X7BCM2NA.js.map} +0 -0
- /package/dist/{chunk-Q4AUIFUA.js.map → chunk-XAITGGX5.js.map} +0 -0
- /package/dist/{chunk-WPDKBUWX.js.map → chunk-XCF3SFHD.js.map} +0 -0
- /package/dist/{chunk-LO4UKPKX.js.map → chunk-YHU5XUF4.js.map} +0 -0
- /package/dist/{chunk-F6IVBYFS.js.map → chunk-YIZ2EUUL.js.map} +0 -0
- /package/dist/{chunk-EZ25VE3G.js.map → chunk-YNDLCWXS.js.map} +0 -0
- /package/dist/{chunk-5VAF4ID4.js.map → chunk-ZEPVWLCN.js.map} +0 -0
- /package/dist/{graph-edge-decay-MKIRZ762.js.map → extraction-span-config.js.map} +0 -0
- /package/dist/{first-start-migration-L3UFX5CU.js.map → first-start-migration-GZ45G5FS.js.map} +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Span-mode materialization for production extraction (issue #2333 Phase B).
|
|
3
|
+
*
|
|
4
|
+
* Runs immediately after the extraction result is parsed and BEFORE
|
|
5
|
+
* sanitize/grounding/judge/dedup/persistence, so everything downstream sees
|
|
6
|
+
* exactly one content form and the content-hash dedup invariant (checklist
|
|
7
|
+
* §13) holds by construction. Offsets die here — nothing offset-based is
|
|
8
|
+
* stored.
|
|
9
|
+
*
|
|
10
|
+
* Modes:
|
|
11
|
+
* - "off": spans are never requested; a stray span is stripped untrusted.
|
|
12
|
+
* - "shadow": spans are requested alongside full content; materialization
|
|
13
|
+
* runs for comparison only, the generated content is persisted
|
|
14
|
+
* unchanged (zero behavior change), agreement telemetry logged.
|
|
15
|
+
* - "on": materialized frame+span content is persisted; per-fact fail-open
|
|
16
|
+
* to the generated content (the frame) on any validation failure.
|
|
17
|
+
*
|
|
18
|
+
* Validation (identical to the Phase A bench contract):
|
|
19
|
+
* - `0 <= charStart < charEnd <= turn.text.length`, end-exclusive, integers;
|
|
20
|
+
* - slice length <= 400 chars and non-whitespace;
|
|
21
|
+
* - frame 1..15 words;
|
|
22
|
+
* - the turn text's stamp (sha256 + length of the exact in-memory string the
|
|
23
|
+
* model saw) must verify — offset drift is rejected, never guessed around.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { log } from "./logger.js";
|
|
27
|
+
import { stampSpanSource, verifySpanSource, type SpanSourceStamp } from "./extraction-span-source-hash.js";
|
|
28
|
+
import { validateSpanOffsets } from "./extraction-span-validate.js";
|
|
29
|
+
import { sliceSpanText } from "./extraction-span-slice.js";
|
|
30
|
+
import type { ExtractionResult } from "./types.js";
|
|
31
|
+
import type { ExtractedFactSpanRef } from "./extraction-span-config.js";
|
|
32
|
+
|
|
33
|
+
export const SPAN_MAX_SLICE_CHARS = 400;
|
|
34
|
+
export const SPAN_MAX_FRAME_WORDS = 15;
|
|
35
|
+
|
|
36
|
+
export type SpanMode = "off" | "shadow" | "on";
|
|
37
|
+
|
|
38
|
+
/** A source turn exactly as rendered into the extraction prompt. */
|
|
39
|
+
export interface SpanMaterializeTurn {
|
|
40
|
+
text: string;
|
|
41
|
+
stamp: SpanSourceStamp;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SpanMaterializeFact {
|
|
45
|
+
content: string;
|
|
46
|
+
span?: ExtractedFactSpanRef | null;
|
|
47
|
+
quote?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface SpanMaterializeTelemetry {
|
|
51
|
+
/** Facts that carried a span ref. */
|
|
52
|
+
attempts: number;
|
|
53
|
+
/** Spans that failed validation and fell back to generated content. */
|
|
54
|
+
fallbacks: number;
|
|
55
|
+
/** Shadow mode only: comparisons made / exact-or-containment agreements. */
|
|
56
|
+
shadowComparisons: number;
|
|
57
|
+
shadowAgreements: number;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Strip span refs from facts that were never given the span prompt
|
|
61
|
+
* (e.g. the proactive second pass). Untrusted: never validated, never used.
|
|
62
|
+
* The key is omitted entirely so no `span: undefined` reaches persistence. */
|
|
63
|
+
export function stripUntrustedFactSpans<T extends { span?: unknown }>(facts: readonly T[]): T[] {
|
|
64
|
+
return facts.map((fact) => {
|
|
65
|
+
if (fact.span === undefined || fact.span === null) return fact;
|
|
66
|
+
const { span: _span, ...rest } = fact;
|
|
67
|
+
return rest as T;
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function buildSpanMaterializeTurns(texts: readonly string[]): SpanMaterializeTurn[] {
|
|
72
|
+
return texts.map((text) => ({ text, stamp: stampSpanSource(text) }));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function truncateLocalExtractionConversation(
|
|
76
|
+
conversation: string,
|
|
77
|
+
maxConversationChars: number,
|
|
78
|
+
): string {
|
|
79
|
+
return conversation.length > maxConversationChars
|
|
80
|
+
? `${conversation.slice(0, maxConversationChars)}\n\n[truncated]`
|
|
81
|
+
: conversation;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export function bindLocalExtractionPrompt(
|
|
85
|
+
conversation: string,
|
|
86
|
+
turns: readonly { role: string; content: string; extractionContextOnly?: boolean }[],
|
|
87
|
+
maxConversationChars: number,
|
|
88
|
+
renderedConversation: string = conversation,
|
|
89
|
+
): { promptConversation: string; spanTurns: SpanMaterializeTurn[] } {
|
|
90
|
+
const promptConversation = truncateLocalExtractionConversation(conversation, maxConversationChars);
|
|
91
|
+
if (conversation.length <= maxConversationChars || !conversation.endsWith(renderedConversation)) {
|
|
92
|
+
return { promptConversation, spanTurns: buildSpanMaterializeTurns(turns.map((turn) => turn.content)) };
|
|
93
|
+
}
|
|
94
|
+
const renderedStart = conversation.length - renderedConversation.length;
|
|
95
|
+
const limit = maxConversationChars;
|
|
96
|
+
const texts: string[] = [];
|
|
97
|
+
let pos = 0;
|
|
98
|
+
for (let index = 0; index < turns.length; index += 1) {
|
|
99
|
+
const turn = turns[index];
|
|
100
|
+
if (turn === undefined) {
|
|
101
|
+
texts.push("");
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (index > 0) pos += 2;
|
|
105
|
+
const label = turn.extractionContextOnly === true ? `context ${turn.role}` : turn.role;
|
|
106
|
+
pos += `[${label}] `.length;
|
|
107
|
+
const absStart = renderedStart + pos;
|
|
108
|
+
const absEnd = absStart + turn.content.length;
|
|
109
|
+
texts.push(absEnd > absStart && limit > absStart ? conversation.slice(absStart, Math.min(absEnd, limit)) : "");
|
|
110
|
+
pos += turn.content.length;
|
|
111
|
+
}
|
|
112
|
+
return { promptConversation, spanTurns: buildSpanMaterializeTurns(texts) };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function factCarriesSpan(fact: { span?: ExtractedFactSpanRef | null }): boolean {
|
|
116
|
+
return fact.span !== undefined && fact.span !== null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Materialize one fact's span. Never throws: any validation failure falls
|
|
121
|
+
* open to the fact's generated content and is counted.
|
|
122
|
+
*/
|
|
123
|
+
export function materializeFactSpan<T extends SpanMaterializeFact>(
|
|
124
|
+
fact: T,
|
|
125
|
+
turns: readonly SpanMaterializeTurn[],
|
|
126
|
+
mode: SpanMode,
|
|
127
|
+
): { fact: T; outcome: "span" | "fallback"; materialized?: string } {
|
|
128
|
+
const span = fact.span ?? null;
|
|
129
|
+
if (span === null) {
|
|
130
|
+
return { fact, outcome: "fallback" };
|
|
131
|
+
}
|
|
132
|
+
const { sourceMessageIndex, charStart, charEnd, frame, sourceHash, sourceLength } = span;
|
|
133
|
+
const turn = turns[sourceMessageIndex];
|
|
134
|
+
if (
|
|
135
|
+
!Number.isInteger(sourceMessageIndex) ||
|
|
136
|
+
sourceMessageIndex < 0 ||
|
|
137
|
+
sourceMessageIndex >= turns.length ||
|
|
138
|
+
turn === undefined
|
|
139
|
+
) {
|
|
140
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
141
|
+
}
|
|
142
|
+
const stampCheck = verifySpanSource(turn.text, turn.stamp);
|
|
143
|
+
if (!stampCheck.ok) {
|
|
144
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
145
|
+
}
|
|
146
|
+
if (
|
|
147
|
+
(sourceHash !== undefined && sourceHash !== turn.stamp.hash) ||
|
|
148
|
+
(sourceLength !== undefined && sourceLength !== turn.stamp.length)
|
|
149
|
+
) {
|
|
150
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
151
|
+
}
|
|
152
|
+
const offsetCheck = validateSpanOffsets({ start: charStart, end: charEnd, textLength: turn.text.length });
|
|
153
|
+
if (!offsetCheck.ok) {
|
|
154
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
155
|
+
}
|
|
156
|
+
const slice = sliceSpanText({ text: turn.text, start: charStart, end: charEnd });
|
|
157
|
+
if (slice.length > SPAN_MAX_SLICE_CHARS || slice.trim().length === 0) {
|
|
158
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
159
|
+
}
|
|
160
|
+
const frameWords = frame.trim().split(/\s+/).filter(Boolean);
|
|
161
|
+
if (frameWords.length === 0 || frameWords.length > SPAN_MAX_FRAME_WORDS) {
|
|
162
|
+
return { fact: stripSpan(fact), outcome: "fallback" };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const trimmedFrame = frameWords.join(" ");
|
|
166
|
+
const materialized = /[:—-]$/.test(trimmedFrame)
|
|
167
|
+
? `${trimmedFrame} ${slice}`
|
|
168
|
+
: `${trimmedFrame}: ${slice}`;
|
|
169
|
+
|
|
170
|
+
if (mode === "on") {
|
|
171
|
+
return {
|
|
172
|
+
fact: { ...stripSpan(fact), content: materialized, quote: slice },
|
|
173
|
+
outcome: "span",
|
|
174
|
+
materialized,
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// shadow: persist generated content unchanged; materialize for comparison.
|
|
178
|
+
return { fact: stripSpan(fact), outcome: "span", materialized };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Shadow agreement: exact match or containment either way. */
|
|
182
|
+
export function spanAgreesWithContent(materialized: string, content: string): boolean {
|
|
183
|
+
const left = materialized.trim();
|
|
184
|
+
const right = content.trim();
|
|
185
|
+
return left === right || left.includes(right) || right.includes(left);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Whole-result span materialization pass (issue #2333 Phase B). Called from
|
|
190
|
+
* `ExtractionEngine.applySpanMaterialization` after parse, before sanitize /
|
|
191
|
+
* grounding / judge / dedup / persist. "off" strips stray spans untrusted.
|
|
192
|
+
* Shadow logs agreement telemetry and persists generated content. "on"
|
|
193
|
+
* persists materialized frame+span content; facts that omit the optional
|
|
194
|
+
* span are dropped so a short frame cannot persist as a standalone memory.
|
|
195
|
+
*/
|
|
196
|
+
export function applyExtractionSpanMaterialization(
|
|
197
|
+
result: ExtractionResult,
|
|
198
|
+
turns: readonly SpanMaterializeTurn[],
|
|
199
|
+
mode: SpanMode,
|
|
200
|
+
): ExtractionResult {
|
|
201
|
+
if (mode === "off") {
|
|
202
|
+
return { ...result, facts: stripUntrustedFactSpans(result.facts) };
|
|
203
|
+
}
|
|
204
|
+
let attempts = 0;
|
|
205
|
+
let fallbacks = 0;
|
|
206
|
+
let agreements = 0;
|
|
207
|
+
const facts = result.facts.flatMap((fact) => {
|
|
208
|
+
if (!factCarriesSpan(fact)) {
|
|
209
|
+
return mode === "on" ? [] : [fact];
|
|
210
|
+
}
|
|
211
|
+
attempts += 1;
|
|
212
|
+
const { fact: materialized, outcome, materialized: text } = materializeFactSpan(
|
|
213
|
+
fact,
|
|
214
|
+
turns,
|
|
215
|
+
mode,
|
|
216
|
+
);
|
|
217
|
+
if (outcome === "fallback") {
|
|
218
|
+
fallbacks += 1;
|
|
219
|
+
} else if (mode === "shadow" && text !== undefined) {
|
|
220
|
+
if (spanAgreesWithContent(text, fact.content)) {
|
|
221
|
+
agreements += 1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return [materialized];
|
|
225
|
+
});
|
|
226
|
+
if (mode === "shadow") {
|
|
227
|
+
log.info(
|
|
228
|
+
`extraction span-mode shadow: ${agreements}/${attempts} span facts agree with generated content (${fallbacks} span validation fallbacks)`,
|
|
229
|
+
);
|
|
230
|
+
} else if (fallbacks > 0) {
|
|
231
|
+
log.info(
|
|
232
|
+
`extraction span-mode: ${fallbacks}/${attempts} span facts fell back to generated content`,
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
return { ...result, facts };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function stripSpan<T extends SpanMaterializeFact>(fact: T): T {
|
|
239
|
+
const { span: _span, ...rest } = fact;
|
|
240
|
+
return rest as T;
|
|
241
|
+
}
|
package/src/extraction.ts
CHANGED
|
@@ -20,18 +20,8 @@ import {
|
|
|
20
20
|
type ProactiveQuestionsResultParsed,
|
|
21
21
|
DaySummaryResultSchema,
|
|
22
22
|
} from "./schemas.js";
|
|
23
|
-
import type {
|
|
24
|
-
|
|
25
|
-
ExtractionResult,
|
|
26
|
-
ConsolidationResult,
|
|
27
|
-
MemoryFile,
|
|
28
|
-
PluginConfig,
|
|
29
|
-
LlmTraceEvent,
|
|
30
|
-
GatewayConfig,
|
|
31
|
-
MemoryCategory,
|
|
32
|
-
DaySummaryResult as DaySummaryResultShape,
|
|
33
|
-
ExtractionFailureClass,
|
|
34
|
-
} from "./types.js";
|
|
23
|
+
import type { BufferTurn, ExtractionResult, ConsolidationResult, MemoryFile, PluginConfig, LlmTraceEvent, GatewayConfig, MemoryCategory, DaySummaryResult as DaySummaryResultShape, ExtractionFailureClass } from "./types.js";
|
|
24
|
+
import type { ExtractedFactSpanRef } from "./extraction-span-config.js";
|
|
35
25
|
import { ModelRegistry } from "./model-registry.js";
|
|
36
26
|
import { extractJsonCandidates } from "./json-extract.js";
|
|
37
27
|
import { sanitizeMemoryContent } from "./sanitize.js";
|
|
@@ -53,13 +43,14 @@ import { AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT, clampAmbientCaptureConfidence }
|
|
|
53
43
|
import {
|
|
54
44
|
CONSOLIDATION_RESPONSE_SCHEMA,
|
|
55
45
|
CUE_ANCHOR_PROMPT_INSTRUCTION,
|
|
56
|
-
|
|
46
|
+
extractionResponseShape,
|
|
57
47
|
OUTPUT_LANGUAGE_POLICY,
|
|
58
48
|
PROFILE_CONSOLIDATION_RESPONSE_SCHEMA,
|
|
59
49
|
buildConsolidationSystemPrompt,
|
|
60
50
|
buildExtractionInstructions,
|
|
61
51
|
buildProfileConsolidationSystemPrompt,
|
|
62
52
|
eventTimePromptInstruction,
|
|
53
|
+
spanModePromptSection,
|
|
63
54
|
} from "./extraction-prompt.js";
|
|
64
55
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
65
56
|
import {
|
|
@@ -70,8 +61,15 @@ import {
|
|
|
70
61
|
isPlainRecord,
|
|
71
62
|
} from "./extraction-normalization.js";
|
|
72
63
|
export { classifyExtractionThrownError, classifyFallbackParseFailure } from "./extraction-error-classification.js";
|
|
64
|
+
import {
|
|
65
|
+
applyExtractionSpanMaterialization,
|
|
66
|
+
bindLocalExtractionPrompt,
|
|
67
|
+
buildSpanMaterializeTurns,
|
|
68
|
+
stripUntrustedFactSpans,
|
|
69
|
+
truncateLocalExtractionConversation,
|
|
70
|
+
type SpanMaterializeTurn,
|
|
71
|
+
} from "./extraction-span-materialize.js";
|
|
73
72
|
import { resolveLocalLlmCapabilities, resolveMemoryLifecycleCapabilities, resolvePipelineProcessingCapabilities, resolveRecallAuxiliaryCapabilities } from "./capabilities.js";
|
|
74
|
-
|
|
75
73
|
type ExtractionQuestion = ExtractionResult["questions"][number];
|
|
76
74
|
type ExtractedFactResult = ExtractionResult["facts"][number];
|
|
77
75
|
type ExtractedEntityResult = ExtractionResult["entities"][number];
|
|
@@ -113,6 +111,28 @@ function normalizeQuestion(question: ExtractionQuestion): ExtractionQuestion {
|
|
|
113
111
|
};
|
|
114
112
|
}
|
|
115
113
|
|
|
114
|
+
function normalizeExtractedSpanRef(value: unknown): ExtractedFactSpanRef | undefined {
|
|
115
|
+
if (!isPlainRecord(value)) return undefined;
|
|
116
|
+
const { sourceMessageIndex, charStart, charEnd, frame, sourceHash, sourceLength } = value;
|
|
117
|
+
if (
|
|
118
|
+
typeof sourceMessageIndex !== "number" ||
|
|
119
|
+
typeof charStart !== "number" ||
|
|
120
|
+
typeof charEnd !== "number" ||
|
|
121
|
+
typeof frame !== "string"
|
|
122
|
+
) {
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
sourceMessageIndex,
|
|
127
|
+
charStart,
|
|
128
|
+
charEnd,
|
|
129
|
+
frame,
|
|
130
|
+
...(typeof sourceHash === "string" && typeof sourceLength === "number"
|
|
131
|
+
? { sourceHash, sourceLength }
|
|
132
|
+
: {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
116
136
|
function normalizeFactKey(fact: Pick<ExtractedFactResult, "category" | "content">): string {
|
|
117
137
|
return `${fact.category}:${fact.content.trim().toLowerCase()}`;
|
|
118
138
|
}
|
|
@@ -206,6 +226,22 @@ export class ExtractionEngine {
|
|
|
206
226
|
return !this.useGatewayModelSource && this.client !== null;
|
|
207
227
|
}
|
|
208
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Span-mode materialization (issue #2333 Phase B): sibling module, called
|
|
231
|
+
* after parse and before sanitize/grounding so downstream sees one content
|
|
232
|
+
* form. Offsets index the exact prompt turn texts and die at materialization.
|
|
233
|
+
*/
|
|
234
|
+
private applySpanMaterialization(
|
|
235
|
+
result: ExtractionResult,
|
|
236
|
+
spanTurns: readonly SpanMaterializeTurn[],
|
|
237
|
+
): ExtractionResult {
|
|
238
|
+
return applyExtractionSpanMaterialization(
|
|
239
|
+
result,
|
|
240
|
+
spanTurns,
|
|
241
|
+
this.config.extraction?.spanMode ?? "off",
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
209
245
|
/**
|
|
210
246
|
* Build FallbackLlmOptions with the configured gateway agent ID injected.
|
|
211
247
|
*/
|
|
@@ -328,6 +364,7 @@ export class ExtractionEngine {
|
|
|
328
364
|
procedureSteps,
|
|
329
365
|
reasoningTrace,
|
|
330
366
|
quote: extractionText(f.quote),
|
|
367
|
+
span: normalizeExtractedSpanRef(f.span),
|
|
331
368
|
eventTime: extractionText(f.eventTime) ?? extractionText(f.event_time),
|
|
332
369
|
};
|
|
333
370
|
})
|
|
@@ -628,7 +665,7 @@ export class ExtractionEngine {
|
|
|
628
665
|
const ambient = ctx.ambientCapture === true;
|
|
629
666
|
const proactiveAdditions = await this.answerProactiveQuestions(
|
|
630
667
|
conversation, base, proactive, maxAdditional, ctx.sourceConnector, ambient, signal);
|
|
631
|
-
const sanitizedAdditions = this.sanitizeExtractionResult(proactiveAdditions, ctx.messageTimestamp);
|
|
668
|
+
const sanitizedAdditions = this.sanitizeExtractionResult({ ...proactiveAdditions, facts: stripUntrustedFactSpans(proactiveAdditions.facts) }, ctx.messageTimestamp);
|
|
632
669
|
const groundedAdditions = applyGroundingWithConnector(this.config, sanitizedAdditions, ctx);
|
|
633
670
|
if (!this.hasExtractionOutputs(groundedAdditions)) return base;
|
|
634
671
|
return this.mergeProactiveExtractionPass(base, groundedAdditions, maxAdditional);
|
|
@@ -1102,6 +1139,7 @@ export class ExtractionEngine {
|
|
|
1102
1139
|
? resolvedConnector
|
|
1103
1140
|
: undefined;
|
|
1104
1141
|
const { conversation, renderedConversation } = renderExtractionConversation(boundedTurns, headerConnector(sourceConnector));
|
|
1142
|
+
const spanTurns = buildSpanMaterializeTurns(boundedTurns.map((turn) => turn.content));
|
|
1105
1143
|
|
|
1106
1144
|
const groundingSource = boundedTurns
|
|
1107
1145
|
.map((turn) => turn.content)
|
|
@@ -1191,7 +1229,16 @@ export class ExtractionEngine {
|
|
|
1191
1229
|
this.profiler.endSpan("local-llm", extractionTraceId);
|
|
1192
1230
|
this.emit({ kind: "llm_end", traceId, model: this.config.localLlmModel, operation: "extraction", durationMs });
|
|
1193
1231
|
log.debug(`extraction: used local LLM — ${localResult.facts.length} facts, ${localResult.entities.length} entities`);
|
|
1194
|
-
const
|
|
1232
|
+
const localSpanTurns = bindLocalExtractionPrompt(
|
|
1233
|
+
conversation,
|
|
1234
|
+
boundedTurns,
|
|
1235
|
+
this.modelRegistry.calculateContextSizes(
|
|
1236
|
+
this.config.localLlmModel,
|
|
1237
|
+
this.config.localLlmMaxContext,
|
|
1238
|
+
).maxInputChars,
|
|
1239
|
+
renderedConversation,
|
|
1240
|
+
).spanTurns;
|
|
1241
|
+
const sanitized = this.sanitizeExtractionResult(this.applySpanMaterialization(localResult, localSpanTurns), messageTimestamp);
|
|
1195
1242
|
const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
|
|
1196
1243
|
const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
|
|
1197
1244
|
return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
|
|
@@ -1240,7 +1287,7 @@ export class ExtractionEngine {
|
|
|
1240
1287
|
this.profiler.endSpan("direct-client", extractionTraceId);
|
|
1241
1288
|
this.emit({ kind: "llm_end", traceId, model: this.config.model, operation: "extraction", durationMs });
|
|
1242
1289
|
log.debug(`extraction: used direct client (${this.config.model}) — ${directResult.facts.length} facts, ${directResult.entities.length} entities`);
|
|
1243
|
-
const sanitized = this.sanitizeExtractionResult(directResult, messageTimestamp);
|
|
1290
|
+
const sanitized = this.sanitizeExtractionResult(this.applySpanMaterialization(directResult, spanTurns), messageTimestamp);
|
|
1244
1291
|
const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
|
|
1245
1292
|
const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
|
|
1246
1293
|
return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
|
|
@@ -1303,7 +1350,7 @@ export class ExtractionEngine {
|
|
|
1303
1350
|
role: "system" as const,
|
|
1304
1351
|
content:
|
|
1305
1352
|
buildExtractionInstructions(this.config, existingEntities, ambientCapture) +
|
|
1306
|
-
`\n\nReturn only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:\n${
|
|
1353
|
+
`\n\nReturn only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:\n${extractionResponseShape(this.config.extraction?.spanMode ?? "off")}`,
|
|
1307
1354
|
},
|
|
1308
1355
|
{ role: "user" as const, content: conversation },
|
|
1309
1356
|
];
|
|
@@ -1338,7 +1385,7 @@ export class ExtractionEngine {
|
|
|
1338
1385
|
`extracted ${result.facts.length} facts, ${result.entities.length} entities, ${(result.questions ?? []).length} questions via fallback (${detailed.modelUsed})`,
|
|
1339
1386
|
);
|
|
1340
1387
|
const normalized = this.normalizeExtractionResultPayload(result);
|
|
1341
|
-
const sanitized = this.sanitizeExtractionResult(normalized, messageTimestamp);
|
|
1388
|
+
const sanitized = this.sanitizeExtractionResult(this.applySpanMaterialization(normalized, spanTurns), messageTimestamp);
|
|
1342
1389
|
const grounded = applyGroundingWithConnector(this.config, sanitized, groundingContext);
|
|
1343
1390
|
const finalResult = await this.applyProactiveQuestionPass(conversation, grounded, groundingContext, signal);
|
|
1344
1391
|
return this.finalizeExtractionResult(finalResult, boundedTurns, resolvedConnector, ambientCapture);
|
|
@@ -1414,9 +1461,7 @@ export class ExtractionEngine {
|
|
|
1414
1461
|
log.debug(`Model context: ${contextSizes.description}`);
|
|
1415
1462
|
|
|
1416
1463
|
const maxConversationChars = contextSizes.maxInputChars;
|
|
1417
|
-
const truncatedConversation = conversation
|
|
1418
|
-
? conversation.slice(0, maxConversationChars) + "\n\n[truncated]"
|
|
1419
|
-
: conversation;
|
|
1464
|
+
const truncatedConversation = truncateLocalExtractionConversation(conversation, maxConversationChars);
|
|
1420
1465
|
|
|
1421
1466
|
const localPrompt = `You are a memory extraction system. Extract durable, reusable memories from this conversation.
|
|
1422
1467
|
|
|
@@ -1449,9 +1494,9 @@ ${CUE_ANCHOR_PROMPT_INSTRUCTION}\n- Include at most five durable relationships.$
|
|
|
1449
1494
|
- Each fact must include a quote copied verbatim from one contiguous conversation span.` : ""}${lifecycleCaps.extractionScopeClassification ? `
|
|
1450
1495
|
- Set each fact scope to "global" for cross-project knowledge or "project" for codebase-specific knowledge. Tool, command, or CLI-flag instructions tied to one agent are "project" (the same tool name can mean different things across agents); when keeping one, begin the fact with a leading "In <agent>," clause naming that agent.` : ""}${this.config.subjectClassification?.enabled === true ? `
|
|
1451
1496
|
- Set each fact subject to "user" when it models the person (preferences, relationships, biography, moments, commitments about their life) or "agent" when it is reusable operating knowledge (procedures, principles, tool-usage lessons, debugging strategies, environment facts with no personal content).` : ""}${ambientCapture ? AMBIENT_CAPTURE_PROMPT_SECTION_COMPACT : ""}
|
|
1452
|
-
${eventTimePromptInstruction(this.config)}
|
|
1497
|
+
${eventTimePromptInstruction(this.config)}${spanModePromptSection(this.config.extraction?.spanMode ?? "off")}
|
|
1453
1498
|
Return only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:
|
|
1454
|
-
${
|
|
1499
|
+
${extractionResponseShape(this.config.extraction?.spanMode ?? "off")}
|
|
1455
1500
|
|
|
1456
1501
|
Conversation:
|
|
1457
1502
|
${truncatedConversation}`;
|
|
@@ -1542,7 +1587,7 @@ ${truncatedConversation}`;
|
|
|
1542
1587
|
role: "system",
|
|
1543
1588
|
content:
|
|
1544
1589
|
buildExtractionInstructions(this.config, existingEntities, ambientCapture) +
|
|
1545
|
-
`\n\nReturn only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:\n${
|
|
1590
|
+
`\n\nReturn only valid JSON matching this shape. Placeholder text describes field shape only and is never source evidence:\n${extractionResponseShape(this.config.extraction?.spanMode ?? "off")}`,
|
|
1546
1591
|
},
|
|
1547
1592
|
{ role: "user", content: conversation },
|
|
1548
1593
|
],
|
|
@@ -5,7 +5,7 @@ import { computeLegacyContentHash } from "../content-hash.js";
|
|
|
5
5
|
import { attachCitation, formatCitation } from "../source-attribution.js";
|
|
6
6
|
import { parseFrontmatter } from "../storage.js";
|
|
7
7
|
import { ContentHashIndex } from "../storage/content-hash-index.js";
|
|
8
|
-
import { type ReconcileManifest, buildReconcileManifest, collapseActiveFactDuplicates } from "./manifest.js";
|
|
8
|
+
import { type ReconcileManifest, buildReconcileManifest, citationTemplateFingerprint, collapseActiveFactDuplicates, peerManifestRevision } from "./manifest.js";
|
|
9
9
|
import { planReconciliation } from "./plan.js";
|
|
10
10
|
|
|
11
11
|
const fileHash = (content: string): string => createHash("sha256").update(content).digest("hex");
|
|
@@ -29,6 +29,16 @@ function memoryFile(options: {
|
|
|
29
29
|
].join("\n");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
test("peer manifest revision includes the citation-template fingerprint", () => {
|
|
33
|
+
const fallback = peerManifestRevision();
|
|
34
|
+
const custom = peerManifestRevision("{{source}}");
|
|
35
|
+
assert.match(fallback, new RegExp(`(?:^|;)citation=${citationTemplateFingerprint(undefined)}(?:;|$)`));
|
|
36
|
+
assert.match(custom, new RegExp(`(?:^|;)citation=${citationTemplateFingerprint("{{source}}")}(?:;|$)`));
|
|
37
|
+
assert.notEqual(fallback, custom);
|
|
38
|
+
assert.notEqual(custom, peerManifestRevision("{{title}}"));
|
|
39
|
+
assert.equal(peerManifestRevision("{{source}}"), custom);
|
|
40
|
+
});
|
|
41
|
+
|
|
32
42
|
test("reconcile manifest keeps file identity separate from canonical semantic identity", async () => {
|
|
33
43
|
const content = "The deployment uses a durable queue with an enrichment suffix.";
|
|
34
44
|
const semanticHash = ContentHashIndex.computeHash("The deployment uses a durable queue.");
|
|
@@ -30,6 +30,18 @@ export const CONTENT_HASH_NORMALIZER_VERSION = 4;
|
|
|
30
30
|
*/
|
|
31
31
|
export const IDENTITY_RESOLUTION_VERSION = 2;
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Identity of the manifest-affecting implementation this peer builds
|
|
35
|
+
* STREAMED manifests with. Advertised via offline-sync capabilities so the
|
|
36
|
+
* client can key peer-side plan caches on it: a peer that upgrades its
|
|
37
|
+
* normalization logic or citation template without rewriting stored files
|
|
38
|
+
* keeps the same file hashes, and only this revision invalidates the stale
|
|
39
|
+
* cached identities (#2803 / #2956 review).
|
|
40
|
+
*/
|
|
41
|
+
export function peerManifestRevision(citationTemplate?: string): string {
|
|
42
|
+
return `schema=${RECONCILE_MANIFEST_SCHEMA_VERSION};normalizer=${CONTENT_HASH_NORMALIZER_VERSION};identity=${IDENTITY_RESOLUTION_VERSION};citation=${citationTemplateFingerprint(citationTemplate)}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
export interface ReconcileMemoryIdentity {
|
|
34
46
|
id: string;
|
|
35
47
|
category: string;
|
package/src/schemas.ts
CHANGED
|
@@ -129,6 +129,20 @@ export const ExtractedFactSchema = z.object({
|
|
|
129
129
|
.describe(
|
|
130
130
|
'For category "procedure" only: ordered steps (intent per step). At least two steps; include explicit trigger phrasing in content (e.g. "When you deploy…").',
|
|
131
131
|
),
|
|
132
|
+
span: z
|
|
133
|
+
.object({
|
|
134
|
+
sourceMessageIndex: z.number(),
|
|
135
|
+
charStart: z.number(),
|
|
136
|
+
charEnd: z.number(),
|
|
137
|
+
frame: z.string(),
|
|
138
|
+
sourceHash: z.string().optional().nullable(),
|
|
139
|
+
sourceLength: z.number().optional().nullable(),
|
|
140
|
+
})
|
|
141
|
+
.optional()
|
|
142
|
+
.nullable()
|
|
143
|
+
.describe(
|
|
144
|
+
'Span-mode only (issue #2333): offsets of a verbatim supporting span in the numbered conversation segment. Messages are numbered in order starting at 0; charStart/charEnd index that message\'s text in a [charStart, charEnd) interval (end-exclusive). "frame" is at most 15 words that make the span self-contained (resolve pronouns, name the subject). Optional sourceHash/sourceLength bind the span to the exact prompt text. When span-mode requests spans, omit the full "content" restatement and let the frame plus span carry the fact.',
|
|
145
|
+
),
|
|
132
146
|
reasoningTrace: z
|
|
133
147
|
.object({
|
|
134
148
|
steps: z
|
|
@@ -60,7 +60,11 @@ export function applyGroundingWithConnector(
|
|
|
60
60
|
ctx: ExtractionGroundingContext,
|
|
61
61
|
): ExtractionResult {
|
|
62
62
|
const caps = resolvePipelineProcessingCapabilities(config);
|
|
63
|
-
const options = {
|
|
63
|
+
const options = {
|
|
64
|
+
sourceGrounding: caps.sourceGrounding,
|
|
65
|
+
anchorTemporalExpressions: caps.delinearize,
|
|
66
|
+
spanMode: config.extraction?.spanMode ?? "off",
|
|
67
|
+
};
|
|
64
68
|
const known = buildKnownConnectors(ctx.sourceConnector);
|
|
65
69
|
// Scope-forcing is decoupled from strip/restore (runs without a trusted
|
|
66
70
|
// connector) but gated on the capability: flag off = byte-identical pre-#2183.
|
|
@@ -73,6 +73,7 @@ function namespacedConfig(memoryDir: string): PluginConfig {
|
|
|
73
73
|
{ name: "alice", readPrincipals: ["alice"], writePrincipals: ["alice"] },
|
|
74
74
|
{ name: "bob", readPrincipals: ["bob"], writePrincipals: ["bob"] },
|
|
75
75
|
],
|
|
76
|
+
extraction: { spanMode: "on" },
|
|
76
77
|
});
|
|
77
78
|
}
|
|
78
79
|
|
|
@@ -98,6 +99,7 @@ function rememberedBindingConfig(memoryDir: string): PluginConfig {
|
|
|
98
99
|
principalFromSessionKeyMode: "map",
|
|
99
100
|
principalFromSessionKeyRules: [{ match: REMEMBERED_SESSION, principal: "alice" }],
|
|
100
101
|
namespacePolicies: [{ name: "alice", readPrincipals: ["alice"], writePrincipals: ["alice"] }],
|
|
102
|
+
extraction: { spanMode: "on" },
|
|
101
103
|
});
|
|
102
104
|
}
|
|
103
105
|
|
|
@@ -107,6 +109,20 @@ const NAMESPACE_ROWS: Partial<Record<MatrixRowId, true>> = {
|
|
|
107
109
|
"provider-rebinding": true,
|
|
108
110
|
};
|
|
109
111
|
|
|
112
|
+
function spanBearingResult(turns: BufferTurn[]) {
|
|
113
|
+
const result = singleFactResult(turns.map((turn) => turn.content).join(" | "));
|
|
114
|
+
const first = turns[0]?.content ?? "";
|
|
115
|
+
const fact = result.facts[0];
|
|
116
|
+
if (fact === undefined) return result;
|
|
117
|
+
fact.span = {
|
|
118
|
+
sourceMessageIndex: 0,
|
|
119
|
+
charStart: 0,
|
|
120
|
+
charEnd: first.length,
|
|
121
|
+
frame: "Lifecycle probe",
|
|
122
|
+
};
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
|
|
110
126
|
async function assertHarmonicEpisode(memoryDir: string, sessionKey?: string): Promise<void> {
|
|
111
127
|
const status = await harmonicNodeStoreStatus(memoryDir);
|
|
112
128
|
assert.equal(status.nodes.invalid, 0, "harmonic persistence must write only valid abstraction nodes");
|
|
@@ -133,10 +149,15 @@ const subject: LifecycleSubject<ExtractionLifecycleState> = {
|
|
|
133
149
|
? makeHarmonicLifecycleConfig(memoryDir, {
|
|
134
150
|
extractionDedupeEnabled: true,
|
|
135
151
|
extractionDedupeWindowMs: 60_000,
|
|
152
|
+
// Issue #2333: materialization sits inside the extraction
|
|
153
|
+
// path, so the dedupe/replay row must hold with spanMode on.
|
|
154
|
+
extraction: { spanMode: "on" },
|
|
136
155
|
})
|
|
137
|
-
:
|
|
156
|
+
// Issue #2333: extraction-lifecycle rows (compaction flush,
|
|
157
|
+
// before_reset, …) must pass with `extraction.spanMode: "on"`.
|
|
158
|
+
: makeHarmonicLifecycleConfig(memoryDir, { extraction: { spanMode: "on" } });
|
|
138
159
|
primary = new Orchestrator(cfg);
|
|
139
|
-
const calls = stubExtraction(primary, (turns) =>
|
|
160
|
+
const calls = stubExtraction(primary, (turns) => spanBearingResult(turns));
|
|
140
161
|
return { memoryDir, cfg, orchestrators: [primary], calls };
|
|
141
162
|
} catch (err) {
|
|
142
163
|
// Transactional setup: a partial build must not leak the orchestrator or temp dir.
|
|
@@ -216,11 +237,9 @@ const subject: LifecycleSubject<ExtractionLifecycleState> = {
|
|
|
216
237
|
);
|
|
217
238
|
await primary.destroy();
|
|
218
239
|
state.orchestrators.length = 0;
|
|
219
|
-
const second = new Orchestrator(makeHarmonicLifecycleConfig(state.memoryDir));
|
|
240
|
+
const second = new Orchestrator(makeHarmonicLifecycleConfig(state.memoryDir, { extraction: { spanMode: "on" } }));
|
|
220
241
|
state.orchestrators.push(second);
|
|
221
|
-
state.restartCalls = stubExtraction(second, (turns) =>
|
|
222
|
-
singleFactResult(turns.map((turn) => turn.content).join(" | "))
|
|
223
|
-
);
|
|
242
|
+
state.restartCalls = stubExtraction(second, (turns) => spanBearingResult(turns));
|
|
224
243
|
// Drain the buffer that survived the restart (state/buffer.json).
|
|
225
244
|
await second.flushSession("session-parked", { reason: "session_end" });
|
|
226
245
|
return;
|
|
@@ -250,7 +269,7 @@ const subject: LifecycleSubject<ExtractionLifecycleState> = {
|
|
|
250
269
|
// Rewire the seam: extraction succeeds but trips the abort mid-flight.
|
|
251
270
|
state.abortFlushCalls = stubExtraction(primary, (turns) => {
|
|
252
271
|
controller.abort();
|
|
253
|
-
return
|
|
272
|
+
return spanBearingResult(turns);
|
|
254
273
|
});
|
|
255
274
|
let abortRejected = false;
|
|
256
275
|
await primary
|
|
@@ -267,9 +286,7 @@ const subject: LifecycleSubject<ExtractionLifecycleState> = {
|
|
|
267
286
|
// A fresh, non-aborted flush must find the turn still buffered AND must
|
|
268
287
|
// itself succeed — swallowing its failure would let a recovery-flush
|
|
269
288
|
// regression pass vacuously (the extraction call still bumps the count).
|
|
270
|
-
state.secondFlushCalls = stubExtraction(primary, (turns) =>
|
|
271
|
-
singleFactResult(turns.map((turn) => turn.content).join(" | "))
|
|
272
|
-
);
|
|
289
|
+
state.secondFlushCalls = stubExtraction(primary, (turns) => spanBearingResult(turns));
|
|
273
290
|
await primary.flushSession("session-reset", { reason: "before_reset" });
|
|
274
291
|
// The recovery flush must PERSIST the preserved turn as a fact...
|
|
275
292
|
state.recoveredFactCount = (
|
package/src/types.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { LocationConfig } from "./location/types.js";
|
|
|
4
4
|
import type { OkfConfig } from "./okf/config.js";
|
|
5
5
|
import type { ActivityConfig } from "./activity/types.js";
|
|
6
6
|
import type { WearablesConfig } from "./wearables/types.js";
|
|
7
|
+
import type { ExtractionSpanConfig, ExtractedFactSpanRef } from "./extraction-span-config.js";
|
|
7
8
|
import type { ExtractionLivenessConfig } from "./extraction-liveness.js";
|
|
8
9
|
import type { ReplicaPeersConfig } from "./replica-peers-config.js";
|
|
9
10
|
import type { ExternalWikiRoot } from "./external-wiki-config.js";
|
|
@@ -1231,6 +1232,8 @@ export interface PluginConfig
|
|
|
1231
1232
|
dreamsPhases: DreamsPhasesConfig;
|
|
1232
1233
|
procedural: ProceduralConfig;
|
|
1233
1234
|
extractionLiveness: ExtractionLivenessConfig;
|
|
1235
|
+
/** Span-mode extraction (#2333 Phase B, bench-gated). Default off. */
|
|
1236
|
+
extraction: ExtractionSpanConfig;
|
|
1234
1237
|
replicaPeers: ReplicaPeersConfig;
|
|
1235
1238
|
converge: ConvergeConfig;
|
|
1236
1239
|
/** Claim-level provenance spans (#1575); see `ProvenanceConfig` for defaults. */
|
|
@@ -3232,17 +3235,11 @@ export interface ExtractedFact {
|
|
|
3232
3235
|
* content-hash dedup (rule 23 / checklist §13).
|
|
3233
3236
|
*/
|
|
3234
3237
|
quote?: string;
|
|
3235
|
-
/**
|
|
3236
|
-
*
|
|
3237
|
-
* `provenance.requireSpans` is on. Persist path routes the fact to
|
|
3238
|
-
* `pending_review`. Stripped before persistence — never reaches frontmatter.
|
|
3239
|
-
*/
|
|
3238
|
+
/** Transient requireSpans signal (#1575 PR 2): quote unlocatable while
|
|
3239
|
+
* `provenance.requireSpans` is on → routed to `pending_review`; stripped pre-persist. */
|
|
3240
3240
|
requireSpansPending?: boolean;
|
|
3241
3241
|
promptedByQuestion?: string;
|
|
3242
|
-
/**
|
|
3243
|
-
* Project- vs global-scoped; emitted when `extractionScopeClassificationEnabled`.
|
|
3244
|
-
* Defaults to "project" with a coding context active, else "global".
|
|
3245
|
-
*/
|
|
3242
|
+
/** Project- vs global-scoped; emitted when `extractionScopeClassificationEnabled`; defaults "project" with a coding context. */
|
|
3246
3243
|
scope?: MemoryScope;
|
|
3247
3244
|
/** Extractor-assigned subject, present only when subjectClassification.enabled (issue #2372). */
|
|
3248
3245
|
subject?: MemorySubject;
|
|
@@ -3278,6 +3275,9 @@ export interface ExtractedFact {
|
|
|
3278
3275
|
* `observedAt`, then to the batch anchor, when absent.
|
|
3279
3276
|
*/
|
|
3280
3277
|
sourceTurnTimestamp?: string;
|
|
3278
|
+
/** Transient span-mode reference (issue #2333): offsets into the exact
|
|
3279
|
+
* per-turn text the extraction model saw; stripped at materialization. */
|
|
3280
|
+
span?: ExtractedFactSpanRef | null;
|
|
3281
3281
|
}
|
|
3282
3282
|
|
|
3283
3283
|
export interface ExtractedReasoningTraceStep {
|