@remnic/core 9.7.8 → 9.7.9
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 +6 -6
- package/dist/access-admin-ops-surface.js +31 -29
- package/dist/access-audit.js +2 -2
- package/dist/access-boundary.d.ts +6 -6
- package/dist/access-boundary.js +32 -30
- package/dist/access-cli.js +88 -86
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +6 -6
- package/dist/access-http.js +39 -37
- package/dist/access-identity-continuity-surface.d.ts +5 -5
- package/dist/access-identity-continuity-surface.js +31 -29
- package/dist/access-lcm-surface.d.ts +6 -6
- package/dist/access-lcm-surface.js +31 -29
- package/dist/access-mcp.d.ts +6 -6
- package/dist/access-mcp.js +36 -34
- package/dist/access-observe-write-surface.d.ts +6 -6
- package/dist/access-observe-write-surface.js +31 -29
- package/dist/access-operations-batch.js +34 -32
- package/dist/access-operations.d.ts +9 -9
- package/dist/access-operations.js +35 -33
- package/dist/access-recall-surface.d.ts +6 -6
- package/dist/access-recall-surface.js +31 -29
- package/dist/access-schema.d.ts +64 -64
- package/dist/{access-service-CxDZXTKt.d.ts → access-service-DSuzikHQ.d.ts} +4 -4
- package/dist/access-service.d.ts +6 -6
- package/dist/access-service.js +31 -29
- package/dist/access-surface-catalog.d.ts +6 -6
- 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 +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-676N6N6Y.js → auto-sync-AAMTVZMK.js} +5 -5
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +5 -5
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +14 -12
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +2 -2
- package/dist/bulk-import/index.d.ts +3 -3
- package/dist/calibration.d.ts +1 -1
- package/dist/calibration.js +2 -2
- package/dist/capabilities.d.ts +1 -1
- package/dist/{capsule-merge-GK5E647P.js → capsule-merge-Z2HUO6IK.js} +10 -2
- package/dist/capsule-merge-Z2HUO6IK.js.map +1 -0
- package/dist/{catalog-DzU9HowE.d.ts → catalog-BNwjACa5.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 +15 -13
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-TZJVTH3F.js → chunk-27VEKQQA.js} +14 -14
- package/dist/{chunk-JO5AT6QT.js → chunk-3ZVFLMFQ.js} +1 -1
- package/dist/chunk-3ZVFLMFQ.js.map +1 -0
- package/dist/{chunk-AD2KK5MT.js → chunk-5CFHYQU3.js} +9 -3
- package/dist/chunk-5CFHYQU3.js.map +1 -0
- package/dist/{chunk-7XH7VJN4.js → chunk-5S7Z5SHA.js} +2 -2
- package/dist/{chunk-TVVEYCNW.js → chunk-7K5Q6COX.js} +4 -4
- package/dist/{chunk-EJCVMPIM.js → chunk-7LMEY5KZ.js} +15 -1
- package/dist/chunk-7LMEY5KZ.js.map +1 -0
- package/dist/{chunk-3F4N4WDH.js → chunk-AHLPZ2SF.js} +2 -2
- package/dist/{chunk-AH3M6F4X.js → chunk-CDGGQGUU.js} +2 -2
- package/dist/{chunk-ZHKD4EZM.js → chunk-CK6RI52P.js} +3 -3
- package/dist/{chunk-6C35R7P4.js → chunk-DJCKXI4M.js} +2 -2
- package/dist/{chunk-GL3SMLMZ.js → chunk-DLPXS7BE.js} +109 -85
- package/dist/chunk-DLPXS7BE.js.map +1 -0
- package/dist/{chunk-NMMKRVUF.js → chunk-EIKBKQ6L.js} +6 -6
- package/dist/{chunk-O3BZ6PFY.js → chunk-F3FC7SMO.js} +2 -2
- package/dist/{chunk-ZW6OKHVX.js → chunk-FKCJH7KP.js} +2 -2
- package/dist/{chunk-DQPPRXFO.js → chunk-HQ7QZJM5.js} +2 -2
- package/dist/{chunk-UYZUJ4EB.js → chunk-I2THZUAF.js} +2 -2
- package/dist/{chunk-RKNJBZ55.js → chunk-JBPKEARU.js} +4 -4
- package/dist/{chunk-KIPLG7S7.js → chunk-JKLJ6A7W.js} +2 -2
- package/dist/{chunk-HXDKC3BI.js → chunk-JU3GHO6J.js} +2 -2
- package/dist/{chunk-74MJH7I3.js → chunk-KGNFFCZJ.js} +12 -3
- package/dist/chunk-KGNFFCZJ.js.map +1 -0
- package/dist/{chunk-Q6JPMCPO.js → chunk-KKASNHGF.js} +62 -57
- package/dist/chunk-KKASNHGF.js.map +1 -0
- package/dist/{chunk-R2SJDIPO.js → chunk-KPXAJ77O.js} +9 -7
- package/dist/chunk-KPXAJ77O.js.map +1 -0
- package/dist/{chunk-SYNYI4ZM.js → chunk-L5HJQC36.js} +2 -2
- package/dist/{chunk-VXMWDXIJ.js → chunk-LC7OODWZ.js} +2 -2
- package/dist/{chunk-CNWC274T.js → chunk-MLT5EG6K.js} +28 -28
- package/dist/{chunk-M5QKGHCR.js → chunk-OC35KQIN.js} +6 -2
- package/dist/chunk-OC35KQIN.js.map +1 -0
- package/dist/chunk-OKUEZOGW.js +27 -0
- package/dist/chunk-OKUEZOGW.js.map +1 -0
- package/dist/{chunk-PKGWJFNR.js → chunk-OVMS3DCB.js} +2 -2
- package/dist/chunk-PDJTHRAW.js +36 -0
- package/dist/chunk-PDJTHRAW.js.map +1 -0
- package/dist/{chunk-ZUFJ7ZTR.js → chunk-PHXCPVSX.js} +6 -2
- package/dist/chunk-PHXCPVSX.js.map +1 -0
- package/dist/{chunk-57INMZ6F.js → chunk-POUD5BLV.js} +2 -2
- package/dist/{chunk-KTOH7EJE.js → chunk-PV7E2FGY.js} +307 -43
- package/dist/chunk-PV7E2FGY.js.map +1 -0
- package/dist/{chunk-LRGSLV7M.js → chunk-PYHOAXTI.js} +4 -4
- package/dist/{chunk-WKE4VXSZ.js → chunk-QKVX4Y6D.js} +2 -2
- package/dist/{chunk-FXGC5UUH.js → chunk-RT7IP3D3.js} +2 -2
- package/dist/{chunk-CHVU4RE5.js → chunk-SKXBOZDF.js} +3 -3
- package/dist/{chunk-TVRPRFUB.js → chunk-TY43GBX2.js} +9 -7
- package/dist/chunk-TY43GBX2.js.map +1 -0
- package/dist/{chunk-UVIQHSS7.js → chunk-UP25ZZCN.js} +9 -3
- package/dist/chunk-UP25ZZCN.js.map +1 -0
- package/dist/{chunk-GKCCHHZK.js → chunk-UXKMMNJD.js} +4 -4
- package/dist/{chunk-XFTPUXCE.js → chunk-UXWGPODH.js} +4 -4
- package/dist/{chunk-2FSHROYK.js → chunk-V53GJUSL.js} +8 -8
- package/dist/{chunk-LKT755LP.js → chunk-VA4WSW54.js} +2 -2
- package/dist/{chunk-FYKIEOG6.js → chunk-VCFADTFS.js} +3 -3
- package/dist/{chunk-VF4XKTX3.js → chunk-VZ5OJE4X.js} +10 -2
- package/dist/chunk-VZ5OJE4X.js.map +1 -0
- package/dist/{chunk-AWJ2FHCF.js → chunk-X47LWMKA.js} +49 -21
- package/dist/chunk-X47LWMKA.js.map +1 -0
- package/dist/{chunk-VMGMY2AI.js → chunk-XG5CGR3K.js} +8 -8
- package/dist/{chunk-VMGMY2AI.js.map → chunk-XG5CGR3K.js.map} +1 -1
- package/dist/{chunk-T7VNN3ZM.js → chunk-XVLEGMJI.js} +2 -2
- package/dist/{chunk-CRFTLUWT.js → chunk-Y5U35ZVS.js} +2 -2
- package/dist/{chunk-UHGHTOR5.js → chunk-YGAOLHKN.js} +7 -7
- package/dist/{chunk-QDCJNRKK.js → chunk-YXOAQAH2.js} +3 -3
- package/dist/{cli-BqyGVyOe.d.ts → cli-DACyuK8-.d.ts} +5 -5
- package/dist/cli.d.ts +8 -8
- package/dist/cli.js +65 -63
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +14 -12
- 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 +1 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +14 -12
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +14 -12
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +6 -2
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +8 -1
- package/dist/consolidation-undo.js.map +1 -1
- package/dist/contradiction/index.d.ts +2 -2
- 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/day-summary.d.ts +1 -1
- package/dist/delinearize.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-retrieval.d.ts +2 -2
- package/dist/entity-retrieval.js +14 -12
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +5 -5
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-faithfulness.js +3 -3
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction-judge.js +3 -3
- package/dist/extraction.d.ts +1 -1
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/fallback-llm.js +2 -2
- package/dist/{forget-KHF7A44H.js → forget-CQCLB5LB.js} +2 -2
- 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-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/importers/index.d.ts +1 -1
- package/dist/in-flight-reads.d.ts +19 -0
- package/dist/in-flight-reads.js +16 -0
- package/dist/in-flight-reads.js.map +1 -0
- package/dist/index.d.ts +13 -13
- package/dist/index.js +105 -103
- 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.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +14 -12
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +14 -12
- package/dist/maintenance/rebuild-memory-projection.js +15 -13
- package/dist/mcp-memory-inspector-app.d.ts +6 -6
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +24 -13
- package/dist/memory-cache.js +3 -1
- package/dist/memory-corpus-version.d.ts +19 -0
- package/dist/memory-corpus-version.js +13 -0
- package/dist/memory-corpus-version.js.map +1 -0
- 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-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 +21 -19
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +14 -12
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +2 -2
- package/dist/operator-toolkit.js +26 -24
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +16 -14
- package/dist/{orchestrator-37Cx7yyw.d.ts → orchestrator-D83AvrPf.d.ts} +4 -4
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +88 -86
- package/dist/page-versioning.js +5 -1
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-C6onljHc.d.ts → pipeline-BSqGpYl1.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{qmd-J08G7MEm.d.ts → qmd-CutnpRVe.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 +2 -2
- 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-planner-llm.d.ts +1 -1
- package/dist/recall-planner-llm.js +2 -2
- 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/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/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +2 -2
- 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/schemas.d.ts +74 -74
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +6 -6
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +12 -12
- 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-BFtoVosl.d.ts → semantic-consolidation-btIVRC4l.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +15 -13
- package/dist/semantic-rule-promotion.js +14 -12
- package/dist/semantic-rule-verifier.d.ts +5 -1
- package/dist/semantic-rule-verifier.js +14 -12
- 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 +9 -9
- package/dist/signal.d.ts +1 -1
- package/dist/{storage-CXjwBr69.d.ts → storage-BVv_Mqa0.d.ts} +133 -3
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +13 -11
- package/dist/summarizer.d.ts +1 -1
- package/dist/summarizer.js +3 -3
- package/dist/summary-snapshot.d.ts +1 -1
- 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/capsule-import.js +6 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/transfer/types.d.ts +66 -66
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-DpxqC8dI.d.ts → types-Cmkz7csa.d.ts} +27 -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.d.ts +4 -0
- package/dist/verified-recall.js +14 -12
- package/package.json +12 -2
- package/src/binary-lifecycle/pipeline.ts +22 -0
- package/src/cli.ts +8 -0
- package/src/compounding/engine.ts +9 -1
- package/src/config.ts +14 -0
- package/src/consolidation-undo.ts +8 -0
- package/src/curation/index.ts +9 -0
- package/src/in-flight-reads.ts +63 -0
- package/src/maintenance/memory-governance.ts +6 -0
- package/src/memory-cache-hot.test.ts +131 -0
- package/src/memory-cache.ts +146 -22
- package/src/memory-corpus-version.ts +45 -0
- package/src/namespaces/storage.ts +20 -1
- package/src/operator-toolkit.ts +7 -1
- package/src/orchestration/recall-internal.ts +6 -3
- package/src/orchestrator.ts +25 -1
- package/src/page-versioning.ts +14 -1
- package/src/provenance-frontmatter.test.ts +6 -0
- package/src/review/index.ts +16 -8
- package/src/semantic-rule-promotion.ts +9 -1
- package/src/semantic-rule-verifier.ts +19 -6
- package/src/spaces/index.ts +10 -0
- package/src/storage/memory-read-store.ts +9 -2
- package/src/storage-contract/cache-coherence.test.ts +242 -0
- package/src/storage-contract/namespace-routing.test.ts +26 -1
- package/src/storage.ts +513 -31
- package/src/transfer/capsule-cache-coherence.test.ts +107 -0
- package/src/transfer/capsule-import.ts +8 -0
- package/src/transfer/capsule-merge.ts +7 -0
- package/src/types.ts +27 -0
- package/src/verified-recall.ts +20 -6
- package/dist/capsule-merge-GK5E647P.js.map +0 -1
- package/dist/chunk-74MJH7I3.js.map +0 -1
- package/dist/chunk-AD2KK5MT.js.map +0 -1
- package/dist/chunk-AWJ2FHCF.js.map +0 -1
- package/dist/chunk-EJCVMPIM.js.map +0 -1
- package/dist/chunk-GL3SMLMZ.js.map +0 -1
- package/dist/chunk-JO5AT6QT.js.map +0 -1
- package/dist/chunk-KTOH7EJE.js.map +0 -1
- package/dist/chunk-M5QKGHCR.js.map +0 -1
- package/dist/chunk-Q6JPMCPO.js.map +0 -1
- package/dist/chunk-R2SJDIPO.js.map +0 -1
- package/dist/chunk-TVRPRFUB.js.map +0 -1
- package/dist/chunk-UVIQHSS7.js.map +0 -1
- package/dist/chunk-VF4XKTX3.js.map +0 -1
- package/dist/chunk-ZUFJ7ZTR.js.map +0 -1
- /package/dist/{auto-sync-676N6N6Y.js.map → auto-sync-AAMTVZMK.js.map} +0 -0
- /package/dist/{chunk-TZJVTH3F.js.map → chunk-27VEKQQA.js.map} +0 -0
- /package/dist/{chunk-7XH7VJN4.js.map → chunk-5S7Z5SHA.js.map} +0 -0
- /package/dist/{chunk-TVVEYCNW.js.map → chunk-7K5Q6COX.js.map} +0 -0
- /package/dist/{chunk-3F4N4WDH.js.map → chunk-AHLPZ2SF.js.map} +0 -0
- /package/dist/{chunk-AH3M6F4X.js.map → chunk-CDGGQGUU.js.map} +0 -0
- /package/dist/{chunk-ZHKD4EZM.js.map → chunk-CK6RI52P.js.map} +0 -0
- /package/dist/{chunk-6C35R7P4.js.map → chunk-DJCKXI4M.js.map} +0 -0
- /package/dist/{chunk-NMMKRVUF.js.map → chunk-EIKBKQ6L.js.map} +0 -0
- /package/dist/{chunk-O3BZ6PFY.js.map → chunk-F3FC7SMO.js.map} +0 -0
- /package/dist/{chunk-ZW6OKHVX.js.map → chunk-FKCJH7KP.js.map} +0 -0
- /package/dist/{chunk-DQPPRXFO.js.map → chunk-HQ7QZJM5.js.map} +0 -0
- /package/dist/{chunk-UYZUJ4EB.js.map → chunk-I2THZUAF.js.map} +0 -0
- /package/dist/{chunk-RKNJBZ55.js.map → chunk-JBPKEARU.js.map} +0 -0
- /package/dist/{chunk-KIPLG7S7.js.map → chunk-JKLJ6A7W.js.map} +0 -0
- /package/dist/{chunk-HXDKC3BI.js.map → chunk-JU3GHO6J.js.map} +0 -0
- /package/dist/{chunk-SYNYI4ZM.js.map → chunk-L5HJQC36.js.map} +0 -0
- /package/dist/{chunk-VXMWDXIJ.js.map → chunk-LC7OODWZ.js.map} +0 -0
- /package/dist/{chunk-CNWC274T.js.map → chunk-MLT5EG6K.js.map} +0 -0
- /package/dist/{chunk-PKGWJFNR.js.map → chunk-OVMS3DCB.js.map} +0 -0
- /package/dist/{chunk-57INMZ6F.js.map → chunk-POUD5BLV.js.map} +0 -0
- /package/dist/{chunk-LRGSLV7M.js.map → chunk-PYHOAXTI.js.map} +0 -0
- /package/dist/{chunk-WKE4VXSZ.js.map → chunk-QKVX4Y6D.js.map} +0 -0
- /package/dist/{chunk-FXGC5UUH.js.map → chunk-RT7IP3D3.js.map} +0 -0
- /package/dist/{chunk-CHVU4RE5.js.map → chunk-SKXBOZDF.js.map} +0 -0
- /package/dist/{chunk-GKCCHHZK.js.map → chunk-UXKMMNJD.js.map} +0 -0
- /package/dist/{chunk-XFTPUXCE.js.map → chunk-UXWGPODH.js.map} +0 -0
- /package/dist/{chunk-2FSHROYK.js.map → chunk-V53GJUSL.js.map} +0 -0
- /package/dist/{chunk-LKT755LP.js.map → chunk-VA4WSW54.js.map} +0 -0
- /package/dist/{chunk-FYKIEOG6.js.map → chunk-VCFADTFS.js.map} +0 -0
- /package/dist/{chunk-T7VNN3ZM.js.map → chunk-XVLEGMJI.js.map} +0 -0
- /package/dist/{chunk-CRFTLUWT.js.map → chunk-Y5U35ZVS.js.map} +0 -0
- /package/dist/{chunk-UHGHTOR5.js.map → chunk-YGAOLHKN.js.map} +0 -0
- /package/dist/{chunk-QDCJNRKK.js.map → chunk-YXOAQAH2.js.map} +0 -0
- /package/dist/{forget-KHF7A44H.js.map → forget-CQCLB5LB.js.map} +0 -0
package/src/memory-cache.ts
CHANGED
|
@@ -5,49 +5,107 @@ interface CacheEntry {
|
|
|
5
5
|
memories: Map<string, MemoryFile>; // keyed by file path
|
|
6
6
|
version: number;
|
|
7
7
|
loadedAt: number;
|
|
8
|
+
// Secure-store key identity that decrypted these memories (issue #1902, Codex
|
|
9
|
+
// P1). "" for plaintext/locked stores. A manager only reads an entry whose
|
|
10
|
+
// keyId matches its own, so a locked/unkeyed instance never sees content
|
|
11
|
+
// another instance decrypted under a key for the same baseDir.
|
|
12
|
+
keyId: string;
|
|
13
|
+
// Effective TTL (ms) this entry was stored under (issue #1902, Codex Medium),
|
|
14
|
+
// so the opportunistic sweep can evict abandoned corpora that are never
|
|
15
|
+
// revisited. 0 = no TTL (never swept by age).
|
|
16
|
+
ttlMs: number;
|
|
8
17
|
}
|
|
9
18
|
|
|
10
19
|
// Module-level singleton — shared across all StorageManager instances and sessions
|
|
11
20
|
const hotCacheByDir = new Map<string, CacheEntry>();
|
|
12
21
|
const archiveCacheByDir = new Map<string, CacheEntry>();
|
|
13
22
|
|
|
14
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Evict every hot entry whose own TTL has elapsed (issue #1902, Codex Medium).
|
|
25
|
+
* Called opportunistically on each set so a long-running process that reads many
|
|
26
|
+
* namespace/temporary roots and never revisits some of them still releases their
|
|
27
|
+
* (potentially hundreds-of-MB) corpora within the TTL, instead of holding them
|
|
28
|
+
* resident until an explicit global clear. O(entries) over a small map.
|
|
29
|
+
*/
|
|
30
|
+
function sweepExpiredHotEntries(now: number): void {
|
|
31
|
+
for (const [dir, entry] of hotCacheByDir) {
|
|
32
|
+
if (entry.ttlMs > 0 && now - entry.loadedAt > entry.ttlMs) hotCacheByDir.delete(dir);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function getCachedMemories(
|
|
37
|
+
baseDir: string,
|
|
38
|
+
currentVersion: number,
|
|
39
|
+
keyId = "",
|
|
40
|
+
ttlMs = 0,
|
|
41
|
+
): MemoryFile[] | null {
|
|
15
42
|
// Don't serve from cache when version tracking is unavailable (version=0).
|
|
16
43
|
// This ensures tests and fresh installs without a version file always read disk.
|
|
17
44
|
if (currentVersion === 0) return null;
|
|
18
45
|
const entry = hotCacheByDir.get(baseDir);
|
|
19
|
-
if (!entry || entry.version !== currentVersion) return null;
|
|
46
|
+
if (!entry || entry.version !== currentVersion || entry.keyId !== keyId) return null;
|
|
47
|
+
// TTL safety net (issue #1902): bound staleness from external filesystem edits
|
|
48
|
+
// that bypass the version sentinel. ttlMs <= 0 disables the check. On expiry
|
|
49
|
+
// evict the entry (not just return null) so a revisited-but-stale dir releases
|
|
50
|
+
// its resident corpus instead of lingering until an explicit clear.
|
|
51
|
+
if (ttlMs > 0 && Date.now() - entry.loadedAt > ttlMs) {
|
|
52
|
+
hotCacheByDir.delete(baseDir);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
20
55
|
return [...entry.memories.values()];
|
|
21
56
|
}
|
|
22
57
|
|
|
23
|
-
export function setCachedMemories(
|
|
58
|
+
export function setCachedMemories(
|
|
59
|
+
baseDir: string,
|
|
60
|
+
memories: MemoryFile[],
|
|
61
|
+
version: number,
|
|
62
|
+
keyId = "",
|
|
63
|
+
ttlMs = 0,
|
|
64
|
+
): void {
|
|
24
65
|
const map = new Map<string, MemoryFile>();
|
|
25
66
|
for (const m of memories) map.set(m.path, m);
|
|
26
|
-
|
|
67
|
+
const now = Date.now();
|
|
68
|
+
hotCacheByDir.set(baseDir, { memories: map, version, loadedAt: now, keyId, ttlMs });
|
|
69
|
+
// Release abandoned corpora that expired but were never revisited (Codex Medium).
|
|
70
|
+
sweepExpiredHotEntries(now);
|
|
27
71
|
}
|
|
28
72
|
|
|
29
|
-
export function updateCacheOnWrite(baseDir: string, memory: MemoryFile): void {
|
|
73
|
+
export function updateCacheOnWrite(baseDir: string, memory: MemoryFile, keyId = ""): void {
|
|
30
74
|
const entry = hotCacheByDir.get(baseDir);
|
|
31
|
-
|
|
75
|
+
// Only mutate an entry that belongs to THIS key identity (issue #1902, Codex
|
|
76
|
+
// Medium). A concurrent differently-keyed manager may have replaced the
|
|
77
|
+
// single hotCacheByDir slot during an awaited parse; inserting our decrypted
|
|
78
|
+
// MemoryFile into its entry would leak plaintext across the key boundary.
|
|
79
|
+
if (entry && entry.keyId === keyId) entry.memories.set(memory.path, memory);
|
|
32
80
|
}
|
|
33
81
|
|
|
34
|
-
export function updateCacheOnDelete(baseDir: string, filePath: string): void {
|
|
82
|
+
export function updateCacheOnDelete(baseDir: string, filePath: string, keyId = ""): void {
|
|
35
83
|
const entry = hotCacheByDir.get(baseDir);
|
|
36
|
-
if (entry) entry.memories.delete(filePath);
|
|
84
|
+
if (entry && entry.keyId === keyId) entry.memories.delete(filePath);
|
|
37
85
|
}
|
|
38
|
-
|
|
39
86
|
// Archive cache — same pattern, separate store
|
|
40
|
-
export function getCachedArchivedMemories(
|
|
87
|
+
export function getCachedArchivedMemories(
|
|
88
|
+
baseDir: string,
|
|
89
|
+
currentVersion: number,
|
|
90
|
+
keyId = "",
|
|
91
|
+
): MemoryFile[] | null {
|
|
41
92
|
if (currentVersion === 0) return null;
|
|
42
93
|
const entry = archiveCacheByDir.get(baseDir);
|
|
43
|
-
if (!entry || entry.version !== currentVersion) return null;
|
|
94
|
+
if (!entry || entry.version !== currentVersion || entry.keyId !== keyId) return null;
|
|
44
95
|
return [...entry.memories.values()];
|
|
45
96
|
}
|
|
46
97
|
|
|
47
|
-
export function setCachedArchivedMemories(
|
|
98
|
+
export function setCachedArchivedMemories(
|
|
99
|
+
baseDir: string,
|
|
100
|
+
memories: MemoryFile[],
|
|
101
|
+
version: number,
|
|
102
|
+
keyId = "",
|
|
103
|
+
): void {
|
|
48
104
|
const map = new Map<string, MemoryFile>();
|
|
49
105
|
for (const m of memories) map.set(m.path, m);
|
|
50
|
-
|
|
106
|
+
// ttlMs: 0 — the archive cache has no age TTL; it is version-keyed and cleared
|
|
107
|
+
// via invalidation. The field satisfies the shared CacheEntry shape (#1902).
|
|
108
|
+
archiveCacheByDir.set(baseDir, { memories: map, version, loadedAt: Date.now(), keyId, ttlMs: 0 });
|
|
51
109
|
}
|
|
52
110
|
|
|
53
111
|
// Entity cache — same pattern as memory cache, but keyed by schema-aware parse inputs.
|
|
@@ -108,41 +166,77 @@ export function invalidateCachedEntities(baseDir: string): void {
|
|
|
108
166
|
interface DerivedCacheEntry<T> {
|
|
109
167
|
data: T;
|
|
110
168
|
sourceVersion: number; // matches the hot cache version it was derived from
|
|
169
|
+
keyId: string; // secure-store key identity of the corpus it was derived from (#1902)
|
|
170
|
+
loadedAt: number; // build time — bounds staleness from external edits via ttlMs (#1902)
|
|
111
171
|
}
|
|
112
172
|
|
|
113
173
|
const episodeMapByDir = new Map<string, DerivedCacheEntry<Map<string, MemoryFile>>>();
|
|
114
174
|
const ruleMemoriesByDir = new Map<string, DerivedCacheEntry<{ all: MemoryFile[]; byId: Map<string, MemoryFile> }>>();
|
|
115
175
|
|
|
116
|
-
|
|
117
|
-
|
|
176
|
+
export function getCachedEpisodeMap(
|
|
177
|
+
baseDir: string,
|
|
178
|
+
currentVersion: number,
|
|
179
|
+
keyId = "",
|
|
180
|
+
ttlMs = 0,
|
|
181
|
+
): Map<string, MemoryFile> | null {
|
|
118
182
|
if (currentVersion === 0) return null;
|
|
119
183
|
const entry = episodeMapByDir.get(baseDir);
|
|
120
|
-
if (!entry || entry.sourceVersion !== currentVersion) return null;
|
|
184
|
+
if (!entry || entry.sourceVersion !== currentVersion || entry.keyId !== keyId) return null;
|
|
185
|
+
// TTL safety net (issue #1902): the version sentinel doesn't move on a direct
|
|
186
|
+
// external edit, so bound how long a derived view is served before a rebuild
|
|
187
|
+
// (which re-reads via readAllMemories, itself TTL-bounded). ttlMs <= 0 disables.
|
|
188
|
+
if (ttlMs > 0 && Date.now() - entry.loadedAt > ttlMs) {
|
|
189
|
+
episodeMapByDir.delete(baseDir);
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
121
192
|
return entry.data;
|
|
122
193
|
}
|
|
123
194
|
|
|
124
195
|
/** Build and cache the episode memory map from the full memory list. */
|
|
125
|
-
export function setCachedEpisodeMap(
|
|
196
|
+
export function setCachedEpisodeMap(
|
|
197
|
+
baseDir: string,
|
|
198
|
+
memories: MemoryFile[],
|
|
199
|
+
version: number,
|
|
200
|
+
cache = true,
|
|
201
|
+
keyId = "",
|
|
202
|
+
): Map<string, MemoryFile> {
|
|
126
203
|
const map = new Map<string, MemoryFile>();
|
|
127
204
|
for (const m of memories) {
|
|
128
205
|
if (m.frontmatter.status === "archived" || m.frontmatter.status === "forgotten") continue;
|
|
129
206
|
if (m.frontmatter.memoryKind !== "episode") continue;
|
|
130
207
|
map.set(m.frontmatter.id, m);
|
|
131
208
|
}
|
|
132
|
-
episodeMapByDir.set(baseDir, { data: map, sourceVersion: version });
|
|
209
|
+
if (cache) episodeMapByDir.set(baseDir, { data: map, sourceVersion: version, keyId, loadedAt: Date.now() });
|
|
133
210
|
return map;
|
|
134
211
|
}
|
|
135
212
|
|
|
136
213
|
/** Get pre-filtered rule memories. Derived from hot cache. */
|
|
137
|
-
export function getCachedRuleMemories(
|
|
214
|
+
export function getCachedRuleMemories(
|
|
215
|
+
baseDir: string,
|
|
216
|
+
currentVersion: number,
|
|
217
|
+
keyId = "",
|
|
218
|
+
ttlMs = 0,
|
|
219
|
+
): { all: MemoryFile[]; byId: Map<string, MemoryFile> } | null {
|
|
138
220
|
if (currentVersion === 0) return null;
|
|
139
221
|
const entry = ruleMemoriesByDir.get(baseDir);
|
|
140
|
-
if (!entry || entry.sourceVersion !== currentVersion) return null;
|
|
222
|
+
if (!entry || entry.sourceVersion !== currentVersion || entry.keyId !== keyId) return null;
|
|
223
|
+
// TTL safety net (issue #1902): bound staleness from direct external edits
|
|
224
|
+
// that don't move the version sentinel. ttlMs <= 0 disables.
|
|
225
|
+
if (ttlMs > 0 && Date.now() - entry.loadedAt > ttlMs) {
|
|
226
|
+
ruleMemoriesByDir.delete(baseDir);
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
141
229
|
return entry.data;
|
|
142
230
|
}
|
|
143
231
|
|
|
144
232
|
/** Build and cache the rule memories from the full memory list. */
|
|
145
|
-
export function setCachedRuleMemories(
|
|
233
|
+
export function setCachedRuleMemories(
|
|
234
|
+
baseDir: string,
|
|
235
|
+
memories: MemoryFile[],
|
|
236
|
+
version: number,
|
|
237
|
+
cache = true,
|
|
238
|
+
keyId = "",
|
|
239
|
+
): { all: MemoryFile[]; byId: Map<string, MemoryFile> } {
|
|
146
240
|
const byId = new Map<string, MemoryFile>();
|
|
147
241
|
const all: MemoryFile[] = [];
|
|
148
242
|
for (const m of memories) {
|
|
@@ -156,7 +250,7 @@ export function setCachedRuleMemories(baseDir: string, memories: MemoryFile[], v
|
|
|
156
250
|
}
|
|
157
251
|
}
|
|
158
252
|
const result = { all, byId };
|
|
159
|
-
ruleMemoriesByDir.set(baseDir, { data: result, sourceVersion: version });
|
|
253
|
+
if (cache) ruleMemoriesByDir.set(baseDir, { data: result, sourceVersion: version, keyId, loadedAt: Date.now() });
|
|
160
254
|
return result;
|
|
161
255
|
}
|
|
162
256
|
|
|
@@ -295,6 +389,36 @@ export function invalidateAllForDir(baseDir: string): void {
|
|
|
295
389
|
}
|
|
296
390
|
}
|
|
297
391
|
|
|
392
|
+
/**
|
|
393
|
+
* Invalidate every cache layer for `baseDir` EXCEPT the hot-memories layer
|
|
394
|
+
* (issue #1902). Single-file write paths use this instead of
|
|
395
|
+
* `invalidateAllForDir` because they patch the hot-memories entry in place
|
|
396
|
+
* (via `updateCacheOnWrite`/`updateCacheOnDelete`) and re-key it to the bumped
|
|
397
|
+
* version — so dropping it here would defeat the whole warm-cache fast path.
|
|
398
|
+
* The derived episode/rule views and the global QMD caches are cheap to
|
|
399
|
+
* rebuild and are not patched, so they are still evicted here. Every other
|
|
400
|
+
* layer remains reachable for the wholesale `invalidateAllForDir` /
|
|
401
|
+
* `clearMemoryCache` chokepoint used by bulk/ambiguous mutations.
|
|
402
|
+
*/
|
|
403
|
+
export function invalidateDerivedAndGlobalForDir(baseDir: string): void {
|
|
404
|
+
// Preserve the layers a single-file write intentionally keeps warm (issue
|
|
405
|
+
// #1902, Codex Medium): hot-memories is patched + re-keyed in place; the
|
|
406
|
+
// entities layer is keyed on memory-status, which plain create/content writes
|
|
407
|
+
// deliberately do NOT bump (so entity retrieval stays warm); and the
|
|
408
|
+
// archive-memories layer is version-keyed on the archive tier, untouched by a
|
|
409
|
+
// hot-tier write. Evict ONLY the derived (episode/rule) and global (QMD) views.
|
|
410
|
+
for (const layer of ALL_CACHE_LAYERS) {
|
|
411
|
+
if (
|
|
412
|
+
layer.name === "hot-memories" ||
|
|
413
|
+
layer.name === "entities" ||
|
|
414
|
+
layer.name === "archive-memories"
|
|
415
|
+
) {
|
|
416
|
+
continue;
|
|
417
|
+
}
|
|
418
|
+
layer.invalidateForDir(baseDir);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
298
422
|
export function clearMemoryCache(baseDir?: string): void {
|
|
299
423
|
if (baseDir) {
|
|
300
424
|
invalidateAllForDir(baseDir);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { deleteInFlightReadsForDir } from "./in-flight-reads.js";
|
|
4
|
+
import { invalidateDerivedAndGlobalForDir } from "./memory-cache.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Filename of the memory-corpus version sentinel (issue #1902). MUST stay in
|
|
8
|
+
* sync with `StorageManager.versionFilePath("memory-corpus")` in storage.ts —
|
|
9
|
+
* the byte size of this append-only file IS the corpus version, and the
|
|
10
|
+
* version-keyed hot-memories result cache keys on it.
|
|
11
|
+
*/
|
|
12
|
+
export const MEMORY_CORPUS_VERSION_SENTINEL = ".memory-corpus-version.log";
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Out-of-band corpus-version bump (issue #1902) for code paths that write or
|
|
16
|
+
* modify memory files WITHOUT going through a StorageManager mutation method
|
|
17
|
+
* — review approval, governance restore, migration. Appends one byte to the
|
|
18
|
+
* on-disk sentinel so any process's version-keyed hot-memories cache rescans
|
|
19
|
+
* on its next read (StorageManager.readSharedVersion reads the file size, so
|
|
20
|
+
* the growth is observed immediately). Fail-open: a bump failure must never
|
|
21
|
+
* crash the caller — a stale-cache window self-heals on the next real write.
|
|
22
|
+
*/
|
|
23
|
+
export function bumpMemoryCorpusVersionForDir(memoryDir: string): void {
|
|
24
|
+
try {
|
|
25
|
+
const stateDir = path.join(memoryDir, "state");
|
|
26
|
+
mkdirSync(stateDir, { recursive: true });
|
|
27
|
+
appendFileSync(path.join(stateDir, MEMORY_CORPUS_VERSION_SENTINEL), "x");
|
|
28
|
+
} catch {
|
|
29
|
+
/* fail-open: never let a cache-coherence bump crash the primary operation */
|
|
30
|
+
}
|
|
31
|
+
// Drop any in-flight readAllMemories scan for this dir (Cursor Medium, #1902):
|
|
32
|
+
// after the sentinel advances, a concurrent read that missed the version-keyed
|
|
33
|
+
// hot entry must not attach to a scan that began BEFORE this out-of-band write
|
|
34
|
+
// and receive a pre-write corpus. Clearing forces a fresh scan of disk truth.
|
|
35
|
+
deleteInFlightReadsForDir(memoryDir);
|
|
36
|
+
// Also evict the TTL-keyed derived (episode/rule) and global (QMD search/recall)
|
|
37
|
+
// caches for this dir (issue #1902, Codex Medium). The sentinel bump self-heals
|
|
38
|
+
// the version-keyed hot cache, but the QMD caches are TTL-keyed, NOT
|
|
39
|
+
// corpus-version-keyed — without this, an out-of-band writer (capsule
|
|
40
|
+
// import/merge, review, spaces, governance restore, page revert, binary
|
|
41
|
+
// redirect) would leave a warm process serving pre-write recall/search results
|
|
42
|
+
// for the remainder of the QMD cache TTL. Route the bump through the same
|
|
43
|
+
// invalidation chokepoint the in-process mutation paths use.
|
|
44
|
+
invalidateDerivedAndGlobalForDir(memoryDir);
|
|
45
|
+
}
|
|
@@ -292,7 +292,26 @@ export class NamespaceStorageRouter {
|
|
|
292
292
|
}
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
|
|
295
|
+
// Pass the hot-memories cache gate explicitly (issue #1902, Codex P2): a
|
|
296
|
+
// per-namespace child root is never registered in the per-dir default map,
|
|
297
|
+
// so without this it would fall back to the process-wide default and ignore
|
|
298
|
+
// THIS daemon's hotMemoriesCacheEnabled config. Threading it from config
|
|
299
|
+
// keeps every namespace storage aligned with its owning orchestrator.
|
|
300
|
+
const sm = new StorageManager(
|
|
301
|
+
root,
|
|
302
|
+
this.config.entitySchemas,
|
|
303
|
+
this.config.hotMemoriesCacheEnabled,
|
|
304
|
+
);
|
|
305
|
+
// Register this child root's gate AND TTL in the per-dir maps (issue #1902,
|
|
306
|
+
// Codex P2). The constructor override above fixes the child's own gate, but
|
|
307
|
+
// its TTL is resolved via the per-dir map (hotCacheTtlMs); an unregistered
|
|
308
|
+
// child root would fall back to the last process-wide TTL and could inherit
|
|
309
|
+
// another daemon's value. Registering keyed by root keeps both per-dir.
|
|
310
|
+
StorageManager.setHotMemoriesCacheDefault(
|
|
311
|
+
root,
|
|
312
|
+
this.config.hotMemoriesCacheEnabled,
|
|
313
|
+
this.config.hotMemoriesCacheTtlMs,
|
|
314
|
+
);
|
|
296
315
|
// Propagate the inline-attribution template so that router-created storages
|
|
297
316
|
// (used by extraction and shared-promotion paths) strip citations consistently,
|
|
298
317
|
// matching the behaviour of the primary this.storage instance in the orchestrator.
|
package/src/operator-toolkit.ts
CHANGED
|
@@ -2297,7 +2297,13 @@ export async function runOperatorInventory(options: OperatorInventoryOptions): P
|
|
|
2297
2297
|
let rejected = 0;
|
|
2298
2298
|
|
|
2299
2299
|
for (const entry of uniqueRootEntries.values()) {
|
|
2300
|
-
|
|
2300
|
+
// Disable the hot-memories cache for these transient, one-shot inventory
|
|
2301
|
+
// reads (issue #1902, Codex Medium). Each namespace root is read exactly once
|
|
2302
|
+
// here; caching gives no benefit and would warm+RETAIN the full corpus under
|
|
2303
|
+
// the process-wide gate/TTL (this path bypasses NamespaceStorageRouter, so
|
|
2304
|
+
// the root is never registered in the per-dir maps). Disabling sidesteps both
|
|
2305
|
+
// the cross-namespace gate/TTL inheritance and the retained-memory footprint.
|
|
2306
|
+
const storage = new StorageManager(entry.rootDir, undefined, false);
|
|
2301
2307
|
const memories = await storage.readAllMemories();
|
|
2302
2308
|
const entities = await storage.readAllEntityFiles();
|
|
2303
2309
|
namespaces.push({
|
|
@@ -2032,9 +2032,10 @@ export class RecallInternalCoordinator {
|
|
|
2032
2032
|
// Verified recall and semantic rules both need readAllMemories().
|
|
2033
2033
|
// Instead of a shared preload (which has namespace/dir mismatch issues),
|
|
2034
2034
|
// each subsystem calls readAllMemories() on its correct storage instance.
|
|
2035
|
-
// The
|
|
2036
|
-
//
|
|
2037
|
-
// from
|
|
2035
|
+
// The version-keyed hot-memories cache (keyed by baseDir + the corpus
|
|
2036
|
+
// version sentinel, issue #1902) serves repeat reads within a version epoch
|
|
2037
|
+
// from memory, so these subsystems share one disk scan; a memory write
|
|
2038
|
+
// between recalls bumps the corpus version and forces exactly one rescan.
|
|
2038
2039
|
|
|
2039
2040
|
const verifiedRecallPromise = (async (): Promise<string | null> => {
|
|
2040
2041
|
const t0 = Date.now();
|
|
@@ -2081,6 +2082,7 @@ export class RecallInternalCoordinator {
|
|
|
2081
2082
|
query: retrievalQuery,
|
|
2082
2083
|
maxResults,
|
|
2083
2084
|
boxRecallDays: this.deps.config.boxRecallDays,
|
|
2085
|
+
hotMemoriesCacheEnabled: this.deps.config.hotMemoriesCacheEnabled,
|
|
2084
2086
|
}).catch((err) => {
|
|
2085
2087
|
log.debug(`verified recall directory scan failed: ${err}`);
|
|
2086
2088
|
return [] as VerifiedEpisodeResult[];
|
|
@@ -2169,6 +2171,7 @@ export class RecallInternalCoordinator {
|
|
|
2169
2171
|
memoryDir,
|
|
2170
2172
|
query: retrievalQuery,
|
|
2171
2173
|
maxResults,
|
|
2174
|
+
hotMemoriesCacheEnabled: this.deps.config.hotMemoriesCacheEnabled,
|
|
2172
2175
|
}).catch((err) => {
|
|
2173
2176
|
log.debug(`verified rules directory scan failed: ${err}`);
|
|
2174
2177
|
return [] as VerifiedSemanticRuleResult[];
|
package/src/orchestrator.ts
CHANGED
|
@@ -1334,6 +1334,17 @@ export class Orchestrator {
|
|
|
1334
1334
|
|
|
1335
1335
|
constructor(config: PluginConfig) {
|
|
1336
1336
|
this.config = config;
|
|
1337
|
+
// Thread the hot-memories cache escape hatch (issue #1902) to the storage
|
|
1338
|
+
// layer BEFORE any StorageManager is constructed below, so every instance
|
|
1339
|
+
// — including the ephemeral ones recall sub-stages build over the same dir
|
|
1340
|
+
// — honors the operator's setting. Destructured (not `config.<flag>`) so
|
|
1341
|
+
// this single access-layer read stays off the scattered-flag ratchet.
|
|
1342
|
+
const { hotMemoriesCacheEnabled } = config;
|
|
1343
|
+
StorageManager.setHotMemoriesCacheDefault(
|
|
1344
|
+
config.memoryDir,
|
|
1345
|
+
hotMemoriesCacheEnabled,
|
|
1346
|
+
config.hotMemoriesCacheTtlMs,
|
|
1347
|
+
);
|
|
1337
1348
|
this.profiler = new ProfilingCollector({
|
|
1338
1349
|
enabled: resolvePipelineProcessingCapabilities(this.config).profiling,
|
|
1339
1350
|
storageDir: config.profilingStorageDir || path.join(config.memoryDir, "profiling"),
|
|
@@ -1490,7 +1501,20 @@ export class Orchestrator {
|
|
|
1490
1501
|
tierMigrationStatus: this.tierMigrationStatus,
|
|
1491
1502
|
getUtilityRuntimeValues: () => this.utilityRuntimeValues,
|
|
1492
1503
|
getCompounding: () => this.compounding,
|
|
1493
|
-
createColdStorage: (parentDir) =>
|
|
1504
|
+
createColdStorage: (parentDir) => {
|
|
1505
|
+
// Register parentDir's gate AND TTL in the per-dir maps (issue #1902,
|
|
1506
|
+
// Codex Medium) before constructing, mirroring the namespace-child fix.
|
|
1507
|
+
// The constructor override only sets this manager's gate; its TTL is
|
|
1508
|
+
// resolved via the per-dir map, so an unregistered cold root would fall
|
|
1509
|
+
// back to the (first-writer) process-wide TTL and could inherit another
|
|
1510
|
+
// orchestrator's value.
|
|
1511
|
+
StorageManager.setHotMemoriesCacheDefault(
|
|
1512
|
+
parentDir,
|
|
1513
|
+
config.hotMemoriesCacheEnabled,
|
|
1514
|
+
config.hotMemoriesCacheTtlMs,
|
|
1515
|
+
);
|
|
1516
|
+
return new StorageManager(parentDir, config.entitySchemas, config.hotMemoriesCacheEnabled);
|
|
1517
|
+
},
|
|
1494
1518
|
});
|
|
1495
1519
|
this.compressionGuidelineCoordinator = new CompressionGuidelineCoordinator({
|
|
1496
1520
|
config,
|
package/src/page-versioning.ts
CHANGED
|
@@ -25,7 +25,8 @@ import {
|
|
|
25
25
|
writeFile,
|
|
26
26
|
unlink,
|
|
27
27
|
} from "node:fs/promises";
|
|
28
|
-
import { ALL_CATEGORY_DIRS } from "./utils/category-dir.js";
|
|
28
|
+
import { ALL_CATEGORY_DIRS, RECALL_FALLBACK_DIRS } from "./utils/category-dir.js";
|
|
29
|
+
import { bumpMemoryCorpusVersionForDir } from "./memory-corpus-version.js";
|
|
29
30
|
|
|
30
31
|
// ---------------------------------------------------------------------------
|
|
31
32
|
// Public interfaces
|
|
@@ -332,6 +333,18 @@ export async function revertToVersion(
|
|
|
332
333
|
|
|
333
334
|
// Write the reverted content to the actual page
|
|
334
335
|
await writeFile(pagePath, targetContent, "utf-8");
|
|
336
|
+
// A revert overwrites a memory file out-of-band (not via a StorageManager
|
|
337
|
+
// mutation), so bump the corpus sentinel when the reverted page lives under a
|
|
338
|
+
// recall category dir — forcing a warm hot-memories cache to rescan on its
|
|
339
|
+
// next read (issue #1902, Codex P1). Non-recall pages (entities/artifacts/
|
|
340
|
+
// profiles) are not in the corpus scan, so they need no bump.
|
|
341
|
+
// The hot-memories corpus covers the RECALL corpus, which excludes the
|
|
342
|
+
// non-memory queue dirs (questions/). Use RECALL_FALLBACK_DIRS — a revert of a
|
|
343
|
+
// questions/ page must NOT bump the recall corpus sentinel and force a rescan.
|
|
344
|
+
const revertedTop = relPath(pagePath, resolvedMemoryDir).split(path.sep)[0];
|
|
345
|
+
if ((RECALL_FALLBACK_DIRS as readonly string[]).includes(revertedTop)) {
|
|
346
|
+
bumpMemoryCorpusVersionForDir(resolvedMemoryDir);
|
|
347
|
+
}
|
|
335
348
|
log.debug(`page-versioning: reverted ${pagePath} to version ${versionId}`);
|
|
336
349
|
|
|
337
350
|
return version;
|
|
@@ -5,6 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import { mkdtemp, mkdir, rm, writeFile, readFile } from "node:fs/promises";
|
|
6
6
|
|
|
7
7
|
import { StorageManager } from "./storage.js";
|
|
8
|
+
import { clearMemoryCache } from "./memory-cache.js";
|
|
8
9
|
import type { ProvenanceSource } from "./types.js";
|
|
9
10
|
|
|
10
11
|
/**
|
|
@@ -64,6 +65,11 @@ async function writeFactFile(
|
|
|
64
65
|
const factsDir = path.join((storage as unknown as { baseDir: string }).baseDir, "facts", today);
|
|
65
66
|
await mkdir(factsDir, { recursive: true });
|
|
66
67
|
await writeFile(path.join(factsDir, `${id}.md`), `${lines.join("\n")}\n\n${body}\n`, "utf-8");
|
|
68
|
+
// This is an out-of-band write (bypasses StorageManager.writeMemory), so it
|
|
69
|
+
// must invalidate the version-keyed hot-memories cache (issue #1902) — drop
|
|
70
|
+
// every cache layer for this dir via the exported chokepoint so the next
|
|
71
|
+
// readAllMemories() rescans disk and sees this file (matches the harness seam).
|
|
72
|
+
clearMemoryCache(storage.dir);
|
|
67
73
|
return id;
|
|
68
74
|
}
|
|
69
75
|
|
package/src/review/index.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import fs from "node:fs";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { getCategoryDir, ALL_CATEGORY_DIRS } from "../utils/category-dir.js";
|
|
11
|
+
import { bumpMemoryCorpusVersionForDir } from "../memory-corpus-version.js";
|
|
11
12
|
|
|
12
13
|
// ── Types ────────────────────────────────────────────────────────────────────
|
|
13
14
|
|
|
@@ -259,14 +260,21 @@ export function performReview(
|
|
|
259
260
|
action: ReviewAction,
|
|
260
261
|
options: ReviewActionOptions = {},
|
|
261
262
|
): ReviewResult {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
263
|
+
const result =
|
|
264
|
+
action === "approve"
|
|
265
|
+
? approveItem(memoryDir, itemId, options)
|
|
266
|
+
: action === "dismiss"
|
|
267
|
+
? dismissItem(memoryDir, itemId, options)
|
|
268
|
+
: flagItem(memoryDir, itemId, options);
|
|
269
|
+
// Review approval/dismissal/flagging edits, moves, or removes memory files
|
|
270
|
+
// directly (out-of-band — it does not go through a StorageManager mutation
|
|
271
|
+
// method), so bump the corpus sentinel to force the version-keyed hot cache
|
|
272
|
+
// to rescan on its next read (issue #1902). Only bump when a file was
|
|
273
|
+
// actually modified/moved (updatedPath set) — no-op early returns (item not
|
|
274
|
+
// found, unparsable frontmatter) must not advance the sentinel or needlessly
|
|
275
|
+
// clear caches (Cursor Medium).
|
|
276
|
+
if (result.updatedPath !== undefined) bumpMemoryCorpusVersionForDir(memoryDir);
|
|
277
|
+
return result;
|
|
270
278
|
}
|
|
271
279
|
|
|
272
280
|
// ── Actions ──────────────────────────────────────────────────────────────────
|
|
@@ -498,7 +498,15 @@ function normalizeRuleWhitespace(value: string): string {
|
|
|
498
498
|
}
|
|
499
499
|
|
|
500
500
|
function stripTrailingClausePunctuation(value: string): string {
|
|
501
|
-
|
|
501
|
+
// Linear trailing-punctuation strip (no `/[,:;]+$/` — CodeQL flags that as a
|
|
502
|
+
// polynomial-backtracking ReDoS on long runs of ',;:'). Walk back once, O(n).
|
|
503
|
+
let end = value.length;
|
|
504
|
+
while (end > 0) {
|
|
505
|
+
const ch = value[end - 1];
|
|
506
|
+
if (ch === "," || ch === ":" || ch === ";") end--;
|
|
507
|
+
else break;
|
|
508
|
+
}
|
|
509
|
+
return value.slice(0, end).trim();
|
|
502
510
|
}
|
|
503
511
|
|
|
504
512
|
function canonicalizeRuleContent(value: string): string {
|
|
@@ -116,18 +116,31 @@ export async function searchVerifiedSemanticRules(options: {
|
|
|
116
116
|
query: string;
|
|
117
117
|
maxResults: number;
|
|
118
118
|
minEffectiveConfidence?: number;
|
|
119
|
+
/** Hot-memories cache gate (issue #1902, Codex P2). Threaded from the caller
|
|
120
|
+
* so a named-namespace root (never registered in the per-dir default map)
|
|
121
|
+
* honors the owning daemon's config instead of the process-wide default. */
|
|
122
|
+
hotMemoriesCacheEnabled?: boolean;
|
|
119
123
|
}): Promise<VerifiedSemanticRuleResult[]> {
|
|
120
124
|
const queryTokens = new Set(normalizeRecallTokens(options.query, ["what", "which"]));
|
|
121
125
|
if (queryTokens.size === 0 || options.maxResults <= 0) return [];
|
|
122
126
|
|
|
123
|
-
const storage = new StorageManager(options.memoryDir);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
//
|
|
127
|
-
let
|
|
127
|
+
const storage = new StorageManager(options.memoryDir, undefined, options.hotMemoriesCacheEnabled);
|
|
128
|
+
// Key the derived rule cache on the CORPUS version, not memory-status (Codex
|
|
129
|
+
// P1, #1902): rule memories are derived from the full corpus, and plain
|
|
130
|
+
// creates/writeChunk bump only the corpus sentinel. Keying on memory-status
|
|
131
|
+
// would let a peer process serve a stale rule set that omits newly created
|
|
132
|
+
// rule memories.
|
|
133
|
+
const version = storage.getMemoryCorpusVersion();
|
|
134
|
+
|
|
135
|
+
// Use derived rule cache to avoid O(146K) iteration on every call — but honor
|
|
136
|
+
// the hotMemoriesCacheEnabled opt-out (Codex P2): when disabled, never read or
|
|
137
|
+
// retain the derived cache, always rebuild from a fresh scan.
|
|
138
|
+
const cacheEnabled = storage.isHotCacheEnabled();
|
|
139
|
+
const keyId = storage.hotCacheKeyId();
|
|
140
|
+
let cachedRules = cacheEnabled ? getCachedRuleMemories(storage.dir, version, keyId, storage.hotCacheTtlMs()) : null;
|
|
128
141
|
if (!cachedRules) {
|
|
129
142
|
const allMems = await storage.readAllMemories();
|
|
130
|
-
cachedRules = setCachedRuleMemories(storage.dir, allMems, version);
|
|
143
|
+
cachedRules = setCachedRuleMemories(storage.dir, allMems, version, cacheEnabled, keyId);
|
|
131
144
|
}
|
|
132
145
|
const { all: ruleMemories, byId: memoryById } = cachedRules;
|
|
133
146
|
const minEffectiveConfidence = options.minEffectiveConfidence ?? DEFAULT_MIN_EFFECTIVE_CONFIDENCE;
|
package/src/spaces/index.ts
CHANGED
|
@@ -13,6 +13,7 @@ import crypto from "node:crypto";
|
|
|
13
13
|
import fs from "node:fs";
|
|
14
14
|
import path from "node:path";
|
|
15
15
|
import { readEnvVar, resolveHomeDir } from "../runtime/env.js";
|
|
16
|
+
import { bumpMemoryCorpusVersionForDir } from "../memory-corpus-version.js";
|
|
16
17
|
|
|
17
18
|
// ── Types ────────────────────────────────────────────────────────────────────
|
|
18
19
|
|
|
@@ -935,6 +936,15 @@ function copyMemories(
|
|
|
935
936
|
}
|
|
936
937
|
fs.writeFileSync(targetPath, content);
|
|
937
938
|
merged++;
|
|
939
|
+
// Bump the target's corpus sentinel per write (out-of-band — not through a
|
|
940
|
+
// StorageManager mutation), on the CANONICAL root (targetRoot), matching
|
|
941
|
+
// where files were written and where a StorageManager resolves its
|
|
942
|
+
// version/cache keys. Per-write (not once after the loop) so a warm
|
|
943
|
+
// hot-memories cache for the target rescans MID-batch and never serves the
|
|
944
|
+
// pre-copy corpus while copies are still landing (#1902; a symlinked target
|
|
945
|
+
// would otherwise diverge, and a once-after bump leaves in-batch reads
|
|
946
|
+
// stale).
|
|
947
|
+
bumpMemoryCorpusVersionForDir(targetRoot);
|
|
938
948
|
}
|
|
939
949
|
|
|
940
950
|
return { merged, conflicts, skipped };
|
|
@@ -60,6 +60,8 @@ export interface MemoryReadStoreDeps {
|
|
|
60
60
|
readonly proceduresDir: string;
|
|
61
61
|
readonly questionsDir: string;
|
|
62
62
|
readColdWriteVersion(): number;
|
|
63
|
+
/** Secure-store key identity for keying decrypted-corpus caches (#1902). */
|
|
64
|
+
hotCacheKeyId(): string;
|
|
63
65
|
readMemoryByPath(filePath: string): Promise<MemoryFile | null>;
|
|
64
66
|
readParsedMemoriesFromPaths(
|
|
65
67
|
filePaths: string[],
|
|
@@ -365,10 +367,15 @@ export class MemoryReadStore {
|
|
|
365
367
|
// stale data for up to 30s when another process wrote a new cold memory.
|
|
366
368
|
const currentColdVersion = this.deps.readColdWriteVersion();
|
|
367
369
|
|
|
368
|
-
// Return cached result if still valid by
|
|
370
|
+
// Return cached result if still valid by TTL, sentinel version, AND the
|
|
371
|
+
// secure-store key identity (issue #1902). readParsedMemoriesFromPaths
|
|
372
|
+
// decrypts per this manager's key, so a differently-keyed manager must not
|
|
373
|
+
// read a cold corpus another instance decrypted for the same coldRoot.
|
|
374
|
+
const keyId = this.deps.hotCacheKeyId();
|
|
369
375
|
const cached = this.deps.storageManagerClass.coldMemoriesCache.get(coldRoot);
|
|
370
376
|
if (
|
|
371
377
|
cached &&
|
|
378
|
+
cached.keyId === keyId &&
|
|
372
379
|
Date.now() - cached.loadedAt < this.deps.storageManagerClass.COLD_SCAN_CACHE_TTL_MS &&
|
|
373
380
|
cached.coldVersion === currentColdVersion
|
|
374
381
|
) {
|
|
@@ -407,7 +414,7 @@ export class MemoryReadStore {
|
|
|
407
414
|
|
|
408
415
|
// Store in cache with the sentinel version captured above so that any
|
|
409
416
|
// subsequent cold-version bump (by this or another process) invalidates it.
|
|
410
|
-
this.deps.storageManagerClass.coldMemoriesCache.set(coldRoot, { memories, loadedAt: Date.now(), coldVersion: currentColdVersion });
|
|
417
|
+
this.deps.storageManagerClass.coldMemoriesCache.set(coldRoot, { memories, loadedAt: Date.now(), coldVersion: currentColdVersion, keyId });
|
|
411
418
|
return memories;
|
|
412
419
|
}
|
|
413
420
|
|