@remnic/core 9.69.46 → 9.69.48
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 +15 -14
- package/dist/access-admin-ops-surface.js +43 -42
- package/dist/access-authorization-probe.d.ts +15 -14
- package/dist/access-authorization-probe.js +44 -43
- package/dist/access-boundary.d.ts +15 -14
- package/dist/access-boundary.js +43 -42
- package/dist/access-cli.js +120 -115
- 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 +15 -14
- package/dist/access-extraction-force-flush.js +43 -42
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-briefing.d.ts +15 -14
- package/dist/access-http-briefing.js +44 -43
- package/dist/access-http-lcm-compaction.d.ts +15 -14
- package/dist/access-http-lifecycle-flush.d.ts +15 -14
- package/dist/access-http-offline-stream.d.ts +15 -14
- package/dist/access-http-query.d.ts +2 -2
- package/dist/access-http-query.js +45 -44
- package/dist/access-http.d.ts +16 -15
- package/dist/access-http.js +68 -64
- package/dist/access-identity-continuity-surface.d.ts +11 -11
- package/dist/access-identity-continuity-surface.js +43 -42
- package/dist/access-lcm-surface.d.ts +15 -14
- package/dist/access-lcm-surface.js +43 -42
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp-shared-context-tools.d.ts +15 -14
- package/dist/access-mcp.d.ts +15 -14
- package/dist/access-mcp.js +56 -53
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-DDnsN22V.d.ts → access-namespace-preflight-CetF9ziA.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +43 -42
- package/dist/access-observe-transcript.d.ts +11 -11
- package/dist/access-observe-write-category.d.ts +3 -3
- package/dist/access-observe-write-category.js +4 -4
- package/dist/access-observe-write-surface.d.ts +15 -14
- package/dist/access-observe-write-surface.js +43 -42
- package/dist/access-offline-manifest.d.ts +11 -11
- package/dist/access-offline-manifest.js +2 -2
- package/dist/access-operations-batch.js +45 -44
- package/dist/access-operations.d.ts +16 -15
- package/dist/access-operations.js +52 -50
- package/dist/access-recall-concurrency.d.ts +15 -14
- package/dist/access-recall-concurrency.js +43 -42
- package/dist/access-recall-response.d.ts +15 -14
- package/dist/access-recall-response.js +43 -42
- package/dist/access-recall-surface.d.ts +15 -14
- package/dist/access-recall-surface.js +43 -42
- package/dist/access-schema.d.ts +114 -114
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-DGynYlbE.d.ts → access-service-DUkTWyZS.d.ts} +77 -74
- package/dist/access-service-helpers.d.ts +15 -14
- package/dist/access-service.d.ts +15 -14
- package/dist/access-service.js +43 -42
- package/dist/access-surface-catalog.d.ts +15 -14
- package/dist/access-surface-catalog.js +51 -44
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +4 -4
- 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 +3 -2
- package/dist/active-recall.js.map +1 -1
- package/dist/activity/digest.d.ts +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.d.ts +1 -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 +11 -11
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +13 -13
- 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 +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-Dl2hYqpS.d.ts → catalog-Bns9zpl3.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 +14 -14
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-N46SNYMC.js → chunk-2B2RHLHI.js} +2 -2
- package/dist/{chunk-F5V7KRQS.js → chunk-2WMXZYMS.js} +2 -2
- package/dist/{chunk-KF57IQFX.js → chunk-32ZBIGID.js} +19 -15
- package/dist/chunk-32ZBIGID.js.map +1 -0
- package/dist/{chunk-ORQ7AZMU.js → chunk-3RKVSECD.js} +8 -8
- package/dist/{chunk-3NYM6JA4.js → chunk-4LPIVP77.js} +2 -2
- package/dist/{chunk-PW4HTWXL.js → chunk-55XWRL6F.js} +2 -2
- package/dist/{chunk-GGY7WKMB.js → chunk-5KBI2MOC.js} +1 -1
- package/dist/{chunk-IXMWTNNY.js → chunk-6A6HSXWV.js} +2 -2
- package/dist/{chunk-P7S7BVBJ.js → chunk-7DU2F7LM.js} +3 -3
- package/dist/{chunk-4HTQ76O4.js → chunk-7SJCSDQ3.js} +2 -2
- package/dist/{chunk-U4ESGVZ2.js → chunk-7YUX52XZ.js} +3 -3
- package/dist/{chunk-FMEP2RB5.js → chunk-B4WI7OF2.js} +2 -2
- package/dist/{chunk-EUP4AXIW.js → chunk-B6VDWDFN.js} +2 -2
- package/dist/{chunk-UOREPQ3C.js → chunk-BIXELUIR.js} +2 -2
- package/dist/{chunk-GYYLZOSO.js → chunk-BMBAA2M5.js} +13 -6
- package/dist/chunk-BMBAA2M5.js.map +1 -0
- package/dist/{chunk-AYZHHMTK.js → chunk-BNX2TUSF.js} +2 -2
- package/dist/{chunk-5ZXGH2ZL.js → chunk-BXOPUJ3W.js} +2 -2
- package/dist/{chunk-TE6B2UU6.js → chunk-CD7VTZIG.js} +2 -2
- package/dist/{chunk-EC5SVM6H.js → chunk-DE4ZGH2N.js} +2 -2
- package/dist/{chunk-YFVIA5A6.js → chunk-DRLZB3CN.js} +2 -2
- package/dist/{chunk-SRRZZHA5.js → chunk-EGOWY342.js} +2 -2
- package/dist/chunk-EIB4FJVR.js +46 -0
- package/dist/chunk-EIB4FJVR.js.map +1 -0
- package/dist/{chunk-W44T2KHG.js → chunk-EWBDJQ5Y.js} +3 -3
- package/dist/{chunk-JMBTNVMW.js → chunk-FGRJJBFO.js} +2 -2
- package/dist/{chunk-F3TURDFG.js → chunk-FPB5LQWW.js} +4 -1
- package/dist/{chunk-F3TURDFG.js.map → chunk-FPB5LQWW.js.map} +1 -1
- package/dist/{chunk-WGZHSQDV.js → chunk-G2XZFGYN.js} +4 -4
- package/dist/{chunk-CFIHVWYZ.js → chunk-GGROFIYX.js} +2 -2
- package/dist/{chunk-XLZZLUWL.js → chunk-HG74GEVY.js} +2 -2
- package/dist/chunk-HMDYSGY6.js +54 -0
- package/dist/chunk-HMDYSGY6.js.map +1 -0
- package/dist/{chunk-WUUGE7QC.js → chunk-HS75MCQF.js} +4 -4
- package/dist/{chunk-DO6R3LIE.js → chunk-I6IJDTRP.js} +2 -2
- package/dist/{chunk-7ZNJN5WZ.js → chunk-IHOXK2I6.js} +55 -6
- package/dist/chunk-IHOXK2I6.js.map +1 -0
- package/dist/{chunk-2NKY7OC6.js → chunk-IMJPJY7V.js} +2 -2
- package/dist/{chunk-TZ44E732.js → chunk-IO7K7GES.js} +2 -2
- package/dist/{chunk-7BNB7KHB.js → chunk-JIURESYF.js} +7 -7
- package/dist/{chunk-AYP2FZFA.js → chunk-JUOJGZPV.js} +2 -2
- package/dist/{chunk-4XTSKGLX.js → chunk-JYXLW22X.js} +3 -3
- package/dist/{chunk-HXDXR2FH.js → chunk-KPYMORPQ.js} +41 -31
- package/dist/chunk-KPYMORPQ.js.map +1 -0
- package/dist/{chunk-IPLYGWQF.js → chunk-KQAFEZQX.js} +5 -5
- package/dist/{chunk-AN2O4KZY.js → chunk-KVIMQAER.js} +2 -2
- package/dist/chunk-LI4APB6M.js +218 -0
- package/dist/chunk-LI4APB6M.js.map +1 -0
- package/dist/{chunk-VGRVJ6Z6.js → chunk-LIAM7U2J.js} +2 -2
- package/dist/{chunk-S3SND7SO.js → chunk-LIDJWAQV.js} +2 -2
- package/dist/{chunk-T5NI5K46.js → chunk-LYMJ36UI.js} +2 -2
- package/dist/{chunk-UGGOQKO6.js → chunk-MKJFPIVG.js} +93 -51
- package/dist/chunk-MKJFPIVG.js.map +1 -0
- package/dist/{chunk-UEJY6ZTQ.js → chunk-MKLDZNBD.js} +2 -2
- package/dist/{chunk-QUFJ3NJE.js → chunk-MNG536IS.js} +20 -20
- package/dist/{chunk-SW42MMAH.js → chunk-MQT3WP3F.js} +2 -2
- package/dist/{chunk-5EHPB6RL.js → chunk-MUNR43V3.js} +2 -2
- package/dist/{chunk-OV7GJ4KW.js → chunk-NNFB4CU4.js} +2 -2
- package/dist/{chunk-47C6DF43.js → chunk-OS4JVTHR.js} +3 -3
- package/dist/{chunk-W6YDAIVB.js → chunk-OSTXIFZW.js} +13 -2
- package/dist/chunk-OSTXIFZW.js.map +1 -0
- package/dist/chunk-P3YNEMYY.js +212 -0
- package/dist/chunk-P3YNEMYY.js.map +1 -0
- package/dist/{chunk-JOP7W24J.js → chunk-PA67GXYJ.js} +8 -8
- package/dist/{chunk-FSH6KRKO.js → chunk-PPJLJD2D.js} +2 -2
- package/dist/{chunk-AG6PANBG.js → chunk-PXJ6HE2W.js} +11 -11
- package/dist/{chunk-DDBLZJRV.js → chunk-QB4VXCFN.js} +2 -2
- package/dist/{chunk-L63M2PE4.js → chunk-QGAKUOKU.js} +2 -2
- package/dist/{chunk-YUQPUK6H.js → chunk-QLCMOHRE.js} +2 -2
- package/dist/{chunk-Q4AUIFUA.js → chunk-QMWKENNK.js} +4 -4
- package/dist/{chunk-66QOUYNS.js → chunk-R32AEEU3.js} +174 -57
- package/dist/chunk-R32AEEU3.js.map +1 -0
- package/dist/{chunk-TNQR7N52.js → chunk-S3YM4SZQ.js} +2 -1
- package/dist/chunk-S3YM4SZQ.js.map +1 -0
- package/dist/{chunk-RW4QNB4J.js → chunk-S45INSV3.js} +3 -1
- package/dist/{chunk-RW4QNB4J.js.map → chunk-S45INSV3.js.map} +1 -1
- package/dist/{chunk-EEHQY7ER.js → chunk-SK6HEQTW.js} +2 -2
- package/dist/{chunk-PGAB2V53.js → chunk-SMBWBEE7.js} +2 -2
- package/dist/{chunk-62NYUFNH.js → chunk-SS33RR4F.js} +8 -8
- package/dist/{chunk-4ECS33D4.js → chunk-T3T5HTZZ.js} +2 -2
- package/dist/{chunk-KG2OOAFF.js → chunk-TQSCR5DU.js} +6 -6
- package/dist/{chunk-D5DTZBTV.js → chunk-TW4MXM7H.js} +6 -6
- package/dist/chunk-TW4MXM7H.js.map +1 -0
- package/dist/{chunk-AS2NOPDM.js → chunk-V7IONNTJ.js} +2 -2
- package/dist/{chunk-HYWPUYLO.js → chunk-VV5GCNKG.js} +2 -2
- package/dist/{chunk-Y3XHIWVP.js → chunk-WL3PGPGU.js} +2 -2
- package/dist/{chunk-3UQIS2GC.js → chunk-WNMVUWI7.js} +2 -2
- package/dist/{chunk-66YUOI53.js → chunk-WQW6KPVC.js} +1 -1
- package/dist/chunk-WQW6KPVC.js.map +1 -0
- package/dist/{chunk-2AV75BJW.js → chunk-WVI43D54.js} +24 -1
- package/dist/chunk-WVI43D54.js.map +1 -0
- package/dist/{chunk-WOBMSMUK.js → chunk-WYU66IVZ.js} +3 -3
- package/dist/{chunk-A7GQBJP5.js → chunk-X2NFFBTO.js} +4 -4
- package/dist/{chunk-CWMMKFO7.js → chunk-XEHLYA5Z.js} +3 -3
- package/dist/{chunk-JIWZVOQM.js → chunk-XKHRNAK7.js} +2 -2
- package/dist/{chunk-VW5TGNJN.js → chunk-XXLH6KFO.js} +2 -2
- package/dist/chunk-XYGINDIJ.js +74 -0
- package/dist/chunk-XYGINDIJ.js.map +1 -0
- package/dist/{chunk-J5OXWG66.js → chunk-XZUHXKM3.js} +2 -2
- package/dist/{chunk-K4KE5MYE.js → chunk-Y5VT7BIT.js} +2 -2
- package/dist/{chunk-S7KDHFF2.js → chunk-YXWMZAAN.js} +2 -2
- package/dist/{chunk-EAZ3YZKN.js → chunk-ZEIJQ4I3.js} +2 -2
- package/dist/{cli-Cik3H7q1.d.ts → cli-Bbndoc6k.d.ts} +5 -5
- package/dist/cli.d.ts +17 -16
- package/dist/cli.js +90 -85
- package/dist/coding/export-okf-codegraph.d.ts +1 -1
- package/dist/coding/export-okf-codegraph.js +12 -12
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +13 -13
- 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 +3 -2
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +13 -13
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +13 -13
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/contradiction/index.d.ts +4 -4
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +15 -15
- 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 +15 -15
- 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 +15 -14
- package/dist/deep-recall-http-glue.js +4 -4
- package/dist/deep-recall-mcp-tools.d.ts +15 -14
- package/dist/deep-recall-policy-llm.d.ts +2 -2
- package/dist/deep-recall-seeds.d.ts +1 -1
- package/dist/deep-recall.js +2 -2
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-BXaUoVUf.d.ts → dependency-propagation-delivery-B-LvcDaq.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 +14 -14
- 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 +11 -11
- package/dist/external-wiki-access.d.ts +15 -14
- package/dist/external-wiki-access.js +44 -43
- 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 +15 -14
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-evidence-class.d.ts +142 -0
- package/dist/extraction-evidence-class.js +113 -0
- package/dist/extraction-evidence-class.js.map +1 -0
- package/dist/extraction-faithfulness.d.ts +2 -2
- package/dist/extraction-judge-telemetry.d.ts +2 -2
- package/dist/extraction-judge-training.d.ts +2 -2
- package/dist/extraction-judge.d.ts +2 -2
- 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-source-grounding.js +2 -2
- package/dist/extraction-span-config.d.ts +1 -1
- package/dist/extraction-span-materialize.d.ts +1 -1
- package/dist/extraction-span-wire.d.ts +1 -1
- package/dist/extraction.d.ts +2 -2
- package/dist/extraction.js +21 -21
- package/dist/fallback-llm-codex-subscription.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{generic-recall-paths-BkVVEoeO.d.ts → generic-recall-paths-Bfc7zigS.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-Zb6SUV4R.d.ts → index-C7IA1DxB.d.ts} +3 -3
- package/dist/index.d.ts +798 -707
- package/dist/index.js +184 -134
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/index.js +7 -7
- 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-DdrhmecM.d.ts → local-llm-DH4tWtck.d.ts} +1 -1
- package/dist/local-llm-helpers.d.ts +2 -2
- package/dist/local-llm.d.ts +2 -2
- package/dist/local-llm.js +2 -2
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/location/index.d.ts +5 -5
- package/dist/location/index.js +15 -15
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +13 -13
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +14 -14
- package/dist/{maintenance-Du_VRvVg.d.ts → maintenance-n6yeTQhR.d.ts} +4 -4
- package/dist/mcp-memory-inspector-app.d.ts +15 -14
- package/dist/mcp-read-only-tools.js +1 -1
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-browse-http-glue.d.ts +170 -0
- package/dist/memory-browse-http-glue.js +9 -0
- package/dist/memory-browse-http-glue.js.map +1 -0
- package/dist/memory-browse-mcp-tools.d.ts +160 -0
- package/dist/memory-browse-mcp-tools.js +8 -0
- package/dist/memory-browse-mcp-tools.js.map +1 -0
- package/dist/memory-browse-operations.d.ts +2 -0
- package/dist/memory-browse-operations.js +246 -0
- package/dist/memory-browse-operations.js.map +1 -0
- package/dist/memory-browse.d.ts +113 -0
- package/dist/memory-browse.js +49 -0
- package/dist/memory-browse.js.map +1 -0
- 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 +15 -14
- package/dist/memory-subject.d.ts +15 -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 +14 -14
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +13 -13
- 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 +16 -16
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +23 -22
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +23 -23
- package/dist/{orchestrator-D9U3Zgjp.d.ts → orchestrator-Cirjo3ZB.d.ts} +10 -10
- package/dist/orchestrator.d.ts +11 -11
- package/dist/orchestrator.js +122 -117
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-4lqKJZ_0.d.ts → pipeline-DK79FrgH.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 +77 -2
- package/dist/provenance.js +7 -3
- package/dist/{public-http-AabioFLh.d.ts → public-http-DaHHhWRR.d.ts} +1 -1
- package/dist/{qmd-DnoWaXKb.d.ts → qmd-BT0ErlRS.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +2 -2
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +2 -2
- package/dist/qmd.js +4 -4
- package/dist/recall-concurrency-config.d.ts +1 -1
- package/dist/recall-context-composition.d.ts +43 -3
- package/dist/recall-context-composition.js +5 -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 +2 -2
- package/dist/recall-navigate.d.ts +1 -1
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-http-glue.d.ts +15 -14
- package/dist/recall-navigation-mcp-tools.d.ts +15 -14
- package/dist/recall-navigation-operations.js +44 -43
- package/dist/recall-navigation-renderer.d.ts +1 -1
- package/dist/recall-navigation.d.ts +1 -1
- package/dist/recall-navigation.js +43 -42
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state-view-admission.d.ts +2 -2
- package/dist/recall-state-view-admission.js +5 -5
- package/dist/recall-state-view-anchors.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-timings.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +4 -1
- package/dist/reconcile/manifest.js +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 +4 -3
- 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/schemas.d.ts +160 -160
- package/dist/{scope-profiles-crazXegZ.d.ts → scope-profiles-BgPQx9iE.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 +5 -5
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +9 -9
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-B09JI9WM.d.ts → semantic-consolidation-BrAWKVcm.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +14 -14
- package/dist/semantic-rule-promotion.js +13 -13
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +13 -13
- package/dist/{service-ByjbCuj7.d.ts → service-CqHOTg87.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 +7 -7
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +17 -17
- package/dist/standing-memory-block.d.ts +77 -0
- package/dist/standing-memory-block.js +40 -0
- package/dist/standing-memory-block.js.map +1 -0
- package/dist/standup/build.js +13 -13
- package/dist/{storage-CbdF077z.d.ts → storage-mD2YQ8_2.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +12 -12
- package/dist/subject-config.d.ts +1 -1
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +18 -17
- package/dist/support-passport/index.js +46 -45
- package/dist/{tagging-CF7DNV7_.d.ts → tagging-CiAVA-ID.d.ts} +2 -2
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-timeline-recall.d.ts +1 -1
- package/dist/temporal-timeline-recall.js +2 -2
- 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/autodetect.js +1 -1
- package/dist/transfer/backup.js +1 -1
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/export-okf.d.ts +1 -1
- package/dist/transfer/export-okf.js +13 -13
- package/dist/transfer/types.d.ts +78 -78
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-nmhnJpxx.d.ts → types-DgDaoY61.d.ts} +6 -0
- 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 +13 -13
- package/dist/who-knows-cli.d.ts +15 -14
- package/dist/who-knows-cli.js +14 -14
- package/dist/who-knows.d.ts +15 -14
- package/dist/who-knows.js +13 -13
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +3 -0
- package/src/access-http.ts +2 -2
- package/src/access-mcp-output-schemas.ts +25 -0
- package/src/access-mcp.ts +3 -3
- package/src/access-operations.ts +2 -0
- package/src/access-service.ts +6 -1
- package/src/access-surface-catalog.test.ts +20 -0
- package/src/access-surface-catalog.ts +6 -0
- package/src/activity/timeline/index.ts +1 -0
- package/src/activity/timeline/journal-recap.test.ts +17 -0
- package/src/activity/timeline/journal-recap.ts +19 -6
- package/src/activity/timeline/recap-export-range.test.ts +289 -0
- package/src/activity/timeline/recap-export-range.ts +169 -0
- package/src/activity/timeline/recap-export.test.ts +73 -1
- package/src/activity/timeline/recap-export.ts +57 -4
- package/src/cli/memory-browse-commands.ts +77 -0
- package/src/cli.ts +2 -2
- package/src/config.ts +11 -0
- package/src/extraction-evidence-class.test.ts +355 -0
- package/src/extraction-evidence-class.ts +241 -0
- package/src/index.ts +1 -0
- package/src/mcp-read-only-tools.ts +3 -0
- package/src/memory-browse-http-glue.ts +93 -0
- package/src/memory-browse-mcp-tools.ts +57 -0
- package/src/memory-browse-operations.ts +88 -0
- package/src/memory-browse-surface.test.ts +500 -0
- package/src/memory-browse.ts +316 -0
- package/src/provenance.ts +3 -3
- package/src/recall-context-composition.test.ts +66 -0
- package/src/recall-context-composition.ts +102 -2
- package/src/reconcile/manifest.test.ts +27 -0
- package/src/reconcile/manifest.ts +7 -0
- package/src/standing-memory-block.test.ts +262 -0
- package/src/standing-memory-block.ts +331 -0
- package/src/types.ts +6 -0
- package/dist/chunk-2AV75BJW.js.map +0 -1
- package/dist/chunk-66QOUYNS.js.map +0 -1
- package/dist/chunk-66YUOI53.js.map +0 -1
- package/dist/chunk-7ZNJN5WZ.js.map +0 -1
- package/dist/chunk-D5DTZBTV.js.map +0 -1
- package/dist/chunk-GYYLZOSO.js.map +0 -1
- package/dist/chunk-HXDXR2FH.js.map +0 -1
- package/dist/chunk-KF57IQFX.js.map +0 -1
- package/dist/chunk-TNQR7N52.js.map +0 -1
- package/dist/chunk-UGGOQKO6.js.map +0 -1
- package/dist/chunk-W6YDAIVB.js.map +0 -1
- /package/dist/{chunk-N46SNYMC.js.map → chunk-2B2RHLHI.js.map} +0 -0
- /package/dist/{chunk-F5V7KRQS.js.map → chunk-2WMXZYMS.js.map} +0 -0
- /package/dist/{chunk-ORQ7AZMU.js.map → chunk-3RKVSECD.js.map} +0 -0
- /package/dist/{chunk-3NYM6JA4.js.map → chunk-4LPIVP77.js.map} +0 -0
- /package/dist/{chunk-PW4HTWXL.js.map → chunk-55XWRL6F.js.map} +0 -0
- /package/dist/{chunk-GGY7WKMB.js.map → chunk-5KBI2MOC.js.map} +0 -0
- /package/dist/{chunk-IXMWTNNY.js.map → chunk-6A6HSXWV.js.map} +0 -0
- /package/dist/{chunk-P7S7BVBJ.js.map → chunk-7DU2F7LM.js.map} +0 -0
- /package/dist/{chunk-4HTQ76O4.js.map → chunk-7SJCSDQ3.js.map} +0 -0
- /package/dist/{chunk-U4ESGVZ2.js.map → chunk-7YUX52XZ.js.map} +0 -0
- /package/dist/{chunk-FMEP2RB5.js.map → chunk-B4WI7OF2.js.map} +0 -0
- /package/dist/{chunk-EUP4AXIW.js.map → chunk-B6VDWDFN.js.map} +0 -0
- /package/dist/{chunk-UOREPQ3C.js.map → chunk-BIXELUIR.js.map} +0 -0
- /package/dist/{chunk-AYZHHMTK.js.map → chunk-BNX2TUSF.js.map} +0 -0
- /package/dist/{chunk-5ZXGH2ZL.js.map → chunk-BXOPUJ3W.js.map} +0 -0
- /package/dist/{chunk-TE6B2UU6.js.map → chunk-CD7VTZIG.js.map} +0 -0
- /package/dist/{chunk-EC5SVM6H.js.map → chunk-DE4ZGH2N.js.map} +0 -0
- /package/dist/{chunk-YFVIA5A6.js.map → chunk-DRLZB3CN.js.map} +0 -0
- /package/dist/{chunk-SRRZZHA5.js.map → chunk-EGOWY342.js.map} +0 -0
- /package/dist/{chunk-W44T2KHG.js.map → chunk-EWBDJQ5Y.js.map} +0 -0
- /package/dist/{chunk-JMBTNVMW.js.map → chunk-FGRJJBFO.js.map} +0 -0
- /package/dist/{chunk-WGZHSQDV.js.map → chunk-G2XZFGYN.js.map} +0 -0
- /package/dist/{chunk-CFIHVWYZ.js.map → chunk-GGROFIYX.js.map} +0 -0
- /package/dist/{chunk-XLZZLUWL.js.map → chunk-HG74GEVY.js.map} +0 -0
- /package/dist/{chunk-WUUGE7QC.js.map → chunk-HS75MCQF.js.map} +0 -0
- /package/dist/{chunk-DO6R3LIE.js.map → chunk-I6IJDTRP.js.map} +0 -0
- /package/dist/{chunk-2NKY7OC6.js.map → chunk-IMJPJY7V.js.map} +0 -0
- /package/dist/{chunk-TZ44E732.js.map → chunk-IO7K7GES.js.map} +0 -0
- /package/dist/{chunk-7BNB7KHB.js.map → chunk-JIURESYF.js.map} +0 -0
- /package/dist/{chunk-AYP2FZFA.js.map → chunk-JUOJGZPV.js.map} +0 -0
- /package/dist/{chunk-4XTSKGLX.js.map → chunk-JYXLW22X.js.map} +0 -0
- /package/dist/{chunk-IPLYGWQF.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-AN2O4KZY.js.map → chunk-KVIMQAER.js.map} +0 -0
- /package/dist/{chunk-VGRVJ6Z6.js.map → chunk-LIAM7U2J.js.map} +0 -0
- /package/dist/{chunk-S3SND7SO.js.map → chunk-LIDJWAQV.js.map} +0 -0
- /package/dist/{chunk-T5NI5K46.js.map → chunk-LYMJ36UI.js.map} +0 -0
- /package/dist/{chunk-UEJY6ZTQ.js.map → chunk-MKLDZNBD.js.map} +0 -0
- /package/dist/{chunk-QUFJ3NJE.js.map → chunk-MNG536IS.js.map} +0 -0
- /package/dist/{chunk-SW42MMAH.js.map → chunk-MQT3WP3F.js.map} +0 -0
- /package/dist/{chunk-5EHPB6RL.js.map → chunk-MUNR43V3.js.map} +0 -0
- /package/dist/{chunk-OV7GJ4KW.js.map → chunk-NNFB4CU4.js.map} +0 -0
- /package/dist/{chunk-47C6DF43.js.map → chunk-OS4JVTHR.js.map} +0 -0
- /package/dist/{chunk-JOP7W24J.js.map → chunk-PA67GXYJ.js.map} +0 -0
- /package/dist/{chunk-FSH6KRKO.js.map → chunk-PPJLJD2D.js.map} +0 -0
- /package/dist/{chunk-AG6PANBG.js.map → chunk-PXJ6HE2W.js.map} +0 -0
- /package/dist/{chunk-DDBLZJRV.js.map → chunk-QB4VXCFN.js.map} +0 -0
- /package/dist/{chunk-L63M2PE4.js.map → chunk-QGAKUOKU.js.map} +0 -0
- /package/dist/{chunk-YUQPUK6H.js.map → chunk-QLCMOHRE.js.map} +0 -0
- /package/dist/{chunk-Q4AUIFUA.js.map → chunk-QMWKENNK.js.map} +0 -0
- /package/dist/{chunk-EEHQY7ER.js.map → chunk-SK6HEQTW.js.map} +0 -0
- /package/dist/{chunk-PGAB2V53.js.map → chunk-SMBWBEE7.js.map} +0 -0
- /package/dist/{chunk-62NYUFNH.js.map → chunk-SS33RR4F.js.map} +0 -0
- /package/dist/{chunk-4ECS33D4.js.map → chunk-T3T5HTZZ.js.map} +0 -0
- /package/dist/{chunk-KG2OOAFF.js.map → chunk-TQSCR5DU.js.map} +0 -0
- /package/dist/{chunk-AS2NOPDM.js.map → chunk-V7IONNTJ.js.map} +0 -0
- /package/dist/{chunk-HYWPUYLO.js.map → chunk-VV5GCNKG.js.map} +0 -0
- /package/dist/{chunk-Y3XHIWVP.js.map → chunk-WL3PGPGU.js.map} +0 -0
- /package/dist/{chunk-3UQIS2GC.js.map → chunk-WNMVUWI7.js.map} +0 -0
- /package/dist/{chunk-WOBMSMUK.js.map → chunk-WYU66IVZ.js.map} +0 -0
- /package/dist/{chunk-A7GQBJP5.js.map → chunk-X2NFFBTO.js.map} +0 -0
- /package/dist/{chunk-CWMMKFO7.js.map → chunk-XEHLYA5Z.js.map} +0 -0
- /package/dist/{chunk-JIWZVOQM.js.map → chunk-XKHRNAK7.js.map} +0 -0
- /package/dist/{chunk-VW5TGNJN.js.map → chunk-XXLH6KFO.js.map} +0 -0
- /package/dist/{chunk-J5OXWG66.js.map → chunk-XZUHXKM3.js.map} +0 -0
- /package/dist/{chunk-K4KE5MYE.js.map → chunk-Y5VT7BIT.js.map} +0 -0
- /package/dist/{chunk-S7KDHFF2.js.map → chunk-YXWMZAAN.js.map} +0 -0
- /package/dist/{chunk-EAZ3YZKN.js.map → chunk-ZEIJQ4I3.js.map} +0 -0
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory-store browse verbs (issue #2978) — deterministic `ls` / `tree` /
|
|
3
|
+
* `find` over ONE resolved namespace's memory store, so an agent can see
|
|
4
|
+
* what exists instead of guessing ids at an opaque search box.
|
|
5
|
+
*
|
|
6
|
+
* Scope rules (all existing contracts, no new ones):
|
|
7
|
+
* - Every call resolves through the caller's `resolveReadableNamespace`
|
|
8
|
+
* (read/write path symmetry) and ONE storage instance — browse never
|
|
9
|
+
* enumerates across namespaces.
|
|
10
|
+
* - Only the recall corpus is browsable: a path's top segment must be a
|
|
11
|
+
* `RECALL_FALLBACK_DIRS` category AND survive
|
|
12
|
+
* `isGenericRecallExcludedPath`. Derived stores (`artifacts/`,
|
|
13
|
+
* `meetings/` records, wearables day stores, `state/`, ...) are
|
|
14
|
+
* indistinguishable from missing paths — `not_found`, never listed.
|
|
15
|
+
* - Support-passport private memories are filtered exactly like
|
|
16
|
+
* `memoryBrowse` (the paginated list): their names never appear.
|
|
17
|
+
* - Output is deterministically sorted (plain code-point order, no
|
|
18
|
+
* locale) and entry-capped so a huge store cannot blow the response.
|
|
19
|
+
*
|
|
20
|
+
* `ponytail:` the index is rebuilt from `readAllMemories()` per call —
|
|
21
|
+
* O(corpus) per browse. Fine at agent cadence; swap for a cached directory
|
|
22
|
+
* index if browsing ever sits on a hot path.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { toMemoryPathRel } from "./memory-lifecycle-ledger-utils.js";
|
|
26
|
+
import { normalizeProjectionPreview } from "./memory-projection-format.js";
|
|
27
|
+
import { isGenericRecallExcludedPath } from "./orchestration/generic-recall-paths.js";
|
|
28
|
+
import { isSupportPassportPrivateMemory } from "./support-passport/card-projection.js";
|
|
29
|
+
import { RECALL_FALLBACK_DIRS } from "./utils/category-dir.js";
|
|
30
|
+
import type { MemoryFile } from "./types.js";
|
|
31
|
+
|
|
32
|
+
/** Browse reads touch only these storage members. */
|
|
33
|
+
export interface MemoryBrowseStorage {
|
|
34
|
+
readonly dir: string;
|
|
35
|
+
readAllMemories(): Promise<MemoryFile[]>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Injected seams; the service supplies live wiring, tests supply doubles. */
|
|
39
|
+
export interface MemoryBrowseDeps {
|
|
40
|
+
readonly resolveReadableNamespace: (namespace: string | undefined, principal?: string) => string;
|
|
41
|
+
readonly getStorage: (namespace: string) => Promise<MemoryBrowseStorage>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type BrowseVerb = "ls" | "tree" | "find";
|
|
45
|
+
|
|
46
|
+
export interface MemoryStoreBrowseRequest {
|
|
47
|
+
readonly verb: BrowseVerb;
|
|
48
|
+
/** ls/tree: directory relative to the store root ("" or "/" = root). */
|
|
49
|
+
readonly path?: string;
|
|
50
|
+
/** tree: expansion depth, 1..MAX_TREE_DEPTH (default 1). */
|
|
51
|
+
readonly depth?: number;
|
|
52
|
+
/** find: glob (`*` wildcard) or substring matched against path and name. */
|
|
53
|
+
readonly pattern?: string;
|
|
54
|
+
readonly namespace?: string;
|
|
55
|
+
readonly authenticatedPrincipal?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface MemoryBrowseEntry {
|
|
59
|
+
/** Store-relative path with forward slashes; dirs carry no trailing slash. */
|
|
60
|
+
readonly path: string;
|
|
61
|
+
readonly kind: "dir" | "file";
|
|
62
|
+
readonly name: string;
|
|
63
|
+
/** Files: first content line (180-char preview). Dirs: empty. */
|
|
64
|
+
readonly description: string;
|
|
65
|
+
/** Dirs: recursive memory count beneath. Files: 1. */
|
|
66
|
+
readonly count: number;
|
|
67
|
+
/** 0-based depth relative to the browse root (tree nests; ls/find are 0). */
|
|
68
|
+
readonly depth: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type MemoryBrowseError = "invalid_path" | "not_found" | "invalid_depth" | "invalid_pattern";
|
|
72
|
+
|
|
73
|
+
export type MemoryStoreBrowseResult =
|
|
74
|
+
| {
|
|
75
|
+
ok: true;
|
|
76
|
+
verb: BrowseVerb;
|
|
77
|
+
namespace: string;
|
|
78
|
+
path: string;
|
|
79
|
+
total: number;
|
|
80
|
+
entries: MemoryBrowseEntry[];
|
|
81
|
+
truncated: boolean;
|
|
82
|
+
rendered: string;
|
|
83
|
+
}
|
|
84
|
+
| {
|
|
85
|
+
ok: false;
|
|
86
|
+
verb: BrowseVerb;
|
|
87
|
+
path: string;
|
|
88
|
+
error: MemoryBrowseError;
|
|
89
|
+
message: string;
|
|
90
|
+
rendered: string;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const MAX_LS_ENTRIES = 200;
|
|
94
|
+
export const MAX_TREE_ENTRIES = 400;
|
|
95
|
+
export const MAX_TREE_DEPTH = 4;
|
|
96
|
+
export const MAX_FIND_ENTRIES = 200;
|
|
97
|
+
const MAX_PATH_CHARS = 512;
|
|
98
|
+
const MAX_PATTERN_CHARS = 256;
|
|
99
|
+
|
|
100
|
+
const BROWSABLE_ROOTS: Record<string, true> = Object.fromEntries(RECALL_FALLBACK_DIRS.map((dir) => [dir, true]));
|
|
101
|
+
|
|
102
|
+
/** The recall-corpus visibility rule shared by every browse code path. */
|
|
103
|
+
function isBrowsableMemoryPath(relPath: string): boolean {
|
|
104
|
+
if (!relPath.endsWith(".md")) return false;
|
|
105
|
+
const top = relPath.split("/")[0] ?? "";
|
|
106
|
+
return BROWSABLE_ROOTS[top] === true && !isGenericRecallExcludedPath(relPath);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Normalize a caller-supplied store path. Returns "" for the root. Throws
|
|
111
|
+
* `Error` on absolute paths, `..`/`.` segments, backslashes, control
|
|
112
|
+
* characters, or oversize input — never reinterpreted (pattern 39).
|
|
113
|
+
*/
|
|
114
|
+
export function sanitizeBrowsePath(raw: string | undefined): string {
|
|
115
|
+
const trimmed = (raw ?? "").trim();
|
|
116
|
+
if (trimmed === "" || trimmed === "/") return "";
|
|
117
|
+
if (trimmed.length > MAX_PATH_CHARS) throw new Error("path is too long");
|
|
118
|
+
if (trimmed.includes("\\")) throw new Error("path must use '/' separators");
|
|
119
|
+
const segments = trimmed.split("/");
|
|
120
|
+
for (const segment of segments) {
|
|
121
|
+
if (segment === "") throw new Error("path has an empty segment");
|
|
122
|
+
if (segment === "." || segment === "..") throw new Error("path must not contain '.' or '..' segments");
|
|
123
|
+
for (const ch of segment) {
|
|
124
|
+
const code = ch.charCodeAt(0);
|
|
125
|
+
if (code < 0x20 || code === 0x7f) throw new Error("path has control characters");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return segments.join("/");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Escape every regex metacharacter in a glob segment. */
|
|
132
|
+
function segmentRegex(segment: string): RegExp {
|
|
133
|
+
const source = `^${segment.split("*").map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join(".*")}$`;
|
|
134
|
+
return new RegExp(source, "i");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* `*` glob (one segment per pattern segment, `find -name` semantics — `*`
|
|
139
|
+
* never crosses `/`) or case-insensitive substring over path and name.
|
|
140
|
+
*/
|
|
141
|
+
export function browsePatternMatches(pattern: string, relPath: string): boolean {
|
|
142
|
+
const segments = relPath.split("/");
|
|
143
|
+
const name = segments[segments.length - 1] ?? "";
|
|
144
|
+
const patternSegments = pattern.split("/");
|
|
145
|
+
if (patternSegments.length === 1) {
|
|
146
|
+
const single = patternSegments[0]!;
|
|
147
|
+
if (single.includes("*")) return segmentRegex(single).test(name);
|
|
148
|
+
const needle = single.toLowerCase();
|
|
149
|
+
return relPath.toLowerCase().includes(needle) || name.toLowerCase().includes(needle);
|
|
150
|
+
}
|
|
151
|
+
if (patternSegments.length !== segments.length) return false;
|
|
152
|
+
return patternSegments.every((segment, index) => segmentRegex(segment).test(segments[index]!));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
interface DirNode {
|
|
156
|
+
readonly subdirs: Map<string, DirNode>;
|
|
157
|
+
readonly files: Map<string, MemoryFile>;
|
|
158
|
+
count: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function emptyNode(): DirNode {
|
|
162
|
+
return { subdirs: new Map(), files: new Map(), count: 0 };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Directory index over the browsable corpus: root "" holds category dirs. */
|
|
166
|
+
function buildIndex(memories: readonly MemoryFile[], dir: string): DirNode {
|
|
167
|
+
const root = emptyNode();
|
|
168
|
+
for (const memory of memories) {
|
|
169
|
+
const rel = toMemoryPathRel(dir, memory.path);
|
|
170
|
+
if (!isBrowsableMemoryPath(rel)) continue;
|
|
171
|
+
const segments = rel.split("/");
|
|
172
|
+
let node = root;
|
|
173
|
+
node.count += 1;
|
|
174
|
+
for (let index = 0; index < segments.length - 1; index += 1) {
|
|
175
|
+
const name = segments[index]!;
|
|
176
|
+
let child = node.subdirs.get(name);
|
|
177
|
+
if (child === undefined) {
|
|
178
|
+
child = emptyNode();
|
|
179
|
+
node.subdirs.set(name, child);
|
|
180
|
+
}
|
|
181
|
+
node = child;
|
|
182
|
+
node.count += 1;
|
|
183
|
+
}
|
|
184
|
+
node.files.set(segments[segments.length - 1]!, memory);
|
|
185
|
+
}
|
|
186
|
+
return root;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function byPath(left: { path: string }, right: { path: string }): number {
|
|
190
|
+
return left.path < right.path ? -1 : left.path > right.path ? 1 : 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function dirEntries(node: DirNode, dirPath: string): MemoryBrowseEntry[] {
|
|
194
|
+
const prefix = dirPath === "" ? "" : `${dirPath}/`;
|
|
195
|
+
const entries: MemoryBrowseEntry[] = [];
|
|
196
|
+
for (const [name, child] of node.subdirs) {
|
|
197
|
+
entries.push({ path: `${prefix}${name}`, kind: "dir", name, description: "", count: child.count, depth: 0 });
|
|
198
|
+
}
|
|
199
|
+
for (const [name, memory] of node.files) {
|
|
200
|
+
entries.push({
|
|
201
|
+
path: `${prefix}${name}`,
|
|
202
|
+
kind: "file",
|
|
203
|
+
name,
|
|
204
|
+
description: normalizeProjectionPreview(memory.content),
|
|
205
|
+
count: 1,
|
|
206
|
+
depth: 0,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
return entries.sort(byPath);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function renderEntries(verb: BrowseVerb, namespace: string, browsePath: string, entries: readonly MemoryBrowseEntry[]): string {
|
|
213
|
+
const lines = [`${verb} ${namespace}:${browsePath === "" ? "/" : browsePath}`];
|
|
214
|
+
for (const entry of entries) {
|
|
215
|
+
const indent = " ".repeat(entry.depth);
|
|
216
|
+
if (entry.kind === "dir") {
|
|
217
|
+
lines.push(`${indent}${entry.path}/ (${entry.count} memories)`);
|
|
218
|
+
} else {
|
|
219
|
+
const description = entry.description.length > 0 ? ` — ${entry.description}` : "";
|
|
220
|
+
lines.push(`${indent}${entry.path}${description}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return lines.join("\n");
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function refusal(verb: BrowseVerb, browsePath: string, error: MemoryBrowseError, message: string): MemoryStoreBrowseResult {
|
|
227
|
+
return { ok: false, verb, path: browsePath, error, message, rendered: `browse ${verb} failed: ${error} — ${message}` };
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Run one browse verb. Malformed input throws `Error`; typed refusals return in-band. */
|
|
231
|
+
export async function runMemoryBrowse(
|
|
232
|
+
deps: MemoryBrowseDeps,
|
|
233
|
+
request: MemoryStoreBrowseRequest,
|
|
234
|
+
): Promise<MemoryStoreBrowseResult> {
|
|
235
|
+
const namespace = deps.resolveReadableNamespace(request.namespace, request.authenticatedPrincipal);
|
|
236
|
+
const storage = await deps.getStorage(namespace);
|
|
237
|
+
const memories = (await storage.readAllMemories()).filter((memory) => !isSupportPassportPrivateMemory(memory));
|
|
238
|
+
|
|
239
|
+
if (request.verb === "find") {
|
|
240
|
+
const pattern = (request.pattern ?? "").trim();
|
|
241
|
+
if (pattern.length === 0) return refusal(request.verb, "", "invalid_pattern", "pattern is required");
|
|
242
|
+
if (pattern.length > MAX_PATTERN_CHARS) {
|
|
243
|
+
return refusal(request.verb, "", "invalid_pattern", "pattern is too long");
|
|
244
|
+
}
|
|
245
|
+
const hits: MemoryBrowseEntry[] = [];
|
|
246
|
+
let truncated = false;
|
|
247
|
+
let total = 0;
|
|
248
|
+
for (const memory of memories) {
|
|
249
|
+
const rel = toMemoryPathRel(storage.dir, memory.path);
|
|
250
|
+
if (!isBrowsableMemoryPath(rel)) continue;
|
|
251
|
+
if (!browsePatternMatches(pattern, rel)) continue;
|
|
252
|
+
total += 1;
|
|
253
|
+
if (hits.length >= MAX_FIND_ENTRIES) {
|
|
254
|
+
truncated = true;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
hits.push({
|
|
258
|
+
path: rel,
|
|
259
|
+
kind: "file",
|
|
260
|
+
name: rel.split("/").pop() ?? rel,
|
|
261
|
+
description: normalizeProjectionPreview(memory.content),
|
|
262
|
+
count: 1,
|
|
263
|
+
depth: 0,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
hits.sort(byPath);
|
|
267
|
+
return { ok: true, verb: "find", namespace, path: "", total, entries: hits, truncated, rendered: renderEntries("find", namespace, "", hits) };
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
let browsePath: string;
|
|
271
|
+
try {
|
|
272
|
+
browsePath = sanitizeBrowsePath(request.path);
|
|
273
|
+
} catch (err) {
|
|
274
|
+
return refusal(request.verb, request.path ?? "", "invalid_path", err instanceof Error ? err.message : String(err));
|
|
275
|
+
}
|
|
276
|
+
const root = buildIndex(memories, storage.dir);
|
|
277
|
+
let node: DirNode | undefined = root;
|
|
278
|
+
for (const segment of browsePath === "" ? [] : browsePath.split("/")) {
|
|
279
|
+
node = node?.subdirs.get(segment);
|
|
280
|
+
if (node === undefined) break;
|
|
281
|
+
}
|
|
282
|
+
// Invisible-by-design stores resolve as not_found, indistinguishable from
|
|
283
|
+
// a missing path: the index only ever contains browsable corpus paths.
|
|
284
|
+
if (node === undefined) {
|
|
285
|
+
return refusal(request.verb, browsePath, "not_found", `no browsable store path: ${browsePath}`);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (request.verb === "ls") {
|
|
289
|
+
const all = dirEntries(node, browsePath);
|
|
290
|
+
const truncated = all.length > MAX_LS_ENTRIES;
|
|
291
|
+
const entries = all.slice(0, MAX_LS_ENTRIES);
|
|
292
|
+
return { ok: true, verb: "ls", namespace, path: browsePath, total: all.length, entries, truncated, rendered: renderEntries("ls", namespace, browsePath, entries) };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
if (request.depth !== undefined && (!Number.isInteger(request.depth) || request.depth < 1 || request.depth > MAX_TREE_DEPTH)) {
|
|
296
|
+
return refusal(request.verb, browsePath, "invalid_depth", `depth must be an integer between 1 and ${MAX_TREE_DEPTH}`);
|
|
297
|
+
}
|
|
298
|
+
const depth = request.depth ?? 1;
|
|
299
|
+
const entries: MemoryBrowseEntry[] = [];
|
|
300
|
+
let truncated = false;
|
|
301
|
+
const walk = (current: DirNode, currentPath: string, currentDepth: number): void => {
|
|
302
|
+
for (const entry of dirEntries(current, currentPath)) {
|
|
303
|
+
if (entries.length >= MAX_TREE_ENTRIES) {
|
|
304
|
+
truncated = true;
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
entries.push({ ...entry, depth: currentDepth });
|
|
308
|
+
if (entry.kind === "dir" && currentDepth < depth - 1) {
|
|
309
|
+
walk(current.subdirs.get(entry.name)!, entry.path, currentDepth + 1);
|
|
310
|
+
if (truncated) return;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
walk(node, browsePath, 0);
|
|
315
|
+
return { ok: true, verb: "tree", namespace, path: browsePath, total: entries.length, entries, truncated, rendered: renderEntries("tree", namespace, browsePath, entries) };
|
|
316
|
+
}
|
package/src/provenance.ts
CHANGED
|
@@ -652,11 +652,11 @@ function casefold(s: string): string {
|
|
|
652
652
|
* this as a verified match and record a source without offsets (cursor
|
|
653
653
|
* thread Ocver — "Normalized match drops verified provenance").
|
|
654
654
|
*/
|
|
655
|
-
type LocateQuoteResult =
|
|
655
|
+
export type LocateQuoteResult =
|
|
656
656
|
| { matched: false }
|
|
657
657
|
| { matched: true; offsets?: { charStart: number; charEnd: number } };
|
|
658
658
|
|
|
659
|
-
function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
|
|
659
|
+
export function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
|
|
660
660
|
// 1. Exact substring match (handles unicode, curly quotes, emoji verbatim).
|
|
661
661
|
const exactIdx = text.indexOf(quote);
|
|
662
662
|
if (exactIdx >= 0) {
|
|
@@ -769,7 +769,7 @@ function locateQuoteOffsets(quote: string, text: string): LocateQuoteResult {
|
|
|
769
769
|
* original meaning (chatgpt-codex-connector thread 4xA — limiting role-prefix
|
|
770
770
|
* stripping to actual prompt labels).
|
|
771
771
|
*/
|
|
772
|
-
function stripLeadingRolePrefix(quote: string): string {
|
|
772
|
+
export function stripLeadingRolePrefix(quote: string): string {
|
|
773
773
|
return quote.replace(/^\s*\[(?:context\s+)?(?:user|assistant)\]\s+/i, "");
|
|
774
774
|
}
|
|
775
775
|
|
|
@@ -2,6 +2,9 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import test from "node:test";
|
|
3
3
|
|
|
4
4
|
import {
|
|
5
|
+
boundRecallContextComposition,
|
|
6
|
+
composeMissingMemoryContext,
|
|
7
|
+
composeRecallContext,
|
|
5
8
|
formatCuriosityFooter,
|
|
6
9
|
renderMemoryContextPrompt,
|
|
7
10
|
selectCuriosityQuestion,
|
|
@@ -88,3 +91,66 @@ test("renderMemoryContextPrompt caps context before its footer deterministically
|
|
|
88
91
|
assert.ok(rendered);
|
|
89
92
|
assert.equal(rendered.body, "ab\n\n---\n\nfooter");
|
|
90
93
|
});
|
|
94
|
+
|
|
95
|
+
test("#2972 healthy recall carries no degradation marker", () => {
|
|
96
|
+
const composition = boundRecallContextComposition({
|
|
97
|
+
context: "A remembered deployment decision.",
|
|
98
|
+
maxChars: 512,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
assert.equal("degradation" in composition, false);
|
|
102
|
+
assert.ok(!JSON.stringify(composition).includes("degradation"));
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("#2972 budget-clipped context is marked degraded, not silently cut", () => {
|
|
106
|
+
const composition = boundRecallContextComposition({
|
|
107
|
+
context: "x".repeat(100),
|
|
108
|
+
maxChars: 20,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
assert.equal(composition.degradation?.state, "degraded");
|
|
112
|
+
assert.equal(composition.degradation?.reason, "budget-clipped");
|
|
113
|
+
assert.equal(composition.degradation?.budget?.fullChars, 100);
|
|
114
|
+
assert.ok(
|
|
115
|
+
(composition.degradation?.budget?.deliveredChars ?? 0) <
|
|
116
|
+
(composition.degradation?.budget?.fullChars ?? 0),
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("#2972 a fitting compact context is preferred over clipping the tail", () => {
|
|
121
|
+
const composition = boundRecallContextComposition({
|
|
122
|
+
context: "full-form entry one\n\nfull-form entry two",
|
|
123
|
+
compactContext: "entry one\nentry two",
|
|
124
|
+
maxChars: 30,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
assert.equal(composition.context, "entry one\nentry two");
|
|
128
|
+
assert.equal(composition.degradation?.state, "degraded");
|
|
129
|
+
assert.equal(composition.degradation?.reason, "budget-compacted");
|
|
130
|
+
assert.equal(composition.degradation?.budget?.deliveredChars, 19);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
test("#2972 a compact form that is not shallower than the full context is ignored", () => {
|
|
134
|
+
const composition = boundRecallContextComposition({
|
|
135
|
+
context: "x".repeat(50),
|
|
136
|
+
compactContext: "y".repeat(60),
|
|
137
|
+
maxChars: 10,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
assert.equal(composition.degradation?.reason, "budget-clipped");
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
test("#2972 backend failure yields an explicit missing note, never an empty string", () => {
|
|
144
|
+
const composition = composeMissingMemoryContext({ detail: "backend_unavailable" });
|
|
145
|
+
const body = composeRecallContext(composition);
|
|
146
|
+
|
|
147
|
+
assert.ok(body.length > 0);
|
|
148
|
+
assert.match(body, /memory context unavailable/i);
|
|
149
|
+
assert.equal(composition.degradation?.state, "missing");
|
|
150
|
+
assert.equal(composition.degradation?.reason, "backend-unavailable");
|
|
151
|
+
assert.equal(composition.degradation?.detail, "backend_unavailable");
|
|
152
|
+
|
|
153
|
+
const rendered = renderMemoryContextPrompt({ ...composition, maxChars: 512 });
|
|
154
|
+
assert.ok(rendered);
|
|
155
|
+
assert.match(rendered.body, /memory context unavailable/i);
|
|
156
|
+
});
|
|
@@ -35,6 +35,33 @@ const TRIM_MARKER = "\n\n...(memory context trimmed)";
|
|
|
35
35
|
export interface RecallContextComposition {
|
|
36
36
|
context: string;
|
|
37
37
|
footer?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Machine-readable degradation marker (#2972). Absent on a healthy
|
|
40
|
+
* recall so the healthy wire shape stays byte-stable. Budget warnings
|
|
41
|
+
* ride here — never inside the injected text — so the block stays
|
|
42
|
+
* cache-stable while degradation stays inspectable.
|
|
43
|
+
*/
|
|
44
|
+
degradation?: RecallContextDegradation;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type RecallDegradationState = "complete" | "degraded" | "missing";
|
|
48
|
+
|
|
49
|
+
export type RecallDegradationReason =
|
|
50
|
+
| "budget-clipped"
|
|
51
|
+
| "budget-compacted"
|
|
52
|
+
| "backend-unavailable";
|
|
53
|
+
|
|
54
|
+
export interface RecallContextDegradation {
|
|
55
|
+
state: RecallDegradationState;
|
|
56
|
+
reason: RecallDegradationReason;
|
|
57
|
+
/** Operator-facing detail (e.g. a SearchDegradation code). */
|
|
58
|
+
detail?: string;
|
|
59
|
+
/** Budget accounting, present on budget-driven degradation. */
|
|
60
|
+
budget?: {
|
|
61
|
+
contextBudget: number;
|
|
62
|
+
fullChars: number;
|
|
63
|
+
deliveredChars: number;
|
|
64
|
+
};
|
|
38
65
|
}
|
|
39
66
|
|
|
40
67
|
export interface CuriosityQuestion {
|
|
@@ -53,6 +80,14 @@ export interface RenderedMemoryContextPrompt {
|
|
|
53
80
|
|
|
54
81
|
export interface RenderMemoryContextPromptInput extends RecallContextComposition {
|
|
55
82
|
maxChars: number;
|
|
83
|
+
/**
|
|
84
|
+
* Pre-rendered shallow form of every entry (#2972). When the full
|
|
85
|
+
* context exceeds budget, a fitting compact form is delivered instead
|
|
86
|
+
* of clipping the tail — breadth-complete-but-shallow over
|
|
87
|
+
* deep-but-amputated. Ignored unless strictly shorter than the full
|
|
88
|
+
* context and within budget.
|
|
89
|
+
*/
|
|
90
|
+
compactContext?: string;
|
|
56
91
|
}
|
|
57
92
|
|
|
58
93
|
function trimText(value: string | undefined): string {
|
|
@@ -96,14 +131,77 @@ export function boundRecallContextComposition({
|
|
|
96
131
|
context: rawContext,
|
|
97
132
|
footer: rawFooter,
|
|
98
133
|
maxChars,
|
|
134
|
+
compactContext: rawCompactContext,
|
|
99
135
|
}: RenderMemoryContextPromptInput): RecallContextComposition {
|
|
100
136
|
if (!Number.isFinite(maxChars) || maxChars <= 0) return { context: "" };
|
|
101
137
|
|
|
102
138
|
const limit = Math.floor(maxChars);
|
|
103
139
|
const footer = trimText(rawFooter);
|
|
104
|
-
const
|
|
140
|
+
const contextBudget = contextBudgetForFooter(limit, footer);
|
|
141
|
+
const fullContext = trimText(rawContext);
|
|
142
|
+
let context = fullContext;
|
|
143
|
+
let degradation: RecallContextDegradation | undefined;
|
|
144
|
+
if (fullContext.length > contextBudget) {
|
|
145
|
+
const compactContext = trimText(rawCompactContext);
|
|
146
|
+
if (
|
|
147
|
+
compactContext.length > 0 &&
|
|
148
|
+
compactContext.length <= contextBudget &&
|
|
149
|
+
compactContext.length < fullContext.length
|
|
150
|
+
) {
|
|
151
|
+
context = compactContext;
|
|
152
|
+
degradation = {
|
|
153
|
+
state: "degraded",
|
|
154
|
+
reason: "budget-compacted",
|
|
155
|
+
budget: {
|
|
156
|
+
contextBudget,
|
|
157
|
+
fullChars: fullContext.length,
|
|
158
|
+
deliveredChars: compactContext.length,
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
} else {
|
|
162
|
+
context = truncateToBudget(fullContext, contextBudget);
|
|
163
|
+
degradation = {
|
|
164
|
+
state: "degraded",
|
|
165
|
+
reason: "budget-clipped",
|
|
166
|
+
budget: {
|
|
167
|
+
contextBudget,
|
|
168
|
+
fullChars: fullContext.length,
|
|
169
|
+
deliveredChars: context.length,
|
|
170
|
+
},
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// Footer truncation is fixed overhead, not lost memory content; the
|
|
175
|
+
// degradation contract covers the recall context only.
|
|
105
176
|
const boundedFooter = footer.length > limit ? truncateToBudget(footer, limit) : footer;
|
|
106
|
-
return {
|
|
177
|
+
return {
|
|
178
|
+
context,
|
|
179
|
+
...(boundedFooter ? { footer: boundedFooter } : {}),
|
|
180
|
+
...(degradation ? { degradation } : {}),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export const MEMORY_CONTEXT_UNAVAILABLE_NOTE =
|
|
185
|
+
"Memory context unavailable for this turn: recall failed. " +
|
|
186
|
+
"This means the memory backend could not be queried — it does not mean " +
|
|
187
|
+
"no relevant memories exist.";
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Missing state (#2972): a failed recall path composes this INSTEAD of an
|
|
191
|
+
* empty or silently truncated context, so "backend failed" is never
|
|
192
|
+
* indistinguishable from "no relevant memories" (the injection-side twin
|
|
193
|
+
* of Review-Prevention rule 22). Replace the bounded composition with
|
|
194
|
+
* this result on failure; do not run it back through bounding.
|
|
195
|
+
*/
|
|
196
|
+
export function composeMissingMemoryContext(input: { detail?: string } = {}): RecallContextComposition {
|
|
197
|
+
return {
|
|
198
|
+
context: MEMORY_CONTEXT_UNAVAILABLE_NOTE,
|
|
199
|
+
degradation: {
|
|
200
|
+
state: "missing",
|
|
201
|
+
reason: "backend-unavailable",
|
|
202
|
+
...(input.detail ? { detail: input.detail } : {}),
|
|
203
|
+
},
|
|
204
|
+
};
|
|
107
205
|
}
|
|
108
206
|
export function composeRecallContext(composition: RecallContextComposition): string {
|
|
109
207
|
const context = trimText(composition.context);
|
|
@@ -117,11 +215,13 @@ export function renderMemoryContextPrompt({
|
|
|
117
215
|
context: rawContext,
|
|
118
216
|
footer: rawFooter,
|
|
119
217
|
maxChars,
|
|
218
|
+
compactContext: rawCompactContext,
|
|
120
219
|
}: RenderMemoryContextPromptInput): RenderedMemoryContextPrompt | null {
|
|
121
220
|
const bounded = boundRecallContextComposition({
|
|
122
221
|
context: rawContext,
|
|
123
222
|
footer: rawFooter,
|
|
124
223
|
maxChars,
|
|
224
|
+
compactContext: rawCompactContext,
|
|
125
225
|
});
|
|
126
226
|
const body = composeRecallContext(bounded);
|
|
127
227
|
if (body.length === 0) return null;
|
|
@@ -39,6 +39,33 @@ test("peer manifest revision includes the citation-template fingerprint", () =>
|
|
|
39
39
|
assert.equal(peerManifestRevision("{{source}}"), custom);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
+
test("buildReconcileManifest stops scheduling read batches once the signal aborts (#2954)", async () => {
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
let reads = 0;
|
|
45
|
+
const stub = Buffer.from("stub");
|
|
46
|
+
// 120 files = three 50-file read batches; the abort lands inside batch 1.
|
|
47
|
+
const files = Array.from({ length: 120 }, (_, i) => ({
|
|
48
|
+
path: `facts/batch-abort-${i}.md`,
|
|
49
|
+
sha256: createHash("sha256").update(String(i)).digest("hex"),
|
|
50
|
+
}));
|
|
51
|
+
await assert.rejects(
|
|
52
|
+
buildReconcileManifest({
|
|
53
|
+
files,
|
|
54
|
+
parseMemory: parseFrontmatter,
|
|
55
|
+
signal: controller.signal,
|
|
56
|
+
readFile: async () => {
|
|
57
|
+
reads += 1;
|
|
58
|
+
if (reads === 1) controller.abort();
|
|
59
|
+
return stub;
|
|
60
|
+
},
|
|
61
|
+
}),
|
|
62
|
+
(error: unknown) => (error as Error)?.name === "AbortError"
|
|
63
|
+
);
|
|
64
|
+
// Batch 1 was already in flight when the abort landed, so exactly its 50
|
|
65
|
+
// reads ran; batches 2 and 3 must never be scheduled.
|
|
66
|
+
assert.equal(reads, 50);
|
|
67
|
+
});
|
|
68
|
+
|
|
42
69
|
test("reconcile manifest keeps file identity separate from canonical semantic identity", async () => {
|
|
43
70
|
const content = "The deployment uses a durable queue with an enrichment suffix.";
|
|
44
71
|
const semanticHash = ContentHashIndex.computeHash("The deployment uses a durable queue.");
|
|
@@ -82,6 +82,9 @@ export interface BuildReconcileManifestOptions {
|
|
|
82
82
|
parseMemory: ReconcileMemoryParser;
|
|
83
83
|
cachedFiles?: Iterable<ReconcileManifestFile>;
|
|
84
84
|
citationTemplate?: string;
|
|
85
|
+
/** Cancellation (#2954): checked between read batches so an aborted run
|
|
86
|
+
* stops scheduling new file reads instead of walking the whole corpus. */
|
|
87
|
+
signal?: AbortSignal;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
const SHA256_PATTERN = /^[a-f0-9]{64}$/i;
|
|
@@ -287,6 +290,10 @@ export async function buildReconcileManifest(options: BuildReconcileManifestOpti
|
|
|
287
290
|
}
|
|
288
291
|
}
|
|
289
292
|
for (let i = 0; i < uncached.length; i += MANIFEST_BUILD_BATCH_SIZE) {
|
|
293
|
+
// Between batches, not within one: an abort mid-batch lets the in-flight
|
|
294
|
+
// reads settle (their own fetch signal does the aborting) and stops the
|
|
295
|
+
// NEXT batch from ever being scheduled.
|
|
296
|
+
options.signal?.throwIfAborted();
|
|
290
297
|
const batch = uncached.slice(i, i + MANIFEST_BUILD_BATCH_SIZE);
|
|
291
298
|
const results = await Promise.all(
|
|
292
299
|
batch.map(({ file }) =>
|