@remnic/core 10.0.84 → 10.0.86
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.js +90 -88
- package/dist/access-authorization-probe.js +91 -89
- package/dist/access-boundary.d.ts.map +1 -1
- package/dist/access-boundary.js +90 -88
- package/dist/access-cli.js +198 -194
- package/dist/access-cli.js.map +1 -1
- package/dist/access-errors.d.ts +14 -0
- package/dist/access-errors.d.ts.map +1 -1
- package/dist/access-errors.js +5 -1
- package/dist/access-extraction-force-flush.js +90 -88
- package/dist/access-http-briefing.js +91 -89
- package/dist/access-http-query.js +92 -90
- package/dist/access-http.d.ts +12 -0
- package/dist/access-http.d.ts.map +1 -1
- package/dist/access-http.js +119 -116
- package/dist/access-identity-continuity-surface.js +90 -88
- package/dist/access-lcm-surface.js +90 -88
- package/dist/access-mcp-frames.d.ts +29 -0
- package/dist/access-mcp-frames.d.ts.map +1 -0
- package/dist/access-mcp-frames.js +10 -0
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.d.ts.map +1 -1
- package/dist/access-mcp.js +105 -102
- package/dist/access-memory-search-fanout.js +2 -2
- package/dist/access-namespace-preflight.js +90 -88
- package/dist/access-observe-write-category.js +15 -14
- package/dist/access-observe-write-surface.d.ts.map +1 -1
- package/dist/access-observe-write-surface.js +90 -88
- package/dist/access-offline-manifest.js +10 -10
- package/dist/access-operations-batch.js +94 -92
- package/dist/access-operations.js +101 -99
- package/dist/access-recall-concurrency.js +90 -88
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +90 -88
- package/dist/access-recall-surface.js +90 -88
- package/dist/access-schema.d.ts.map +1 -1
- package/dist/access-schema.js +10 -9
- package/dist/access-service.d.ts +3 -3
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +90 -88
- package/dist/access-surface-catalog.js +92 -90
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-token-capabilities.js +2 -2
- package/dist/active-recall.js +38 -38
- package/dist/adapters/index.js +7 -7
- package/dist/adapters/registry.js +3 -3
- package/dist/{auto-sync-C7E6G7Y2.js → auto-sync-3AZW7MXI.js} +6 -6
- package/dist/briefing-deadline.d.ts +2 -2
- package/dist/briefing-deadline.d.ts.map +1 -1
- package/dist/briefing-deadline.js +1 -1
- package/dist/briefing.js +25 -25
- package/dist/buffer-admission.d.ts +22 -0
- package/dist/buffer-admission.d.ts.map +1 -0
- package/dist/buffer-admission.js +13 -0
- package/dist/buffer-eviction.d.ts +4 -5
- package/dist/buffer-eviction.d.ts.map +1 -1
- package/dist/buffer-eviction.js +1 -1
- package/dist/buffer-persistence.d.ts +8 -4
- package/dist/buffer-persistence.d.ts.map +1 -1
- package/dist/buffer-persistence.js +1 -1
- package/dist/buffer-turn-helpers.d.ts +12 -0
- package/dist/buffer-turn-helpers.d.ts.map +1 -1
- package/dist/buffer-turn-helpers.js +9 -1
- package/dist/buffer-types.d.ts +24 -1
- package/dist/buffer-types.d.ts.map +1 -1
- package/dist/buffer.d.ts +21 -19
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.js +17 -13
- package/dist/calibration.js +3 -3
- package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/capsule-gunzip-KGBDGF7P.js +11 -0
- package/dist/capsule-gunzip-KGBDGF7P.js.map +1 -0
- package/dist/capsule-import-gate.d.ts +11 -0
- package/dist/capsule-import-gate.d.ts.map +1 -0
- package/dist/capsule-import-gate.js +12 -0
- package/dist/capsule-import-gate.js.map +1 -0
- package/dist/{capsule-merge-XVTQJJ6R.js → capsule-merge-2IIXFXN5.js} +5 -11
- package/dist/capsule-merge-2IIXFXN5.js.map +1 -0
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +27 -27
- package/dist/causal-retrieval.js +2 -2
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-MSIRVXQ3.js → chunk-2G4TV2ML.js} +12 -12
- package/dist/{chunk-B74NPUHT.js → chunk-2JG2NI7C.js} +54 -54
- package/dist/chunk-2JG2NI7C.js.map +1 -0
- package/dist/{chunk-IR4C3DP2.js → chunk-2K3AUDH7.js} +2 -2
- package/dist/{chunk-2IW5PT7U.js → chunk-2N4OUSIA.js} +2 -2
- package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-QZSIDSB2.js → chunk-2NUDHVYM.js} +2 -2
- package/dist/{chunk-HPFVZPRH.js → chunk-2U4LMSEX.js} +3 -3
- package/dist/{chunk-WHQXWFH7.js → chunk-2XOFVTTT.js} +2 -2
- package/dist/{chunk-I6ORDT54.js → chunk-32CA7B6L.js} +2 -2
- package/dist/{chunk-T77AX6DG.js → chunk-32YX7EJ3.js} +4 -4
- package/dist/{chunk-HLKUZW42.js → chunk-3CTKEXXF.js} +144 -156
- package/dist/chunk-3CTKEXXF.js.map +1 -0
- package/dist/{chunk-HLWXCDUQ.js → chunk-3DAWHP5K.js} +5 -5
- package/dist/{chunk-ZJJFUEPO.js → chunk-3PJEDHLD.js} +2 -2
- package/dist/{chunk-PJYK7HH2.js → chunk-3UZ2VMKD.js} +2 -2
- package/dist/{chunk-IN4OFAHX.js → chunk-3Y5X6YFH.js} +2 -2
- package/dist/{chunk-YUTT4ZTI.js → chunk-45VUHDV2.js} +2 -2
- package/dist/{chunk-T6T2RMWW.js → chunk-4GMI5HFH.js} +12 -12
- package/dist/{chunk-YOEYL6CH.js → chunk-4LCVA2LW.js} +3 -3
- package/dist/{chunk-66JOLMWS.js → chunk-4X7HQKAG.js} +2 -2
- package/dist/{chunk-65SKM4BF.js → chunk-4XYAWK5H.js} +2 -2
- package/dist/{chunk-H7BZBSP6.js → chunk-52II7PB6.js} +4 -4
- package/dist/{chunk-TPX7XXY4.js → chunk-5SOSQTVE.js} +2 -2
- package/dist/{chunk-G3T6YMBO.js → chunk-64S6X4IU.js} +7 -7
- package/dist/{chunk-BK7AJUWB.js → chunk-6BCWFCDG.js} +7 -7
- package/dist/{chunk-V27FK6D6.js → chunk-6XTUZKCZ.js} +2 -2
- package/dist/{chunk-KASJJGRG.js → chunk-6ZELOK6O.js} +3 -8
- package/dist/chunk-6ZELOK6O.js.map +1 -0
- package/dist/{chunk-LECSS7EE.js → chunk-73UZZFJC.js} +3 -3
- package/dist/{chunk-4EACCIPO.js → chunk-77PDJ4OE.js} +3 -3
- package/dist/{chunk-GQZSGXR6.js → chunk-7GSL4LBG.js} +2 -2
- package/dist/{chunk-B6SPPYGJ.js → chunk-7IWRLYFJ.js} +2 -2
- package/dist/{chunk-R45L4TV6.js → chunk-7LCGFUMB.js} +6 -6
- package/dist/{chunk-A7BM2JTH.js → chunk-AJHNXIQU.js} +2 -2
- package/dist/{chunk-2D7BTSDW.js → chunk-ANZZLRUX.js} +2 -2
- package/dist/{chunk-ZXF3O7P4.js → chunk-ARRTLPRC.js} +2 -2
- package/dist/{chunk-S5CQI2KF.js → chunk-B3GKQ6DU.js} +2 -2
- package/dist/{chunk-XRBHIR7Q.js → chunk-B56LORLY.js} +2 -2
- package/dist/{chunk-KO3YBHOV.js → chunk-BIVKPQ6Q.js} +3 -3
- package/dist/{chunk-QZBTIYKD.js → chunk-BLSHFIR6.js} +7 -6
- package/dist/chunk-BLSHFIR6.js.map +1 -0
- package/dist/{chunk-54FDG7K7.js → chunk-C2HORX76.js} +3 -3
- package/dist/{chunk-WAD32CZG.js → chunk-CC4V7HNP.js} +43 -30
- package/dist/chunk-CC4V7HNP.js.map +1 -0
- package/dist/{chunk-LGEH473S.js → chunk-CJCTKL6Y.js} +9 -1
- package/dist/chunk-CJCTKL6Y.js.map +1 -0
- package/dist/{chunk-E33UJHY3.js → chunk-CN7Q3T2J.js} +4 -4
- package/dist/{chunk-YUTG35M4.js → chunk-CYCEROPR.js} +3 -3
- package/dist/{chunk-TFLPDNQV.js → chunk-D5EV6Y2L.js} +3 -3
- package/dist/{chunk-BFBS7OFQ.js → chunk-DC55RIEZ.js} +4 -4
- package/dist/{chunk-B4ZU34JQ.js → chunk-DT7SNJH6.js} +3 -3
- package/dist/{chunk-VLMBSGQF.js → chunk-DZ7DPDVW.js} +10 -8
- package/dist/chunk-DZ7DPDVW.js.map +1 -0
- package/dist/{chunk-FVRTCYZ3.js → chunk-EA2LA5RI.js} +2 -2
- package/dist/{chunk-WBN66HPI.js → chunk-ELHJK7LM.js} +6 -6
- package/dist/{chunk-77R7BQZ2.js → chunk-EQ4U73UH.js} +77 -24
- package/dist/chunk-EQ4U73UH.js.map +1 -0
- package/dist/{chunk-3JPTUCD7.js → chunk-EUBDYOLD.js} +32 -23
- package/dist/chunk-EUBDYOLD.js.map +1 -0
- package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
- package/dist/{chunk-YAUHSNPB.js → chunk-F74G4KIH.js} +2 -2
- package/dist/{chunk-MPGLM2VU.js → chunk-FF3EFLUT.js} +7 -5
- package/dist/chunk-FF3EFLUT.js.map +1 -0
- package/dist/{chunk-BV2BRHD4.js → chunk-FHGWKODN.js} +2 -2
- package/dist/chunk-FKBGK3NC.js +62 -0
- package/dist/chunk-FKBGK3NC.js.map +1 -0
- package/dist/{chunk-X2KO4FK5.js → chunk-FNFURZBZ.js} +5 -5
- package/dist/chunk-FNFURZBZ.js.map +1 -0
- package/dist/{chunk-KESJ5XX3.js → chunk-G54BOKZ6.js} +2 -2
- package/dist/{chunk-YK7GOPIE.js → chunk-G67EUQAB.js} +9 -7
- package/dist/chunk-G67EUQAB.js.map +1 -0
- package/dist/{chunk-K36RMINQ.js → chunk-GOZXQNIM.js} +3 -3
- package/dist/{chunk-OQSSQOKQ.js → chunk-GULUWOA5.js} +2 -2
- package/dist/{chunk-K6RTQZA4.js → chunk-HFUKXOUW.js} +2 -2
- package/dist/{chunk-WV254W4V.js → chunk-HLN2HOXX.js} +2 -2
- package/dist/{chunk-FUOAIJKQ.js → chunk-IBDWYRDR.js} +3 -3
- package/dist/{chunk-Z3DDQXM4.js → chunk-IBGU6AN6.js} +45 -45
- package/dist/chunk-IBGU6AN6.js.map +1 -0
- package/dist/{chunk-AJG2TAMR.js → chunk-IEEV27BC.js} +2 -2
- package/dist/chunk-IGLJNHOX.js +62 -0
- package/dist/chunk-IGLJNHOX.js.map +1 -0
- package/dist/{chunk-LTDLJCMQ.js → chunk-IJ3OEECW.js} +4 -4
- package/dist/{chunk-BK4FBHZ3.js → chunk-IPD5GC7C.js} +3 -3
- package/dist/{chunk-KFLD7ZZG.js → chunk-IUKYFTGW.js} +3 -3
- package/dist/{chunk-GCAQ3VUJ.js → chunk-JM2YZKCQ.js} +2 -2
- package/dist/{chunk-BNQJKWWZ.js → chunk-K3FH3LAQ.js} +4 -4
- package/dist/{chunk-LU66I56Q.js → chunk-KVSOEVAF.js} +61 -12
- package/dist/chunk-KVSOEVAF.js.map +1 -0
- package/dist/chunk-M3BEJJNV.js +31 -0
- package/dist/chunk-M3BEJJNV.js.map +1 -0
- package/dist/{chunk-RZH5RVJC.js → chunk-MTTYIXSU.js} +2 -2
- package/dist/{chunk-XHGYZRVW.js → chunk-NIVKG3DS.js} +5 -5
- package/dist/{chunk-VZELUMKK.js → chunk-NQP4ZYGG.js} +2 -2
- package/dist/{chunk-7PMOCQOL.js → chunk-NT7F7WJQ.js} +192 -63
- package/dist/chunk-NT7F7WJQ.js.map +1 -0
- package/dist/{chunk-YO2JEX2Z.js → chunk-OGBQMY46.js} +2 -2
- package/dist/{chunk-TLHF75OR.js → chunk-OL553AWT.js} +12 -12
- package/dist/{chunk-CLVILSBR.js → chunk-OZNBZJ3S.js} +22 -22
- package/dist/{chunk-VUROWXFL.js → chunk-P452SEKO.js} +2 -2
- package/dist/{chunk-JX3E4XCW.js → chunk-PDOOUXCS.js} +2 -2
- package/dist/{chunk-6QYPL6NI.js → chunk-PKZ274PI.js} +3 -3
- package/dist/{chunk-KJCL2FZO.js → chunk-QD5R6U5J.js} +2 -2
- package/dist/{chunk-JRVMCZE3.js → chunk-QEYTRFR3.js} +2 -2
- package/dist/{chunk-VKDAJJQP.js → chunk-QEZ3DW5O.js} +11 -11
- package/dist/{chunk-WYPCJK6K.js → chunk-QKERFEJS.js} +2 -2
- package/dist/{chunk-BDN3TDGV.js → chunk-QKES7GU6.js} +2 -2
- package/dist/{chunk-PCQWKMOL.js → chunk-QNSZYTSG.js} +2 -2
- package/dist/chunk-QV2VZKD5.js +31 -0
- package/dist/chunk-QV2VZKD5.js.map +1 -0
- package/dist/{chunk-IZJQNDGI.js → chunk-R6HMAIKM.js} +2 -2
- package/dist/{chunk-CIIHIAJ2.js → chunk-ROGO7FRA.js} +6 -5
- package/dist/{chunk-CIIHIAJ2.js.map → chunk-ROGO7FRA.js.map} +1 -1
- package/dist/{chunk-NUSAAN75.js → chunk-ROKDHO74.js} +2 -2
- package/dist/{chunk-D5SSBCYY.js → chunk-RWGRSKN5.js} +7 -5
- package/dist/chunk-RWGRSKN5.js.map +1 -0
- package/dist/{chunk-FF6N7BXC.js → chunk-S45INSV3.js} +4 -4
- package/dist/{chunk-2RUTN7PR.js → chunk-S7GJNA3K.js} +2 -2
- package/dist/{chunk-XT45WCKX.js → chunk-SYKJBS7S.js} +10 -10
- package/dist/{chunk-5BE3FLKL.js → chunk-TAUHAP5J.js} +4 -4
- package/dist/{chunk-RJWL3RHB.js → chunk-TFEHSPGQ.js} +2 -2
- package/dist/{chunk-XYP5WBDO.js → chunk-TQ4SCPGQ.js} +76 -60
- package/dist/chunk-TQ4SCPGQ.js.map +1 -0
- package/dist/{chunk-K3B72DKJ.js → chunk-TRMZHGIX.js} +8 -8
- package/dist/{chunk-WBDIZWJQ.js → chunk-TSS3D7ZY.js} +2 -2
- package/dist/{chunk-6LCWKS62.js → chunk-UAUV3BWS.js} +104 -121
- package/dist/chunk-UAUV3BWS.js.map +1 -0
- package/dist/{chunk-KQUSP6LB.js → chunk-UDKWFDV2.js} +1 -1
- package/dist/chunk-UDKWFDV2.js.map +1 -0
- package/dist/{chunk-HQPFACXO.js → chunk-UH3FPX3L.js} +2 -2
- package/dist/{chunk-GGJFRVRD.js → chunk-US7KPQA5.js} +2 -2
- package/dist/{chunk-FJ2VJTGA.js → chunk-UWRHHRDK.js} +3 -3
- package/dist/{chunk-4KLQI3L2.js → chunk-UXXK523X.js} +40 -2
- package/dist/chunk-UXXK523X.js.map +1 -0
- package/dist/{chunk-SDESKFKT.js → chunk-UYHDMCY2.js} +2 -2
- package/dist/{chunk-3T3VHXUH.js → chunk-VKILERSL.js} +2 -2
- package/dist/{chunk-2TGIKMMZ.js → chunk-WXDTOE6F.js} +2 -2
- package/dist/{chunk-KQLBXUUQ.js → chunk-WYG5UNDY.js} +2 -2
- package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-MPDLLLOG.js → chunk-XO23OKMK.js} +9 -5
- package/dist/chunk-XO23OKMK.js.map +1 -0
- package/dist/{chunk-WC475JOG.js → chunk-XU37EJTW.js} +24 -24
- package/dist/chunk-XU37EJTW.js.map +1 -0
- package/dist/{chunk-FZVROZKC.js → chunk-XVZA6VXC.js} +4 -4
- package/dist/{chunk-QA3Y2O6H.js → chunk-YAVIBVCU.js} +2 -2
- package/dist/{chunk-2XJZLSXE.js → chunk-YL4UKMD7.js} +124 -58
- package/dist/chunk-YL4UKMD7.js.map +1 -0
- package/dist/{chunk-VPEIWMUT.js → chunk-YLTU2DC4.js} +2 -2
- package/dist/{chunk-HWHNQVRV.js → chunk-YMJRLT7S.js} +28 -8
- package/dist/chunk-YMJRLT7S.js.map +1 -0
- package/dist/{chunk-EBOHFZI4.js → chunk-YRZPBN46.js} +3 -3
- package/dist/{chunk-FMFCQRDM.js → chunk-ZANNIXXE.js} +3 -3
- package/dist/{chunk-HQGATKG2.js → chunk-ZBFLV657.js} +3 -3
- package/dist/{chunk-6L63IN3M.js → chunk-ZOJUWVAU.js} +1 -1
- package/dist/cli.js +144 -141
- package/dist/coding/export-okf-codegraph.js +24 -24
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +26 -26
- package/dist/config.js +35 -35
- package/dist/connectors/codex-materialize-runner.js +24 -24
- package/dist/connectors/index.js +28 -28
- package/dist/contradiction/index.js +4 -4
- package/dist/convergence-refresh.js +26 -26
- package/dist/corpus-watermark.js +28 -28
- package/dist/dashboard-runtime.js +2 -2
- package/dist/deep-recall-config.js +2 -2
- package/dist/deep-recall-http-glue.js +12 -12
- package/dist/entity-retrieval.js +25 -25
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.js +6 -6
- package/dist/external-wiki-access.js +91 -89
- package/dist/extraction-evidence-class.js +2 -2
- package/dist/extraction-quote-grounding.d.ts +5 -1
- package/dist/extraction-quote-grounding.d.ts.map +1 -1
- package/dist/extraction-quote-grounding.js +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +3 -1
- package/dist/extraction-source-grounding-rules.d.ts.map +1 -1
- package/dist/extraction-source-grounding-rules.js +2 -2
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts.map +1 -1
- package/dist/extraction-source-grounding.js +5 -5
- package/dist/extraction-span-materialize.js +2 -2
- package/dist/extraction.d.ts.map +1 -1
- package/dist/extraction.js +43 -43
- package/dist/{first-start-migration-QVD22WWS.js → first-start-migration-A6PHIBUQ.js} +4 -4
- package/dist/{graph-edge-decay-CXTNJ7IQ.js → graph-edge-decay-EKWXRBWF.js} +5 -5
- package/dist/graph-edge-decay-EKWXRBWF.js.map +1 -0
- package/dist/graph-jsonl.js +3 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/harmonic-retrieval.js +24 -24
- package/dist/index.js +255 -251
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +5 -5
- package/dist/local-llm.js +3 -3
- package/dist/location/index.js +28 -28
- package/dist/maintenance/memory-governance.js +24 -24
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +24 -24
- package/dist/maintenance/rebuild-memory-projection-runner.js +26 -26
- package/dist/maintenance/rebuild-memory-projection.js +25 -25
- package/dist/memory-browse-http-glue.js +2 -2
- package/dist/memory-browse-operations.js +91 -89
- package/dist/memory-browse.js +5 -5
- package/dist/memory-subject.js +2 -2
- package/dist/namespaces/migrate.js +25 -25
- package/dist/namespaces/search.d.ts +9 -0
- package/dist/namespaces/search.d.ts.map +1 -1
- package/dist/namespaces/search.js +13 -7
- package/dist/namespaces/storage.js +24 -24
- package/dist/offline-sync-changeset-generations.js +3 -3
- package/dist/offline-sync-embedding-generation.js +2 -2
- package/dist/offline-sync-impression-drain.js +2 -2
- package/dist/offline-sync-snapshot-stream.js +6 -6
- package/dist/offline-sync.js +5 -5
- package/dist/operator-doctor-corpus.js +31 -31
- package/dist/operator-doctor-replica.js +4 -4
- package/dist/operator-toolkit.js +49 -49
- package/dist/orchestration/backlog-scheduler.d.ts +3 -2
- package/dist/orchestration/backlog-scheduler.d.ts.map +1 -1
- package/dist/orchestration/backlog-scheduler.js +209 -205
- package/dist/orchestration/backlog-scheduler.js.map +1 -1
- package/dist/orchestration/buffer-drain-runner.d.ts +6 -1
- package/dist/orchestration/buffer-drain-runner.d.ts.map +1 -1
- package/dist/orchestration/buffer-drain-runner.js +199 -195
- package/dist/orchestration/extraction-persist.d.ts.map +1 -1
- package/dist/orchestration/fact-dedup-window.d.ts +1 -4
- package/dist/orchestration/fact-dedup-window.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +41 -41
- package/dist/orchestration/turn-ingestion.d.ts +2 -9
- package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
- package/dist/orchestrator.js +198 -194
- package/dist/provenance.js +2 -2
- package/dist/qmd.js +4 -4
- package/dist/recall-navigation-http-glue.js +2 -2
- package/dist/recall-navigation-operations.js +91 -89
- package/dist/recall-navigation.js +90 -88
- package/dist/recall-state-view-admission.js +5 -5
- package/dist/recall-why-service.js +5 -5
- package/dist/reconcile/manifest.js +2 -2
- package/dist/replica-divergence.js +3 -3
- package/dist/{resolution-BNWE5Y25.js → resolution-23ZBDM6A.js} +5 -5
- package/dist/resolution-23ZBDM6A.js.map +1 -0
- package/dist/resume-bundles.js +36 -36
- package/dist/salvage-envelope.js +4 -4
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +12 -12
- package/dist/semantic-consolidation.js +25 -25
- package/dist/semantic-rule-promotion.js +24 -24
- package/dist/semantic-rule-verifier.js +24 -24
- package/dist/source-agent-qualifier.d.ts +2 -0
- package/dist/source-agent-qualifier.d.ts.map +1 -1
- package/dist/source-agent-qualifier.js +36 -36
- package/dist/standup/build.js +25 -25
- package/dist/storage/buffer-drain-claims.d.ts +18 -6
- package/dist/storage/buffer-drain-claims.d.ts.map +1 -1
- package/dist/storage/buffer-drain-claims.js +2 -2
- package/dist/storage/buffer-session-files.js +2 -2
- package/dist/storage/content-hash-index.d.ts +8 -0
- package/dist/storage/content-hash-index.d.ts.map +1 -1
- package/dist/storage.d.ts +10 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +23 -23
- package/dist/subject-config.js +3 -3
- package/dist/summarizer.js +4 -4
- package/dist/support-passport/index.js +93 -91
- package/dist/tokens.js +3 -3
- package/dist/transfer/autodetect.js +1 -1
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +3 -3
- package/dist/transfer/capsule-gunzip.d.ts +14 -0
- package/dist/transfer/capsule-gunzip.d.ts.map +1 -0
- package/dist/transfer/capsule-import.d.ts.map +1 -1
- package/dist/transfer/capsule-import.js +3 -2
- package/dist/transfer/capsule-merge.d.ts.map +1 -1
- package/dist/transfer/export-okf.js +24 -24
- package/dist/verified-recall.js +24 -24
- package/dist/who-knows-cli.js +26 -26
- package/dist/who-knows.js +25 -25
- package/dist/write-envelope.js +3 -3
- package/package.json +2 -2
- package/src/access-boundary.ts +15 -0
- package/src/access-errors.ts +22 -0
- package/src/access-fleet-wide-work-peer.test.ts +236 -0
- package/src/access-http-peer-fleet-wide.test.ts +192 -0
- package/src/access-http.test.ts +249 -4
- package/src/access-http.ts +114 -39
- package/src/access-mcp-frames.test.ts +47 -0
- package/src/access-mcp-frames.ts +74 -0
- package/src/access-mcp.test.ts +210 -0
- package/src/access-mcp.ts +47 -37
- package/src/access-observe-replay-durability.test.ts +40 -4
- package/src/access-observe-write-surface.ts +4 -4
- package/src/access-operations-batch.ts +23 -12
- package/src/access-proto-injection.test.ts +340 -0
- package/src/access-schema.ts +31 -5
- package/src/access-service-capsule-import.test.ts +235 -0
- package/src/access-service.ts +6 -45
- package/src/backlog-scheduler.test.ts +443 -3
- package/src/briefing-deadline.ts +5 -4
- package/src/buffer-admission.ts +45 -0
- package/src/buffer-eviction-backpressure.test.ts +211 -0
- package/src/buffer-eviction.ts +8 -14
- package/src/buffer-incremental-persistence.test.ts +25 -37
- package/src/buffer-persistence.ts +15 -6
- package/src/buffer-session.test.ts +32 -16
- package/src/buffer-turn-helpers.ts +47 -0
- package/src/buffer-types.ts +28 -1
- package/src/buffer.ts +83 -91
- package/src/capsule-import-gate.ts +109 -0
- package/src/cli.ts +4 -4
- package/src/extraction-quote-grounding.test.ts +125 -0
- package/src/extraction-quote-grounding.ts +99 -25
- package/src/extraction-source-grounding-rules.ts +6 -1
- package/src/extraction-source-grounding.ts +2 -0
- package/src/extraction.ts +3 -4
- package/src/fact-dedup-window.test.ts +103 -20
- package/src/namespaces/search.test.ts +480 -1
- package/src/namespaces/search.ts +93 -10
- package/src/orchestration/backlog-scheduler.ts +13 -12
- package/src/orchestration/buffer-drain-runner.ts +40 -16
- package/src/orchestration/extraction-persist.ts +2 -10
- package/src/orchestration/fact-dedup-window.ts +5 -12
- package/src/orchestration/turn-ingestion.ts +38 -39
- package/src/recall-navigation-operations.ts +9 -2
- package/src/source-agent-qualifier.ts +3 -0
- package/src/storage/buffer-drain-claims.test.ts +330 -6
- package/src/storage/buffer-drain-claims.ts +226 -80
- package/src/storage/buffer-session-files.ts +2 -2
- package/src/storage/content-hash-index.ts +9 -0
- package/src/storage.ts +15 -0
- package/src/transfer/capsule-gunzip.ts +39 -0
- package/src/transfer/capsule-import.test.ts +73 -0
- package/src/transfer/capsule-import.ts +2 -2
- package/src/transfer/capsule-merge.test.ts +34 -0
- package/src/transfer/capsule-merge.ts +2 -10
- package/dist/capsule-merge-XVTQJJ6R.js.map +0 -1
- package/dist/chunk-2XJZLSXE.js.map +0 -1
- package/dist/chunk-3JPTUCD7.js.map +0 -1
- package/dist/chunk-4KLQI3L2.js.map +0 -1
- package/dist/chunk-6LCWKS62.js.map +0 -1
- package/dist/chunk-77R7BQZ2.js.map +0 -1
- package/dist/chunk-7PMOCQOL.js.map +0 -1
- package/dist/chunk-B74NPUHT.js.map +0 -1
- package/dist/chunk-D5SSBCYY.js.map +0 -1
- package/dist/chunk-HLKUZW42.js.map +0 -1
- package/dist/chunk-HWHNQVRV.js.map +0 -1
- package/dist/chunk-KASJJGRG.js.map +0 -1
- package/dist/chunk-KQUSP6LB.js.map +0 -1
- package/dist/chunk-LGEH473S.js.map +0 -1
- package/dist/chunk-LU66I56Q.js.map +0 -1
- package/dist/chunk-MPDLLLOG.js.map +0 -1
- package/dist/chunk-MPGLM2VU.js.map +0 -1
- package/dist/chunk-QZBTIYKD.js.map +0 -1
- package/dist/chunk-VLMBSGQF.js.map +0 -1
- package/dist/chunk-WAD32CZG.js.map +0 -1
- package/dist/chunk-WC475JOG.js.map +0 -1
- package/dist/chunk-X2KO4FK5.js.map +0 -1
- package/dist/chunk-XYP5WBDO.js.map +0 -1
- package/dist/chunk-YK7GOPIE.js.map +0 -1
- package/dist/chunk-Z3DDQXM4.js.map +0 -1
- /package/dist/{capsule-crypto-YO5QJ6L3.js.map → access-mcp-frames.js.map} +0 -0
- /package/dist/{auto-sync-C7E6G7Y2.js.map → auto-sync-3AZW7MXI.js.map} +0 -0
- /package/dist/{graph-edge-decay-CXTNJ7IQ.js.map → buffer-admission.js.map} +0 -0
- /package/dist/{resolution-BNWE5Y25.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-MSIRVXQ3.js.map → chunk-2G4TV2ML.js.map} +0 -0
- /package/dist/{chunk-IR4C3DP2.js.map → chunk-2K3AUDH7.js.map} +0 -0
- /package/dist/{chunk-2IW5PT7U.js.map → chunk-2N4OUSIA.js.map} +0 -0
- /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-QZSIDSB2.js.map → chunk-2NUDHVYM.js.map} +0 -0
- /package/dist/{chunk-HPFVZPRH.js.map → chunk-2U4LMSEX.js.map} +0 -0
- /package/dist/{chunk-WHQXWFH7.js.map → chunk-2XOFVTTT.js.map} +0 -0
- /package/dist/{chunk-I6ORDT54.js.map → chunk-32CA7B6L.js.map} +0 -0
- /package/dist/{chunk-T77AX6DG.js.map → chunk-32YX7EJ3.js.map} +0 -0
- /package/dist/{chunk-HLWXCDUQ.js.map → chunk-3DAWHP5K.js.map} +0 -0
- /package/dist/{chunk-ZJJFUEPO.js.map → chunk-3PJEDHLD.js.map} +0 -0
- /package/dist/{chunk-PJYK7HH2.js.map → chunk-3UZ2VMKD.js.map} +0 -0
- /package/dist/{chunk-IN4OFAHX.js.map → chunk-3Y5X6YFH.js.map} +0 -0
- /package/dist/{chunk-YUTT4ZTI.js.map → chunk-45VUHDV2.js.map} +0 -0
- /package/dist/{chunk-T6T2RMWW.js.map → chunk-4GMI5HFH.js.map} +0 -0
- /package/dist/{chunk-YOEYL6CH.js.map → chunk-4LCVA2LW.js.map} +0 -0
- /package/dist/{chunk-66JOLMWS.js.map → chunk-4X7HQKAG.js.map} +0 -0
- /package/dist/{chunk-65SKM4BF.js.map → chunk-4XYAWK5H.js.map} +0 -0
- /package/dist/{chunk-H7BZBSP6.js.map → chunk-52II7PB6.js.map} +0 -0
- /package/dist/{chunk-TPX7XXY4.js.map → chunk-5SOSQTVE.js.map} +0 -0
- /package/dist/{chunk-G3T6YMBO.js.map → chunk-64S6X4IU.js.map} +0 -0
- /package/dist/{chunk-BK7AJUWB.js.map → chunk-6BCWFCDG.js.map} +0 -0
- /package/dist/{chunk-V27FK6D6.js.map → chunk-6XTUZKCZ.js.map} +0 -0
- /package/dist/{chunk-LECSS7EE.js.map → chunk-73UZZFJC.js.map} +0 -0
- /package/dist/{chunk-4EACCIPO.js.map → chunk-77PDJ4OE.js.map} +0 -0
- /package/dist/{chunk-GQZSGXR6.js.map → chunk-7GSL4LBG.js.map} +0 -0
- /package/dist/{chunk-B6SPPYGJ.js.map → chunk-7IWRLYFJ.js.map} +0 -0
- /package/dist/{chunk-R45L4TV6.js.map → chunk-7LCGFUMB.js.map} +0 -0
- /package/dist/{chunk-A7BM2JTH.js.map → chunk-AJHNXIQU.js.map} +0 -0
- /package/dist/{chunk-2D7BTSDW.js.map → chunk-ANZZLRUX.js.map} +0 -0
- /package/dist/{chunk-ZXF3O7P4.js.map → chunk-ARRTLPRC.js.map} +0 -0
- /package/dist/{chunk-S5CQI2KF.js.map → chunk-B3GKQ6DU.js.map} +0 -0
- /package/dist/{chunk-XRBHIR7Q.js.map → chunk-B56LORLY.js.map} +0 -0
- /package/dist/{chunk-KO3YBHOV.js.map → chunk-BIVKPQ6Q.js.map} +0 -0
- /package/dist/{chunk-54FDG7K7.js.map → chunk-C2HORX76.js.map} +0 -0
- /package/dist/{chunk-E33UJHY3.js.map → chunk-CN7Q3T2J.js.map} +0 -0
- /package/dist/{chunk-YUTG35M4.js.map → chunk-CYCEROPR.js.map} +0 -0
- /package/dist/{chunk-TFLPDNQV.js.map → chunk-D5EV6Y2L.js.map} +0 -0
- /package/dist/{chunk-BFBS7OFQ.js.map → chunk-DC55RIEZ.js.map} +0 -0
- /package/dist/{chunk-B4ZU34JQ.js.map → chunk-DT7SNJH6.js.map} +0 -0
- /package/dist/{chunk-FVRTCYZ3.js.map → chunk-EA2LA5RI.js.map} +0 -0
- /package/dist/{chunk-WBN66HPI.js.map → chunk-ELHJK7LM.js.map} +0 -0
- /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
- /package/dist/{chunk-YAUHSNPB.js.map → chunk-F74G4KIH.js.map} +0 -0
- /package/dist/{chunk-BV2BRHD4.js.map → chunk-FHGWKODN.js.map} +0 -0
- /package/dist/{chunk-KESJ5XX3.js.map → chunk-G54BOKZ6.js.map} +0 -0
- /package/dist/{chunk-K36RMINQ.js.map → chunk-GOZXQNIM.js.map} +0 -0
- /package/dist/{chunk-OQSSQOKQ.js.map → chunk-GULUWOA5.js.map} +0 -0
- /package/dist/{chunk-K6RTQZA4.js.map → chunk-HFUKXOUW.js.map} +0 -0
- /package/dist/{chunk-WV254W4V.js.map → chunk-HLN2HOXX.js.map} +0 -0
- /package/dist/{chunk-FUOAIJKQ.js.map → chunk-IBDWYRDR.js.map} +0 -0
- /package/dist/{chunk-AJG2TAMR.js.map → chunk-IEEV27BC.js.map} +0 -0
- /package/dist/{chunk-LTDLJCMQ.js.map → chunk-IJ3OEECW.js.map} +0 -0
- /package/dist/{chunk-BK4FBHZ3.js.map → chunk-IPD5GC7C.js.map} +0 -0
- /package/dist/{chunk-KFLD7ZZG.js.map → chunk-IUKYFTGW.js.map} +0 -0
- /package/dist/{chunk-GCAQ3VUJ.js.map → chunk-JM2YZKCQ.js.map} +0 -0
- /package/dist/{chunk-BNQJKWWZ.js.map → chunk-K3FH3LAQ.js.map} +0 -0
- /package/dist/{chunk-RZH5RVJC.js.map → chunk-MTTYIXSU.js.map} +0 -0
- /package/dist/{chunk-XHGYZRVW.js.map → chunk-NIVKG3DS.js.map} +0 -0
- /package/dist/{chunk-VZELUMKK.js.map → chunk-NQP4ZYGG.js.map} +0 -0
- /package/dist/{chunk-YO2JEX2Z.js.map → chunk-OGBQMY46.js.map} +0 -0
- /package/dist/{chunk-TLHF75OR.js.map → chunk-OL553AWT.js.map} +0 -0
- /package/dist/{chunk-CLVILSBR.js.map → chunk-OZNBZJ3S.js.map} +0 -0
- /package/dist/{chunk-VUROWXFL.js.map → chunk-P452SEKO.js.map} +0 -0
- /package/dist/{chunk-JX3E4XCW.js.map → chunk-PDOOUXCS.js.map} +0 -0
- /package/dist/{chunk-6QYPL6NI.js.map → chunk-PKZ274PI.js.map} +0 -0
- /package/dist/{chunk-KJCL2FZO.js.map → chunk-QD5R6U5J.js.map} +0 -0
- /package/dist/{chunk-JRVMCZE3.js.map → chunk-QEYTRFR3.js.map} +0 -0
- /package/dist/{chunk-VKDAJJQP.js.map → chunk-QEZ3DW5O.js.map} +0 -0
- /package/dist/{chunk-WYPCJK6K.js.map → chunk-QKERFEJS.js.map} +0 -0
- /package/dist/{chunk-BDN3TDGV.js.map → chunk-QKES7GU6.js.map} +0 -0
- /package/dist/{chunk-PCQWKMOL.js.map → chunk-QNSZYTSG.js.map} +0 -0
- /package/dist/{chunk-IZJQNDGI.js.map → chunk-R6HMAIKM.js.map} +0 -0
- /package/dist/{chunk-NUSAAN75.js.map → chunk-ROKDHO74.js.map} +0 -0
- /package/dist/{chunk-FF6N7BXC.js.map → chunk-S45INSV3.js.map} +0 -0
- /package/dist/{chunk-2RUTN7PR.js.map → chunk-S7GJNA3K.js.map} +0 -0
- /package/dist/{chunk-XT45WCKX.js.map → chunk-SYKJBS7S.js.map} +0 -0
- /package/dist/{chunk-5BE3FLKL.js.map → chunk-TAUHAP5J.js.map} +0 -0
- /package/dist/{chunk-RJWL3RHB.js.map → chunk-TFEHSPGQ.js.map} +0 -0
- /package/dist/{chunk-K3B72DKJ.js.map → chunk-TRMZHGIX.js.map} +0 -0
- /package/dist/{chunk-WBDIZWJQ.js.map → chunk-TSS3D7ZY.js.map} +0 -0
- /package/dist/{chunk-HQPFACXO.js.map → chunk-UH3FPX3L.js.map} +0 -0
- /package/dist/{chunk-GGJFRVRD.js.map → chunk-US7KPQA5.js.map} +0 -0
- /package/dist/{chunk-FJ2VJTGA.js.map → chunk-UWRHHRDK.js.map} +0 -0
- /package/dist/{chunk-SDESKFKT.js.map → chunk-UYHDMCY2.js.map} +0 -0
- /package/dist/{chunk-3T3VHXUH.js.map → chunk-VKILERSL.js.map} +0 -0
- /package/dist/{chunk-2TGIKMMZ.js.map → chunk-WXDTOE6F.js.map} +0 -0
- /package/dist/{chunk-KQLBXUUQ.js.map → chunk-WYG5UNDY.js.map} +0 -0
- /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-FZVROZKC.js.map → chunk-XVZA6VXC.js.map} +0 -0
- /package/dist/{chunk-QA3Y2O6H.js.map → chunk-YAVIBVCU.js.map} +0 -0
- /package/dist/{chunk-VPEIWMUT.js.map → chunk-YLTU2DC4.js.map} +0 -0
- /package/dist/{chunk-EBOHFZI4.js.map → chunk-YRZPBN46.js.map} +0 -0
- /package/dist/{chunk-FMFCQRDM.js.map → chunk-ZANNIXXE.js.map} +0 -0
- /package/dist/{chunk-HQGATKG2.js.map → chunk-ZBFLV657.js.map} +0 -0
- /package/dist/{chunk-6L63IN3M.js.map → chunk-ZOJUWVAU.js.map} +0 -0
- /package/dist/{first-start-migration-QVD22WWS.js.map → first-start-migration-A6PHIBUQ.js.map} +0 -0
package/src/namespaces/search.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
SearchExecutionOptions,
|
|
8
8
|
SearchQueryOptions,
|
|
9
9
|
} from "../search/port.js";
|
|
10
|
+
import { reportSearchDegradation } from "../search/port.js";
|
|
10
11
|
import { createSearchBackend } from "../search/factory.js";
|
|
11
12
|
import { namespaceIdentityToken, normalizeNamespaceIdentity } from "./identity.js";
|
|
12
13
|
import { ALL_CATEGORY_DIRS } from "../utils/category-dir.js";
|
|
@@ -14,6 +15,13 @@ import { ALL_CATEGORY_DIRS } from "../utils/category-dir.js";
|
|
|
14
15
|
const NESTED_NAMESPACE_FILTER_OVERFETCH_FACTOR = 4;
|
|
15
16
|
const NESTED_NAMESPACE_FILTER_OVERFETCH_MIN = 50;
|
|
16
17
|
|
|
18
|
+
// Short TTL so repeated health polls skip a full QMD re-probe (~1.5s).
|
|
19
|
+
const HEALTH_RESULT_CACHE_TTL_MS = 10_000;
|
|
20
|
+
|
|
21
|
+
// Each cross-namespace search leg gets this budget; a stalled backend leg
|
|
22
|
+
// degrades its own namespace instead of holding the whole search (#3139).
|
|
23
|
+
export const NAMESPACE_SEARCH_LEG_TIMEOUT_MS = 25_000;
|
|
24
|
+
|
|
17
25
|
export function namespaceCollectionName(
|
|
18
26
|
baseCollection: string,
|
|
19
27
|
namespace: string,
|
|
@@ -72,6 +80,27 @@ export interface NamespaceSearchHealth {
|
|
|
72
80
|
embeddingBacklogThreshold: number;
|
|
73
81
|
}
|
|
74
82
|
|
|
83
|
+
/** True when the pending-embedding count is above a positive backlog threshold. */
|
|
84
|
+
export function embeddingBacklogExceeds(pending: number | null, threshold: number): boolean {
|
|
85
|
+
return threshold > 0 && pending !== null && pending > threshold;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* The one definition of a degraded search answer. The readiness consumer
|
|
90
|
+
* reports it, and `healthForNamespace` refuses to cache it.
|
|
91
|
+
*/
|
|
92
|
+
export function isSearchHealthDegraded(
|
|
93
|
+
health: Pick<NamespaceSearchHealth, "available" | "collectionState" | "pendingEmbeddings">,
|
|
94
|
+
backlogThreshold: number,
|
|
95
|
+
): boolean {
|
|
96
|
+
const active = health.available && health.collectionState !== "missing";
|
|
97
|
+
return (
|
|
98
|
+
!active ||
|
|
99
|
+
health.collectionState === "unknown" ||
|
|
100
|
+
embeddingBacklogExceeds(health.pendingEmbeddings, backlogThreshold)
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
75
104
|
type NamespaceScopedSearchConfig = PluginConfig & {
|
|
76
105
|
hostEmbeddingProviderScope?: string;
|
|
77
106
|
};
|
|
@@ -84,6 +113,11 @@ type BackendRecordOptions = {
|
|
|
84
113
|
|
|
85
114
|
export class NamespaceSearchRouter {
|
|
86
115
|
private readonly cache = new Map<string, Promise<NamespaceBackendRecord>>();
|
|
116
|
+
private readonly healthResultCache = new Map<
|
|
117
|
+
string,
|
|
118
|
+
{ expiresAt: number; value: NamespaceSearchHealth }
|
|
119
|
+
>();
|
|
120
|
+
|
|
87
121
|
private readonly pendingDisposals = new Set<Promise<void>>();
|
|
88
122
|
|
|
89
123
|
constructor(
|
|
@@ -148,42 +182,67 @@ export class NamespaceSearchRouter {
|
|
|
148
182
|
return { namespace, results: [] as QmdSearchResult[] };
|
|
149
183
|
}
|
|
150
184
|
const backendLimit = backendSearchLimit(record, maxResults);
|
|
151
|
-
|
|
185
|
+
// One stalled backend leg must not hold the whole cross-namespace
|
|
186
|
+
// search (#3139). The backend gets the deadline signal so it cancels
|
|
187
|
+
// its own work, and the await is raced against the same budget. A leg
|
|
188
|
+
// that outlives its budget degrades only its own namespace; real
|
|
189
|
+
// backend errors and caller aborts propagate as before.
|
|
190
|
+
const legAbort = new AbortController();
|
|
191
|
+
const legTimer = setTimeout(() => legAbort.abort(), NAMESPACE_SEARCH_LEG_TIMEOUT_MS);
|
|
192
|
+
const legSignal = options.execution?.signal
|
|
193
|
+
? AbortSignal.any([options.execution.signal, legAbort.signal])
|
|
194
|
+
: legAbort.signal;
|
|
195
|
+
const legExecution: SearchExecutionOptions = { ...options.execution, signal: legSignal };
|
|
196
|
+
let leg: Promise<QmdSearchResult[]>;
|
|
152
197
|
switch (method) {
|
|
153
198
|
case "hybrid":
|
|
154
|
-
|
|
199
|
+
leg = record.backend.hybridSearch(
|
|
155
200
|
query,
|
|
156
201
|
record.collection,
|
|
157
202
|
backendLimit,
|
|
158
|
-
|
|
203
|
+
legExecution,
|
|
159
204
|
);
|
|
160
205
|
break;
|
|
161
206
|
case "bm25":
|
|
162
|
-
|
|
207
|
+
leg = record.backend.bm25Search(
|
|
163
208
|
query,
|
|
164
209
|
record.collection,
|
|
165
210
|
backendLimit,
|
|
166
|
-
|
|
211
|
+
legExecution,
|
|
167
212
|
);
|
|
168
213
|
break;
|
|
169
214
|
case "vector":
|
|
170
|
-
|
|
215
|
+
leg = record.backend.vectorSearch(
|
|
171
216
|
query,
|
|
172
217
|
record.collection,
|
|
173
218
|
backendLimit,
|
|
174
|
-
|
|
219
|
+
legExecution,
|
|
175
220
|
);
|
|
176
221
|
break;
|
|
177
222
|
default:
|
|
178
|
-
|
|
223
|
+
leg = record.backend.search(
|
|
179
224
|
query,
|
|
180
225
|
record.collection,
|
|
181
226
|
backendLimit,
|
|
182
227
|
options.searchOptions,
|
|
183
|
-
|
|
228
|
+
legExecution,
|
|
184
229
|
);
|
|
185
230
|
break;
|
|
186
231
|
}
|
|
232
|
+
let results: QmdSearchResult[];
|
|
233
|
+
try {
|
|
234
|
+
results = await awaitWithAbort(leg, legSignal);
|
|
235
|
+
} catch (error) {
|
|
236
|
+
if (options.execution?.signal?.aborted || !legAbort.signal.aborted) throw error;
|
|
237
|
+
reportSearchDegradation(options.execution, {
|
|
238
|
+
backend: "qmd",
|
|
239
|
+
code: "deadline_exceeded",
|
|
240
|
+
detail: `namespace search deadline exceeded: ${namespace}`,
|
|
241
|
+
});
|
|
242
|
+
return { namespace, results: [] };
|
|
243
|
+
} finally {
|
|
244
|
+
clearTimeout(legTimer);
|
|
245
|
+
}
|
|
187
246
|
results = filterNamespaceSubtreeResults(record, results)
|
|
188
247
|
.map((result) => ({
|
|
189
248
|
...result,
|
|
@@ -279,6 +338,11 @@ export class NamespaceSearchRouter {
|
|
|
279
338
|
execution?: SearchExecutionOptions,
|
|
280
339
|
): Promise<NamespaceSearchHealth> {
|
|
281
340
|
const key = namespace.trim() || this.config.defaultNamespace;
|
|
341
|
+
const cached = this.healthResultCache.get(key);
|
|
342
|
+
if (cached && cached.expiresAt > Date.now()) {
|
|
343
|
+
return { ...cached.value };
|
|
344
|
+
}
|
|
345
|
+
|
|
282
346
|
const record = await this.createBackendRecordFor(
|
|
283
347
|
key,
|
|
284
348
|
execution,
|
|
@@ -310,7 +374,7 @@ export class NamespaceSearchRouter {
|
|
|
310
374
|
? "missing"
|
|
311
375
|
: record.collectionState;
|
|
312
376
|
|
|
313
|
-
|
|
377
|
+
const health: NamespaceSearchHealth = {
|
|
314
378
|
collection: record.collection,
|
|
315
379
|
memoryDir: record.memoryDir,
|
|
316
380
|
available: liveRecord?.available ?? record.available,
|
|
@@ -326,6 +390,22 @@ export class NamespaceSearchRouter {
|
|
|
326
390
|
oldestPendingAgeMs: backendStatus?.oldestPendingAgeMs ?? null,
|
|
327
391
|
embeddingBacklogThreshold: this.config.qmdEmbeddingBacklogThreshold,
|
|
328
392
|
};
|
|
393
|
+
|
|
394
|
+
// Cache only a healthy answer that carries backlog data when the backend
|
|
395
|
+
// reports status. A degraded or incomplete answer must re-probe so a
|
|
396
|
+
// readiness poll sees recovery on the next call, not one TTL late.
|
|
397
|
+
const statusMissing = backendStatus === null && "status" in diagnosticBackend;
|
|
398
|
+
if (
|
|
399
|
+
execution?.signal?.aborted !== true &&
|
|
400
|
+
!statusMissing &&
|
|
401
|
+
!isSearchHealthDegraded(health, health.embeddingBacklogThreshold)
|
|
402
|
+
) {
|
|
403
|
+
this.healthResultCache.set(key, {
|
|
404
|
+
expiresAt: Date.now() + HEALTH_RESULT_CACHE_TTL_MS,
|
|
405
|
+
value: { ...health },
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
return { ...health };
|
|
329
409
|
} finally {
|
|
330
410
|
const dispose = (record.backend as { dispose?: () => void | Promise<void> }).dispose;
|
|
331
411
|
await dispose?.call(record.backend);
|
|
@@ -358,6 +438,7 @@ export class NamespaceSearchRouter {
|
|
|
358
438
|
|
|
359
439
|
/** Clear cached backend records so the next access re-probes availability. */
|
|
360
440
|
clearCache(): void {
|
|
441
|
+
this.healthResultCache.clear();
|
|
361
442
|
const pendingRecords = Array.from(this.cache.values());
|
|
362
443
|
this.cache.clear();
|
|
363
444
|
const disposal = Promise.allSettled(pendingRecords).then(async (settled) => {
|
|
@@ -379,6 +460,7 @@ export class NamespaceSearchRouter {
|
|
|
379
460
|
/** Release any per-namespace backend handles held by cached records. */
|
|
380
461
|
async dispose(): Promise<void> {
|
|
381
462
|
await this.drainPendingDisposals();
|
|
463
|
+
this.healthResultCache.clear();
|
|
382
464
|
const pendingRecords = Array.from(this.cache.values());
|
|
383
465
|
this.cache.clear();
|
|
384
466
|
const settled = await Promise.allSettled(pendingRecords);
|
|
@@ -395,6 +477,7 @@ export class NamespaceSearchRouter {
|
|
|
395
477
|
* has been switched to NoopSearchBackend for a missing collection.
|
|
396
478
|
*/
|
|
397
479
|
async disableSearchBackends(): Promise<void> {
|
|
480
|
+
this.healthResultCache.clear();
|
|
398
481
|
const settled = await Promise.allSettled(this.cache.values());
|
|
399
482
|
await Promise.allSettled(
|
|
400
483
|
settled.flatMap((entry) => {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* every claim retryable; a restarted daemon's scheduler adopts them.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
import { randomUUID } from "node:crypto";
|
|
28
29
|
import { hostname } from "node:os";
|
|
29
30
|
import { log } from "../logger.js";
|
|
30
31
|
import type { Orchestrator } from "../orchestrator.js";
|
|
@@ -44,8 +45,8 @@ export interface BacklogSchedulerDeps {
|
|
|
44
45
|
liveBufferCounts():
|
|
45
46
|
| Map<string, { turns: number; retainedTurns: number }>
|
|
46
47
|
| Promise<Map<string, { turns: number; retainedTurns: number }>>;
|
|
47
|
-
/**
|
|
48
|
-
lease(): DrainLease;
|
|
48
|
+
/** Create a fresh lease for a unique owner token. */
|
|
49
|
+
lease(ownerId: string): DrainLease;
|
|
49
50
|
/** Drain one key to quiescence (BufferDrainRunner.drainSession). */
|
|
50
51
|
drainKey(
|
|
51
52
|
key: string,
|
|
@@ -63,6 +64,7 @@ export interface BacklogSchedulerDeps {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export interface BacklogSchedulerOptions {
|
|
67
|
+
/** Optional label prefix; each scheduler instance adds a unique token. */
|
|
66
68
|
ownerId?: string;
|
|
67
69
|
/** Scan cadence in ms (startup + new-work + retry checks). */
|
|
68
70
|
pollMs?: number;
|
|
@@ -135,7 +137,7 @@ export class BacklogScheduler {
|
|
|
135
137
|
constructor(deps: BacklogSchedulerDeps, options: BacklogSchedulerOptions = {}) {
|
|
136
138
|
this.deps = deps;
|
|
137
139
|
this.options = {
|
|
138
|
-
ownerId: options.ownerId ??
|
|
140
|
+
ownerId: `${options.ownerId ?? "daemon-drain"}-${randomUUID()}`,
|
|
139
141
|
pollMs: options.pollMs ?? DEFAULT_POLL_MS,
|
|
140
142
|
retryBaseMs: options.retryBaseMs ?? DEFAULT_RETRY_BASE_MS,
|
|
141
143
|
retryMaxMs: options.retryMaxMs ?? DEFAULT_RETRY_MAX_MS,
|
|
@@ -333,11 +335,11 @@ export class BacklogScheduler {
|
|
|
333
335
|
const { promise: settled, resolve: settle } = Promise.withResolvers<void>();
|
|
334
336
|
this.inFlight.set(key, { controller, settled });
|
|
335
337
|
try {
|
|
336
|
-
if (!(await this.claimForSubmit(key, needsClaim))) return;
|
|
338
|
+
if (!(await this.claimForSubmit(key, needsClaim, this.options.ownerId))) return;
|
|
337
339
|
// Stopped between the claim decision and the task: leave the claim
|
|
338
340
|
// with its lease (it expires; the next start adopts) — never drain.
|
|
339
341
|
if (this.stopped) return;
|
|
340
|
-
await this.drainClaimedKey(key, controller.signal);
|
|
342
|
+
await this.drainClaimedKey(key, controller.signal, this.options.ownerId);
|
|
341
343
|
} catch (err) {
|
|
342
344
|
// Claim/drain failures are scheduler-level: the claim content is
|
|
343
345
|
// untouched — count failed and back off (never an unhandled rejection
|
|
@@ -357,10 +359,10 @@ export class BacklogScheduler {
|
|
|
357
359
|
}
|
|
358
360
|
|
|
359
361
|
/** after all — the key goes quiet without a task. "claimed": ours. */
|
|
360
|
-
private async claimForSubmit(key: string, needsClaim: boolean): Promise<boolean> {
|
|
362
|
+
private async claimForSubmit(key: string, needsClaim: boolean, ownerId: string): Promise<boolean> {
|
|
361
363
|
if (!needsClaim) return true;
|
|
362
364
|
try {
|
|
363
|
-
const outcome = await this.deps.claims.claimFromSessionFile(key, this.deps.lease());
|
|
365
|
+
const outcome = await this.deps.claims.claimFromSessionFile(key, this.deps.lease(ownerId));
|
|
364
366
|
if (outcome === "empty") {
|
|
365
367
|
this.keys.delete(key);
|
|
366
368
|
return false;
|
|
@@ -375,11 +377,11 @@ export class BacklogScheduler {
|
|
|
375
377
|
/** Drain one claimed key. drainKey reports failures as outcomes; a thrown
|
|
376
378
|
* error still means the claim content is intact — count it failed and
|
|
377
379
|
* back off. */
|
|
378
|
-
private async drainClaimedKey(key: string, signal: AbortSignal): Promise<void> {
|
|
380
|
+
private async drainClaimedKey(key: string, signal: AbortSignal, ownerId: string): Promise<void> {
|
|
379
381
|
this.counters.claimed += 1;
|
|
380
382
|
try {
|
|
381
383
|
const outcome = await this.deps.drainKey(key, {
|
|
382
|
-
ownerId
|
|
384
|
+
ownerId,
|
|
383
385
|
signal,
|
|
384
386
|
});
|
|
385
387
|
this.applyOutcome(key, outcome);
|
|
@@ -480,7 +482,6 @@ export function wireBacklogScheduler(
|
|
|
480
482
|
orchestrator: Orchestrator,
|
|
481
483
|
options: BacklogSchedulerOptions = {}
|
|
482
484
|
): BacklogScheduler {
|
|
483
|
-
const ownerId = options.ownerId ?? `daemon-drain-${process.pid}`;
|
|
484
485
|
const runner = new BufferDrainRunner(orchestrator);
|
|
485
486
|
return new BacklogScheduler(
|
|
486
487
|
{
|
|
@@ -492,7 +493,7 @@ export function wireBacklogScheduler(
|
|
|
492
493
|
await orchestrator.buffer.load();
|
|
493
494
|
return orchestrator.buffer.entryCounts();
|
|
494
495
|
},
|
|
495
|
-
lease: () => {
|
|
496
|
+
lease: (ownerId) => {
|
|
496
497
|
const now = new Date().toISOString();
|
|
497
498
|
return {
|
|
498
499
|
ownerId,
|
|
@@ -508,6 +509,6 @@ export function wireBacklogScheduler(
|
|
|
508
509
|
// claim-backed drain accumulate toward the same threshold).
|
|
509
510
|
breakerSnapshot: () => orchestrator.getExtractionResilienceStatus().breaker,
|
|
510
511
|
},
|
|
511
|
-
|
|
512
|
+
options
|
|
512
513
|
);
|
|
513
514
|
}
|
|
@@ -74,27 +74,35 @@ const DEFAULT_LEASE_MS = 120_000;
|
|
|
74
74
|
* A `BufferStorage` view of one drain claim: the claim file IS the buffer.
|
|
75
75
|
* Writes are the drain's progress (what is left to extract), so every
|
|
76
76
|
* successfully extracted chunk is durably removed before the next one runs.
|
|
77
|
+
*
|
|
78
|
+
* `seen` is the drainer's own view of the claim: the entry it loaded, then the
|
|
79
|
+
* entry it last wrote. Each progress write is diffed against it, so a write
|
|
80
|
+
* records only the turns extracted since the previous one.
|
|
77
81
|
*/
|
|
78
82
|
export class ClaimBufferStorage implements BufferStorage {
|
|
83
|
+
private seen: BufferEntryState;
|
|
84
|
+
|
|
79
85
|
constructor(
|
|
80
86
|
private readonly claims: BufferDrainClaims,
|
|
81
87
|
private readonly key: string,
|
|
82
88
|
private readonly ownerId: string,
|
|
83
|
-
|
|
84
|
-
) {
|
|
89
|
+
entry: BufferEntryState
|
|
90
|
+
) {
|
|
91
|
+
this.seen = entry;
|
|
92
|
+
}
|
|
85
93
|
|
|
86
94
|
async loadBuffer(): Promise<BufferState> {
|
|
87
95
|
const entries: NonNullable<BufferState["entries"]> = Object.create(null);
|
|
88
96
|
entries[this.key] = {
|
|
89
|
-
turns: this.
|
|
90
|
-
retainedTurns: this.
|
|
91
|
-
lastExtractionAt: this.
|
|
92
|
-
extractionCount: this.
|
|
97
|
+
turns: this.seen.turns,
|
|
98
|
+
retainedTurns: this.seen.retainedTurns,
|
|
99
|
+
lastExtractionAt: this.seen.lastExtractionAt,
|
|
100
|
+
extractionCount: this.seen.extractionCount,
|
|
93
101
|
};
|
|
94
102
|
return {
|
|
95
|
-
turns: this.
|
|
96
|
-
lastExtractionAt: this.
|
|
97
|
-
extractionCount: this.
|
|
103
|
+
turns: this.seen.turns,
|
|
104
|
+
lastExtractionAt: this.seen.lastExtractionAt,
|
|
105
|
+
extractionCount: this.seen.extractionCount,
|
|
98
106
|
entries,
|
|
99
107
|
};
|
|
100
108
|
}
|
|
@@ -102,16 +110,21 @@ export class ClaimBufferStorage implements BufferStorage {
|
|
|
102
110
|
async saveBuffer(state: BufferState): Promise<void> {
|
|
103
111
|
// Whole-state fallback (the claim covers one session): persist the entry.
|
|
104
112
|
const entry = state.entries?.[this.key];
|
|
105
|
-
await this.
|
|
106
|
-
this.key,
|
|
107
|
-
this.ownerId,
|
|
108
|
-
entry ?? { turns: [], lastExtractionAt: null, extractionCount: 0 },
|
|
109
|
-
this.entry
|
|
110
|
-
);
|
|
113
|
+
await this.writeProgress(entry ?? { turns: [], lastExtractionAt: null, extractionCount: 0 });
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
async saveBufferSession(key: string, entry: BufferEntryState): Promise<void> {
|
|
114
|
-
|
|
117
|
+
if (key !== this.key) {
|
|
118
|
+
await this.claims.writeEntry(key, this.ownerId, entry, undefined);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
await this.writeProgress(entry);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private async writeProgress(entry: BufferEntryState): Promise<void> {
|
|
125
|
+
await this.claims.writeEntry(this.key, this.ownerId, entry, this.seen);
|
|
126
|
+
// Copy the lists: the buffer keeps mutating its own arrays after a save.
|
|
127
|
+
this.seen = { ...entry, turns: [...entry.turns], retainedTurns: entry.retainedTurns ? [...entry.retainedTurns] : undefined };
|
|
115
128
|
}
|
|
116
129
|
|
|
117
130
|
async deleteBufferSession(): Promise<void> {
|
|
@@ -554,14 +567,25 @@ async function runClaimDrain(
|
|
|
554
567
|
options: BufferDrainRunnerOptions,
|
|
555
568
|
heartbeat: NodeJS.Timeout
|
|
556
569
|
): Promise<DrainSessionOutcome> {
|
|
570
|
+
// Reconcile only identities recorded as durably extracted under this
|
|
571
|
+
// owner's claim lease. The claim lock is released before entering the live
|
|
572
|
+
// buffer mutation queue, preserving the buffer→claim lock order used by
|
|
573
|
+
// concurrent ingress saves.
|
|
574
|
+
const reconcileDrainedTurns = async (): Promise<void> => {
|
|
575
|
+
const drained = await ctx.claims.drainedTurnsForOwner(ctx.key, ctx.ownerId);
|
|
576
|
+
if (drained !== null) await ctx.orchestrator.buffer.save({ key: ctx.key, drained });
|
|
577
|
+
};
|
|
578
|
+
|
|
557
579
|
// An emptied claim acks here: the ack verdict is the truth (drained), or
|
|
558
580
|
// live ingress merged between the read and the ack — deferred, source kept.
|
|
559
581
|
if (ctx.turns.length === 0) {
|
|
582
|
+
await reconcileDrainedTurns();
|
|
560
583
|
const outcome = await ackEmptyClaim(ctx.claims, ctx.key, ctx.ownerId, ctx.turnsAtStart);
|
|
561
584
|
options.onEvent?.({ type: "session_finished", key: ctx.key, outcome });
|
|
562
585
|
return outcome;
|
|
563
586
|
}
|
|
564
587
|
const { groupOutcomes, groupError } = await drainScopeGroups(ctx);
|
|
588
|
+
await reconcileDrainedTurns();
|
|
565
589
|
// Heartbeat cleared on EVERY exit path: a rejected drain must not keep
|
|
566
590
|
// renewing the lease forever (cleared in the caller's finally).
|
|
567
591
|
const remaining = await ctx.claims.load(ctx.key);
|
|
@@ -1694,11 +1694,7 @@ export class ExtractionPersistCoordinator {
|
|
|
1694
1694
|
// confirmation, so a disabled deployment never suppresses a write via
|
|
1695
1695
|
// dedup (PR #2016 thread SD-nH).
|
|
1696
1696
|
if (factDedupEnabled) {
|
|
1697
|
-
exactDuplicate = await confirmActiveFactDuplicate(
|
|
1698
|
-
{ hasContentHashDedup: (storage, key) => this.deps.hasContentHashDedup(storage, key) },
|
|
1699
|
-
targetStorage,
|
|
1700
|
-
raceDedupOpts(contentHashDedupKey),
|
|
1701
|
-
);
|
|
1697
|
+
exactDuplicate = await confirmActiveFactDuplicate(targetStorage, raceDedupOpts(contentHashDedupKey));
|
|
1702
1698
|
}
|
|
1703
1699
|
// PR #2016/#3231: finalize committed writes before a fail-closed
|
|
1704
1700
|
// window throw propagates (PRRT_kwDORJXyws6zxG6H).
|
|
@@ -1711,11 +1707,7 @@ export class ExtractionPersistCoordinator {
|
|
|
1711
1707
|
const raceRecheck = (storage: StorageManager, key: string) => () => {
|
|
1712
1708
|
// Gates mirror the persist-time suppression gates (PR #2016 SD-nH; #1645 quarantine).
|
|
1713
1709
|
if (!factDedupEnabled || injectionScreenStatus === "pending_review") return Promise.resolve(false);
|
|
1714
|
-
return confirmActiveFactDuplicate(
|
|
1715
|
-
{ hasContentHashDedup: (s, k) => this.deps.hasContentHashDedup(s, k) },
|
|
1716
|
-
storage,
|
|
1717
|
-
raceDedupOpts(key),
|
|
1718
|
-
);
|
|
1710
|
+
return confirmActiveFactDuplicate(storage, raceDedupOpts(key));
|
|
1719
1711
|
};
|
|
1720
1712
|
// #1671/#1707 — backfill bi-temporal bounds onto the surviving copy
|
|
1721
1713
|
// when a duplicate short-circuits: persist-time hit OR raced duplicate
|
|
@@ -19,9 +19,6 @@ import { log } from "../logger.js";
|
|
|
19
19
|
* OUTSIDE the window exactly like the consolidation LLM call stays outside
|
|
20
20
|
* commitConsolidatedProfile.
|
|
21
21
|
*/
|
|
22
|
-
export interface FactDedupProbe {
|
|
23
|
-
hasContentHashDedup(storage: StorageManager, key: string): Promise<boolean>;
|
|
24
|
-
}
|
|
25
22
|
|
|
26
23
|
interface FactDedupMatchOptions {
|
|
27
24
|
readonly category: string;
|
|
@@ -55,22 +52,18 @@ function matchesActiveConnectorDuplicate(memory: MemoryFile, opts: FactDedupMatc
|
|
|
55
52
|
* silently drop content.
|
|
56
53
|
*/
|
|
57
54
|
export async function confirmActiveFactDuplicate(
|
|
58
|
-
probe: FactDedupProbe,
|
|
59
55
|
storage: StorageManager,
|
|
60
56
|
opts: FactDedupMatchOptions,
|
|
61
57
|
): Promise<boolean> {
|
|
62
|
-
let needsCorpusConfirm: boolean;
|
|
63
58
|
try {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
59
|
+
// One lookup returns the MISS together with the authority behind it, so a
|
|
60
|
+
// stale MISS is never paired with authority from another moment: any
|
|
61
|
+
// second read of authority can rebuild the index and bless it (#3312).
|
|
62
|
+
const lookup = await storage.lookupContentHash(opts.contentHashDedupKey);
|
|
63
|
+
if (!lookup.present && lookup.authoritative) return false;
|
|
70
64
|
} catch {
|
|
71
65
|
// Dedup lookup failed (e.g. the authoritative rebuild could not run). Do
|
|
72
66
|
// NOT fail-open into a possible duplicate — confirm against the corpus.
|
|
73
|
-
needsCorpusConfirm = true;
|
|
74
67
|
}
|
|
75
68
|
try {
|
|
76
69
|
// #2016 cold-tier finding: the authoritative content-hash rebuild unions
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { createHash, randomBytes } from "node:crypto";
|
|
20
20
|
import { abortError, isPreemptedExtraction } from "../abort-error.js";
|
|
21
|
-
import { SmartBuffer } from "../buffer.js";
|
|
21
|
+
import { SmartBuffer, type AddTurnOutcome } from "../buffer.js";
|
|
22
22
|
import type { ImportTurn } from "../bulk-import/types.js";
|
|
23
23
|
import { resolveNamespaceCapabilities, resolvePipelineProcessingCapabilities, resolveRecallAuxiliaryCapabilities } from "../capabilities.js";
|
|
24
24
|
import type { CorrectionService } from "../correction/correction-service.js";
|
|
@@ -57,18 +57,10 @@ import {
|
|
|
57
57
|
type BulkImportBatchIngestResult,
|
|
58
58
|
} from "../orchestrator.js";
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* previously accepted capture was evicted to make room.
|
|
65
|
-
*/
|
|
66
|
-
export class ReplayAdmissionRefusedError extends Error {
|
|
67
|
-
constructor(message: string) {
|
|
68
|
-
super(message);
|
|
69
|
-
this.name = "ReplayAdmissionRefusedError";
|
|
70
|
-
}
|
|
71
|
-
}
|
|
60
|
+
// The class lives in ../buffer-admission.js next to BufferAdmissionRefusedError;
|
|
61
|
+
// re-exported here so existing importers keep their import path.
|
|
62
|
+
import { ReplayAdmissionRefusedError } from "../buffer-admission.js";
|
|
63
|
+
export { ReplayAdmissionRefusedError };
|
|
72
64
|
|
|
73
65
|
export interface TurnIngestionDeps {
|
|
74
66
|
readonly buffer: SmartBuffer;
|
|
@@ -440,10 +432,29 @@ export class TurnIngestionCoordinator {
|
|
|
440
432
|
"accepted capture requires an explicit storage target (writeNamespaceOverride or scopeProfileWritePlan.writeNamespace)",
|
|
441
433
|
);
|
|
442
434
|
}
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (options.
|
|
435
|
+
const pin = (turn: BufferTurn): BufferTurn => {
|
|
436
|
+
const pinned: BufferTurn = { ...turn, acceptedCapture: true, writeNamespaceOverride: resolvedWriteTarget };
|
|
437
|
+
if (options.codingContext) pinned.codingContext = options.codingContext;
|
|
438
|
+
if (options.principalOverride) pinned.principalOverride = options.principalOverride;
|
|
439
|
+
if (options.scopeProfileWritePlan) pinned.scopeProfileWritePlan = options.scopeProfileWritePlan;
|
|
440
|
+
return pinned;
|
|
441
|
+
};
|
|
442
|
+
const batches = [...bySession].map(([bufferKey, sessionTurns]) => ({ bufferKey, turns: sessionTurns.map(pin) }));
|
|
443
|
+
const outcomes = await this.deps.buffer.addTurnsBounded(batches);
|
|
444
|
+
if (outcomes === null) {
|
|
445
|
+
const refusedKey = batches.find((batch) => batch.turns.length > 0)?.bufferKey ?? "unknown";
|
|
446
|
+
throw new ReplayAdmissionRefusedError(
|
|
447
|
+
`durable observe capture refused: extraction buffer at entry capacity for batch containing ${refusedKey}`,
|
|
448
|
+
);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// All requested session keys were capacity-admitted together before any
|
|
452
|
+
// turn was saved. There is no retry identity: a repeat after a crash that
|
|
453
|
+
// persisted only a prefix duplicates that prefix, as on main.
|
|
454
|
+
await this.deps.buffer.flushPendingSave({ throwOnFailure: true });
|
|
455
|
+
|
|
456
|
+
if (options.archiveLcm !== false && this.deps.lcmEngine?.enabled) {
|
|
457
|
+
for (const [bufferKey, sessionTurns] of bySession) {
|
|
447
458
|
await this.deps.lcmEngine.observeMessages(
|
|
448
459
|
bufferKey,
|
|
449
460
|
sessionTurns.map((turn) => ({
|
|
@@ -455,29 +466,17 @@ export class TurnIngestionCoordinator {
|
|
|
455
466
|
})),
|
|
456
467
|
);
|
|
457
468
|
}
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
}
|
|
469
|
-
if (outcome.decision !== "keep_buffering" && outcome.extractionTurns) {
|
|
470
|
-
queueBufferedCaptureScopeGroups(
|
|
471
|
-
this.deps.queueBufferedExtraction,
|
|
472
|
-
outcome.extractionTurns,
|
|
473
|
-
bufferKey,
|
|
474
|
-
options,
|
|
475
|
-
);
|
|
476
|
-
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
for (const { bufferKey, outcome } of outcomes) {
|
|
472
|
+
if (outcome.decision !== "keep_buffering" && outcome.extractionTurns) {
|
|
473
|
+
queueBufferedCaptureScopeGroups(
|
|
474
|
+
this.deps.queueBufferedExtraction,
|
|
475
|
+
outcome.extractionTurns,
|
|
476
|
+
bufferKey,
|
|
477
|
+
options,
|
|
478
|
+
);
|
|
477
479
|
}
|
|
478
|
-
// Acceptance durability barrier (#1909 seam): surfaces storage failures
|
|
479
|
-
// BEFORE the caller can report acceptance. Not abort-gated.
|
|
480
|
-
await this.deps.buffer.flushPendingSave({ throwOnFailure: true });
|
|
481
480
|
}
|
|
482
481
|
}
|
|
483
482
|
|
|
@@ -11,13 +11,20 @@
|
|
|
11
11
|
import { z } from "zod";
|
|
12
12
|
|
|
13
13
|
import { defineOperation } from "./access-boundary.js";
|
|
14
|
-
import { EngramAccessInputError } from "./access-errors.js";
|
|
14
|
+
import { EngramAccessInputError, rejectReservedArgumentKey } from "./access-errors.js";
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Null-prototype accumulator for cleaned request arguments, matching the
|
|
18
|
+
* batch preprocessors (issue #3225 B1): a copied own `__proto__` member on a
|
|
19
|
+
* plain `{}` switches the accumulator's prototype and an inherited field then
|
|
20
|
+
* reaches the zod parse.
|
|
21
|
+
*/
|
|
16
22
|
function stripNulls(data: unknown): unknown {
|
|
17
23
|
if (data !== null && typeof data === "object" && !Array.isArray(data)) {
|
|
18
24
|
const obj = data as Record<string, unknown>;
|
|
19
|
-
const cleaned
|
|
25
|
+
const cleaned = Object.create(null);
|
|
20
26
|
for (const [key, value] of Object.entries(obj)) {
|
|
27
|
+
rejectReservedArgumentKey(key);
|
|
21
28
|
if (value !== null) cleaned[key] = value;
|
|
22
29
|
}
|
|
23
30
|
return cleaned;
|
|
@@ -52,6 +52,8 @@ export interface ExtractionGroundingContext {
|
|
|
52
52
|
* second pass reads it so its prompts carry the same media warning. */
|
|
53
53
|
ambientCapture?: boolean;
|
|
54
54
|
scopeClassificationEnabled?: boolean;
|
|
55
|
+
/** Contents of the turns assertionSource was joined from, so quote anchors cut at real turn boundaries. */
|
|
56
|
+
turns?: readonly string[];
|
|
55
57
|
}
|
|
56
58
|
|
|
57
59
|
export function applyGroundingWithConnector(
|
|
@@ -64,6 +66,7 @@ export function applyGroundingWithConnector(
|
|
|
64
66
|
sourceGrounding: caps.sourceGrounding,
|
|
65
67
|
anchorTemporalExpressions: caps.delinearize,
|
|
66
68
|
spanMode: config.extraction?.spanMode ?? "off",
|
|
69
|
+
turns: ctx.turns,
|
|
67
70
|
};
|
|
68
71
|
const known = buildKnownConnectors(ctx.sourceConnector);
|
|
69
72
|
// Scope-forcing is decoupled from strip/restore (runs without a trusted
|