@remnic/core 10.0.30 → 10.0.31
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 +47 -46
- package/dist/access-authorization-probe.js +48 -47
- package/dist/access-boundary.js +47 -46
- package/dist/access-cli.js +107 -107
- package/dist/access-extraction-force-flush.d.ts.map +1 -1
- package/dist/access-extraction-force-flush.js +47 -46
- package/dist/access-http-briefing.js +48 -47
- package/dist/access-http-query.js +49 -48
- package/dist/access-http.js +65 -64
- package/dist/access-identity-continuity-surface.js +47 -46
- package/dist/access-lcm-surface.js +47 -46
- package/dist/access-mcp.js +57 -56
- package/dist/access-namespace-preflight.js +47 -46
- package/dist/access-observe-write-surface.d.ts.map +1 -1
- package/dist/access-observe-write-surface.js +47 -46
- package/dist/access-offline-manifest.js +4 -4
- package/dist/access-operations-batch.js +48 -47
- package/dist/access-operations.js +55 -54
- package/dist/access-recall-concurrency.js +47 -46
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +47 -46
- package/dist/access-recall-surface.js +47 -46
- package/dist/access-schema.d.ts +47 -47
- package/dist/access-service.js +47 -46
- package/dist/access-surface-catalog.js +49 -48
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/active-recall.js +20 -20
- package/dist/briefing.js +21 -21
- package/dist/buffer-turn-helpers.d.ts +20 -0
- package/dist/buffer-turn-helpers.d.ts.map +1 -1
- package/dist/buffer-turn-helpers.js +11 -3
- package/dist/buffer-turn.d.ts +50 -0
- package/dist/buffer-turn.d.ts.map +1 -0
- package/dist/buffer-turn.js +1 -0
- package/dist/buffer-turn.js.map +1 -0
- package/dist/buffer.d.ts +13 -1
- package/dist/buffer.d.ts.map +1 -1
- package/dist/buffer.js +4 -4
- package/dist/causal-consolidation.js +26 -26
- package/dist/{chunk-BIE3ZH3N.js → chunk-2IXEKMBJ.js} +143 -112
- package/dist/chunk-2IXEKMBJ.js.map +1 -0
- package/dist/{chunk-YGVZ4QOZ.js → chunk-3CRE3UZI.js} +2 -2
- package/dist/{chunk-YZTFQBYY.js → chunk-3GOPAWA7.js} +3 -3
- package/dist/{chunk-NAPHQ2MG.js → chunk-3IDNKOCE.js} +2 -2
- package/dist/{chunk-PYCTZ2HX.js → chunk-3VYNGM5A.js} +2 -2
- package/dist/{chunk-2XVLY424.js → chunk-42MM5DKK.js} +2 -2
- package/dist/{chunk-CKR7LXEK.js → chunk-464QR7WO.js} +255 -63
- package/dist/chunk-464QR7WO.js.map +1 -0
- package/dist/{chunk-3IXNL6SK.js → chunk-4ZTVOECF.js} +4 -4
- package/dist/{chunk-ETZUIRCI.js → chunk-53GYS3GG.js} +2 -2
- package/dist/{chunk-ZXTAHSQU.js → chunk-5GPHJ333.js} +2 -2
- package/dist/{chunk-AUYFUBBE.js → chunk-5HJCZ7SB.js} +4 -4
- package/dist/{chunk-52II7PB6.js → chunk-645WOU5I.js} +4 -4
- package/dist/{chunk-2WDMUQOH.js → chunk-64IO6ZEE.js} +2 -2
- package/dist/{chunk-OIIAIY7J.js → chunk-7SXUGYPE.js} +3 -3
- package/dist/{chunk-74IN6PV5.js → chunk-7WWITD3H.js} +4 -4
- package/dist/{chunk-7FZ4YVOH.js → chunk-A5ZY537U.js} +2 -2
- package/dist/{chunk-LDXNKEYB.js → chunk-A6PKEU7T.js} +1 -1
- package/dist/chunk-A6PKEU7T.js.map +1 -0
- package/dist/{chunk-VLBFSD7B.js → chunk-APRGEZQN.js} +2 -2
- package/dist/{chunk-XNROYP5E.js → chunk-AQ5XLA36.js} +2 -2
- package/dist/{chunk-K2REHR42.js → chunk-BDHYRMJC.js} +2 -2
- package/dist/{chunk-GQ7VWY6N.js → chunk-BQ6DGL6A.js} +2 -2
- package/dist/{chunk-4OE4UE2Y.js → chunk-D3EXT5KG.js} +2 -2
- package/dist/{chunk-MROA6OFU.js → chunk-DGBWPSM6.js} +2 -2
- package/dist/{chunk-NOMHXZD7.js → chunk-DNZ2CWPG.js} +2 -2
- package/dist/{chunk-HG2VVIKI.js → chunk-DZBMASSI.js} +12 -12
- package/dist/{chunk-NB2YX6X2.js → chunk-EXYDKAR6.js} +5 -5
- package/dist/{chunk-V4FI2TG6.js → chunk-F5FZ7DB4.js} +2 -2
- package/dist/{chunk-IY7DGT2Z.js → chunk-GDPTMK5V.js} +2 -2
- package/dist/{chunk-27OJ5G3D.js → chunk-GJBSEMC5.js} +7 -7
- package/dist/{chunk-MMBLOJJB.js → chunk-HMON55NJ.js} +85 -44
- package/dist/chunk-HMON55NJ.js.map +1 -0
- package/dist/{chunk-C2QVDLQV.js → chunk-HNTB7NIE.js} +2 -2
- package/dist/{chunk-4HNINU7Q.js → chunk-HSPEVXT5.js} +42 -42
- package/dist/{chunk-4QPW6JVI.js → chunk-ID2PLENW.js} +2 -2
- package/dist/{chunk-FN6OFDBZ.js → chunk-ID62FNER.js} +2 -2
- package/dist/{chunk-GSKW64NB.js → chunk-J6SZXAQ2.js} +2 -2
- package/dist/{chunk-3CHHQXAR.js → chunk-JTACUJP3.js} +2 -2
- package/dist/{chunk-3SN2D43X.js → chunk-K6RQ2KOX.js} +2 -2
- package/dist/{chunk-GWB7ZD2A.js → chunk-K6YJGWJP.js} +2 -2
- package/dist/{chunk-OANSZGAG.js → chunk-KFR343VH.js} +2 -2
- package/dist/{chunk-WC3V7HHP.js → chunk-KJZKO2M6.js} +2 -1
- package/dist/chunk-KJZKO2M6.js.map +1 -0
- package/dist/{chunk-T5IF2ZCE.js → chunk-KZMRMKC7.js} +81 -2
- package/dist/chunk-KZMRMKC7.js.map +1 -0
- package/dist/{chunk-NPO4ZQFY.js → chunk-LDXS746V.js} +3 -3
- package/dist/{chunk-UTXYOWDR.js → chunk-LGR54NYT.js} +3 -3
- package/dist/{chunk-UTXYOWDR.js.map → chunk-LGR54NYT.js.map} +1 -1
- package/dist/{chunk-DDLRKPR2.js → chunk-NKW27NU3.js} +2 -2
- package/dist/{chunk-4HYP4OKH.js → chunk-NU247WVX.js} +2 -2
- package/dist/{chunk-RRJ462HP.js → chunk-O6YJI5VX.js} +2 -2
- package/dist/{chunk-WYLBEJQI.js → chunk-OCWNT322.js} +4 -4
- package/dist/{chunk-UUYAW3JH.js → chunk-OIKLZCJD.js} +2 -2
- package/dist/{chunk-IO2UQVR2.js → chunk-OTWZXOJI.js} +2 -2
- package/dist/{chunk-OXYXMGRH.js → chunk-PGHYQMKZ.js} +11 -11
- package/dist/{chunk-LDEKVBVO.js → chunk-PZWW6MDE.js} +2 -2
- package/dist/{chunk-TFA6HPOA.js → chunk-QCP75JGO.js} +5 -5
- package/dist/{chunk-M236YHUH.js → chunk-RILIWZA6.js} +3 -3
- package/dist/{chunk-7VB3Y5OL.js → chunk-RRYN5FFC.js} +4 -4
- package/dist/{chunk-PZEADMX4.js → chunk-RU6WB55E.js} +9 -9
- package/dist/{chunk-VARNSLUW.js → chunk-SGII36L6.js} +2 -2
- package/dist/{chunk-KFKFK6G6.js → chunk-TB2J4PBY.js} +3 -3
- package/dist/{chunk-WQIYGYY6.js → chunk-TEUPXKC5.js} +2 -2
- package/dist/{chunk-VEB7NEON.js → chunk-U4BNX4R2.js} +3 -3
- package/dist/{chunk-7HFTCBCZ.js → chunk-UBBZFODO.js} +2 -2
- package/dist/{chunk-654GT5UP.js → chunk-UZDOPJ2P.js} +2 -2
- package/dist/{chunk-D4RV54HH.js → chunk-VAPVRDC4.js} +2 -2
- package/dist/{chunk-OXX4ORRL.js → chunk-W7X7XT7Z.js} +15 -15
- package/dist/{chunk-5NPZFXQH.js → chunk-WK7GFAQ2.js} +2 -2
- package/dist/{chunk-G6DAE2LT.js → chunk-WPCK6EJ2.js} +2 -2
- package/dist/{chunk-VKQI47DJ.js → chunk-Y7427SL7.js} +4 -4
- package/dist/{chunk-ZCRDYQL6.js → chunk-YGBWSKBD.js} +2 -2
- package/dist/{chunk-NCPR2FOJ.js → chunk-YXWLQHAW.js} +2 -2
- package/dist/{chunk-UM73Q46J.js → chunk-ZEMBRSKK.js} +2 -2
- package/dist/{chunk-TTIEXXL3.js → chunk-ZGP2XB4S.js} +16 -16
- package/dist/{chunk-UVUBLLM3.js → chunk-ZY4S5WMQ.js} +2 -2
- package/dist/cli.js +83 -82
- package/dist/coding/export-okf-codegraph.js +20 -20
- package/dist/compounding/engine.js +22 -22
- package/dist/config.js +20 -20
- package/dist/connectors/codex-materialize-runner.js +21 -21
- package/dist/connectors/index.js +21 -21
- package/dist/convergence-refresh.js +23 -23
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +23 -23
- package/dist/entity-retrieval.js +22 -22
- package/dist/event-order-recall.js +3 -3
- package/dist/external-wiki-access.js +48 -47
- package/dist/extraction.js +31 -31
- package/dist/harmonic-retrieval.js +21 -21
- package/dist/index.js +126 -126
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +2 -2
- package/dist/location/index.js +23 -23
- package/dist/maintenance/memory-governance.js +21 -21
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +21 -21
- package/dist/maintenance/rebuild-memory-projection-runner.js +23 -23
- package/dist/maintenance/rebuild-memory-projection.js +22 -22
- package/dist/memory-browse-operations.js +48 -47
- package/dist/namespaces/migrate.js +22 -22
- package/dist/namespaces/scope-profiles.d.ts +1 -0
- package/dist/namespaces/scope-profiles.d.ts.map +1 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.js +21 -21
- package/dist/offline-sync-impression-drain.js +3 -3
- package/dist/operator-doctor-corpus.js +24 -24
- package/dist/operator-toolkit.js +32 -32
- package/dist/orchestration/maintenance.js +33 -33
- package/dist/orchestration/session-context.d.ts +6 -0
- package/dist/orchestration/session-context.d.ts.map +1 -1
- package/dist/orchestration/turn-ingestion.d.ts +35 -1
- package/dist/orchestration/turn-ingestion.d.ts.map +1 -1
- package/dist/orchestrator.d.ts +2 -32
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +107 -107
- 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 +48 -47
- package/dist/recall-navigation.js +47 -46
- 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/relay/mission.d.ts +2 -2
- package/dist/resume-bundles.js +20 -20
- package/dist/schemas.d.ts +4 -4
- package/dist/search/factory.js +8 -8
- package/dist/search/index.js +13 -13
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +22 -22
- package/dist/semantic-rule-promotion.js +21 -21
- package/dist/semantic-rule-verifier.js +21 -21
- package/dist/source-agent-qualifier.js +24 -24
- package/dist/standup/build.js +21 -21
- package/dist/storage.js +20 -20
- package/dist/support-passport/contracts.d.ts +6 -6
- package/dist/support-passport/grant-contracts.d.ts +4 -4
- package/dist/support-passport/index.js +50 -49
- package/dist/transfer/export-okf.js +21 -21
- package/dist/types.d.ts +3 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +21 -21
- package/dist/who-knows-cli.js +22 -22
- package/dist/who-knows.js +21 -21
- package/package.json +2 -2
- package/src/access-extraction-force-flush.ts +37 -25
- package/src/access-observe-acceptance-boundary.test.ts +172 -0
- package/src/access-observe-replay-durability.test.ts +2212 -0
- package/src/access-observe-write-surface.ts +36 -41
- package/src/access-service-observe-lcm-parity.test.ts +63 -39
- package/src/access-service-observe-scope.test.ts +3 -2
- package/src/buffer-turn-helpers.ts +120 -1
- package/src/buffer-turn.ts +50 -0
- package/src/buffer.ts +115 -49
- package/src/namespaces/scope-profiles.ts +1 -1
- package/src/orchestration/extraction-run.ts +1 -1
- package/src/orchestration/session-context.ts +117 -49
- package/src/orchestration/turn-ingestion.ts +313 -9
- package/src/orchestrator-flush.test.ts +16 -3
- package/src/orchestrator.ts +2 -32
- package/src/types.ts +3 -17
- package/dist/chunk-BIE3ZH3N.js.map +0 -1
- package/dist/chunk-CKR7LXEK.js.map +0 -1
- package/dist/chunk-LDXNKEYB.js.map +0 -1
- package/dist/chunk-MMBLOJJB.js.map +0 -1
- package/dist/chunk-T5IF2ZCE.js.map +0 -1
- package/dist/chunk-WC3V7HHP.js.map +0 -1
- /package/dist/{chunk-YGVZ4QOZ.js.map → chunk-3CRE3UZI.js.map} +0 -0
- /package/dist/{chunk-YZTFQBYY.js.map → chunk-3GOPAWA7.js.map} +0 -0
- /package/dist/{chunk-NAPHQ2MG.js.map → chunk-3IDNKOCE.js.map} +0 -0
- /package/dist/{chunk-PYCTZ2HX.js.map → chunk-3VYNGM5A.js.map} +0 -0
- /package/dist/{chunk-2XVLY424.js.map → chunk-42MM5DKK.js.map} +0 -0
- /package/dist/{chunk-3IXNL6SK.js.map → chunk-4ZTVOECF.js.map} +0 -0
- /package/dist/{chunk-ETZUIRCI.js.map → chunk-53GYS3GG.js.map} +0 -0
- /package/dist/{chunk-ZXTAHSQU.js.map → chunk-5GPHJ333.js.map} +0 -0
- /package/dist/{chunk-AUYFUBBE.js.map → chunk-5HJCZ7SB.js.map} +0 -0
- /package/dist/{chunk-52II7PB6.js.map → chunk-645WOU5I.js.map} +0 -0
- /package/dist/{chunk-2WDMUQOH.js.map → chunk-64IO6ZEE.js.map} +0 -0
- /package/dist/{chunk-OIIAIY7J.js.map → chunk-7SXUGYPE.js.map} +0 -0
- /package/dist/{chunk-74IN6PV5.js.map → chunk-7WWITD3H.js.map} +0 -0
- /package/dist/{chunk-7FZ4YVOH.js.map → chunk-A5ZY537U.js.map} +0 -0
- /package/dist/{chunk-VLBFSD7B.js.map → chunk-APRGEZQN.js.map} +0 -0
- /package/dist/{chunk-XNROYP5E.js.map → chunk-AQ5XLA36.js.map} +0 -0
- /package/dist/{chunk-K2REHR42.js.map → chunk-BDHYRMJC.js.map} +0 -0
- /package/dist/{chunk-GQ7VWY6N.js.map → chunk-BQ6DGL6A.js.map} +0 -0
- /package/dist/{chunk-4OE4UE2Y.js.map → chunk-D3EXT5KG.js.map} +0 -0
- /package/dist/{chunk-MROA6OFU.js.map → chunk-DGBWPSM6.js.map} +0 -0
- /package/dist/{chunk-NOMHXZD7.js.map → chunk-DNZ2CWPG.js.map} +0 -0
- /package/dist/{chunk-HG2VVIKI.js.map → chunk-DZBMASSI.js.map} +0 -0
- /package/dist/{chunk-NB2YX6X2.js.map → chunk-EXYDKAR6.js.map} +0 -0
- /package/dist/{chunk-V4FI2TG6.js.map → chunk-F5FZ7DB4.js.map} +0 -0
- /package/dist/{chunk-IY7DGT2Z.js.map → chunk-GDPTMK5V.js.map} +0 -0
- /package/dist/{chunk-27OJ5G3D.js.map → chunk-GJBSEMC5.js.map} +0 -0
- /package/dist/{chunk-C2QVDLQV.js.map → chunk-HNTB7NIE.js.map} +0 -0
- /package/dist/{chunk-4HNINU7Q.js.map → chunk-HSPEVXT5.js.map} +0 -0
- /package/dist/{chunk-4QPW6JVI.js.map → chunk-ID2PLENW.js.map} +0 -0
- /package/dist/{chunk-FN6OFDBZ.js.map → chunk-ID62FNER.js.map} +0 -0
- /package/dist/{chunk-GSKW64NB.js.map → chunk-J6SZXAQ2.js.map} +0 -0
- /package/dist/{chunk-3CHHQXAR.js.map → chunk-JTACUJP3.js.map} +0 -0
- /package/dist/{chunk-3SN2D43X.js.map → chunk-K6RQ2KOX.js.map} +0 -0
- /package/dist/{chunk-GWB7ZD2A.js.map → chunk-K6YJGWJP.js.map} +0 -0
- /package/dist/{chunk-OANSZGAG.js.map → chunk-KFR343VH.js.map} +0 -0
- /package/dist/{chunk-NPO4ZQFY.js.map → chunk-LDXS746V.js.map} +0 -0
- /package/dist/{chunk-DDLRKPR2.js.map → chunk-NKW27NU3.js.map} +0 -0
- /package/dist/{chunk-4HYP4OKH.js.map → chunk-NU247WVX.js.map} +0 -0
- /package/dist/{chunk-RRJ462HP.js.map → chunk-O6YJI5VX.js.map} +0 -0
- /package/dist/{chunk-WYLBEJQI.js.map → chunk-OCWNT322.js.map} +0 -0
- /package/dist/{chunk-UUYAW3JH.js.map → chunk-OIKLZCJD.js.map} +0 -0
- /package/dist/{chunk-IO2UQVR2.js.map → chunk-OTWZXOJI.js.map} +0 -0
- /package/dist/{chunk-OXYXMGRH.js.map → chunk-PGHYQMKZ.js.map} +0 -0
- /package/dist/{chunk-LDEKVBVO.js.map → chunk-PZWW6MDE.js.map} +0 -0
- /package/dist/{chunk-TFA6HPOA.js.map → chunk-QCP75JGO.js.map} +0 -0
- /package/dist/{chunk-M236YHUH.js.map → chunk-RILIWZA6.js.map} +0 -0
- /package/dist/{chunk-7VB3Y5OL.js.map → chunk-RRYN5FFC.js.map} +0 -0
- /package/dist/{chunk-PZEADMX4.js.map → chunk-RU6WB55E.js.map} +0 -0
- /package/dist/{chunk-VARNSLUW.js.map → chunk-SGII36L6.js.map} +0 -0
- /package/dist/{chunk-KFKFK6G6.js.map → chunk-TB2J4PBY.js.map} +0 -0
- /package/dist/{chunk-WQIYGYY6.js.map → chunk-TEUPXKC5.js.map} +0 -0
- /package/dist/{chunk-VEB7NEON.js.map → chunk-U4BNX4R2.js.map} +0 -0
- /package/dist/{chunk-7HFTCBCZ.js.map → chunk-UBBZFODO.js.map} +0 -0
- /package/dist/{chunk-654GT5UP.js.map → chunk-UZDOPJ2P.js.map} +0 -0
- /package/dist/{chunk-D4RV54HH.js.map → chunk-VAPVRDC4.js.map} +0 -0
- /package/dist/{chunk-OXX4ORRL.js.map → chunk-W7X7XT7Z.js.map} +0 -0
- /package/dist/{chunk-5NPZFXQH.js.map → chunk-WK7GFAQ2.js.map} +0 -0
- /package/dist/{chunk-G6DAE2LT.js.map → chunk-WPCK6EJ2.js.map} +0 -0
- /package/dist/{chunk-VKQI47DJ.js.map → chunk-Y7427SL7.js.map} +0 -0
- /package/dist/{chunk-ZCRDYQL6.js.map → chunk-YGBWSKBD.js.map} +0 -0
- /package/dist/{chunk-NCPR2FOJ.js.map → chunk-YXWLQHAW.js.map} +0 -0
- /package/dist/{chunk-UM73Q46J.js.map → chunk-ZEMBRSKK.js.map} +0 -0
- /package/dist/{chunk-TTIEXXL3.js.map → chunk-ZGP2XB4S.js.map} +0 -0
- /package/dist/{chunk-UVUBLLM3.js.map → chunk-ZY4S5WMQ.js.map} +0 -0
package/src/buffer.ts
CHANGED
|
@@ -10,8 +10,9 @@ import type {
|
|
|
10
10
|
PluginConfig,
|
|
11
11
|
SignalLevel,
|
|
12
12
|
} from "./types.js";
|
|
13
|
-
import { resolvePresentationCapabilities } from "./capabilities.js";
|
|
13
|
+
import { resolvePresentationCapabilities, resolveNamespaceCapabilities } from "./capabilities.js";
|
|
14
14
|
import { resolvePrincipal } from "./namespaces/principal.js";
|
|
15
|
+
import { scopeProfilePlanIdentity } from "./buffer-turn-helpers.js";
|
|
15
16
|
import { ExtractionDeadlineError } from "./orchestration/extraction-run.js";
|
|
16
17
|
import type { ExtractionBufferSnapshot } from "./extraction-liveness.js";
|
|
17
18
|
import {
|
|
@@ -20,9 +21,11 @@ import {
|
|
|
20
21
|
bufferTurnsEqual,
|
|
21
22
|
copyBufferTurn,
|
|
22
23
|
describeError,
|
|
24
|
+
hasPinnedCaptureScope,
|
|
23
25
|
liveTurnsFromExtractionSnapshot,
|
|
24
26
|
matchingQueuedExtractionPrefixLength,
|
|
25
27
|
probeWithTimeout,
|
|
28
|
+
selectRetainedDeferredTurns,
|
|
26
29
|
} from "./buffer-turn-helpers.js";
|
|
27
30
|
|
|
28
31
|
export type TriggerDecision = "extract_now" | "extract_batch" | "keep_buffering";
|
|
@@ -35,6 +38,11 @@ export interface AddTurnOutcome {
|
|
|
35
38
|
export interface RetainedTurnCleanupOptions {
|
|
36
39
|
abortSignal?: AbortSignal;
|
|
37
40
|
deadlineMs?: number;
|
|
41
|
+
/** Keep cleanup within the accepted namespace. */
|
|
42
|
+
writeNamespaceOverride?: string;
|
|
43
|
+
/** Match the original profile and project binding, not just its write namespace. */
|
|
44
|
+
scopeProfileWritePlan?: import("./namespaces/scope-profiles.js").ResolvedScopeProfilePlan | null;
|
|
45
|
+
codingContext?: import("./types.js").CodingContext;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
/**
|
|
@@ -65,6 +73,8 @@ export interface BufferSurpriseProbe {
|
|
|
65
73
|
}
|
|
66
74
|
|
|
67
75
|
const MAX_BUFFER_ENTRY_COUNT = 200;
|
|
76
|
+
const isAcceptedTurn = (t: { acceptedCapture?: boolean; writeNamespaceOverride?: string }): boolean =>
|
|
77
|
+
t.acceptedCapture === true || t.writeNamespaceOverride !== undefined;
|
|
68
78
|
|
|
69
79
|
/**
|
|
70
80
|
* Upper bound on how long a debounced buffer save may be deferred under
|
|
@@ -272,7 +282,13 @@ export class SmartBuffer {
|
|
|
272
282
|
if (leftAt !== rightAt) return leftAt - rightAt;
|
|
273
283
|
return (insertionOrder.get(left) ?? 0) - (insertionOrder.get(right) ?? 0);
|
|
274
284
|
};
|
|
275
|
-
const candidates = keys.filter(
|
|
285
|
+
const candidates = keys.filter(
|
|
286
|
+
(key) =>
|
|
287
|
+
key !== "default" &&
|
|
288
|
+
!retainKeys.includes(key) &&
|
|
289
|
+
// #3251: accepted captures exit via refusal/backpressure, never eviction.
|
|
290
|
+
!this.entryHoldsAcceptedCapture(entries[key]),
|
|
291
|
+
);
|
|
276
292
|
const emptyRemovable = candidates
|
|
277
293
|
.filter((key) => (entries[key]?.turns.length ?? 0) === 0)
|
|
278
294
|
.sort(byOldestActivity);
|
|
@@ -524,11 +540,66 @@ export class SmartBuffer {
|
|
|
524
540
|
return (await this.addTurnWithOutcome(bufferKey, turn)).decision;
|
|
525
541
|
}
|
|
526
542
|
|
|
543
|
+
/** Admit atomically; refuse at capacity rather than evict accepted work. */
|
|
544
|
+
async addTurnBounded(bufferKey: string, turn: BufferTurn): Promise<AddTurnOutcome | null> {
|
|
545
|
+
const mutation = await this.enqueueMutation(async () => {
|
|
546
|
+
await this.loadUnlocked();
|
|
547
|
+
if (this.peekEntry(bufferKey) === null) {
|
|
548
|
+
this.makeRoomForEntryUnlocked();
|
|
549
|
+
if (Object.keys(this.state.entries ?? {}).length >= MAX_BUFFER_ENTRY_COUNT) {
|
|
550
|
+
log.warn(
|
|
551
|
+
`buffer[${bufferKey}]: durable capture refused at MAX_BUFFER_ENTRY_COUNT=${MAX_BUFFER_ENTRY_COUNT}`,
|
|
552
|
+
);
|
|
553
|
+
return null;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return this.recordTurnUnlocked(bufferKey, turn);
|
|
557
|
+
});
|
|
558
|
+
if (mutation === null) return null;
|
|
559
|
+
return this.completeAddTurnOutcome(bufferKey, turn, mutation);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/** Prune empty entries only; accepted work must survive capacity pressure. */
|
|
563
|
+
private makeRoomForEntryUnlocked(): void {
|
|
564
|
+
const entries = this.state.entries;
|
|
565
|
+
if (!entries) return;
|
|
566
|
+
const keys = Object.keys(entries);
|
|
567
|
+
if (keys.length < MAX_BUFFER_ENTRY_COUNT) return;
|
|
568
|
+
const byOldestActivity = (left: string, right: string): number =>
|
|
569
|
+
this.entryActivityAt(entries[left] ?? { turns: [], lastExtractionAt: null, extractionCount: 0 }) -
|
|
570
|
+
this.entryActivityAt(entries[right] ?? { turns: [], lastExtractionAt: null, extractionCount: 0 });
|
|
571
|
+
const emptyRemovable = keys
|
|
572
|
+
.filter(
|
|
573
|
+
(key) =>
|
|
574
|
+
key !== "default" &&
|
|
575
|
+
(entries[key]?.turns.length ?? 0) === 0 &&
|
|
576
|
+
(entries[key]?.retainedTurns?.length ?? 0) === 0,
|
|
577
|
+
)
|
|
578
|
+
.sort(byOldestActivity);
|
|
579
|
+
for (const key of emptyRemovable) {
|
|
580
|
+
if (Object.keys(entries).length < MAX_BUFFER_ENTRY_COUNT) break;
|
|
581
|
+
delete entries[key];
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
private entryHoldsAcceptedCapture(entry: BufferEntryState | undefined): boolean {
|
|
586
|
+
return (entry?.turns ?? []).some(isAcceptedTurn) || (entry?.retainedTurns ?? []).some(isAcceptedTurn);
|
|
587
|
+
}
|
|
588
|
+
|
|
527
589
|
async addTurnWithOutcome(
|
|
528
590
|
bufferKey: string,
|
|
529
591
|
turn: BufferTurn,
|
|
530
592
|
): Promise<AddTurnOutcome> {
|
|
531
593
|
const mutation = await this.enqueueMutation(() => this.recordTurnUnlocked(bufferKey, turn));
|
|
594
|
+
return this.completeAddTurnOutcome(bufferKey, turn, mutation);
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/** Run probes outside the mutation lock to avoid reentrancy deadlocks. */
|
|
598
|
+
private async completeAddTurnOutcome(
|
|
599
|
+
bufferKey: string,
|
|
600
|
+
turn: BufferTurn,
|
|
601
|
+
mutation: AddTurnMutationResult,
|
|
602
|
+
): Promise<AddTurnOutcome> {
|
|
532
603
|
let decision = mutation.decision;
|
|
533
604
|
let extractionTurns: BufferTurn[] | undefined;
|
|
534
605
|
|
|
@@ -874,61 +945,20 @@ export class SmartBuffer {
|
|
|
874
945
|
bufferKey: string,
|
|
875
946
|
turns: BufferTurn[],
|
|
876
947
|
max = 10,
|
|
948
|
+
originalTurns?: readonly BufferTurn[],
|
|
877
949
|
): Promise<void> {
|
|
878
950
|
await this.enqueueMutation(async () => {
|
|
879
951
|
await this.loadUnlocked();
|
|
880
952
|
const entry = this.entryFor(bufferKey);
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
// already early-return above when max <= 0.
|
|
887
|
-
const tail = turns.slice(-max);
|
|
888
|
-
// Copy explicit fields only — never spread an external object into a
|
|
889
|
-
// plain object because spread preserves any own `__proto__` /
|
|
890
|
-
// `constructor` keys that may have arrived via JSON deserialization
|
|
891
|
-
// of untrusted input (CodeQL js/prototype-polluting-assignment).
|
|
892
|
-
entry.retainedTurns = tail.map<BufferTurn>((t) => {
|
|
893
|
-
const copy: BufferTurn = {
|
|
894
|
-
role: t.role,
|
|
895
|
-
content: typeof t.content === "string" ? t.content : "",
|
|
896
|
-
timestamp:
|
|
897
|
-
typeof t.timestamp === "string"
|
|
898
|
-
? t.timestamp
|
|
899
|
-
: new Date().toISOString(),
|
|
900
|
-
};
|
|
901
|
-
if (typeof t.sessionKey === "string") copy.sessionKey = t.sessionKey;
|
|
902
|
-
if (typeof t.sessionOwnerPrincipal === "string") {
|
|
903
|
-
copy.sessionOwnerPrincipal = t.sessionOwnerPrincipal;
|
|
904
|
-
}
|
|
905
|
-
if (typeof t.logicalSessionKey === "string") {
|
|
906
|
-
copy.logicalSessionKey = t.logicalSessionKey;
|
|
907
|
-
}
|
|
908
|
-
if (
|
|
909
|
-
t.providerThreadId === null ||
|
|
910
|
-
typeof t.providerThreadId === "string"
|
|
911
|
-
) {
|
|
912
|
-
copy.providerThreadId = t.providerThreadId;
|
|
913
|
-
}
|
|
914
|
-
if (typeof t.turnFingerprint === "string") {
|
|
915
|
-
copy.turnFingerprint = t.turnFingerprint;
|
|
916
|
-
}
|
|
917
|
-
if (typeof t.persistProcessedFingerprint === "boolean") {
|
|
918
|
-
copy.persistProcessedFingerprint = t.persistProcessedFingerprint;
|
|
919
|
-
}
|
|
920
|
-
if (typeof t.sourceConnector === "string") copy.sourceConnector = t.sourceConnector;
|
|
921
|
-
if (t.originRole === "user" || t.originRole === "assistant" || t.originRole === "tool") {
|
|
922
|
-
copy.originRole = t.originRole;
|
|
923
|
-
}
|
|
924
|
-
return copy;
|
|
925
|
-
});
|
|
926
|
-
}
|
|
953
|
+
const retained = selectRetainedDeferredTurns(
|
|
954
|
+
entry.retainedTurns ?? [], turns, max, originalTurns,
|
|
955
|
+
);
|
|
956
|
+
if (retained.length > 0) entry.retainedTurns = retained;
|
|
957
|
+
else delete entry.retainedTurns;
|
|
927
958
|
await this.saveUnlocked();
|
|
928
959
|
});
|
|
929
960
|
}
|
|
930
961
|
|
|
931
|
-
|
|
932
962
|
/**
|
|
933
963
|
* Return the current retention window (issue #562, PR 2). Primarily for
|
|
934
964
|
* tests and diagnostics.
|
|
@@ -953,6 +983,11 @@ export class SmartBuffer {
|
|
|
953
983
|
typeof ownerPrincipal === "string" && ownerPrincipal.trim().length > 0
|
|
954
984
|
? ownerPrincipal.trim()
|
|
955
985
|
: undefined;
|
|
986
|
+
const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces === true;
|
|
987
|
+
const normalizedCleanupNamespace =
|
|
988
|
+
namespacesEnabled && options.writeNamespaceOverride !== undefined && options.writeNamespaceOverride.length > 0
|
|
989
|
+
? options.writeNamespaceOverride
|
|
990
|
+
: undefined;
|
|
956
991
|
const assertLifecycle = (): void => {
|
|
957
992
|
throwIfAborted(options.abortSignal, "extraction force-flush aborted");
|
|
958
993
|
if (typeof options.deadlineMs === "number" && Date.now() >= options.deadlineMs) {
|
|
@@ -978,8 +1013,39 @@ export class SmartBuffer {
|
|
|
978
1013
|
return;
|
|
979
1014
|
}
|
|
980
1015
|
let changed = false;
|
|
1016
|
+
const matchesCleanupScope = (turn: BufferTurn): boolean => {
|
|
1017
|
+
// Legacy unpinned turns keep their existing cleanup semantics.
|
|
1018
|
+
if (
|
|
1019
|
+
turn.writeNamespaceOverride !== undefined &&
|
|
1020
|
+
normalizedCleanupNamespace !== undefined &&
|
|
1021
|
+
turn.writeNamespaceOverride !== normalizedCleanupNamespace
|
|
1022
|
+
) {
|
|
1023
|
+
return false;
|
|
1024
|
+
}
|
|
1025
|
+
// Equal write namespaces can still belong to different project bindings.
|
|
1026
|
+
if (options.scopeProfileWritePlan && hasPinnedCaptureScope(turn)) {
|
|
1027
|
+
if (
|
|
1028
|
+
scopeProfilePlanIdentity(turn.scopeProfileWritePlan) !== scopeProfilePlanIdentity(options.scopeProfileWritePlan) &&
|
|
1029
|
+
!(turn.acceptedCapture === true && turn.scopeProfileWritePlan === undefined)
|
|
1030
|
+
) {
|
|
1031
|
+
return false;
|
|
1032
|
+
}
|
|
1033
|
+
const ctx = options.codingContext;
|
|
1034
|
+
if (
|
|
1035
|
+
ctx && turn.codingContext &&
|
|
1036
|
+
(turn.codingContext.projectId !== ctx.projectId ||
|
|
1037
|
+
turn.codingContext.rootPath !== ctx.rootPath ||
|
|
1038
|
+
turn.codingContext.branch !== ctx.branch ||
|
|
1039
|
+
turn.codingContext.defaultBranch !== ctx.defaultBranch)
|
|
1040
|
+
) {
|
|
1041
|
+
return false;
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
return true;
|
|
1045
|
+
};
|
|
981
1046
|
const belongsToOwner = (turn: BufferTurn): boolean => {
|
|
982
1047
|
if (turn.sessionKey !== sessionKey) return false;
|
|
1048
|
+
if (!matchesCleanupScope(turn)) return false;
|
|
983
1049
|
if (normalizedOwnerPrincipal === undefined) return true;
|
|
984
1050
|
if (turn.sessionOwnerPrincipal === normalizedOwnerPrincipal) return true;
|
|
985
1051
|
return (
|
|
@@ -87,7 +87,7 @@ function scopeProfileSelfNamespace(principal: string | undefined, config: Plugin
|
|
|
87
87
|
return derivedScopeProfileSelfNamespace(principal, config) ?? existing;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
function hasExplicitNamespacePolicy(namespace: string, config: PluginConfig): boolean {
|
|
90
|
+
export function hasExplicitNamespacePolicy(namespace: string, config: PluginConfig): boolean {
|
|
91
91
|
const identity = normalizeNamespaceIdentity(namespace);
|
|
92
92
|
return (config.namespacePolicies ?? []).some(
|
|
93
93
|
(policy) => normalizeNamespaceIdentity(policy.name) === identity,
|
|
@@ -1108,7 +1108,7 @@ export class ExtractionRunCoordinator {
|
|
|
1108
1108
|
normalizedTurns: normalizedTurns as BufferTurn[],
|
|
1109
1109
|
bufferKey,
|
|
1110
1110
|
retainDeferredTurns: (key, retainedTurns, max) =>
|
|
1111
|
-
this.deps.getBuffer().retainDeferredTurns(key, retainedTurns, max),
|
|
1111
|
+
this.deps.getBuffer().retainDeferredTurns(key, retainedTurns, max, turns),
|
|
1112
1112
|
clearBuffer,
|
|
1113
1113
|
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
1114
1114
|
});
|
|
@@ -28,6 +28,7 @@ import type { ExtractionRunResult } from "./extraction-run.js";
|
|
|
28
28
|
import type { EntitySynthesisCoordinator } from "./entity-synthesis-coordinator.js";
|
|
29
29
|
import type { BufferTurn, CodingContext, DaySummaryResult, MemoryFile, PluginConfig } from "../types.js";
|
|
30
30
|
import type { ResolvedScopeProfilePlan } from "../namespaces/scope-profiles.js";
|
|
31
|
+
import { groupTurnsByExtractionScope, hasPinnedCaptureScope, scopeProfilePlanIdentity } from "../buffer-turn-helpers.js";
|
|
31
32
|
import {
|
|
32
33
|
Orchestrator,
|
|
33
34
|
} from "../orchestrator.js";
|
|
@@ -103,6 +104,12 @@ export interface SessionFlushOptions {
|
|
|
103
104
|
/** Resolved profile plan from access scope resolution; avoids recomputing from shared session context. */
|
|
104
105
|
scopeProfileWritePlan?: ResolvedScopeProfilePlan | null;
|
|
105
106
|
principalOverride?: string;
|
|
107
|
+
/**
|
|
108
|
+
* #3251: the ALREADY-resolved native coding context this flush's plan was
|
|
109
|
+
* resolved with — plan-pinned flushes drain only captures bound to the
|
|
110
|
+
* SAME project identity.
|
|
111
|
+
*/
|
|
112
|
+
codingContext?: CodingContext;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
115
|
/** Scoped flushes must never claim an opaque buffer without trusted ingestion ownership. */
|
|
@@ -475,8 +482,49 @@ export class SessionContextCoordinator {
|
|
|
475
482
|
ownershipEnforced &&
|
|
476
483
|
ownerPrincipal !== undefined &&
|
|
477
484
|
(resolvedSessionPrincipal === undefined || resolvedSessionPrincipal === "default");
|
|
485
|
+
// #3251: the flush's effective write namespace. An explicit override pins
|
|
486
|
+
// it; otherwise it is the session principal's default store. Only PINNED
|
|
487
|
+
// captures are namespace-compared — legacy unpinned turns keep their
|
|
488
|
+
// prior semantics (any flush of their session drains them), while a
|
|
489
|
+
// pinned capture is never drained under a different namespace.
|
|
490
|
+
const flushNamespace =
|
|
491
|
+
options.writeNamespaceOverride !== undefined
|
|
492
|
+
? options.writeNamespaceOverride
|
|
493
|
+
: namespacesEnabled && this.deps.config
|
|
494
|
+
? defaultNamespaceForPrincipal(resolvePrincipal(sessionKey, this.deps.config), this.deps.config)
|
|
495
|
+
: undefined;
|
|
478
496
|
const belongsToSession = (turn: BufferTurn): boolean => {
|
|
479
497
|
if (turn.sessionKey !== sessionKey) return false;
|
|
498
|
+
if (
|
|
499
|
+
namespacesEnabled &&
|
|
500
|
+
turn.writeNamespaceOverride !== undefined &&
|
|
501
|
+
turn.writeNamespaceOverride !== flushNamespace
|
|
502
|
+
) {
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
// Existing profile pins require the same profile and project binding.
|
|
506
|
+
// Accepted no-plan captures stay unprofiled within the matching namespace.
|
|
507
|
+
const flushPlanIdentity = scopeProfilePlanIdentity(options.scopeProfileWritePlan);
|
|
508
|
+
if (flushPlanIdentity !== "" && hasPinnedCaptureScope(turn)) {
|
|
509
|
+
if (
|
|
510
|
+
scopeProfilePlanIdentity(turn.scopeProfileWritePlan) !== flushPlanIdentity &&
|
|
511
|
+
!(turn.acceptedCapture === true && turn.scopeProfileWritePlan === undefined)
|
|
512
|
+
) {
|
|
513
|
+
return false;
|
|
514
|
+
}
|
|
515
|
+
// Compare bindings only when the ORIGINAL capture is context-bound —
|
|
516
|
+
// an unbound capture must not be orphaned by a project attached later.
|
|
517
|
+
if (
|
|
518
|
+
options.codingContext &&
|
|
519
|
+
turn.codingContext &&
|
|
520
|
+
(turn.codingContext.projectId !== options.codingContext.projectId ||
|
|
521
|
+
turn.codingContext.rootPath !== options.codingContext.rootPath ||
|
|
522
|
+
turn.codingContext.branch !== options.codingContext.branch ||
|
|
523
|
+
turn.codingContext.defaultBranch !== options.codingContext.defaultBranch)
|
|
524
|
+
) {
|
|
525
|
+
return false;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
480
528
|
if (!ownershipEnforced || ownerPrincipal === undefined) return true;
|
|
481
529
|
if (turn.sessionOwnerPrincipal === ownerPrincipal) return true;
|
|
482
530
|
return (
|
|
@@ -499,60 +547,80 @@ export class SessionContextCoordinator {
|
|
|
499
547
|
}
|
|
500
548
|
for (const bufferKey of bufferKeys) {
|
|
501
549
|
const turns = this.deps.buffer.getTurns(bufferKey);
|
|
502
|
-
|
|
550
|
+
// #3251: EVERY flush filters — unqualified lifecycle drains must not
|
|
551
|
+
// clear another namespace's pinned capture; single-store mode no-ops
|
|
552
|
+
// the filter (namespacesEnabled gate inside belongsToSession).
|
|
553
|
+
const turnsForSession = turns.filter(belongsToSession);
|
|
503
554
|
if (turnsForSession.length === 0) continue;
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
if (options.reason === "session_end" && this.deps.config.sessionExperience?.enabled === true) {
|
|
532
|
-
await this.extractSessionEndExperience(turnsForSession, sessionKey, options);
|
|
555
|
+
const scopeGroups = groupTurnsByExtractionScope(turnsForSession);
|
|
556
|
+
// Filtered or grouped slices need identity clearing rather than prefix clearing.
|
|
557
|
+
const needsIdentityClear =
|
|
558
|
+
turnsForSession.length < turns.length || scopeGroups.length > 1;
|
|
559
|
+
const namespacesOn = this.deps.config
|
|
560
|
+
? resolveNamespaceCapabilities(this.deps.config).namespaces === true
|
|
561
|
+
: true;
|
|
562
|
+
for (const group of scopeGroups) {
|
|
563
|
+
const groupPinned =
|
|
564
|
+
group.writeNamespaceOverride !== undefined ||
|
|
565
|
+
group.principalOverride !== undefined ||
|
|
566
|
+
group.scopeProfileWritePlan !== undefined;
|
|
567
|
+
// Preserve groups captured under another profile or project binding;
|
|
568
|
+
// the binding compares only when the ORIGINAL group is context-bound.
|
|
569
|
+
if (
|
|
570
|
+
group.scopeProfileWritePlan &&
|
|
571
|
+
options.scopeProfileWritePlan &&
|
|
572
|
+
(scopeProfilePlanIdentity(group.scopeProfileWritePlan) !==
|
|
573
|
+
scopeProfilePlanIdentity(options.scopeProfileWritePlan) ||
|
|
574
|
+
(options.codingContext &&
|
|
575
|
+
group.codingContext &&
|
|
576
|
+
(group.codingContext.projectId !== options.codingContext.projectId ||
|
|
577
|
+
group.codingContext.rootPath !== options.codingContext.rootPath ||
|
|
578
|
+
group.codingContext.branch !== options.codingContext.branch ||
|
|
579
|
+
group.codingContext.defaultBranch !== options.codingContext.defaultBranch)))
|
|
580
|
+
) {
|
|
581
|
+
continue;
|
|
533
582
|
}
|
|
534
|
-
|
|
583
|
+
// Force-flush must reject preserved work before retained-turn cleanup can run.
|
|
535
584
|
if (
|
|
536
|
-
|
|
537
|
-
|
|
585
|
+
groupPinned &&
|
|
586
|
+
!namespacesOn &&
|
|
587
|
+
group.writeNamespaceOverride !== undefined &&
|
|
588
|
+
group.writeNamespaceOverride !== this.deps.config?.defaultNamespace
|
|
538
589
|
) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
)
|
|
549
|
-
.catch((error: unknown) => {
|
|
550
|
-
log.warn(
|
|
551
|
-
`session flush could not restore retained turns for other sessions in ${bufferKey}`,
|
|
552
|
-
error,
|
|
553
|
-
);
|
|
554
|
-
});
|
|
590
|
+
if (options.failOnExtractionFailure === true) {
|
|
591
|
+
throw new Error(
|
|
592
|
+
`accepted capture preserved: pinned_namespace_unavailable (${group.writeNamespaceOverride})`,
|
|
593
|
+
);
|
|
594
|
+
}
|
|
595
|
+
log.warn(
|
|
596
|
+
`flushSession: pinned namespace ${group.writeNamespaceOverride} unavailable while namespaces are disabled; capture stays pending`,
|
|
597
|
+
);
|
|
598
|
+
continue;
|
|
555
599
|
}
|
|
600
|
+
const { promise, resolve, reject } = Promise.withResolvers<void>();
|
|
601
|
+
void this.deps.queueBufferedExtraction(group.turns, "trigger_mode", {
|
|
602
|
+
bufferKey,
|
|
603
|
+
clearBufferAfterExtraction: true,
|
|
604
|
+
skipDedupeCheck: true,
|
|
605
|
+
skipCharThreshold: true,
|
|
606
|
+
skipUserTurnThreshold: true,
|
|
607
|
+
failOnExtractionFailure: options.failOnExtractionFailure === true,
|
|
608
|
+
forceExtractionAttempt: true,
|
|
609
|
+
abortSignal: options.abortSignal,
|
|
610
|
+
extractionDeadlineMs: options.extractionDeadlineMs,
|
|
611
|
+
writeNamespaceOverride: group.writeNamespaceOverride ?? options.writeNamespaceOverride,
|
|
612
|
+
principalOverride: group.principalOverride ?? options.principalOverride,
|
|
613
|
+
scopeProfileWritePlan: group.turns.some((turn) => turn.acceptedCapture === true)
|
|
614
|
+
? group.scopeProfileWritePlan ?? null
|
|
615
|
+
: group.scopeProfileWritePlan ?? options.scopeProfileWritePlan,
|
|
616
|
+
clearMatchingTurns: options.clearMatchingTurns === true || scopedRequest || groupPinned || needsIdentityClear,
|
|
617
|
+
onDurableCommit: options.onCommitted,
|
|
618
|
+
onTaskSettled: (error) => (error ? reject(error) : resolve()),
|
|
619
|
+
}).catch(reject);
|
|
620
|
+
await promise;
|
|
621
|
+
}
|
|
622
|
+
if (options.reason === "session_end" && this.deps.config.sessionExperience?.enabled === true) {
|
|
623
|
+
await this.extractSessionEndExperience(turnsForSession, sessionKey, options);
|
|
556
624
|
}
|
|
557
625
|
}
|
|
558
626
|
}
|