@remnic/core 9.65.2 → 9.65.3
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 +44 -44
- package/dist/access-admin-ops-surface.js +14 -14
- package/dist/access-authorization-probe.d.ts +38 -38
- package/dist/access-authorization-probe.js +15 -15
- package/dist/access-boundary.d.ts +40 -40
- package/dist/access-boundary.js +14 -14
- package/dist/access-cli.js +52 -52
- package/dist/access-coding-context-resolution.d.ts +3 -1
- package/dist/access-extraction-force-flush.d.ts +25 -25
- package/dist/access-extraction-force-flush.js +14 -14
- package/dist/access-health-types.d.ts +3 -1
- package/dist/access-http-lcm-compaction.d.ts +39 -39
- package/dist/access-http-lifecycle-flush.d.ts +39 -39
- package/dist/access-http-offline-stream.d.ts +25 -25
- package/dist/access-http-query.d.ts +4 -2
- package/dist/access-http-query.js +16 -16
- package/dist/access-http.d.ts +51 -44
- package/dist/access-http.js +30 -30
- package/dist/access-identity-continuity-surface.d.ts +12 -12
- package/dist/access-identity-continuity-surface.js +14 -14
- package/dist/access-lcm-surface.d.ts +27 -27
- package/dist/access-lcm-surface.js +14 -14
- package/dist/access-mcp-admin-tools.d.ts +9 -1
- package/dist/access-mcp-admin-tools.js +3 -1
- package/dist/access-mcp-output-schemas.js +1 -1
- package/dist/access-mcp.d.ts +39 -39
- package/dist/access-mcp.js +24 -24
- package/dist/access-memory-search-fanout.d.ts +4 -2
- package/dist/{access-namespace-preflight-Dhvcl-T0.d.ts → access-namespace-preflight-B7Usyz-K.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +5 -3
- package/dist/access-namespace-preflight.js +14 -14
- package/dist/access-observe-write-surface.d.ts +39 -39
- package/dist/access-observe-write-surface.js +14 -14
- package/dist/access-offline-manifest.d.ts +12 -12
- package/dist/access-operations-batch.js +18 -18
- package/dist/access-operations.d.ts +40 -40
- package/dist/access-operations.js +21 -21
- package/dist/access-recall-concurrency.d.ts +40 -40
- package/dist/access-recall-concurrency.js +14 -14
- package/dist/access-recall-response.d.ts +24 -24
- package/dist/access-recall-response.js +14 -14
- package/dist/access-recall-surface.d.ts +24 -24
- package/dist/access-recall-surface.js +14 -14
- package/dist/access-schema.d.ts +45 -45
- package/dist/{access-service-Bke1alZO.d.ts → access-service-DkaIG3n8.d.ts} +219 -75
- package/dist/access-service-helpers.d.ts +40 -40
- package/dist/access-service.d.ts +47 -47
- package/dist/access-service.js +14 -14
- package/dist/access-surface-catalog.d.ts +40 -40
- package/dist/access-surface-catalog.js +20 -16
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-wearables-meetings-surface.d.ts +5 -3
- package/dist/action-confidence.d.ts +3 -1
- package/dist/active-memory-bridge.d.ts +3 -1
- package/dist/active-recall.d.ts +3 -1
- package/dist/active-recall.js +6 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/ambient-provenance.d.ts +3 -1
- package/dist/artifact-search.d.ts +3 -1
- package/dist/behavior-learner.d.ts +3 -1
- package/dist/behavior-signals.d.ts +3 -1
- package/dist/bootstrap.d.ts +12 -12
- package/dist/briefing-window.d.ts +4 -2
- package/dist/briefing.d.ts +4 -2
- package/dist/briefing.js +3 -3
- package/dist/buffer-surprise-report.d.ts +3 -1
- package/dist/buffer-turn-helpers.d.ts +3 -1
- package/dist/buffer.d.ts +4 -2
- package/dist/bulk-import/index.d.ts +5 -3
- package/dist/calibration.d.ts +3 -1
- package/dist/capabilities.d.ts +3 -1
- package/dist/{catalog-DV6qnbr7.d.ts → catalog-CX2BZEJh.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +3 -1
- package/dist/causal-consolidation.js +7 -7
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-R7JAM2XF.js → chunk-2VXWFYJE.js} +3 -3
- package/dist/{chunk-UXO5IMBK.js → chunk-4XDGYCZI.js} +2 -2
- package/dist/{chunk-OTHZWLUD.js → chunk-57HVIG5U.js} +2 -2
- package/dist/{chunk-EILZG5VC.js → chunk-6TAX66IA.js} +2 -2
- package/dist/{chunk-NKKD4ZAU.js → chunk-6VALIZKG.js} +2 -2
- package/dist/{chunk-BWLRUMOG.js → chunk-76PL4XLG.js} +435 -1
- package/dist/chunk-76PL4XLG.js.map +1 -0
- package/dist/{chunk-2E36UXVW.js → chunk-7KFIMGMP.js} +2 -2
- package/dist/{chunk-LGO6A7GJ.js → chunk-7QOO4LGC.js} +28 -28
- package/dist/{chunk-TBOJ76ER.js → chunk-AB3A7EFH.js} +18 -2
- package/dist/{chunk-TBOJ76ER.js.map → chunk-AB3A7EFH.js.map} +1 -1
- package/dist/{chunk-DZUJ46DO.js → chunk-AUO2LJ3K.js} +2 -2
- package/dist/{chunk-ZO6AXLEH.js → chunk-AYDDB3XI.js} +2 -2
- package/dist/{chunk-NTWN6HB2.js → chunk-AYYGRVRP.js} +2 -2
- package/dist/{chunk-7YQ4IYS2.js → chunk-AZAA5DNP.js} +2 -2
- package/dist/{chunk-4KYOLI6M.js → chunk-BKYPJUQL.js} +120 -14
- package/dist/chunk-BKYPJUQL.js.map +1 -0
- package/dist/{chunk-Z7PBQPJ4.js → chunk-BQUEAVNW.js} +2 -2
- package/dist/{chunk-35NN3ZFA.js → chunk-CTVWELNK.js} +21 -3
- package/dist/chunk-CTVWELNK.js.map +1 -0
- package/dist/{chunk-5YQ63T4B.js → chunk-D27J626P.js} +2 -2
- package/dist/{chunk-LZH5FR2W.js → chunk-DHTQP334.js} +2 -2
- package/dist/{chunk-Y7DK7HHJ.js → chunk-E4MVQQVX.js} +2 -2
- package/dist/{chunk-JYYBA7TF.js → chunk-EIVIB73I.js} +2 -2
- package/dist/{chunk-S2DPMJXH.js → chunk-EV3YFLCB.js} +2 -2
- package/dist/{chunk-TZNQUNKL.js → chunk-FC7TIRFS.js} +15 -1
- package/dist/chunk-FC7TIRFS.js.map +1 -0
- package/dist/{chunk-3I7ASZN3.js → chunk-G57LQRP6.js} +2 -2
- package/dist/{chunk-UIN2BWDD.js → chunk-GN55KU2P.js} +2 -2
- package/dist/{chunk-PE255F4T.js → chunk-GUXS322H.js} +2 -2
- package/dist/{chunk-V3MXUL3D.js → chunk-H5FW4S5Q.js} +319 -643
- package/dist/chunk-H5FW4S5Q.js.map +1 -0
- package/dist/chunk-I32NKXE2.js +879 -0
- package/dist/chunk-I32NKXE2.js.map +1 -0
- package/dist/{chunk-YB42WZCY.js → chunk-IQSC3V2E.js} +2 -2
- package/dist/{chunk-MN4KB2A4.js → chunk-MBDJJTAT.js} +3 -3
- package/dist/{chunk-SQI57UCJ.js → chunk-MRTUN665.js} +2 -2
- package/dist/{chunk-SBDCZ2AX.js → chunk-NXKJHSDN.js} +1 -1
- package/dist/chunk-NXKJHSDN.js.map +1 -0
- package/dist/{chunk-SPUJNJJC.js → chunk-NZWEEALH.js} +2 -2
- package/dist/{chunk-2XDWWPTN.js → chunk-OJD4WS2E.js} +2 -2
- package/dist/{chunk-ZWXJBFZU.js → chunk-OLWTCWQ2.js} +8 -8
- package/dist/{chunk-XRYZRW54.js → chunk-P4DHENRE.js} +2 -2
- package/dist/{chunk-J275IYMG.js → chunk-PAYGC3BD.js} +29 -2
- package/dist/chunk-PAYGC3BD.js.map +1 -0
- package/dist/{chunk-IID2CMUU.js → chunk-PDVQ5JU3.js} +2 -2
- package/dist/{chunk-7BY7V4YX.js → chunk-Q4WONDMJ.js} +4 -3
- package/dist/{chunk-7BY7V4YX.js.map → chunk-Q4WONDMJ.js.map} +1 -1
- package/dist/{chunk-5NM4OH4P.js → chunk-QFMO32TO.js} +3 -3
- package/dist/{chunk-SIHSCCUQ.js → chunk-QXIQPCCN.js} +1 -1
- package/dist/{chunk-2YI72KM3.js → chunk-R47WINCY.js} +2 -2
- package/dist/{chunk-ZQHI2BZB.js → chunk-RK4WXUI2.js} +2 -2
- package/dist/{chunk-QOS5LBZN.js → chunk-S7Q5CM7E.js} +2 -2
- package/dist/{chunk-GDFVPUJ5.js → chunk-TDKSCV62.js} +2 -2
- package/dist/{chunk-OCZIYAE5.js → chunk-TYUS5TLG.js} +3 -3
- package/dist/{chunk-GNCCUR6K.js → chunk-URHCUXKI.js} +2 -2
- package/dist/{chunk-TF77C7SV.js → chunk-VA5KMSAE.js} +7 -5
- package/dist/chunk-VA5KMSAE.js.map +1 -0
- package/dist/{chunk-SB7D4BT7.js → chunk-WN5FSGLE.js} +1545 -105
- package/dist/chunk-WN5FSGLE.js.map +1 -0
- package/dist/{chunk-YLDXWCZP.js → chunk-YF6UHWOV.js} +14 -9
- package/dist/chunk-YF6UHWOV.js.map +1 -0
- package/dist/{chunk-CT56C22C.js → chunk-Z4RPXHJH.js} +4 -4
- package/dist/{cli-cShQ13XG.d.ts → cli-ChKeYMZv.d.ts} +5 -5
- package/dist/cli.d.ts +25 -25
- package/dist/cli.js +44 -43
- package/dist/coding/pre-action-gate.d.ts +2 -60
- package/dist/compounding/engine.d.ts +4 -2
- package/dist/compounding/engine.js +3 -3
- package/dist/compounding/preference-consolidator.d.ts +3 -1
- package/dist/compression-optimizer.d.ts +3 -1
- package/dist/config.d.ts +3 -1
- package/dist/config.js +6 -1
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +3 -3
- package/dist/connectors/codex-materialize.d.ts +3 -1
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +3 -3
- package/dist/consolidation-provenance-check.d.ts +4 -2
- package/dist/consolidation-undo.d.ts +4 -2
- package/dist/contradiction/index.d.ts +10 -270
- package/dist/contradiction/index.js +11 -6
- package/dist/{contradiction-review-QKJH5DKD.js → contradiction-review-WRVLRWHS.js} +6 -2
- package/dist/{contradiction-scan-VOTQRRSX.js → contradiction-scan-AKUWPX5N.js} +5 -3
- package/dist/converge-config.d.ts +3 -1
- package/dist/convergence-refresh.d.ts +4 -2
- package/dist/convergence-refresh.js +5 -5
- package/dist/conversation-index/backend.d.ts +3 -1
- package/dist/conversation-index/chunker.d.ts +3 -1
- package/dist/conversation-index/faiss-adapter.d.ts +3 -1
- package/dist/conversation-index/indexer.d.ts +3 -1
- package/dist/conversation-index/search.d.ts +3 -1
- package/dist/corpus-watermark.d.ts +3 -1
- package/dist/corpus-watermark.js +5 -5
- package/dist/cross-lingual-recall.d.ts +3 -1
- package/dist/day-summary.d.ts +3 -1
- package/dist/delinearize.d.ts +3 -1
- package/dist/dependency-propagation-config.d.ts +3 -1
- package/dist/{dependency-propagation-delivery-CsGg-VwS.d.ts → dependency-propagation-delivery-B8ZMBBCY.d.ts} +1 -1
- package/dist/direct-answer-wiring.d.ts +3 -1
- package/dist/direct-answer.d.ts +3 -1
- package/dist/embedding-fallback.d.ts +3 -1
- package/dist/enrichment/index.d.ts +3 -1
- package/dist/entity-origin-fields.d.ts +3 -1
- package/dist/entity-retrieval.d.ts +4 -2
- package/dist/entity-retrieval.js +3 -3
- package/dist/entity-schema.d.ts +3 -1
- package/dist/episodic-context.d.ts +3 -1
- package/dist/explicit-capture.d.ts +12 -12
- package/dist/external-wiki-access.d.ts +40 -40
- package/dist/external-wiki-access.js +15 -15
- package/dist/external-wiki-collection-registration.d.ts +3 -1
- package/dist/external-wiki-collection.d.ts +3 -1
- package/dist/external-wiki-mcp-tools.d.ts +40 -40
- package/dist/extraction-error-classification.d.ts +3 -1
- package/dist/extraction-faithfulness.d.ts +3 -1
- package/dist/extraction-judge-telemetry.d.ts +3 -1
- package/dist/extraction-judge-training.d.ts +3 -1
- package/dist/extraction-judge.d.ts +3 -1
- package/dist/extraction-liveness.d.ts +3 -1
- package/dist/extraction-normalization.d.ts +3 -1
- package/dist/extraction-prompt.d.ts +3 -1
- package/dist/extraction-source-grounding-rules.d.ts +3 -1
- package/dist/extraction-source-grounding.d.ts +3 -1
- package/dist/extraction.d.ts +3 -1
- package/dist/extraction.js +3 -3
- package/dist/fallback-llm.d.ts +3 -1
- package/dist/graph-dashboard-diff.d.ts +3 -1
- package/dist/graph-dashboard-key.d.ts +3 -1
- package/dist/graph-dashboard-parser.d.ts +3 -1
- package/dist/graph-edge-reinforcement.d.ts +3 -1
- package/dist/graph-path-reconstruction.d.ts +3 -1
- package/dist/graph-path-scoring.d.ts +3 -1
- package/dist/graph-snapshot.d.ts +3 -1
- package/dist/graph.d.ts +3 -1
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/importance.d.ts +3 -1
- package/dist/importers/index.d.ts +3 -1
- package/dist/in-flight-reads.d.ts +3 -1
- package/dist/index-CexDrJzC.d.ts +284 -0
- package/dist/index.d.ts +251 -29
- package/dist/index.js +129 -75
- package/dist/intent.d.ts +3 -1
- package/dist/lcm/engine.d.ts +3 -1
- package/dist/lcm/index.d.ts +3 -1
- package/dist/lcm/tools.d.ts +3 -1
- package/dist/lifecycle.d.ts +3 -1
- package/dist/live-connectors-runner.d.ts +3 -1
- package/dist/local-llm.d.ts +3 -1
- package/dist/local-model-endpoint.d.ts +3 -1
- package/dist/maintenance/memory-governance.d.ts +3 -1
- package/dist/maintenance/memory-governance.js +3 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -3
- package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-projection.js +4 -4
- package/dist/{maintenance-jhMpeGne.d.ts → maintenance-nkdtSrVr.d.ts} +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +37 -37
- package/dist/memory-action-policy.d.ts +3 -1
- package/dist/memory-cache.d.ts +3 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +3 -1
- package/dist/memory-projection-store.d.ts +3 -1
- package/dist/memory-provenance.d.ts +3 -1
- package/dist/memory-snapshot.d.ts +3 -1
- package/dist/memory-subject-cli.d.ts +40 -40
- package/dist/memory-subject.d.ts +42 -42
- package/dist/memory-worth-outcomes.d.ts +4 -2
- package/dist/models-json.d.ts +3 -1
- package/dist/namespaces/migrate.d.ts +5 -3
- package/dist/namespaces/migrate.js +4 -4
- package/dist/namespaces/principal.d.ts +3 -1
- package/dist/namespaces/search.d.ts +3 -1
- package/dist/namespaces/storage.d.ts +5 -3
- package/dist/namespaces/storage.js +3 -3
- package/dist/native-knowledge.d.ts +3 -1
- package/dist/offline-sync-impression-drain.d.ts +3 -1
- package/dist/operator-doctor-corpus.d.ts +3 -1
- package/dist/operator-doctor-corpus.js +6 -6
- package/dist/operator-doctor-replica.d.ts +3 -1
- package/dist/operator-toolkit.d.ts +5 -3
- package/dist/operator-toolkit.js +15 -12
- package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
- package/dist/orchestration/maintenance.d.ts +6 -4
- package/dist/orchestration/maintenance.js +9 -9
- package/dist/{orchestrator-DyGUC7re.d.ts → orchestrator-Bvq1-RQs.d.ts} +23 -9
- package/dist/orchestrator.d.ts +12 -12
- package/dist/orchestrator.js +52 -52
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-C25Oxtp1.d.ts → pipeline-C8vfIiTX.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +3 -1
- package/dist/proactive-contention.d.ts +3 -1
- package/dist/provenance.d.ts +3 -1
- package/dist/{public-http-CMe7NQzj.d.ts → public-http-Cy0aYbys.d.ts} +1 -1
- package/dist/{qmd-DkDVCbgF.d.ts → qmd-B9p1SZTZ.d.ts} +1 -1
- package/dist/qmd-preflight.d.ts +4 -2
- package/dist/qmd-recall-cache.d.ts +3 -1
- package/dist/qmd.d.ts +4 -2
- package/dist/recall-concurrency-config.d.ts +3 -1
- package/dist/recall-disclosure-escalation.d.ts +3 -1
- package/dist/recall-explain-renderer.d.ts +3 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +3 -1
- package/dist/recall-planner-llm.d.ts +3 -1
- package/dist/recall-state.d.ts +3 -1
- package/dist/recall-tag-filter.d.ts +3 -1
- package/dist/recall-timings.d.ts +3 -1
- package/dist/recall-xray-cli.d.ts +3 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +3 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +3 -1
- package/dist/recall-xray.js +2 -2
- package/dist/reconcile/cursor.d.ts +3 -1
- package/dist/reconcile/manifest.d.ts +3 -1
- package/dist/reconcile/plan.d.ts +3 -1
- package/dist/replay/normalizers/chatgpt.d.ts +3 -1
- package/dist/replay/normalizers/claude.d.ts +3 -1
- package/dist/replay/normalizers/openclaw.d.ts +3 -1
- package/dist/replay/normalizers/shared.d.ts +3 -1
- package/dist/replay/runner.d.ts +3 -1
- package/dist/replay/types.d.ts +3 -1
- package/dist/replica-divergence.d.ts +3 -1
- package/dist/replica-peers-config.d.ts +3 -1
- package/dist/{resolution-MFY72STR.js → resolution-4552BNRV.js} +13 -3
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resume-bundles.js +4 -2
- package/dist/retrieval-agents.d.ts +4 -2
- package/dist/retrieval-tiers.d.ts +3 -1
- package/dist/routing/engine.d.ts +3 -1
- package/dist/routing/store.d.ts +3 -1
- package/dist/salvage-envelope.d.ts +3 -1
- package/dist/schemas.d.ts +44 -44
- package/dist/{scope-profiles-B9xMoFO-.d.ts → scope-profiles-DLrRxFWR.d.ts} +1 -1
- package/dist/search/embed-helper.d.ts +3 -1
- package/dist/search/factory.d.ts +3 -1
- package/dist/search/index.d.ts +3 -1
- package/dist/search/lancedb-backend.d.ts +3 -1
- package/dist/search/meilisearch-backend.d.ts +3 -1
- package/dist/search/noop-backend.d.ts +3 -1
- package/dist/search/orama-backend.d.ts +3 -1
- package/dist/search/port.d.ts +3 -1
- package/dist/search/remote-backend.d.ts +3 -1
- package/dist/{semantic-TddhF0y7.d.ts → semantic-BalR6EXU.d.ts} +1 -1
- package/dist/{semantic-consolidation-C4uykW84.d.ts → semantic-consolidation-DlN6xe20.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +4 -4
- package/dist/semantic-rule-promotion.js +3 -3
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +3 -3
- package/dist/{service-DCZDZNcV.d.ts → service-GkYyVfm9.d.ts} +2 -2
- package/dist/session-observer-bands.d.ts +3 -1
- package/dist/session-observer-state.d.ts +3 -1
- package/dist/shared-context/manager.d.ts +3 -1
- package/dist/signal.d.ts +3 -1
- package/dist/source-agent-qualifier.d.ts +3 -1
- package/dist/source-agent-qualifier.js +3 -3
- package/dist/{storage-CcKmEjL8.d.ts → storage-BIDzuKIn.d.ts} +1 -1
- package/dist/storage.d.ts +4 -2
- package/dist/storage.js +2 -2
- package/dist/subject-config.d.ts +3 -1
- package/dist/summarizer.d.ts +3 -1
- package/dist/summary-snapshot.d.ts +3 -1
- package/dist/support-passport/index.d.ts +43 -43
- package/dist/support-passport/index.js +17 -17
- package/dist/temporal-supersession.d.ts +4 -2
- package/dist/temporal-timeline-recall.d.ts +3 -1
- package/dist/temporal-validity.d.ts +3 -1
- package/dist/threading.d.ts +3 -1
- package/dist/tier-migration.d.ts +4 -2
- package/dist/tier-routing.d.ts +3 -1
- package/dist/topics.d.ts +3 -1
- package/dist/transcript.d.ts +3 -1
- package/dist/transfer/types.d.ts +20 -20
- package/dist/trust-score-stage.d.ts +3 -1
- package/dist/trust-score.d.ts +3 -1
- package/dist/{types-Pi0lfaEt.d.ts → types-BxAcOl5Q.d.ts} +323 -4
- package/dist/types.d.ts +3 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +3 -1
- package/dist/verified-recall.js +3 -3
- package/dist/who-knows-cli.d.ts +40 -40
- package/dist/who-knows-cli.js +4 -4
- package/dist/who-knows.d.ts +42 -42
- package/dist/who-knows.js +3 -3
- package/dist/write-envelope.d.ts +3 -1
- package/package.json +2 -2
- package/src/access-boundary.ts +4 -0
- package/src/access-http.ts +6 -5
- package/src/access-mcp-admin-tools.ts +24 -0
- package/src/access-mcp-output-schemas.ts +14 -0
- package/src/access-mcp.ts +2 -2
- package/src/access-operations-batch.ts +5 -0
- package/src/access-service.ts +27 -0
- package/src/access-surface-catalog.test.ts +24 -0
- package/src/access-surface-catalog.ts +4 -0
- package/src/coding/action-gate.test.ts +341 -0
- package/src/coding/action-gate.ts +556 -0
- package/src/config.ts +5 -0
- package/src/contradiction/contradiction-review.ts +50 -4
- package/src/contradiction/contradiction-scan.ts +14 -3
- package/src/contradiction/resolution.ts +50 -2
- package/src/index.ts +4 -3
- package/src/orchestration/recall-rerank-coordinator.ts +123 -4
- package/src/orchestration/recall-result-formatter.ts +6 -2
- package/src/orchestration/recall-search-pipeline.ts +14 -1
- package/src/preferences/drift-config.ts +118 -0
- package/src/preferences/drift-recall.ts +133 -0
- package/src/preferences/drift-types.ts +87 -0
- package/src/preferences/index.ts +12 -0
- package/src/preferences/preference-drift.test.ts +690 -0
- package/src/preferences/preference-drift.ts +724 -0
- package/src/review/review-deck-access.test.ts +325 -0
- package/src/review/review-deck-http-base.ts +133 -0
- package/src/review/review-deck-mutation.test.ts +417 -0
- package/src/review/review-deck-mutation.ts +677 -0
- package/src/review/review-deck-snapshot.ts +196 -0
- package/src/review/review-deck-surface.ts +117 -0
- package/src/review/review-deck.test.ts +347 -0
- package/src/review/review-deck.ts +311 -0
- package/src/storage.ts +4 -6
- package/src/types.ts +7 -3
- package/dist/chunk-35NN3ZFA.js.map +0 -1
- package/dist/chunk-4KYOLI6M.js.map +0 -1
- package/dist/chunk-BWLRUMOG.js.map +0 -1
- package/dist/chunk-J275IYMG.js.map +0 -1
- package/dist/chunk-SB7D4BT7.js.map +0 -1
- package/dist/chunk-SBDCZ2AX.js.map +0 -1
- package/dist/chunk-TF77C7SV.js.map +0 -1
- package/dist/chunk-TZNQUNKL.js.map +0 -1
- package/dist/chunk-V3MXUL3D.js.map +0 -1
- package/dist/chunk-XCTXS7VY.js +0 -402
- package/dist/chunk-XCTXS7VY.js.map +0 -1
- package/dist/chunk-YLDXWCZP.js.map +0 -1
- /package/dist/{chunk-R7JAM2XF.js.map → chunk-2VXWFYJE.js.map} +0 -0
- /package/dist/{chunk-UXO5IMBK.js.map → chunk-4XDGYCZI.js.map} +0 -0
- /package/dist/{chunk-OTHZWLUD.js.map → chunk-57HVIG5U.js.map} +0 -0
- /package/dist/{chunk-EILZG5VC.js.map → chunk-6TAX66IA.js.map} +0 -0
- /package/dist/{chunk-NKKD4ZAU.js.map → chunk-6VALIZKG.js.map} +0 -0
- /package/dist/{chunk-2E36UXVW.js.map → chunk-7KFIMGMP.js.map} +0 -0
- /package/dist/{chunk-LGO6A7GJ.js.map → chunk-7QOO4LGC.js.map} +0 -0
- /package/dist/{chunk-DZUJ46DO.js.map → chunk-AUO2LJ3K.js.map} +0 -0
- /package/dist/{chunk-ZO6AXLEH.js.map → chunk-AYDDB3XI.js.map} +0 -0
- /package/dist/{chunk-NTWN6HB2.js.map → chunk-AYYGRVRP.js.map} +0 -0
- /package/dist/{chunk-7YQ4IYS2.js.map → chunk-AZAA5DNP.js.map} +0 -0
- /package/dist/{chunk-Z7PBQPJ4.js.map → chunk-BQUEAVNW.js.map} +0 -0
- /package/dist/{chunk-5YQ63T4B.js.map → chunk-D27J626P.js.map} +0 -0
- /package/dist/{chunk-LZH5FR2W.js.map → chunk-DHTQP334.js.map} +0 -0
- /package/dist/{chunk-Y7DK7HHJ.js.map → chunk-E4MVQQVX.js.map} +0 -0
- /package/dist/{chunk-JYYBA7TF.js.map → chunk-EIVIB73I.js.map} +0 -0
- /package/dist/{chunk-S2DPMJXH.js.map → chunk-EV3YFLCB.js.map} +0 -0
- /package/dist/{chunk-3I7ASZN3.js.map → chunk-G57LQRP6.js.map} +0 -0
- /package/dist/{chunk-UIN2BWDD.js.map → chunk-GN55KU2P.js.map} +0 -0
- /package/dist/{chunk-PE255F4T.js.map → chunk-GUXS322H.js.map} +0 -0
- /package/dist/{chunk-YB42WZCY.js.map → chunk-IQSC3V2E.js.map} +0 -0
- /package/dist/{chunk-MN4KB2A4.js.map → chunk-MBDJJTAT.js.map} +0 -0
- /package/dist/{chunk-SQI57UCJ.js.map → chunk-MRTUN665.js.map} +0 -0
- /package/dist/{chunk-SPUJNJJC.js.map → chunk-NZWEEALH.js.map} +0 -0
- /package/dist/{chunk-2XDWWPTN.js.map → chunk-OJD4WS2E.js.map} +0 -0
- /package/dist/{chunk-ZWXJBFZU.js.map → chunk-OLWTCWQ2.js.map} +0 -0
- /package/dist/{chunk-XRYZRW54.js.map → chunk-P4DHENRE.js.map} +0 -0
- /package/dist/{chunk-IID2CMUU.js.map → chunk-PDVQ5JU3.js.map} +0 -0
- /package/dist/{chunk-5NM4OH4P.js.map → chunk-QFMO32TO.js.map} +0 -0
- /package/dist/{chunk-SIHSCCUQ.js.map → chunk-QXIQPCCN.js.map} +0 -0
- /package/dist/{chunk-2YI72KM3.js.map → chunk-R47WINCY.js.map} +0 -0
- /package/dist/{chunk-ZQHI2BZB.js.map → chunk-RK4WXUI2.js.map} +0 -0
- /package/dist/{chunk-QOS5LBZN.js.map → chunk-S7Q5CM7E.js.map} +0 -0
- /package/dist/{chunk-GDFVPUJ5.js.map → chunk-TDKSCV62.js.map} +0 -0
- /package/dist/{chunk-OCZIYAE5.js.map → chunk-TYUS5TLG.js.map} +0 -0
- /package/dist/{chunk-GNCCUR6K.js.map → chunk-URHCUXKI.js.map} +0 -0
- /package/dist/{chunk-CT56C22C.js.map → chunk-Z4RPXHJH.js.map} +0 -0
- /package/dist/{contradiction-review-QKJH5DKD.js.map → contradiction-review-WRVLRWHS.js.map} +0 -0
- /package/dist/{contradiction-scan-VOTQRRSX.js.map → contradiction-scan-AKUWPX5N.js.map} +0 -0
- /package/dist/{resolution-MFY72STR.js.map → resolution-4552BNRV.js.map} +0 -0
package/src/access-service.ts
CHANGED
|
@@ -303,6 +303,7 @@ import {
|
|
|
303
303
|
readOfflineSyncFileContentChunk,
|
|
304
304
|
} from "./offline-sync.js";
|
|
305
305
|
import { selfDeps } from "./orchestration/self-deps.js";
|
|
306
|
+
import { ReviewDeckSurface } from "./review/review-deck-surface.js";
|
|
306
307
|
import { formatProfileTraceAscii } from "./profiling.js";
|
|
307
308
|
import { decideDisclosureEscalation } from "./recall-disclosure-escalation.js";
|
|
308
309
|
import { toRecallExplainJson } from "./recall-explain-renderer.js";
|
|
@@ -1243,6 +1244,7 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
1243
1244
|
private readonly corpusWatermarkCache = new CorpusWatermarkCache();
|
|
1244
1245
|
private readonly replicaDivergenceMonitor: ReplicaDivergenceMonitor;
|
|
1245
1246
|
private readonly injectedSupportPassportGatewayRoute: SupportPassportModelRoute | null;
|
|
1247
|
+
readonly reviewDeckEnabled: boolean;
|
|
1246
1248
|
|
|
1247
1249
|
/** AccessObserveWriteSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
1248
1250
|
private _accessObserveWriteSurface: AccessObserveWriteSurface | undefined;
|
|
@@ -1278,6 +1280,17 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
1278
1280
|
return this._accessAdminOpsSurface;
|
|
1279
1281
|
}
|
|
1280
1282
|
|
|
1283
|
+
private _reviewDeckSurface: ReviewDeckSurface | undefined;
|
|
1284
|
+
|
|
1285
|
+
private get reviewDeckSurface(): ReviewDeckSurface {
|
|
1286
|
+
if (!this._reviewDeckSurface) {
|
|
1287
|
+
this._reviewDeckSurface = new ReviewDeckSurface(
|
|
1288
|
+
selfDeps<ConstructorParameters<typeof ReviewDeckSurface>[0]>(this)
|
|
1289
|
+
);
|
|
1290
|
+
}
|
|
1291
|
+
return this._reviewDeckSurface;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1281
1294
|
/** AccessRecallSurface (access-service decomposition). Lazy; selfDeps live wiring. */
|
|
1282
1295
|
private _accessRecallSurface: AccessRecallSurface | undefined;
|
|
1283
1296
|
|
|
@@ -1308,6 +1321,7 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
1308
1321
|
options: {
|
|
1309
1322
|
resolveSecretRef?: ResolveSecretRefFn | null;
|
|
1310
1323
|
supportPassportGatewayRoute?: SupportPassportModelRoute | null;
|
|
1324
|
+
reviewDeckEnabled?: boolean;
|
|
1311
1325
|
} = {}
|
|
1312
1326
|
) {
|
|
1313
1327
|
super();
|
|
@@ -1318,6 +1332,7 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
1318
1332
|
// per-peer `unreachable` (never a throw).
|
|
1319
1333
|
this.replicaDivergenceMonitor = new ReplicaDivergenceMonitor({ resolveSecretRef: options.resolveSecretRef });
|
|
1320
1334
|
this.injectedSupportPassportGatewayRoute = options.supportPassportGatewayRoute ?? null;
|
|
1335
|
+
this.reviewDeckEnabled = options.reviewDeckEnabled === true;
|
|
1321
1336
|
const accessCaps = resolveAccessSetupCapabilities(orchestrator.config); // #1566 Cluster B
|
|
1322
1337
|
this.budget = new CrossNamespaceBudget({
|
|
1323
1338
|
enabled: accessCaps.recallCrossNamespaceBudget,
|
|
@@ -5687,4 +5702,16 @@ export class EngramAccessService extends SupportPassportAccessServiceBase {
|
|
|
5687
5702
|
}) {
|
|
5688
5703
|
return this.accessAdminOpsSurface.adminPromoteMemory(request);
|
|
5689
5704
|
}
|
|
5705
|
+
|
|
5706
|
+
async reviewDeckList(opts: Parameters<ReviewDeckSurface["list"]>[0]) {
|
|
5707
|
+
return this.reviewDeckSurface.list(opts);
|
|
5708
|
+
}
|
|
5709
|
+
|
|
5710
|
+
async reviewDeckAction(...args: Parameters<ReviewDeckSurface["action"]>) {
|
|
5711
|
+
return this.reviewDeckSurface.action(...args);
|
|
5712
|
+
}
|
|
5713
|
+
|
|
5714
|
+
async reviewDeckUndo(...args: Parameters<ReviewDeckSurface["undo"]>) {
|
|
5715
|
+
return this.reviewDeckSurface.undo(...args);
|
|
5716
|
+
}
|
|
5690
5717
|
}
|
|
@@ -170,6 +170,14 @@ function extractMcpDispatchMap(): Map<string, string> {
|
|
|
170
170
|
new URL("./support-passport/mcp-tools.ts", import.meta.url),
|
|
171
171
|
"SUPPORT_PASSPORT_MCP_MIGRATED_OPERATIONS",
|
|
172
172
|
),
|
|
173
|
+
// Third dispatch home (issue #2371): the admin/maintenance tool table
|
|
174
|
+
// contributes its own map fragment, spread into MCP_MIGRATED_OPERATIONS.
|
|
175
|
+
// Every module that can register a dispatch entry must be read here, or
|
|
176
|
+
// this validator reports a false "no dispatch wiring".
|
|
177
|
+
...extractMcpOperationMap(
|
|
178
|
+
new URL("./access-mcp-admin-tools.ts", import.meta.url),
|
|
179
|
+
"MCP_ADMIN_OPS_MIGRATED_OPERATIONS",
|
|
180
|
+
),
|
|
173
181
|
]);
|
|
174
182
|
}
|
|
175
183
|
|
|
@@ -317,6 +325,22 @@ function extractHttpRouteDispatchMap(): Map<string, Set<string>> {
|
|
|
317
325
|
}
|
|
318
326
|
}
|
|
319
327
|
}
|
|
328
|
+
if (/\bawait\s+this\.handleReviewDeckRequest\(/.test(source)) {
|
|
329
|
+
const deckSource = readFileSync(
|
|
330
|
+
new URL("./review/review-deck-http-base.ts", import.meta.url),
|
|
331
|
+
"utf-8",
|
|
332
|
+
);
|
|
333
|
+
const deckRoutes = [
|
|
334
|
+
["GET", "/engram/v1/review/deck", "review_deck_list"],
|
|
335
|
+
["POST", "/engram/v1/review/deck/action", "review_deck_action"],
|
|
336
|
+
["POST", "/engram/v1/review/deck/undo", "review_deck_undo"],
|
|
337
|
+
] as const;
|
|
338
|
+
for (const [method, pathname, operation] of deckRoutes) {
|
|
339
|
+
if (deckSource.includes(`"${pathname}"`) && deckSource.includes(`enforceTokenOp("${operation}")`)) {
|
|
340
|
+
routeOps.set(`${method} ${pathname}`, new Set([operation]));
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
320
344
|
for (const [sourcePath, routes] of [
|
|
321
345
|
["./support-passport/access-http.ts", SUPPORT_PASSPORT_OWNER_HTTP_ROUTES],
|
|
322
346
|
["./support-passport/public-http.ts", SUPPORT_PASSPORT_PUBLIC_HTTP_ROUTES],
|
|
@@ -153,6 +153,7 @@ export const MCP_TOOLS: readonly McpToolEntry[] = [
|
|
|
153
153
|
{ tool: "review_list", operation: "review_list" },
|
|
154
154
|
{ tool: "review_resolve", operation: "review_resolve" },
|
|
155
155
|
{ tool: "contradiction_scan_run", operation: "contradiction_scan_run" },
|
|
156
|
+
{ tool: "preference_drift_scan", operation: "preference_drift_scan" },
|
|
156
157
|
{ tool: "memory_summarize_hourly", operation: "memory_summarize_hourly" },
|
|
157
158
|
{ tool: "conversation_index_update", operation: "conversation_index_update" },
|
|
158
159
|
{ tool: "profiling_report", operation: "profiling_report" },
|
|
@@ -253,6 +254,9 @@ export const HTTP_ROUTES: readonly HttpRouteEntry[] = [
|
|
|
253
254
|
{ method: "GET", pathname: "/engram/v1/procedural/stats", operation: "procedural_stats" },
|
|
254
255
|
{ method: "GET", pathname: "/engram/v1/trust-zones/records", operation: "trust_zones_records" },
|
|
255
256
|
{ method: "POST", pathname: "/engram/v1/review-disposition", operation: "review_disposition" },
|
|
257
|
+
{ method: "GET", pathname: "/engram/v1/review/deck", operation: "review_deck_list" },
|
|
258
|
+
{ method: "POST", pathname: "/engram/v1/review/deck/action", operation: "review_deck_action" },
|
|
259
|
+
{ method: "POST", pathname: "/engram/v1/review/deck/undo", operation: "review_deck_undo" },
|
|
256
260
|
{ method: "POST", pathname: "/engram/v1/trust-zones/promote", operation: "trust_zones_promote" },
|
|
257
261
|
{ method: "POST", pathname: "/engram/v1/trust-zones/demo-seed", operation: "trust_zones_demo_seed" },
|
|
258
262
|
{ method: "POST", pathname: "/v1/citations/observed", operation: "citations_observed" },
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import { recordCausalTrajectory } from "../causal-trajectory.js";
|
|
7
|
+
import type { CodingContext, MemoryFile } from "../types.js";
|
|
8
|
+
import {
|
|
9
|
+
ACTION_GATE_DEFAULTS,
|
|
10
|
+
type ActionGateAuditRecord,
|
|
11
|
+
type ActionGateCandidateSource,
|
|
12
|
+
type ActionGateRequest,
|
|
13
|
+
ActionGateService,
|
|
14
|
+
actionTermsFor,
|
|
15
|
+
createFailureMemoryCandidateSource,
|
|
16
|
+
createTrajectoryCandidateSource,
|
|
17
|
+
isFailureClassMemory,
|
|
18
|
+
parseActionGateConfig,
|
|
19
|
+
} from "./action-gate.js";
|
|
20
|
+
import { PreActionFailureGate, normalizeActionIntent } from "./pre-action-gate.js";
|
|
21
|
+
|
|
22
|
+
const codingContext: CodingContext = {
|
|
23
|
+
projectId: "proj-gate",
|
|
24
|
+
branch: "main",
|
|
25
|
+
rootPath: "/work/project",
|
|
26
|
+
defaultBranch: null,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function memory(id: string, content: string, overrides: Record<string, unknown> = {}): MemoryFile {
|
|
30
|
+
return {
|
|
31
|
+
path: `facts/2026-08-18/${id}.md`,
|
|
32
|
+
content,
|
|
33
|
+
frontmatter: {
|
|
34
|
+
id,
|
|
35
|
+
category: "correction",
|
|
36
|
+
created: "2026-08-18T00:00:00Z",
|
|
37
|
+
updated: "2026-08-18T00:00:00Z",
|
|
38
|
+
source: "test",
|
|
39
|
+
confidence: 0.9,
|
|
40
|
+
confidenceTier: "explicit",
|
|
41
|
+
tags: [],
|
|
42
|
+
status: "active",
|
|
43
|
+
...overrides,
|
|
44
|
+
} as MemoryFile["frontmatter"],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function request(overrides: Partial<ActionGateRequest> = {}): ActionGateRequest {
|
|
49
|
+
return {
|
|
50
|
+
sessionKey: "session-a",
|
|
51
|
+
turnId: "turn-1",
|
|
52
|
+
strategyId: "RUN_CHECK",
|
|
53
|
+
intent: { kind: "command", command: "pnpm", args: ["migrate", "--force"] },
|
|
54
|
+
codingContext,
|
|
55
|
+
memoryDir: "/tmp/does-not-matter",
|
|
56
|
+
...overrides,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function staticSource(id: string, memoryIds: string[]): ActionGateCandidateSource {
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
async find() {
|
|
64
|
+
return {
|
|
65
|
+
ok: true,
|
|
66
|
+
candidates: memoryIds.map((memoryId, index) => ({
|
|
67
|
+
memoryId,
|
|
68
|
+
score: memoryIds.length - index,
|
|
69
|
+
advisoryText: `advisory for ${memoryId}`,
|
|
70
|
+
})),
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
test("parses the actionGate block with safe defaults and zero-limit semantics", () => {
|
|
77
|
+
assert.deepEqual(parseActionGateConfig(undefined), ACTION_GATE_DEFAULTS);
|
|
78
|
+
assert.equal(parseActionGateConfig(undefined).enabled, false);
|
|
79
|
+
// CLI values arrive as strings.
|
|
80
|
+
assert.equal(parseActionGateConfig({ enabled: "false" }).enabled, false);
|
|
81
|
+
assert.equal(parseActionGateConfig({ enabled: "on" }).enabled, true);
|
|
82
|
+
assert.equal(parseActionGateConfig({ maxAdvisoriesPerTurn: "0" }).maxAdvisoriesPerTurn, 0);
|
|
83
|
+
assert.equal(parseActionGateConfig({ timeoutMs: "120" }).timeoutMs, 120);
|
|
84
|
+
assert.equal(parseActionGateConfig({ timeoutMs: 0 }).timeoutMs, 1);
|
|
85
|
+
assert.throws(() => parseActionGateConfig({ enabled: "maybe" }), /actionGate.enabled/);
|
|
86
|
+
assert.throws(() => parseActionGateConfig([]), /must be an object/);
|
|
87
|
+
assert.throws(() => parseActionGateConfig(null), /must be an object/);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("disabled gate performs no lookup on any path", async () => {
|
|
91
|
+
let calls = 0;
|
|
92
|
+
const source: ActionGateCandidateSource = {
|
|
93
|
+
id: "spy",
|
|
94
|
+
async find() {
|
|
95
|
+
calls += 1;
|
|
96
|
+
return { ok: true, candidates: [{ memoryId: "m1", advisoryText: "never" }] };
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const audits: ActionGateAuditRecord[] = [];
|
|
100
|
+
const disabled = new ActionGateService(parseActionGateConfig({}), {
|
|
101
|
+
sources: [source],
|
|
102
|
+
audit: (record) => void audits.push(record),
|
|
103
|
+
});
|
|
104
|
+
const decision = await disabled.evaluate(request());
|
|
105
|
+
assert.equal(decision.status, "DISABLED");
|
|
106
|
+
assert.deepEqual(decision.advisories, []);
|
|
107
|
+
assert.equal(calls, 0);
|
|
108
|
+
assert.deepEqual(disabled.suppressedForTurnStart("session-a"), []);
|
|
109
|
+
disabled.noteTurnStartDelivery("session-a", ["m1"]);
|
|
110
|
+
assert.deepEqual(disabled.suppressedForTurnStart("session-a"), []);
|
|
111
|
+
|
|
112
|
+
const zeroBudget = new ActionGateService(parseActionGateConfig({ enabled: true, maxAdvisoriesPerTurn: 0 }), {
|
|
113
|
+
sources: [source],
|
|
114
|
+
});
|
|
115
|
+
const zeroDecision = await zeroBudget.evaluate(request());
|
|
116
|
+
assert.equal(zeroDecision.status, "DISABLED");
|
|
117
|
+
assert.match(zeroDecision.reason ?? "", /maxAdvisoriesPerTurn is 0/);
|
|
118
|
+
assert.equal(calls, 0);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("delivers one bounded advisory and suppresses it from turn-start recall", async () => {
|
|
122
|
+
const audits: ActionGateAuditRecord[] = [];
|
|
123
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true }), {
|
|
124
|
+
sources: [
|
|
125
|
+
createFailureMemoryCandidateSource({
|
|
126
|
+
async listMemories() {
|
|
127
|
+
return [
|
|
128
|
+
memory("mem-match", "Running pnpm migrate --force dropped the dev database."),
|
|
129
|
+
memory("mem-other", "Unrelated note about documentation."),
|
|
130
|
+
memory("mem-archived", "pnpm migrate --force failed again", { status: "archived" }),
|
|
131
|
+
];
|
|
132
|
+
},
|
|
133
|
+
}),
|
|
134
|
+
],
|
|
135
|
+
audit: (record) => void audits.push(record),
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
const decision = await service.evaluate(request());
|
|
139
|
+
assert.equal(decision.status, "MATCH_WARN");
|
|
140
|
+
assert.equal(decision.advisories.length, 1);
|
|
141
|
+
assert.equal(decision.advisories[0].memoryId, "mem-match");
|
|
142
|
+
assert.equal(decision.advisories[0].sourceId, "failure-memory");
|
|
143
|
+
assert.match(decision.advisories[0].text, /dropped the dev database/);
|
|
144
|
+
assert.ok(decision.advisories[0].text.length <= 400);
|
|
145
|
+
assert.deepEqual(decision.degradations, []);
|
|
146
|
+
|
|
147
|
+
// Double-delivery suppression: turn-start recall must skip what the gate sent.
|
|
148
|
+
assert.deepEqual(service.suppressedForTurnStart("session-a"), ["mem-match"]);
|
|
149
|
+
|
|
150
|
+
// Same turn, same action: deduplicated per fact per turn.
|
|
151
|
+
const repeat = await service.evaluate(request());
|
|
152
|
+
assert.deepEqual(repeat.advisories, []);
|
|
153
|
+
assert.deepEqual(repeat.suppressedIds, ["mem-match"]);
|
|
154
|
+
assert.equal(repeat.status, "NO_MATCH");
|
|
155
|
+
|
|
156
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
157
|
+
assert.equal(audits.length, 2);
|
|
158
|
+
assert.deepEqual(audits[0].deliveredIds, ["mem-match"]);
|
|
159
|
+
assert.deepEqual(audits[1].suppressedIds, ["mem-match"]);
|
|
160
|
+
assert.match(audits[0].fingerprint ?? "", /^v1:sha256:/);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test("skips candidates turn-start recall already delivered", async () => {
|
|
164
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true }), {
|
|
165
|
+
sources: [staticSource("static", ["mem-a"])],
|
|
166
|
+
});
|
|
167
|
+
service.noteTurnStartDelivery("session-a", ["mem-a"]);
|
|
168
|
+
const decision = await service.evaluate(request());
|
|
169
|
+
assert.equal(decision.status, "NO_MATCH");
|
|
170
|
+
assert.deepEqual(decision.suppressedIds, ["mem-a"]);
|
|
171
|
+
assert.deepEqual(decision.advisories, []);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
test("caps advisories per turn and resets the budget on the next turn", async () => {
|
|
175
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true, maxAdvisoriesPerTurn: 2 }), {
|
|
176
|
+
sources: [staticSource("static", ["mem-a", "mem-b", "mem-c"])],
|
|
177
|
+
});
|
|
178
|
+
const first = await service.evaluate(request());
|
|
179
|
+
assert.deepEqual(
|
|
180
|
+
first.advisories.map((advisory) => advisory.memoryId),
|
|
181
|
+
["mem-a", "mem-b"]
|
|
182
|
+
);
|
|
183
|
+
assert.deepEqual(first.suppressedIds, ["mem-c"]);
|
|
184
|
+
|
|
185
|
+
const nextTurn = await service.evaluate(request({ turnId: "turn-2" }));
|
|
186
|
+
// A new turn re-arms the budget: proposing the same action again warns again,
|
|
187
|
+
// which is the whole point of action-site delivery.
|
|
188
|
+
assert.deepEqual(
|
|
189
|
+
nextTurn.advisories.map((advisory) => advisory.memoryId),
|
|
190
|
+
["mem-a", "mem-b"]
|
|
191
|
+
);
|
|
192
|
+
assert.deepEqual(nextTurn.suppressedIds, ["mem-c"]);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("namespace scoping keeps advisories inside the requesting principal", async () => {
|
|
196
|
+
const byNamespace: Record<string, MemoryFile[]> = {
|
|
197
|
+
"tenant-a": [memory("mem-a", "pnpm migrate --force wiped tenant a data")],
|
|
198
|
+
"tenant-b": [memory("mem-b", "pnpm migrate --force wiped tenant b data")],
|
|
199
|
+
};
|
|
200
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true }), {
|
|
201
|
+
sources: [
|
|
202
|
+
createFailureMemoryCandidateSource({
|
|
203
|
+
async listMemories({ namespace }) {
|
|
204
|
+
return byNamespace[namespace ?? ""] ?? [];
|
|
205
|
+
},
|
|
206
|
+
}),
|
|
207
|
+
],
|
|
208
|
+
});
|
|
209
|
+
const a = await service.evaluate(request({ sessionKey: "s-a", namespace: "tenant-a" }));
|
|
210
|
+
const b = await service.evaluate(request({ sessionKey: "s-b", namespace: "tenant-b" }));
|
|
211
|
+
assert.deepEqual(
|
|
212
|
+
a.advisories.map((advisory) => advisory.memoryId),
|
|
213
|
+
["mem-a"]
|
|
214
|
+
);
|
|
215
|
+
assert.deepEqual(
|
|
216
|
+
b.advisories.map((advisory) => advisory.memoryId),
|
|
217
|
+
["mem-b"]
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
test("source failure fails open with a distinct status and audit degradation", async () => {
|
|
222
|
+
const audits: ActionGateAuditRecord[] = [];
|
|
223
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true }), {
|
|
224
|
+
sources: [
|
|
225
|
+
{
|
|
226
|
+
id: "broken",
|
|
227
|
+
async find() {
|
|
228
|
+
throw new Error("store unreadable");
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
],
|
|
232
|
+
audit: (record) => void audits.push(record),
|
|
233
|
+
});
|
|
234
|
+
const decision = await service.evaluate(request());
|
|
235
|
+
assert.equal(decision.status, "ERROR_FAIL_OPEN");
|
|
236
|
+
assert.deepEqual(decision.advisories, []);
|
|
237
|
+
assert.match(decision.degradations[0], /broken: store unreadable/);
|
|
238
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
239
|
+
assert.equal(audits[0].status, "ERROR_FAIL_OPEN");
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test("an over-deadline source fails open instead of delaying the action", async () => {
|
|
243
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true, timeoutMs: 5 }), {
|
|
244
|
+
sources: [
|
|
245
|
+
{
|
|
246
|
+
id: "slow",
|
|
247
|
+
find() {
|
|
248
|
+
return new Promise((resolve) =>
|
|
249
|
+
setTimeout(() => resolve({ ok: true, candidates: [{ memoryId: "late", advisoryText: "late" }] }), 200)
|
|
250
|
+
);
|
|
251
|
+
},
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
});
|
|
255
|
+
const startedAt = Date.now();
|
|
256
|
+
const decision = await service.evaluate(request());
|
|
257
|
+
assert.ok(Date.now() - startedAt < 150, "gate must not wait for the slow source");
|
|
258
|
+
assert.equal(decision.status, "ERROR_FAIL_OPEN");
|
|
259
|
+
assert.match(decision.degradations[0], /timed out after 5ms/);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("an invalid action intent fails open rather than throwing", async () => {
|
|
263
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true }), {
|
|
264
|
+
sources: [staticSource("static", ["mem-a"])],
|
|
265
|
+
});
|
|
266
|
+
const decision = await service.evaluate(
|
|
267
|
+
request({ intent: { kind: "edit", filePath: "/elsewhere/secret.ts", editKind: "update" } })
|
|
268
|
+
);
|
|
269
|
+
assert.equal(decision.status, "ERROR_FAIL_OPEN");
|
|
270
|
+
assert.match(decision.reason ?? "", /contained/);
|
|
271
|
+
assert.deepEqual(decision.advisories, []);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("trajectory source surfaces a recorded failure at the action site", async () => {
|
|
275
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-action-gate-"));
|
|
276
|
+
try {
|
|
277
|
+
const intent = { kind: "command" as const, command: "pnpm", args: ["migrate", "--force"] };
|
|
278
|
+
await recordCausalTrajectory({
|
|
279
|
+
memoryDir,
|
|
280
|
+
record: {
|
|
281
|
+
schemaVersion: 1,
|
|
282
|
+
trajectoryId: "traj-failure",
|
|
283
|
+
recordedAt: "2026-08-17T12:00:00Z",
|
|
284
|
+
sessionKey: "historical-session",
|
|
285
|
+
goal: "Migrate the database",
|
|
286
|
+
actionSummary: "Ran the forced migration",
|
|
287
|
+
observationSummary: "The migration destroyed local data",
|
|
288
|
+
outcomeKind: "failure",
|
|
289
|
+
outcomeSummary: "Dev database dropped",
|
|
290
|
+
followUpSummary: "Take a snapshot before migrating",
|
|
291
|
+
codingContext: { projectId: codingContext.projectId, branch: "main" },
|
|
292
|
+
actionIdentity: {
|
|
293
|
+
fingerprintVersion: 1,
|
|
294
|
+
fingerprint: normalizeActionIntent(intent, "RUN_CHECK", codingContext).fingerprint,
|
|
295
|
+
strategyId: "RUN_CHECK",
|
|
296
|
+
},
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
const service = new ActionGateService(parseActionGateConfig({ enabled: true, timeoutMs: 2000 }), {
|
|
300
|
+
sources: [createTrajectoryCandidateSource(new PreActionFailureGate({ timeoutMs: 1000 }))],
|
|
301
|
+
});
|
|
302
|
+
const decision = await service.evaluate(request({ intent, memoryDir }));
|
|
303
|
+
assert.equal(decision.status, "MATCH_WARN");
|
|
304
|
+
assert.equal(decision.advisories[0].memoryId, "traj-failure");
|
|
305
|
+
assert.equal(decision.advisories[0].sourceId, "causal-trajectory");
|
|
306
|
+
assert.match(decision.advisories[0].text, /Dev database dropped/);
|
|
307
|
+
|
|
308
|
+
const unrelated = await service.evaluate(
|
|
309
|
+
request({
|
|
310
|
+
turnId: "turn-2",
|
|
311
|
+
intent: { kind: "command", command: "pnpm", args: ["build"] },
|
|
312
|
+
memoryDir,
|
|
313
|
+
})
|
|
314
|
+
);
|
|
315
|
+
assert.equal(unrelated.status, "NO_MATCH");
|
|
316
|
+
} finally {
|
|
317
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
test("failure-class detection and action terms stay deterministic", () => {
|
|
322
|
+
assert.equal(isFailureClassMemory(memory("m", "x")), true);
|
|
323
|
+
assert.equal(isFailureClassMemory(memory("m", "x", { category: "fact" })), false);
|
|
324
|
+
assert.equal(
|
|
325
|
+
isFailureClassMemory(memory("m", "x", { category: "procedure", structuredAttributes: { needsRepair: "true" } })),
|
|
326
|
+
true
|
|
327
|
+
);
|
|
328
|
+
assert.equal(isFailureClassMemory(memory("m", "x", { category: "fact", mw_fail: 3, mw_success: 1 })), true);
|
|
329
|
+
assert.equal(isFailureClassMemory(memory("m", "x", { category: "fact", mw_fail: 1, mw_success: 4 })), false);
|
|
330
|
+
assert.equal(isFailureClassMemory(memory("m", "x", { status: "pending_review" })), false);
|
|
331
|
+
|
|
332
|
+
assert.deepEqual(actionTermsFor({ kind: "command", command: "pnpm", args: ["migrate", "-f", "migrate"] }), [
|
|
333
|
+
"pnpm",
|
|
334
|
+
"migrate",
|
|
335
|
+
]);
|
|
336
|
+
assert.deepEqual(actionTermsFor({ kind: "edit", filePath: "src/config.ts", editKind: "update" }), [
|
|
337
|
+
"src",
|
|
338
|
+
"config.ts",
|
|
339
|
+
"update",
|
|
340
|
+
]);
|
|
341
|
+
});
|