@remnic/core 9.30.1 → 9.31.0
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 +10 -10
- package/dist/access-admin-ops-surface.js +50 -44
- package/dist/access-authorization-probe.d.ts +10 -10
- package/dist/access-authorization-probe.js +51 -45
- package/dist/access-boundary.d.ts +13 -11
- package/dist/access-boundary.js +50 -44
- package/dist/access-cli.js +168 -123
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +119 -0
- package/dist/access-extraction-force-flush.js +166 -0
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +47 -13
- package/dist/access-http-lcm-compaction.js +7 -3
- package/dist/access-http-lifecycle-flush.d.ts +132 -0
- package/dist/access-http-lifecycle-flush.js +9 -0
- package/dist/access-http-lifecycle-flush.js.map +1 -0
- package/dist/access-http.d.ts +11 -10
- package/dist/access-http.js +66 -59
- package/dist/access-identity-continuity-surface.d.ts +8 -8
- package/dist/access-identity-continuity-surface.js +50 -44
- package/dist/access-lcm-surface.d.ts +10 -10
- package/dist/access-lcm-surface.js +50 -44
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +16 -10
- package/dist/access-mcp.js +58 -52
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-VfXssvoI.d.ts → access-namespace-preflight-D4vW97H1.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +50 -44
- package/dist/access-observe-helpers.d.ts +22 -0
- package/dist/access-observe-helpers.js +10 -0
- package/dist/access-observe-helpers.js.map +1 -0
- package/dist/access-observe-write-surface.d.ts +51 -47
- package/dist/access-observe-write-surface.js +50 -44
- package/dist/access-operations-batch.js +53 -47
- package/dist/access-operations.d.ts +11 -11
- package/dist/access-operations.js +55 -49
- package/dist/access-recall-concurrency.d.ts +10 -10
- package/dist/access-recall-concurrency.js +50 -44
- package/dist/access-recall-response.d.ts +10 -10
- package/dist/access-recall-response.js +50 -44
- package/dist/access-recall-surface.d.ts +10 -10
- package/dist/access-recall-surface.js +50 -44
- package/dist/access-schema.d.ts +37 -7
- package/dist/access-schema.js +5 -3
- package/dist/{access-service-B5RwVsTV.d.ts → access-service-B6PZ_xUL.d.ts} +44 -20
- package/dist/access-service-helpers.d.ts +113 -0
- package/dist/access-service-helpers.js +8 -0
- package/dist/access-service-helpers.js.map +1 -0
- package/dist/access-service.d.ts +10 -10
- package/dist/access-service.js +50 -44
- package/dist/access-surface-catalog.d.ts +10 -10
- package/dist/access-surface-catalog.js +2 -0
- package/dist/access-surface-catalog.js.map +1 -1
- 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 +1 -1
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +8 -8
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +14 -14
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +5 -0
- package/dist/buffer-turn-helpers.js +24 -0
- package/dist/buffer-turn-helpers.js.map +1 -0
- package/dist/buffer.d.ts +17 -4
- package/dist/buffer.js +21 -1
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-crypto-GWVG7LGC.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/capsule-crypto-7FJQINUR.js.map +1 -0
- package/dist/{capsule-merge-5KKJQBWQ.js → capsule-merge-2H2IUTBT.js} +4 -4
- package/dist/{catalog-V7inUQdp.d.ts → catalog-CGFYmTT8.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 +19 -19
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-LEPOP46W.js → chunk-227UFSEQ.js} +4 -4
- package/dist/{chunk-GIBMDSJ2.js → chunk-27P5YVDU.js} +2 -2
- package/dist/{chunk-2SA56WMI.js → chunk-2LTDWSR6.js} +4 -4
- package/dist/{chunk-OWHERGF2.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-YTSNAUXN.js → chunk-3F2LKUMU.js} +22 -8
- package/dist/chunk-3F2LKUMU.js.map +1 -0
- package/dist/chunk-3QL24R5Y.js +9 -0
- package/dist/chunk-3QL24R5Y.js.map +1 -0
- package/dist/chunk-4RNZMRAV.js +60 -0
- package/dist/chunk-4RNZMRAV.js.map +1 -0
- package/dist/{chunk-6U7F52DE.js → chunk-4XHR3I67.js} +60 -60
- package/dist/chunk-5IVLTFOV.js +65 -0
- package/dist/chunk-5IVLTFOV.js.map +1 -0
- package/dist/{chunk-2EUVEDF5.js → chunk-5XA7PQ5I.js} +2 -2
- package/dist/{chunk-ALSGMEJR.js → chunk-65ZPVYTA.js} +7 -7
- package/dist/{chunk-5VQJBH2G.js → chunk-6TAUHL33.js} +2 -2
- package/dist/{chunk-HUHX2OCX.js → chunk-7DRETLP5.js} +1 -1
- package/dist/chunk-7DRETLP5.js.map +1 -0
- package/dist/{chunk-RGIWINDN.js → chunk-7G5MH4NT.js} +30 -30
- package/dist/{chunk-WVO4G37W.js → chunk-7TEZUUGM.js} +3 -3
- package/dist/{chunk-MJCGLM25.js → chunk-7VUAG236.js} +5 -5
- package/dist/{chunk-M3C2V3PV.js → chunk-AJEMDQNA.js} +12 -12
- package/dist/{chunk-RKNJBZ55.js → chunk-AU7Q3LSC.js} +7 -7
- package/dist/{chunk-ACXPX4AG.js → chunk-BR2K43MK.js} +2 -2
- package/dist/{chunk-IYZ5K7MU.js → chunk-BUE5E2HL.js} +4 -187
- package/dist/chunk-BUE5E2HL.js.map +1 -0
- package/dist/{chunk-CZRYLSSW.js → chunk-BUGVGH4N.js} +2 -2
- package/dist/{chunk-YTQNQ4KB.js → chunk-C4VQMFVM.js} +3 -3
- package/dist/{chunk-ZPSVBSOF.js → chunk-CIVDJD6P.js} +3 -3
- package/dist/{chunk-K5GB36ME.js → chunk-CZDOT5I2.js} +2 -2
- package/dist/{chunk-VI2JQPNQ.js → chunk-E4PWACUN.js} +2 -2
- package/dist/{chunk-D2ANTDGO.js → chunk-E6BMSH7U.js} +2 -2
- package/dist/{chunk-P5PXWTW7.js → chunk-EJCAV3QZ.js} +3 -3
- package/dist/{chunk-CKMO4RDY.js → chunk-EMDLM3LW.js} +4 -4
- package/dist/chunk-ER7W6H4T.js +112 -0
- package/dist/chunk-ER7W6H4T.js.map +1 -0
- package/dist/{chunk-6FUPCJUL.js → chunk-FI4F5X2V.js} +54 -54
- package/dist/chunk-FI4F5X2V.js.map +1 -0
- package/dist/{chunk-LGHKJABJ.js → chunk-GOUILH55.js} +40 -18
- package/dist/chunk-GOUILH55.js.map +1 -0
- package/dist/{chunk-G5R3D5UP.js → chunk-GTTAHHD3.js} +2 -2
- package/dist/{chunk-H5CPS5JP.js → chunk-H36LJIPD.js} +3 -3
- package/dist/{chunk-AITCS2RC.js → chunk-IJ7HK452.js} +4 -4
- package/dist/{chunk-D3LMYTBV.js → chunk-J7WZUL2K.js} +9 -9
- package/dist/{chunk-5W4ZLBEZ.js → chunk-JCFTIQBR.js} +2 -2
- package/dist/{chunk-XOZ4ALGB.js → chunk-KE353EWI.js} +3 -3
- package/dist/{chunk-W5EG6LE3.js → chunk-KIT6M7EB.js} +3 -3
- package/dist/{chunk-5W7CTZ2E.js → chunk-KQAFEZQX.js} +4 -4
- package/dist/{chunk-Z54EM5YZ.js → chunk-MAXVH44E.js} +7 -7
- package/dist/{chunk-WZFAPHIK.js → chunk-MU7ZHSZE.js} +2 -2
- package/dist/chunk-N5Z4EVOR.js +123 -0
- package/dist/chunk-N5Z4EVOR.js.map +1 -0
- package/dist/{chunk-66772WBP.js → chunk-NFXQJHJD.js} +5 -5
- package/dist/{chunk-AZ5BTEKX.js → chunk-NQUF7XKR.js} +2 -2
- package/dist/{chunk-W4FBGYGK.js → chunk-NRV4Y3PM.js} +1 -1
- package/dist/{chunk-NHWB6HG2.js → chunk-NYCGIQRA.js} +2 -2
- package/dist/{chunk-4WKA6I65.js → chunk-OGCNZPKX.js} +1119 -309
- package/dist/chunk-OGCNZPKX.js.map +1 -0
- package/dist/{chunk-QJAQNXWI.js → chunk-ONHRRJZM.js} +6 -6
- package/dist/{chunk-FDAMS4PK.js → chunk-PNPOWBGC.js} +2 -2
- package/dist/{chunk-IC6CBHCA.js → chunk-QGENAYVS.js} +2 -2
- package/dist/{chunk-GBJ4RDFR.js → chunk-QIHIHZYC.js} +66 -91
- package/dist/chunk-QIHIHZYC.js.map +1 -0
- package/dist/{chunk-YNQBRLC5.js → chunk-RUYJ7TWU.js} +517 -2011
- package/dist/chunk-RUYJ7TWU.js.map +1 -0
- package/dist/{chunk-4A6YGWQN.js → chunk-TL4TO3EA.js} +115 -120
- package/dist/chunk-TL4TO3EA.js.map +1 -0
- package/dist/{chunk-SPJXKAVF.js → chunk-U52AKICI.js} +14 -13
- package/dist/chunk-U52AKICI.js.map +1 -0
- package/dist/chunk-ULARSG5Z.js +203 -0
- package/dist/chunk-ULARSG5Z.js.map +1 -0
- package/dist/{chunk-62U4J2GN.js → chunk-UR77VKF7.js} +2 -2
- package/dist/{chunk-JCBWCYEJ.js → chunk-VANLTS5F.js} +2 -2
- package/dist/{chunk-4Z4XNEWZ.js → chunk-VCD4PSK2.js} +56 -12
- package/dist/chunk-VCD4PSK2.js.map +1 -0
- package/dist/{chunk-RMMVQQA6.js → chunk-WDISJRMG.js} +2 -2
- package/dist/{chunk-B6JDYXL7.js → chunk-WWUVONGW.js} +7 -1
- package/dist/chunk-WWUVONGW.js.map +1 -0
- package/dist/{chunk-UVYI6VIX.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-TH2LSRMG.js → chunk-XHDIB4T4.js} +2 -2
- package/dist/{chunk-CVILPI77.js → chunk-XOQSEF7X.js} +6 -6
- package/dist/{chunk-LBOD4U5B.js → chunk-YFOMN2II.js} +6 -6
- package/dist/{chunk-RPW2NOU6.js → chunk-YIAA2X3D.js} +41 -1
- package/dist/chunk-YIAA2X3D.js.map +1 -0
- package/dist/chunk-YPC7W6GA.js +1604 -0
- package/dist/chunk-YPC7W6GA.js.map +1 -0
- package/dist/{chunk-I5NLEENJ.js → chunk-Z4SWV4VW.js} +3 -3
- package/dist/{chunk-PHWUFPCO.js → chunk-ZCPP5OW6.js} +61 -53
- package/dist/chunk-ZCPP5OW6.js.map +1 -0
- package/dist/{cli-C4GbETPC.d.ts → cli-BptUDTtp.d.ts} +5 -5
- package/dist/cli.d.ts +12 -12
- package/dist/cli.js +91 -84
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +14 -14
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +14 -14
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +17 -17
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +5 -5
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +3 -3
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/contradiction/index.js +4 -4
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/backend.js +2 -2
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +26 -26
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +14 -14
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +8 -8
- 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-liveness.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +15 -2
- package/dist/extraction-source-grounding.js +10 -1
- package/dist/extraction.d.ts +2 -15
- package/dist/extraction.js +5 -4
- package/dist/fallback-llm.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-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +19 -19
- package/dist/index.js +215 -207
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +3 -3
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +6 -6
- 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-helpers.d.ts +7 -0
- package/dist/local-llm-helpers.js +16 -0
- package/dist/local-llm-helpers.js.map +1 -0
- package/dist/local-llm.d.ts +3 -6
- package/dist/local-llm.js +2 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +14 -14
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -14
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +15 -15
- package/dist/{maintenance-CL30NWtc.d.ts → maintenance-b6f92bRz.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +10 -10
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-corpus-version.js +2 -2
- 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 +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +24 -24
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +14 -14
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/offline-sync-impression-drain.js +6 -5
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +29 -29
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-doctor-replica.js +3 -3
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +38 -37
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +22 -21
- package/dist/{orchestrator-CKTCRwWV.d.ts → orchestrator-3uGxC1qO.d.ts} +72 -34
- package/dist/orchestrator.d.ts +8 -8
- package/dist/orchestrator.js +167 -159
- package/dist/page-versioning.js +3 -3
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-B7wj4rRZ.d.ts → pipeline-DepuNr-m.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/{qmd-q9tg4dHp.d.ts → qmd-Dalr3Jby.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/qmd.js +4 -4
- 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-planner-llm.d.ts +1 -1
- 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/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-divergence.js +2 -2
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +1 -1
- 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/{scope-profiles-CWDyglPM.d.ts → scope-profiles-BpiM5hTU.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +8 -8
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +12 -12
- 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-BUE3deLn.d.ts → semantic-consolidation-CMtVrf9f.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +16 -16
- package/dist/semantic-rule-promotion.js +14 -14
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +14 -14
- package/dist/{service-CXgM0bQG.d.ts → service-DuAxwSgg.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 +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-DysJq-XH.d.ts → storage-CF0Ih8GP.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +13 -13
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -2
- package/dist/summary-snapshot.d.ts +1 -1
- 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/tokens.js +2 -2
- 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 +5 -5
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-aPPzhnjT.d.ts → types-BpaYvJ6v.d.ts} +22 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +14 -14
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +3 -0
- package/src/access-cli.test.ts +93 -0
- package/src/access-cli.ts +56 -2
- package/src/access-extraction-force-flush.ts +177 -0
- package/src/access-http-extraction-force-flush.test.ts +132 -0
- package/src/access-http-lcm-compaction.ts +99 -22
- package/src/access-http-lifecycle-flush.ts +81 -0
- package/src/access-http.test.ts +227 -0
- package/src/access-http.ts +33 -40
- package/src/access-mcp-output-schemas.ts +6 -0
- package/src/access-mcp.test.ts +40 -0
- package/src/access-mcp.ts +32 -1
- package/src/access-observe-helpers.ts +180 -0
- package/src/access-observe-write-surface.ts +78 -19
- package/src/access-operations-batch.ts +2 -1
- package/src/access-schema-pi.test.ts +17 -0
- package/src/access-schema.ts +28 -11
- package/src/access-service-helpers.ts +46 -0
- package/src/access-service-observe-lcm-parity.test.ts +781 -31
- package/src/access-service-observe-scope.test.ts +88 -0
- package/src/access-service.ts +46 -128
- package/src/access-surface-catalog.test.ts +32 -0
- package/src/access-surface-catalog.ts +2 -0
- package/src/buffer-session.test.ts +148 -0
- package/src/buffer-turn-helpers.ts +152 -0
- package/src/buffer.ts +126 -201
- package/src/correction/correction-access-wiring.ts +79 -27
- package/src/correction/correction-executor.test.ts +542 -1
- package/src/correction/correction-executor.ts +309 -89
- package/src/correction/correction-planner.test.ts +35 -1
- package/src/correction/correction-planner.ts +50 -3
- package/src/correction/correction-service.ts +12 -7
- package/src/correction/correction-storage-integration.test.ts +172 -1
- package/src/correction/passive-capture.test.ts +35 -0
- package/src/correction/passive-capture.ts +17 -3
- package/src/extraction-source-grounding.ts +55 -1
- package/src/extraction-timeout.test.ts +51 -0
- package/src/extraction.ts +64 -90
- package/src/local-llm-headers-timeout.test.ts +48 -0
- package/src/local-llm-helpers.ts +58 -0
- package/src/local-llm.ts +62 -58
- package/src/orchestration/extraction-run-helpers.ts +309 -0
- package/src/orchestration/extraction-run.test.ts +350 -7
- package/src/orchestration/extraction-run.ts +327 -250
- package/src/orchestration/session-context.ts +193 -18
- package/src/orchestration/turn-ingestion.ts +61 -11
- package/src/orchestrator-flush.test.ts +511 -5
- package/src/orchestrator.ts +8 -6
- package/src/types.ts +2 -2
- package/dist/chunk-4A6YGWQN.js.map +0 -1
- package/dist/chunk-4WKA6I65.js.map +0 -1
- package/dist/chunk-4Z4XNEWZ.js.map +0 -1
- package/dist/chunk-6FUPCJUL.js.map +0 -1
- package/dist/chunk-B6JDYXL7.js.map +0 -1
- package/dist/chunk-GBJ4RDFR.js.map +0 -1
- package/dist/chunk-HUHX2OCX.js.map +0 -1
- package/dist/chunk-IYZ5K7MU.js.map +0 -1
- package/dist/chunk-LGHKJABJ.js.map +0 -1
- package/dist/chunk-PHWUFPCO.js.map +0 -1
- package/dist/chunk-RPW2NOU6.js.map +0 -1
- package/dist/chunk-SPJXKAVF.js.map +0 -1
- package/dist/chunk-YNQBRLC5.js.map +0 -1
- package/dist/chunk-YTSNAUXN.js.map +0 -1
- /package/dist/{capsule-crypto-GWVG7LGC.js.map → access-extraction-force-flush.js.map} +0 -0
- /package/dist/{capsule-merge-5KKJQBWQ.js.map → capsule-merge-2H2IUTBT.js.map} +0 -0
- /package/dist/{chunk-LEPOP46W.js.map → chunk-227UFSEQ.js.map} +0 -0
- /package/dist/{chunk-GIBMDSJ2.js.map → chunk-27P5YVDU.js.map} +0 -0
- /package/dist/{chunk-2SA56WMI.js.map → chunk-2LTDWSR6.js.map} +0 -0
- /package/dist/{chunk-OWHERGF2.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-6U7F52DE.js.map → chunk-4XHR3I67.js.map} +0 -0
- /package/dist/{chunk-2EUVEDF5.js.map → chunk-5XA7PQ5I.js.map} +0 -0
- /package/dist/{chunk-ALSGMEJR.js.map → chunk-65ZPVYTA.js.map} +0 -0
- /package/dist/{chunk-5VQJBH2G.js.map → chunk-6TAUHL33.js.map} +0 -0
- /package/dist/{chunk-RGIWINDN.js.map → chunk-7G5MH4NT.js.map} +0 -0
- /package/dist/{chunk-WVO4G37W.js.map → chunk-7TEZUUGM.js.map} +0 -0
- /package/dist/{chunk-MJCGLM25.js.map → chunk-7VUAG236.js.map} +0 -0
- /package/dist/{chunk-M3C2V3PV.js.map → chunk-AJEMDQNA.js.map} +0 -0
- /package/dist/{chunk-RKNJBZ55.js.map → chunk-AU7Q3LSC.js.map} +0 -0
- /package/dist/{chunk-ACXPX4AG.js.map → chunk-BR2K43MK.js.map} +0 -0
- /package/dist/{chunk-CZRYLSSW.js.map → chunk-BUGVGH4N.js.map} +0 -0
- /package/dist/{chunk-YTQNQ4KB.js.map → chunk-C4VQMFVM.js.map} +0 -0
- /package/dist/{chunk-ZPSVBSOF.js.map → chunk-CIVDJD6P.js.map} +0 -0
- /package/dist/{chunk-K5GB36ME.js.map → chunk-CZDOT5I2.js.map} +0 -0
- /package/dist/{chunk-VI2JQPNQ.js.map → chunk-E4PWACUN.js.map} +0 -0
- /package/dist/{chunk-D2ANTDGO.js.map → chunk-E6BMSH7U.js.map} +0 -0
- /package/dist/{chunk-P5PXWTW7.js.map → chunk-EJCAV3QZ.js.map} +0 -0
- /package/dist/{chunk-CKMO4RDY.js.map → chunk-EMDLM3LW.js.map} +0 -0
- /package/dist/{chunk-G5R3D5UP.js.map → chunk-GTTAHHD3.js.map} +0 -0
- /package/dist/{chunk-H5CPS5JP.js.map → chunk-H36LJIPD.js.map} +0 -0
- /package/dist/{chunk-AITCS2RC.js.map → chunk-IJ7HK452.js.map} +0 -0
- /package/dist/{chunk-D3LMYTBV.js.map → chunk-J7WZUL2K.js.map} +0 -0
- /package/dist/{chunk-5W4ZLBEZ.js.map → chunk-JCFTIQBR.js.map} +0 -0
- /package/dist/{chunk-XOZ4ALGB.js.map → chunk-KE353EWI.js.map} +0 -0
- /package/dist/{chunk-W5EG6LE3.js.map → chunk-KIT6M7EB.js.map} +0 -0
- /package/dist/{chunk-5W7CTZ2E.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-Z54EM5YZ.js.map → chunk-MAXVH44E.js.map} +0 -0
- /package/dist/{chunk-WZFAPHIK.js.map → chunk-MU7ZHSZE.js.map} +0 -0
- /package/dist/{chunk-66772WBP.js.map → chunk-NFXQJHJD.js.map} +0 -0
- /package/dist/{chunk-AZ5BTEKX.js.map → chunk-NQUF7XKR.js.map} +0 -0
- /package/dist/{chunk-W4FBGYGK.js.map → chunk-NRV4Y3PM.js.map} +0 -0
- /package/dist/{chunk-NHWB6HG2.js.map → chunk-NYCGIQRA.js.map} +0 -0
- /package/dist/{chunk-QJAQNXWI.js.map → chunk-ONHRRJZM.js.map} +0 -0
- /package/dist/{chunk-FDAMS4PK.js.map → chunk-PNPOWBGC.js.map} +0 -0
- /package/dist/{chunk-IC6CBHCA.js.map → chunk-QGENAYVS.js.map} +0 -0
- /package/dist/{chunk-62U4J2GN.js.map → chunk-UR77VKF7.js.map} +0 -0
- /package/dist/{chunk-JCBWCYEJ.js.map → chunk-VANLTS5F.js.map} +0 -0
- /package/dist/{chunk-RMMVQQA6.js.map → chunk-WDISJRMG.js.map} +0 -0
- /package/dist/{chunk-UVYI6VIX.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-TH2LSRMG.js.map → chunk-XHDIB4T4.js.map} +0 -0
- /package/dist/{chunk-CVILPI77.js.map → chunk-XOQSEF7X.js.map} +0 -0
- /package/dist/{chunk-LBOD4U5B.js.map → chunk-YFOMN2II.js.map} +0 -0
- /package/dist/{chunk-I5NLEENJ.js.map → chunk-Z4SWV4VW.js.map} +0 -0
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
import { strict as assert } from "node:assert";
|
|
15
|
-
import { readFile } from "node:fs/promises";
|
|
15
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
16
16
|
import path from "node:path";
|
|
17
17
|
import { test } from "node:test";
|
|
18
18
|
|
|
@@ -157,6 +157,40 @@ test("search-located plan: no targetIds → search runs and top hits become cand
|
|
|
157
157
|
});
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
+
test("aborted planning does not persist a pending plan", async () => {
|
|
161
|
+
await withTempDir(async (dir) => {
|
|
162
|
+
const abortController = new AbortController();
|
|
163
|
+
const state: StubState = {
|
|
164
|
+
candidatesById: new Map([
|
|
165
|
+
["mem-a", makeCandidate({ memoryId: "mem-a", content: "PostgreSQL" })],
|
|
166
|
+
]),
|
|
167
|
+
llmResult: () => {
|
|
168
|
+
abortController.abort();
|
|
169
|
+
return {
|
|
170
|
+
classification: "outdated",
|
|
171
|
+
confidence: 0.9,
|
|
172
|
+
actions: [{ kind: "retract", memoryId: "mem-a" }],
|
|
173
|
+
relevance: [{ memoryId: "mem-a", why: "directly contradicted" }],
|
|
174
|
+
warnings: [],
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
writeReplacementCalls: 0,
|
|
178
|
+
propagateCalls: 0,
|
|
179
|
+
retireCalls: 0,
|
|
180
|
+
};
|
|
181
|
+
const planner = new CorrectionPlanner(makeDeps(dir, state));
|
|
182
|
+
|
|
183
|
+
await assert.rejects(
|
|
184
|
+
planner.plan({ text: "PostgreSQL" }, ["default"], { abortSignal: abortController.signal }),
|
|
185
|
+
/correction planning aborted/,
|
|
186
|
+
);
|
|
187
|
+
await assert.rejects(
|
|
188
|
+
readdir(path.join(dir, "state", "corrections", "pending")),
|
|
189
|
+
/ENOENT/,
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
160
194
|
test("not-found target → explicit error (rule 34)", async () => {
|
|
161
195
|
await withTempDir(async (dir) => {
|
|
162
196
|
const state: StubState = {
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* only thing it persists is the plan document itself.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
+
import { throwIfAborted } from "../abort-error.js";
|
|
23
24
|
import { mkdir, readFile, rename, unlink, readdir, writeFile } from "node:fs/promises";
|
|
24
25
|
import path from "node:path";
|
|
25
26
|
import { serializeMutations } from "../utils/serialize-mutations.js";
|
|
@@ -150,7 +151,10 @@ export class CorrectionPlanner {
|
|
|
150
151
|
async plan(
|
|
151
152
|
request: CorrectionRequest,
|
|
152
153
|
readableNamespaces: readonly string[],
|
|
154
|
+
opts?: { abortSignal?: AbortSignal },
|
|
153
155
|
): Promise<CorrectionPlan> {
|
|
156
|
+
const abortSignal = opts?.abortSignal;
|
|
157
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
154
158
|
const cleaned = validateCorrectionRequest(request);
|
|
155
159
|
if (cleaned.text.length > CORRECTION_TEXT_MAX) {
|
|
156
160
|
// Defensive double-check; validateCorrectionRequest already throws.
|
|
@@ -171,13 +175,15 @@ export class CorrectionPlanner {
|
|
|
171
175
|
}
|
|
172
176
|
|
|
173
177
|
// 1. LOCATE
|
|
174
|
-
const located = await this.locateCandidates(cleaned, namespaces);
|
|
178
|
+
const located = await this.locateCandidates(cleaned, namespaces, abortSignal);
|
|
179
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
175
180
|
if (located.candidates.length === 0) {
|
|
176
181
|
// No candidates AND no explicit targets → empty plan is valid (the user
|
|
177
182
|
// can still discard). But explicit-target-not-found was already raised
|
|
178
183
|
// inside locateCandidates (rule 34).
|
|
179
184
|
return this.persist(
|
|
180
185
|
this.emptyPlan(cleaned, namespaces[0], "no matching memories found for the correction text"),
|
|
186
|
+
abortSignal,
|
|
181
187
|
);
|
|
182
188
|
}
|
|
183
189
|
|
|
@@ -186,6 +192,7 @@ export class CorrectionPlanner {
|
|
|
186
192
|
text: cleaned.text,
|
|
187
193
|
candidates: located.candidates,
|
|
188
194
|
});
|
|
195
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
189
196
|
|
|
190
197
|
// Validate every action shape before persisting — the adapter is trusted
|
|
191
198
|
// to validate, but a malformed action must never reach the executor
|
|
@@ -245,6 +252,7 @@ export class CorrectionPlanner {
|
|
|
245
252
|
const diff = llm.fallback
|
|
246
253
|
? ""
|
|
247
254
|
: await this.deps.renderDiff({ candidates: located.candidates, actions: llm.actions });
|
|
255
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
248
256
|
|
|
249
257
|
const createdAt = this.deps.now().toISOString();
|
|
250
258
|
const expiresAt = new Date(
|
|
@@ -275,18 +283,21 @@ export class CorrectionPlanner {
|
|
|
275
283
|
status: "pending",
|
|
276
284
|
};
|
|
277
285
|
|
|
278
|
-
|
|
286
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
287
|
+
return this.persist(plan, abortSignal);
|
|
279
288
|
}
|
|
280
289
|
|
|
281
290
|
private async locateCandidates(
|
|
282
291
|
request: CorrectionRequest,
|
|
283
292
|
namespaces: readonly string[],
|
|
293
|
+
abortSignal?: AbortSignal,
|
|
284
294
|
): Promise<{ candidates: PlannerCandidate[] }> {
|
|
285
295
|
if (request.targetIds && request.targetIds.length > 0) {
|
|
286
296
|
const targets = await this.deps.resolveTargets({
|
|
287
297
|
targetIds: request.targetIds,
|
|
288
298
|
namespaces,
|
|
289
299
|
});
|
|
300
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
290
301
|
// Expand 1-hop neighbors and merge (dedup by memoryId, keep highest score).
|
|
291
302
|
const seedIds = targets.map((c) => c.memoryId);
|
|
292
303
|
const neighbors = await this.deps.expandNeighbors({
|
|
@@ -294,6 +305,7 @@ export class CorrectionPlanner {
|
|
|
294
305
|
namespaces,
|
|
295
306
|
limit: this.deps.maxAffected,
|
|
296
307
|
});
|
|
308
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
297
309
|
return { candidates: mergeCandidates(targets, neighbors).slice(0, this.deps.maxAffected) };
|
|
298
310
|
}
|
|
299
311
|
|
|
@@ -302,6 +314,7 @@ export class CorrectionPlanner {
|
|
|
302
314
|
namespaces,
|
|
303
315
|
limit: this.deps.maxAffected,
|
|
304
316
|
});
|
|
317
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
305
318
|
if (searched.length === 0) return { candidates: [] };
|
|
306
319
|
const seedIds = searched.slice(0, Math.min(5, searched.length)).map((c) => c.memoryId);
|
|
307
320
|
const neighbors = await this.deps.expandNeighbors({
|
|
@@ -309,6 +322,7 @@ export class CorrectionPlanner {
|
|
|
309
322
|
namespaces,
|
|
310
323
|
limit: this.deps.maxAffected,
|
|
311
324
|
});
|
|
325
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
312
326
|
return { candidates: mergeCandidates(searched, neighbors).slice(0, this.deps.maxAffected) };
|
|
313
327
|
}
|
|
314
328
|
|
|
@@ -386,8 +400,13 @@ export class CorrectionPlanner {
|
|
|
386
400
|
return path.join(await this.deps.storageDir(namespace), "state", "corrections", "pending");
|
|
387
401
|
}
|
|
388
402
|
|
|
389
|
-
private async persist(
|
|
403
|
+
private async persist(
|
|
404
|
+
plan: CorrectionPlan,
|
|
405
|
+
abortSignal?: AbortSignal,
|
|
406
|
+
): Promise<CorrectionPlan> {
|
|
407
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
390
408
|
const dir = await this.pendingDir(plan.namespace);
|
|
409
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
391
410
|
const target = path.join(dir, `${plan.planId}.json`);
|
|
392
411
|
// #1678 (thread Oid8t): never-store/redaction corrections carry the very
|
|
393
412
|
// secret/pattern the user asked Remnic NOT to retain. The durable audit
|
|
@@ -411,9 +430,12 @@ export class CorrectionPlanner {
|
|
|
411
430
|
? { ...plan, request: { ...plan.request, text: REDACTED_REQUEST_TEXT } }
|
|
412
431
|
: plan;
|
|
413
432
|
await serializeMutations(`correction-plan:${target}`, async () => {
|
|
433
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
414
434
|
await mkdir(dir, { recursive: true });
|
|
415
435
|
const tmp = `${target}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
436
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
416
437
|
await writeFile(tmp, `${JSON.stringify(persistedPlan)}\n`, "utf-8");
|
|
438
|
+
throwIfAborted(abortSignal, "correction planning aborted");
|
|
417
439
|
// rename() is atomic on POSIX for same-filesystem renames (rule 54).
|
|
418
440
|
await rename(tmp, target);
|
|
419
441
|
});
|
|
@@ -503,6 +525,31 @@ export class CorrectionPlanner {
|
|
|
503
525
|
await rename(tmp, file);
|
|
504
526
|
});
|
|
505
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Return an applying plan to the pending queue when cancellation arrives
|
|
530
|
+
* before its first correction mutation.
|
|
531
|
+
*/
|
|
532
|
+
async resetApplying(namespace: string, planId: string): Promise<void> {
|
|
533
|
+
assertSafePlanId(planId);
|
|
534
|
+
const file = path.join(await this.pendingDir(namespace), `${planId}.json`);
|
|
535
|
+
await serializeMutations(`correction-plan:${file}`, async () => {
|
|
536
|
+
let raw: string;
|
|
537
|
+
try {
|
|
538
|
+
raw = await readFile(file, "utf-8");
|
|
539
|
+
} catch (err) {
|
|
540
|
+
const code = (err as NodeJS.ErrnoException)?.code;
|
|
541
|
+
if (code === "ENOENT") return;
|
|
542
|
+
throw err;
|
|
543
|
+
}
|
|
544
|
+
const plan = parsePlan(raw);
|
|
545
|
+
if (!plan || plan.status !== "applying") return;
|
|
546
|
+
plan.status = "pending";
|
|
547
|
+
delete plan.applyingAt;
|
|
548
|
+
const tmp = `${file}.${process.pid}.${Date.now().toString(36)}.tmp`;
|
|
549
|
+
await writeFile(tmp, `${JSON.stringify(plan)}\n`, "utf-8");
|
|
550
|
+
await rename(tmp, file);
|
|
551
|
+
});
|
|
552
|
+
}
|
|
506
553
|
|
|
507
554
|
async deletePlan(namespace: string, planId: string): Promise<void> {
|
|
508
555
|
assertSafePlanId(planId);
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* WRITE — both resolved through the injected namespace policy.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { throwIfAborted } from "../abort-error.js";
|
|
16
17
|
import {
|
|
17
18
|
CorrectionContractError,
|
|
18
19
|
type CorrectionOutcome,
|
|
@@ -105,16 +106,16 @@ export class CorrectionService {
|
|
|
105
106
|
* the principal can write, so reading from a non-writable namespace to
|
|
106
107
|
* draft a correction that can never be applied would be misleading.
|
|
107
108
|
*/
|
|
108
|
-
async plan(
|
|
109
|
+
async plan(
|
|
110
|
+
request: CorrectionRequest,
|
|
111
|
+
opts?: { abortSignal?: AbortSignal },
|
|
112
|
+
): Promise<CorrectionPlan> {
|
|
109
113
|
this.requireEnabled();
|
|
114
|
+
throwIfAborted(opts?.abortSignal, "correction planning aborted");
|
|
110
115
|
const authorized = await this.deps.policy.resolveAuthorizedNamespace(request);
|
|
111
|
-
|
|
116
|
+
throwIfAborted(opts?.abortSignal, "correction planning aborted");
|
|
117
|
+
return this.planner.plan(request, [authorized], opts);
|
|
112
118
|
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Apply a persisted plan by id. Requires `confirm: true` (or interactive
|
|
116
|
-
* yes at the CLI) when `applyRequiresConfirm` is on (default).
|
|
117
|
-
*/
|
|
118
119
|
async apply(
|
|
119
120
|
planId: string,
|
|
120
121
|
opts: {
|
|
@@ -122,9 +123,11 @@ export class CorrectionService {
|
|
|
122
123
|
namespace?: string;
|
|
123
124
|
sessionKey?: string;
|
|
124
125
|
principal?: string;
|
|
126
|
+
abortSignal?: AbortSignal;
|
|
125
127
|
},
|
|
126
128
|
): Promise<CorrectionOutcome> {
|
|
127
129
|
this.requireEnabled();
|
|
130
|
+
throwIfAborted(opts.abortSignal, "correction apply aborted");
|
|
128
131
|
if (this.deps.applyRequiresConfirm() && opts.confirm !== true) {
|
|
129
132
|
throw new CorrectionContractError(
|
|
130
133
|
"Correction apply requires explicit confirmation (pass `confirm: true`).",
|
|
@@ -135,8 +138,10 @@ export class CorrectionService {
|
|
|
135
138
|
...(opts.sessionKey ? { sessionKey: opts.sessionKey } : {}),
|
|
136
139
|
...(opts.principal ? { principal: opts.principal } : {}),
|
|
137
140
|
});
|
|
141
|
+
throwIfAborted(opts.abortSignal, "correction apply aborted");
|
|
138
142
|
return this.executor.apply(namespace, planId, {
|
|
139
143
|
confirm: true,
|
|
144
|
+
abortSignal: opts.abortSignal,
|
|
140
145
|
// Authorize rescope destinations through the namespace policy bound to
|
|
141
146
|
// THIS caller's principal (review thread: authorize-rescope-destination).
|
|
142
147
|
canWriteDestination: (dest) =>
|
|
@@ -12,6 +12,7 @@ import assert from "node:assert/strict";
|
|
|
12
12
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
14
|
import path from "node:path";
|
|
15
|
+
import type { MemoryFile } from "../types.js";
|
|
15
16
|
|
|
16
17
|
import { StorageManager, ContentHashIndex } from "../storage.js";
|
|
17
18
|
import { sanitizeMemoryContent } from "../sanitize.js";
|
|
@@ -19,8 +20,10 @@ import {
|
|
|
19
20
|
isEligibleCorrectionCandidate,
|
|
20
21
|
applyEditMemory,
|
|
21
22
|
appendTombstoneFn,
|
|
23
|
+
retireMemoryFn,
|
|
24
|
+
rescopeMemoryFn,
|
|
25
|
+
writeReplacementMemory,
|
|
22
26
|
} from "./correction-access-wiring.js";
|
|
23
|
-
import type { MemoryFile } from "../types.js";
|
|
24
27
|
|
|
25
28
|
async function makeStorage(prefix = "remnic-corr-wiring-") {
|
|
26
29
|
StorageManager.clearAllStaticCaches();
|
|
@@ -121,6 +124,174 @@ test("#1672 item 3: applyEditMemory leaves non-fact contentHash untouched (only
|
|
|
121
124
|
}
|
|
122
125
|
});
|
|
123
126
|
|
|
127
|
+
test("#2128 edit returns its committed id after cancellation", async () => {
|
|
128
|
+
const { storage, cleanup } = await makeStorage("remnic-corr-edit-abort-");
|
|
129
|
+
try {
|
|
130
|
+
const { id } = await storage.writeMemory("fact", "the database is MySQL", { source: "test" });
|
|
131
|
+
const originalWriteFrontmatter = storage.writeMemoryFrontmatter.bind(storage);
|
|
132
|
+
const abortController = new AbortController();
|
|
133
|
+
let committed = false;
|
|
134
|
+
(storage as any).writeMemoryFrontmatter = async (...args: any[]) => {
|
|
135
|
+
const result = await (originalWriteFrontmatter as (...inner: any[]) => Promise<unknown>)(...args);
|
|
136
|
+
committed = true;
|
|
137
|
+
abortController.abort(new Error("caller disconnected"));
|
|
138
|
+
return result;
|
|
139
|
+
};
|
|
140
|
+
const wiring = { orchestrator: { getStorage: async () => storage } } as any;
|
|
141
|
+
|
|
142
|
+
const editedId = await applyEditMemory(
|
|
143
|
+
wiring,
|
|
144
|
+
"default",
|
|
145
|
+
id,
|
|
146
|
+
"the database is PostgreSQL",
|
|
147
|
+
abortController.signal,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
assert.equal(committed, true);
|
|
151
|
+
assert.equal(editedId, id);
|
|
152
|
+
assert.equal((await storage.getMemoryById(id))?.content, "the database is PostgreSQL");
|
|
153
|
+
} finally {
|
|
154
|
+
await cleanup();
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test("#2128 retirement completes after cancellation during the durable write", async () => {
|
|
159
|
+
const { storage, cleanup } = await makeStorage("remnic-corr-retire-abort-");
|
|
160
|
+
try {
|
|
161
|
+
const { id } = await storage.writeMemory("fact", "the database is MySQL", { source: "test" });
|
|
162
|
+
const originalWriteFrontmatter = storage.writeMemoryFrontmatter.bind(storage);
|
|
163
|
+
const abortController = new AbortController();
|
|
164
|
+
let committed = false;
|
|
165
|
+
(storage as any).writeMemoryFrontmatter = async (...args: any[]) => {
|
|
166
|
+
const result = await (originalWriteFrontmatter as (...inner: any[]) => Promise<unknown>)(...args);
|
|
167
|
+
committed = true;
|
|
168
|
+
abortController.abort(new Error("caller disconnected"));
|
|
169
|
+
return result;
|
|
170
|
+
};
|
|
171
|
+
const wiring = { orchestrator: { getStorage: async () => storage } } as any;
|
|
172
|
+
|
|
173
|
+
await retireMemoryFn(
|
|
174
|
+
wiring,
|
|
175
|
+
"default",
|
|
176
|
+
id,
|
|
177
|
+
{ status: "retracted" },
|
|
178
|
+
abortController.signal,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
assert.equal(committed, true);
|
|
182
|
+
assert.equal((await storage.getMemoryById(id))?.frontmatter.status, "forgotten");
|
|
183
|
+
} finally {
|
|
184
|
+
await cleanup();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// ---------------------------------------------------------------------------
|
|
189
|
+
// Rescope cancellation transaction
|
|
190
|
+
// ---------------------------------------------------------------------------
|
|
191
|
+
|
|
192
|
+
test("#2128 rescope retires the source when cancellation lands after destination write", async () => {
|
|
193
|
+
const source = await makeStorage("remnic-corr-rescope-source-");
|
|
194
|
+
const destination = await makeStorage("remnic-corr-rescope-dest-");
|
|
195
|
+
try {
|
|
196
|
+
const { id: sourceId } = await source.storage.writeMemory("fact", "the database is MySQL", {
|
|
197
|
+
source: "test",
|
|
198
|
+
});
|
|
199
|
+
const abortController = new AbortController();
|
|
200
|
+
const originalWriteSealedMemory = destination.storage.writeSealedMemory.bind(destination.storage);
|
|
201
|
+
let destinationWriteCompleted = false;
|
|
202
|
+
(destination.storage as any).writeSealedMemory = async (...args: any[]) => {
|
|
203
|
+
const result = await (originalWriteSealedMemory as (...args: any[]) => Promise<unknown>)(...args);
|
|
204
|
+
destinationWriteCompleted = true;
|
|
205
|
+
abortController.abort(new Error("caller disconnected"));
|
|
206
|
+
return result;
|
|
207
|
+
};
|
|
208
|
+
const wiring = {
|
|
209
|
+
orchestrator: {
|
|
210
|
+
getStorage: async (namespace: string) =>
|
|
211
|
+
namespace === "source" ? source.storage : destination.storage,
|
|
212
|
+
},
|
|
213
|
+
} as any;
|
|
214
|
+
|
|
215
|
+
const destinationId = await rescopeMemoryFn(
|
|
216
|
+
wiring,
|
|
217
|
+
"source",
|
|
218
|
+
sourceId,
|
|
219
|
+
"destination",
|
|
220
|
+
abortController.signal,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
assert.equal(destinationWriteCompleted, true);
|
|
224
|
+
const archivedSource = await source.storage.getMemoryById(sourceId);
|
|
225
|
+
const activeDestination = await destination.storage.getMemoryById(destinationId);
|
|
226
|
+
assert.equal(archivedSource?.frontmatter.status, "archived");
|
|
227
|
+
assert.equal(activeDestination?.frontmatter.status, "active");
|
|
228
|
+
} finally {
|
|
229
|
+
await source.cleanup();
|
|
230
|
+
await destination.cleanup();
|
|
231
|
+
}
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("#2128 replacement write returns its committed id after cancellation", async () => {
|
|
235
|
+
const { storage, cleanup } = await makeStorage("remnic-corr-replacement-");
|
|
236
|
+
try {
|
|
237
|
+
const originalWriteSealedMemory = storage.writeSealedMemory.bind(storage);
|
|
238
|
+
const abortController = new AbortController();
|
|
239
|
+
let committed = false;
|
|
240
|
+
(storage as any).writeSealedMemory = async (...args: any[]) => {
|
|
241
|
+
const result = await (originalWriteSealedMemory as (...inner: any[]) => Promise<unknown>)(...args);
|
|
242
|
+
committed = true;
|
|
243
|
+
abortController.abort(new Error("caller disconnected"));
|
|
244
|
+
return result;
|
|
245
|
+
};
|
|
246
|
+
const wiring = { orchestrator: { getStorage: async () => storage } } as any;
|
|
247
|
+
|
|
248
|
+
const id = await writeReplacementMemory(
|
|
249
|
+
wiring,
|
|
250
|
+
"default",
|
|
251
|
+
{ content: "the database is PostgreSQL", supersedes: "source-id" },
|
|
252
|
+
abortController.signal,
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
assert.equal(committed, true);
|
|
256
|
+
assert.equal(typeof id, "string");
|
|
257
|
+
assert.equal((await storage.getMemoryById(id))?.frontmatter.status, "active");
|
|
258
|
+
} finally {
|
|
259
|
+
await cleanup();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
test("#2128 tombstone append returns its committed id after cancellation", async () => {
|
|
264
|
+
const { storage, cleanup } = await makeStorage("remnic-corr-tombstone-abort-");
|
|
265
|
+
try {
|
|
266
|
+
const originalAppendTombstone = storage.appendTombstone.bind(storage);
|
|
267
|
+
const abortController = new AbortController();
|
|
268
|
+
let committed = false;
|
|
269
|
+
(storage as any).appendTombstone = async (...args: any[]) => {
|
|
270
|
+
const result = await (originalAppendTombstone as (...inner: any[]) => Promise<string | null>)(...args);
|
|
271
|
+
committed = true;
|
|
272
|
+
abortController.abort(new Error("caller disconnected"));
|
|
273
|
+
return result;
|
|
274
|
+
};
|
|
275
|
+
const wiring = { orchestrator: { getStorage: async () => storage } } as any;
|
|
276
|
+
|
|
277
|
+
const id = await appendTombstoneFn(
|
|
278
|
+
wiring,
|
|
279
|
+
"default",
|
|
280
|
+
{
|
|
281
|
+
reason: "retraction",
|
|
282
|
+
sourceMemoryId: "source-id",
|
|
283
|
+
rawContent: "the database is PostgreSQL",
|
|
284
|
+
},
|
|
285
|
+
abortController.signal,
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
assert.equal(committed, true);
|
|
289
|
+
assert.equal(typeof id, "string");
|
|
290
|
+
} finally {
|
|
291
|
+
await cleanup();
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
|
|
124
295
|
// ---------------------------------------------------------------------------
|
|
125
296
|
// item 4: per-key tombstone emission
|
|
126
297
|
// ---------------------------------------------------------------------------
|
|
@@ -181,6 +181,41 @@ test("auto mode: applies when all guards pass", async () => {
|
|
|
181
181
|
assert.deepStrictEqual(appliedPlans, ["corr-test-001"]);
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
+
test("passive capture forwards its cancellation signal to plan and apply", async () => {
|
|
185
|
+
const abortController = new AbortController();
|
|
186
|
+
const plan = makePlan({ confidence: 0.9, classification: "outdated" });
|
|
187
|
+
let plannedSignal: AbortSignal | undefined;
|
|
188
|
+
let appliedSignal: AbortSignal | undefined;
|
|
189
|
+
const deps: PassiveCaptureDeps = {
|
|
190
|
+
planCorrection: async (_request, opts) => {
|
|
191
|
+
plannedSignal = opts?.abortSignal;
|
|
192
|
+
return plan;
|
|
193
|
+
},
|
|
194
|
+
applyCorrection: async (_planId, opts) => {
|
|
195
|
+
appliedSignal = opts.abortSignal;
|
|
196
|
+
return {
|
|
197
|
+
planId: plan.planId,
|
|
198
|
+
status: "applied",
|
|
199
|
+
results: [{ action: plan.actions[0]!, status: "applied" }],
|
|
200
|
+
auditMemoryId: "audit-001",
|
|
201
|
+
appliedAt: new Date().toISOString(),
|
|
202
|
+
};
|
|
203
|
+
},
|
|
204
|
+
storageDir: async () => "/tmp/test-passive-capture",
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
await capturePassiveCorrections(
|
|
208
|
+
[makeCorrection()],
|
|
209
|
+
{ ...LIVE_CTX, abortSignal: abortController.signal },
|
|
210
|
+
AUTO_CONFIG,
|
|
211
|
+
deps,
|
|
212
|
+
new Set<string>(),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
assert.equal(plannedSignal, abortController.signal);
|
|
216
|
+
assert.equal(appliedSignal, abortController.signal);
|
|
217
|
+
});
|
|
218
|
+
|
|
184
219
|
test("auto mode: suppressed — confidence below floor → queued", async () => {
|
|
185
220
|
const appliedPlans: string[] = [];
|
|
186
221
|
const plan = makePlan({ confidence: 0.5 });
|
|
@@ -64,6 +64,8 @@ export interface PassiveCaptureContext {
|
|
|
64
64
|
principal?: string;
|
|
65
65
|
/** Authorized namespace the extraction wrote to. */
|
|
66
66
|
namespace: string;
|
|
67
|
+
/** Shared extraction deadline/cancellation signal. */
|
|
68
|
+
abortSignal?: AbortSignal;
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
// ---------------------------------------------------------------------------
|
|
@@ -72,11 +74,20 @@ export interface PassiveCaptureContext {
|
|
|
72
74
|
|
|
73
75
|
export interface PassiveCaptureDeps {
|
|
74
76
|
/** Plan a correction through the Correction Contract. */
|
|
75
|
-
planCorrection(
|
|
77
|
+
planCorrection(
|
|
78
|
+
request: CorrectionRequest,
|
|
79
|
+
opts?: { abortSignal?: AbortSignal },
|
|
80
|
+
): Promise<CorrectionPlan>;
|
|
76
81
|
/** Apply a planned correction (auto mode only). */
|
|
77
82
|
applyCorrection(
|
|
78
83
|
planId: string,
|
|
79
|
-
opts: {
|
|
84
|
+
opts: {
|
|
85
|
+
confirm: true;
|
|
86
|
+
namespace?: string;
|
|
87
|
+
sessionKey?: string;
|
|
88
|
+
principal?: string;
|
|
89
|
+
abortSignal?: AbortSignal;
|
|
90
|
+
},
|
|
80
91
|
): Promise<CorrectionOutcome>;
|
|
81
92
|
/** Resolve the storage dir for notification enqueue (per namespace). */
|
|
82
93
|
storageDir(namespace: string): Promise<string>;
|
|
@@ -207,6 +218,7 @@ export async function capturePassiveCorrections(
|
|
|
207
218
|
telemetry.detected = corrections.length;
|
|
208
219
|
|
|
209
220
|
for (const correction of corrections) {
|
|
221
|
+
if (ctx.abortSignal?.aborted) return { telemetry, plans };
|
|
210
222
|
// 1. Dedup — checked before planning, but the fingerprint is only
|
|
211
223
|
// recorded AFTER a successful plan so a transient planning failure
|
|
212
224
|
// can be retried on a later flush (review: "dedup blocks retry
|
|
@@ -243,13 +255,14 @@ export async function capturePassiveCorrections(
|
|
|
243
255
|
|
|
244
256
|
let plan: CorrectionPlan;
|
|
245
257
|
try {
|
|
246
|
-
plan = await deps.planCorrection(request);
|
|
258
|
+
plan = await deps.planCorrection(request, { abortSignal: ctx.abortSignal });
|
|
247
259
|
} catch (err) {
|
|
248
260
|
log.warn(
|
|
249
261
|
`passive-correction: planning failed for "${correction.targetHint.slice(0, 60)}": ${err instanceof Error ? err.message : String(err)}`,
|
|
250
262
|
);
|
|
251
263
|
continue;
|
|
252
264
|
}
|
|
265
|
+
if (ctx.abortSignal?.aborted) return { telemetry, plans };
|
|
253
266
|
plans.push(plan);
|
|
254
267
|
// Record the fingerprint only after a successful plan.
|
|
255
268
|
dedupState.add(fp);
|
|
@@ -276,6 +289,7 @@ export async function capturePassiveCorrections(
|
|
|
276
289
|
namespace: ctx.namespace,
|
|
277
290
|
...(ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {}),
|
|
278
291
|
...(ctx.principal ? { principal: ctx.principal } : {}),
|
|
292
|
+
abortSignal: ctx.abortSignal,
|
|
279
293
|
});
|
|
280
294
|
// A partial outcome means some actions failed (per-action races or
|
|
281
295
|
// storage failures). Don't count it as auto-applied or notify — queue
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ExtractionResult } from "./types.js";
|
|
1
|
+
import type { ExtractionResult, ProvenanceConfig } from "./types.js";
|
|
2
|
+
import { buildFactProvenance, type ProvenanceTurnInput } from "./provenance.js";
|
|
2
3
|
import { delinearize } from "./delinearize.js";
|
|
3
4
|
import {
|
|
4
5
|
applyExtractionSourceGrounding as applyGroundingRules,
|
|
@@ -39,6 +40,59 @@ export function applyExtractionSourceGrounding(
|
|
|
39
40
|
);
|
|
40
41
|
}
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Attach claim-level provenance spans to each fact after extraction has
|
|
45
|
+
* completed. The validator never throws or drops a fact: an unverifiable
|
|
46
|
+
* quote remains a tagged state. When provenance is disabled, transient
|
|
47
|
+
* model-provided quotes are stripped before the result leaves extraction.
|
|
48
|
+
*/
|
|
49
|
+
export function attachExtractionProvenance(
|
|
50
|
+
result: ExtractionResult,
|
|
51
|
+
turns: ReadonlyArray<{
|
|
52
|
+
content: string;
|
|
53
|
+
sessionKey?: string;
|
|
54
|
+
logicalSessionKey?: string;
|
|
55
|
+
timestamp: string;
|
|
56
|
+
turnFingerprint?: string;
|
|
57
|
+
}>,
|
|
58
|
+
provenanceConfig: ProvenanceConfig,
|
|
59
|
+
): ExtractionResult {
|
|
60
|
+
if (!provenanceConfig.enabled) {
|
|
61
|
+
if (result.facts.length === 0) return result;
|
|
62
|
+
return {
|
|
63
|
+
...result,
|
|
64
|
+
facts: result.facts.map((fact) => {
|
|
65
|
+
if (fact.quote === undefined) return fact;
|
|
66
|
+
const { quote: _stripped, ...rest } = fact;
|
|
67
|
+
return rest;
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (result.facts.length === 0) return result;
|
|
72
|
+
const provenanceTurns: ProvenanceTurnInput[] = turns.map((turn) => ({
|
|
73
|
+
content: turn.content,
|
|
74
|
+
sessionKey: turn.sessionKey,
|
|
75
|
+
logicalSessionKey: turn.logicalSessionKey,
|
|
76
|
+
timestamp: turn.timestamp,
|
|
77
|
+
turnId: turn.turnFingerprint,
|
|
78
|
+
}));
|
|
79
|
+
const facts = result.facts.map((fact) => {
|
|
80
|
+
const built = buildFactProvenance(
|
|
81
|
+
fact.quote,
|
|
82
|
+
provenanceTurns,
|
|
83
|
+
provenanceConfig,
|
|
84
|
+
);
|
|
85
|
+
const { quote: _stripped, ...factWithoutQuote } = fact;
|
|
86
|
+
return {
|
|
87
|
+
...factWithoutQuote,
|
|
88
|
+
...(built.sources && built.sources.length > 0 ? { sources: built.sources } : {}),
|
|
89
|
+
...(built.provenance !== "none" ? { provenance: built.provenance } : {}),
|
|
90
|
+
...(built.requireSpansPending ? { requireSpansPending: true } : {}),
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
return { ...result, facts };
|
|
94
|
+
}
|
|
95
|
+
|
|
42
96
|
export function filterExtractionResultBySource(
|
|
43
97
|
result: ExtractionResult,
|
|
44
98
|
source: string,
|
|
@@ -268,3 +268,54 @@ test("extraction keeps action transcripts with durable memory cues", async () =>
|
|
|
268
268
|
|
|
269
269
|
assert.equal(fallbackCalls, 1);
|
|
270
270
|
});
|
|
271
|
+
|
|
272
|
+
test("gateway extraction forwards caller cancellation to the provider", async () => {
|
|
273
|
+
const config = parseConfig({
|
|
274
|
+
modelSource: "gateway",
|
|
275
|
+
gatewayConfig: {
|
|
276
|
+
agents: {
|
|
277
|
+
defaults: { model: { primary: "bench-internal/gpt-5.5" } },
|
|
278
|
+
list: [],
|
|
279
|
+
},
|
|
280
|
+
models: {
|
|
281
|
+
providers: {
|
|
282
|
+
"bench-internal": {
|
|
283
|
+
api: "codex-cli",
|
|
284
|
+
baseUrl: "codex-cli://local",
|
|
285
|
+
models: [{ id: "gpt-5.5", name: "gpt-5.5" }],
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
});
|
|
291
|
+
const engine = new ExtractionEngine(config);
|
|
292
|
+
const controller = new AbortController();
|
|
293
|
+
let capturedSignal: AbortSignal | undefined;
|
|
294
|
+
(engine as unknown as {
|
|
295
|
+
fallbackLlm: {
|
|
296
|
+
parseWithSchemaDetailed(
|
|
297
|
+
messages: unknown,
|
|
298
|
+
schema: unknown,
|
|
299
|
+
options: { signal?: AbortSignal },
|
|
300
|
+
): Promise<unknown>;
|
|
301
|
+
};
|
|
302
|
+
}).fallbackLlm = {
|
|
303
|
+
async parseWithSchemaDetailed(_messages, _schema, options) {
|
|
304
|
+
capturedSignal = options.signal;
|
|
305
|
+
await new Promise<never>((_resolve, reject) => {
|
|
306
|
+
options.signal?.addEventListener("abort", () => reject(options.signal?.reason), { once: true });
|
|
307
|
+
});
|
|
308
|
+
return null;
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
const extraction = engine.extract(
|
|
313
|
+
[{ role: "user", content: "Remember this cancellation test.", timestamp: "2026-05-08T00:00:00.000Z" }],
|
|
314
|
+
undefined,
|
|
315
|
+
controller.signal,
|
|
316
|
+
);
|
|
317
|
+
await new Promise<void>((resolve) => queueMicrotask(resolve));
|
|
318
|
+
assert.equal(capturedSignal, controller.signal);
|
|
319
|
+
controller.abort(new Error("deadline"));
|
|
320
|
+
await assert.rejects(extraction, /deadline/);
|
|
321
|
+
});
|