@remnic/core 9.50.0 → 9.50.1
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 +10 -10
- package/dist/access-admin-ops-surface.js +15 -15
- package/dist/access-authorization-probe.d.ts +10 -10
- package/dist/access-authorization-probe.js +16 -16
- package/dist/access-boundary.d.ts +10 -10
- package/dist/access-boundary.js +15 -15
- package/dist/access-cli.js +39 -39
- package/dist/access-coding-context-resolution.d.ts +1 -1
- package/dist/access-extraction-force-flush.d.ts +10 -10
- package/dist/access-extraction-force-flush.js +15 -15
- package/dist/access-health-types.d.ts +1 -1
- package/dist/access-http-lcm-compaction.d.ts +10 -10
- package/dist/access-http-lifecycle-flush.d.ts +10 -10
- package/dist/access-http-offline-stream.d.ts +10 -10
- package/dist/access-http-query.js +15 -15
- package/dist/access-http.d.ts +10 -10
- package/dist/access-http.js +21 -21
- package/dist/access-identity-continuity-surface.d.ts +8 -8
- package/dist/access-identity-continuity-surface.js +15 -15
- package/dist/access-lcm-surface.d.ts +10 -10
- package/dist/access-lcm-surface.js +15 -15
- package/dist/access-mcp.d.ts +10 -10
- package/dist/access-mcp.js +19 -19
- package/dist/access-memory-search-fanout.d.ts +2 -2
- package/dist/{access-namespace-preflight-DuDU301-.d.ts → access-namespace-preflight-Dj2QolFE.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +3 -3
- package/dist/access-namespace-preflight.js +15 -15
- package/dist/access-observe-write-surface.d.ts +10 -10
- package/dist/access-observe-write-surface.js +15 -15
- package/dist/access-offline-manifest.d.ts +8 -8
- package/dist/access-operations-batch.js +16 -16
- package/dist/access-operations.d.ts +10 -10
- package/dist/access-operations.js +18 -18
- package/dist/access-recall-concurrency.d.ts +10 -10
- package/dist/access-recall-concurrency.js +15 -15
- package/dist/access-recall-response.d.ts +10 -10
- package/dist/access-recall-response.js +15 -15
- package/dist/access-recall-surface.d.ts +10 -10
- package/dist/access-recall-surface.js +15 -15
- package/dist/{access-service--_3T_v23.d.ts → access-service-DesbnTSa.d.ts} +7 -7
- package/dist/access-service-helpers.d.ts +10 -10
- package/dist/access-service.d.ts +10 -10
- package/dist/access-service.js +15 -15
- package/dist/access-surface-catalog.d.ts +10 -10
- 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 +8 -8
- package/dist/briefing.d.ts +2 -2
- package/dist/briefing.js +6 -6
- 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/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-KXTRZ23Z.js → capsule-merge-XMFBXVDP.js} +4 -4
- package/dist/{catalog-DjUmUIal.d.ts → catalog-D-G7RgXR.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 +7 -7
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-N3CXAYPJ.js → chunk-2HGUDBRJ.js} +2 -2
- package/dist/{chunk-FV7YQTN3.js → chunk-2S72LWKX.js} +2 -2
- package/dist/{chunk-NKL25FCF.js → chunk-4MBPIL4V.js} +2 -2
- package/dist/{chunk-ZN4EYMKJ.js → chunk-67QG75MJ.js} +2 -2
- package/dist/{chunk-JI62YGPI.js → chunk-6QPHF6RR.js} +2 -2
- package/dist/{chunk-4EABKPZS.js → chunk-75XOWNRS.js} +4 -4
- package/dist/{chunk-O76MWTVS.js → chunk-7BAYBYY5.js} +2 -2
- package/dist/{chunk-4JWJMRPJ.js → chunk-7PKFPLLZ.js} +2 -2
- package/dist/{chunk-24BKGKGO.js → chunk-BOFVT6P3.js} +5 -5
- package/dist/{chunk-3LD4N2TF.js → chunk-D73B6HMN.js} +67 -81
- package/dist/chunk-D73B6HMN.js.map +1 -0
- package/dist/{chunk-SHYIMIX5.js → chunk-ESG7Z255.js} +2 -2
- package/dist/{chunk-P26YHAQH.js → chunk-EWMTOVMY.js} +51 -27
- package/dist/chunk-EWMTOVMY.js.map +1 -0
- package/dist/{chunk-WPZX7MEA.js → chunk-FXX6RQYC.js} +3 -3
- package/dist/{chunk-S75UQ3T3.js → chunk-GDDGZVFI.js} +2 -2
- package/dist/{chunk-S2SJEOTM.js → chunk-GFIKG4FR.js} +2 -2
- package/dist/{chunk-7NDM2PNK.js → chunk-GZICBRWK.js} +2 -2
- package/dist/{chunk-LQKXVQZR.js → chunk-HS4M6BZM.js} +5 -5
- package/dist/{chunk-7BLWBSRL.js → chunk-IB25FBMX.js} +2 -2
- package/dist/{chunk-GKEYXXKX.js → chunk-IXXABW5A.js} +2 -2
- package/dist/{chunk-GGBSF2X7.js → chunk-JB6D7EFB.js} +2 -2
- package/dist/{chunk-T35UJI5R.js → chunk-JFNRA7YJ.js} +18 -18
- package/dist/{chunk-E633OXMH.js → chunk-JPHEOE6Z.js} +8 -8
- package/dist/{chunk-ELQCS47S.js → chunk-LOW66JRO.js} +3 -3
- package/dist/{chunk-JDCQK3C5.js → chunk-M4A44LUA.js} +2 -2
- package/dist/{chunk-RBPH3GZV.js → chunk-NZ6UDRUA.js} +26 -29
- package/dist/chunk-NZ6UDRUA.js.map +1 -0
- package/dist/{chunk-PWLB4TRK.js → chunk-OQAL6SIR.js} +2 -2
- package/dist/{chunk-6XGEBQ3R.js → chunk-P7ADRREJ.js} +3 -3
- package/dist/{chunk-EURCX6PS.js → chunk-PWN32TAG.js} +2 -2
- package/dist/{chunk-P4QOYG52.js → chunk-QN7NTKRC.js} +1 -1
- package/dist/{chunk-ZJIFYUJI.js → chunk-SV3PSA7Y.js} +2 -2
- package/dist/{chunk-7VWZ4LRW.js → chunk-T6RATUV2.js} +2 -2
- package/dist/{chunk-GSEPRIZC.js → chunk-TS4AJ2GI.js} +2 -2
- package/dist/{chunk-PWIMF7LP.js → chunk-UWIDGVQM.js} +10 -10
- package/dist/{chunk-VFS3MK5F.js → chunk-V5H6OJCR.js} +2 -2
- package/dist/{chunk-4S3ECH3U.js → chunk-VJXY5ZCT.js} +2 -2
- package/dist/{chunk-PLCHU56K.js → chunk-YQ4IQ2GA.js} +2 -2
- package/dist/{chunk-LTOAJXZB.js → chunk-Z3RHPGSY.js} +3 -3
- package/dist/{chunk-QWLW3VQH.js → chunk-ZCO5F5FW.js} +2 -2
- package/dist/{chunk-5XCN4XBU.js → chunk-ZQOCRIGA.js} +3 -3
- package/dist/{cli-BLNmNEMT.d.ts → cli-D4vvtxjY.d.ts} +5 -5
- package/dist/cli.d.ts +12 -12
- package/dist/cli.js +32 -32
- package/dist/coding/pre-action-gate.d.ts +1 -1
- package/dist/compounding/engine.d.ts +2 -2
- package/dist/compounding/engine.js +6 -6
- 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 +6 -6
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +6 -6
- package/dist/consolidation-provenance-check.d.ts +2 -2
- package/dist/consolidation-provenance-check.js +4 -4
- package/dist/consolidation-undo.d.ts +2 -2
- package/dist/consolidation-undo.js +3 -3
- 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 +8 -8
- 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 +8 -8
- 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/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 +6 -6
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +8 -8
- package/dist/explicit-capture.js +4 -4
- package/dist/external-wiki-access.d.ts +10 -10
- package/dist/external-wiki-access.js +16 -16
- 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 +10 -10
- 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 +17 -18
- package/dist/extraction.js +7 -7
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/{forget-GJ42LCBW.js → forget-UJDJHG6R.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/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 +19 -19
- package/dist/index.js +39 -39
- 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 +6 -6
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +6 -6
- package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
- package/dist/maintenance/rebuild-memory-projection.js +7 -7
- package/dist/{maintenance-DKbKZi3u.d.ts → maintenance-ClmUVpGI.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +10 -10
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-snapshot.d.ts +1 -1
- package/dist/memory-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 +7 -7
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/storage.d.ts +3 -3
- package/dist/namespaces/storage.js +6 -6
- 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 +9 -9
- package/dist/operator-doctor-replica.d.ts +1 -1
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +14 -14
- package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +11 -11
- package/dist/{orchestrator-BRwD7ceU.d.ts → orchestrator-qJ07zI8H.d.ts} +8 -12
- package/dist/orchestrator.d.ts +8 -8
- package/dist/orchestrator.js +39 -39
- package/dist/page-versioning.js +3 -3
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/{pipeline-DC-1C9T8.d.ts → pipeline-WFCxhHOn.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/{qmd-DdeCEZdb.d.ts → qmd-5tzkQ44y.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/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/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/{scope-profiles-BXVq4Jv0.d.ts → scope-profiles--vfXPl3X.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/index.d.ts +1 -1
- 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-CGYxfa8F.d.ts → semantic-consolidation-BBDuP9nJ.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +7 -7
- package/dist/semantic-rule-promotion.js +6 -6
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +6 -6
- package/dist/{service-CBDBQFCN.d.ts → service-B8DtbpCM.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/source-agent-qualifier.d.ts +1 -1
- package/dist/source-agent-qualifier.js +6 -6
- package/dist/{storage-V--MQi7w.d.ts → storage-BkYN1RIy.d.ts} +1 -1
- package/dist/storage.d.ts +2 -2
- package/dist/storage.js +5 -5
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +2 -2
- package/dist/temporal-supersession.js +1 -1
- 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 +4 -4
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-D_a6Sqjz.d.ts → types-u2s9j1uD.d.ts} +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +6 -6
- package/dist/write-envelope.d.ts +1 -1
- package/package.json +2 -2
- package/src/dependency-revalidation-routing.test.ts +165 -0
- package/src/extraction.ts +46 -31
- package/src/orchestration/dependency-propagation.test.ts +89 -8
- package/src/orchestration/dependency-propagation.ts +60 -27
- package/src/orchestration/dependency-revalidation.test.ts +119 -0
- package/src/orchestration/dependency-revalidation.ts +31 -82
- package/src/orchestrator.ts +5 -7
- package/src/testing/subjects/dependency-propagation.test.ts +367 -0
- package/dist/chunk-3LD4N2TF.js.map +0 -1
- package/dist/chunk-P26YHAQH.js.map +0 -1
- package/dist/chunk-RBPH3GZV.js.map +0 -1
- /package/dist/{capsule-merge-KXTRZ23Z.js.map → capsule-merge-XMFBXVDP.js.map} +0 -0
- /package/dist/{chunk-N3CXAYPJ.js.map → chunk-2HGUDBRJ.js.map} +0 -0
- /package/dist/{chunk-FV7YQTN3.js.map → chunk-2S72LWKX.js.map} +0 -0
- /package/dist/{chunk-NKL25FCF.js.map → chunk-4MBPIL4V.js.map} +0 -0
- /package/dist/{chunk-ZN4EYMKJ.js.map → chunk-67QG75MJ.js.map} +0 -0
- /package/dist/{chunk-JI62YGPI.js.map → chunk-6QPHF6RR.js.map} +0 -0
- /package/dist/{chunk-4EABKPZS.js.map → chunk-75XOWNRS.js.map} +0 -0
- /package/dist/{chunk-O76MWTVS.js.map → chunk-7BAYBYY5.js.map} +0 -0
- /package/dist/{chunk-4JWJMRPJ.js.map → chunk-7PKFPLLZ.js.map} +0 -0
- /package/dist/{chunk-24BKGKGO.js.map → chunk-BOFVT6P3.js.map} +0 -0
- /package/dist/{chunk-SHYIMIX5.js.map → chunk-ESG7Z255.js.map} +0 -0
- /package/dist/{chunk-WPZX7MEA.js.map → chunk-FXX6RQYC.js.map} +0 -0
- /package/dist/{chunk-S75UQ3T3.js.map → chunk-GDDGZVFI.js.map} +0 -0
- /package/dist/{chunk-S2SJEOTM.js.map → chunk-GFIKG4FR.js.map} +0 -0
- /package/dist/{chunk-7NDM2PNK.js.map → chunk-GZICBRWK.js.map} +0 -0
- /package/dist/{chunk-LQKXVQZR.js.map → chunk-HS4M6BZM.js.map} +0 -0
- /package/dist/{chunk-7BLWBSRL.js.map → chunk-IB25FBMX.js.map} +0 -0
- /package/dist/{chunk-GKEYXXKX.js.map → chunk-IXXABW5A.js.map} +0 -0
- /package/dist/{chunk-GGBSF2X7.js.map → chunk-JB6D7EFB.js.map} +0 -0
- /package/dist/{chunk-T35UJI5R.js.map → chunk-JFNRA7YJ.js.map} +0 -0
- /package/dist/{chunk-E633OXMH.js.map → chunk-JPHEOE6Z.js.map} +0 -0
- /package/dist/{chunk-ELQCS47S.js.map → chunk-LOW66JRO.js.map} +0 -0
- /package/dist/{chunk-JDCQK3C5.js.map → chunk-M4A44LUA.js.map} +0 -0
- /package/dist/{chunk-PWLB4TRK.js.map → chunk-OQAL6SIR.js.map} +0 -0
- /package/dist/{chunk-6XGEBQ3R.js.map → chunk-P7ADRREJ.js.map} +0 -0
- /package/dist/{chunk-EURCX6PS.js.map → chunk-PWN32TAG.js.map} +0 -0
- /package/dist/{chunk-P4QOYG52.js.map → chunk-QN7NTKRC.js.map} +0 -0
- /package/dist/{chunk-ZJIFYUJI.js.map → chunk-SV3PSA7Y.js.map} +0 -0
- /package/dist/{chunk-7VWZ4LRW.js.map → chunk-T6RATUV2.js.map} +0 -0
- /package/dist/{chunk-GSEPRIZC.js.map → chunk-TS4AJ2GI.js.map} +0 -0
- /package/dist/{chunk-PWIMF7LP.js.map → chunk-UWIDGVQM.js.map} +0 -0
- /package/dist/{chunk-VFS3MK5F.js.map → chunk-V5H6OJCR.js.map} +0 -0
- /package/dist/{chunk-4S3ECH3U.js.map → chunk-VJXY5ZCT.js.map} +0 -0
- /package/dist/{chunk-PLCHU56K.js.map → chunk-YQ4IQ2GA.js.map} +0 -0
- /package/dist/{chunk-LTOAJXZB.js.map → chunk-Z3RHPGSY.js.map} +0 -0
- /package/dist/{chunk-QWLW3VQH.js.map → chunk-ZCO5F5FW.js.map} +0 -0
- /package/dist/{chunk-5XCN4XBU.js.map → chunk-ZQOCRIGA.js.map} +0 -0
- /package/dist/{forget-GJ42LCBW.js.map → forget-UJDJHG6R.js.map} +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
revalidateDependentsViaLlm,
|
|
6
|
+
type RevalidationDeps,
|
|
7
|
+
} from "./dependency-revalidation.js";
|
|
8
|
+
|
|
9
|
+
type Dependent = { id: string; category: string; content: string };
|
|
10
|
+
type CompletionOptions = {
|
|
11
|
+
operation?: string;
|
|
12
|
+
priority?: "background" | "recall-critical";
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
temperature?: number;
|
|
16
|
+
maxTokens?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
type CompletionCall = {
|
|
20
|
+
messages: Array<{ role: string; content: string }>;
|
|
21
|
+
options: CompletionOptions;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const superseded = { id: "old", content: "old supporting fact" };
|
|
25
|
+
const replacement = { id: "new", content: "new supporting fact" };
|
|
26
|
+
|
|
27
|
+
function dependents(count: number): Dependent[] {
|
|
28
|
+
return Array.from({ length: count }, (_, index) => ({
|
|
29
|
+
id: `dependent-${String(index + 1).padStart(2, "0")}`,
|
|
30
|
+
category: index % 2 === 0 ? "fact" : "decision",
|
|
31
|
+
content: `dependent claim ${index + 1}`,
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function makeDeps(payload: unknown, calls: CompletionCall[]): RevalidationDeps {
|
|
36
|
+
return {
|
|
37
|
+
fastChatCompletion: async (messages, options) => {
|
|
38
|
+
calls.push({ messages, options });
|
|
39
|
+
return { content: JSON.stringify(payload) };
|
|
40
|
+
},
|
|
41
|
+
parseJsonObject: (raw) => JSON.parse(raw ?? "null") as unknown,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
test("revalidation uses only the injected fast completion seam", async () => {
|
|
46
|
+
const calls: CompletionCall[] = [];
|
|
47
|
+
const signal = new AbortController().signal;
|
|
48
|
+
const requested = dependents(1);
|
|
49
|
+
|
|
50
|
+
await revalidateDependentsViaLlm(
|
|
51
|
+
makeDeps({ verdicts: [{ memoryId: requested[0]!.id, verdict: "still_valid" }] }, calls),
|
|
52
|
+
superseded,
|
|
53
|
+
replacement,
|
|
54
|
+
requested,
|
|
55
|
+
{ signal, timeoutMs: 37 },
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const call = calls[0];
|
|
59
|
+
assert.ok(call);
|
|
60
|
+
assert.equal(call.options.operation, "dependency_revalidation");
|
|
61
|
+
assert.equal(call.options.priority, "background");
|
|
62
|
+
assert.equal(call.options.timeoutMs, 37);
|
|
63
|
+
assert.equal(call.options.signal, signal);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("revalidation normalizes one verdict per dependent for one, five, and ten dependents", async () => {
|
|
67
|
+
for (const count of [1, 5, 10]) {
|
|
68
|
+
const requested = dependents(count);
|
|
69
|
+
const calls: CompletionCall[] = [];
|
|
70
|
+
const result = await revalidateDependentsViaLlm(
|
|
71
|
+
makeDeps(
|
|
72
|
+
{
|
|
73
|
+
verdicts: [
|
|
74
|
+
...requested.map((dependent) => ({ memoryId: dependent.id, verdict: "invalidated" })),
|
|
75
|
+
{ memoryId: "unknown-id", verdict: "invalidated" },
|
|
76
|
+
{ memoryId: requested[0]!.id, verdict: "still_valid" },
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
calls,
|
|
80
|
+
),
|
|
81
|
+
superseded,
|
|
82
|
+
replacement,
|
|
83
|
+
requested,
|
|
84
|
+
{ timeoutMs: 37 },
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
assert.equal(result.verdicts.length, count);
|
|
88
|
+
assert.deepEqual(
|
|
89
|
+
result.verdicts.map((verdict) => verdict.memoryId),
|
|
90
|
+
requested.map((dependent) => dependent.id),
|
|
91
|
+
);
|
|
92
|
+
assert.equal(new Set(result.verdicts.map((verdict) => verdict.memoryId)).size, count);
|
|
93
|
+
assert.equal(calls.length, 1);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("revalidation rejects empty completion output", async () => {
|
|
98
|
+
for (const content of [null, "", " "]) {
|
|
99
|
+
const deps: RevalidationDeps = {
|
|
100
|
+
fastChatCompletion: async () => content === null ? null : { content },
|
|
101
|
+
parseJsonObject: (raw) => JSON.parse(raw ?? "null") as unknown,
|
|
102
|
+
};
|
|
103
|
+
await assert.rejects(
|
|
104
|
+
revalidateDependentsViaLlm(deps, superseded, replacement, dependents(1)),
|
|
105
|
+
/no dependency revalidation output/,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("revalidation defaults invalid verdict enums to uncertain", async () => {
|
|
111
|
+
const requested = dependents(1);
|
|
112
|
+
const result = await revalidateDependentsViaLlm(
|
|
113
|
+
makeDeps({ verdicts: [{ memoryId: requested[0]!.id, verdict: "approved" }] }, []),
|
|
114
|
+
superseded,
|
|
115
|
+
replacement,
|
|
116
|
+
requested,
|
|
117
|
+
);
|
|
118
|
+
assert.deepEqual(result.verdicts, [{ memoryId: requested[0]!.id, verdict: "uncertain" }]);
|
|
119
|
+
});
|
|
@@ -4,8 +4,6 @@
|
|
|
4
4
|
* Extracted from ExtractionEngine to keep extraction.ts under its ratchet
|
|
5
5
|
* ceiling. The ExtractionEngine.revalidateDependents method delegates here.
|
|
6
6
|
*/
|
|
7
|
-
import type { LocalLlmClient } from "../local-llm.js";
|
|
8
|
-
import type { FallbackLlmClient, FallbackLlmOptions } from "../fallback-llm.js";
|
|
9
7
|
|
|
10
8
|
export interface RevalidationVerdict {
|
|
11
9
|
memoryId: string;
|
|
@@ -13,18 +11,20 @@ export interface RevalidationVerdict {
|
|
|
13
11
|
reason?: string;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
temperature: number;
|
|
25
|
-
maxTokens: number;
|
|
14
|
+
export type RevalidationFastChatCompletion = (
|
|
15
|
+
messages: Array<{ role: "system" | "user" | "assistant"; content: string }>,
|
|
16
|
+
options: {
|
|
17
|
+
temperature?: number;
|
|
18
|
+
maxTokens?: number;
|
|
19
|
+
timeoutMs?: number;
|
|
20
|
+
operation?: string;
|
|
21
|
+
priority?: "background" | "recall-critical";
|
|
26
22
|
signal?: AbortSignal;
|
|
27
|
-
}
|
|
23
|
+
},
|
|
24
|
+
) => Promise<{ content: string } | null>;
|
|
25
|
+
|
|
26
|
+
export interface RevalidationDeps {
|
|
27
|
+
fastChatCompletion: RevalidationFastChatCompletion;
|
|
28
28
|
parseJsonObject: (raw: string | null) => unknown;
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -95,78 +95,27 @@ export async function revalidateDependentsViaLlm(
|
|
|
95
95
|
superseded: { id: string; content: string },
|
|
96
96
|
replacement: { id: string; content: string } | null,
|
|
97
97
|
dependents: Array<{ id: string; category: string; content: string }>,
|
|
98
|
-
signal?: AbortSignal,
|
|
98
|
+
options: { signal?: AbortSignal; timeoutMs?: number } = {},
|
|
99
99
|
): Promise<{ verdicts: RevalidationVerdict[] }> {
|
|
100
100
|
const { input, instructionText } = buildPrompt(superseded, replacement, dependents);
|
|
101
101
|
const maxTokens = Math.max(1024, dependents.length * 256);
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
rawContent = response?.content ?? null;
|
|
120
|
-
if (!rawContent && !deps.config.localLlmFallback) {
|
|
121
|
-
throw new Error("local LLM returned no dependency revalidation output");
|
|
122
|
-
}
|
|
123
|
-
} catch (error) {
|
|
124
|
-
if (!deps.config.localLlmFallback || signal?.aborted) throw error;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (rawContent === null && !deps.shouldUseDirectClient) {
|
|
129
|
-
const response = await deps.fallbackLlm.chatCompletion(
|
|
130
|
-
[
|
|
131
|
-
{ role: "system", content: instructionText },
|
|
132
|
-
{ role: "user", content: input },
|
|
133
|
-
],
|
|
134
|
-
deps.withGatewayAgent({ temperature: 0.2, maxTokens, signal }),
|
|
135
|
-
);
|
|
136
|
-
rawContent = response?.content ?? null;
|
|
137
|
-
if (!rawContent) throw new Error("fallback LLM returned no dependency revalidation output");
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (rawContent === null && deps.shouldUseDirectClient) {
|
|
141
|
-
const chatClient = deps.client as unknown as {
|
|
142
|
-
chat: {
|
|
143
|
-
completions: {
|
|
144
|
-
create(
|
|
145
|
-
request: {
|
|
146
|
-
model: string;
|
|
147
|
-
messages: Array<{ role: string; content: string }>;
|
|
148
|
-
max_tokens?: number;
|
|
149
|
-
},
|
|
150
|
-
options?: { signal?: AbortSignal },
|
|
151
|
-
): Promise<{ choices?: Array<{ message?: { content?: string } }> }>;
|
|
152
|
-
};
|
|
153
|
-
};
|
|
154
|
-
};
|
|
155
|
-
const response = await chatClient.chat.completions.create(
|
|
156
|
-
{
|
|
157
|
-
model: deps.config.model,
|
|
158
|
-
messages: [
|
|
159
|
-
{ role: "system", content: instructionText },
|
|
160
|
-
{ role: "user", content: input },
|
|
161
|
-
],
|
|
162
|
-
max_tokens: maxTokens,
|
|
163
|
-
},
|
|
164
|
-
{ signal },
|
|
165
|
-
);
|
|
166
|
-
rawContent = response.choices?.[0]?.message?.content ?? null;
|
|
167
|
-
if (!rawContent?.trim()) {
|
|
168
|
-
throw new Error("direct client returned no dependency revalidation output");
|
|
169
|
-
}
|
|
102
|
+
const response = await deps.fastChatCompletion(
|
|
103
|
+
[
|
|
104
|
+
{ role: "system", content: instructionText },
|
|
105
|
+
{ role: "user", content: input },
|
|
106
|
+
],
|
|
107
|
+
{
|
|
108
|
+
temperature: 0.2,
|
|
109
|
+
maxTokens,
|
|
110
|
+
operation: "dependency_revalidation",
|
|
111
|
+
priority: "background",
|
|
112
|
+
timeoutMs: options.timeoutMs,
|
|
113
|
+
signal: options.signal,
|
|
114
|
+
},
|
|
115
|
+
);
|
|
116
|
+
const rawContent = response?.content ?? null;
|
|
117
|
+
if (!rawContent?.trim()) {
|
|
118
|
+
throw new Error("fast completion returned no dependency revalidation output");
|
|
170
119
|
}
|
|
171
120
|
|
|
172
121
|
return { verdicts: normalizeVerdicts(deps.parseJsonObject(rawContent), dependents) };
|
package/src/orchestrator.ts
CHANGED
|
@@ -24,6 +24,7 @@ import { SmartBuffer } from "./buffer.js";
|
|
|
24
24
|
import { chunkContent, type ChunkingConfig } from "./chunking.js";
|
|
25
25
|
import { semanticChunkContent, type SemanticChunkResult } from "./semantic-chunking.js";
|
|
26
26
|
import { ExtractionEngine } from "./extraction.js";
|
|
27
|
+
import type { RevalidationFastChatCompletion } from "./orchestration/dependency-revalidation.js";
|
|
27
28
|
import { detectPassiveCorrections } from "./correction/passive-correction-detector.js";
|
|
28
29
|
import { capturePassiveCorrections, type PassiveCaptureConfig } from "./correction/passive-capture.js";
|
|
29
30
|
import { createCorrectionService } from "./correction/correction-access-wiring.js";
|
|
@@ -1684,6 +1685,7 @@ export class Orchestrator {
|
|
|
1684
1685
|
this.localLlm,
|
|
1685
1686
|
config.gatewayConfig,
|
|
1686
1687
|
this.modelRegistry,
|
|
1688
|
+
this.fastChatCompletion.bind(this),
|
|
1687
1689
|
);
|
|
1688
1690
|
this.lifecyclePolicyCoordinator = new LifecyclePolicyCoordinator({
|
|
1689
1691
|
config,
|
|
@@ -1881,21 +1883,17 @@ export class Orchestrator {
|
|
|
1881
1883
|
);
|
|
1882
1884
|
}
|
|
1883
1885
|
|
|
1884
|
-
/**
|
|
1885
|
-
* Execute a fast-tier LLM chat completion.
|
|
1886
|
-
* When gateway model source is active and fastGatewayAgentId is configured,
|
|
1887
|
-
* routes through the gateway chain. Otherwise uses the local fast LLM.
|
|
1888
|
-
*/
|
|
1886
|
+
/** Execute a fast-tier completion through the gateway when configured, otherwise the local fast LLM. */
|
|
1889
1887
|
private async fastChatCompletion(
|
|
1890
1888
|
messages: Array<{ role: string; content: string }>,
|
|
1891
|
-
options:
|
|
1889
|
+
options: Parameters<RevalidationFastChatCompletion>[1],
|
|
1892
1890
|
): Promise<{ content: string } | null> {
|
|
1893
1891
|
if (this._fastGatewayLlm && this.config.modelSource === "gateway") {
|
|
1894
1892
|
const agentId =
|
|
1895
1893
|
this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined;
|
|
1896
1894
|
const result = await this._fastGatewayLlm.chatCompletion(
|
|
1897
1895
|
messages as Array<{ role: "system" | "user" | "assistant"; content: string }>,
|
|
1898
|
-
{
|
|
1896
|
+
{ ...options, agentId },
|
|
1899
1897
|
);
|
|
1900
1898
|
return result ? { content: result.content } : null;
|
|
1901
1899
|
}
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency propagation lifecycle subject for the scenario-matrix harness.
|
|
3
|
+
*
|
|
4
|
+
* Each namespace uses a real StorageManager over an isolated temporary directory.
|
|
5
|
+
* ExtractionEngine uses its production revalidation route with deterministic completion.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
|
|
13
|
+
import { ExtractionEngine } from "../../extraction.js";
|
|
14
|
+
import {
|
|
15
|
+
propagateInvalidation,
|
|
16
|
+
type PropagationEvent,
|
|
17
|
+
type PropagationResult,
|
|
18
|
+
} from "../../orchestration/dependency-propagation.js";
|
|
19
|
+
import type { RevalidationFastChatCompletion } from "../../orchestration/dependency-revalidation.js";
|
|
20
|
+
import { StorageManager } from "../../storage.js";
|
|
21
|
+
import type { MemoryFile, MemoryLinkType, PluginConfig } from "../../types.js";
|
|
22
|
+
import {
|
|
23
|
+
type LifecycleSubject,
|
|
24
|
+
type MatrixRow,
|
|
25
|
+
runLifecycleMatrix,
|
|
26
|
+
} from "../lifecycle-matrix.js";
|
|
27
|
+
|
|
28
|
+
const NOW = "2026-08-09T00:00:00.000Z";
|
|
29
|
+
type NamespaceName = "alice" | "bob" | "default";
|
|
30
|
+
type NamespaceDirectoryMap = Map<NamespaceName, string>;
|
|
31
|
+
type NamespaceStorageMap = Map<NamespaceName, StorageManager>;
|
|
32
|
+
type CompletionCall = {
|
|
33
|
+
messages: Parameters<RevalidationFastChatCompletion>[0];
|
|
34
|
+
options: Parameters<RevalidationFastChatCompletion>[1];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type PropagationState = {
|
|
38
|
+
rootDir: string;
|
|
39
|
+
namespaceDirs: NamespaceDirectoryMap;
|
|
40
|
+
storages: NamespaceStorageMap;
|
|
41
|
+
activeNamespace: NamespaceName;
|
|
42
|
+
storage: StorageManager;
|
|
43
|
+
extraction: ExtractionEngine;
|
|
44
|
+
propagationCalls: PropagationEvent[];
|
|
45
|
+
propagationResults: PropagationResult[];
|
|
46
|
+
completionCalls: CompletionCall[];
|
|
47
|
+
revalidationCalls: Array<{
|
|
48
|
+
supersededId: string;
|
|
49
|
+
dependentIds: string[];
|
|
50
|
+
}>;
|
|
51
|
+
lifecycleLabels: string[];
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
function makeMemory(
|
|
55
|
+
id: string,
|
|
56
|
+
options: {
|
|
57
|
+
links?: Array<{ targetId: string; linkType: MemoryLinkType }>;
|
|
58
|
+
content?: string;
|
|
59
|
+
} = {},
|
|
60
|
+
): MemoryFile {
|
|
61
|
+
return {
|
|
62
|
+
path: `synthetic/${id}.md`,
|
|
63
|
+
content: options.content ?? `claim for ${id}`,
|
|
64
|
+
frontmatter: {
|
|
65
|
+
id,
|
|
66
|
+
category: "fact",
|
|
67
|
+
created: NOW,
|
|
68
|
+
updated: NOW,
|
|
69
|
+
source: "synthetic-dependency-propagation",
|
|
70
|
+
confidence: 0.9,
|
|
71
|
+
confidenceTier: "explicit",
|
|
72
|
+
tags: [],
|
|
73
|
+
status: "active",
|
|
74
|
+
links: options.links?.map((link) => ({ ...link, strength: 0.9 })),
|
|
75
|
+
},
|
|
76
|
+
} as unknown as MemoryFile;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function makeConfig(memoryDir: string): PluginConfig {
|
|
80
|
+
return {
|
|
81
|
+
memoryDir,
|
|
82
|
+
model: "synthetic-dependency-propagation",
|
|
83
|
+
modelSource: "plugin",
|
|
84
|
+
localLlmEnabled: false,
|
|
85
|
+
dependencyPropagation: {
|
|
86
|
+
enabled: true,
|
|
87
|
+
linkTypes: ["supports", "follows"],
|
|
88
|
+
maxDependents: 10,
|
|
89
|
+
timeoutMs: 500,
|
|
90
|
+
dryRun: false,
|
|
91
|
+
},
|
|
92
|
+
} as unknown as PluginConfig;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function namespaceMemories(namespace: NamespaceName): MemoryFile[] {
|
|
96
|
+
const oldId = `${namespace}-old`;
|
|
97
|
+
const dependentId = `${namespace}-dependent`;
|
|
98
|
+
const grandchildId = `${namespace}-grandchild`;
|
|
99
|
+
return [
|
|
100
|
+
makeMemory(oldId, {
|
|
101
|
+
content: `supporting claim for ${namespace}`,
|
|
102
|
+
links: [{ targetId: dependentId, linkType: "supports" }],
|
|
103
|
+
}),
|
|
104
|
+
makeMemory(dependentId, {
|
|
105
|
+
links: [{ targetId: oldId, linkType: "follows" }],
|
|
106
|
+
}),
|
|
107
|
+
makeMemory(grandchildId, {
|
|
108
|
+
links: [{ targetId: dependentId, linkType: "supports" }],
|
|
109
|
+
}),
|
|
110
|
+
];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function serializeFixture(memory: MemoryFile): string {
|
|
114
|
+
const links = (memory.frontmatter.links ?? [])
|
|
115
|
+
.map(
|
|
116
|
+
(link) =>
|
|
117
|
+
` - targetId: ${link.targetId} linkType: ${link.linkType} strength: ${link.strength ?? 0.9}`,
|
|
118
|
+
)
|
|
119
|
+
.join("\n");
|
|
120
|
+
return [
|
|
121
|
+
"---",
|
|
122
|
+
`id: ${memory.frontmatter.id}`,
|
|
123
|
+
`category: ${memory.frontmatter.category}`,
|
|
124
|
+
`created: ${memory.frontmatter.created}`,
|
|
125
|
+
`updated: ${memory.frontmatter.updated}`,
|
|
126
|
+
`source: ${memory.frontmatter.source}`,
|
|
127
|
+
`confidence: ${memory.frontmatter.confidence}`,
|
|
128
|
+
`confidenceTier: ${memory.frontmatter.confidenceTier}`,
|
|
129
|
+
"tags: []",
|
|
130
|
+
`status: ${memory.frontmatter.status}`,
|
|
131
|
+
"links:",
|
|
132
|
+
links,
|
|
133
|
+
"---",
|
|
134
|
+
"",
|
|
135
|
+
memory.content,
|
|
136
|
+
"",
|
|
137
|
+
].join("\n");
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function persistFixtures(directory: string, memories: MemoryFile[]): Promise<void> {
|
|
141
|
+
const factsDir = path.join(directory, "facts", "2026-08-09");
|
|
142
|
+
await mkdir(factsDir, { recursive: true });
|
|
143
|
+
await Promise.all(
|
|
144
|
+
memories.map((memory) =>
|
|
145
|
+
writeFile(
|
|
146
|
+
path.join(factsDir, `${memory.frontmatter.id}.md`),
|
|
147
|
+
serializeFixture(memory),
|
|
148
|
+
"utf8",
|
|
149
|
+
),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function activeStorage(state: PropagationState): StorageManager {
|
|
155
|
+
const storage = state.storages.get(state.activeNamespace);
|
|
156
|
+
assert.ok(storage, `missing namespace storage ${state.activeNamespace}`);
|
|
157
|
+
return storage;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function makeExtraction(
|
|
161
|
+
stateRef: { current?: PropagationState },
|
|
162
|
+
config: PluginConfig,
|
|
163
|
+
): ExtractionEngine {
|
|
164
|
+
const fastCompletion: RevalidationFastChatCompletion = async (messages, options) => {
|
|
165
|
+
const state = stateRef.current;
|
|
166
|
+
assert.ok(state, "extraction state is not initialized");
|
|
167
|
+
state.completionCalls.push({ messages, options });
|
|
168
|
+
const userMessage = messages.find((message) => message.role === "user")?.content ?? "";
|
|
169
|
+
const supersededId = userMessage.match(/^SUPERSEDED MEMORY \(id: ([^)]+)\):$/m)?.[1] ?? "";
|
|
170
|
+
const dependentIds = [...userMessage.matchAll(/^\[\d+\] id: ([^ |]+) \| category:/gm)].map(
|
|
171
|
+
(match) => match[1]!,
|
|
172
|
+
);
|
|
173
|
+
state.revalidationCalls.push({ supersededId, dependentIds });
|
|
174
|
+
if (options.signal?.aborted) return null;
|
|
175
|
+
return {
|
|
176
|
+
content: JSON.stringify({
|
|
177
|
+
verdicts: dependentIds.map((memoryId) => ({
|
|
178
|
+
memoryId,
|
|
179
|
+
verdict: "invalidated",
|
|
180
|
+
reason: "synthetic supporting claim changed",
|
|
181
|
+
})),
|
|
182
|
+
}),
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
return new ExtractionEngine(config, undefined, undefined, undefined, undefined, fastCompletion);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function namespaceFor(row: MatrixRow): NamespaceName {
|
|
189
|
+
if (row.dimensions.providerIdentity === "rebound") return "bob";
|
|
190
|
+
if (row.dimensions.providerIdentity === "sparse" && !row.dimensions.rememberedBinding) return "default";
|
|
191
|
+
return "alice";
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function causeFor(row: MatrixRow): PropagationEvent["cause"] {
|
|
195
|
+
switch (row.dimensions.flush) {
|
|
196
|
+
case "compaction":
|
|
197
|
+
return "consolidation_invalidate";
|
|
198
|
+
case "before_reset":
|
|
199
|
+
return "contradiction";
|
|
200
|
+
case "session_end":
|
|
201
|
+
return "temporal_supersession";
|
|
202
|
+
case "none":
|
|
203
|
+
return "contradiction";
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
async function eventFor(state: PropagationState, row: MatrixRow): Promise<PropagationEvent> {
|
|
208
|
+
const old = await activeStorage(state).getMemoryById(`${state.activeNamespace}-old`);
|
|
209
|
+
assert.ok(old, `missing old memory for ${state.activeNamespace}`);
|
|
210
|
+
return {
|
|
211
|
+
oldMemory: {
|
|
212
|
+
content: old.content,
|
|
213
|
+
frontmatter: { ...old.frontmatter },
|
|
214
|
+
},
|
|
215
|
+
replacementId: `${state.activeNamespace}-replacement`,
|
|
216
|
+
replacementContent: `replacement claim for ${state.activeNamespace}`,
|
|
217
|
+
cause: causeFor(row),
|
|
218
|
+
namespaceScope: state.activeNamespace,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const subject: LifecycleSubject<PropagationState> = {
|
|
223
|
+
async setup(row: MatrixRow): Promise<PropagationState> {
|
|
224
|
+
const rootDir = await mkdtemp(path.join(os.tmpdir(), "remnic-dependency-propagation-"));
|
|
225
|
+
try {
|
|
226
|
+
const namespaceDirs: NamespaceDirectoryMap = new Map();
|
|
227
|
+
const storages: NamespaceStorageMap = new Map();
|
|
228
|
+
for (const namespace of ["alice", "bob", "default"] as const) {
|
|
229
|
+
const directory = path.join(rootDir, namespace);
|
|
230
|
+
await mkdir(directory, { recursive: true });
|
|
231
|
+
const storage = new StorageManager(directory);
|
|
232
|
+
await storage.ensureDirectories();
|
|
233
|
+
await persistFixtures(directory, namespaceMemories(namespace));
|
|
234
|
+
namespaceDirs.set(namespace, directory);
|
|
235
|
+
storages.set(namespace, storage);
|
|
236
|
+
}
|
|
237
|
+
const activeNamespace = namespaceFor(row);
|
|
238
|
+
const storage = storages.get(activeNamespace);
|
|
239
|
+
const memoryDir = namespaceDirs.get(activeNamespace);
|
|
240
|
+
assert.ok(storage, `missing namespace storage ${activeNamespace}`);
|
|
241
|
+
assert.ok(memoryDir, `missing namespace directory ${activeNamespace}`);
|
|
242
|
+
const stateRef: { current?: PropagationState } = {};
|
|
243
|
+
const state: PropagationState = {
|
|
244
|
+
rootDir,
|
|
245
|
+
namespaceDirs,
|
|
246
|
+
storages,
|
|
247
|
+
activeNamespace,
|
|
248
|
+
storage,
|
|
249
|
+
extraction: makeExtraction(stateRef, makeConfig(memoryDir)),
|
|
250
|
+
propagationCalls: [],
|
|
251
|
+
propagationResults: [],
|
|
252
|
+
completionCalls: [],
|
|
253
|
+
revalidationCalls: [],
|
|
254
|
+
lifecycleLabels: [],
|
|
255
|
+
};
|
|
256
|
+
stateRef.current = state;
|
|
257
|
+
return state;
|
|
258
|
+
} catch (error) {
|
|
259
|
+
await rm(rootDir, { recursive: true, force: true });
|
|
260
|
+
throw error;
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
async exercise(state: PropagationState, row: MatrixRow): Promise<void> {
|
|
265
|
+
state.lifecycleLabels.push(row.dimensions.flush);
|
|
266
|
+
if (row.dimensions.restart) {
|
|
267
|
+
const directory = state.namespaceDirs.get(state.activeNamespace);
|
|
268
|
+
assert.ok(directory, `missing namespace directory ${state.activeNamespace}`);
|
|
269
|
+
state.storage = new StorageManager(directory);
|
|
270
|
+
state.storages.set(state.activeNamespace, state.storage);
|
|
271
|
+
const stateRef: { current?: PropagationState } = { current: state };
|
|
272
|
+
state.extraction = makeExtraction(stateRef, makeConfig(directory));
|
|
273
|
+
}
|
|
274
|
+
const run = async (): Promise<void> => {
|
|
275
|
+
const event = await eventFor(state, row);
|
|
276
|
+
state.propagationCalls.push(event);
|
|
277
|
+
state.propagationResults.push(
|
|
278
|
+
await propagateInvalidation(
|
|
279
|
+
{
|
|
280
|
+
storage: state.storage,
|
|
281
|
+
extraction: state.extraction,
|
|
282
|
+
config: makeConfig(state.namespaceDirs.get(state.activeNamespace)!),
|
|
283
|
+
},
|
|
284
|
+
event,
|
|
285
|
+
),
|
|
286
|
+
);
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
await run();
|
|
290
|
+
if (row.dimensions.dedupeOrReplay) await run();
|
|
291
|
+
},
|
|
292
|
+
|
|
293
|
+
async invariants(state: PropagationState, row: MatrixRow): Promise<void> {
|
|
294
|
+
assert.equal(state.propagationCalls.length, row.dimensions.dedupeOrReplay ? 2 : 1);
|
|
295
|
+
assert.equal(state.propagationResults[0]?.route, "fast-completion");
|
|
296
|
+
assert.equal(state.propagationResults[0]?.dependentsFound, 1);
|
|
297
|
+
assert.equal(state.propagationResults[0]?.invalidated, 1);
|
|
298
|
+
if (row.dimensions.dedupeOrReplay) {
|
|
299
|
+
assert.equal(state.propagationResults[1]?.skipped, "no_dependents");
|
|
300
|
+
assert.equal(state.propagationResults[1]?.dependentsFound, 0);
|
|
301
|
+
}
|
|
302
|
+
assert.equal(state.revalidationCalls.length, 1, "the real LLM revalidation path must run");
|
|
303
|
+
const revalidation = state.revalidationCalls[0];
|
|
304
|
+
assert.ok(revalidation, "missing revalidation call");
|
|
305
|
+
assert.equal(revalidation.supersededId, `${state.activeNamespace}-old`);
|
|
306
|
+
assert.deepEqual(
|
|
307
|
+
revalidation.dependentIds,
|
|
308
|
+
[`${state.activeNamespace}-dependent`],
|
|
309
|
+
"discovery must stay one-hop and namespace-scoped",
|
|
310
|
+
);
|
|
311
|
+
assert.equal(state.completionCalls.length, 1);
|
|
312
|
+
const completion = state.completionCalls[0];
|
|
313
|
+
assert.ok(completion, "missing completion call");
|
|
314
|
+
assert.deepEqual(completion.messages.map((message) => message.role), ["system", "user"]);
|
|
315
|
+
assert.equal(
|
|
316
|
+
completion.messages[1]?.content,
|
|
317
|
+
`SUPERSEDED MEMORY (id: ${state.activeNamespace}-old):
|
|
318
|
+
supporting claim for ${state.activeNamespace}
|
|
319
|
+
|
|
320
|
+
REPLACEMENT (id: ${state.activeNamespace}-replacement):
|
|
321
|
+
replacement claim for ${state.activeNamespace}
|
|
322
|
+
|
|
323
|
+
DEPENDENTS TO REVALIDATE (return exactly one verdict per id):
|
|
324
|
+
[1] id: ${state.activeNamespace}-dependent | category: fact
|
|
325
|
+
claim for ${state.activeNamespace}-dependent`,
|
|
326
|
+
);
|
|
327
|
+
assert.match(completion.messages[0]?.content ?? "", /Never invent memory IDs/);
|
|
328
|
+
assert.equal(completion.options.temperature, 0.2);
|
|
329
|
+
assert.equal(completion.options.maxTokens, 1024);
|
|
330
|
+
assert.equal(completion.options.timeoutMs, 500);
|
|
331
|
+
assert.equal(completion.options.operation, "dependency_revalidation");
|
|
332
|
+
assert.equal(completion.options.priority, "background");
|
|
333
|
+
assert.ok(completion.options.signal instanceof AbortSignal);
|
|
334
|
+
assert.equal(completion.options.signal?.aborted, false);
|
|
335
|
+
assert.equal(state.lifecycleLabels.length, 1);
|
|
336
|
+
assert.equal(state.lifecycleLabels[0], row.dimensions.flush);
|
|
337
|
+
|
|
338
|
+
const active = await activeStorage(state).readAllMemories();
|
|
339
|
+
const dependent = active.find((memory) => memory.frontmatter.id === `${state.activeNamespace}-dependent`);
|
|
340
|
+
const grandchild = active.find((memory) => memory.frontmatter.id === `${state.activeNamespace}-grandchild`);
|
|
341
|
+
assert.equal(dependent?.frontmatter.status, "superseded");
|
|
342
|
+
assert.equal(dependent?.frontmatter.supersededBy, `${state.activeNamespace}-replacement`);
|
|
343
|
+
assert.equal(dependent?.frontmatter.supersessionCause, "dependency");
|
|
344
|
+
assert.equal(dependent?.frontmatter.invalidatedBy, `${state.activeNamespace}-old`);
|
|
345
|
+
assert.equal(grandchild?.frontmatter.status, "active");
|
|
346
|
+
for (const [namespace, storage] of state.storages) {
|
|
347
|
+
if (namespace === state.activeNamespace) continue;
|
|
348
|
+
const memories = await storage.readAllMemories();
|
|
349
|
+
assert.equal(
|
|
350
|
+
memories.find((memory) => memory.frontmatter.id === `${namespace}-dependent`)?.frontmatter.status,
|
|
351
|
+
"active",
|
|
352
|
+
`dependent in ${namespace} must not be invalidated by ${state.activeNamespace}`,
|
|
353
|
+
);
|
|
354
|
+
assert.equal(
|
|
355
|
+
memories.find((memory) => memory.frontmatter.id === `${namespace}-grandchild`)?.frontmatter.status,
|
|
356
|
+
"active",
|
|
357
|
+
`grandchild in ${namespace} must remain untouched`,
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
async teardown(state: PropagationState): Promise<void> {
|
|
363
|
+
await rm(state.rootDir, { recursive: true, force: true });
|
|
364
|
+
},
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
runLifecycleMatrix("dependency-propagation", subject);
|