@remnic/core 9.69.39 → 9.69.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.d.ts +16 -14
- package/dist/access-admin-ops-surface.js +37 -37
- package/dist/access-authorization-probe.d.ts +16 -14
- package/dist/access-authorization-probe.js +38 -38
- package/dist/access-boundary.d.ts +16 -14
- package/dist/access-boundary.js +37 -37
- package/dist/access-cli.js +98 -97
- package/dist/access-cli.js.map +1 -1
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +16 -14
- package/dist/access-extraction-force-flush.js +37 -37
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-briefing.d.ts +16 -14
- package/dist/access-http-briefing.js +38 -38
- package/dist/access-http-lcm-compaction.d.ts +16 -14
- package/dist/access-http-lifecycle-flush.d.ts +16 -14
- package/dist/access-http-offline-stream.d.ts +16 -14
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +39 -39
- package/dist/access-http.d.ts +17 -15
- package/dist/access-http.js +53 -53
- package/dist/access-identity-continuity-surface.d.ts +13 -12
- package/dist/access-identity-continuity-surface.js +37 -37
- package/dist/access-lcm-surface.d.ts +16 -14
- package/dist/access-lcm-surface.js +37 -37
- package/dist/access-mcp.d.ts +16 -14
- package/dist/access-mcp.js +45 -45
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-DY4z6L5X.d.ts → access-namespace-preflight-CKBumJ8W.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +37 -37
- package/dist/access-observe-transcript.d.ts +13 -12
- package/dist/access-observe-write-category.d.ts +1 -1
- package/dist/access-observe-write-category.js +2 -2
- package/dist/access-observe-write-surface.d.ts +16 -14
- package/dist/access-observe-write-surface.js +37 -37
- package/dist/access-offline-manifest.d.ts +37 -13
- package/dist/access-offline-manifest.js +7 -3
- package/dist/access-operations-batch.js +39 -39
- package/dist/access-operations.d.ts +16 -14
- package/dist/access-operations.js +44 -44
- package/dist/access-recall-concurrency.d.ts +16 -14
- package/dist/access-recall-concurrency.js +37 -37
- package/dist/access-recall-response.d.ts +16 -14
- package/dist/access-recall-response.js +37 -37
- package/dist/access-recall-surface.d.ts +16 -14
- package/dist/access-recall-surface.js +37 -37
- package/dist/access-schema.d.ts +5 -3
- package/dist/access-schema.js +1 -1
- package/dist/{access-service-MY4bsr_Q.d.ts → access-service-DJ3qogNt.d.ts} +8 -8
- package/dist/access-service-helpers.d.ts +16 -14
- package/dist/access-service.d.ts +16 -14
- package/dist/access-service.js +37 -37
- package/dist/access-surface-catalog.d.ts +16 -14
- package/dist/access-surface-catalog.js +39 -39
- package/dist/access-wearables-meetings-surface.d.ts +6 -5
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +6 -5
- package/dist/active-recall.js.map +1 -1
- package/dist/activity/digest.d.ts +1 -1
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -1
- package/dist/{auto-sync-RP4C6ZPF.js → auto-sync-D6BAPIJV.js} +5 -5
- package/dist/background-generation-config.d.ts +1 -1
- package/dist/background-generation-config.js +3 -1
- package/dist/background-generation.d.ts +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +13 -12
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +15 -15
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer-turn-helpers.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/buffer.js +5 -5
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +3 -2
- package/dist/calibration.js +2 -2
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-CW87xGx8.d.ts → catalog-BHXkBVhg.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +19 -18
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-B36GUU6T.js → chunk-23HFXQ5J.js} +36 -3
- package/dist/chunk-23HFXQ5J.js.map +1 -0
- package/dist/{chunk-YFTNZMGR.js → chunk-27NO2KVB.js} +31 -8
- package/dist/chunk-27NO2KVB.js.map +1 -0
- package/dist/{chunk-JTQR6L2N.js → chunk-2SKMZUOW.js} +2 -2
- package/dist/{chunk-GG5FHZJJ.js → chunk-2SNCQHJZ.js} +2 -2
- package/dist/{chunk-O76F5QPP.js → chunk-3QEVOQF5.js} +2 -2
- package/dist/{chunk-3N3PBBEH.js → chunk-3XPN7AVY.js} +2 -2
- package/dist/{chunk-X4TD4O2F.js → chunk-46Z3VGWF.js} +2 -2
- package/dist/{chunk-2ZTDRNCS.js → chunk-4CMXI55L.js} +2 -2
- package/dist/{chunk-FWWWUPOE.js → chunk-5LYSEZOF.js} +18 -9
- package/dist/chunk-5LYSEZOF.js.map +1 -0
- package/dist/{chunk-IQEJIOEU.js → chunk-62HFZNCJ.js} +17 -10
- package/dist/chunk-62HFZNCJ.js.map +1 -0
- package/dist/{chunk-YKREX63Z.js → chunk-6L2II3KS.js} +5 -3
- package/dist/chunk-6L2II3KS.js.map +1 -0
- package/dist/{chunk-MUTVRKKY.js → chunk-7D6SER6A.js} +8 -8
- package/dist/{chunk-WBM2MVBK.js → chunk-7Z54NXVS.js} +2 -2
- package/dist/{chunk-ACY4ZPF7.js → chunk-AEOOGXMQ.js} +10 -5
- package/dist/chunk-AEOOGXMQ.js.map +1 -0
- package/dist/{chunk-UHRZ324M.js → chunk-BGRTZOJB.js} +3 -3
- package/dist/{chunk-ZEGL7YCC.js → chunk-BXIJSPCL.js} +2 -2
- package/dist/{chunk-JKKII6GX.js → chunk-BYQX4IOG.js} +2 -2
- package/dist/{chunk-WIWLX65T.js → chunk-C5R73BON.js} +2 -2
- package/dist/{chunk-BD7JTBYP.js → chunk-D7MAYFQP.js} +2 -2
- package/dist/{chunk-TNZNSMVJ.js → chunk-DAZANIYU.js} +249 -295
- package/dist/chunk-DAZANIYU.js.map +1 -0
- package/dist/{chunk-LMLGBG6H.js → chunk-DFVSJFHK.js} +2 -2
- package/dist/{chunk-3NPNBVFR.js → chunk-ES5BUPYB.js} +2 -2
- package/dist/{chunk-MVAQ2WM3.js → chunk-G2XZFGYN.js} +6 -2
- package/dist/chunk-G2XZFGYN.js.map +1 -0
- package/dist/{chunk-TNSCIPBQ.js → chunk-G6NQ3L4T.js} +2 -2
- package/dist/{chunk-5N4MZLEH.js → chunk-GO5LOHCD.js} +2 -2
- package/dist/{chunk-AECJY3GJ.js → chunk-GSSDHAYH.js} +2 -2
- package/dist/{chunk-TSP5WH72.js → chunk-HJUP3K6L.js} +2 -2
- package/dist/{chunk-AAZEKXUP.js → chunk-ICNJ6J46.js} +2 -2
- package/dist/{chunk-6EHM2AV7.js → chunk-IMBQFHRV.js} +2 -2
- package/dist/{chunk-4RZLTZVM.js → chunk-IOPIGX7Y.js} +1 -1
- package/dist/{chunk-EYKIDK33.js → chunk-IS2IDFJP.js} +13 -13
- package/dist/{chunk-VJIE4D2I.js → chunk-J4WGTN2N.js} +2 -2
- package/dist/{chunk-NXGSONWM.js → chunk-J7FVMLBR.js} +2 -2
- package/dist/{chunk-VSL63CFJ.js → chunk-JAJIMTFB.js} +6 -6
- package/dist/{chunk-4JVQRFZD.js → chunk-JOP7W24J.js} +9 -9
- package/dist/{chunk-YUW66UAH.js → chunk-JUDT33RX.js} +2 -2
- package/dist/{chunk-QHT7MOUF.js → chunk-K4A6UVPB.js} +22 -11
- package/dist/chunk-K4A6UVPB.js.map +1 -0
- package/dist/{chunk-D545Z7UH.js → chunk-K4JKAXMO.js} +2 -2
- package/dist/{chunk-BV4ZKIZH.js → chunk-K75A5XWU.js} +3 -2
- package/dist/{chunk-3CBI2ZSA.js → chunk-KG2OOAFF.js} +20 -12
- package/dist/chunk-KG2OOAFF.js.map +1 -0
- package/dist/{chunk-M6HBPLBA.js → chunk-KOTG3RXE.js} +2 -2
- package/dist/{chunk-CWTCMZGE.js → chunk-KTOXQMW3.js} +119 -3
- package/dist/chunk-KTOXQMW3.js.map +1 -0
- package/dist/{chunk-OB3XMWX5.js → chunk-KVO2BTA4.js} +2 -2
- package/dist/{chunk-GI4ZBWPQ.js → chunk-KY236SP5.js} +3 -3
- package/dist/{chunk-4BCHFSC7.js → chunk-LFVZD5EC.js} +3 -3
- package/dist/{chunk-O4M4BDIJ.js → chunk-LKFVVN7R.js} +2 -2
- package/dist/{chunk-IYKZJVL5.js → chunk-MDIEES23.js} +1 -1
- package/dist/chunk-MDIEES23.js.map +1 -0
- package/dist/{chunk-4RX5O34R.js → chunk-MJC7UKH7.js} +2 -2
- package/dist/{chunk-CZTPU65V.js → chunk-MVG3KXON.js} +63 -16
- package/dist/chunk-MVG3KXON.js.map +1 -0
- package/dist/{chunk-YDVAM7S4.js → chunk-NETQXOPY.js} +2 -2
- package/dist/chunk-NETQXOPY.js.map +1 -0
- package/dist/{chunk-UZZ7SQT3.js → chunk-NVVZPBKI.js} +2 -2
- package/dist/{chunk-BLDBT6HZ.js → chunk-PJRKLB4Z.js} +18 -2
- package/dist/chunk-PJRKLB4Z.js.map +1 -0
- package/dist/{chunk-VBSNUH4J.js → chunk-PKUJNICO.js} +2 -2
- package/dist/{chunk-OPBFP4TF.js → chunk-QE6YVNP5.js} +7 -7
- package/dist/{chunk-WKDFJXW5.js → chunk-QM2SPLKQ.js} +1 -1
- package/dist/chunk-QM2SPLKQ.js.map +1 -0
- package/dist/{chunk-ENBPQEVU.js → chunk-QPVNK2VE.js} +2 -2
- package/dist/{chunk-RLJHJQUY.js → chunk-QS5Q5RBV.js} +2 -2
- package/dist/{chunk-3EKVN2OP.js → chunk-RDLPFM7I.js} +2 -2
- package/dist/{chunk-F4EHXVP7.js → chunk-RJQAP333.js} +2 -2
- package/dist/{chunk-QTQ6XKGT.js → chunk-RLU2Y5GV.js} +4 -4
- package/dist/chunk-RLU2Y5GV.js.map +1 -0
- package/dist/{chunk-5SPCMAUC.js → chunk-ROEFLU37.js} +4 -4
- package/dist/{chunk-UZEHHXYC.js → chunk-SFHLQPBF.js} +22 -22
- package/dist/chunk-SK7D34OL.js +68 -0
- package/dist/chunk-SK7D34OL.js.map +1 -0
- package/dist/{chunk-ZBW7A667.js → chunk-SUEOG2S4.js} +2 -2
- package/dist/{chunk-Q7CLGFA7.js → chunk-TEMKBSV6.js} +2 -2
- package/dist/{chunk-LQNRVPTV.js → chunk-THTF2W7M.js} +151 -118
- package/dist/chunk-THTF2W7M.js.map +1 -0
- package/dist/{chunk-GMIQV6DD.js → chunk-TO36VPZI.js} +2 -2
- package/dist/{chunk-6YAIN5XJ.js → chunk-TZ44E732.js} +44 -6
- package/dist/chunk-TZ44E732.js.map +1 -0
- package/dist/{chunk-JXN77SGO.js → chunk-U2VDCFXW.js} +1 -1
- package/dist/chunk-U2VDCFXW.js.map +1 -0
- package/dist/{chunk-LPYYY4AP.js → chunk-UZ6JYPJ6.js} +500 -218
- package/dist/chunk-UZ6JYPJ6.js.map +1 -0
- package/dist/{chunk-FXHOZGSE.js → chunk-V2ZA4YWE.js} +2 -2
- package/dist/{chunk-XH3HGI2N.js → chunk-VHKXRYQN.js} +2 -2
- package/dist/{chunk-GAS7KYC7.js → chunk-VKWFNPBH.js} +2 -2
- package/dist/{chunk-6H2G7RFT.js → chunk-VNQRRUNS.js} +11 -10
- package/dist/chunk-VNQRRUNS.js.map +1 -0
- package/dist/{chunk-IL6ODG6M.js → chunk-VQWBUPSJ.js} +2 -2
- package/dist/{chunk-5YCNDC3C.js → chunk-VQYWKCDR.js} +2 -2
- package/dist/{chunk-54NX5EG4.js → chunk-W23JARAQ.js} +2 -2
- package/dist/{chunk-YQNNHLCG.js → chunk-WPGR3RW4.js} +2 -2
- package/dist/{chunk-FNHLI2RE.js → chunk-WZYHPAG5.js} +3 -3
- package/dist/{chunk-5HYUUFMQ.js → chunk-XCPNH2MG.js} +259 -10
- package/dist/chunk-XCPNH2MG.js.map +1 -0
- package/dist/{chunk-TA4C3XB7.js → chunk-XM46Y66S.js} +2 -2
- package/dist/{chunk-PCOVEDPK.js → chunk-YRIFXXMI.js} +3 -3
- package/dist/{chunk-TRLOFIQC.js → chunk-YTK5MVNF.js} +2 -2
- package/dist/{chunk-Q432REND.js → chunk-YTZN2UZO.js} +2 -2
- package/dist/{chunk-6AGWBKQU.js → chunk-Z4GUX2M6.js} +2 -2
- package/dist/{chunk-AENM6GKU.js → chunk-ZAEPD4C2.js} +2 -2
- package/dist/{chunk-KQW3YGEN.js → chunk-ZRMMXWYI.js} +2 -2
- package/dist/{chunk-P4ZAEYKG.js → chunk-ZX3AYNNV.js} +6 -3
- package/dist/chunk-ZX3AYNNV.js.map +1 -0
- package/dist/{chunk-MCRVQ5YQ.js → chunk-ZZCR2QYL.js} +2 -2
- package/dist/{cli-DGq0MNpO.d.ts → cli-BWri5-am.d.ts} +5 -5
- package/dist/cli.d.ts +18 -16
- package/dist/cli.js +75 -74
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +14 -14
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +15 -15
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +6 -5
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +15 -15
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +15 -15
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +6 -5
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +17 -17
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/corpus-watermark.d.ts +1 -1
- package/dist/corpus-watermark.js +17 -17
- package/dist/cross-lingual-recall.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/deep-recall-http-glue.d.ts +16 -14
- package/dist/deep-recall-http-glue.js +2 -2
- package/dist/deep-recall-mcp-tools.d.ts +16 -14
- package/dist/deep-recall-policy-llm.d.ts +4 -3
- package/dist/deep-recall-policy-llm.js +3 -3
- package/dist/deep-recall-seeds.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-Cq1ekOwV.d.ts → dependency-propagation-delivery-ueZlKTQB.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-origin-fields.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +15 -15
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/eval-trajectory-contracts.d.ts +1 -1
- package/dist/eval-trajectory-store.d.ts +1 -1
- package/dist/eval-trajectory.d.ts +1 -1
- package/dist/explicit-capture.d.ts +13 -12
- package/dist/external-wiki-access.d.ts +16 -14
- package/dist/external-wiki-access.js +38 -38
- package/dist/external-wiki-collection-registration.d.ts +1 -1
- package/dist/external-wiki-collection.d.ts +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +16 -14
- package/dist/extraction-error-classification.d.ts +14 -3
- package/dist/extraction-error-classification.js +5 -3
- package/dist/extraction-faithfulness.d.ts +4 -3
- package/dist/extraction-faithfulness.js +3 -3
- package/dist/extraction-judge-telemetry.d.ts +4 -3
- package/dist/extraction-judge-training.d.ts +4 -3
- package/dist/extraction-judge.d.ts +4 -3
- package/dist/extraction-judge.js +3 -3
- package/dist/extraction-liveness.d.ts +1 -1
- package/dist/extraction-normalization.d.ts +1 -1
- package/dist/extraction-prompt.d.ts +1 -1
- package/dist/extraction-source-grounding-rules.d.ts +1 -1
- package/dist/extraction-source-grounding.d.ts +1 -1
- package/dist/extraction-span-config.d.ts +1 -1
- package/dist/extraction-span-materialize.d.ts +1 -1
- package/dist/extraction.d.ts +4 -4
- package/dist/extraction.js +25 -23
- package/dist/fallback-llm-codex-subscription.d.ts +52 -7
- package/dist/fallback-llm-codex-subscription.js +17 -1
- package/dist/fallback-llm.d.ts +25 -28
- package/dist/fallback-llm.js +4 -3
- package/dist/{generic-recall-paths-BcySh_f9.d.ts → generic-recall-paths-CpyVmA88.d.ts} +1 -1
- package/dist/graph-append-error.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-jsonl.d.ts +1 -1
- package/dist/graph-path-reconstruction.d.ts +1 -1
- package/dist/graph-path-scoring.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/importers/test-utils.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +1 -1
- package/dist/{index-DWOb4wz9.d.ts → index-BvUA4S7M.d.ts} +3 -3
- package/dist/index.d.ts +79 -39
- package/dist/index.js +119 -103
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +3 -3
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm-BsJGulur.d.ts +247 -0
- package/dist/local-llm-config.d.ts +4 -1
- package/dist/local-llm-config.js +4 -2
- package/dist/local-llm-helpers.d.ts +18 -69
- package/dist/local-llm-helpers.js +1 -1
- package/dist/local-llm.d.ts +3 -170
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/location/index.d.ts +3 -3
- package/dist/location/index.js +17 -17
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +15 -15
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +15 -15
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +16 -16
- package/dist/{maintenance-CW9wCzMP.d.ts → maintenance-CYubtIRr.d.ts} +9 -3
- package/dist/mcp-memory-inspector-app.d.ts +16 -14
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-controller.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +16 -14
- package/dist/memory-subject.d.ts +16 -14
- package/dist/memory-worth-outcomes.d.ts +2 -2
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +3 -3
- package/dist/namespaces/migrate.js +16 -16
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +12 -1
- package/dist/namespaces/search.js +9 -9
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +15 -15
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync-impression-drain.d.ts +1 -1
- package/dist/operator-doctor-corpus.d.ts +1 -1
- package/dist/operator-doctor-corpus.js +18 -18
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +29 -28
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +26 -26
- package/dist/{orchestrator-ComHLm49.d.ts → orchestrator-BWDRJ_0d.d.ts} +24 -11
- package/dist/orchestrator.d.ts +13 -12
- package/dist/orchestrator.js +101 -98
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-CiYcqqhl.d.ts → pipeline-7JMn2yMH.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +2 -2
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-CuK4_Cb1.d.ts → public-http-CJWs3mo9.d.ts} +1 -1
- package/dist/{qmd-qXD4vatU.d.ts → qmd-CxCH9G9m.d.ts} +2 -2
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/qmd.js +2 -2
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-navigate-access.d.ts +1 -1
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.d.ts +1 -1
- package/dist/recall-navigate-disclosure.js +1 -1
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-planner-llm.d.ts +3 -2
- package/dist/recall-planner-llm.js +4 -3
- package/dist/recall-planner-llm.js.map +1 -1
- package/dist/recall-state-view-admission.d.ts +13 -3
- package/dist/recall-state-view-admission.js +8 -8
- package/dist/recall-state-view-anchors.d.ts +1 -1
- package/dist/recall-state-view-anchors.js +2 -2
- package/dist/recall-state-view-inject.js +2 -2
- package/dist/recall-state-view-render.js +2 -2
- package/dist/recall-state-view-widen.js +2 -2
- package/dist/recall-state-view-wire.js +3 -3
- package/dist/recall-state-view.d.ts +1 -0
- package/dist/recall-state-view.js +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/plan.d.ts +1 -1
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/replica-divergence.d.ts +1 -1
- package/dist/replica-peers-config.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +7 -6
- package/dist/retrieval-agents.d.ts +2 -2
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/salvage-envelope.d.ts +1 -1
- package/dist/{scope-profiles-BT9rqC3w.d.ts → scope-profiles-BGAUqhBR.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +8 -8
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +10 -10
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +2 -2
- package/dist/search/port.js +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/search/remote-backend.js +2 -2
- package/dist/{semantic-consolidation-CmZi7thY.d.ts → semantic-consolidation-CCeRD9pV.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +16 -16
- package/dist/semantic-rule-promotion.js +15 -15
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +15 -15
- package/dist/{service-CLkA7AQB.d.ts → service-BwpzRduk.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +18 -18
- package/dist/standup/build.js +15 -15
- package/dist/{storage-wvX01lht.d.ts → storage-BprAGBG0.d.ts} +2 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +14 -14
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +5 -5
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +18 -17
- package/dist/support-passport/index.js +40 -40
- package/dist/task-llm-config.d.ts +16 -0
- package/dist/task-llm-config.js +12 -0
- package/dist/task-llm-config.js.map +1 -0
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +15 -15
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-Cyr32ABj.d.ts → types-nJV23pa3.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +15 -15
- package/dist/who-knows-cli.d.ts +16 -14
- package/dist/who-knows-cli.js +16 -16
- package/dist/who-knows.d.ts +16 -14
- package/dist/who-knows.js +15 -15
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-category-alias.test.ts +93 -0
- package/src/access-offline-manifest.ts +52 -2
- package/src/access-schema.ts +9 -4
- package/src/activity/config.test.ts +61 -0
- package/src/activity/config.ts +40 -1
- package/src/activity/timeline/analysis-provider.ts +8 -2
- package/src/activity/timeline/analysis-run.test.ts +82 -0
- package/src/activity/timeline/publish-cli.test.ts +30 -0
- package/src/activity/timeline/publish-cli.ts +7 -0
- package/src/activity/timeline/query.ts +8 -1
- package/src/activity/timeline/regenerate.test.ts +82 -2
- package/src/activity/timeline/regenerate.ts +7 -1
- package/src/activity/vault-frontmatter.test.ts +99 -1
- package/src/activity/vault-frontmatter.ts +131 -0
- package/src/activity/vault-publish.ts +6 -0
- package/src/activity/vault-publisher.test.ts +172 -0
- package/src/activity/vault-publisher.ts +69 -15
- package/src/activity/vault-region.test.ts +7 -2
- package/src/activity/vault-region.ts +7 -3
- package/src/background-generation-config.ts +32 -6
- package/src/background-generation.test.ts +10 -1
- package/src/cli/timeline-publish-commands.ts +9 -0
- package/src/config.test.ts +170 -43
- package/src/config.ts +17 -5
- package/src/extraction-error-classification.ts +36 -1
- package/src/extraction-timeout.test.ts +110 -1
- package/src/extraction.test.ts +19 -1
- package/src/extraction.ts +23 -21
- package/src/fallback-llm-codex-subscription.ts +193 -7
- package/src/fallback-llm-parse-failure.test.ts +156 -0
- package/src/fallback-llm.test.ts +58 -0
- package/src/fallback-llm.ts +187 -186
- package/src/index.ts +1 -0
- package/src/local-llm-config.ts +11 -10
- package/src/local-llm-headers-timeout.test.ts +30 -0
- package/src/local-llm-helpers.ts +28 -0
- package/src/local-llm.ts +8 -19
- package/src/namespaces/search.test.ts +51 -1
- package/src/namespaces/search.ts +48 -3
- package/src/orchestration/extraction-persist-promotion.test.ts +228 -2
- package/src/orchestration/extraction-persist-promotion.ts +17 -14
- package/src/orchestration/orchestrator-helpers.test.ts +104 -0
- package/src/orchestration/orchestrator-init.ts +366 -106
- package/src/orchestration/recall-internal.ts +5 -11
- package/src/orchestration/semantic-merge-promotion-payload.ts +62 -6
- package/src/orchestration/startup-collection-checks.ts +85 -0
- package/src/orchestrator-flush.test.ts +7 -0
- package/src/orchestrator-init.test.ts +1539 -0
- package/src/orchestrator.ts +7 -0
- package/src/qmd.ts +21 -10
- package/src/recall-state-view-admission.ts +11 -1
- package/src/recall-state-view-cron-intent.test.ts +268 -0
- package/src/recall-state-view-widen.test.ts +14 -5
- package/src/recall-state-view-widen.ts +8 -1
- package/src/recall-state-view.ts +5 -2
- package/src/reconcile-identity-cache.test.ts +82 -1
- package/src/search/port.ts +1 -1
- package/src/storage/cas-revision-store.test.ts +4 -0
- package/src/storage/cas-revision-store.ts +104 -12
- package/src/storage-frontmatter-cas.test.ts +19 -17
- package/src/summarizer.ts +5 -1
- package/src/task-llm-config.test.ts +124 -0
- package/src/task-llm-config.ts +88 -0
- package/src/testing/subjects/startup-discovery-lifecycle.test.ts +273 -0
- package/src/types.ts +1 -0
- package/dist/chunk-3CBI2ZSA.js.map +0 -1
- package/dist/chunk-5HYUUFMQ.js.map +0 -1
- package/dist/chunk-6H2G7RFT.js.map +0 -1
- package/dist/chunk-6YAIN5XJ.js.map +0 -1
- package/dist/chunk-ACY4ZPF7.js.map +0 -1
- package/dist/chunk-B36GUU6T.js.map +0 -1
- package/dist/chunk-BLDBT6HZ.js.map +0 -1
- package/dist/chunk-CWTCMZGE.js.map +0 -1
- package/dist/chunk-CZTPU65V.js.map +0 -1
- package/dist/chunk-FWWWUPOE.js.map +0 -1
- package/dist/chunk-IQEJIOEU.js.map +0 -1
- package/dist/chunk-IYKZJVL5.js.map +0 -1
- package/dist/chunk-JXN77SGO.js.map +0 -1
- package/dist/chunk-LPYYY4AP.js.map +0 -1
- package/dist/chunk-LQNRVPTV.js.map +0 -1
- package/dist/chunk-MVAQ2WM3.js.map +0 -1
- package/dist/chunk-P4ZAEYKG.js.map +0 -1
- package/dist/chunk-QHT7MOUF.js.map +0 -1
- package/dist/chunk-QTQ6XKGT.js.map +0 -1
- package/dist/chunk-TNZNSMVJ.js.map +0 -1
- package/dist/chunk-WKDFJXW5.js.map +0 -1
- package/dist/chunk-YDVAM7S4.js.map +0 -1
- package/dist/chunk-YFTNZMGR.js.map +0 -1
- package/dist/chunk-YKREX63Z.js.map +0 -1
- /package/dist/{auto-sync-RP4C6ZPF.js.map → auto-sync-D6BAPIJV.js.map} +0 -0
- /package/dist/{chunk-JTQR6L2N.js.map → chunk-2SKMZUOW.js.map} +0 -0
- /package/dist/{chunk-GG5FHZJJ.js.map → chunk-2SNCQHJZ.js.map} +0 -0
- /package/dist/{chunk-O76F5QPP.js.map → chunk-3QEVOQF5.js.map} +0 -0
- /package/dist/{chunk-3N3PBBEH.js.map → chunk-3XPN7AVY.js.map} +0 -0
- /package/dist/{chunk-X4TD4O2F.js.map → chunk-46Z3VGWF.js.map} +0 -0
- /package/dist/{chunk-2ZTDRNCS.js.map → chunk-4CMXI55L.js.map} +0 -0
- /package/dist/{chunk-MUTVRKKY.js.map → chunk-7D6SER6A.js.map} +0 -0
- /package/dist/{chunk-WBM2MVBK.js.map → chunk-7Z54NXVS.js.map} +0 -0
- /package/dist/{chunk-UHRZ324M.js.map → chunk-BGRTZOJB.js.map} +0 -0
- /package/dist/{chunk-ZEGL7YCC.js.map → chunk-BXIJSPCL.js.map} +0 -0
- /package/dist/{chunk-JKKII6GX.js.map → chunk-BYQX4IOG.js.map} +0 -0
- /package/dist/{chunk-WIWLX65T.js.map → chunk-C5R73BON.js.map} +0 -0
- /package/dist/{chunk-BD7JTBYP.js.map → chunk-D7MAYFQP.js.map} +0 -0
- /package/dist/{chunk-LMLGBG6H.js.map → chunk-DFVSJFHK.js.map} +0 -0
- /package/dist/{chunk-3NPNBVFR.js.map → chunk-ES5BUPYB.js.map} +0 -0
- /package/dist/{chunk-TNSCIPBQ.js.map → chunk-G6NQ3L4T.js.map} +0 -0
- /package/dist/{chunk-5N4MZLEH.js.map → chunk-GO5LOHCD.js.map} +0 -0
- /package/dist/{chunk-AECJY3GJ.js.map → chunk-GSSDHAYH.js.map} +0 -0
- /package/dist/{chunk-TSP5WH72.js.map → chunk-HJUP3K6L.js.map} +0 -0
- /package/dist/{chunk-AAZEKXUP.js.map → chunk-ICNJ6J46.js.map} +0 -0
- /package/dist/{chunk-6EHM2AV7.js.map → chunk-IMBQFHRV.js.map} +0 -0
- /package/dist/{chunk-4RZLTZVM.js.map → chunk-IOPIGX7Y.js.map} +0 -0
- /package/dist/{chunk-EYKIDK33.js.map → chunk-IS2IDFJP.js.map} +0 -0
- /package/dist/{chunk-VJIE4D2I.js.map → chunk-J4WGTN2N.js.map} +0 -0
- /package/dist/{chunk-NXGSONWM.js.map → chunk-J7FVMLBR.js.map} +0 -0
- /package/dist/{chunk-VSL63CFJ.js.map → chunk-JAJIMTFB.js.map} +0 -0
- /package/dist/{chunk-4JVQRFZD.js.map → chunk-JOP7W24J.js.map} +0 -0
- /package/dist/{chunk-YUW66UAH.js.map → chunk-JUDT33RX.js.map} +0 -0
- /package/dist/{chunk-D545Z7UH.js.map → chunk-K4JKAXMO.js.map} +0 -0
- /package/dist/{chunk-BV4ZKIZH.js.map → chunk-K75A5XWU.js.map} +0 -0
- /package/dist/{chunk-M6HBPLBA.js.map → chunk-KOTG3RXE.js.map} +0 -0
- /package/dist/{chunk-OB3XMWX5.js.map → chunk-KVO2BTA4.js.map} +0 -0
- /package/dist/{chunk-GI4ZBWPQ.js.map → chunk-KY236SP5.js.map} +0 -0
- /package/dist/{chunk-4BCHFSC7.js.map → chunk-LFVZD5EC.js.map} +0 -0
- /package/dist/{chunk-O4M4BDIJ.js.map → chunk-LKFVVN7R.js.map} +0 -0
- /package/dist/{chunk-4RX5O34R.js.map → chunk-MJC7UKH7.js.map} +0 -0
- /package/dist/{chunk-UZZ7SQT3.js.map → chunk-NVVZPBKI.js.map} +0 -0
- /package/dist/{chunk-VBSNUH4J.js.map → chunk-PKUJNICO.js.map} +0 -0
- /package/dist/{chunk-OPBFP4TF.js.map → chunk-QE6YVNP5.js.map} +0 -0
- /package/dist/{chunk-ENBPQEVU.js.map → chunk-QPVNK2VE.js.map} +0 -0
- /package/dist/{chunk-RLJHJQUY.js.map → chunk-QS5Q5RBV.js.map} +0 -0
- /package/dist/{chunk-3EKVN2OP.js.map → chunk-RDLPFM7I.js.map} +0 -0
- /package/dist/{chunk-F4EHXVP7.js.map → chunk-RJQAP333.js.map} +0 -0
- /package/dist/{chunk-5SPCMAUC.js.map → chunk-ROEFLU37.js.map} +0 -0
- /package/dist/{chunk-UZEHHXYC.js.map → chunk-SFHLQPBF.js.map} +0 -0
- /package/dist/{chunk-ZBW7A667.js.map → chunk-SUEOG2S4.js.map} +0 -0
- /package/dist/{chunk-Q7CLGFA7.js.map → chunk-TEMKBSV6.js.map} +0 -0
- /package/dist/{chunk-GMIQV6DD.js.map → chunk-TO36VPZI.js.map} +0 -0
- /package/dist/{chunk-FXHOZGSE.js.map → chunk-V2ZA4YWE.js.map} +0 -0
- /package/dist/{chunk-XH3HGI2N.js.map → chunk-VHKXRYQN.js.map} +0 -0
- /package/dist/{chunk-GAS7KYC7.js.map → chunk-VKWFNPBH.js.map} +0 -0
- /package/dist/{chunk-IL6ODG6M.js.map → chunk-VQWBUPSJ.js.map} +0 -0
- /package/dist/{chunk-5YCNDC3C.js.map → chunk-VQYWKCDR.js.map} +0 -0
- /package/dist/{chunk-54NX5EG4.js.map → chunk-W23JARAQ.js.map} +0 -0
- /package/dist/{chunk-YQNNHLCG.js.map → chunk-WPGR3RW4.js.map} +0 -0
- /package/dist/{chunk-FNHLI2RE.js.map → chunk-WZYHPAG5.js.map} +0 -0
- /package/dist/{chunk-TA4C3XB7.js.map → chunk-XM46Y66S.js.map} +0 -0
- /package/dist/{chunk-PCOVEDPK.js.map → chunk-YRIFXXMI.js.map} +0 -0
- /package/dist/{chunk-TRLOFIQC.js.map → chunk-YTK5MVNF.js.map} +0 -0
- /package/dist/{chunk-Q432REND.js.map → chunk-YTZN2UZO.js.map} +0 -0
- /package/dist/{chunk-6AGWBKQU.js.map → chunk-Z4GUX2M6.js.map} +0 -0
- /package/dist/{chunk-AENM6GKU.js.map → chunk-ZAEPD4C2.js.map} +0 -0
- /package/dist/{chunk-KQW3YGEN.js.map → chunk-ZRMMXWYI.js.map} +0 -0
- /package/dist/{chunk-MCRVQ5YQ.js.map → chunk-ZZCR2QYL.js.map} +0 -0
package/src/index.ts
CHANGED
package/src/local-llm-config.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { coerceNumber } from "./connectors/coerce.js";
|
|
|
2
2
|
import { parseBackgroundGeneration } from "./background-generation-config.js";
|
|
3
3
|
import type { BackgroundGenerationConfig } from "./background-generation-config.js";
|
|
4
4
|
import { readEnvVar } from "./runtime/env.js";
|
|
5
|
-
|
|
5
|
+
import { parseTaskLlmConfig } from "./task-llm-config.js";
|
|
6
6
|
export interface LocalLlmConfig {
|
|
7
7
|
// Local LLM Provider (v2.1)
|
|
8
8
|
localLlmEnabled: boolean;
|
|
@@ -17,14 +17,17 @@ export interface LocalLlmConfig {
|
|
|
17
17
|
/** If false, do not send Authorization header even when localLlmApiKey is set. */
|
|
18
18
|
localLlmAuthHeader: boolean;
|
|
19
19
|
localLlmFallback: boolean;
|
|
20
|
+
taskLlmFallback?: boolean;
|
|
20
21
|
/** Optional home directory override for local LLM helpers (LM Studio settings, CLI PATH). */
|
|
21
22
|
localLlmHomeDir?: string;
|
|
22
23
|
/** Optional absolute path to LMS CLI binary (preferred over auto-detection). */
|
|
23
24
|
localLmsCliPath?: string;
|
|
24
25
|
/** Optional bin directory prepended to PATH for LMS CLI execution. */
|
|
25
26
|
localLmsBinDir?: string;
|
|
26
|
-
/** Hard timeout for local LLM
|
|
27
|
+
/** Hard timeout for local LLM requests (ms). Legacy alias for the task-chain timeout when `taskLlmTimeoutMs` is absent. */
|
|
27
28
|
localLlmTimeoutMs: number;
|
|
29
|
+
/** Timeout for the gateway/task LLM chain (ms). */
|
|
30
|
+
taskLlmTimeoutMs?: number;
|
|
28
31
|
/** Max context window for local LLM (override auto-detection). Set lower if your LLM server defaults to smaller contexts. */
|
|
29
32
|
localLlmMaxContext?: number;
|
|
30
33
|
}
|
|
@@ -33,11 +36,6 @@ export type LocalLlmParseResult = LocalLlmConfig & {
|
|
|
33
36
|
backgroundGeneration?: BackgroundGenerationConfig;
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
function parseLocalLlmTimeoutMs(value: unknown): number {
|
|
37
|
-
const coerced = coerceNumber(value);
|
|
38
|
-
if (coerced === undefined) return 180_000;
|
|
39
|
-
return Math.min(86_400_000, Math.max(1, Math.floor(coerced)));
|
|
40
|
-
}
|
|
41
39
|
|
|
42
40
|
function parseLocalLlmMaxContext(value: unknown): number | undefined {
|
|
43
41
|
if (value === undefined || value === null) return undefined;
|
|
@@ -70,8 +68,9 @@ export function parseLocalLlmConfig(
|
|
|
70
68
|
localLlmApiKeyEnv: string | undefined,
|
|
71
69
|
resolveEnvVars: (value: string) => string,
|
|
72
70
|
): LocalLlmParseResult {
|
|
71
|
+
const taskLlm = parseTaskLlmConfig(cfg);
|
|
73
72
|
return {
|
|
74
|
-
backgroundGeneration: parseBackgroundGeneration(cfg),
|
|
73
|
+
backgroundGeneration: parseBackgroundGeneration(cfg, resolveEnvVars),
|
|
75
74
|
localLlmEnabled: cfg.localLlmEnabled === true || cfg.localLlmEnabled === "true",
|
|
76
75
|
localLlmUrl:
|
|
77
76
|
typeof cfg.localLlmUrl === "string" && cfg.localLlmUrl.length > 0
|
|
@@ -90,7 +89,8 @@ export function parseLocalLlmConfig(
|
|
|
90
89
|
localLlmApiKeyEnv,
|
|
91
90
|
localLlmHeaders: copyStringRecord(cfg.localLlmHeaders),
|
|
92
91
|
localLlmAuthHeader: cfg.localLlmAuthHeader !== false,
|
|
93
|
-
localLlmFallback:
|
|
92
|
+
localLlmFallback: taskLlm.fallback,
|
|
93
|
+
taskLlmFallback: taskLlm.fallback,
|
|
94
94
|
localLlmHomeDir:
|
|
95
95
|
typeof cfg.localLlmHomeDir === "string" && cfg.localLlmHomeDir.length > 0
|
|
96
96
|
? cfg.localLlmHomeDir
|
|
@@ -103,7 +103,8 @@ export function parseLocalLlmConfig(
|
|
|
103
103
|
typeof cfg.localLmsBinDir === "string" && cfg.localLmsBinDir.length > 0
|
|
104
104
|
? cfg.localLmsBinDir
|
|
105
105
|
: undefined,
|
|
106
|
-
localLlmTimeoutMs:
|
|
106
|
+
localLlmTimeoutMs: taskLlm.localTimeoutMs,
|
|
107
|
+
taskLlmTimeoutMs: taskLlm.timeoutMs,
|
|
107
108
|
localLlmMaxContext: parseLocalLlmMaxContext(cfg.localLlmMaxContext),
|
|
108
109
|
};
|
|
109
110
|
}
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from "undici";
|
|
13
13
|
|
|
14
14
|
import { LocalLlmClient } from "./local-llm.js";
|
|
15
|
+
import { classifyAnalysisProviderError } from "./activity/timeline/analysis-provider.js";
|
|
15
16
|
import { ChatTransport } from "./local-llm-transport.js";
|
|
16
17
|
import { initLogger, resetLogger } from "./logger.js";
|
|
17
18
|
import type { PluginConfig } from "./types.js";
|
|
@@ -553,3 +554,32 @@ test("sensitive local requests do not log provider error bodies", { concurrency:
|
|
|
553
554
|
await dispatcherOf(client).close();
|
|
554
555
|
}
|
|
555
556
|
});
|
|
557
|
+
|
|
558
|
+
test("failureDiag preserves a 429 rate-limit failure cause (issue #2891)", { concurrency: false }, async () => {
|
|
559
|
+
const original = globalThis.fetch;
|
|
560
|
+
globalThis.fetch = (async () =>
|
|
561
|
+
new Response(JSON.stringify({ error: { message: "rate limit exceeded" } }), {
|
|
562
|
+
status: 429,
|
|
563
|
+
headers: { "content-type": "application/json" },
|
|
564
|
+
})) as typeof fetch;
|
|
565
|
+
const client = new LocalLlmClient(createConfig());
|
|
566
|
+
|
|
567
|
+
try {
|
|
568
|
+
primeClient(client);
|
|
569
|
+
const failureDiag: { lastError?: unknown } = {};
|
|
570
|
+
assert.equal(
|
|
571
|
+
await client.chatCompletion(
|
|
572
|
+
[{ role: "user", content: "test" }],
|
|
573
|
+
{ redactProviderErrors: true, failureDiag },
|
|
574
|
+
),
|
|
575
|
+
null,
|
|
576
|
+
);
|
|
577
|
+
const lastError = failureDiag.lastError;
|
|
578
|
+
assert.ok(lastError instanceof Error, "expected the terminal provider error to survive the request");
|
|
579
|
+
assert.equal("status" in lastError ? lastError.status : undefined, 429);
|
|
580
|
+
assert.equal(classifyAnalysisProviderError(lastError), "rate_limited");
|
|
581
|
+
} finally {
|
|
582
|
+
globalThis.fetch = original;
|
|
583
|
+
await dispatcherOf(client).close();
|
|
584
|
+
}
|
|
585
|
+
});
|
package/src/local-llm-helpers.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
1
|
import { log } from "./logger.js";
|
|
2
|
+
import type { LocalLlmRequestPriority } from "./local-llm.js";
|
|
3
|
+
|
|
4
|
+
export interface LocalLlmChatCompletionOptions {
|
|
5
|
+
temperature?: number;
|
|
6
|
+
maxTokens?: number;
|
|
7
|
+
responseFormat?: { type: string };
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
operation?: string;
|
|
10
|
+
forceDisableThinking?: boolean;
|
|
11
|
+
disableThinking?: boolean;
|
|
12
|
+
priority?: LocalLlmRequestPriority;
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
redactProviderErrors?: boolean;
|
|
15
|
+
/** Per-request model; defaults to config.localLlmModel. */
|
|
16
|
+
model?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Optional out-box for the terminal failure cause (issue #2891): on a
|
|
19
|
+
* failed request the client records the last provider error here so
|
|
20
|
+
* callers can classify it (e.g. HTTP 429 → rate-limited) in memory
|
|
21
|
+
* instead of seeing only null. Never logged.
|
|
22
|
+
*/
|
|
23
|
+
failureDiag?: { lastError?: unknown };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface LocalLlmChatCompletionResult {
|
|
27
|
+
content: string;
|
|
28
|
+
usage?: { promptTokens: number; completionTokens: number; totalTokens: number };
|
|
29
|
+
}
|
|
2
30
|
export function isAbortError(err: unknown): boolean {
|
|
3
31
|
if (!err || typeof err !== "object") return false;
|
|
4
32
|
const maybe = err as { name?: string; message?: string };
|
package/src/local-llm.ts
CHANGED
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
normalizeBackendTripReason,
|
|
20
20
|
waitForRetryBackoff,
|
|
21
21
|
SingleFlightProbe,
|
|
22
|
+
type LocalLlmChatCompletionOptions,
|
|
23
|
+
type LocalLlmChatCompletionResult,
|
|
22
24
|
} from "./local-llm-helpers.js";
|
|
23
25
|
|
|
24
26
|
/** Trim trailing slash characters without backtracking regex. */
|
|
@@ -226,20 +228,8 @@ export interface LocalModelInfo {
|
|
|
226
228
|
|
|
227
229
|
export type LocalLlmRequestPriority = "recall-critical" | "background";
|
|
228
230
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
maxTokens?: number;
|
|
232
|
-
responseFormat?: { type: string };
|
|
233
|
-
timeoutMs?: number;
|
|
234
|
-
operation?: string;
|
|
235
|
-
forceDisableThinking?: boolean;
|
|
236
|
-
disableThinking?: boolean;
|
|
237
|
-
priority?: LocalLlmRequestPriority;
|
|
238
|
-
signal?: AbortSignal;
|
|
239
|
-
redactProviderErrors?: boolean;
|
|
240
|
-
/** Per-request model; defaults to config.localLlmModel. */
|
|
241
|
-
model?: string;
|
|
242
|
-
}
|
|
231
|
+
// LocalLlmChatCompletionOptions and LocalLlmChatCompletionResult live in
|
|
232
|
+
// local-llm-helpers.ts so this file stays under its size ceiling (#1995).
|
|
243
233
|
interface LocalLlmQueuedRequest {
|
|
244
234
|
messages: Array<{ role: string; content: string }>;
|
|
245
235
|
options: LocalLlmChatCompletionOptions;
|
|
@@ -248,11 +238,6 @@ interface LocalLlmQueuedRequest {
|
|
|
248
238
|
resolve: (value: LocalLlmChatCompletionResult | null) => void;
|
|
249
239
|
}
|
|
250
240
|
|
|
251
|
-
interface LocalLlmChatCompletionResult {
|
|
252
|
-
content: string;
|
|
253
|
-
usage?: { promptTokens: number; completionTokens: number; totalTokens: number };
|
|
254
|
-
}
|
|
255
|
-
|
|
256
241
|
const LOCAL_LLM_GLOBAL_BACKEND_STATE = "__openclawEngramLocalLlmBackendState";
|
|
257
242
|
|
|
258
243
|
type LocalLlmBackendState = {
|
|
@@ -1165,6 +1150,10 @@ export class LocalLlmClient {
|
|
|
1165
1150
|
} else {
|
|
1166
1151
|
this.consecutive400s = 0;
|
|
1167
1152
|
}
|
|
1153
|
+
if (options.failureDiag)
|
|
1154
|
+
options.failureDiag.lastError = Object.assign(new Error("local LLM http failure"), {
|
|
1155
|
+
status: response.status,
|
|
1156
|
+
});
|
|
1168
1157
|
return null;
|
|
1169
1158
|
}
|
|
1170
1159
|
this.consecutive400s = 0;
|
|
@@ -21,6 +21,7 @@ class FakeBackend implements SearchBackend {
|
|
|
21
21
|
strictEmbeds = 0;
|
|
22
22
|
strictCollectionEmbeds: string[] = [];
|
|
23
23
|
disposed = 0;
|
|
24
|
+
disposeWait: Promise<void> | null = null;
|
|
24
25
|
available = true;
|
|
25
26
|
calls: Array<{
|
|
26
27
|
method: string;
|
|
@@ -28,6 +29,7 @@ class FakeBackend implements SearchBackend {
|
|
|
28
29
|
maxResults: number | undefined;
|
|
29
30
|
}> = [];
|
|
30
31
|
availabilitySignals: Array<AbortSignal | undefined> = [];
|
|
32
|
+
probeSignals: Array<AbortSignal | undefined> = [];
|
|
31
33
|
probeCalls = 0;
|
|
32
34
|
ensureSignals: Array<AbortSignal | undefined> = [];
|
|
33
35
|
ensureCollections: Array<string | undefined> = [];
|
|
@@ -54,8 +56,9 @@ class FakeBackend implements SearchBackend {
|
|
|
54
56
|
: this.results;
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
async probe(): Promise<boolean> {
|
|
59
|
+
async probe(execution?: SearchExecutionOptions): Promise<boolean> {
|
|
58
60
|
this.probeCalls += 1;
|
|
61
|
+
this.probeSignals.push(execution?.signal);
|
|
59
62
|
return this.available;
|
|
60
63
|
}
|
|
61
64
|
|
|
@@ -89,6 +92,7 @@ class FakeBackend implements SearchBackend {
|
|
|
89
92
|
|
|
90
93
|
async dispose(): Promise<void> {
|
|
91
94
|
this.disposed += 1;
|
|
95
|
+
await this.disposeWait;
|
|
92
96
|
}
|
|
93
97
|
|
|
94
98
|
async search(
|
|
@@ -470,10 +474,56 @@ test("ensureNamespaceCollection forwards abort signals to backend collection che
|
|
|
470
474
|
});
|
|
471
475
|
|
|
472
476
|
assert.equal(state, "present");
|
|
477
|
+
assert.deepEqual(backend.probeSignals, [controller.signal]);
|
|
473
478
|
assert.deepEqual(backend.ensureSignals, [controller.signal]);
|
|
474
479
|
assert.deepEqual(backend.ensureCollections, ["openclaw-engram--ns-6d61696e"]);
|
|
475
480
|
});
|
|
476
481
|
|
|
482
|
+
test("disableSearchBackends releases cached namespace backends without recreating search", async () => {
|
|
483
|
+
const backend = new FakeBackend(false);
|
|
484
|
+
const router = new NamespaceSearchRouter(
|
|
485
|
+
config(),
|
|
486
|
+
{ storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
|
|
487
|
+
() => backend,
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
assert.equal(await router.ensureNamespaceCollection("main"), "present");
|
|
491
|
+
await router.disableSearchBackends();
|
|
492
|
+
|
|
493
|
+
await router.disableSearchBackends();
|
|
494
|
+
|
|
495
|
+
assert.equal(backend.disposed, 1, "repeated runtime disable must not double-dispose the same backend");
|
|
496
|
+
assert.equal(await router.backendForNamespace("main"), null);
|
|
497
|
+
assert.equal(await router.ensureNamespaceCollection("main"), "missing");
|
|
498
|
+
assert.equal(backend.probeCalls, 1, "disabled records must not recreate a concrete backend");
|
|
499
|
+
});
|
|
500
|
+
|
|
501
|
+
test("clearCache releases evicted namespace backend handles before recreation", async () => {
|
|
502
|
+
const oldBackend = new FakeBackend(false);
|
|
503
|
+
const newBackend = new FakeBackend(false);
|
|
504
|
+
let releaseOldDispose: (() => void) | undefined;
|
|
505
|
+
oldBackend.disposeWait = new Promise<void>((resolve) => { releaseOldDispose = resolve; });
|
|
506
|
+
let createCalls = 0;
|
|
507
|
+
const router = new NamespaceSearchRouter(
|
|
508
|
+
config(),
|
|
509
|
+
{ storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
|
|
510
|
+
() => {
|
|
511
|
+
createCalls += 1;
|
|
512
|
+
return createCalls === 1 ? oldBackend : newBackend;
|
|
513
|
+
},
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
await router.ensureNamespaceCollection("main");
|
|
517
|
+
router.clearCache();
|
|
518
|
+
const recreation = router.ensureNamespaceCollection("main");
|
|
519
|
+
await Promise.resolve();
|
|
520
|
+
assert.equal(createCalls, 1, "recreation must wait for the evicted handle disposal barrier");
|
|
521
|
+
releaseOldDispose?.();
|
|
522
|
+
assert.equal(await recreation, "present");
|
|
523
|
+
assert.equal(oldBackend.disposed, 1);
|
|
524
|
+
assert.equal(createCalls, 2);
|
|
525
|
+
});
|
|
526
|
+
|
|
477
527
|
test("legacy default namespace root auto-creates its base collection (broad root, #1929)", async () => {
|
|
478
528
|
const backend = new FakeBackend(false);
|
|
479
529
|
const router = new NamespaceSearchRouter(
|
package/src/namespaces/search.ts
CHANGED
|
@@ -45,6 +45,7 @@ type NamespaceBackendRecord = {
|
|
|
45
45
|
available: boolean;
|
|
46
46
|
collectionState: CollectionState;
|
|
47
47
|
filtersNestedNamespaces: boolean;
|
|
48
|
+
disposed: boolean;
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
export interface NamespaceUpdateResult {
|
|
@@ -83,6 +84,7 @@ type BackendRecordOptions = {
|
|
|
83
84
|
|
|
84
85
|
export class NamespaceSearchRouter {
|
|
85
86
|
private readonly cache = new Map<string, Promise<NamespaceBackendRecord>>();
|
|
87
|
+
private readonly pendingDisposals = new Set<Promise<void>>();
|
|
86
88
|
|
|
87
89
|
constructor(
|
|
88
90
|
private readonly config: PluginConfig,
|
|
@@ -344,21 +346,62 @@ export class NamespaceSearchRouter {
|
|
|
344
346
|
return cachedRecord;
|
|
345
347
|
}
|
|
346
348
|
|
|
349
|
+
private trackDisposal(promise: Promise<void>): void {
|
|
350
|
+
this.pendingDisposals.add(promise);
|
|
351
|
+
void promise.finally(() => this.pendingDisposals.delete(promise));
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private async drainPendingDisposals(): Promise<void> {
|
|
355
|
+
if (this.pendingDisposals.size === 0) return;
|
|
356
|
+
await Promise.allSettled(this.pendingDisposals);
|
|
357
|
+
}
|
|
358
|
+
|
|
347
359
|
/** Clear cached backend records so the next access re-probes availability. */
|
|
348
360
|
clearCache(): void {
|
|
361
|
+
const pendingRecords = Array.from(this.cache.values());
|
|
349
362
|
this.cache.clear();
|
|
363
|
+
const disposal = Promise.allSettled(pendingRecords).then(async (settled) => {
|
|
364
|
+
await Promise.allSettled(
|
|
365
|
+
settled.flatMap((entry) =>
|
|
366
|
+
entry.status === "fulfilled" ? [this.disposeRecord(entry.value)] : []),
|
|
367
|
+
);
|
|
368
|
+
});
|
|
369
|
+
this.trackDisposal(disposal);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
private async disposeRecord(record: NamespaceBackendRecord): Promise<void> {
|
|
373
|
+
if (record.disposed) return;
|
|
374
|
+
record.disposed = true;
|
|
375
|
+
const dispose = (record.backend as { dispose?: () => void | Promise<void> }).dispose;
|
|
376
|
+
await dispose?.call(record.backend);
|
|
350
377
|
}
|
|
351
378
|
|
|
352
379
|
/** Release any per-namespace backend handles held by cached records. */
|
|
353
380
|
async dispose(): Promise<void> {
|
|
381
|
+
await this.drainPendingDisposals();
|
|
354
382
|
const pendingRecords = Array.from(this.cache.values());
|
|
355
383
|
this.cache.clear();
|
|
356
384
|
const settled = await Promise.allSettled(pendingRecords);
|
|
385
|
+
await Promise.allSettled(
|
|
386
|
+
settled.flatMap((entry) =>
|
|
387
|
+
entry.status === "fulfilled" ? [this.disposeRecord(entry.value)] : []),
|
|
388
|
+
);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/**
|
|
392
|
+
* Disable namespace search for this runtime while retaining the resolved
|
|
393
|
+
* records as unavailable/missing. This releases concrete QMD/daemon handles
|
|
394
|
+
* without letting later reads recreate a search backend after the root path
|
|
395
|
+
* has been switched to NoopSearchBackend for a missing collection.
|
|
396
|
+
*/
|
|
397
|
+
async disableSearchBackends(): Promise<void> {
|
|
398
|
+
const settled = await Promise.allSettled(this.cache.values());
|
|
357
399
|
await Promise.allSettled(
|
|
358
400
|
settled.flatMap((entry) => {
|
|
359
401
|
if (entry.status !== "fulfilled") return [];
|
|
360
|
-
|
|
361
|
-
|
|
402
|
+
entry.value.available = false;
|
|
403
|
+
entry.value.collectionState = "missing";
|
|
404
|
+
return [this.disposeRecord(entry.value)];
|
|
362
405
|
}),
|
|
363
406
|
);
|
|
364
407
|
}
|
|
@@ -367,6 +410,7 @@ export class NamespaceSearchRouter {
|
|
|
367
410
|
namespace: string,
|
|
368
411
|
execution?: SearchExecutionOptions,
|
|
369
412
|
): Promise<NamespaceBackendRecord> {
|
|
413
|
+
await this.drainPendingDisposals();
|
|
370
414
|
const key = namespace.trim() || this.config.defaultNamespace;
|
|
371
415
|
const existing = this.cache.get(key);
|
|
372
416
|
if (existing) return await existing;
|
|
@@ -412,7 +456,7 @@ export class NamespaceSearchRouter {
|
|
|
412
456
|
try {
|
|
413
457
|
const availabilityProbe =
|
|
414
458
|
options.autoCreateCollection || typeof backend.checkAvailability !== "function"
|
|
415
|
-
? backend.probe()
|
|
459
|
+
? backend.probe(execution)
|
|
416
460
|
: backend.checkAvailability({ signal: execution?.signal });
|
|
417
461
|
const available = await awaitWithAbort(availabilityProbe, execution?.signal).catch((error) => {
|
|
418
462
|
if (error instanceof NamespaceSearchAbortError && !options.abortAsUnavailable) {
|
|
@@ -453,6 +497,7 @@ export class NamespaceSearchRouter {
|
|
|
453
497
|
available,
|
|
454
498
|
collectionState,
|
|
455
499
|
filtersNestedNamespaces,
|
|
500
|
+
disposed: false,
|
|
456
501
|
};
|
|
457
502
|
} catch (error) {
|
|
458
503
|
const dispose = (backend as { dispose?: () => void | Promise<void> }).dispose;
|
|
@@ -757,7 +757,229 @@ test("buildMergedTargetPromotionPayload and promotion refuse when interleaving w
|
|
|
757
757
|
);
|
|
758
758
|
});
|
|
759
759
|
|
|
760
|
-
|
|
760
|
+
// ── #2870: access-only telemetry vs semantic metadata in the promotion binding ──
|
|
761
|
+
|
|
762
|
+
type RawFileMutator = (raw: string) => string;
|
|
763
|
+
|
|
764
|
+
const withFrontmatterLine = (line: string): RawFileMutator => (raw) =>
|
|
765
|
+
raw.replace("\n---\n", `\n${line}\n---\n`);
|
|
766
|
+
|
|
767
|
+
/** Rewrite the durable file directly — a writer that changes semantics
|
|
768
|
+
* WITHOUT minting a CAS receipt (hand edit, legacy tool). Exactly the
|
|
769
|
+
* writer class the semantic-fingerprint clause must catch. */
|
|
770
|
+
async function rewriteDurableWithoutReceipt(
|
|
771
|
+
storage: StorageManager,
|
|
772
|
+
memoryId: string,
|
|
773
|
+
mutate: RawFileMutator,
|
|
774
|
+
): Promise<void> {
|
|
775
|
+
const row = await storage.getMemoryByIdIncludingArchived(memoryId);
|
|
776
|
+
assert.ok(row);
|
|
777
|
+
const before = await readFile(row.path, "utf8");
|
|
778
|
+
await writeFile(row.path, mutate(before), "utf8");
|
|
779
|
+
}
|
|
780
|
+
async function flushAccess(
|
|
781
|
+
storage: StorageManager,
|
|
782
|
+
memoryId: string,
|
|
783
|
+
newCount: number,
|
|
784
|
+
): Promise<number> {
|
|
785
|
+
return await storage.flushAccessTracking([
|
|
786
|
+
{ memoryId, newCount, lastAccessed: "2026-08-23T00:00:00.000Z" },
|
|
787
|
+
]);
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
async function runPromotion(
|
|
791
|
+
s: { source: StorageManager; router: { storageFor: (namespace: string) => Promise<StorageManager> } },
|
|
792
|
+
payload: MergedTargetPromotionPayload | null,
|
|
793
|
+
sourceMemoryId: string,
|
|
794
|
+
): Promise<number> {
|
|
795
|
+
let promotions = 0;
|
|
796
|
+
await promoteAndReconcileMergedTarget({
|
|
797
|
+
promote: async () => {
|
|
798
|
+
promotions += 1;
|
|
799
|
+
return `copy-${promotions}`;
|
|
800
|
+
},
|
|
801
|
+
config: parseConfig({ memoryDir: s.source.dir, sharedNamespace: "shared" }),
|
|
802
|
+
getStorageRouter: () => s.router,
|
|
803
|
+
scopeProfileWritePlan: null,
|
|
804
|
+
sourceStorage: s.source,
|
|
805
|
+
sourceMemoryId,
|
|
806
|
+
mergedPromotion: payload,
|
|
807
|
+
normalize: (content: string) => content,
|
|
808
|
+
});
|
|
809
|
+
return promotions;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
test("access flush between merge commit and payload build still promotes (#2870)", async () => {
|
|
813
|
+
const s = await makeStorages();
|
|
814
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
815
|
+
source: "test",
|
|
816
|
+
confidence: 0.5,
|
|
817
|
+
});
|
|
818
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
819
|
+
const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
|
|
820
|
+
assert.ok(committed);
|
|
821
|
+
const shardPath = casShardPath(s.source.dir, committed.path);
|
|
822
|
+
const receiptBefore = JSON.parse(await readFile(shardPath, "utf8")) as { revision: string };
|
|
823
|
+
const bytesBefore = await readFile(committed.path, "utf8");
|
|
824
|
+
|
|
825
|
+
assert.equal(await flushAccess(s.source, target.id, 3), 1, "the access flush landed");
|
|
826
|
+
|
|
827
|
+
// Prove the interleaving is real: bytes changed, receipt did not re-mint.
|
|
828
|
+
assert.notEqual(await readFile(committed.path, "utf8"), bytesBefore, "the flush rewrote the durable file");
|
|
829
|
+
const receiptAfter = JSON.parse(await readFile(shardPath, "utf8")) as { revision: string };
|
|
830
|
+
assert.equal(receiptAfter.revision, receiptBefore.revision, "an access flush mints no receipt");
|
|
831
|
+
|
|
832
|
+
const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
|
|
833
|
+
targetId: target.id,
|
|
834
|
+
mergedContent: A_MERGED_BODY,
|
|
835
|
+
provenancePatched: true,
|
|
836
|
+
});
|
|
837
|
+
assert.equal(readFailed, false);
|
|
838
|
+
assert.ok(payload, "an access-only flush must not refuse the payload");
|
|
839
|
+
assert.ok(payload?.committedSemanticFingerprint, "the payload carries the semantic binding");
|
|
840
|
+
|
|
841
|
+
assert.equal(await runPromotion(s, payload, target.id), 1, "the flushed-but-unchanged semantics still promote");
|
|
842
|
+
});
|
|
843
|
+
|
|
844
|
+
test("access flush between payload build and promotion still promotes (#2870)", async () => {
|
|
845
|
+
const s = await makeStorages();
|
|
846
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
847
|
+
source: "test",
|
|
848
|
+
confidence: 0.5,
|
|
849
|
+
});
|
|
850
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
851
|
+
const { payload } = await buildMergedTargetPromotionPayload(s.source, {
|
|
852
|
+
targetId: target.id,
|
|
853
|
+
mergedContent: A_MERGED_BODY,
|
|
854
|
+
provenancePatched: true,
|
|
855
|
+
});
|
|
856
|
+
assert.ok(payload);
|
|
857
|
+
assert.equal(await flushAccess(s.source, target.id, 7), 1, "the access flush lands after the build");
|
|
858
|
+
|
|
859
|
+
assert.equal(await runPromotion(s, payload, target.id), 1, "the final guard confirms the flushed record's semantics");
|
|
860
|
+
});
|
|
861
|
+
|
|
862
|
+
test("payload build refuses a semantic mutation that minted no receipt (#2870)", async () => {
|
|
863
|
+
const s = await makeStorages();
|
|
864
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
865
|
+
source: "test",
|
|
866
|
+
confidence: 0.5,
|
|
867
|
+
});
|
|
868
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
869
|
+
await rewriteDurableWithoutReceipt(
|
|
870
|
+
s.source,
|
|
871
|
+
target.id,
|
|
872
|
+
(raw) => raw.replace(/^confidence: .*$/m, "confidence: 0.99"),
|
|
873
|
+
);
|
|
874
|
+
const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
|
|
875
|
+
targetId: target.id,
|
|
876
|
+
mergedContent: A_MERGED_BODY,
|
|
877
|
+
provenancePatched: true,
|
|
878
|
+
});
|
|
879
|
+
assert.equal(payload, null, "a same-body confidence change must refuse the payload");
|
|
880
|
+
assert.equal(readFailed, true, "the refusal is an unknown outcome, not a no-promotion verdict");
|
|
881
|
+
});
|
|
882
|
+
|
|
883
|
+
test("final guard refuses each semantic field mutation that minted no receipt (#2870)", async () => {
|
|
884
|
+
const mutations: Array<[label: string, mutate: RawFileMutator]> = [
|
|
885
|
+
["confidence", (raw) => raw.replace(/^confidence: .*$/m, "confidence: 0.99")],
|
|
886
|
+
["tags", (raw) => raw.replace(/^tags: .*$/m, 'tags: ["mutated"]')],
|
|
887
|
+
["status", withFrontmatterLine("status: superseded")],
|
|
888
|
+
["provenance", withFrontmatterLine("provenance: unverified")],
|
|
889
|
+
["tool scope", withFrontmatterLine("toolScoped: true")],
|
|
890
|
+
["body", (raw) => `${raw}\nmutated body suffix`],
|
|
891
|
+
];
|
|
892
|
+
for (const [label, mutate] of mutations) {
|
|
893
|
+
const s = await makeStorages();
|
|
894
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
895
|
+
source: "test",
|
|
896
|
+
confidence: 0.5,
|
|
897
|
+
});
|
|
898
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
899
|
+
const { payload } = await buildMergedTargetPromotionPayload(s.source, {
|
|
900
|
+
targetId: target.id,
|
|
901
|
+
mergedContent: A_MERGED_BODY,
|
|
902
|
+
provenancePatched: true,
|
|
903
|
+
});
|
|
904
|
+
assert.ok(payload, `payload builds before the ${label} mutation`);
|
|
905
|
+
await rewriteDurableWithoutReceipt(s.source, target.id, mutate);
|
|
906
|
+
|
|
907
|
+
assert.equal(
|
|
908
|
+
await runPromotion(s, payload, target.id),
|
|
909
|
+
0,
|
|
910
|
+
`a ${label} mutation without a receipt must refuse promotion`,
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
});
|
|
914
|
+
|
|
915
|
+
test("a PENDING receipt marker between build and promotion abandons it (#2870)", async () => {
|
|
916
|
+
const s = await makeStorages();
|
|
917
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
918
|
+
source: "test",
|
|
919
|
+
confidence: 0.5,
|
|
920
|
+
});
|
|
921
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
922
|
+
const { payload } = await buildMergedTargetPromotionPayload(s.source, {
|
|
923
|
+
targetId: target.id,
|
|
924
|
+
mergedContent: A_MERGED_BODY,
|
|
925
|
+
provenancePatched: true,
|
|
926
|
+
});
|
|
927
|
+
assert.ok(payload);
|
|
928
|
+
const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
|
|
929
|
+
assert.ok(committed);
|
|
930
|
+
const shardPath = casShardPath(s.source.dir, committed.path);
|
|
931
|
+
const relative = path.relative(s.source.dir, committed.path).split(path.sep).join("/");
|
|
932
|
+
// A pending marker whose expected digest matches nothing: lazy recovery
|
|
933
|
+
// cannot decide it, so the receipt reads UNAVAILABLE and the promotion
|
|
934
|
+
// must refuse rather than confirm against an unknown identity.
|
|
935
|
+
await writeFile(
|
|
936
|
+
shardPath,
|
|
937
|
+
`${JSON.stringify({
|
|
938
|
+
version: 1,
|
|
939
|
+
path: relative,
|
|
940
|
+
revision: "2026-08-23T00:00:00.001Z",
|
|
941
|
+
state: "pending",
|
|
942
|
+
previous: payload.committedRevision ?? "2026-08-23T00:00:00.000Z",
|
|
943
|
+
baselineDigest: "0".repeat(64),
|
|
944
|
+
expectedDigest: "1".repeat(64),
|
|
945
|
+
})}\n`,
|
|
946
|
+
"utf8",
|
|
947
|
+
);
|
|
948
|
+
|
|
949
|
+
assert.equal(
|
|
950
|
+
await runPromotion(s, payload, target.id),
|
|
951
|
+
0,
|
|
952
|
+
"a pending (recovery-needed) receipt must not confirm the payload",
|
|
953
|
+
);
|
|
954
|
+
});
|
|
955
|
+
|
|
956
|
+
test("a legacy shard without a stored semantic fingerprint keeps the conservative digest refusal (#2870)", async () => {
|
|
957
|
+
const s = await makeStorages();
|
|
958
|
+
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, {
|
|
959
|
+
source: "test",
|
|
960
|
+
confidence: 0.5,
|
|
961
|
+
});
|
|
962
|
+
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
963
|
+
const committed = await s.source.getMemoryByIdIncludingArchived(target.id);
|
|
964
|
+
assert.ok(committed);
|
|
965
|
+
// Downgrade the shard to its pre-#2870 shape: committed digest, no
|
|
966
|
+
// semantic fingerprint.
|
|
967
|
+
const shardPath = casShardPath(s.source.dir, committed.path);
|
|
968
|
+
const shard = JSON.parse(await readFile(shardPath, "utf8")) as Record<string, unknown>;
|
|
969
|
+
delete shard.committedSemanticFingerprint;
|
|
970
|
+
await writeFile(shardPath, `${JSON.stringify(shard)}\n`, "utf8");
|
|
971
|
+
|
|
972
|
+
assert.equal(await flushAccess(s.source, target.id, 4), 1, "the access flush lands on the legacy shard");
|
|
973
|
+
const { payload, readFailed } = await buildMergedTargetPromotionPayload(s.source, {
|
|
974
|
+
targetId: target.id,
|
|
975
|
+
mergedContent: A_MERGED_BODY,
|
|
976
|
+
provenancePatched: true,
|
|
977
|
+
});
|
|
978
|
+
assert.equal(payload, null, "legacy shards keep the full-digest binding until the next semantic write");
|
|
979
|
+
assert.equal(readFailed, true);
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
test("legacy receipt with unavailable snapshot digest refuses promotion (#2813 P1, #2870)", async () => {
|
|
761
983
|
const s = await makeStorages();
|
|
762
984
|
const target = await s.source.writeMemory("fact", PRE_MERGE_BODY, { source: "test" });
|
|
763
985
|
await commitWriterMerge(s.source, target.id, A_MERGED_BODY);
|
|
@@ -769,6 +991,10 @@ test("buildMergedTargetPromotionPayload: unavailable snapshot digest refuses whe
|
|
|
769
991
|
status.status === "present" && status.committedDigest,
|
|
770
992
|
"the standing receipt carries a committed digest",
|
|
771
993
|
);
|
|
994
|
+
const shardPath = casShardPath(s.source.dir, committedRow.path);
|
|
995
|
+
const shard = JSON.parse(await readFile(shardPath, "utf8")) as Record<string, unknown>;
|
|
996
|
+
delete shard.committedSemanticFingerprint;
|
|
997
|
+
await writeFile(shardPath, `${JSON.stringify(shard)}\n`, "utf8");
|
|
772
998
|
|
|
773
999
|
s.source.readDurableFileDigest = async () => null;
|
|
774
1000
|
const built = await buildMergedTargetPromotionPayload(s.source, {
|
|
@@ -776,7 +1002,7 @@ test("buildMergedTargetPromotionPayload: unavailable snapshot digest refuses whe
|
|
|
776
1002
|
mergedContent: A_MERGED_BODY,
|
|
777
1003
|
provenancePatched: true,
|
|
778
1004
|
});
|
|
779
|
-
assert.equal(built.payload, null, "an unreadable snapshot digest must refuse the
|
|
1005
|
+
assert.equal(built.payload, null, "an unreadable snapshot digest must refuse the legacy receipt");
|
|
780
1006
|
assert.equal(built.readFailed, true, "unavailable snapshot is unknown, not an absent revision");
|
|
781
1007
|
|
|
782
1008
|
const legacyStore = await makeStorages();
|