@remnic/core 9.63.3 → 9.63.5
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 +11 -11
- package/dist/access-admin-ops-surface.js +23 -23
- package/dist/access-authorization-probe.d.ts +11 -11
- package/dist/access-authorization-probe.js +24 -24
- package/dist/access-boundary.d.ts +11 -11
- package/dist/access-boundary.js +23 -23
- package/dist/access-cli.js +55 -54
- 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 +11 -11
- package/dist/access-extraction-force-flush.js +23 -23
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +11 -11
- package/dist/access-http-lifecycle-flush.d.ts +11 -11
- package/dist/access-http-offline-stream.d.ts +11 -11
- package/dist/access-http-query.d.ts +13 -1
- package/dist/access-http-query.js +27 -24
- package/dist/access-http.d.ts +12 -12
- package/dist/access-http.js +34 -33
- package/dist/access-identity-continuity-surface.d.ts +9 -9
- package/dist/access-identity-continuity-surface.js +23 -23
- package/dist/access-lcm-surface.d.ts +11 -11
- package/dist/access-lcm-surface.js +23 -23
- package/dist/access-mcp.d.ts +11 -11
- package/dist/access-mcp.js +28 -28
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-yO4LMGFH.d.ts → access-namespace-preflight-DB0zXFek.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +23 -23
- package/dist/access-observe-write-surface.d.ts +11 -11
- package/dist/access-observe-write-surface.js +23 -23
- package/dist/access-offline-manifest.d.ts +9 -9
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +24 -24
- package/dist/access-operations.d.ts +14 -14
- package/dist/access-operations.js +27 -27
- package/dist/access-recall-concurrency.d.ts +11 -11
- package/dist/access-recall-concurrency.js +23 -23
- package/dist/access-recall-response.d.ts +11 -11
- package/dist/access-recall-response.js +23 -23
- package/dist/access-recall-surface.d.ts +11 -11
- package/dist/access-recall-surface.js +23 -23
- package/dist/access-schema.d.ts +88 -88
- package/dist/{access-service-M4LgO141.d.ts → access-service-cKQrte9Z.d.ts} +71 -77
- package/dist/access-service-helpers.d.ts +11 -11
- package/dist/access-service.d.ts +11 -11
- package/dist/access-service.js +23 -23
- package/dist/access-surface-catalog.d.ts +11 -11
- package/dist/access-surface-catalog.js +25 -25
- package/dist/access-wearables-meetings-surface.d.ts +3 -3
- 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/ambient-provenance.d.ts +1 -1
- package/dist/artifact-search.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 +9 -9
- package/dist/briefing-window.d.ts +2 -2
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +11 -11
- 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 +4 -4
- 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/{capsule-merge-HCJJMLPS.js → capsule-merge-SGIVB3WA.js} +5 -5
- package/dist/{catalog-CyYTf_ok.d.ts → catalog-CCzmf8IH.d.ts} +3 -11
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +12 -12
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-XFCQIQQU.js → chunk-2UM6WHME.js} +3 -3
- package/dist/{chunk-6F2UMP4H.js → chunk-3Z5TGRFA.js} +8 -8
- package/dist/{chunk-JJX5XEIG.js → chunk-77QZW2D6.js} +4 -4
- package/dist/{chunk-X4MGNVOO.js → chunk-7AF243WZ.js} +1 -1
- package/dist/{chunk-2ASAS3CQ.js → chunk-7KQB4EBS.js} +2 -2
- package/dist/{chunk-3LJ2L3T3.js → chunk-7LF2OHIJ.js} +2 -2
- package/dist/{chunk-VAMQU4W7.js → chunk-AYVCKGA6.js} +2 -2
- package/dist/{chunk-GTRGH4ZT.js → chunk-BB2LH5JM.js} +2 -2
- package/dist/{chunk-XMMESCPD.js → chunk-C64XATK7.js} +17 -27
- package/dist/chunk-C64XATK7.js.map +1 -0
- package/dist/{chunk-6UZR7KEK.js → chunk-CUDSA46O.js} +8 -2
- package/dist/chunk-CUDSA46O.js.map +1 -0
- package/dist/{chunk-PADG72LJ.js → chunk-DXDAQZ2K.js} +2 -2
- package/dist/{chunk-EJQXDKYK.js → chunk-DYZR3Z6D.js} +3 -3
- package/dist/{chunk-VN7IIQGS.js → chunk-E4KMY4KR.js} +2 -2
- package/dist/{chunk-ZQKXRKMR.js → chunk-EFKZT6AY.js} +2 -2
- package/dist/{chunk-DNRTKO2U.js → chunk-EJY3HJMT.js} +2 -2
- package/dist/{chunk-RYGJGXL6.js → chunk-ERPBRXVZ.js} +2 -2
- package/dist/{chunk-5UFQCU6M.js → chunk-F6JYBVL6.js} +27 -57
- package/dist/{chunk-5UFQCU6M.js.map → chunk-F6JYBVL6.js.map} +1 -1
- package/dist/{chunk-JWPG65LH.js → chunk-FHKXVTM5.js} +38 -39
- package/dist/chunk-FHKXVTM5.js.map +1 -0
- package/dist/{chunk-RPKJHYVE.js → chunk-FPEZ74F7.js} +2 -2
- package/dist/{chunk-Z334TJRB.js → chunk-GF7RQWXC.js} +2 -2
- package/dist/{chunk-6D7PZKCJ.js → chunk-GG4DN63W.js} +2 -2
- package/dist/{chunk-IM56VPKO.js → chunk-GTD4Q62X.js} +2 -6
- package/dist/{chunk-A73QHOZP.js → chunk-I5FLIB2J.js} +2 -2
- package/dist/{chunk-JJ7JW62R.js → chunk-IVXVLDNT.js} +12 -22
- package/dist/chunk-IVXVLDNT.js.map +1 -0
- package/dist/{chunk-NRFU5MVH.js → chunk-JOEJG4SD.js} +47 -1
- package/dist/chunk-JOEJG4SD.js.map +1 -0
- package/dist/{chunk-EJLTNPRY.js → chunk-KHCUVYCY.js} +3 -3
- package/dist/{chunk-QSIQVC32.js → chunk-KYTRF64R.js} +2 -2
- package/dist/{chunk-R74NCKEY.js → chunk-LX4TNSAE.js} +4 -4
- package/dist/{chunk-H6ZXNH5I.js → chunk-MUJ4QFUQ.js} +3 -3
- package/dist/{chunk-4NMVX5U7.js → chunk-NA56NSKL.js} +2 -2
- package/dist/{chunk-MR5HWQHS.js → chunk-NKB43PGI.js} +2 -2
- package/dist/{chunk-DLQQU4EG.js → chunk-NS5ETDYD.js} +2 -2
- package/dist/{chunk-44KHFMCM.js → chunk-OETHJBAL.js} +76 -53
- package/dist/{chunk-44KHFMCM.js.map → chunk-OETHJBAL.js.map} +1 -1
- package/dist/{chunk-KWN6NOHQ.js → chunk-PB4WVYGC.js} +2 -2
- package/dist/{chunk-Q35XGIEM.js → chunk-PBRCYYO7.js} +2 -2
- package/dist/{chunk-QYN5PXDZ.js → chunk-PMVPCZJZ.js} +4 -4
- package/dist/{chunk-AJSZ2EK6.js → chunk-QI5RDDEL.js} +3 -3
- package/dist/{chunk-I6OQCT3Y.js → chunk-QRWMS6SI.js} +2 -2
- package/dist/{chunk-ITYAXU4S.js → chunk-R6UMNP5C.js} +3 -3
- package/dist/{chunk-5W62VEFH.js → chunk-RWMSMTQP.js} +2 -2
- package/dist/{chunk-FKJVEW6O.js → chunk-SYVGVK4S.js} +2 -2
- package/dist/{chunk-TRPX6F2G.js → chunk-TSTI6A3A.js} +10 -13
- package/dist/chunk-TSTI6A3A.js.map +1 -0
- package/dist/{chunk-XZPSBGHA.js → chunk-UCLMKNHA.js} +2 -2
- package/dist/{chunk-ZMSZVISA.js → chunk-UFKPQBXH.js} +3 -3
- package/dist/{chunk-B2OOJCUX.js → chunk-UGHCZS6K.js} +2 -2
- package/dist/chunk-V3KIRICY.js +727 -0
- package/dist/chunk-V3KIRICY.js.map +1 -0
- package/dist/{chunk-6ZYQ36IB.js → chunk-VPHSMJ2E.js} +15 -2
- package/dist/chunk-VPHSMJ2E.js.map +1 -0
- package/dist/{chunk-E2GYBTSP.js → chunk-VYEPACWY.js} +2 -2
- package/dist/{chunk-5W5N7XJZ.js → chunk-X7LEDA74.js} +20 -753
- package/dist/chunk-X7LEDA74.js.map +1 -0
- package/dist/{chunk-KMAP7SNQ.js → chunk-XCB6QDL6.js} +2 -2
- package/dist/{chunk-WDUG2CH3.js → chunk-YEQCMA5L.js} +2 -2
- package/dist/{chunk-LZCSOUJ7.js → chunk-YFCEBB5P.js} +2 -2
- package/dist/{chunk-IKXUG6KC.js → chunk-YXMHUBN2.js} +2 -2
- package/dist/{chunk-GFNS3BHV.js → chunk-ZUPKNWRZ.js} +3 -3
- package/dist/{chunk-GSTIBXBW.js → chunk-ZVPVTPGI.js} +2 -2
- package/dist/{cli-Bw9z-KqX.d.ts → cli-BFBDYV0D.d.ts} +5 -5
- package/dist/cli.d.ts +13 -13
- package/dist/cli.js +45 -44
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +11 -11
- 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/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +11 -11
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +11 -11
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +5 -5
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +4 -4
- package/dist/contradiction/index.d.ts +2 -2
- package/dist/converge-config.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +2 -2
- package/dist/convergence-refresh.js +13 -13
- 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 +13 -13
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/dependency-propagation-config.d.ts +1 -1
- package/dist/{dependency-propagation-delivery-BxhvAppj.d.ts → dependency-propagation-delivery-DiY5T63p.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 +11 -11
- package/dist/entity-schema.d.ts +1 -1
- package/dist/episodic-context.d.ts +1 -1
- package/dist/explicit-capture.d.ts +9 -9
- package/dist/explicit-capture.js +5 -5
- package/dist/external-wiki-access.d.ts +11 -11
- package/dist/external-wiki-access.js +24 -24
- 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 +11 -11
- package/dist/extraction-error-classification.d.ts +1 -1
- package/dist/extraction-faithfulness.d.ts +1 -1
- 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-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.d.ts +1 -1
- package/dist/extraction.js +14 -14
- package/dist/fallback-llm.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-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/in-flight-reads.d.ts +1 -1
- package/dist/index.d.ts +697 -697
- package/dist/index.js +57 -56
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/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 +11 -11
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +11 -11
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +12 -12
- package/dist/{maintenance-uJb74j64.d.ts → maintenance-CaqA4z7V.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +11 -11
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-cache.js +1 -1
- package/dist/memory-corpus-version.js +2 -2
- 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-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 +12 -12
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +11 -11
- 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 +14 -14
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +20 -19
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +17 -16
- package/dist/{orchestrator-CFi-5JSR.d.ts → orchestrator-CSc9GfQv.d.ts} +8 -8
- package/dist/orchestrator.d.ts +9 -9
- package/dist/orchestrator.js +55 -54
- package/dist/page-versioning.js +4 -4
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-BdF3ferY.d.ts → pipeline-X606GdRJ.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/proactive-contention.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/{public-http-DK-QwaBu.d.ts → public-http-8PcrDIYi.d.ts} +1 -1
- package/dist/{qmd-CBSxevyb.d.ts → qmd-DCKeR-GX.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-concurrency-config.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-memory-map.d.ts +1 -1
- package/dist/recall-planner-llm.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-renderer.d.ts +1 -1
- package/dist/recall-xray.d.ts +1 -1
- package/dist/reconcile/cursor.d.ts +1 -1
- package/dist/reconcile/manifest.d.ts +1 -1
- package/dist/reconcile/manifest.js +2 -2
- 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/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 +108 -108
- package/dist/{scope-profiles-CeMv7pP0.d.ts → scope-profiles-_Y_RHCeE.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 +3 -3
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +3 -3
- 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-B-85brYj.d.ts → semantic-consolidation-DT2VSrU0.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +12 -12
- package/dist/semantic-rule-promotion.js +11 -11
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +11 -11
- package/dist/{service-CoO0HA2E.d.ts → service-BMo-gwDE.d.ts} +3 -3
- 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/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +13 -13
- package/dist/{storage-BVAVitkO.d.ts → storage-CGzJGUUu.d.ts} +49 -24
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +10 -10
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/support-passport/index.d.ts +14 -14
- package/dist/support-passport/index.js +26 -26
- 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 +5 -5
- 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-DWHOxlZP.d.ts → types-CBEAYU76.d.ts} +112 -128
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +11 -11
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/access-http-query.ts +12 -0
- package/src/access-http.test.ts +32 -0
- package/src/access-http.ts +3 -7
- package/src/admin/admin-surfaces.test.ts +5 -10
- package/src/admin/admin-surfaces.ts +0 -16
- package/src/binary-lifecycle/pipeline.test.ts +1 -1
- package/src/binary-lifecycle/pipeline.ts +23 -9
- package/src/buffer.ts +6 -0
- package/src/chat/chat-cli.test.ts +53 -0
- package/src/chat/chat-cli.ts +22 -58
- package/src/dedup/index.test.ts +65 -1
- package/src/dedup/index.ts +24 -2
- package/src/maintenance/namespace-planner.ts +0 -2
- package/src/meetings/build.test.ts +20 -4
- package/src/meetings/build.ts +2 -2
- package/src/meetings/day-source.test.ts +3 -1
- package/src/meetings/day-source.ts +1 -12
- package/src/meetings/fuse.test.ts +64 -15
- package/src/meetings/fuse.ts +18 -12
- package/src/meetings/types.ts +4 -19
- package/src/memory-cache-derived.test.ts +90 -0
- package/src/memory-cache.ts +40 -42
- package/src/namespaces/catalog.test.ts +53 -8
- package/src/namespaces/catalog.ts +5 -37
- package/src/orchestration/turn-ingestion-snapshot.test.ts +167 -0
- package/src/orchestration/turn-ingestion.ts +2 -1
- package/src/storage/content-hash-index.ts +54 -0
- package/src/storage-contract/content-hash.test.ts +59 -1
- package/src/storage-fact-hash-index-defer.test.ts +9 -9
- package/src/storage.ts +39 -40
- package/dist/chunk-5W5N7XJZ.js.map +0 -1
- package/dist/chunk-6UZR7KEK.js.map +0 -1
- package/dist/chunk-6ZYQ36IB.js.map +0 -1
- package/dist/chunk-JJ7JW62R.js.map +0 -1
- package/dist/chunk-JWPG65LH.js.map +0 -1
- package/dist/chunk-NRFU5MVH.js.map +0 -1
- package/dist/chunk-TRPX6F2G.js.map +0 -1
- package/dist/chunk-XMMESCPD.js.map +0 -1
- /package/dist/{capsule-merge-HCJJMLPS.js.map → capsule-merge-SGIVB3WA.js.map} +0 -0
- /package/dist/{chunk-XFCQIQQU.js.map → chunk-2UM6WHME.js.map} +0 -0
- /package/dist/{chunk-6F2UMP4H.js.map → chunk-3Z5TGRFA.js.map} +0 -0
- /package/dist/{chunk-JJX5XEIG.js.map → chunk-77QZW2D6.js.map} +0 -0
- /package/dist/{chunk-X4MGNVOO.js.map → chunk-7AF243WZ.js.map} +0 -0
- /package/dist/{chunk-2ASAS3CQ.js.map → chunk-7KQB4EBS.js.map} +0 -0
- /package/dist/{chunk-3LJ2L3T3.js.map → chunk-7LF2OHIJ.js.map} +0 -0
- /package/dist/{chunk-VAMQU4W7.js.map → chunk-AYVCKGA6.js.map} +0 -0
- /package/dist/{chunk-GTRGH4ZT.js.map → chunk-BB2LH5JM.js.map} +0 -0
- /package/dist/{chunk-PADG72LJ.js.map → chunk-DXDAQZ2K.js.map} +0 -0
- /package/dist/{chunk-EJQXDKYK.js.map → chunk-DYZR3Z6D.js.map} +0 -0
- /package/dist/{chunk-VN7IIQGS.js.map → chunk-E4KMY4KR.js.map} +0 -0
- /package/dist/{chunk-ZQKXRKMR.js.map → chunk-EFKZT6AY.js.map} +0 -0
- /package/dist/{chunk-DNRTKO2U.js.map → chunk-EJY3HJMT.js.map} +0 -0
- /package/dist/{chunk-RYGJGXL6.js.map → chunk-ERPBRXVZ.js.map} +0 -0
- /package/dist/{chunk-RPKJHYVE.js.map → chunk-FPEZ74F7.js.map} +0 -0
- /package/dist/{chunk-Z334TJRB.js.map → chunk-GF7RQWXC.js.map} +0 -0
- /package/dist/{chunk-6D7PZKCJ.js.map → chunk-GG4DN63W.js.map} +0 -0
- /package/dist/{chunk-IM56VPKO.js.map → chunk-GTD4Q62X.js.map} +0 -0
- /package/dist/{chunk-A73QHOZP.js.map → chunk-I5FLIB2J.js.map} +0 -0
- /package/dist/{chunk-EJLTNPRY.js.map → chunk-KHCUVYCY.js.map} +0 -0
- /package/dist/{chunk-QSIQVC32.js.map → chunk-KYTRF64R.js.map} +0 -0
- /package/dist/{chunk-R74NCKEY.js.map → chunk-LX4TNSAE.js.map} +0 -0
- /package/dist/{chunk-H6ZXNH5I.js.map → chunk-MUJ4QFUQ.js.map} +0 -0
- /package/dist/{chunk-4NMVX5U7.js.map → chunk-NA56NSKL.js.map} +0 -0
- /package/dist/{chunk-MR5HWQHS.js.map → chunk-NKB43PGI.js.map} +0 -0
- /package/dist/{chunk-DLQQU4EG.js.map → chunk-NS5ETDYD.js.map} +0 -0
- /package/dist/{chunk-KWN6NOHQ.js.map → chunk-PB4WVYGC.js.map} +0 -0
- /package/dist/{chunk-Q35XGIEM.js.map → chunk-PBRCYYO7.js.map} +0 -0
- /package/dist/{chunk-QYN5PXDZ.js.map → chunk-PMVPCZJZ.js.map} +0 -0
- /package/dist/{chunk-AJSZ2EK6.js.map → chunk-QI5RDDEL.js.map} +0 -0
- /package/dist/{chunk-I6OQCT3Y.js.map → chunk-QRWMS6SI.js.map} +0 -0
- /package/dist/{chunk-ITYAXU4S.js.map → chunk-R6UMNP5C.js.map} +0 -0
- /package/dist/{chunk-5W62VEFH.js.map → chunk-RWMSMTQP.js.map} +0 -0
- /package/dist/{chunk-FKJVEW6O.js.map → chunk-SYVGVK4S.js.map} +0 -0
- /package/dist/{chunk-XZPSBGHA.js.map → chunk-UCLMKNHA.js.map} +0 -0
- /package/dist/{chunk-ZMSZVISA.js.map → chunk-UFKPQBXH.js.map} +0 -0
- /package/dist/{chunk-B2OOJCUX.js.map → chunk-UGHCZS6K.js.map} +0 -0
- /package/dist/{chunk-E2GYBTSP.js.map → chunk-VYEPACWY.js.map} +0 -0
- /package/dist/{chunk-KMAP7SNQ.js.map → chunk-XCB6QDL6.js.map} +0 -0
- /package/dist/{chunk-WDUG2CH3.js.map → chunk-YEQCMA5L.js.map} +0 -0
- /package/dist/{chunk-LZCSOUJ7.js.map → chunk-YFCEBB5P.js.map} +0 -0
- /package/dist/{chunk-IKXUG6KC.js.map → chunk-YXMHUBN2.js.map} +0 -0
- /package/dist/{chunk-GFNS3BHV.js.map → chunk-ZUPKNWRZ.js.map} +0 -0
- /package/dist/{chunk-GSTIBXBW.js.map → chunk-ZVPVTPGI.js.map} +0 -0
package/src/meetings/fuse.ts
CHANGED
|
@@ -23,9 +23,9 @@ import type {
|
|
|
23
23
|
FusionConversationInput,
|
|
24
24
|
FusionSegmentInput,
|
|
25
25
|
} from "../wearables/fusion/types.js";
|
|
26
|
+
import type { ActivitySnapshot } from "../activity/types.js";
|
|
26
27
|
import type {
|
|
27
28
|
FusedMeeting,
|
|
28
|
-
MeetingActivitySnapshot,
|
|
29
29
|
MeetingBuildInput,
|
|
30
30
|
MeetingScreenContextEvent,
|
|
31
31
|
MeetingsConfig,
|
|
@@ -119,20 +119,22 @@ function shortenUrl(url: string): string {
|
|
|
119
119
|
return url.replace(/^[a-z]+:\/\//i, "");
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
function contextLabel(snap:
|
|
123
|
-
if (snap.
|
|
124
|
-
|
|
122
|
+
function contextLabel(snap: ActivitySnapshot): string {
|
|
123
|
+
if (snap.browserUrl !== undefined && snap.browserUrl.length > 0) {
|
|
124
|
+
return `${snap.app}: ${shortenUrl(snap.browserUrl)}`;
|
|
125
|
+
}
|
|
126
|
+
if (snap.windowTitle.length > 0) return `${snap.app}: ${snap.windowTitle}`;
|
|
125
127
|
return snap.app;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
/** True when a snapshot is the meeting app itself (captions/chat/participants),
|
|
129
131
|
* not other context. Matches the meeting's app or any configured app pattern. */
|
|
130
132
|
function isMeetingAppSnapshot(
|
|
131
|
-
snap:
|
|
133
|
+
snap: ActivitySnapshot,
|
|
132
134
|
meetingApp: string | undefined,
|
|
133
135
|
appPatterns: readonly string[],
|
|
134
136
|
): boolean {
|
|
135
|
-
const hay = `${snap.app} ${snap.
|
|
137
|
+
const hay = `${snap.app} ${snap.windowTitle} ${snap.browserUrl ?? ""}`.toLowerCase();
|
|
136
138
|
if (meetingApp !== undefined && meetingApp.length > 0 && hay.includes(meetingApp.toLowerCase())) {
|
|
137
139
|
return true;
|
|
138
140
|
}
|
|
@@ -159,21 +161,25 @@ interface ScreenContextResult {
|
|
|
159
161
|
* kept. Meeting-app snapshots never enter the timeline but feed excerpts.
|
|
160
162
|
*/
|
|
161
163
|
function buildScreenContext(
|
|
162
|
-
activity: readonly
|
|
164
|
+
activity: readonly ActivitySnapshot[],
|
|
163
165
|
windowStartMs: number,
|
|
164
166
|
windowEndMs: number,
|
|
165
167
|
meetingApp: string | undefined,
|
|
166
168
|
config: MeetingsConfig,
|
|
167
169
|
): ScreenContextResult {
|
|
168
170
|
const win = activity
|
|
169
|
-
.map((snap) => ({ snap, ms: Date.parse(snap.
|
|
171
|
+
.map((snap) => ({ snap, ms: Date.parse(snap.capturedAtUtc) }))
|
|
170
172
|
.filter((entry) => Number.isFinite(entry.ms) && entry.ms >= windowStartMs && entry.ms < windowEndMs)
|
|
171
173
|
.sort((a, b) => a.ms - b.ms || SORT_STR(a.snap.app, b.snap.app));
|
|
172
174
|
|
|
173
|
-
|
|
175
|
+
/** Run key detail: the URL when present, else the window title. */
|
|
176
|
+
const keyDetail = (snap: ActivitySnapshot): string =>
|
|
177
|
+
snap.browserUrl !== undefined && snap.browserUrl.length > 0 ? snap.browserUrl : snap.windowTitle;
|
|
178
|
+
|
|
179
|
+
const keyOf = (snap: ActivitySnapshot): string =>
|
|
174
180
|
isMeetingAppSnapshot(snap, meetingApp, config.appPatterns)
|
|
175
181
|
? MEETING_APP_KEY
|
|
176
|
-
: `${snap.app}\u0000${snap
|
|
182
|
+
: `${snap.app}\u0000${keyDetail(snap)}`;
|
|
177
183
|
|
|
178
184
|
const events: MeetingScreenContextEvent[] = [];
|
|
179
185
|
const includedText: string[] = [];
|
|
@@ -197,7 +203,7 @@ function buildScreenContext(
|
|
|
197
203
|
// Captions / chat / participant text visible on the meeting app itself.
|
|
198
204
|
for (let i = runStartIdx; i < runEndIdx; i++) {
|
|
199
205
|
const text = win[i]!.snap.text;
|
|
200
|
-
if (text
|
|
206
|
+
if (text.trim().length > 0) includedText.push(text.trim());
|
|
201
207
|
}
|
|
202
208
|
} else if (dwellSeconds >= config.contextDwellSeconds) {
|
|
203
209
|
events.push({
|
|
@@ -209,7 +215,7 @@ function buildScreenContext(
|
|
|
209
215
|
});
|
|
210
216
|
for (let i = runStartIdx; i < runEndIdx; i++) {
|
|
211
217
|
const text = win[i]!.snap.text;
|
|
212
|
-
if (text
|
|
218
|
+
if (text.trim().length > 0) includedText.push(text.trim());
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
221
|
runStartIdx = runEndIdx;
|
package/src/meetings/types.ts
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* timestamps are UTC ISO-8601; windows are half-open [startUtc, endUtc).
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
+
import type { ActivitySnapshot } from "../activity/types.js";
|
|
11
12
|
import type {
|
|
12
13
|
FusedSegment,
|
|
13
14
|
FusedSpeaker,
|
|
@@ -81,23 +82,6 @@ export interface MeetingsDetectionConfig {
|
|
|
81
82
|
mergeGapMinutes: number;
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
/**
|
|
85
|
-
* One screen-activity snapshot fed into meeting fusion (assembled from the
|
|
86
|
-
* activity store by a later wiring slice; injected directly in tests). Text is
|
|
87
|
-
* already post-redaction — meeting fusion never sees raw capture.
|
|
88
|
-
*/
|
|
89
|
-
export interface MeetingActivitySnapshot {
|
|
90
|
-
/** ISO 8601 UTC instant the snapshot was captured. */
|
|
91
|
-
tsUtc: string;
|
|
92
|
-
/** Foreground application label (e.g. "Preview", "Chrome", "Zoom"). */
|
|
93
|
-
app: string;
|
|
94
|
-
/** Window title, when known. */
|
|
95
|
-
title?: string;
|
|
96
|
-
/** Browser URL, when known. */
|
|
97
|
-
url?: string;
|
|
98
|
-
/** Extracted on-screen text excerpt, when known. */
|
|
99
|
-
text?: string;
|
|
100
|
-
}
|
|
101
85
|
|
|
102
86
|
/** One entry in a meeting's screen-context timeline (an other-app dwell). */
|
|
103
87
|
export interface MeetingScreenContextEvent {
|
|
@@ -144,8 +128,9 @@ export interface MeetingBuildInput {
|
|
|
144
128
|
* is fine (they are clipped in `fuseMeeting`).
|
|
145
129
|
*/
|
|
146
130
|
conversations: FusionConversationInput[];
|
|
147
|
-
/** Day screen-activity snapshots (filtered to the window in `fuseMeeting`).
|
|
148
|
-
|
|
131
|
+
/** Day screen-activity snapshots (filtered to the window in `fuseMeeting`).
|
|
132
|
+
* Already post-redaction — meeting fusion never sees raw capture. */
|
|
133
|
+
activity?: ActivitySnapshot[];
|
|
149
134
|
}
|
|
150
135
|
|
|
151
136
|
/** The fused, screen-aware view of a meeting produced by `fuseMeeting`. */
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #2481 — the derived cache layers (episode map, rule memories) share
|
|
3
|
+
* one getVersionedCacheEntry read gate with the hot layer. These pin the
|
|
4
|
+
* per-layer contracts that must keep holding after that dedup: version-keyed
|
|
5
|
+
* round-trip, version-mismatch miss, keyId mismatch miss, and TTL expiry
|
|
6
|
+
* miss on EACH layer. (Hot-layer equivalents live in memory-cache-hot.test.ts.)
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import assert from "node:assert/strict";
|
|
10
|
+
import test from "node:test";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
clearMemoryCache,
|
|
14
|
+
getCachedEpisodeMap,
|
|
15
|
+
getCachedRuleMemories,
|
|
16
|
+
setCachedEpisodeMap,
|
|
17
|
+
setCachedRuleMemories,
|
|
18
|
+
} from "./memory-cache.js";
|
|
19
|
+
import type { MemoryFile } from "./types.js";
|
|
20
|
+
|
|
21
|
+
function mem(path: string, id: string, category = "fact", memoryKind?: string): MemoryFile {
|
|
22
|
+
return {
|
|
23
|
+
path,
|
|
24
|
+
frontmatter: { id, category, ...(memoryKind ? { memoryKind } : {}) },
|
|
25
|
+
content: "x",
|
|
26
|
+
} as unknown as MemoryFile;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const EPISODE = mem("a.md", "ep-1", "fact", "episode");
|
|
30
|
+
|
|
31
|
+
test("episode map: matching version hits; version or keyId mismatch misses", () => {
|
|
32
|
+
const dir = "/tmp/remnic-derived-ep-ver";
|
|
33
|
+
clearMemoryCache();
|
|
34
|
+
setCachedEpisodeMap(dir, [EPISODE], 7, true, "key:1");
|
|
35
|
+
const got = getCachedEpisodeMap(dir, 7, "key:1");
|
|
36
|
+
assert.ok(got, "expected a hit at the matching version and keyId");
|
|
37
|
+
assert.deepEqual([...got.keys()], ["ep-1"]);
|
|
38
|
+
assert.equal(getCachedEpisodeMap(dir, 8, "key:1"), null, "a bumped version must miss");
|
|
39
|
+
assert.equal(getCachedEpisodeMap(dir, 7, "key:2"), null, "a mismatched keyId must miss");
|
|
40
|
+
clearMemoryCache();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("episode map: TTL expiry misses; ttl=0 disables expiry", (t) => {
|
|
44
|
+
const dir = "/tmp/remnic-derived-ep-ttl";
|
|
45
|
+
clearMemoryCache();
|
|
46
|
+
t.mock.timers.enable({ apis: ["Date"] });
|
|
47
|
+
try {
|
|
48
|
+
setCachedEpisodeMap(dir, [EPISODE], 9);
|
|
49
|
+
assert.ok(getCachedEpisodeMap(dir, 9, "", 60_000), "fresh entry within TTL hits");
|
|
50
|
+
t.mock.timers.tick(120_000);
|
|
51
|
+
assert.equal(getCachedEpisodeMap(dir, 9, "", 60_000), null, "entry older than ttl is a miss");
|
|
52
|
+
setCachedEpisodeMap(dir, [EPISODE], 9);
|
|
53
|
+
t.mock.timers.tick(600_000);
|
|
54
|
+
assert.ok(getCachedEpisodeMap(dir, 9, "", 0), "ttl=0 disables expiry");
|
|
55
|
+
} finally {
|
|
56
|
+
t.mock.timers.reset();
|
|
57
|
+
clearMemoryCache();
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("rule memories: matching version hits; version or keyId mismatch misses", () => {
|
|
62
|
+
const dir = "/tmp/remnic-derived-rule-ver";
|
|
63
|
+
clearMemoryCache();
|
|
64
|
+
setCachedRuleMemories(dir, [mem("r.md", "r-1", "rule"), mem("f.md", "f-1", "fact")], 7, true, "key:1");
|
|
65
|
+
const got = getCachedRuleMemories(dir, 7, "key:1");
|
|
66
|
+
assert.ok(got, "expected a hit at the matching version and keyId");
|
|
67
|
+
assert.deepEqual(got.all.map((m) => m.frontmatter.id), ["r-1"], "only rule-category memories in all");
|
|
68
|
+
assert.ok(got.byId.has("f-1"), "byId indexes every memory");
|
|
69
|
+
assert.equal(getCachedRuleMemories(dir, 8, "key:1"), null, "a bumped version must miss");
|
|
70
|
+
assert.equal(getCachedRuleMemories(dir, 7, "key:2"), null, "a mismatched keyId must miss");
|
|
71
|
+
clearMemoryCache();
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("rule memories: TTL expiry misses; ttl=0 disables expiry", (t) => {
|
|
75
|
+
const dir = "/tmp/remnic-derived-rule-ttl";
|
|
76
|
+
clearMemoryCache();
|
|
77
|
+
t.mock.timers.enable({ apis: ["Date"] });
|
|
78
|
+
try {
|
|
79
|
+
setCachedRuleMemories(dir, [mem("r.md", "r-1", "rule")], 9);
|
|
80
|
+
assert.ok(getCachedRuleMemories(dir, 9, "", 60_000), "fresh entry within TTL hits");
|
|
81
|
+
t.mock.timers.tick(120_000);
|
|
82
|
+
assert.equal(getCachedRuleMemories(dir, 9, "", 60_000), null, "entry older than ttl is a miss");
|
|
83
|
+
setCachedRuleMemories(dir, [mem("r.md", "r-1", "rule")], 9);
|
|
84
|
+
t.mock.timers.tick(600_000);
|
|
85
|
+
assert.ok(getCachedRuleMemories(dir, 9, "", 0), "ttl=0 disables expiry");
|
|
86
|
+
} finally {
|
|
87
|
+
t.mock.timers.reset();
|
|
88
|
+
clearMemoryCache();
|
|
89
|
+
}
|
|
90
|
+
});
|
package/src/memory-cache.ts
CHANGED
|
@@ -33,26 +33,41 @@ function sweepExpiredHotEntries(now: number): void {
|
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Shared read gate for every versioned cache layer (issue #2481): serve an
|
|
38
|
+
* entry only when its version and secure-store keyId match the caller.
|
|
39
|
+
* `currentVersion === 0` means version tracking is unavailable (tests, fresh
|
|
40
|
+
* installs) and always misses so disk is read. The TTL is a safety net for
|
|
41
|
+
* external filesystem edits that bypass the version sentinel (issue #1902):
|
|
42
|
+
* ttlMs <= 0 disables it, and on expiry the entry is evicted — not just
|
|
43
|
+
* skipped — so a stale dir releases its resident corpus instead of lingering
|
|
44
|
+
* until an explicit clear.
|
|
45
|
+
*/
|
|
46
|
+
function getVersionedCacheEntry<K, E extends { version: number; keyId: string; loadedAt: number }>(
|
|
47
|
+
cache: Map<K, E>,
|
|
48
|
+
key: K,
|
|
38
49
|
currentVersion: number,
|
|
39
|
-
keyId
|
|
40
|
-
ttlMs
|
|
41
|
-
):
|
|
42
|
-
// Don't serve from cache when version tracking is unavailable (version=0).
|
|
43
|
-
// This ensures tests and fresh installs without a version file always read disk.
|
|
50
|
+
keyId: string,
|
|
51
|
+
ttlMs: number,
|
|
52
|
+
): E | null {
|
|
44
53
|
if (currentVersion === 0) return null;
|
|
45
|
-
const entry =
|
|
54
|
+
const entry = cache.get(key);
|
|
46
55
|
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
56
|
if (ttlMs > 0 && Date.now() - entry.loadedAt > ttlMs) {
|
|
52
|
-
|
|
57
|
+
cache.delete(key);
|
|
53
58
|
return null;
|
|
54
59
|
}
|
|
55
|
-
return
|
|
60
|
+
return entry;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function getCachedMemories(
|
|
64
|
+
baseDir: string,
|
|
65
|
+
currentVersion: number,
|
|
66
|
+
keyId = "",
|
|
67
|
+
ttlMs = 0,
|
|
68
|
+
): MemoryFile[] | null {
|
|
69
|
+
const entry = getVersionedCacheEntry(hotCacheByDir, baseDir, currentVersion, keyId, ttlMs);
|
|
70
|
+
return entry ? [...entry.memories.values()] : null;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
export function setCachedMemories(
|
|
@@ -89,10 +104,10 @@ export function getCachedArchivedMemories(
|
|
|
89
104
|
currentVersion: number,
|
|
90
105
|
keyId = "",
|
|
91
106
|
): MemoryFile[] | null {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
return [...entry.memories.values()];
|
|
107
|
+
// ttlMs 0: the archive cache has no age TTL; it is version-keyed and cleared
|
|
108
|
+
// via invalidation.
|
|
109
|
+
const entry = getVersionedCacheEntry(archiveCacheByDir, baseDir, currentVersion, keyId, 0);
|
|
110
|
+
return entry ? [...entry.memories.values()] : null;
|
|
96
111
|
}
|
|
97
112
|
|
|
98
113
|
export function setCachedArchivedMemories(
|
|
@@ -165,7 +180,7 @@ export function invalidateCachedEntities(baseDir: string): void {
|
|
|
165
180
|
// These avoid O(146K) filter+map on every verified recall/rules call.
|
|
166
181
|
interface DerivedCacheEntry<T> {
|
|
167
182
|
data: T;
|
|
168
|
-
|
|
183
|
+
version: number; // matches the hot cache version it was derived from
|
|
169
184
|
keyId: string; // secure-store key identity of the corpus it was derived from (#1902)
|
|
170
185
|
loadedAt: number; // build time — bounds staleness from external edits via ttlMs (#1902)
|
|
171
186
|
}
|
|
@@ -179,17 +194,8 @@ export function getCachedEpisodeMap(
|
|
|
179
194
|
keyId = "",
|
|
180
195
|
ttlMs = 0,
|
|
181
196
|
): Map<string, MemoryFile> | null {
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
}
|
|
192
|
-
return entry.data;
|
|
197
|
+
const entry = getVersionedCacheEntry(episodeMapByDir, baseDir, currentVersion, keyId, ttlMs);
|
|
198
|
+
return entry ? entry.data : null;
|
|
193
199
|
}
|
|
194
200
|
|
|
195
201
|
/** Build and cache the episode memory map from the full memory list. */
|
|
@@ -206,7 +212,7 @@ export function setCachedEpisodeMap(
|
|
|
206
212
|
if (m.frontmatter.memoryKind !== "episode") continue;
|
|
207
213
|
map.set(m.frontmatter.id, m);
|
|
208
214
|
}
|
|
209
|
-
if (cache) episodeMapByDir.set(baseDir, { data: map,
|
|
215
|
+
if (cache) episodeMapByDir.set(baseDir, { data: map, version, keyId, loadedAt: Date.now() });
|
|
210
216
|
return map;
|
|
211
217
|
}
|
|
212
218
|
|
|
@@ -217,16 +223,8 @@ export function getCachedRuleMemories(
|
|
|
217
223
|
keyId = "",
|
|
218
224
|
ttlMs = 0,
|
|
219
225
|
): { all: MemoryFile[]; byId: Map<string, MemoryFile> } | null {
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
}
|
|
229
|
-
return entry.data;
|
|
226
|
+
const entry = getVersionedCacheEntry(ruleMemoriesByDir, baseDir, currentVersion, keyId, ttlMs);
|
|
227
|
+
return entry ? entry.data : null;
|
|
230
228
|
}
|
|
231
229
|
|
|
232
230
|
/** Build and cache the rule memories from the full memory list. */
|
|
@@ -250,7 +248,7 @@ export function setCachedRuleMemories(
|
|
|
250
248
|
}
|
|
251
249
|
}
|
|
252
250
|
const result = { all, byId };
|
|
253
|
-
if (cache) ruleMemoriesByDir.set(baseDir, { data: result,
|
|
251
|
+
if (cache) ruleMemoriesByDir.set(baseDir, { data: result, version, keyId, loadedAt: Date.now() });
|
|
254
252
|
return result;
|
|
255
253
|
}
|
|
256
254
|
|
|
@@ -600,15 +600,16 @@ test("catalog quarantines malformed JSONL record fields at the parse boundary",
|
|
|
600
600
|
|
|
601
601
|
assert.deepEqual(
|
|
602
602
|
list.map((r) => r.namespace),
|
|
603
|
-
["valid"],
|
|
604
|
-
"
|
|
603
|
+
["bad-kind", "valid"],
|
|
604
|
+
"unknown kinds coerce to explicit; other malformed records stay quarantined",
|
|
605
605
|
);
|
|
606
|
-
assert.equal(list
|
|
607
|
-
|
|
608
|
-
assert.equal(
|
|
609
|
-
assert.equal(
|
|
610
|
-
assert.equal(
|
|
611
|
-
assert.
|
|
606
|
+
assert.equal(list.find((r) => r.namespace === "bad-kind")?.kind, "explicit");
|
|
607
|
+
const valid = list.find((r) => r.namespace === "valid");
|
|
608
|
+
assert.equal(valid?.kind, "project");
|
|
609
|
+
assert.equal(valid?.discoveredBy, "write");
|
|
610
|
+
assert.equal(valid?.lastReadAt, undefined);
|
|
611
|
+
assert.equal(valid?.lastWriteAt, undefined);
|
|
612
|
+
assert.deepEqual(valid?.lastMaintenanceAt, { ok: now });
|
|
612
613
|
} finally {
|
|
613
614
|
await rm(memoryDir, { recursive: true, force: true });
|
|
614
615
|
}
|
|
@@ -3952,3 +3953,47 @@ test("#1903 cross-instance compaction never drops another instance's rows", asyn
|
|
|
3952
3953
|
await rm(memoryDir, { recursive: true, force: true });
|
|
3953
3954
|
}
|
|
3954
3955
|
});
|
|
3956
|
+
|
|
3957
|
+
test("#2469 persisted self/legacy kinds coerce to explicit and drop unused hints", async () => {
|
|
3958
|
+
const memoryDir = await mkMemoryDir();
|
|
3959
|
+
try {
|
|
3960
|
+
const ns = "project-origin-dead-kind";
|
|
3961
|
+
const token = namespaceIdentityToken(ns);
|
|
3962
|
+
const stateDir = path.join(memoryDir, "state");
|
|
3963
|
+
await mkdir(stateDir, { recursive: true });
|
|
3964
|
+
const line = JSON.stringify({
|
|
3965
|
+
namespace: ns,
|
|
3966
|
+
identityToken: token,
|
|
3967
|
+
kind: "self",
|
|
3968
|
+
principal: "unused",
|
|
3969
|
+
projectId: "unused",
|
|
3970
|
+
branch: "unused",
|
|
3971
|
+
parentNamespace: "unused",
|
|
3972
|
+
createdAt: "2026-08-17T00:00:00.000Z",
|
|
3973
|
+
storageDir: path.join(memoryDir, "namespaces", token),
|
|
3974
|
+
discoveredBy: "write",
|
|
3975
|
+
});
|
|
3976
|
+
const legacyLine = JSON.stringify({
|
|
3977
|
+
namespace: "shared",
|
|
3978
|
+
identityToken: namespaceIdentityToken("shared"),
|
|
3979
|
+
kind: "legacy",
|
|
3980
|
+
createdAt: "2026-08-17T00:00:00.000Z",
|
|
3981
|
+
storageDir: path.join(memoryDir, "namespaces", namespaceIdentityToken("shared")),
|
|
3982
|
+
discoveredBy: "config",
|
|
3983
|
+
});
|
|
3984
|
+
await writeFile(path.join(stateDir, "namespaces.jsonl"), `${line}\n${legacyLine}\n`, "utf8");
|
|
3985
|
+
|
|
3986
|
+
const catalog = new NamespaceCatalog(makeConfig(memoryDir));
|
|
3987
|
+
const selfRecord = await catalog.getNamespaceRecord(ns);
|
|
3988
|
+
assert.equal(selfRecord?.kind, "explicit");
|
|
3989
|
+
assert.equal(
|
|
3990
|
+
(selfRecord as { principal?: string } | null)?.principal,
|
|
3991
|
+
undefined,
|
|
3992
|
+
);
|
|
3993
|
+
const legacyRecord = await catalog.getNamespaceRecord("shared");
|
|
3994
|
+
assert.equal(legacyRecord?.kind, "explicit");
|
|
3995
|
+
} finally {
|
|
3996
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
3997
|
+
}
|
|
3998
|
+
});
|
|
3999
|
+
|
|
@@ -59,13 +59,11 @@ import { ALL_CATEGORY_DIRS } from "../utils/category-dir.js";
|
|
|
59
59
|
|
|
60
60
|
export type NamespaceKind =
|
|
61
61
|
| "default"
|
|
62
|
-
| "self"
|
|
63
62
|
| "shared"
|
|
64
63
|
| "project"
|
|
65
64
|
| "branch"
|
|
66
65
|
| "team-project"
|
|
67
|
-
| "explicit"
|
|
68
|
-
| "legacy";
|
|
66
|
+
| "explicit";
|
|
69
67
|
|
|
70
68
|
export type NamespaceDiscoverySource = "config" | "write" | "read" | "scan" | "migration";
|
|
71
69
|
|
|
@@ -73,10 +71,6 @@ export interface NamespaceRecord {
|
|
|
73
71
|
namespace: string;
|
|
74
72
|
identityToken: string;
|
|
75
73
|
kind: NamespaceKind;
|
|
76
|
-
principal?: string;
|
|
77
|
-
projectId?: string;
|
|
78
|
-
branch?: string;
|
|
79
|
-
parentNamespace?: string;
|
|
80
74
|
createdAt: string;
|
|
81
75
|
lastReadAt?: string;
|
|
82
76
|
lastWriteAt?: string;
|
|
@@ -95,10 +89,6 @@ export interface NamespaceCatalogFilter {
|
|
|
95
89
|
export interface NamespaceTouchMetadata {
|
|
96
90
|
discoveredBy?: NamespaceDiscoverySource;
|
|
97
91
|
kind?: NamespaceKind;
|
|
98
|
-
principal?: string;
|
|
99
|
-
projectId?: string;
|
|
100
|
-
branch?: string;
|
|
101
|
-
parentNamespace?: string;
|
|
102
92
|
/** Explicit storage dir (when the caller already resolved it). */
|
|
103
93
|
storageDir?: string;
|
|
104
94
|
/** Override the touch timestamp (mainly for tests / migration replay). */
|
|
@@ -129,13 +119,11 @@ export interface NamespaceCatalogRebuildResult {
|
|
|
129
119
|
|
|
130
120
|
const NAMESPACE_KINDS: readonly NamespaceKind[] = [
|
|
131
121
|
"default",
|
|
132
|
-
"self",
|
|
133
122
|
"shared",
|
|
134
123
|
"project",
|
|
135
124
|
"branch",
|
|
136
125
|
"team-project",
|
|
137
126
|
"explicit",
|
|
138
|
-
"legacy",
|
|
139
127
|
];
|
|
140
128
|
|
|
141
129
|
const NAMESPACE_DISCOVERY_SOURCES: readonly NamespaceDiscoverySource[] = [
|
|
@@ -275,7 +263,7 @@ function isValidIsoTimestamp(value: string): boolean {
|
|
|
275
263
|
return Number.isFinite(ms);
|
|
276
264
|
}
|
|
277
265
|
|
|
278
|
-
function isNamespaceKind(value: unknown): value is NamespaceKind {
|
|
266
|
+
export function isNamespaceKind(value: unknown): value is NamespaceKind {
|
|
279
267
|
return typeof value === "string" && (NAMESPACE_KINDS as readonly string[]).includes(value);
|
|
280
268
|
}
|
|
281
269
|
|
|
@@ -301,8 +289,7 @@ function coerceRecord(value: unknown): NamespaceRecord | null {
|
|
|
301
289
|
if (typeof v.storageDir !== "string" || v.storageDir.length === 0) return null;
|
|
302
290
|
if (typeof v.createdAt !== "string" || v.createdAt.length === 0) return null;
|
|
303
291
|
if (!isValidIsoTimestamp(v.createdAt)) return null;
|
|
304
|
-
const kind =
|
|
305
|
-
if (!kind) return null;
|
|
292
|
+
const kind = isNamespaceKind(v.kind) ? v.kind : "explicit";
|
|
306
293
|
const discoveredBy =
|
|
307
294
|
v.discoveredBy === undefined
|
|
308
295
|
? "scan"
|
|
@@ -318,10 +305,6 @@ function coerceRecord(value: unknown): NamespaceRecord | null {
|
|
|
318
305
|
storageDir: v.storageDir,
|
|
319
306
|
discoveredBy,
|
|
320
307
|
};
|
|
321
|
-
if (typeof v.principal === "string") record.principal = v.principal;
|
|
322
|
-
if (typeof v.projectId === "string") record.projectId = v.projectId;
|
|
323
|
-
if (typeof v.branch === "string") record.branch = v.branch;
|
|
324
|
-
if (typeof v.parentNamespace === "string") record.parentNamespace = v.parentNamespace;
|
|
325
308
|
if (typeof v.lastReadAt === "string" && isValidIsoTimestamp(v.lastReadAt)) {
|
|
326
309
|
record.lastReadAt = v.lastReadAt;
|
|
327
310
|
}
|
|
@@ -792,12 +775,6 @@ export class NamespaceCatalog {
|
|
|
792
775
|
if (kind === "read" && cached.lastReadAt === undefined) return true;
|
|
793
776
|
if (!metadata) return false;
|
|
794
777
|
if (metadata.kind !== undefined && metadata.kind !== cached.kind) return true;
|
|
795
|
-
if (metadata.principal !== undefined && metadata.principal !== cached.principal) return true;
|
|
796
|
-
if (metadata.projectId !== undefined && metadata.projectId !== cached.projectId) return true;
|
|
797
|
-
if (metadata.branch !== undefined && metadata.branch !== cached.branch) return true;
|
|
798
|
-
if (metadata.parentNamespace !== undefined && metadata.parentNamespace !== cached.parentNamespace) {
|
|
799
|
-
return true;
|
|
800
|
-
}
|
|
801
778
|
// A changed storageDir repoints routing/containment for this namespace —
|
|
802
779
|
// must be observable at once, not held stale by the coalesce window (#1903, Cursor).
|
|
803
780
|
if (metadata.storageDir !== undefined && metadata.storageDir !== cached.storageDir) return true;
|
|
@@ -1399,15 +1376,10 @@ export class NamespaceCatalog {
|
|
|
1399
1376
|
(kind === "register" ? "config" : kind === "maintenance" ? "scan" : kind),
|
|
1400
1377
|
};
|
|
1401
1378
|
|
|
1402
|
-
// Update mutable fields. storageDir
|
|
1403
|
-
//
|
|
1379
|
+
// Update mutable fields. storageDir and kind may change over a
|
|
1380
|
+
// namespace's lifetime, so they upsert.
|
|
1404
1381
|
record.storageDir = storageDir;
|
|
1405
1382
|
if (metadata?.kind) record.kind = metadata.kind;
|
|
1406
|
-
if (metadata?.principal !== undefined) record.principal = metadata.principal;
|
|
1407
|
-
if (metadata?.projectId !== undefined) record.projectId = metadata.projectId;
|
|
1408
|
-
if (metadata?.branch !== undefined) record.branch = metadata.branch;
|
|
1409
|
-
if (metadata?.parentNamespace !== undefined)
|
|
1410
|
-
record.parentNamespace = metadata.parentNamespace;
|
|
1411
1383
|
// PROVENANCE (creation-only, with one upgrade — round 6, codex P2 NBPmT):
|
|
1412
1384
|
// `discoveredBy` is otherwise preserved for existing records (a routine
|
|
1413
1385
|
// read/register/resolve never relabels it). The single exception is a real
|
|
@@ -2109,10 +2081,6 @@ export class NamespaceCatalog {
|
|
|
2109
2081
|
if (prior.lastReadAt) merged.lastReadAt = prior.lastReadAt;
|
|
2110
2082
|
if (prior.lastWriteAt) merged.lastWriteAt = prior.lastWriteAt;
|
|
2111
2083
|
if (prior.lastMaintenanceAt) merged.lastMaintenanceAt = { ...prior.lastMaintenanceAt };
|
|
2112
|
-
if (prior.principal !== undefined) merged.principal = prior.principal;
|
|
2113
|
-
if (prior.projectId !== undefined) merged.projectId = prior.projectId;
|
|
2114
|
-
if (prior.branch !== undefined) merged.branch = prior.branch;
|
|
2115
|
-
if (prior.parentNamespace !== undefined) merged.parentNamespace = prior.parentNamespace;
|
|
2116
2084
|
return merged;
|
|
2117
2085
|
}
|
|
2118
2086
|
// ── Persistence ──────────────────────────────────────────────────────────
|