@remnic/core 10.0.38 → 10.0.40
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 +73 -73
- package/dist/access-audit.js +2 -2
- package/dist/access-authorization-probe.js +74 -74
- package/dist/access-boundary.js +73 -73
- package/dist/access-citation-namespace.js +2 -2
- package/dist/access-cli.js +162 -161
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.js +73 -73
- package/dist/access-http-briefing.js +74 -74
- package/dist/access-http-query.js +75 -75
- package/dist/access-http.js +98 -98
- package/dist/access-identity-continuity-surface.js +73 -73
- package/dist/access-lcm-surface.js +73 -73
- package/dist/access-mcp.js +87 -87
- package/dist/access-namespace-preflight.js +73 -73
- package/dist/access-observe-write-category.js +15 -15
- package/dist/access-observe-write-surface.js +73 -73
- package/dist/access-offline-manifest.js +12 -12
- package/dist/access-operations-batch.js +77 -77
- package/dist/access-operations.js +84 -84
- package/dist/access-recall-concurrency.js +73 -73
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +73 -73
- package/dist/access-recall-surface.js +73 -73
- package/dist/access-schema.js +10 -10
- package/dist/access-service.d.ts +2 -2
- package/dist/access-service.d.ts.map +1 -1
- package/dist/access-service.js +73 -73
- package/dist/access-surface-catalog.js +75 -75
- package/dist/active-recall.js +29 -29
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-432USQDH.js → auto-sync-BNCBMU6H.js} +7 -7
- package/dist/briefing.js +19 -19
- package/dist/buffer-types.d.ts +59 -0
- package/dist/buffer-types.d.ts.map +1 -0
- package/dist/buffer-types.js +1 -0
- package/dist/buffer.d.ts +14 -22
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.js +11 -11
- package/dist/calibration.js +2 -2
- package/dist/{capsule-crypto-7FJQINUR.js → capsule-crypto-GWVG7LGC.js} +2 -2
- package/dist/causal-behavior.js +2 -2
- package/dist/causal-chain.js +2 -2
- package/dist/causal-consolidation.js +22 -22
- 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-MKE5DP3S.js → chunk-23ZMQONL.js} +2 -2
- package/dist/{chunk-3K5IEJTK.js → chunk-2AV2U2SZ.js} +3 -3
- package/dist/{chunk-HJ3UTGIW.js → chunk-2JNBPOZ2.js} +3 -3
- package/dist/{chunk-5ANUG4JZ.js → chunk-2T6KEOUL.js} +2 -2
- package/dist/{chunk-EEOYF3IB.js → chunk-3RJDYZJE.js} +2 -2
- package/dist/{chunk-P5CUEB2Q.js → chunk-4QLKVZH6.js} +8 -8
- package/dist/{chunk-XTBEXZFN.js → chunk-5SF7JOJB.js} +4 -4
- package/dist/{chunk-53BLBDV6.js → chunk-5TRU6QQC.js} +2 -2
- package/dist/{chunk-DKHX2FHI.js → chunk-64WHWIPL.js} +2 -2
- package/dist/{chunk-TVIGN3XZ.js → chunk-6FRFVIKC.js} +10 -10
- package/dist/{chunk-JIA435P3.js → chunk-6ITNEPJO.js} +2 -2
- package/dist/{chunk-WEK3OUGO.js → chunk-6X3J4NLZ.js} +10 -5
- package/dist/chunk-6X3J4NLZ.js.map +1 -0
- package/dist/{chunk-FGEY2AGV.js → chunk-7BCYAJKP.js} +2 -2
- package/dist/{chunk-PSQ2P2T3.js → chunk-7XZ7TOLQ.js} +3 -3
- package/dist/{chunk-6JEEY42N.js → chunk-AER3HD3B.js} +2 -2
- package/dist/{chunk-POGPI5GR.js → chunk-AY6LO7GD.js} +2 -2
- package/dist/{chunk-HXFIILGF.js → chunk-BFPF5N3H.js} +4 -4
- package/dist/{chunk-WCBLPKG3.js → chunk-BIYVUPC6.js} +172 -143
- package/dist/chunk-BIYVUPC6.js.map +1 -0
- package/dist/{chunk-KQAFEZQX.js → chunk-BUKK5SWA.js} +2 -2
- package/dist/{chunk-LHBOFROT.js → chunk-CHNZPOWX.js} +4 -3
- package/dist/{chunk-LHBOFROT.js.map → chunk-CHNZPOWX.js.map} +1 -1
- package/dist/{chunk-6F5BGIAF.js → chunk-CNAL35D5.js} +3 -3
- package/dist/{chunk-YC2C67F7.js → chunk-CRXGQRNA.js} +3 -3
- package/dist/{chunk-WRDFYSUC.js → chunk-CZVNOTLR.js} +2 -2
- package/dist/{chunk-VPO53QMG.js → chunk-D6DOLQYK.js} +2 -2
- package/dist/{chunk-RGKXF4W3.js → chunk-E5IEI2MR.js} +2 -2
- package/dist/{chunk-Z2T5BPOZ.js → chunk-EIYJK7OD.js} +2 -2
- package/dist/{chunk-FRAL3EU4.js → chunk-EKPRLTAE.js} +2 -2
- package/dist/{chunk-MCPSMWUC.js → chunk-EPEDMEHO.js} +10 -10
- package/dist/{chunk-MCPSMWUC.js.map → chunk-EPEDMEHO.js.map} +1 -1
- package/dist/{chunk-TYGLV6ZG.js → chunk-EYGOM6AI.js} +2 -2
- package/dist/{chunk-TYGLV6ZG.js.map → chunk-EYGOM6AI.js.map} +1 -1
- package/dist/{chunk-I75BWXRZ.js → chunk-F2RDRE7M.js} +2 -2
- package/dist/{chunk-2AKIVSHP.js → chunk-FAKRTS3Y.js} +2 -2
- package/dist/{chunk-MZWHIAOL.js → chunk-FC3ZFEXF.js} +2 -2
- package/dist/{chunk-3PLAL2KP.js → chunk-FJ264QBP.js} +17 -9
- package/dist/chunk-FJ264QBP.js.map +1 -0
- package/dist/{chunk-7VFNGQ4V.js → chunk-FLDXEJFX.js} +2 -2
- package/dist/{chunk-TYLNWE4D.js → chunk-FNEYSTB6.js} +2 -2
- package/dist/{chunk-XHX67LX6.js → chunk-FPHU6KVI.js} +2 -2
- package/dist/{chunk-JH4FCVWJ.js → chunk-G6OFEGUR.js} +2 -2
- package/dist/{chunk-WCIDCJOQ.js → chunk-GAUS4XGN.js} +3 -3
- package/dist/{chunk-SZPPCEYT.js → chunk-GDOI4U4D.js} +2 -2
- package/dist/{chunk-63YPKHAU.js → chunk-GLB6VV3J.js} +2 -2
- package/dist/{chunk-3XVBGGF3.js → chunk-GRN4BVPM.js} +2 -2
- package/dist/{chunk-ZAP7BKTZ.js → chunk-GZMHBRIR.js} +6 -6
- package/dist/{chunk-645WOU5I.js → chunk-H7BZBSP6.js} +4 -4
- package/dist/{chunk-TXP7Q7T5.js → chunk-HN35OH2C.js} +2 -2
- package/dist/{chunk-SWZOAQUM.js → chunk-HSNV4CSW.js} +57 -57
- package/dist/{chunk-GFYFKXWZ.js → chunk-HUDPXTXW.js} +2 -2
- package/dist/{chunk-C2KOW2UQ.js → chunk-I7CWAJHX.js} +2 -2
- package/dist/{chunk-L2JQSG5M.js → chunk-I7TR2OCU.js} +2 -2
- package/dist/{chunk-5DCS4C4S.js → chunk-ICTJOOWZ.js} +4 -4
- package/dist/{chunk-NH6GZEQN.js → chunk-IF6EG22P.js} +10 -10
- package/dist/chunk-IF6EG22P.js.map +1 -0
- package/dist/{chunk-STM4T335.js → chunk-IJH6METJ.js} +2 -2
- package/dist/{chunk-6SYS5YX3.js → chunk-IJJWM2ZA.js} +2 -2
- package/dist/{chunk-3AODCBKX.js → chunk-IWDFHVPJ.js} +6 -6
- package/dist/{chunk-XHVO3CGX.js → chunk-JGS55BAS.js} +53 -2
- package/dist/chunk-JGS55BAS.js.map +1 -0
- package/dist/{chunk-L7PGPH4E.js → chunk-JJSMSS45.js} +2 -2
- package/dist/{chunk-74AY3S7U.js → chunk-JNLYHJG7.js} +4 -4
- package/dist/{chunk-OLH4XCLU.js → chunk-JXQTECMU.js} +2 -2
- package/dist/{chunk-6QOL4G76.js → chunk-KQXRVELF.js} +2 -2
- package/dist/{chunk-PJRKLB4Z.js → chunk-L5PM7B3I.js} +16 -2
- package/dist/{chunk-PJRKLB4Z.js.map → chunk-L5PM7B3I.js.map} +1 -1
- package/dist/{chunk-VGRM43X6.js → chunk-LB6HIXQC.js} +2 -2
- package/dist/{chunk-N7DVBHU3.js → chunk-LR7RW4T6.js} +3 -3
- package/dist/{chunk-AYBAC2N4.js → chunk-LWIU5BMA.js} +3 -3
- package/dist/{chunk-FZVZYU5C.js → chunk-LXN737FX.js} +2 -2
- package/dist/{chunk-7ZRRJ6RG.js → chunk-MGYZENUY.js} +2 -2
- package/dist/{chunk-YQ6SLFNZ.js → chunk-MPJDQC4G.js} +3 -3
- package/dist/{chunk-7HXZOWTR.js → chunk-N3PUGD7E.js} +2 -2
- package/dist/{chunk-EGNONTVT.js → chunk-NBEM5QEH.js} +6 -6
- package/dist/{chunk-QO5KDQGG.js → chunk-NFJWB27H.js} +20 -18
- package/dist/chunk-NFJWB27H.js.map +1 -0
- package/dist/{chunk-JF3MEIHO.js → chunk-O67H7OXJ.js} +4 -4
- package/dist/{chunk-OLHN4ZNT.js → chunk-ONIVKGNC.js} +3 -3
- package/dist/{chunk-2NLLXCJG.js → chunk-OWHERGF2.js} +2 -2
- package/dist/{chunk-I73ZSORJ.js → chunk-OXSTKCYK.js} +4 -4
- package/dist/{chunk-UFM3PJDT.js → chunk-PARM6OYL.js} +1 -1
- package/dist/chunk-PARM6OYL.js.map +1 -0
- package/dist/{chunk-VSSQIBVU.js → chunk-PJXSBXEC.js} +2 -2
- package/dist/{chunk-4B37KNMP.js → chunk-PW63SXFM.js} +2 -2
- package/dist/{chunk-TPKB7T6Z.js → chunk-Q6UZREJK.js} +2 -2
- package/dist/{chunk-X247CYL6.js → chunk-Q77SLBWT.js} +4 -4
- package/dist/{chunk-TAEJ2MRR.js → chunk-QFD7OANX.js} +62 -62
- package/dist/chunk-QFD7OANX.js.map +1 -0
- package/dist/{chunk-5K23NQRI.js → chunk-QGNZ5QPV.js} +2 -2
- package/dist/{chunk-UJDTXWMT.js → chunk-QIMGULGN.js} +2 -2
- package/dist/{chunk-E24RUQEN.js → chunk-QNIYL5SK.js} +2 -2
- package/dist/{chunk-KOY25HUB.js → chunk-QYAXMXOB.js} +2 -2
- package/dist/{chunk-J7G656MY.js → chunk-R42VUN5V.js} +4 -4
- package/dist/{chunk-LOMSBYNS.js → chunk-RPHCSMTQ.js} +309 -106
- package/dist/chunk-RPHCSMTQ.js.map +1 -0
- package/dist/{chunk-AYXRK264.js → chunk-RROFIAYI.js} +9 -9
- package/dist/{chunk-YYGZ4EIY.js → chunk-RUAIO5UA.js} +2 -2
- package/dist/{chunk-E5PVMB3I.js → chunk-SDXBR5QO.js} +2 -2
- package/dist/{chunk-OKKBOTRA.js → chunk-SLVR3U4E.js} +2 -2
- package/dist/{chunk-CUWOSRCS.js → chunk-SUKPM6DV.js} +2 -2
- package/dist/{chunk-TDCR6PQL.js → chunk-TWRPWJJT.js} +2 -2
- package/dist/{chunk-6DTIYAAN.js → chunk-UGV256H3.js} +2 -2
- package/dist/{chunk-DG4H56SK.js → chunk-UIK3U36O.js} +2 -2
- package/dist/{chunk-KOAVX2IT.js → chunk-UKIIAEJF.js} +2 -2
- package/dist/{chunk-XLEP7SS3.js → chunk-UMSH4I3E.js} +2 -2
- package/dist/{chunk-X7Y7WX73.js → chunk-UVYI6VIX.js} +1 -1
- package/dist/chunk-VA3GNAWQ.js +58 -0
- package/dist/chunk-VA3GNAWQ.js.map +1 -0
- package/dist/{chunk-4P4VLPGB.js → chunk-VECRSYQG.js} +1 -1
- package/dist/{chunk-GGI6FLO6.js → chunk-VHBGJAYC.js} +2 -2
- package/dist/{chunk-NMKETOAX.js → chunk-VSHWPOUB.js} +2 -2
- package/dist/{chunk-VC3X7XP3.js → chunk-VTZSIG6O.js} +2 -2
- package/dist/{chunk-UBN5AOLT.js → chunk-W5EO4USJ.js} +2 -2
- package/dist/{chunk-Y7427SL7.js → chunk-WCGJK4NQ.js} +4 -4
- package/dist/{chunk-4IZ6AC2U.js → chunk-WJMAWDAU.js} +2 -2
- package/dist/{chunk-JH2ALMPR.js → chunk-WR5POHQ3.js} +2 -2
- package/dist/{chunk-EHIKY2IA.js → chunk-WU5WTCH5.js} +2 -2
- package/dist/{chunk-QKXPOLQD.js → chunk-WUBGMV3G.js} +6 -6
- package/dist/{chunk-FKTMWDN2.js → chunk-WUL6LDJ4.js} +2 -2
- package/dist/{chunk-5UPOKIFP.js → chunk-XBHUMPIQ.js} +12 -12
- package/dist/{chunk-Y5ZHZKZD.js → chunk-XJ77IOAD.js} +2 -2
- package/dist/{chunk-U7HJBODU.js → chunk-XKTHJHSQ.js} +5 -5
- package/dist/{chunk-FQFMLOAC.js → chunk-XLUMO5H2.js} +20 -20
- package/dist/chunk-XLUMO5H2.js.map +1 -0
- package/dist/{chunk-JFI3ATK4.js → chunk-XMYWYJM2.js} +2 -2
- package/dist/{chunk-64S6X4IU.js → chunk-XTN54NML.js} +4 -4
- package/dist/{chunk-CVMAOPAH.js → chunk-XXBCUIYQ.js} +10 -10
- package/dist/{chunk-QOUKZ2N3.js → chunk-XXW3P3RX.js} +2 -2
- package/dist/{chunk-RWRHGE75.js → chunk-Y473XFTD.js} +2 -2
- package/dist/{chunk-VGFNTY3Y.js → chunk-YFXRLRKP.js} +2 -2
- package/dist/{chunk-DAOMWGO2.js → chunk-ZX5N5D6M.js} +4 -4
- package/dist/cli.js +121 -121
- package/dist/coding/export-okf-codegraph.js +20 -20
- package/dist/coding/pre-action-gate.js +2 -2
- package/dist/compounding/engine.js +21 -21
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +29 -29
- package/dist/connectors/codex-materialize-runner.js +19 -19
- package/dist/connectors/index.js +19 -19
- package/dist/contradiction/index.js +5 -5
- package/dist/convergence-refresh.js +21 -21
- package/dist/corpus-watermark.js +21 -21
- package/dist/deep-recall-http-glue.js +11 -11
- package/dist/deep-recall.js +2 -2
- package/dist/entity-retrieval.js +20 -20
- package/dist/event-order-recall.js +2 -2
- package/dist/explicit-capture.js +6 -6
- package/dist/external-wiki-access.js +74 -74
- package/dist/extraction-error-classification.d.ts +15 -0
- package/dist/extraction-error-classification.d.ts.map +1 -1
- package/dist/extraction-error-classification.js +7 -3
- package/dist/extraction-window-drain.d.ts +48 -0
- package/dist/extraction-window-drain.d.ts.map +1 -0
- package/dist/extraction-window-drain.js +14 -0
- package/dist/extraction.js +28 -28
- package/dist/{graph-edge-decay-2BZTY2IM.js → graph-edge-decay-3HVLMT6U.js} +5 -5
- package/dist/graph-edge-decay-3HVLMT6U.js.map +1 -0
- package/dist/graph-jsonl.js +3 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +4 -4
- package/dist/harmonic-retrieval.js +20 -20
- package/dist/harmonic-source-lookup.js +2 -2
- package/dist/index.js +209 -208
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +7 -7
- package/dist/local-llm.js +2 -2
- package/dist/location/index.js +22 -22
- package/dist/maintenance/memory-governance.js +19 -19
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +19 -19
- package/dist/maintenance/rebuild-memory-projection-runner.js +21 -21
- package/dist/maintenance/rebuild-memory-projection.js +20 -20
- package/dist/memory-browse-operations.js +74 -74
- package/dist/memory-browse.js +6 -6
- package/dist/memory-subject.js +3 -3
- package/dist/namespaces/migrate.js +20 -20
- package/dist/namespaces/search.d.ts +1 -0
- package/dist/namespaces/search.d.ts.map +1 -1
- package/dist/namespaces/search.js +11 -9
- package/dist/namespaces/storage.js +19 -19
- package/dist/offline-sync-changeset-generations.js +3 -3
- package/dist/offline-sync-embedding-generation.js +2 -2
- package/dist/offline-sync-file-io.js +2 -2
- package/dist/offline-sync-impression-drain.js +3 -3
- package/dist/offline-sync-snapshot-stream.js +8 -8
- package/dist/offline-sync-upload-staging.js +3 -3
- package/dist/offline-sync.js +9 -9
- package/dist/operator-doctor-corpus.js +22 -22
- package/dist/operator-toolkit.js +40 -40
- package/dist/orchestration/extraction-drain.d.ts +90 -0
- package/dist/orchestration/extraction-drain.d.ts.map +1 -0
- package/dist/orchestration/extraction-run-helpers.d.ts +3 -0
- package/dist/orchestration/extraction-run-helpers.d.ts.map +1 -1
- package/dist/orchestration/extraction-run.d.ts +4 -1
- package/dist/orchestration/extraction-run.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +33 -33
- package/dist/orchestration/qmd-result-resolver.d.ts +5 -0
- package/dist/orchestration/qmd-result-resolver.d.ts.map +1 -1
- package/dist/orchestration/recall-search-pipeline.d.ts.map +1 -1
- package/dist/orchestration/turn-ingestion.d.ts +3 -0
- package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
- package/dist/orchestrator.d.ts +8 -0
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +162 -161
- package/dist/qmd.js +5 -5
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +74 -74
- package/dist/recall-navigation.js +73 -73
- package/dist/recall-state-view-admission.js +6 -6
- package/dist/recall-why-service.js +6 -6
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/manifest.js +3 -3
- package/dist/{resolution-4ZEQPXUZ.js → resolution-NNYG37YB.js} +6 -6
- package/dist/resolution-NNYG37YB.js.map +1 -0
- package/dist/resume-bundles.js +30 -30
- package/dist/retrieval-agents.js +2 -2
- package/dist/salvage-envelope.js +5 -5
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +10 -10
- package/dist/secure-store/index.js +2 -2
- package/dist/semantic-consolidation.js +20 -20
- package/dist/semantic-rule-promotion.js +19 -19
- package/dist/semantic-rule-verifier.js +19 -19
- package/dist/source-agent-qualifier.js +23 -23
- package/dist/standup/build.js +19 -19
- package/dist/storage/dropped-extraction-chunk.d.ts +8 -0
- package/dist/storage/dropped-extraction-chunk.d.ts.map +1 -0
- package/dist/storage.d.ts +1 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +18 -18
- package/dist/subject-config.js +4 -4
- package/dist/summarizer.js +3 -3
- package/dist/support-passport/index.js +76 -76
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/export-okf.js +20 -20
- package/dist/types.d.ts +7 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +19 -19
- package/dist/who-knows-cli.js +20 -20
- package/dist/who-knows.js +19 -19
- package/dist/write-envelope.js +4 -4
- package/package.json +2 -2
- package/src/access-entity-principal.test.ts +190 -0
- package/src/access-http.ts +2 -2
- package/src/access-operations-batch.ts +2 -2
- package/src/access-service.ts +7 -6
- package/src/buffer-drop-extraction-chunk.test.ts +196 -0
- package/src/buffer-types.ts +65 -0
- package/src/buffer.ts +60 -62
- package/src/chat/chat-executor.ts +1 -1
- package/src/config.ts +8 -0
- package/src/extraction-error-classification.ts +23 -0
- package/src/extraction-local-failure-class.test.ts +55 -0
- package/src/extraction-window-drain.test.ts +123 -0
- package/src/extraction-window-drain.ts +110 -0
- package/src/extraction.ts +9 -9
- package/src/namespaces/search.ts +1 -1
- package/src/orchestration/extraction-drain.ts +261 -0
- package/src/orchestration/extraction-run-helpers.ts +8 -0
- package/src/orchestration/extraction-run.test.ts +83 -2
- package/src/orchestration/extraction-run.ts +5 -4
- package/src/orchestration/qmd-result-resolver.ts +26 -1
- package/src/orchestration/recall-search-pipeline.ts +11 -12
- package/src/orchestration/turn-ingestion.ts +9 -5
- package/src/orchestrator.ts +21 -0
- package/src/secure-store/secure-fs.ts +3 -1
- package/src/storage/dropped-extraction-chunk.ts +27 -0
- package/src/storage-dropped-chunk-filenames.test.ts +30 -0
- package/src/storage.ts +6 -7
- package/src/types.ts +7 -0
- package/dist/chunk-3PLAL2KP.js.map +0 -1
- package/dist/chunk-FQFMLOAC.js.map +0 -1
- package/dist/chunk-LOMSBYNS.js.map +0 -1
- package/dist/chunk-NH6GZEQN.js.map +0 -1
- package/dist/chunk-QO5KDQGG.js.map +0 -1
- package/dist/chunk-TAEJ2MRR.js.map +0 -1
- package/dist/chunk-UFM3PJDT.js.map +0 -1
- package/dist/chunk-WCBLPKG3.js.map +0 -1
- package/dist/chunk-WEK3OUGO.js.map +0 -1
- package/dist/chunk-XHVO3CGX.js.map +0 -1
- /package/dist/{auto-sync-432USQDH.js.map → auto-sync-BNCBMU6H.js.map} +0 -0
- /package/dist/{capsule-crypto-7FJQINUR.js.map → buffer-types.js.map} +0 -0
- /package/dist/{graph-edge-decay-2BZTY2IM.js.map → capsule-crypto-GWVG7LGC.js.map} +0 -0
- /package/dist/{chunk-MKE5DP3S.js.map → chunk-23ZMQONL.js.map} +0 -0
- /package/dist/{chunk-3K5IEJTK.js.map → chunk-2AV2U2SZ.js.map} +0 -0
- /package/dist/{chunk-HJ3UTGIW.js.map → chunk-2JNBPOZ2.js.map} +0 -0
- /package/dist/{chunk-5ANUG4JZ.js.map → chunk-2T6KEOUL.js.map} +0 -0
- /package/dist/{chunk-EEOYF3IB.js.map → chunk-3RJDYZJE.js.map} +0 -0
- /package/dist/{chunk-P5CUEB2Q.js.map → chunk-4QLKVZH6.js.map} +0 -0
- /package/dist/{chunk-XTBEXZFN.js.map → chunk-5SF7JOJB.js.map} +0 -0
- /package/dist/{chunk-53BLBDV6.js.map → chunk-5TRU6QQC.js.map} +0 -0
- /package/dist/{chunk-DKHX2FHI.js.map → chunk-64WHWIPL.js.map} +0 -0
- /package/dist/{chunk-TVIGN3XZ.js.map → chunk-6FRFVIKC.js.map} +0 -0
- /package/dist/{chunk-JIA435P3.js.map → chunk-6ITNEPJO.js.map} +0 -0
- /package/dist/{chunk-FGEY2AGV.js.map → chunk-7BCYAJKP.js.map} +0 -0
- /package/dist/{chunk-PSQ2P2T3.js.map → chunk-7XZ7TOLQ.js.map} +0 -0
- /package/dist/{chunk-6JEEY42N.js.map → chunk-AER3HD3B.js.map} +0 -0
- /package/dist/{chunk-POGPI5GR.js.map → chunk-AY6LO7GD.js.map} +0 -0
- /package/dist/{chunk-HXFIILGF.js.map → chunk-BFPF5N3H.js.map} +0 -0
- /package/dist/{chunk-KQAFEZQX.js.map → chunk-BUKK5SWA.js.map} +0 -0
- /package/dist/{chunk-6F5BGIAF.js.map → chunk-CNAL35D5.js.map} +0 -0
- /package/dist/{chunk-YC2C67F7.js.map → chunk-CRXGQRNA.js.map} +0 -0
- /package/dist/{chunk-WRDFYSUC.js.map → chunk-CZVNOTLR.js.map} +0 -0
- /package/dist/{chunk-VPO53QMG.js.map → chunk-D6DOLQYK.js.map} +0 -0
- /package/dist/{chunk-RGKXF4W3.js.map → chunk-E5IEI2MR.js.map} +0 -0
- /package/dist/{chunk-Z2T5BPOZ.js.map → chunk-EIYJK7OD.js.map} +0 -0
- /package/dist/{chunk-FRAL3EU4.js.map → chunk-EKPRLTAE.js.map} +0 -0
- /package/dist/{chunk-I75BWXRZ.js.map → chunk-F2RDRE7M.js.map} +0 -0
- /package/dist/{chunk-2AKIVSHP.js.map → chunk-FAKRTS3Y.js.map} +0 -0
- /package/dist/{chunk-MZWHIAOL.js.map → chunk-FC3ZFEXF.js.map} +0 -0
- /package/dist/{chunk-7VFNGQ4V.js.map → chunk-FLDXEJFX.js.map} +0 -0
- /package/dist/{chunk-TYLNWE4D.js.map → chunk-FNEYSTB6.js.map} +0 -0
- /package/dist/{chunk-XHX67LX6.js.map → chunk-FPHU6KVI.js.map} +0 -0
- /package/dist/{chunk-JH4FCVWJ.js.map → chunk-G6OFEGUR.js.map} +0 -0
- /package/dist/{chunk-WCIDCJOQ.js.map → chunk-GAUS4XGN.js.map} +0 -0
- /package/dist/{chunk-SZPPCEYT.js.map → chunk-GDOI4U4D.js.map} +0 -0
- /package/dist/{chunk-63YPKHAU.js.map → chunk-GLB6VV3J.js.map} +0 -0
- /package/dist/{chunk-3XVBGGF3.js.map → chunk-GRN4BVPM.js.map} +0 -0
- /package/dist/{chunk-ZAP7BKTZ.js.map → chunk-GZMHBRIR.js.map} +0 -0
- /package/dist/{chunk-645WOU5I.js.map → chunk-H7BZBSP6.js.map} +0 -0
- /package/dist/{chunk-TXP7Q7T5.js.map → chunk-HN35OH2C.js.map} +0 -0
- /package/dist/{chunk-SWZOAQUM.js.map → chunk-HSNV4CSW.js.map} +0 -0
- /package/dist/{chunk-GFYFKXWZ.js.map → chunk-HUDPXTXW.js.map} +0 -0
- /package/dist/{chunk-C2KOW2UQ.js.map → chunk-I7CWAJHX.js.map} +0 -0
- /package/dist/{chunk-L2JQSG5M.js.map → chunk-I7TR2OCU.js.map} +0 -0
- /package/dist/{chunk-5DCS4C4S.js.map → chunk-ICTJOOWZ.js.map} +0 -0
- /package/dist/{chunk-STM4T335.js.map → chunk-IJH6METJ.js.map} +0 -0
- /package/dist/{chunk-6SYS5YX3.js.map → chunk-IJJWM2ZA.js.map} +0 -0
- /package/dist/{chunk-3AODCBKX.js.map → chunk-IWDFHVPJ.js.map} +0 -0
- /package/dist/{chunk-L7PGPH4E.js.map → chunk-JJSMSS45.js.map} +0 -0
- /package/dist/{chunk-74AY3S7U.js.map → chunk-JNLYHJG7.js.map} +0 -0
- /package/dist/{chunk-OLH4XCLU.js.map → chunk-JXQTECMU.js.map} +0 -0
- /package/dist/{chunk-6QOL4G76.js.map → chunk-KQXRVELF.js.map} +0 -0
- /package/dist/{chunk-VGRM43X6.js.map → chunk-LB6HIXQC.js.map} +0 -0
- /package/dist/{chunk-N7DVBHU3.js.map → chunk-LR7RW4T6.js.map} +0 -0
- /package/dist/{chunk-AYBAC2N4.js.map → chunk-LWIU5BMA.js.map} +0 -0
- /package/dist/{chunk-FZVZYU5C.js.map → chunk-LXN737FX.js.map} +0 -0
- /package/dist/{chunk-7ZRRJ6RG.js.map → chunk-MGYZENUY.js.map} +0 -0
- /package/dist/{chunk-YQ6SLFNZ.js.map → chunk-MPJDQC4G.js.map} +0 -0
- /package/dist/{chunk-7HXZOWTR.js.map → chunk-N3PUGD7E.js.map} +0 -0
- /package/dist/{chunk-EGNONTVT.js.map → chunk-NBEM5QEH.js.map} +0 -0
- /package/dist/{chunk-JF3MEIHO.js.map → chunk-O67H7OXJ.js.map} +0 -0
- /package/dist/{chunk-OLHN4ZNT.js.map → chunk-ONIVKGNC.js.map} +0 -0
- /package/dist/{chunk-2NLLXCJG.js.map → chunk-OWHERGF2.js.map} +0 -0
- /package/dist/{chunk-I73ZSORJ.js.map → chunk-OXSTKCYK.js.map} +0 -0
- /package/dist/{chunk-VSSQIBVU.js.map → chunk-PJXSBXEC.js.map} +0 -0
- /package/dist/{chunk-4B37KNMP.js.map → chunk-PW63SXFM.js.map} +0 -0
- /package/dist/{chunk-TPKB7T6Z.js.map → chunk-Q6UZREJK.js.map} +0 -0
- /package/dist/{chunk-X247CYL6.js.map → chunk-Q77SLBWT.js.map} +0 -0
- /package/dist/{chunk-5K23NQRI.js.map → chunk-QGNZ5QPV.js.map} +0 -0
- /package/dist/{chunk-UJDTXWMT.js.map → chunk-QIMGULGN.js.map} +0 -0
- /package/dist/{chunk-E24RUQEN.js.map → chunk-QNIYL5SK.js.map} +0 -0
- /package/dist/{chunk-KOY25HUB.js.map → chunk-QYAXMXOB.js.map} +0 -0
- /package/dist/{chunk-J7G656MY.js.map → chunk-R42VUN5V.js.map} +0 -0
- /package/dist/{chunk-AYXRK264.js.map → chunk-RROFIAYI.js.map} +0 -0
- /package/dist/{chunk-YYGZ4EIY.js.map → chunk-RUAIO5UA.js.map} +0 -0
- /package/dist/{chunk-E5PVMB3I.js.map → chunk-SDXBR5QO.js.map} +0 -0
- /package/dist/{chunk-OKKBOTRA.js.map → chunk-SLVR3U4E.js.map} +0 -0
- /package/dist/{chunk-CUWOSRCS.js.map → chunk-SUKPM6DV.js.map} +0 -0
- /package/dist/{chunk-TDCR6PQL.js.map → chunk-TWRPWJJT.js.map} +0 -0
- /package/dist/{chunk-6DTIYAAN.js.map → chunk-UGV256H3.js.map} +0 -0
- /package/dist/{chunk-DG4H56SK.js.map → chunk-UIK3U36O.js.map} +0 -0
- /package/dist/{chunk-KOAVX2IT.js.map → chunk-UKIIAEJF.js.map} +0 -0
- /package/dist/{chunk-XLEP7SS3.js.map → chunk-UMSH4I3E.js.map} +0 -0
- /package/dist/{chunk-X7Y7WX73.js.map → chunk-UVYI6VIX.js.map} +0 -0
- /package/dist/{chunk-4P4VLPGB.js.map → chunk-VECRSYQG.js.map} +0 -0
- /package/dist/{chunk-GGI6FLO6.js.map → chunk-VHBGJAYC.js.map} +0 -0
- /package/dist/{chunk-NMKETOAX.js.map → chunk-VSHWPOUB.js.map} +0 -0
- /package/dist/{chunk-VC3X7XP3.js.map → chunk-VTZSIG6O.js.map} +0 -0
- /package/dist/{chunk-UBN5AOLT.js.map → chunk-W5EO4USJ.js.map} +0 -0
- /package/dist/{chunk-Y7427SL7.js.map → chunk-WCGJK4NQ.js.map} +0 -0
- /package/dist/{chunk-4IZ6AC2U.js.map → chunk-WJMAWDAU.js.map} +0 -0
- /package/dist/{chunk-JH2ALMPR.js.map → chunk-WR5POHQ3.js.map} +0 -0
- /package/dist/{chunk-EHIKY2IA.js.map → chunk-WU5WTCH5.js.map} +0 -0
- /package/dist/{chunk-QKXPOLQD.js.map → chunk-WUBGMV3G.js.map} +0 -0
- /package/dist/{chunk-FKTMWDN2.js.map → chunk-WUL6LDJ4.js.map} +0 -0
- /package/dist/{chunk-5UPOKIFP.js.map → chunk-XBHUMPIQ.js.map} +0 -0
- /package/dist/{chunk-Y5ZHZKZD.js.map → chunk-XJ77IOAD.js.map} +0 -0
- /package/dist/{chunk-U7HJBODU.js.map → chunk-XKTHJHSQ.js.map} +0 -0
- /package/dist/{chunk-JFI3ATK4.js.map → chunk-XMYWYJM2.js.map} +0 -0
- /package/dist/{chunk-64S6X4IU.js.map → chunk-XTN54NML.js.map} +0 -0
- /package/dist/{chunk-CVMAOPAH.js.map → chunk-XXBCUIYQ.js.map} +0 -0
- /package/dist/{chunk-QOUKZ2N3.js.map → chunk-XXW3P3RX.js.map} +0 -0
- /package/dist/{chunk-RWRHGE75.js.map → chunk-Y473XFTD.js.map} +0 -0
- /package/dist/{chunk-VGFNTY3Y.js.map → chunk-YFXRLRKP.js.map} +0 -0
- /package/dist/{chunk-DAOMWGO2.js.map → chunk-ZX5N5D6M.js.map} +0 -0
- /package/dist/{resolution-4ZEQPXUZ.js.map → extraction-window-drain.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/orchestration/extraction-run-helpers.ts","../src/orchestration/extraction-run.ts","../src/orchestration/extraction-origin-context.ts"],"sourcesContent":["import type { BufferTurn, ExtractionFailureClass, ExtractionResult, MetaState } from \"../types.js\";\nimport type { StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\n\nexport function combineExtractionAbortSignals(\n primary: AbortSignal | undefined,\n deadlineController: AbortController | undefined,\n): AbortSignal | undefined {\n if (!deadlineController) return primary;\n return primary ? AbortSignal.any([primary, deadlineController.signal]) : deadlineController.signal;\n}\n\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport function deriveTopicsFromExtraction(result: ExtractionResult): string[] {\n if (!isRecord(result)) return [];\n const topics = new Set<string>();\n const facts = Array.isArray(result.facts) ? result.facts : [];\n for (const rawFact of facts) {\n if (!isRecord(rawFact)) continue;\n const tags = Array.isArray(rawFact.tags) ? rawFact.tags : [];\n for (const tag of tags) {\n if (typeof tag === \"string\" && tag.length >= 2) topics.add(tag.toLowerCase());\n }\n if (typeof rawFact.entityRef === \"string\" && rawFact.entityRef.length >= 2) {\n topics.add(rawFact.entityRef.toLowerCase());\n }\n if (typeof rawFact.category === \"string\" && rawFact.category.length > 0) {\n topics.add(rawFact.category);\n }\n }\n const entities = Array.isArray(result.entities) ? result.entities : [];\n for (const rawEntity of entities) {\n if (!isRecord(rawEntity)) continue;\n if (typeof rawEntity.name === \"string\" && rawEntity.name.length >= 2) {\n topics.add(rawEntity.name.toLowerCase());\n }\n }\n return [...topics].slice(0, 16);\n}\n\n/** Bounded cap on persisted per-fingerprint retry-state entries (per namespace meta). */\nexport const EXTRACTION_RETRY_STATE_MAX_ENTRIES = 500;\n\nexport interface ExtractionRetryStateEntry {\n attempts: number;\n nextEligibleAtMs: number;\n firstFailedAtMs: number;\n lastFailureClass: ExtractionFailureClass;\n}\n\nexport interface ExtractionResilienceStatus {\n breaker: {\n state: \"closed\" | \"open\" | \"half_open\";\n openUntilMs: number;\n consecutiveFailures: number;\n lastReason: string;\n };\n backoffFingerprintCount: number;\n}\n\n/**\n * Pure backoff scheduler. Returns the absolute ms timestamp at which a\n * fingerprint that has failed `attempts` times becomes eligible again:\n * exponential via the configured schedule, clamped to `maxBackoffMs`, with\n * ±`jitterRatio` multiplicative jitter. `rng` is injectable for deterministic\n * tests. Never returns a timestamp before `now`.\n */\nexport function computeExtractionRetryNextEligibleMs(\n attempts: number,\n scheduleMs: readonly number[],\n maxBackoffMs: number,\n jitterRatio: number,\n now: number,\n rng: () => number = Math.random,\n): number {\n if (!Number.isFinite(attempts) || !Number.isInteger(attempts) || attempts < 1) {\n throw new RangeError(\"attempts must be a finite integer >= 1\");\n }\n if (!Number.isFinite(maxBackoffMs) || maxBackoffMs < 0) {\n throw new RangeError(\"maxBackoffMs must be a finite number >= 0\");\n }\n if (!Number.isFinite(jitterRatio) || jitterRatio < 0 || jitterRatio > 1) {\n throw new RangeError(\"jitterRatio must be a finite number in [0, 1]\");\n }\n const safeNow = Number.isFinite(now) ? now : 0;\n const cap = maxBackoffMs;\n if (!Array.isArray(scheduleMs) || scheduleMs.length === 0) {\n return safeNow + cap;\n }\n const idx = Math.min(attempts - 1, scheduleMs.length - 1);\n const step = scheduleMs[idx];\n const base = Math.min(typeof step === \"number\" && Number.isFinite(step) && step > 0 ? step : cap, cap);\n const randomValue = rng();\n if (!Number.isFinite(randomValue) || randomValue < 0 || randomValue > 1) {\n throw new RangeError(\"rng() must return a finite number in [0, 1]\");\n }\n const jitter = 1 + (randomValue * 2 - 1) * jitterRatio;\n return safeNow + Math.max(0, Math.round(base * jitter));\n}\n\n/**\n * Cap the persisted retry-state array to the newest `maxEntries` by\n * firstFailedAt. Guards invalid caps so they cannot turn `slice(-maxEntries)`\n * into an unbounded copy (AGENTS.md rule 17).\n */\nexport function capExtractionRetryStateEntries<T extends { firstFailedAt: string }>(\n entries: readonly T[],\n maxEntries: number,\n): T[] {\n if (!Number.isFinite(maxEntries) || !Number.isInteger(maxEntries) || maxEntries <= 0) return [];\n const sorted = [...entries].sort((a, b) => a.firstFailedAt.localeCompare(b.firstFailedAt));\n return sorted.slice(-maxEntries);\n}\n\n/**\n * Derive a single `sourceConnector` from a batch of turns.\n * Returns the connector ONLY when ALL turns carry the same connector.\n * Mixed tagged/untagged batches return undefined — extraction facts are\n * persisted at batch level, so attributing them to the single tagged\n * connector would falsely label facts from untagged turns.\n * Conflicting connectors (different values) also return undefined.\n */\nexport function deriveSourceConnector(turns: readonly BufferTurn[]): string | undefined {\n if (turns.length === 0) return undefined;\n const connectors = new Set<string>();\n let untaggedCount = 0;\n for (const turn of turns) {\n if (typeof turn.sourceConnector === \"string\" && turn.sourceConnector.length > 0) {\n connectors.add(turn.sourceConnector);\n } else {\n untaggedCount += 1;\n }\n }\n // All turns must agree on the same connector — no untagged turns mixed in.\n if (untaggedCount > 0) return undefined;\n return connectors.size === 1 ? [...connectors][0] : undefined;\n}\n\nexport async function runExtractionPostPersistBestEffort(\n runDeadlineAware: (\n operation: () => Promise<unknown>,\n phase: string,\n clearTimerOnError?: boolean,\n options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },\n ) => Promise<unknown>,\n stage: string,\n operation: () => Promise<unknown>,\n options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },\n): Promise<void> {\n try {\n await runDeadlineAware(operation, stage, false, {\n ignoreAbort: options?.ignoreAbort,\n ignoreDeadline: options?.ignoreDeadline,\n });\n } catch (error) {\n if (options?.propagateErrors) throw error;\n log.warn(`runExtraction: ${stage} failed after persistence (non-fatal)`, error);\n }\n}\n\n/**\n * Applies deferred-judge retention only to live, non-shadow extraction runs.\n * Replay/import paths must not synthesize live-buffer entries after persistence.\n */\nexport interface ExtractionDeferRetentionOptions {\n clearBufferAfterExtraction: boolean;\n extractionJudgeShadow: boolean;\n getDeferredCount: () => number;\n normalizedTurns: BufferTurn[];\n bufferKey: string;\n retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;\n}\n\nexport async function runExtractionDeferRetention(\n runPostPersistBestEffort: (\n stage: string,\n operation: () => Promise<unknown>,\n options?: { ignoreAbort?: boolean },\n ) => Promise<void>,\n options: ExtractionDeferRetentionOptions,\n): Promise<void> {\n await runPostPersistBestEffort(\"during_defer_retention\", async () => {\n if (options.clearBufferAfterExtraction && !options.extractionJudgeShadow) {\n const deferredCount = options.getDeferredCount();\n if (deferredCount > 0 && options.normalizedTurns.length > 0) {\n await options.retainDeferredTurns(options.bufferKey, options.normalizedTurns, 10);\n } else {\n await options.retainDeferredTurns(options.bufferKey, [], 0);\n }\n }\n });\n}\n\nexport interface ExtractionPostPersistOptions {\n result: ExtractionResult;\n storage: StorageManager;\n meta?: MetaState;\n extractionFingerprint?: string;\n shouldPersistProcessedFingerprint: boolean;\n recordProcessedExtractionFingerprint: (\n storage: StorageManager,\n fingerprint: string,\n meta: MetaState,\n ) => Promise<void>;\n runDeadlineAware: (\n operation: () => Promise<unknown>,\n phase: string,\n clearTimerOnError?: boolean,\n options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean },\n ) => Promise<unknown>;\n isDeadlineError: (error: unknown) => boolean;\n createDeadlineError: (stage: string) => Error;\n deadlineMs?: number;\n clearBufferAfterExtraction: boolean;\n runPostPersistBestEffort: (\n stage: string,\n operation: () => Promise<unknown>,\n options?: { ignoreAbort?: boolean; ignoreDeadline?: boolean; propagateErrors?: boolean },\n ) => Promise<void>;\n extractionJudgeShadow: boolean;\n getDeferredCount: () => number;\n normalizedTurns: BufferTurn[];\n bufferKey: string;\n retainDeferredTurns: (bufferKey: string, turns: BufferTurn[], max: number) => Promise<void>;\n clearBuffer: (options?: { ignoreAbort?: boolean }) => Promise<void>;\n failOnExtractionFailure: boolean;\n}\n\nexport interface ExtractionPostPersistResult {\n meta?: MetaState;\n metadataFailed: boolean;\n}\n\nexport async function runExtractionPostPersist(\n options: ExtractionPostPersistOptions,\n): Promise<ExtractionPostPersistResult> {\n let metadataFailed = false;\n let deadlineError: Error | undefined;\n const recordFailure = (stage: string, error: unknown): void => {\n metadataFailed = true;\n if (options.isDeadlineError(error) && deadlineError === undefined) {\n deadlineError = error as Error;\n }\n log.warn(`runExtraction: ${stage} failed after durable persistence; continuing with buffer clear`, error);\n };\n let meta = options.meta;\n try {\n meta ??= (await options.runDeadlineAware(\n () => options.storage.loadMeta(),\n \"during_post_persist_load_meta\",\n false,\n )) as MetaState;\n } catch (error) {\n recordFailure(\"metadata load\", error);\n }\n if (meta && options.extractionFingerprint && options.shouldPersistProcessedFingerprint) {\n try {\n await options.runDeadlineAware(\n () => options.recordProcessedExtractionFingerprint(options.storage, options.extractionFingerprint!, meta!),\n \"during_post_persist_fingerprint\",\n false,\n );\n } catch (error) {\n recordFailure(\"processed fingerprint\", error);\n }\n }\n if (meta) {\n meta.extractionCount += 1;\n meta.lastExtractionAt = new Date().toISOString();\n meta.totalMemories += Array.isArray(options.result.facts) ? options.result.facts.length : 0;\n meta.totalEntities += Array.isArray(options.result.entities) ? options.result.entities.length : 0;\n try {\n await options.runDeadlineAware(\n () => options.storage.saveMeta(meta!),\n \"during_post_persist_meta_save\",\n false,\n );\n } catch (error) {\n recordFailure(\"metadata save\", error);\n }\n }\n const runBestEffort = options.runPostPersistBestEffort;\n await runExtractionDeferRetention(runBestEffort, {\n clearBufferAfterExtraction: options.clearBufferAfterExtraction,\n extractionJudgeShadow: options.extractionJudgeShadow,\n getDeferredCount: options.getDeferredCount,\n normalizedTurns: options.normalizedTurns,\n bufferKey: options.bufferKey,\n retainDeferredTurns: options.retainDeferredTurns,\n });\n await runBestEffort(\n \"during_buffer_clear\",\n () => options.clearBuffer({ ignoreAbort: true }),\n {\n ignoreAbort: true,\n ignoreDeadline: options.failOnExtractionFailure,\n propagateErrors: options.failOnExtractionFailure,\n },\n );\n if (options.failOnExtractionFailure && typeof options.deadlineMs === \"number\" && Date.now() >= options.deadlineMs) {\n throw options.createDeadlineError(\"during_buffer_clear\");\n }\n if (deadlineError) throw deadlineError;\n return { meta, metadataFailed };\n}\n\n/**\n * Record a processed fingerprint when applicable and advance the extraction\n * liveness watermark only for a provider-backed empty success. Fingerprinted\n * imports treat the metadata save as load-bearing dedupe state; normal live\n * runs treat the stamp as diagnostic and fail open. Deadline errors always\n * propagate.\n */\nexport async function commitEmptySuccessExtraction(args: {\n storage: StorageManager;\n meta: MetaState | null;\n extractionFingerprint: string | null;\n shouldPersistProcessedFingerprint: boolean;\n hasExtractionFailure: boolean;\n extractionSkippedReason: ExtractionResult[\"extractionSkippedReason\"];\n recordProcessedExtractionFingerprint: (storage: StorageManager, fingerprint: string, meta: MetaState) => Promise<unknown>;\n runDeadlineAware: <T>(operation: () => Promise<T>, phase: string, clearTimerOnError?: boolean) => Promise<T>;\n isDeadlineError: (error: unknown) => boolean;\n}): Promise<void> {\n const {\n storage,\n meta: existingMeta,\n extractionFingerprint,\n shouldPersistProcessedFingerprint,\n hasExtractionFailure,\n extractionSkippedReason,\n recordProcessedExtractionFingerprint,\n runDeadlineAware,\n isDeadlineError,\n } = args;\n const shouldRecordFingerprint =\n extractionFingerprint !== null &&\n shouldPersistProcessedFingerprint &&\n !hasExtractionFailure;\n const shouldStampLiveness =\n !hasExtractionFailure && extractionSkippedReason === undefined;\n if (!shouldRecordFingerprint && !shouldStampLiveness) return;\n\n const metadataFailureIsFatal = shouldRecordFingerprint;\n try {\n const meta =\n existingMeta ??\n await runDeadlineAware(\n () => storage.loadMeta(),\n \"during_empty_success_liveness_load\",\n false,\n );\n if (shouldRecordFingerprint) {\n await recordProcessedExtractionFingerprint(storage, extractionFingerprint, meta);\n }\n if (shouldStampLiveness) {\n meta.extractionCount += 1;\n meta.lastExtractionAt = new Date().toISOString();\n }\n await runDeadlineAware(\n () => storage.saveMeta(meta),\n \"during_empty_success_liveness_save\",\n false,\n );\n } catch (err) {\n if (isDeadlineError(err)) throw err;\n if (metadataFailureIsFatal) throw err;\n log.warn(\"runExtraction: failed to stamp empty-success liveness watermark (non-fatal)\", err);\n }\n}\n","/**\n * Buffer → extract → persist coordinator (issue #1526, seam 15).\n * Owns runExtraction, shouldQueueExtraction, buildExtractionFingerprint,\n * normalizeExtractionFingerprintTurns and recordProcessedExtractionFingerprint.\n * The orchestrator delegates here and retains cross-subsystem routing,\n * persistence and post-write side effects via injected dependencies.\n * Extracted from orchestrator.ts without behavior changes.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { StorageManager } from \"../index.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport type { ExtractionEngine } from \"../extraction.js\";\nimport type { SmartBuffer } from \"../buffer.js\";\nimport type { ThreadingManager } from \"../threading.js\";\nimport type { BoxBuilder } from \"../boxes.js\";\nimport { resolvePrincipal, defaultNamespaceForPrincipal } from \"../namespaces/principal.js\";\nimport { resolveScopeProfilePlan, type ResolvedScopeProfilePlan } from \"../namespaces/scope-profiles.js\";\nimport { resolveCodingNamespaceOverlay } from \"../coding/coding-namespace.js\";\nimport type { CodingContext } from \"../types.js\";\nimport { deriveExtractionOriginContext, type ExtractionSourceContext } from \"./extraction-origin-context.js\";\nimport {\n resolvePresentationCapabilities,\n resolveMemoryLifecycleCapabilities,\n type GraphConstructionCapabilitySet,\n type MemoryLifecycleCapabilitySet,\n} from \"../capabilities.js\";\nimport { parseFlexibleIsoTimestamp } from \"../utils/iso-timestamp.js\";\nimport { tagPersistedMemories } from \"../location/tagging.js\";\nimport { log } from \"../logger.js\";\nimport { emitExtractionLlmFailureError, recordExtractionLlmFailure, recordExtractionLlmSuccess } from \"../extraction-llm-health.js\";\nimport type { PluginConfig, BufferTurn, ExtractionResult, MetaState, ExtractionFailureClass } from \"../types.js\";\nimport type { TierMigrationCycleSummary } from \"../recall-state.js\";\n\nexport interface ExtractionRunResult {\n status: \"completed\" | \"skipped\";\n reason?: string;\n persistedCount: number;\n durableOutputCount: number;\n postPersistMetadataFailed?: boolean;\n}\n\nexport class ExtractionDeadlineError extends Error {\n readonly stage: string;\n\n constructor(stage: string) {\n super(`replay extraction deadline exceeded (${stage})`);\n this.name = \"ExtractionDeadlineError\";\n this.stage = stage;\n }\n}\n\n/** Dependencies injected by the orchestrator. All stable references or\n * live accessors — lazy getters for anything tests reassign\n * post-construction (buffer, extraction, storageRouter, threading). */\nexport interface ExtractionRunCoordinatorDeps {\n config: PluginConfig;\n getBuffer: () => SmartBuffer;\n getExtraction: () => Pick<ExtractionEngine, \"extract\">;\n getStorageRouter: () => Pick<NamespaceStorageRouter, \"storageFor\">;\n getThreading: () => Pick<ThreadingManager, \"processTurn\" | \"updateThreadTitle\">;\n\n persistExtraction: (\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: ExtractionSourceContext,\n baseNamespace?: string,\n scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,\n sourceText?: string,\n graphCaps?: GraphConstructionCapabilitySet,\n lifecycleCaps?: MemoryLifecycleCapabilitySet\n ) => Promise<{ persistedIds: string[]; memoryPathById: Map<string, string> }>;\n\n maybeCapturePassiveCorrections: (\n turns: readonly BufferTurn[],\n opts: {\n sessionKey: string;\n principal?: string;\n namespace: string;\n bufferKey: string;\n isLiveSession: boolean;\n abortSignal?: AbortSignal;\n }\n ) => Promise<void>;\n\n resolveSelfNamespace: (sessionKey?: string) => string;\n getCodingContextForSession: (sessionKey: string) => CodingContext | null;\n applyCodingNamespaceOverlay: (sessionKey: string, namespace: string) => string;\n boxBuilderFor: (storage: StorageManager) => Pick<BoxBuilder, \"onExtraction\">;\n appendPersistedThreadEpisodes: (threadId: string, ids: string[]) => Promise<void>;\n maybeScheduleConsolidation: (nonZero: boolean) => void;\n requestQmdMaintenance: () => void;\n runTierMigrationCycle: (\n storage: StorageManager,\n trigger: \"extraction\" | \"maintenance\" | \"manual\",\n options?: {\n dryRun?: boolean;\n limitOverride?: number;\n force?: boolean;\n }\n ) => Promise<TierMigrationCycleSummary>;\n getLastPersistExtractionDeferredCount: () => number;\n recordProcessedExtractionFingerprint: (\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>\n ) => Promise<void>;\n}\n\n// Recall/extraction abort helpers live in orchestrator-helpers.ts since\n// #1526 seam 25; this file previously carried duplicate copies\n// (AGENTS.md rule 8 — no duplicated helpers).\nimport { raceRecallAbort, throwIfRecallAborted } from \"./orchestrator-helpers.js\";\nimport {\n capExtractionRetryStateEntries,\n combineExtractionAbortSignals,\n commitEmptySuccessExtraction,\n computeExtractionRetryNextEligibleMs,\n deriveSourceConnector,\n deriveTopicsFromExtraction,\n runExtractionPostPersist,\n runExtractionPostPersistBestEffort,\n EXTRACTION_RETRY_STATE_MAX_ENTRIES,\n} from \"./extraction-run-helpers.js\";\nimport type { ExtractionResilienceStatus, ExtractionRetryStateEntry } from \"./extraction-run-helpers.js\";\n\nexport {\n capExtractionRetryStateEntries,\n computeExtractionRetryNextEligibleMs,\n deriveSourceConnector,\n deriveTopicsFromExtraction,\n};\nexport type { ExtractionResilienceStatus };\n\n/**\n * Coordinates the extraction run pipeline. Holds the dedupe fingerprint\n * cache (`recentExtractionFingerprints`) and delegates all side effects\n * to injected orchestrator methods.\n */\nexport class ExtractionRunCoordinator {\n private readonly recentExtractionFingerprints = new Map<string, number>();\n // Per-fingerprint extraction retry/backoff state (extraction hot-loop\n // hardening). Outer key = namespace, inner key = fingerprint. Hydrated lazily\n // from namespace-scoped meta so the hot path is a Map lookup; persisted back\n // to meta on change (restart-safe, cross-process coherent via the shared\n // meta.json). The breaker below is intentionally per-process in-memory\n // (mirrors local-llm.cooldownUntilMs); a restart clears it but the persisted\n // backoff still throttles, so a restart can't resurrect the hot loop.\n private readonly extractionRetryState = new Map<string, Map<string, ExtractionRetryStateEntry>>();\n private readonly hydratedRetryNamespaces = new Set<string>();\n private providerBreaker: {\n consecutiveFailures: number;\n openUntilMs: number;\n state: \"closed\" | \"open\" | \"half_open\";\n lastReason: string;\n } = { consecutiveFailures: 0, openUntilMs: 0, state: \"closed\", lastReason: \"\" };\n\n constructor(private readonly deps: ExtractionRunCoordinatorDeps) {}\n\n private get config(): PluginConfig {\n return this.deps.config;\n }\n\n // -------------------------------------------------------------------------\n // Source-valid-at helpers (moved from orchestrator.ts module scope)\n // -------------------------------------------------------------------------\n\n private latestSourceValidAtFromTurns(turns: readonly BufferTurn[]): string | undefined {\n let latestMs: number | null = null;\n for (const turn of turns) {\n if (turn.extractionContextOnly === true) continue;\n if (typeof turn.sourceValidAt !== \"string\") continue;\n const parsed = parseFlexibleIsoTimestamp(turn.sourceValidAt.trim());\n if (parsed === null) continue;\n if (latestMs === null || parsed > latestMs) {\n latestMs = parsed;\n }\n }\n return latestMs === null ? undefined : new Date(latestMs).toISOString();\n }\n\n // -------------------------------------------------------------------------\n // Extraction dedupe fingerprint helpers\n // -------------------------------------------------------------------------\n\n normalizeExtractionFingerprintTurns(turns: BufferTurn[]): string[] {\n if (!Array.isArray(turns) || turns.length === 0) return [];\n return turns\n .filter((turn) => turn.role === \"user\" || turn.role === \"assistant\")\n .map((turn) => {\n if (typeof turn.turnFingerprint === \"string\" && turn.turnFingerprint.length > 0) {\n return `fp:${turn.turnFingerprint}`;\n }\n return `${turn.role}:${(turn.content ?? \"\").replace(/\\s+/g, \" \").trim().slice(0, this.config.extractionMaxTurnChars)}`;\n })\n .filter((value) => value.length > 0);\n }\n\n buildExtractionFingerprint(turns: BufferTurn[], bufferKey: string): string | null {\n const normalized = this.normalizeExtractionFingerprintTurns(turns).join(\"\\n\");\n if (!normalized) return null;\n return createHash(\"sha256\").update(`${bufferKey}\\n${normalized}`).digest(\"hex\");\n }\n\n shouldQueueExtraction(turns: BufferTurn[], options: { commit?: boolean; bufferKey?: string } = {}): boolean {\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);\n if (!lifecycleCaps.extractionDedupe) return true;\n if (!Array.isArray(turns) || turns.length === 0) return false;\n\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const fingerprint = this.buildExtractionFingerprint(turns, bufferKey);\n if (!fingerprint) return false;\n const now = Date.now();\n const seenAt = this.recentExtractionFingerprints.get(fingerprint);\n if (seenAt && now - seenAt < this.config.extractionDedupeWindowMs) {\n log.debug(\"extraction dedupe: skipped duplicate buffered turn set\");\n return false;\n }\n\n if (options.commit !== false) {\n this.recentExtractionFingerprints.set(fingerprint, now);\n }\n // Keep this cache bounded to avoid unbounded growth.\n if (options.commit !== false && this.recentExtractionFingerprints.size > 200) {\n const entries = Array.from(this.recentExtractionFingerprints.entries()).sort((a, b) => a[1] - b[1]);\n for (const [key] of entries.slice(0, entries.length - 200)) {\n this.recentExtractionFingerprints.delete(key);\n }\n }\n\n return true;\n }\n\n // -------------------------------------------------------------------------\n // Processed-fingerprint recording\n // -------------------------------------------------------------------------\n\n async recordProcessedExtractionFingerprint(\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>\n ): Promise<void> {\n const meta = preloadedMeta ?? (await storage.loadMeta());\n const observedAt = new Date().toISOString();\n const seen = new Map(\n (meta.processedExtractionFingerprints ?? []).map((entry) => [entry.fingerprint, entry.observedAt])\n );\n seen.set(fingerprint, observedAt);\n meta.processedExtractionFingerprints = Array.from(seen.entries())\n .map(([value, at]) => ({ fingerprint: value, observedAt: at }))\n .sort((left, right) => left.observedAt.localeCompare(right.observedAt))\n .slice(-500);\n if (!preloadedMeta) {\n await storage.saveMeta(meta);\n }\n }\n\n // -------------------------------------------------------------------------\n // Extraction retry/backoff + circuit breaker (extraction hot-loop hardening)\n // -------------------------------------------------------------------------\n\n /** Lazily hydrate the in-memory retry-state mirror for a namespace from meta.\n * One-time per namespace per coordinator; the hot path is then a Map lookup.\n * Cross-process coherence: a fresh coordinator hydrates from the shared\n * meta.json, so a failure persisted by another process is honored here. */\n private hydrateRetryStateFromMeta(namespace: string, meta: MetaState): void {\n if (this.hydratedRetryNamespaces.has(namespace)) return;\n this.hydratedRetryNamespaces.add(namespace);\n const nsMap = this.extractionRetryState.get(namespace) ?? new Map<string, ExtractionRetryStateEntry>();\n for (const entry of meta.extractionRetryState ?? []) {\n const nextEligibleAtMs = Date.parse(entry.nextEligibleAt);\n const firstFailedAtMs = Date.parse(entry.firstFailedAt);\n nsMap.set(entry.fingerprint, {\n attempts: entry.attempts,\n nextEligibleAtMs: Number.isFinite(nextEligibleAtMs) ? nextEligibleAtMs : 0,\n firstFailedAtMs: Number.isFinite(firstFailedAtMs) ? firstFailedAtMs : Date.now(),\n lastFailureClass: entry.lastFailureClass,\n });\n }\n this.extractionRetryState.set(namespace, nsMap);\n }\n\n private logBreakerTransition(state: \"closed\" | \"open\" | \"half_open\"): void {\n // Once per state change (not per attempt) — AGENTS.md observability rule.\n log.warn(\"extraction: provider circuit breaker transition\", {\n state,\n consecutiveFailures: this.providerBreaker.consecutiveFailures,\n lastReason: this.providerBreaker.lastReason,\n openUntilMs: this.providerBreaker.openUntilMs,\n });\n }\n\n /** True while the breaker suppresses non-forced attempts. Flips an expired\n * `open` breaker to `half_open`, which allows exactly one probe (the next\n * non-forced attempt) because the extraction queue is a serial drain. */\n private isProviderBreakerOpen(now: number): boolean {\n if (now < this.providerBreaker.openUntilMs) return true;\n if (this.providerBreaker.state === \"open\") {\n this.providerBreaker.state = \"half_open\";\n this.logBreakerTransition(\"half_open\");\n }\n return false;\n }\n\n private onProviderFailure(cls: ExtractionFailureClass, now: number): void {\n this.providerBreaker.consecutiveFailures += 1;\n const trip =\n cls === \"auth_config\" ||\n // A failed half-open probe re-opens immediately (standard breaker\n // semantics). Without this, an auth_config-opened breaker (which trips\n // below the threshold) would get stuck half_open after a transient\n // probe failure and stop suppressing (cursor review).\n this.providerBreaker.state === \"half_open\" ||\n this.providerBreaker.consecutiveFailures >= this.config.extractionBreakerFailureThreshold;\n if (!trip) return;\n const cooldown =\n cls === \"auth_config\"\n ? this.config.extractionBreakerAuthCooldownMs\n : this.config.extractionBreakerCooldownMs;\n this.providerBreaker.openUntilMs = now + Math.max(0, cooldown);\n this.providerBreaker.lastReason = cls;\n if (this.providerBreaker.state !== \"open\") {\n this.providerBreaker.state = \"open\";\n this.logBreakerTransition(\"open\");\n }\n }\n\n private resetProviderBreakerOnSuccess(): void {\n const wasDisturbed =\n this.providerBreaker.state !== \"closed\" ||\n this.providerBreaker.consecutiveFailures > 0 ||\n this.providerBreaker.openUntilMs > 0;\n if (!wasDisturbed) return;\n const wasOpen = this.providerBreaker.state !== \"closed\";\n this.providerBreaker.consecutiveFailures = 0;\n this.providerBreaker.openUntilMs = 0;\n this.providerBreaker.lastReason = \"\";\n this.providerBreaker.state = \"closed\";\n if (wasOpen) this.logBreakerTransition(\"closed\");\n }\n\n /** Rebuild `meta.extractionRetryState` from the in-memory namespace mirror,\n * bounded to the newest entries, and prune the mirror to match. */\n private persistRetryStateToMeta(namespace: string, meta: MetaState): void {\n const nsMap = this.extractionRetryState.get(namespace);\n const entries = nsMap\n ? Array.from(nsMap.entries()).map(([fingerprint, st]) => ({\n fingerprint,\n attempts: st.attempts,\n nextEligibleAt: new Date(st.nextEligibleAtMs).toISOString(),\n firstFailedAt: new Date(st.firstFailedAtMs).toISOString(),\n lastFailureClass: st.lastFailureClass,\n }))\n : [];\n const capped = capExtractionRetryStateEntries(entries, EXTRACTION_RETRY_STATE_MAX_ENTRIES);\n meta.extractionRetryState = capped;\n if (nsMap && capped.length < nsMap.size) {\n const kept = new Set(capped.map((e) => e.fingerprint));\n for (const key of Array.from(nsMap.keys())) {\n if (!kept.has(key)) nsMap.delete(key);\n }\n }\n }\n /** Record an extraction failure into per-fingerprint backoff state + breaker,\n * persisting to namespace meta. Fail-open: never throws upward. */\n private async recordExtractionFailure(\n storage: StorageManager,\n namespace: string,\n fingerprint: string,\n cls: ExtractionFailureClass,\n meta: MetaState,\n now: number,\n ): Promise<void> {\n try {\n this.hydrateRetryStateFromMeta(namespace, meta);\n const nsMap = this.extractionRetryState.get(namespace) ?? new Map<string, ExtractionRetryStateEntry>();\n const prev = nsMap.get(fingerprint);\n const attempts = (prev?.attempts ?? 0) + 1;\n const firstFailedAtMs = prev?.firstFailedAtMs ?? now;\n let nextEligibleAtMs: number;\n if (cls === \"parse_empty\" && attempts > this.config.extractionParseEmptyMaxAttempts) {\n // parse_empty exhausted its attempt budget → long-park (still never\n // marked processed). A dead gateway also yields unparseable output.\n nextEligibleAtMs = now + Math.max(0, this.config.extractionRetryMaxBackoffMs);\n } else {\n nextEligibleAtMs = computeExtractionRetryNextEligibleMs(\n attempts,\n this.config.extractionRetryScheduleMs,\n this.config.extractionRetryMaxBackoffMs,\n this.config.extractionRetryJitterRatio,\n now,\n );\n }\n nsMap.set(fingerprint, { attempts, nextEligibleAtMs, firstFailedAtMs, lastFailureClass: cls });\n this.extractionRetryState.set(namespace, nsMap);\n this.onProviderFailure(cls, now);\n this.persistRetryStateToMeta(namespace, meta);\n await storage.saveMeta(meta);\n } catch (err) {\n // Fail-open: recording failure state must never crash observe/recall.\n log.warn(\"runExtraction: failed to record extraction retry state (non-fatal)\", err);\n }\n }\n\n /** Delete a fingerprint's retry entry from the mirror + meta. Returns whether\n * meta changed (so the caller can decide to persist). Does not touch the\n * breaker — callers pair this with `resetProviderBreakerOnSuccess`. */\n private clearExtractionRetryEntry(namespace: string, fingerprint: string, meta: MetaState): boolean {\n const nsMap = this.extractionRetryState.get(namespace);\n if (!nsMap?.has(fingerprint)) return false;\n nsMap.delete(fingerprint);\n this.persistRetryStateToMeta(namespace, meta);\n return true;\n }\n\n /** Live in-process resilience snapshot (breaker + backoff population). */\n getExtractionResilienceStatus(): ExtractionResilienceStatus {\n let backoffFingerprintCount = 0;\n for (const nsMap of this.extractionRetryState.values()) {\n backoffFingerprintCount += nsMap.size;\n }\n return {\n breaker: {\n state: this.providerBreaker.state,\n openUntilMs: this.providerBreaker.openUntilMs,\n consecutiveFailures: this.providerBreaker.consecutiveFailures,\n lastReason: this.providerBreaker.lastReason,\n },\n backoffFingerprintCount,\n };\n }\n\n // -------------------------------------------------------------------------\n // Main extraction pipeline\n // -------------------------------------------------------------------------\n\n async runExtraction(\n turns: BufferTurn[],\n options: {\n clearBufferAfterExtraction?: boolean;\n clearMatchingTurns?: boolean;\n skipCharThreshold?: boolean;\n skipUserTurnThreshold?: boolean;\n deadlineMs?: number;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n failOnExtractionFailure?: boolean;\n /** Write-rate commit boundary, after persistence returns. */\n onDurableCommit?: () => void;\n /** Disarm preemption once persistence can no longer be aborted. */\n onBeforePersist?: () => void;\n /**\n * Explicit namespace override for the write path (#460). When set, this\n * is the namespace where extraction writes go instead of the one derived\n * from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.\n * The resolved `principal` is still threaded into memory metadata for\n * provenance; only the storage target is overridden.\n */\n writeNamespaceOverride?: string;\n /**\n * Pin the provenance principal instead of deriving it from\n * `resolvePrincipal(sessionKey)`. When set, this is the identity an\n * access surface already authenticated; used so observed-turn provenance\n * is correct even though `turn.sessionKey` is the original key.\n */\n principalOverride?: string;\n /**\n * Access scope resolution may already have selected a profile while the\n * session context remains intentionally unbound. Reuse that plan for\n * persistence instead of deriving it from shared session state.\n */\n scopeProfileWritePlan?: ResolvedScopeProfilePlan | null;\n /**\n * Force the extractor call, bypassing the retry-backoff / circuit-breaker\n * gate (extraction hot-loop hardening). Set by explicit flush paths.\n */\n forceExtractionAttempt?: boolean;\n } = {}\n ): Promise<ExtractionRunResult> {\n log.debug(`running extraction on ${turns.length} turns`);\n const clearBufferAfterExtraction = options.clearBufferAfterExtraction ?? true;\n const clearMatchingTurns = options.clearMatchingTurns === true;\n const skipCharThreshold = options.skipCharThreshold ?? false;\n const skipUserTurnThreshold = options.skipUserTurnThreshold ?? false;\n const deadlineMs =\n typeof options.deadlineMs === \"number\" && Number.isFinite(options.deadlineMs) ? options.deadlineMs : undefined;\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const throwIfDeadlineExceeded = (stage: string): void => {\n if (typeof deadlineMs === \"number\" && Date.now() >= deadlineMs) {\n throw new ExtractionDeadlineError(stage);\n }\n };\n const throwIfAborted = (stage: string): void => {\n throwIfRecallAborted(options.abortSignal, `extraction aborted (${stage})`);\n };\n const runPassiveCapture = async (\n captureTurns: readonly BufferTurn[],\n captureOptions: {\n sessionKey: string;\n principal?: string;\n namespace: string;\n bufferKey: string;\n isLiveSession: boolean;\n abortSignal?: AbortSignal;\n },\n ): Promise<void> => {\n const deadlineController =\n typeof deadlineMs === \"number\" && Number.isFinite(deadlineMs) ? new AbortController() : undefined;\n const captureSignal = combineExtractionAbortSignals(captureOptions.abortSignal ?? options.abortSignal,\n deadlineController);\n let deadlineTimer: NodeJS.Timeout | undefined;\n if (deadlineController && typeof deadlineMs === \"number\") {\n const scheduleDeadlineAbort = (): void => {\n const remainingMs = deadlineMs - Date.now();\n if (remainingMs <= 0) {\n deadlineController.abort();\n return;\n }\n deadlineTimer = setTimeout(\n () => {\n if (Date.now() >= deadlineMs) {\n deadlineController.abort();\n } else {\n scheduleDeadlineAbort();\n }\n },\n Math.min(remainingMs, 2_147_483_647),\n );\n };\n scheduleDeadlineAbort();\n }\n try {\n await raceRecallAbort(\n this.deps.maybeCapturePassiveCorrections(captureTurns, {\n ...captureOptions,\n ...(captureSignal ? { abortSignal: captureSignal } : {}),\n }),\n captureSignal,\n \"extraction aborted (during_passive_capture)\",\n );\n } catch (error) {\n if (typeof deadlineMs === \"number\" && Date.now() >= deadlineMs) {\n throw new ExtractionDeadlineError(\"during_passive_capture\");\n }\n throw error;\n } finally {\n if (deadlineTimer) clearTimeout(deadlineTimer);\n }\n };\n const clearBuffer = async (clearOptions?: { ignoreAbort?: boolean }) => {\n options.onBeforePersist?.();\n if (clearOptions?.ignoreAbort !== true) {\n throwIfDeadlineExceeded(\"before_clear_buffer\");\n throwIfAborted(\"before_clear_buffer\");\n }\n if (clearBufferAfterExtraction) {\n await this.deps\n .getBuffer()\n .clearAfterExtraction(bufferKey, turns, clearMatchingTurns ? { allowNonPrefix: true } : undefined);\n }\n };\n\n // Skip extraction for cron job sessions - these are system operations, not user conversations\n const sessionKey = turns[0]?.sessionKey ?? \"\";\n if (sessionKey.includes(\":cron:\")) {\n log.debug(`skipping extraction for cron session: ${sessionKey}`);\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"cron_session\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n\n const normalizedTurns = turns\n .filter((t) => (t.role === \"user\" || t.role === \"assistant\") && typeof t.content === \"string\")\n .map((t) => ({\n ...t,\n content: t.content.trim().slice(0, this.config.extractionMaxTurnChars),\n }))\n .filter((t) => t.content.length > 0);\n const targetTurns = normalizedTurns.filter((turn) => turn.extractionContextOnly !== true);\n if (targetTurns.length === 0) {\n log.debug(\"skipping extraction: no non-context turns after normalization\");\n // Context-only turns may still contain corrections (review: \"context-only\n // turns skip capture\"). Scan normalizedTurns before clearing the buffer.\n if (normalizedTurns.length > 0) {\n throwIfDeadlineExceeded(\"before_context_only_capture\");\n const capturePrincipal =\n typeof options.principalOverride === \"string\" && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const captureNamespace =\n typeof options.writeNamespaceOverride === \"string\" && options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : this.deps.resolveSelfNamespace(sessionKey);\n await runPassiveCapture(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal: capturePrincipal,\n namespace: captureNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n });\n throwIfDeadlineExceeded(\"before_context_only_clear\");\n }\n await clearBuffer();\n return { status: \"skipped\", reason: \"empty_normalized_turns\", persistedCount: 0, durableOutputCount: 0 };\n }\n const sourceValidAt = this.latestSourceValidAtFromTurns(targetTurns);\n throwIfDeadlineExceeded(\"before_extract\");\n throwIfAborted(\"before_extract\");\n\n const userTurns = targetTurns.filter((t) => t.role === \"user\");\n const totalChars = targetTurns.reduce((sum, t) => sum + t.content.length, 0);\n const belowCharThreshold = totalChars < this.config.extractionMinChars;\n const belowUserTurnThreshold = !skipUserTurnThreshold && userTurns.length < this.config.extractionMinUserTurns;\n if ((!skipCharThreshold && belowCharThreshold) || belowUserTurnThreshold) {\n log.debug(`skipping extraction: below threshold (totalChars=${totalChars}, userTurns=${userTurns.length})`);\n // Passive correction capture runs even when extraction is skipped for\n // being below the char/user-turn threshold (review: \"skipped extraction\n // skips capture\"). A short correction like \"stop using Vim\" is under\n // extractionMinChars but is exactly the high-value case this feature\n // exists for. The write namespace resolves through the SAME scope-profile\n // plan as the full extraction path so corrections target the active\n // profile's write layer, not just resolveSelfNamespace (review:\n // \"below-threshold wrong namespace\"). The ACL in passiveCorrectionService\n // authorizes the actual plan/apply.\n {\n const capturePrincipal =\n typeof options.principalOverride === \"string\" && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const captureWO =\n typeof options.writeNamespaceOverride === \"string\" && options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : undefined;\n const captureCodingCtx = sessionKey ? this.deps.getCodingContextForSession(sessionKey) : null;\n const captureCodingOv = resolveCodingNamespaceOverlay(\n captureCodingCtx,\n this.config.codingMode,\n this.config.defaultNamespace\n );\n const captureScopePlan = resolveScopeProfilePlan({\n config: this.config,\n principal: capturePrincipal,\n codingContext: captureCodingCtx,\n codingOverlay: captureCodingOv,\n });\n const captureNamespace =\n captureWO ?? captureScopePlan?.writeNamespace ?? this.deps.resolveSelfNamespace(sessionKey);\n await runPassiveCapture(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal: capturePrincipal,\n namespace: captureNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n });\n }\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"below_threshold\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n\n // Provenance principal honours the access-surface override (#1495 thread 1,\n // mirroring the recall path's `principalOverride`, issue #570 PR 4). Access\n // surfaces that authenticated the caller at the transport layer pass their\n // resolved principal so provenance uses the SAME identity the surface\n // authorized, instead of `resolvePrincipal(sessionKey)` — which on a\n // namespace-prefixed key would collapse to `default`. The ORIGINAL,\n // un-prefixed session key still drives threading.\n const principal =\n typeof options.principalOverride === \"string\" && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n // Write path — explicit callers still win. Otherwise, an active hosted\n // scope profile owns the extraction write target so hook-captured turns land\n // in the same layer that profile recall searches. Without a profile, preserve\n // the existing coding-agent overlay behavior (issue #569).\n const explicitWriteNamespace =\n typeof options.writeNamespaceOverride === \"string\" && options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : undefined;\n const codingContextForWrite = sessionKey ? this.deps.getCodingContextForSession(sessionKey) : null;\n const codingOverlayForWrite = resolveCodingNamespaceOverlay(\n codingContextForWrite,\n this.config.codingMode,\n this.config.defaultNamespace\n );\n const scopeProfileGatePlan =\n options.scopeProfileWritePlan !== undefined\n ? options.scopeProfileWritePlan\n : resolveScopeProfilePlan({\n config: this.config,\n principal,\n codingContext: codingContextForWrite,\n codingOverlay: codingOverlayForWrite,\n });\n const scopeProfileWritePlan =\n explicitWriteNamespace && options.scopeProfileWritePlan === undefined\n ? null\n : scopeProfileGatePlan;\n if (scopeProfileWritePlan) {\n const selectedLayer = scopeProfileWritePlan.layers.find((layer) => layer.id === scopeProfileWritePlan.writeLayer);\n const writeNamespaceReadable = scopeProfileWritePlan.readNamespaces.includes(\n scopeProfileWritePlan.writeNamespace\n );\n if (!selectedLayer?.writable || !writeNamespaceReadable) {\n log.warn(\n `runExtraction: skipping scope profile ${scopeProfileWritePlan.profileId} because write layer ${scopeProfileWritePlan.writeLayer} is not writable inside the profile read stack`\n );\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"scope_profile_no_writable_layer\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n }\n const selfNamespace =\n explicitWriteNamespace ??\n scopeProfileWritePlan?.writeNamespace ??\n this.deps.applyCodingNamespaceOverlay(sessionKey, defaultNamespaceForPrincipal(principal, this.config));\n const extractionDeadlineController =\n typeof deadlineMs === \"number\" && Number.isFinite(deadlineMs)\n ? new AbortController()\n : undefined;\n const extractionAbortSignal = extractionDeadlineController\n ? options.abortSignal\n ? AbortSignal.any([options.abortSignal, extractionDeadlineController.signal])\n : extractionDeadlineController.signal\n : options.abortSignal;\n let extractionDeadlineTimer: NodeJS.Timeout | undefined;\n const clearExtractionDeadlineTimer = (): void => {\n if (extractionDeadlineTimer) {\n clearTimeout(extractionDeadlineTimer);\n extractionDeadlineTimer = undefined;\n }\n };\n const runDeadlineAware = async <T>(\n operation: () => Promise<T>,\n phase: string,\n clearTimerOnError = true,\n options: { ignoreAbort?: boolean; ignoreDeadline?: boolean } = {},\n ): Promise<T> => {\n const operationSignal = options.ignoreAbort ? undefined : extractionAbortSignal;\n try {\n if (!options.ignoreDeadline && typeof deadlineMs === \"number\" && Date.now() >= deadlineMs) {\n throwIfDeadlineExceeded(phase);\n }\n if (operationSignal?.aborted) {\n throwIfAborted(phase);\n }\n return await raceRecallAbort(\n operation(),\n operationSignal,\n `extraction aborted (${phase})`,\n );\n } catch (error) {\n if (clearTimerOnError) clearExtractionDeadlineTimer();\n if (!options.ignoreDeadline && typeof deadlineMs === \"number\" && Date.now() >= deadlineMs) {\n throw new ExtractionDeadlineError(phase);\n }\n throw error;\n }\n };\n if (extractionDeadlineController && typeof deadlineMs === \"number\") {\n const deadline = deadlineMs;\n const maxTimerDelayMs = 2_147_483_647;\n const scheduleDeadlineAbort = (): void => {\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n extractionDeadlineController.abort();\n return;\n }\n extractionDeadlineTimer = setTimeout(() => {\n if (Date.now() >= deadline) {\n extractionDeadlineController.abort();\n } else {\n scheduleDeadlineAbort();\n }\n }, Math.min(remainingMs, maxTimerDelayMs));\n };\n scheduleDeadlineAbort();\n }\n const storage = await runDeadlineAware(\n () => this.deps.getStorageRouter().storageFor(selfNamespace),\n \"during_storage\",\n );\n const shouldPersistProcessedFingerprint = targetTurns.some((turn) => turn.persistProcessedFingerprint === true);\n const extractionFingerprint = this.buildExtractionFingerprint(targetTurns, bufferKey);\n let meta = extractionFingerprint && shouldPersistProcessedFingerprint\n ? await runDeadlineAware(() => storage.loadMeta(), \"during_load_meta\")\n : null;\n if (\n extractionFingerprint &&\n shouldPersistProcessedFingerprint &&\n (meta?.processedExtractionFingerprints ?? []).some((entry) => entry.fingerprint === extractionFingerprint)\n ) {\n await runDeadlineAware(() => clearBuffer(), \"during_clear_buffer\");\n clearExtractionDeadlineTimer();\n return {\n status: \"skipped\",\n reason: \"processed_fingerprint\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n\n // Extraction retry/backoff + circuit-breaker gate (extraction hot-loop\n // hardening). Suppresses re-attempts of a recently-failed fingerprint and\n // short-circuits every fingerprint while the provider breaker is open, so a\n // failing LLM endpoint is not hammered once per observe. Forced flushes and\n // fail-closed callers bypass the gate (rule 18) but still record failures.\n // On a suppressed attempt the buffer is deliberately NOT cleared, so no\n // extractable turn is dropped — it is retried after cooldown/nextEligibleAt.\n const forcedExtractionAttempt =\n options.failOnExtractionFailure === true || options.forceExtractionAttempt === true;\n // Resolve the gate through the shared lifecycle capability plan (issue\n // #1523) rather than reading the raw config flag at each call site.\n const extractionRetryEnabled = resolveMemoryLifecycleCapabilities(this.config).extractionRetry;\n if (extractionFingerprint && !forcedExtractionAttempt && extractionRetryEnabled) {\n try {\n meta ??= await runDeadlineAware(() => storage.loadMeta(), \"during_retry_gate\");\n this.hydrateRetryStateFromMeta(selfNamespace, meta);\n const nowMs = Date.now();\n let suppressReason: \"provider_circuit_open\" | \"extraction_backoff\" | null = null;\n if (this.isProviderBreakerOpen(nowMs)) {\n suppressReason = \"provider_circuit_open\";\n } else {\n const st = this.extractionRetryState.get(selfNamespace)?.get(extractionFingerprint);\n if (st && nowMs < st.nextEligibleAtMs) suppressReason = \"extraction_backoff\";\n }\n if (suppressReason) {\n // Passive correction capture is local and must not be delayed by a\n // provider cooldown. It remains fail-open.\n try {\n await runDeadlineAware(\n () => runPassiveCapture(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal,\n namespace: selfNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n }),\n \"during_passive_capture\",\n );\n } catch (captureErr) {\n if (captureErr instanceof ExtractionDeadlineError) throw captureErr;\n log.warn(\"runExtraction: passive correction capture failed on suppressed attempt (non-fatal)\", captureErr);\n }\n clearExtractionDeadlineTimer();\n return { status: \"skipped\", reason: suppressReason, persistedCount: 0, durableOutputCount: 0 };\n }\n } catch (err) {\n if (err instanceof ExtractionDeadlineError) throw err;\n // Fail-open: a gate error must never block extraction.\n log.warn(\"runExtraction: extraction retry gate check failed; proceeding (fail-open)\", err);\n }\n }\n\n // Pass existing entity names so the LLM can reuse them instead of inventing variants.\n const existingEntities = await runDeadlineAware(\n () => storage.listEntityNames(),\n \"during_list_entity_names\",\n );\n let result: ExtractionResult;\n try {\n result = await raceRecallAbort(\n this.deps.getExtraction().extract(normalizedTurns, existingEntities, extractionAbortSignal),\n extractionAbortSignal,\n \"extraction aborted (during_extract)\",\n );\n } catch (error) {\n clearExtractionDeadlineTimer();\n if (typeof deadlineMs === \"number\" && Date.now() >= deadlineMs) {\n throw new ExtractionDeadlineError(\"during_extract\");\n }\n throw error;\n }\n try {\n throwIfDeadlineExceeded(\"before_persist\");\n throwIfAborted(\"before_persist\");\n\n // Defensive: validate extraction result before processing. Explicit\n // fail-closed callers, such as flush-plan import, must not observe\n // malformed extractor output as a successful skip.\n if (!result) {\n log.warn(\"runExtraction: extraction returned null/undefined\");\n if (options.failOnExtractionFailure) {\n throw new Error(\"extraction failed: invalid_extraction_result\");\n }\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"invalid_extraction_result\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n const invalidExtractionResultFields = [\n [\"facts\", result.facts],\n [\"entities\", result.entities],\n [\"questions\", result.questions],\n [\"profileUpdates\", result.profileUpdates],\n ]\n .filter(([, value]) => !Array.isArray(value))\n .map(([field]) => field);\n if (invalidExtractionResultFields.length > 0) {\n log.warn(\"runExtraction: extraction returned invalid collection fields\", {\n invalidFields: invalidExtractionResultFields,\n resultKeys: typeof result === \"object\" && result !== null ? Object.keys(result) : [],\n });\n if (options.failOnExtractionFailure) {\n throw new Error(\"extraction failed: invalid_extraction_result\");\n }\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"invalid_extraction_result\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n const extractionFailure =\n typeof result.extractionFailure === \"string\" && result.extractionFailure.trim().length > 0\n ? result.extractionFailure\n : undefined;\n // Issue #3140: surface extraction-LLM outages on /health and as an\n // ERROR-level deduplicated event instead of debug-only lines. Records on\n // every completed attempt so a later success clears the failure.\n if (extractionFailure) {\n recordExtractionLlmFailure(extractionFailure);\n emitExtractionLlmFailureError(extractionFailure, result.extractionFailureClass);\n } else if (result.extractionSkippedReason !== undefined) {\n // Prefiltered batch: no LLM was contacted, so we cannot confirm or deny\n // reachability. Do not clear the outage state.\n } else {\n recordExtractionLlmSuccess();\n }\n let recordedRetryFailure = false;\n // Record failure into backoff/breaker state, or heal on success. Runs for\n // every result path (empty and durable), before the fail-closed throw, so a\n // forced flush still records its failure (rule 18). Gated by\n // extractionRetryEnabled so a disabled feature restores prior behavior.\n if (extractionFingerprint && extractionRetryEnabled) {\n if (extractionFailure) {\n try {\n meta ??= await runDeadlineAware(() => storage.loadMeta(), \"during_retry_bookkeeping_load\", false);\n await runDeadlineAware(\n () =>\n this.recordExtractionFailure(\n storage,\n selfNamespace,\n extractionFingerprint,\n result.extractionFailureClass ?? \"provider_retryable\",\n meta!,\n Date.now(),\n ),\n \"during_retry_bookkeeping_save\",\n false,\n );\n // The buffer is retained below so the backoff gate can re-attempt\n // these turns after nextEligibleAt — clearing would orphan the\n // retry state.\n recordedRetryFailure = true;\n } catch (err) {\n if (err instanceof ExtractionDeadlineError) throw err;\n // Fail-open (codex review): retry bookkeeping is best-effort — a\n // corrupt or locked meta store must not reject the extraction task.\n // With no backoff recorded there is nothing to retain for, so the\n // pre-#1908 clear-buffer behavior applies below.\n log.warn(\"runExtraction: failed to load meta for retry bookkeeping (non-fatal)\", err);\n }\n } else if (result.extractionSkippedReason === undefined) {\n // Provider responded without failure → breaker heals; clear any\n // parked backoff for this fingerprint so it proceeds normally.\n this.resetProviderBreakerOnSuccess();\n try {\n meta ??= await runDeadlineAware(() => storage.loadMeta(), \"during_retry_bookkeeping_load\", false);\n // Hydrate the in-memory mirror from persisted meta before clearing.\n // A forced flush (forceExtractionAttempt) bypasses the retry gate and\n // never hydrated, so without this a stale persisted backoff entry\n // would survive a successful forced flush and keep blocking normal\n // extraction until the timer expired (cursor/codex review).\n this.hydrateRetryStateFromMeta(selfNamespace, meta);\n if (this.clearExtractionRetryEntry(selfNamespace, extractionFingerprint, meta)) {\n await runDeadlineAware(() => storage.saveMeta(meta!), \"during_retry_bookkeeping_save\", false);\n }\n } catch (err) {\n if (err instanceof ExtractionDeadlineError) throw err;\n log.warn(\"runExtraction: failed to persist cleared retry state (non-fatal)\", err);\n }\n }\n }\n if (options.failOnExtractionFailure && extractionFailure) {\n throw new Error(`extraction failed: ${extractionFailure}`);\n }\n if (\n result.facts.length === 0 &&\n result.entities.length === 0 &&\n result.questions.length === 0 &&\n result.profileUpdates.length === 0\n ) {\n log.debug(\"runExtraction: extraction produced no durable outputs; skipping persistence\");\n if (extractionFailure) {\n log.warn(\n \"runExtraction: extraction reported failure with no durable outputs; not marking fingerprint processed\",\n { extractionFailure }\n );\n }\n const emptySuccessCommit = {\n storage,\n meta,\n extractionFingerprint,\n shouldPersistProcessedFingerprint,\n hasExtractionFailure: Boolean(extractionFailure),\n extractionSkippedReason: result.extractionSkippedReason,\n recordProcessedExtractionFingerprint: this.deps.recordProcessedExtractionFingerprint,\n runDeadlineAware,\n isDeadlineError: (error: unknown) => error instanceof ExtractionDeadlineError,\n };\n if (shouldPersistProcessedFingerprint) {\n await commitEmptySuccessExtraction(emptySuccessCommit);\n }\n await runPassiveCapture(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal,\n namespace: selfNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n });\n if (recordedRetryFailure) {\n log.debug(\"runExtraction: retaining buffer for backoff retry after failure\");\n } else {\n await clearBuffer();\n }\n if (!shouldPersistProcessedFingerprint) {\n await commitEmptySuccessExtraction(emptySuccessCommit);\n }\n return { status: \"skipped\", reason: \"empty_extraction_result\", persistedCount: 0, durableOutputCount: 0 };\n }\n\n let threadIdForExtraction: string | null = null;\n if (resolvePresentationCapabilities(this.config).threading && turns.length > 0) {\n const lastTurn = turns[turns.length - 1];\n try {\n threadIdForExtraction = await runDeadlineAware(\n () => this.deps.getThreading().processTurn(lastTurn, []),\n \"during_threading\",\n );\n } catch (err) {\n if (err instanceof ExtractionDeadlineError) throw err;\n // Fail-open: threading errors must not block memory persistence.\n log.warn(\"[threading] processTurn failed before persistence (non-fatal)\", err);\n }\n }\n const originContext = deriveExtractionOriginContext(targetTurns, result.sourceConnector);\n options.onBeforePersist?.();\n throwIfDeadlineExceeded(\"before_persist\");\n throwIfAborted(\"before_persist\");\n\n const { persistedIds } = await this.deps.persistExtraction(\n result,\n storage,\n threadIdForExtraction,\n { sessionKey, principal, validAt: sourceValidAt, ...originContext },\n // Pass the KNOWN base namespace (NHIdx) so the catalog write touch records the\n // real namespace rather than a guess decoded from the storage dir.\n selfNamespace,\n scopeProfileWritePlan,\n // Verbatim source turns for the faithfulness gate (#1576) so it can\n // locate a quote per fact when #1575 spans are absent.\n normalizedTurns\n .map((t) => t.content)\n .join(\"\\n\\n\")\n );\n const durableOutputCount =\n result.facts.length + result.entities.length + result.questions.length + result.profileUpdates.length;\n try {\n options.onDurableCommit?.();\n } catch (error) {\n log.warn(\"runExtraction: durable-commit callback failed\", error);\n }\n const runPostPersistBestEffort = runExtractionPostPersistBestEffort.bind(null, runDeadlineAware);\n await tagPersistedMemories(storage, persistedIds, this.config);\n const postPersist = await runExtractionPostPersist({\n result,\n storage,\n meta: meta ?? undefined,\n extractionFingerprint: extractionFingerprint ?? undefined,\n shouldPersistProcessedFingerprint,\n recordProcessedExtractionFingerprint: this.deps.recordProcessedExtractionFingerprint,\n runDeadlineAware,\n isDeadlineError: (error) => error instanceof ExtractionDeadlineError,\n createDeadlineError: (stage) => new ExtractionDeadlineError(stage),\n deadlineMs,\n clearBufferAfterExtraction,\n runPostPersistBestEffort,\n extractionJudgeShadow: this.config.extractionJudgeShadow,\n getDeferredCount: () => this.deps.getLastPersistExtractionDeferredCount(),\n normalizedTurns: normalizedTurns as BufferTurn[],\n bufferKey,\n retainDeferredTurns: (key, retainedTurns, max) =>\n this.deps.getBuffer().retainDeferredTurns(key, retainedTurns, max, turns),\n clearBuffer,\n failOnExtractionFailure: options.failOnExtractionFailure === true,\n });\n meta = postPersist.meta ?? null;\n const postPersistMetadataFailed = postPersist.metadataFailed;\n\n // Passive correction capture (issue #1581) — detect corrections expressed\n // passively in the extracted turns and route to the Correction Contract.\n // Runs AFTER persistence + buffer clear so a capture failure never blocks\n // the extraction return. `clearBufferAfterExtraction` gates live-session\n // auto-apply (replay/import → queue-only).\n await runPostPersistBestEffort(\"during_post_persist_passive_capture\", () =>\n runPassiveCapture(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal,\n namespace: selfNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n abortSignal: extractionAbortSignal,\n }),\n );\n\n // Build memory box from this extraction (v8.0 Phase 2A)\n // Topics are derived from the current extraction's facts and entities only —\n // not from readAllMemories() — so box topics accurately reflect the current\n // session window and the call is free of expensive full-corpus I/O.\n if (resolvePresentationCapabilities(this.config).memoryBoxes && persistedIds.length > 0) {\n const extractionTopics = deriveTopicsFromExtraction(result);\n // Derive episodic metadata from buffer turns (REMem-inspired)\n const firstUserTurn = turns.find((t) => t.role === \"user\");\n const boxGoal = firstUserTurn?.content?.slice(0, 100)?.trim() || undefined;\n await runPostPersistBestEffort(\"during_memory_box\", () =>\n this.deps.boxBuilderFor(storage).onExtraction({\n topics: extractionTopics,\n memoryIds: persistedIds,\n timestamp: new Date().toISOString(),\n goal: boxGoal,\n }),\n );\n }\n\n // Batch-append persisted IDs so non-fact memories (entities/questions) are\n // always attached to the thread. The helper excludes pending_review ids (#1635).\n if (resolvePresentationCapabilities(this.config).threading && threadIdForExtraction && persistedIds.length > 0) {\n await runPostPersistBestEffort(\"during_thread_episode_append\", () =>\n this.deps.appendPersistedThreadEpisodes(threadIdForExtraction, persistedIds),\n );\n }\n\n // Thread title update for the already-established thread context.\n if (resolvePresentationCapabilities(this.config).threading && threadIdForExtraction) {\n const conversationContent = turns.map((t) => t.content).join(\" \");\n await runPostPersistBestEffort(\"during_thread_title_update\", () =>\n this.deps.getThreading().updateThreadTitle(threadIdForExtraction, conversationContent),\n );\n }\n\n // Check if consolidation is needed (debounced + non-zero gated).\n const nonZeroExtraction = durableOutputCount > 0;\n try {\n // The increment of nonZeroExtractionsSinceConsolidation moved into\n // the scheduler with the rest of the cadence state (issue #1526 PR1).\n this.deps.maybeScheduleConsolidation(nonZeroExtraction);\n } catch (err) {\n log.warn(\"runExtraction: consolidation scheduling failed after persistence (non-fatal)\", err);\n }\n\n try {\n this.deps.requestQmdMaintenance();\n } catch (err) {\n log.warn(\"runExtraction: QMD maintenance scheduling failed after persistence (non-fatal)\", err);\n }\n\n await runPostPersistBestEffort(\"during_tier_migration\", () =>\n this.deps.runTierMigrationCycle(storage, \"extraction\"),\n );\n\n return {\n status: \"completed\",\n persistedCount: persistedIds.length,\n durableOutputCount,\n postPersistMetadataFailed,\n };\n } finally {\n clearExtractionDeadlineTimer();\n }\n }\n}\n","/**\n * Derive issue #1955 origin metadata at the extraction boundary.\n */\n\nimport { classifyOrigin, type OriginClass } from \"../security/origin-authority.js\";\nimport type { BufferTurn } from \"../types.js\";\n\nexport interface ExtractionSourceContext {\n sessionKey?: string;\n principal?: string;\n validAt?: string;\n sourceConnector?: string;\n turnRole?: \"user\" | \"assistant\" | \"tool\" | string;\n importAdapter?: string;\n originConflict?: boolean;\n}\n\n/** Derive one origin context from the turns that supplied an extraction. */\nexport function deriveExtractionOriginContext(\n targetTurns: readonly BufferTurn[],\n fallbackConnector?: string,\n): Pick<ExtractionSourceContext, \"turnRole\" | \"importAdapter\" | \"sourceConnector\" | \"originConflict\"> {\n const originRoles = new Set(targetTurns.map((turn) => turn.originRole ?? turn.role));\n const turnRole = originRoles.size === 1 ? [...originRoles][0] : undefined;\n const originConnectors = new Set(\n targetTurns\n .map((turn) => turn.sourceConnector)\n .filter((connector): connector is string => typeof connector === \"string\" && connector.length > 0),\n );\n // Mirror the pre-#1955 provenance rule: a batch only carries a connector\n // when EVERY turn is tagged with the same one — a mixed tagged+untagged\n // batch must stay connector-less (connector-provenance-lifecycle tests).\n const connector =\n targetTurns.length > 0 &&\n targetTurns.every(\n (turn) => typeof turn.sourceConnector === \"string\" && turn.sourceConnector.length > 0,\n ) &&\n originConnectors.size === 1\n ? [...originConnectors][0]\n : undefined;\n const originAdapters = new Set(\n targetTurns\n .map((turn) => turn.importProvenance?.sourceLabel)\n .filter((adapter): adapter is string => typeof adapter === \"string\" && adapter.length > 0),\n );\n // Conflict when identities disagree OR are only partially present: a batch\n // where some turns carry an import label (or connector) and others do not\n // must classify as unknown, never fall back to the uniform turn role\n // (#1955 review: mixed import labels previously became `user`).\n const everyTurnHasConnector =\n targetTurns.length > 0 &&\n targetTurns.every((turn) => typeof turn.sourceConnector === \"string\" && turn.sourceConnector.length > 0);\n const everyTurnHasAdapter =\n targetTurns.length > 0 &&\n targetTurns.every(\n (turn) => typeof turn.importProvenance?.sourceLabel === \"string\" && turn.importProvenance.sourceLabel.length > 0,\n );\n const originConflict =\n originConnectors.size > 1 ||\n originAdapters.size > 1 ||\n (originConnectors.size > 0 && originAdapters.size > 0) ||\n (originConnectors.size > 0 && !everyTurnHasConnector) ||\n (originAdapters.size > 0 && !everyTurnHasAdapter);\n const importAdapter =\n targetTurns.length > 0 &&\n targetTurns.every(\n (turn) =>\n typeof turn.importProvenance?.sourceLabel === \"string\" &&\n turn.importProvenance.sourceLabel.length > 0,\n ) &&\n originAdapters.size === 1\n ? [...originAdapters][0]\n : undefined;\n return {\n ...(turnRole ? { turnRole } : {}),\n ...(importAdapter ? { importAdapter } : {}),\n ...(originConflict ? { originConflict: true } : {}),\n sourceConnector: fallbackConnector ?? connector,\n };\n}\n\n/** Classify the persisted origin without reading config flags. */\nexport function classifyExtractionOrigin(sourceContext?: ExtractionSourceContext): OriginClass {\n if (sourceContext?.originConflict === true) return \"unknown\";\n return classifyOrigin({\n turnRole: sourceContext?.turnRole,\n connectorId: sourceContext?.sourceConnector,\n importAdapter: sourceContext?.importAdapter,\n });\n}\n"],"mappings":"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","names":["connector","options"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/buffer.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport { throwIfAborted } from \"./abort-error.js\";\nimport { scanSignals } from \"./signal.js\";\nimport { BufferSessionPersistence, type BufferStorage } from \"./buffer-persistence.js\";\nimport { selectEvictedBufferKeys } from \"./buffer-eviction.js\";\nimport type {\n BufferEntryState,\n BufferState,\n BufferSurpriseEvent,\n BufferTurn,\n PluginConfig,\n SignalLevel,\n} from \"./types.js\";\nimport { resolvePresentationCapabilities, resolveNamespaceCapabilities } from \"./capabilities.js\";\nimport { resolvePrincipal } from \"./namespaces/principal.js\";\nimport { scopeProfilePlanIdentity } from \"./buffer-turn-helpers.js\";\nimport { ExtractionDeadlineError } from \"./orchestration/extraction-run.js\";\nimport type { ExtractionBufferSnapshot } from \"./extraction-liveness.js\";\nimport {\n bufferTurnArrayIsSuffixOfSnapshot,\n bufferTurnArraysEqual,\n bufferTurnsEqual,\n copyBufferTurn,\n describeError,\n hasPinnedCaptureScope,\n liveTurnsFromExtractionSnapshot,\n matchingQueuedExtractionPrefixLength,\n probeWithTimeout,\n selectRetainedDeferredTurns,\n} from \"./buffer-turn-helpers.js\";\n\nexport type TriggerDecision = \"extract_now\" | \"extract_batch\" | \"keep_buffering\";\n\nexport interface AddTurnOutcome {\n decision: TriggerDecision;\n extractionTurns?: BufferTurn[];\n}\n\nexport interface RetainedTurnCleanupOptions {\n abortSignal?: AbortSignal;\n deadlineMs?: number;\n /** Keep cleanup within the accepted namespace. */\n writeNamespaceOverride?: string;\n /** Match the original profile and project binding, not just its write namespace. */\n scopeProfileWritePlan?: import(\"./namespaces/scope-profiles.js\").ResolvedScopeProfilePlan | null;\n codingContext?: import(\"./types.js\").CodingContext;\n}\n\n/**\n * Optional surprise probe injected into `SmartBuffer`.\n *\n * Computes a D-MEM-style novelty score in `[0, 1]` for an incoming turn.\n * The buffer treats the probe as purely additive: if it is not provided, if\n * the feature flag is off, or if the probe throws/times out, the buffer\n * falls back to the existing signal/turn-count/time triggers unchanged.\n *\n * Callers are responsible for sampling recent memories and passing them\n * through the embedding pipeline — the buffer does not want to know about\n * storage, embeddings, or QMD.\n *\n * @param bufferKey Identifier for the active buffer (session/thread).\n * @param turn The incoming turn whose novelty is being scored.\n * @param recentTurns Turns already buffered for this key (most recent first\n * is NOT guaranteed — treat as unordered corpus).\n * @returns A surprise score in `[0, 1]`, or `null` if no score could be\n * produced (e.g. empty corpus, probe declined to embed).\n */\nexport interface BufferSurpriseProbe {\n scoreTurn(\n bufferKey: string,\n turn: BufferTurn,\n recentTurns: readonly BufferTurn[],\n ): Promise<number | null>;\n}\n\nconst MAX_BUFFER_ENTRY_COUNT = 200;\nconst isAcceptedTurn = (t: { acceptedCapture?: boolean; writeNamespaceOverride?: string }): boolean =>\n t.acceptedCapture === true || t.writeNamespaceOverride !== undefined;\n\n/**\n * Upper bound on how long a debounced buffer save may be deferred under\n * sustained activity (issue #1909). Each new turn re-arms the trailing-edge\n * timer, so a steady stream of turns could otherwise push the save out\n * indefinitely and widen the crash-loss window without bound. Once a pending\n * save has been deferred this many debounce windows, the next scheduled save\n * forces an inline flush instead of re-arming.\n */\nconst BUFFER_SAVE_MAX_DEFER_MULTIPLIER = 5;\n\n/**\n * Node's maximum 32-bit `setTimeout` delay (2^31-1 ms, ~24.8 days). A larger\n * value is overflow-clamped by Node to 1ms with a TimeoutOverflowWarning, so we\n * clamp defensively at every timer arm (issue #1909 review round 5) even though\n * parseConfig already caps `bufferSaveDebounceMs` — a directly-constructed config\n * could still exceed it.\n */\nconst MAX_SET_TIMEOUT_MS = 2_147_483_647;\n\n/**\n * Minimal data carried on the serialized telemetry write chain\n * (issue #563 PR 3).\n *\n * We intentionally do NOT capture the full `BufferTurn` here: under\n * slow filesystem latency the chain can back up, and retaining\n * `turn.content` for every pending append causes memory pressure on\n * large conversations. Only the fields the ledger row actually needs\n * cross the chain boundary.\n */\ninterface SurpriseTelemetryQueueEntry {\n bufferKey: string;\n turnRole: \"user\" | \"assistant\";\n sessionKey: string | null;\n surpriseScore: number;\n triggered: boolean;\n turnCountInWindow: number;\n /**\n * ISO timestamp captured at the moment the turn was scored, NOT when\n * the ledger append eventually runs. Backpressure on the serialized\n * write chain could otherwise shift event timestamps away from the\n * real decision moment and distort the distribution report (p90\n * inflated, current-threshold row misidentified).\n */\n timestamp: string;\n /**\n * Threshold value in force when `triggered` was computed. Must be\n * snapshot here rather than read from `config` at emit time — a\n * concurrent config change between queue and write would otherwise\n * record `triggered=true` against a newer threshold the operator\n * never set, distorting precision/recall interpretation.\n */\n threshold: number;\n}\n\ninterface AddTurnMutationResult {\n decision: TriggerDecision;\n signalLevel: SignalLevel;\n priorTurns: BufferTurn[];\n activeTurnsSnapshot: BufferTurn[];\n retainedTurnsSnapshot: BufferTurn[];\n turnCountInWindow: number;\n}\n\nexport class SmartBuffer {\n private state: BufferState;\n private loaded = false;\n private loadPromise: Promise<void> | null = null;\n private readonly surpriseProbe: BufferSurpriseProbe | null;\n private mutationChain: Promise<unknown> = Promise.resolve();\n /**\n * Serialized write chain for `BUFFER_SURPRISE` telemetry events.\n *\n * The telemetry path is fire-and-forget (`addTurn` does not await the\n * ledger append), but multiple concurrent appends would still settle\n * out of order under variable filesystem latency. The report path\n * assumes chronological ordering — it slices the tail of the ledger\n * and treats the most recent entry as the current threshold in force.\n * Chaining ensures each append only runs after the previous settles,\n * preserving wall-clock order.\n *\n * We include a `.catch` on every link so a rejected append does not\n * poison the chain (CLAUDE.md rule #40).\n */\n private surpriseTelemetryWriteChain: Promise<unknown> = Promise.resolve();\n\n /**\n * Debounced buffer-save state (issue #1909). Steady-state buffering used to\n * serialize + rewrite the whole multi-session buffer on EVERY turn. We now\n * coalesce those writes onto a trailing-edge timer; correctness boundaries\n * (extraction trigger, extraction clear, shutdown) still force an immediate\n * flush. `bufferSaveDebounceMs: 0` restores save-every-turn exactly.\n */\n private saveTimer: NodeJS.Timeout | null = null;\n private pendingSave = false;\n /** Wall-clock ms when the currently-pending save was first scheduled (issue\n * #1909). Null when nothing is pending. Used to bound deferral under sustained\n * activity (see BUFFER_SAVE_MAX_DEFER_MULTIPLIER). */\n private firstPendingAtMs: number | null = null;\n\n /** Which sessions' persisted files are stale (per-session incremental saves). */\n private readonly persistence = new BufferSessionPersistence();\n\n constructor(\n private readonly config: PluginConfig,\n private readonly storage: BufferStorage,\n surpriseProbe: BufferSurpriseProbe | null = null,\n ) {\n this.state = { turns: [], lastExtractionAt: null, extractionCount: 0 };\n this.surpriseProbe = surpriseProbe;\n }\n\n private enqueueMutation<T>(op: () => Promise<T>): Promise<T> {\n const run = this.mutationChain.catch(() => {}).then(op);\n this.mutationChain = run.catch(() => {});\n return run;\n }\n\n private entryFor(key: string): BufferEntryState {\n if (!this.state.entries) {\n this.state.entries = Object.create(null) as NonNullable<BufferState[\"entries\"]>;\n }\n const entries = this.state.entries as NonNullable<BufferState[\"entries\"]>;\n if (Object.hasOwn(entries, key)) {\n const stored = entries[key];\n // Guard against corrupted state/buffer.json — if the stored entry\n // is not a valid object shape, discard it and recreate.\n if (stored && typeof stored === \"object\" && Array.isArray(stored.turns)) {\n return stored;\n }\n // Corrupted — fall through to recreate.\n }\n const created: BufferEntryState = {\n turns: [],\n lastExtractionAt: null,\n extractionCount: 0,\n };\n entries[key] = created;\n return created;\n }\n\n private peekEntry(key: string): BufferEntryState | null {\n const existing = this.state.entries?.[key];\n if (existing) return existing;\n if (key !== \"default\") return null;\n return {\n turns: Array.isArray(this.state.turns) ? this.state.turns : [],\n lastExtractionAt: this.state.lastExtractionAt ?? null,\n extractionCount:\n typeof this.state.extractionCount === \"number\" ? this.state.extractionCount : 0,\n };\n }\n\n private normalizeState(state: BufferState): BufferState {\n const entries = Object.assign(\n Object.create(null),\n state.entries ?? {},\n ) as NonNullable<BufferState[\"entries\"]>;\n if (!entries.default) {\n entries.default = {\n turns: Array.isArray(state.turns) ? [...state.turns] : [],\n lastExtractionAt: state.lastExtractionAt ?? null,\n extractionCount:\n typeof state.extractionCount === \"number\" ? state.extractionCount : 0,\n };\n }\n return {\n turns: entries.default.turns,\n lastExtractionAt: entries.default.lastExtractionAt,\n extractionCount: entries.default.extractionCount,\n entries,\n };\n }\n\n private entryActivityAt(entry: BufferEntryState): number {\n const lastTurnAt = entry.turns.reduce((latest, turn) => {\n const parsed = Date.parse(turn.timestamp);\n return Number.isFinite(parsed) ? Math.max(latest, parsed) : latest;\n }, -1);\n const lastExtractionAt =\n typeof entry.lastExtractionAt === \"string\"\n ? Date.parse(entry.lastExtractionAt)\n : Number.NaN;\n return Math.max(\n lastTurnAt,\n Number.isFinite(lastExtractionAt) ? lastExtractionAt : -1,\n );\n }\n\n /** Evict oldest entries past MAX_BUFFER_ENTRY_COUNT and queue their session files for deletion. */\n private pruneEntries(retainKeys: string[]): void {\n const entries = this.state.entries;\n if (!entries) return;\n const evicted = selectEvictedBufferKeys(entries, retainKeys, MAX_BUFFER_ENTRY_COUNT, {\n activityAt: (entry) => this.entryActivityAt(entry),\n holdsAcceptedCapture: (entry) => this.entryHoldsAcceptedCapture(entry),\n });\n for (const key of evicted) delete entries[key];\n this.persistence.markEvicted(evicted);\n if (evicted.length > 0) {\n // Loud degradation (extraction hot-loop hardening, Step 7): buffer\n // pressure during a provider outage is bounded and expected, but must\n // be observable, not silent.\n log.warn(\n `buffer: pruned ${evicted.length} oldest session entr${evicted.length === 1 ? \"y\" : \"ies\"} ` +\n `past MAX_BUFFER_ENTRY_COUNT=${MAX_BUFFER_ENTRY_COUNT}; buffered turn data for those sessions was dropped`,\n );\n }\n }\n\n private async loadUnlocked(): Promise<void> {\n if (this.loaded) return;\n if (!this.loadPromise) {\n this.loadPromise = this.storage.loadBuffer()\n .then((state) => {\n this.state = this.normalizeState(state);\n this.loaded = true;\n })\n .finally(() => {\n this.loadPromise = null;\n });\n }\n await this.loadPromise;\n }\n\n async load(): Promise<void> {\n await this.enqueueMutation(async () => this.loadUnlocked());\n }\n\n /** Snapshot of buffered, not-yet-extracted work across sessions (#2151): session count,\n * pending-turn total, oldest buffered turn. Counts retained (#562) + active turns per entry. */\n async getBufferSnapshot(): Promise<ExtractionBufferSnapshot> {\n await this.load();\n let bufferedSessionCount = 0;\n let pendingTurnCount = 0;\n let oldestMs = Number.POSITIVE_INFINITY;\n let oldestTurnTimestamp: string | null = null;\n const consider = (turns: BufferTurn[] | undefined): void => {\n if (!Array.isArray(turns) || turns.length === 0) return;\n bufferedSessionCount += 1;\n pendingTurnCount += turns.length;\n const first = turns[0]?.timestamp;\n const parsed = typeof first === \"string\" ? Date.parse(first) : Number.NaN;\n if (Number.isFinite(parsed) && parsed < oldestMs) {\n oldestMs = parsed;\n oldestTurnTimestamp = first ?? null;\n }\n };\n const entries = this.state.entries;\n if (entries) {\n // Retained turns (deferred #562) are pending too - count with active (oldest-first), like getTurns().\n for (const entry of Object.values(entries)) consider([...(entry?.retainedTurns ?? []), ...(entry?.turns ?? [])]);\n } else {\n consider(this.state.turns);\n }\n return { bufferedSessionCount, pendingTurnCount, oldestTurnTimestamp };\n }\n\n /**\n * Reset the buffer to an empty, usable state.\n * Called when the persisted buffer file is corrupt and load() fails,\n * so the buffer can still accept new turns for the rest of the session.\n */\n resetToEmpty(): void {\n for (const key of Object.keys(this.state.entries ?? {})) {\n this.persistence.markDeleted(key);\n }\n this.state = { turns: [], lastExtractionAt: null, extractionCount: 0 };\n this.loaded = true;\n }\n\n private async saveUnlocked(): Promise<void> {\n await this.persistence.persist(this.storage, this.state, (key) => this.peekEntry(key) ?? undefined);\n }\n\n async save(): Promise<void> {\n await this.enqueueMutation(async () => this.saveUnlocked());\n }\n\n /**\n * Schedule a coalesced, TRUE trailing-edge buffer save (issue #1909). Only\n * used for the debounced (`bufferSaveDebounceMs > 0`) steady-state buffering\n * path; the debounce-off and correctness-boundary paths save inline within the\n * mutation (see `recordTurnUnlocked`). Each call re-arms the timer from now so\n * the write lands one full window after the LAST turn, not the first. To keep\n * sustained activity from deferring the save without bound (which would widen\n * the crash-loss window), once a pending save has been deferred\n * BUFFER_SAVE_MAX_DEFER_MULTIPLIER windows it is flushed inline instead of\n * re-armed. Runs inside the record mutation, so the inline save is awaited.\n */\n private async scheduleSave(): Promise<void> {\n const ms = Math.min(this.config.bufferSaveDebounceMs, MAX_SET_TIMEOUT_MS);\n const now = Date.now();\n this.pendingSave = true;\n if (this.firstPendingAtMs === null) this.firstPendingAtMs = now;\n if (now - this.firstPendingAtMs >= ms * BUFFER_SAVE_MAX_DEFER_MULTIPLIER) {\n // Staleness cap hit: persist now rather than deferring further. Drop the\n // armed timer, attempt the write, and only mark clean on success — a\n // failure keeps the save pending + re-arms so shutdown/the next timer\n // retries (issue #1909 review round 2), never diverging memory from disk.\n clearTimeout(this.saveTimer ?? undefined);\n this.saveTimer = null;\n try {\n await this.saveUnlocked();\n this.pendingSave = false;\n this.firstPendingAtMs = null;\n } catch (err) {\n log.warn(`buffer.scheduleSave: staleness-cap save failed, keeping it pending: ${describeError(err)}`);\n this.saveTimer = setTimeout(() => {\n this.saveTimer = null;\n void this.flushPendingSave();\n }, ms);\n this.saveTimer.unref?.();\n }\n return;\n }\n // True trailing edge: drop any armed timer and re-arm from now.\n clearTimeout(this.saveTimer ?? undefined);\n this.saveTimer = setTimeout(() => {\n this.saveTimer = null;\n void this.flushPendingSave();\n }, ms);\n this.saveTimer.unref?.();\n }\n\n /** Cancel any armed debounced save without persisting. */\n private cancelScheduledSave(): void {\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n this.pendingSave = false;\n this.firstPendingAtMs = null;\n }\n\n /**\n * Persist the current in-memory buffer state inline, keeping the global\n * pending-save state armed until the write SUCCEEDS (issue #1909). On failure\n * the save stays pending and — when debounced — a background retry timer is\n * (re-)armed before the error propagates, so a graceful shutdown flush and the\n * next timer tick both retry. A failed post-mutation save therefore can never\n * silently drop buffered turns, including turns from OTHER sessions that were\n * only in the debounced pending state. The pending flag is cleared (and any\n * armed timer dropped) only after a durable write.\n */\n private async saveNowRetainingPendingOnFailure(context: string): Promise<void> {\n this.pendingSave = true;\n if (this.firstPendingAtMs === null) this.firstPendingAtMs = Date.now();\n try {\n await this.saveUnlocked();\n } catch (err) {\n log.warn(\n `buffer.${context}: inline save failed, keeping it pending for retry: ${describeError(err)}`,\n );\n const ms = Math.min(this.config.bufferSaveDebounceMs, MAX_SET_TIMEOUT_MS);\n if (ms > 0 && !this.saveTimer) {\n this.saveTimer = setTimeout(() => {\n this.saveTimer = null;\n void this.flushPendingSave();\n }, ms);\n this.saveTimer.unref?.();\n }\n throw err;\n }\n this.cancelScheduledSave();\n }\n\n /**\n * Force any pending debounced save to land now (issue #1909). Idempotent and\n * safe to call from outside a mutation (timer tick, shutdown/dispose, or the\n * surprise-promotion path in `addTurnWithOutcome`). Do NOT `await` this from\n * inside a mutation — it enqueues its own mutation and would deadlock the\n * serializer.\n *\n * `throwOnFailure` (review round 7 finding 5): when set, a failed write is\n * rethrown AFTER the keep-pending + re-arm bookkeeping, so the surprise\n * extraction boundary gets the same durability guarantee as the built-in\n * extract triggers (which propagate saveUnlocked failures) instead of\n * proceeding to extract_now on a non-durable triggering turn. Default false\n * keeps the fail-open behavior for the timer/shutdown callers.\n */\n async flushPendingSave(opts?: { throwOnFailure?: boolean }): Promise<void> {\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n // resetToEmpty-only deletions are pending work too, even with no\n // pending-save flag set.\n if (!this.pendingSave && !this.persistence.hasPending()) return;\n try {\n await this.enqueueMutation(async () => {\n // Re-check under the serializer: a concurrent flush may have already\n // persisted this pending save. Skip the redundant write (no phantom\n // writes). resetToEmpty-only deletions also land here without a\n // pending-save flag.\n if (!this.pendingSave && !this.persistence.hasPending()) return;\n await this.saveUnlocked();\n // Clear the pending flag INSIDE the same serialized mutation as the\n // write (issue #1909 review). Clearing it after the enqueue await\n // resolved raced an addTurn interleaving between the write and the\n // clear: that turn's scheduleSave re-armed pendingSave + a timer, then\n // this clear wiped it and the debounced flush was lost. Atomic\n // write+clear means any addTurn runs wholly before (its turn is in the\n // write) or wholly after (its pendingSave survives and its timer\n // persists it).\n this.pendingSave = false;\n this.firstPendingAtMs = null;\n });\n } catch (err) {\n // The write failed: memory and disk diverge (issue #1909 review round 2).\n // Keep the save PENDING (do NOT clear pendingSave/firstPendingAtMs) so a\n // graceful shutdown flush and the re-armed timer both retry it — clearing\n // the flag here would drop the buffered turns permanently. Re-arm a\n // background retry when debounced.\n log.warn(`buffer.flushPendingSave: save failed, keeping it pending for retry: ${describeError(err)}`);\n const ms = Math.min(this.config.bufferSaveDebounceMs, MAX_SET_TIMEOUT_MS);\n if (ms > 0 && !this.saveTimer) {\n this.saveTimer = setTimeout(() => {\n this.saveTimer = null;\n void this.flushPendingSave();\n }, ms);\n this.saveTimer.unref?.();\n }\n // Surprise-extraction boundary needs the durability guarantee — surface\n // the failure so the caller does not proceed with a non-durable flush.\n if (opts?.throwOnFailure) throw err;\n return; // fail-open for timer/shutdown callers\n }\n }\n\n async addTurn(bufferKey: string, turn: BufferTurn): Promise<TriggerDecision> {\n return (await this.addTurnWithOutcome(bufferKey, turn)).decision;\n }\n\n /** Admit atomically; refuse at capacity rather than evict accepted work. */\n async addTurnBounded(bufferKey: string, turn: BufferTurn): Promise<AddTurnOutcome | null> {\n const mutation = await this.enqueueMutation(async () => {\n await this.loadUnlocked();\n if (this.peekEntry(bufferKey) === null) {\n this.makeRoomForEntryUnlocked();\n if (Object.keys(this.state.entries ?? {}).length >= MAX_BUFFER_ENTRY_COUNT) {\n log.warn(\n `buffer[${bufferKey}]: durable capture refused at MAX_BUFFER_ENTRY_COUNT=${MAX_BUFFER_ENTRY_COUNT}`,\n );\n return null;\n }\n }\n return this.recordTurnUnlocked(bufferKey, turn);\n });\n if (mutation === null) return null;\n return this.completeAddTurnOutcome(bufferKey, turn, mutation);\n }\n\n /** Prune empty entries only; accepted work must survive capacity pressure. */\n private makeRoomForEntryUnlocked(): void {\n const entries = this.state.entries;\n if (!entries) return;\n const keys = Object.keys(entries);\n if (keys.length < MAX_BUFFER_ENTRY_COUNT) return;\n const byOldestActivity = (left: string, right: string): number =>\n this.entryActivityAt(entries[left] ?? { turns: [], lastExtractionAt: null, extractionCount: 0 }) -\n this.entryActivityAt(entries[right] ?? { turns: [], lastExtractionAt: null, extractionCount: 0 });\n const emptyRemovable = keys\n .filter(\n (key) =>\n key !== \"default\" &&\n (entries[key]?.turns.length ?? 0) === 0 &&\n (entries[key]?.retainedTurns?.length ?? 0) === 0,\n )\n .sort(byOldestActivity);\n for (const key of emptyRemovable) {\n if (Object.keys(entries).length < MAX_BUFFER_ENTRY_COUNT) break;\n delete entries[key];\n this.persistence.markDeleted(key);\n }\n }\n\n private entryHoldsAcceptedCapture(entry: BufferEntryState | undefined): boolean {\n return (entry?.turns ?? []).some(isAcceptedTurn) || (entry?.retainedTurns ?? []).some(isAcceptedTurn);\n }\n\n async addTurnWithOutcome(\n bufferKey: string,\n turn: BufferTurn,\n ): Promise<AddTurnOutcome> {\n const mutation = await this.enqueueMutation(() => this.recordTurnUnlocked(bufferKey, turn));\n return this.completeAddTurnOutcome(bufferKey, turn, mutation);\n }\n\n /** Run probes outside the mutation lock to avoid reentrancy deadlocks. */\n private async completeAddTurnOutcome(\n bufferKey: string,\n turn: BufferTurn,\n mutation: AddTurnMutationResult,\n ): Promise<AddTurnOutcome> {\n let decision = mutation.decision;\n let extractionTurns: BufferTurn[] | undefined;\n\n // Surprise-gated flush (issue #563). Additive only: if the probe is\n // disabled, unavailable, or the score is below threshold, the decision\n // from the existing trigger logic stands. The probe only ever *promotes*\n // `keep_buffering` → `extract_now`; it never suppresses an existing\n // flush. This preserves the invariant that enabling surprise cannot\n // *reduce* extraction frequency.\n if (\n decision === \"keep_buffering\" &&\n resolvePresentationCapabilities(this.config).bufferSurpriseTrigger &&\n this.surpriseProbe !== null &&\n // Matching the existing \"smart\" branch: surprise is a lower-tier\n // novelty signal that should not second-guess a high-signal hit\n // (which already flushes) or fight `every_n` / `time_based` modes.\n this.config.triggerMode === \"smart\" &&\n mutation.signalLevel !== \"high\"\n ) {\n const surprise = await this.computeSurpriseSafe(bufferKey, turn, mutation.priorTurns);\n if (surprise !== null) {\n const shouldPromote = surprise > this.config.bufferSurpriseThreshold;\n let triggered = false;\n if (shouldPromote) {\n const currentTurns = await this.getExtractionTurnsIfBufferSnapshotStillCurrent(\n bufferKey,\n mutation.activeTurnsSnapshot,\n mutation.retainedTurnsSnapshot,\n );\n if (currentTurns) {\n log.debug(\n `buffer[${bufferKey}]: surprise=${surprise.toFixed(3)} > threshold=${this.config.bufferSurpriseThreshold} → extract_now`,\n );\n decision = \"extract_now\";\n triggered = true;\n extractionTurns = currentTurns;\n // Issue #1909 (review): the record mutation for a `keep_buffering`\n // turn only SCHEDULED a debounced save. Surprise now promotes it to\n // extract_now AFTER that mutation, so force the buffer durable before\n // the caller runs extraction — otherwise state/buffer.json lags the\n // extracted turns by up to the debounce window on a crash. Safe to\n // await here: we are outside the record mutation (deadlock-free).\n // throwOnFailure (round 7 finding 5): match the built-in extract\n // triggers — a failed durability write must NOT silently proceed to\n // extract_now on a non-durable turn.\n await this.flushPendingSave({ throwOnFailure: true });\n } else {\n log.debug(\n `buffer[${bufferKey}]: surprise=${surprise.toFixed(3)} ignored because buffer changed before probe resolved`,\n );\n }\n }\n // Emit telemetry on every scored turn — both triggering and\n // non-triggering — so operators can fit the threshold to real\n // traffic distributions. Fire-and-forget: `addTurn` does NOT\n // await the ledger append, so slow/contended filesystems cannot\n // add JSONL-append latency to every `processTurn`. But we DO\n // serialize writes through a promise chain so concurrent\n // appends settle in wall-clock order — the report path assumes\n // chronological tail rows and reads the most recent as the\n // \"current\" threshold.\n //\n // Project only the fields we need into the queue entry rather\n // than capturing the full `BufferTurn` — under slow filesystem\n // latency the chain can back up, and we must not retain the\n // (potentially large) `turn.content` string for every pending\n // append.\n this.queueSurpriseTelemetryWrite({\n bufferKey,\n turnRole: turn.role,\n sessionKey:\n typeof turn.sessionKey === \"string\" ? turn.sessionKey : null,\n surpriseScore: surprise,\n triggered,\n turnCountInWindow: mutation.turnCountInWindow,\n // Stamp at decision time so backpressure on the write chain\n // does not shift the event's apparent moment away from when\n // the turn was actually scored.\n timestamp: new Date().toISOString(),\n // Snapshot the threshold used to compute `triggered` so a\n // concurrent config mutation cannot retroactively change\n // what the ledger row claims the decision was against.\n threshold: this.config.bufferSurpriseThreshold,\n });\n }\n }\n\n log.debug(\n `buffer[${bufferKey}]: ${mutation.turnCountInWindow} turns, signal=${mutation.signalLevel}, decision=${decision}`,\n );\n if (decision !== \"keep_buffering\" && extractionTurns === undefined) {\n extractionTurns = [\n ...mutation.retainedTurnsSnapshot,\n ...mutation.activeTurnsSnapshot,\n ];\n }\n return extractionTurns ? { decision, extractionTurns } : { decision };\n }\n\n private async recordTurnUnlocked(bufferKey: string, turn: BufferTurn): Promise<AddTurnMutationResult> {\n await this.loadUnlocked();\n const entry = this.entryFor(bufferKey);\n const priorTurns = entry.turns.slice();\n entry.turns.push(turn);\n const activeTurnsSnapshot = entry.turns.map(copyBufferTurn);\n const retainedTurnsSnapshot = (entry.retainedTurns ?? []).map(copyBufferTurn);\n if (bufferKey === \"default\") {\n this.state.turns = entry.turns;\n }\n\n const signal = scanSignals(turn.content, this.config.highSignalPatterns);\n const decision = this.evaluate(entry, signal.level);\n const turnCountInWindow = entry.turns.length;\n\n this.persistence.markDirty(bufferKey);\n this.pruneEntries([bufferKey]);\n if (decision === \"keep_buffering\" && this.config.bufferSaveDebounceMs > 0) {\n // Steady-state buffering: coalesce the whole-state serialize onto a\n // trailing-edge timer (issue #1909) instead of rewriting per turn.\n await this.scheduleSave();\n } else {\n // Persist immediately within this mutation (awaited) when either:\n // - the turn triggered extraction (the buffer must be durable), or\n // - debounce is disabled (bufferSaveDebounceMs <= 0), which reproduces\n // the legacy save-every-turn behavior byte-for-byte.\n // Round 8 thread 4: the write is attempted BEFORE the pending state is\n // cleared, and a failed write leaves it pending (+ a re-armed timer) for\n // shutdown/timer retry instead of dropping the in-memory turns.\n await this.saveNowRetainingPendingOnFailure(\"recordTurn\");\n }\n return {\n decision,\n signalLevel: signal.level,\n priorTurns,\n activeTurnsSnapshot,\n retainedTurnsSnapshot,\n turnCountInWindow,\n };\n }\n\n private async getExtractionTurnsIfBufferSnapshotStillCurrent(\n bufferKey: string,\n activeTurnsSnapshot: readonly BufferTurn[],\n retainedTurnsSnapshot: readonly BufferTurn[],\n ): Promise<BufferTurn[] | null> {\n return this.enqueueMutation(async () => {\n await this.loadUnlocked();\n const entry = this.peekEntry(bufferKey);\n if (!entry) return null;\n const retained = entry.retainedTurns ?? [];\n const stillCurrent =\n bufferTurnArrayIsSuffixOfSnapshot(entry.turns, activeTurnsSnapshot) &&\n bufferTurnArraysEqual(retained, retainedTurnsSnapshot);\n if (!stillCurrent) return null;\n return [...retained, ...entry.turns];\n });\n }\n\n /**\n * Enqueue a telemetry append on the serialized write chain.\n *\n * The chain is a classic `writeChain = writeChain.then(fn).catch(...)`\n * — each link waits for the previous to settle before its append\n * starts, so out-of-order chronology cannot happen even under\n * variable filesystem latency. We always attach `.catch` so one\n * rejection does not poison the chain for the rest of the session\n * (CLAUDE.md rule #40). The error is logged through\n * `emitSurpriseEventSafe` itself, which swallows its own rejections.\n *\n * Public surface is deliberately narrow — only `addTurn` should call\n * this, so the surprise telemetry path stays centralized.\n */\n private queueSurpriseTelemetryWrite(params: SurpriseTelemetryQueueEntry): void {\n this.surpriseTelemetryWriteChain = this.surpriseTelemetryWriteChain\n .then(() => this.emitSurpriseEventSafe(params))\n .catch(() => {\n // `emitSurpriseEventSafe` already handles the logging. We\n // swallow here only so one failure does not break the chain\n // for future writes.\n });\n }\n\n /**\n * Append a single `BUFFER_SURPRISE` telemetry row (issue #563 PR 3).\n *\n * Deliberately swallows write errors: the buffer must never fail to\n * record a turn because the observation ledger is read-only, out of\n * disk, or otherwise unhappy. The log line at debug lets operators\n * confirm the path fired without polluting the error channel.\n */\n private async emitSurpriseEventSafe(\n params: SurpriseTelemetryQueueEntry,\n ): Promise<void> {\n const storage = this.storage;\n if (typeof storage.appendBufferSurpriseEvents !== \"function\") {\n // Older StorageManager / test double without the telemetry sink.\n // Silently skip — core path is still covered by the log line above.\n return;\n }\n const event: BufferSurpriseEvent = {\n event: \"BUFFER_SURPRISE\",\n // Use the decision-time stamp captured when the event was\n // queued, NOT `Date.now()` here — backpressure on the write\n // chain could otherwise shift timestamps into the future relative\n // to when the turn was scored.\n timestamp: params.timestamp,\n bufferKey: params.bufferKey,\n sessionKey: params.sessionKey,\n turnRole: params.turnRole,\n surpriseScore: params.surpriseScore,\n // Use the snapshotted threshold from the queue entry, not the\n // live config — see `SurpriseTelemetryQueueEntry.threshold`\n // doc for the rationale.\n threshold: params.threshold,\n triggeredFlush: params.triggered,\n turnCountInWindow: params.turnCountInWindow,\n };\n try {\n await storage.appendBufferSurpriseEvents([event]);\n } catch (err) {\n // Same guard as `computeSurpriseSafe`: non-Error rejections must\n // not crash the telemetry helper, which would defeat the whole\n // point of isolating the ledger write from the hot path.\n log.debug(\n `buffer[${params.bufferKey}]: surprise telemetry write failed, continuing: ${describeError(err)}`,\n );\n }\n }\n\n /**\n * Invoke the injected surprise probe defensively. Any error (probe throws,\n * embedder unavailable, timeout) is swallowed and logged at debug: the\n * surprise path must never crash the happy-path trigger evaluation. A\n * `null` return indicates \"no score available, fall through to existing\n * triggers\".\n */\n private async computeSurpriseSafe(\n bufferKey: string,\n turn: BufferTurn,\n priorTurns: readonly BufferTurn[],\n ): Promise<number | null> {\n if (!this.surpriseProbe) return null;\n try {\n // Hard timeout around the probe so a hung embedder cannot stall\n // `addTurn()` before `save()`. A slow probe would otherwise\n // prevent the just-appended turn from ever being persisted. The\n // timeout is a soft bound — we race it against the probe, take\n // whichever settles first, and treat the timeout as\n // \"probe unavailable, fall through\" rather than an error that\n // surfaces to the caller.\n const score = await probeWithTimeout(\n this.surpriseProbe.scoreTurn(bufferKey, turn, priorTurns),\n this.config.bufferSurpriseProbeTimeoutMs,\n );\n if (score === null) return null;\n if (typeof score !== \"number\" || !Number.isFinite(score)) {\n log.debug(\n `buffer[${bufferKey}]: surprise probe returned non-finite score (${String(score)}), ignoring`,\n );\n return null;\n }\n // Defensive clamp: formula lives in buffer-surprise.ts, but we never\n // want a misbehaving probe to inject an out-of-range value into the\n // threshold comparison.\n if (score < 0) return 0;\n if (score > 1) return 1;\n return score;\n } catch (err) {\n // `err` may be any thrown value — `throw null` and\n // `Promise.reject(\"x\")` are both legal. Accessing `.message` on a\n // non-Error would itself throw and defeat the failure-isolation\n // contract, so describe the value safely.\n log.debug(\n `buffer[${bufferKey}]: surprise probe failed, falling back to existing triggers: ${describeError(err)}`,\n );\n return null;\n }\n }\n\n private evaluate(entry: BufferEntryState, signalLevel: SignalLevel): TriggerDecision {\n if (this.config.triggerMode === \"smart\") {\n if (signalLevel === \"high\") return \"extract_now\";\n\n if (entry.turns.length >= this.config.bufferMaxTurns) {\n return \"extract_batch\";\n }\n\n if (entry.lastExtractionAt) {\n const elapsed =\n Date.now() - new Date(entry.lastExtractionAt).getTime();\n if (elapsed >= this.config.bufferMaxMinutes * 60_000) {\n return \"extract_batch\";\n }\n }\n\n return \"keep_buffering\";\n }\n\n if (this.config.triggerMode === \"every_n\") {\n return entry.turns.length >= this.config.bufferMaxTurns\n ? \"extract_batch\"\n : \"keep_buffering\";\n }\n\n if (this.config.triggerMode === \"time_based\") {\n if (!entry.lastExtractionAt) {\n return entry.turns.length >= this.config.bufferMaxTurns\n ? \"extract_batch\"\n : \"keep_buffering\";\n }\n const elapsed =\n Date.now() - new Date(entry.lastExtractionAt).getTime();\n return elapsed >= this.config.bufferMaxMinutes * 60_000\n ? \"extract_batch\"\n : \"keep_buffering\";\n }\n\n return \"keep_buffering\";\n }\n\n getTurns(bufferKey = \"default\"): BufferTurn[] {\n const entry = this.peekEntry(bufferKey);\n if (!entry) return [];\n const retained = entry.retainedTurns ?? [];\n // Retained turns (from a previous defer verdict, issue #562 PR 2) are\n // prepended so the chronological order — oldest context first — is\n // preserved for the next extraction pass.\n return [...retained, ...entry.turns];\n }\n\n /**\n * Retain a subset of the current turns across `clearAfterExtraction` so a\n * future extraction pass sees the context behind a deferred candidate\n * (issue #562, PR 2). Callers pass the turns that were seen during the\n * current extraction; the buffer keeps the tail (latest `max` turns) as\n * the retention window. Passing an empty array or `max <= 0` clears the\n * retention slot instead.\n */\n async retainDeferredTurns(\n bufferKey: string,\n turns: BufferTurn[],\n max = 10,\n originalTurns?: readonly BufferTurn[],\n ): Promise<void> {\n await this.enqueueMutation(async () => {\n await this.loadUnlocked();\n const entry = this.entryFor(bufferKey);\n const retained = selectRetainedDeferredTurns(\n entry.retainedTurns ?? [], turns, max, originalTurns,\n );\n if (retained.length > 0) entry.retainedTurns = retained;\n else delete entry.retainedTurns;\n this.persistence.markDirty(bufferKey);\n await this.saveUnlocked();\n });\n }\n\n /**\n * Return the current retention window (issue #562, PR 2). Primarily for\n * tests and diagnostics.\n */\n getRetainedDeferredTurns(bufferKey = \"default\"): BufferTurn[] {\n const entry = this.peekEntry(bufferKey);\n return entry?.retainedTurns ? [...entry.retainedTurns] : [];\n }\n\n /**\n * Clear deferred retention copies for a force-flushed session. Normal\n * extraction preserves these copies so a deferred candidate can be retried;\n * an explicit force flush is the caller's request to drain that context.\n */\n async clearRetainedTurnsForSession(\n sessionKey: string,\n ownerPrincipal?: string,\n options: RetainedTurnCleanupOptions = {},\n ): Promise<void> {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return;\n const normalizedOwnerPrincipal =\n typeof ownerPrincipal === \"string\" && ownerPrincipal.trim().length > 0\n ? ownerPrincipal.trim()\n : undefined;\n const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces === true;\n const normalizedCleanupNamespace =\n namespacesEnabled && options.writeNamespaceOverride !== undefined && options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : undefined;\n const assertLifecycle = (): void => {\n throwIfAborted(options.abortSignal, \"extraction force-flush aborted\");\n if (typeof options.deadlineMs === \"number\" && Date.now() >= options.deadlineMs) {\n throw new ExtractionDeadlineError(\"retained_turn_cleanup\");\n }\n };\n assertLifecycle();\n await this.enqueueMutation(async () => {\n assertLifecycle();\n const hadPendingSave = this.pendingSave;\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n await this.loadUnlocked();\n assertLifecycle();\n const bufferKeys = this.matchingSessionBufferKeysUnlocked(sessionKey);\n if (bufferKeys.length === 0) {\n if (hadPendingSave) {\n assertLifecycle();\n await this.saveNowRetainingPendingOnFailure(\"clearRetainedTurnsForSession\");\n }\n return;\n }\n let changed = false;\n const matchesCleanupScope = (turn: BufferTurn): boolean => {\n // Legacy unpinned turns keep their existing cleanup semantics.\n if (\n turn.writeNamespaceOverride !== undefined &&\n normalizedCleanupNamespace !== undefined &&\n turn.writeNamespaceOverride !== normalizedCleanupNamespace\n ) {\n return false;\n }\n // Equal write namespaces can still belong to different project bindings.\n if (options.scopeProfileWritePlan && hasPinnedCaptureScope(turn)) {\n if (\n scopeProfilePlanIdentity(turn.scopeProfileWritePlan) !== scopeProfilePlanIdentity(options.scopeProfileWritePlan) &&\n !(turn.acceptedCapture === true && turn.scopeProfileWritePlan === undefined)\n ) {\n return false;\n }\n const ctx = options.codingContext;\n if (\n ctx && turn.codingContext &&\n (turn.codingContext.projectId !== ctx.projectId ||\n turn.codingContext.rootPath !== ctx.rootPath ||\n turn.codingContext.branch !== ctx.branch ||\n turn.codingContext.defaultBranch !== ctx.defaultBranch)\n ) {\n return false;\n }\n }\n return true;\n };\n const belongsToOwner = (turn: BufferTurn): boolean => {\n if (turn.sessionKey !== sessionKey) return false;\n if (!matchesCleanupScope(turn)) return false;\n if (normalizedOwnerPrincipal === undefined) return true;\n if (turn.sessionOwnerPrincipal === normalizedOwnerPrincipal) return true;\n return (\n turn.sessionOwnerPrincipal === undefined &&\n resolvePrincipal(turn.sessionKey, this.config) === normalizedOwnerPrincipal\n );\n };\n for (const bufferKey of bufferKeys) {\n const entry = this.entryFor(bufferKey);\n const retainedTurns = entry.retainedTurns ?? [];\n const remainingTurns = retainedTurns.filter((turn) => !belongsToOwner(turn));\n if (remainingTurns.length === retainedTurns.length) continue;\n changed = true;\n if (remainingTurns.length > 0) entry.retainedTurns = remainingTurns;\n else delete entry.retainedTurns;\n if (bufferKey === \"default\") this.state.turns = entry.turns;\n this.persistence.markDirty(bufferKey);\n }\n if (changed || hadPendingSave) {\n assertLifecycle();\n await this.saveNowRetainingPendingOnFailure(\"clearRetainedTurnsForSession\");\n }\n assertLifecycle();\n });\n }\n\n async findBufferKeyForSession(sessionKey: string): Promise<string | null> {\n const bufferKeys = await this.findBufferKeysForSession(sessionKey);\n return bufferKeys[0] ?? null;\n }\n\n private matchingSessionBufferKeysUnlocked(sessionKey: string): string[] {\n const matches: string[] = [];\n const hasSessionTurns = (entry: BufferEntryState | null | undefined): boolean =>\n [...(entry?.turns ?? []), ...(entry?.retainedTurns ?? [])].some(\n (turn) => typeof turn.sessionKey === \"string\" && turn.sessionKey === sessionKey,\n );\n const directEntry = this.peekEntry(sessionKey);\n if (hasSessionTurns(directEntry)) {\n matches.push(sessionKey);\n }\n\n const entries = this.state.entries ?? {};\n for (const [bufferKey, entry] of Object.entries(entries)) {\n if (!matches.includes(bufferKey) && hasSessionTurns(entry)) {\n matches.push(bufferKey);\n }\n }\n\n return matches;\n }\n\n async findBufferKeysForSession(sessionKey: string): Promise<string[]> {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return [];\n await this.mutationChain.catch(() => {});\n await this.load();\n return this.matchingSessionBufferKeysUnlocked(sessionKey);\n }\n\n async clearAfterExtraction(\n bufferKey = \"default\",\n extractedTurns?: readonly BufferTurn[],\n options?: { allowNonPrefix?: boolean },\n ): Promise<void> {\n await this.enqueueMutation(async () => {\n // Drop any armed debounce TIMER so it cannot fire mid-mutation and race\n // our post-clear write, but KEEP the pending-save state (issue #1909\n // review round 13): the post-clear save below can fail, and clearing the\n // pending flag here would strand buffered turns — including turns from\n // OTHER sessions that only ever entered the debounced pending state — with\n // nothing left to retry them. saveNowRetainingPendingOnFailure clears the\n // pending state only after a durable write, or re-arms it on failure.\n if (this.saveTimer) {\n clearTimeout(this.saveTimer);\n this.saveTimer = null;\n }\n await this.loadUnlocked();\n const entry = this.entryFor(bufferKey);\n if (Array.isArray(extractedTurns)) {\n const liveExtractedTurns = liveTurnsFromExtractionSnapshot(\n entry,\n extractedTurns,\n );\n let clearedLiveTurns = false;\n if (liveExtractedTurns.length > 0) {\n if (options?.allowNonPrefix === true) {\n const remainingTurns = [...entry.turns];\n for (const extractedTurn of liveExtractedTurns) {\n const matchingIndex = remainingTurns.findIndex((liveTurn) =>\n bufferTurnsEqual(liveTurn, extractedTurn),\n );\n if (matchingIndex >= 0) {\n remainingTurns.splice(matchingIndex, 1);\n clearedLiveTurns = true;\n }\n }\n if (clearedLiveTurns) entry.turns = remainingTurns;\n } else {\n const matchedCount = matchingQueuedExtractionPrefixLength(\n entry.turns,\n liveExtractedTurns,\n );\n if (matchedCount > 0) {\n entry.turns = entry.turns.slice(matchedCount);\n clearedLiveTurns = true;\n }\n }\n if (!clearedLiveTurns) {\n log.debug(\n `buffer[${bufferKey}]: extraction clear skipped because live turns changed before clear`,\n );\n }\n }\n if (!clearedLiveTurns) {\n await this.saveNowRetainingPendingOnFailure(\"clearAfterExtraction\");\n return;\n }\n } else {\n entry.turns = [];\n }\n entry.lastExtractionAt = new Date().toISOString();\n entry.extractionCount += 1;\n if (bufferKey === \"default\") {\n this.state.turns = entry.turns;\n this.state.lastExtractionAt = entry.lastExtractionAt;\n this.state.extractionCount = entry.extractionCount;\n }\n this.persistence.markDirty(bufferKey);\n this.pruneEntries([bufferKey]);\n await this.saveNowRetainingPendingOnFailure(\"clearAfterExtraction\");\n });\n }\n\n getExtractionCount(bufferKey = \"default\"): number {\n return this.peekEntry(bufferKey)?.extractionCount ?? 0;\n }\n\n /**\n * Await any pending `BUFFER_SURPRISE` telemetry writes.\n *\n * The telemetry path is fire-and-forget from the hot path's point of\n * view, but tests and before-exit hooks sometimes need to make sure\n * the ledger has been flushed before they assert on its contents or\n * close the process. This method resolves once the current chain\n * head has settled; new writes scheduled after this call return a\n * separate, later settlement.\n *\n * Never throws — the chain already catches its own rejections.\n */\n async flushSurpriseTelemetry(): Promise<void> {\n await this.surpriseTelemetryWriteChain;\n }\n}\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|