@remnic/core 9.65.2 → 9.65.4
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 +21 -19
- package/dist/access-authorization-probe.d.ts +38 -38
- package/dist/access-authorization-probe.js +22 -20
- package/dist/access-boundary.d.ts +40 -40
- package/dist/access-boundary.js +21 -19
- package/dist/access-cli.js +62 -60
- package/dist/access-cli.js.map +1 -1
- 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 +21 -19
- 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 +23 -21
- package/dist/access-http.d.ts +51 -44
- package/dist/access-http.js +37 -35
- package/dist/access-identity-continuity-surface.d.ts +12 -12
- package/dist/access-identity-continuity-surface.js +21 -19
- package/dist/access-lcm-surface.d.ts +27 -27
- package/dist/access-lcm-surface.js +21 -19
- 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 +31 -29
- package/dist/access-memory-search-fanout.d.ts +4 -2
- package/dist/{access-namespace-preflight-Dhvcl-T0.d.ts → access-namespace-preflight-D_6mo8ms.d.ts} +1 -1
- package/dist/access-namespace-preflight.d.ts +5 -3
- package/dist/access-namespace-preflight.js +21 -19
- package/dist/access-observe-write-surface.d.ts +39 -39
- package/dist/access-observe-write-surface.js +21 -19
- package/dist/access-offline-manifest.d.ts +12 -12
- package/dist/access-offline-manifest.js +3 -3
- package/dist/access-operations-batch.js +25 -23
- package/dist/access-operations.d.ts +40 -40
- package/dist/access-operations.js +28 -26
- package/dist/access-recall-concurrency.d.ts +40 -40
- package/dist/access-recall-concurrency.js +21 -19
- package/dist/access-recall-response.d.ts +24 -24
- package/dist/access-recall-response.js +21 -19
- package/dist/access-recall-surface.d.ts +24 -24
- package/dist/access-recall-surface.js +21 -19
- package/dist/access-schema.d.ts +45 -45
- package/dist/{access-service-Bke1alZO.d.ts → access-service-DqPa3hy4.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 +21 -19
- package/dist/access-surface-catalog.d.ts +40 -40
- package/dist/access-surface-catalog.js +27 -21
- 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 +10 -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/{auto-sync-H64ZCNIR.js → auto-sync-XVMLL2RH.js} +5 -5
- 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 +4 -4
- 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-DO_7zfkv.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 +12 -9
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/chunk-236PXYG7.js +232 -0
- package/dist/chunk-236PXYG7.js.map +1 -0
- package/dist/{chunk-YB42WZCY.js → chunk-2IXQSGCU.js} +2 -2
- package/dist/{chunk-PE255F4T.js → chunk-2MVTAIL3.js} +2 -2
- package/dist/{chunk-LGO6A7GJ.js → chunk-3JZBPTLD.js} +338 -80
- package/dist/chunk-3JZBPTLD.js.map +1 -0
- package/dist/{chunk-GDFVPUJ5.js → chunk-3NH3VP3U.js} +2 -2
- 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-GNCCUR6K.js → chunk-AXGFOFNY.js} +2 -2
- package/dist/{chunk-SB7D4BT7.js → chunk-AZLLH6YA.js} +1554 -114
- package/dist/chunk-AZLLH6YA.js.map +1 -0
- package/dist/{chunk-5YQ63T4B.js → chunk-BK5G2MHO.js} +2 -2
- package/dist/{chunk-LZH5FR2W.js → chunk-CQBIN77D.js} +2 -2
- package/dist/{chunk-35NN3ZFA.js → chunk-CTVWELNK.js} +21 -3
- package/dist/chunk-CTVWELNK.js.map +1 -0
- package/dist/{chunk-NKKD4ZAU.js → chunk-DORFF5N5.js} +2 -2
- package/dist/{chunk-BWLRUMOG.js → chunk-DPNXADEI.js} +441 -2
- package/dist/chunk-DPNXADEI.js.map +1 -0
- package/dist/{chunk-SQI57UCJ.js → chunk-DUEDOYZD.js} +2 -2
- package/dist/{chunk-5NM4OH4P.js → chunk-DUZARALI.js} +3 -3
- package/dist/{chunk-2E36UXVW.js → chunk-ECLJ4LA2.js} +2 -2
- package/dist/{chunk-TZNQUNKL.js → chunk-FC7TIRFS.js} +15 -1
- package/dist/chunk-FC7TIRFS.js.map +1 -0
- package/dist/{chunk-IID2CMUU.js → chunk-GHD2LLG4.js} +2 -2
- package/dist/{chunk-ZQHI2BZB.js → chunk-HF5BUTI6.js} +2 -2
- package/dist/{chunk-3DVBKTSO.js → chunk-HSZMX3ZJ.js} +4 -4
- package/dist/{chunk-S2DPMJXH.js → chunk-I23ZHYSL.js} +2 -2
- package/dist/{chunk-ODZG724P.js → chunk-I2HTKOOP.js} +2 -2
- package/dist/chunk-I32NKXE2.js +879 -0
- package/dist/chunk-I32NKXE2.js.map +1 -0
- package/dist/{chunk-NTWN6HB2.js → chunk-IURMJBGP.js} +2 -2
- package/dist/{chunk-OCZIYAE5.js → chunk-IWKGOCL6.js} +3 -3
- package/dist/{chunk-UXO5IMBK.js → chunk-J3ATBB7M.js} +2 -2
- package/dist/{chunk-Y7DK7HHJ.js → chunk-JPAKBNTM.js} +2 -2
- package/dist/{chunk-SPUJNJJC.js → chunk-KFIOPZ25.js} +2 -2
- package/dist/{chunk-JYYBA7TF.js → chunk-KOO37E4Y.js} +2 -2
- package/dist/{chunk-OTHZWLUD.js → chunk-KPB2QHJZ.js} +2 -2
- package/dist/{chunk-SBDCZ2AX.js → chunk-LBFFNDFM.js} +1 -1
- package/dist/chunk-LBFFNDFM.js.map +1 -0
- package/dist/{chunk-CT56C22C.js → chunk-LYBIHM4N.js} +4 -4
- package/dist/{chunk-3I7ASZN3.js → chunk-MFOSZUIT.js} +2 -2
- package/dist/{chunk-DZUJ46DO.js → chunk-NLEH4RTB.js} +2 -2
- package/dist/{chunk-ZO6AXLEH.js → chunk-OCCHUEZB.js} +2 -2
- package/dist/{chunk-EILZG5VC.js → chunk-OU34IQXV.js} +2 -2
- package/dist/{chunk-2XDWWPTN.js → chunk-OZDFB22S.js} +2 -2
- package/dist/{chunk-UIN2BWDD.js → chunk-PTZQYCJ4.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-Z7PBQPJ4.js → chunk-QJW4MZSW.js} +2 -2
- package/dist/{chunk-R7JAM2XF.js → chunk-R2MZCYA6.js} +3 -3
- package/dist/{chunk-TF77C7SV.js → chunk-SR5LNI6Q.js} +7 -5
- package/dist/chunk-SR5LNI6Q.js.map +1 -0
- package/dist/{chunk-LBWQ65SX.js → chunk-T42L3S6A.js} +4 -4
- package/dist/{chunk-J275IYMG.js → chunk-THVI4Y7X.js} +34 -7
- package/dist/chunk-THVI4Y7X.js.map +1 -0
- package/dist/{chunk-QOS5LBZN.js → chunk-TJFI3K2O.js} +15 -3
- package/dist/chunk-TJFI3K2O.js.map +1 -0
- package/dist/{chunk-2YI72KM3.js → chunk-UCKG36HO.js} +2 -2
- package/dist/{chunk-SIHSCCUQ.js → chunk-UFR6HX7A.js} +1 -1
- package/dist/{chunk-CDUUDBWJ.js → chunk-VFYRYFLL.js} +2 -2
- package/dist/{chunk-XRYZRW54.js → chunk-WDXD6ITO.js} +2 -2
- package/dist/{chunk-4KYOLI6M.js → chunk-XGM3VQWG.js} +120 -14
- package/dist/chunk-XGM3VQWG.js.map +1 -0
- package/dist/{chunk-MN4KB2A4.js → chunk-YDKF4MSJ.js} +3 -3
- package/dist/{chunk-YLDXWCZP.js → chunk-YHGCT462.js} +14 -9
- package/dist/chunk-YHGCT462.js.map +1 -0
- package/dist/{chunk-7YQ4IYS2.js → chunk-YOXVZJFM.js} +2 -2
- package/dist/{chunk-ZWXJBFZU.js → chunk-YZJM6CLF.js} +8 -8
- package/dist/chunk-ZCUTSMR2.js +61 -0
- package/dist/chunk-ZCUTSMR2.js.map +1 -0
- package/dist/{chunk-LUNJ3WFO.js → chunk-ZK4BFABK.js} +4 -4
- package/dist/{chunk-V3MXUL3D.js → chunk-ZPOHEB5Z.js} +329 -653
- package/dist/chunk-ZPOHEB5Z.js.map +1 -0
- package/dist/{chunk-RDFF2NAU.js → chunk-ZXBTTMGZ.js} +184 -88
- package/dist/chunk-ZXBTTMGZ.js.map +1 -0
- package/dist/{cli-cShQ13XG.d.ts → cli-DO3i14pM.d.ts} +5 -5
- package/dist/cli.d.ts +25 -25
- package/dist/cli.js +51 -48
- package/dist/coding/pre-action-gate.d.ts +2 -60
- package/dist/compounding/engine.d.ts +4 -2
- package/dist/compounding/engine.js +4 -4
- 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 +10 -1
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +8 -5
- package/dist/connectors/codex-materialize.d.ts +16 -1
- package/dist/connectors/codex-materialize.js +10 -1
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +8 -5
- 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 +12 -7
- 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 +6 -6
- 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 +6 -6
- 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-D23_x-s5.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 +4 -4
- 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/explicit-capture.js +1 -1
- package/dist/external-wiki-access.d.ts +40 -40
- package/dist/external-wiki-access.js +22 -20
- 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-judge.js +2 -2
- 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 +9 -7
- 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--QhGIXF2.d.ts +284 -0
- package/dist/index.d.ts +314 -45
- package/dist/index.js +163 -88
- 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 +4 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -4
- package/dist/maintenance/rebuild-memory-projection.d.ts +4 -2
- package/dist/maintenance/rebuild-memory-projection.js +5 -5
- package/dist/{maintenance-jhMpeGne.d.ts → maintenance-PFvY1Pw_.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 +5 -5
- 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 +4 -4
- 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 +7 -7
- package/dist/operator-doctor-replica.d.ts +3 -1
- package/dist/operator-toolkit.d.ts +5 -3
- package/dist/operator-toolkit.js +19 -13
- package/dist/orchestration/compression-guideline-coordinator.d.ts +4 -2
- package/dist/orchestration/maintenance.d.ts +6 -4
- package/dist/orchestration/maintenance.js +10 -10
- package/dist/{orchestrator-DyGUC7re.d.ts → orchestrator-4wzJrPVm.d.ts} +23 -9
- package/dist/orchestrator.d.ts +12 -12
- package/dist/orchestrator.js +62 -60
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-C25Oxtp1.d.ts → pipeline-CgXgdIrF.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-DhIXYBYI.d.ts} +1 -1
- package/dist/{qmd-DkDVCbgF.d.ts → qmd-BppGGxsi.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/manifest.js +2 -2
- 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} +14 -4
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resume-bundles.js +8 -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/salvage-envelope.js +1 -1
- package/dist/schemas.d.ts +44 -44
- package/dist/{scope-profiles-B9xMoFO-.d.ts → scope-profiles-ChZUtxDU.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-mSPwQSmF.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +9 -6
- package/dist/semantic-rule-promotion.js +4 -4
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +4 -4
- package/dist/{service-DCZDZNcV.d.ts → service-BICWLwSP.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/skills-registry.js +4 -56
- package/dist/skills-registry.js.map +1 -1
- package/dist/source-agent-qualifier.d.ts +3 -1
- package/dist/source-agent-qualifier.js +8 -5
- package/dist/{storage-CcKmEjL8.d.ts → storage-B7urx1K3.d.ts} +1 -1
- package/dist/storage.d.ts +4 -2
- package/dist/storage.js +6 -6
- 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 +24 -22
- 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-ETU5N6nB.d.ts} +433 -7
- 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 +4 -4
- package/dist/who-knows-cli.d.ts +40 -40
- package/dist/who-knows-cli.js +5 -5
- package/dist/who-knows.d.ts +42 -42
- package/dist/who-knows.js +4 -4
- package/dist/write-envelope.d.ts +3 -1
- package/dist/write-envelope.js +1 -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/cli/skills-commands.ts +150 -0
- package/src/cli.ts +4 -2
- package/src/coding/action-gate.test.ts +341 -0
- package/src/coding/action-gate.ts +556 -0
- package/src/config.ts +9 -2
- package/src/connectors/codex-materialize-runner.ts +16 -0
- package/src/connectors/codex-materialize-skills.test.ts +141 -0
- package/src/connectors/codex-materialize.ts +58 -40
- package/src/connectors/materialize-paths.ts +50 -0
- package/src/connectors/materialize-skills.ts +127 -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 +9 -13
- 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/procedural/skill-io.test.ts +190 -0
- package/src/procedural/skill-io.ts +220 -0
- package/src/procedural/skill-projection.test.ts +214 -0
- package/src/procedural/skill-projection.ts +356 -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 +9 -6
- 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-LGO6A7GJ.js.map +0 -1
- package/dist/chunk-QOS5LBZN.js.map +0 -1
- package/dist/chunk-RDFF2NAU.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/{auto-sync-H64ZCNIR.js.map → auto-sync-XVMLL2RH.js.map} +0 -0
- /package/dist/{chunk-YB42WZCY.js.map → chunk-2IXQSGCU.js.map} +0 -0
- /package/dist/{chunk-PE255F4T.js.map → chunk-2MVTAIL3.js.map} +0 -0
- /package/dist/{chunk-GDFVPUJ5.js.map → chunk-3NH3VP3U.js.map} +0 -0
- /package/dist/{chunk-GNCCUR6K.js.map → chunk-AXGFOFNY.js.map} +0 -0
- /package/dist/{chunk-5YQ63T4B.js.map → chunk-BK5G2MHO.js.map} +0 -0
- /package/dist/{chunk-LZH5FR2W.js.map → chunk-CQBIN77D.js.map} +0 -0
- /package/dist/{chunk-NKKD4ZAU.js.map → chunk-DORFF5N5.js.map} +0 -0
- /package/dist/{chunk-SQI57UCJ.js.map → chunk-DUEDOYZD.js.map} +0 -0
- /package/dist/{chunk-5NM4OH4P.js.map → chunk-DUZARALI.js.map} +0 -0
- /package/dist/{chunk-2E36UXVW.js.map → chunk-ECLJ4LA2.js.map} +0 -0
- /package/dist/{chunk-IID2CMUU.js.map → chunk-GHD2LLG4.js.map} +0 -0
- /package/dist/{chunk-ZQHI2BZB.js.map → chunk-HF5BUTI6.js.map} +0 -0
- /package/dist/{chunk-3DVBKTSO.js.map → chunk-HSZMX3ZJ.js.map} +0 -0
- /package/dist/{chunk-S2DPMJXH.js.map → chunk-I23ZHYSL.js.map} +0 -0
- /package/dist/{chunk-ODZG724P.js.map → chunk-I2HTKOOP.js.map} +0 -0
- /package/dist/{chunk-NTWN6HB2.js.map → chunk-IURMJBGP.js.map} +0 -0
- /package/dist/{chunk-OCZIYAE5.js.map → chunk-IWKGOCL6.js.map} +0 -0
- /package/dist/{chunk-UXO5IMBK.js.map → chunk-J3ATBB7M.js.map} +0 -0
- /package/dist/{chunk-Y7DK7HHJ.js.map → chunk-JPAKBNTM.js.map} +0 -0
- /package/dist/{chunk-SPUJNJJC.js.map → chunk-KFIOPZ25.js.map} +0 -0
- /package/dist/{chunk-JYYBA7TF.js.map → chunk-KOO37E4Y.js.map} +0 -0
- /package/dist/{chunk-OTHZWLUD.js.map → chunk-KPB2QHJZ.js.map} +0 -0
- /package/dist/{chunk-CT56C22C.js.map → chunk-LYBIHM4N.js.map} +0 -0
- /package/dist/{chunk-3I7ASZN3.js.map → chunk-MFOSZUIT.js.map} +0 -0
- /package/dist/{chunk-DZUJ46DO.js.map → chunk-NLEH4RTB.js.map} +0 -0
- /package/dist/{chunk-ZO6AXLEH.js.map → chunk-OCCHUEZB.js.map} +0 -0
- /package/dist/{chunk-EILZG5VC.js.map → chunk-OU34IQXV.js.map} +0 -0
- /package/dist/{chunk-2XDWWPTN.js.map → chunk-OZDFB22S.js.map} +0 -0
- /package/dist/{chunk-UIN2BWDD.js.map → chunk-PTZQYCJ4.js.map} +0 -0
- /package/dist/{chunk-Z7PBQPJ4.js.map → chunk-QJW4MZSW.js.map} +0 -0
- /package/dist/{chunk-R7JAM2XF.js.map → chunk-R2MZCYA6.js.map} +0 -0
- /package/dist/{chunk-LBWQ65SX.js.map → chunk-T42L3S6A.js.map} +0 -0
- /package/dist/{chunk-2YI72KM3.js.map → chunk-UCKG36HO.js.map} +0 -0
- /package/dist/{chunk-SIHSCCUQ.js.map → chunk-UFR6HX7A.js.map} +0 -0
- /package/dist/{chunk-CDUUDBWJ.js.map → chunk-VFYRYFLL.js.map} +0 -0
- /package/dist/{chunk-XRYZRW54.js.map → chunk-WDXD6ITO.js.map} +0 -0
- /package/dist/{chunk-MN4KB2A4.js.map → chunk-YDKF4MSJ.js.map} +0 -0
- /package/dist/{chunk-7YQ4IYS2.js.map → chunk-YOXVZJFM.js.map} +0 -0
- /package/dist/{chunk-ZWXJBFZU.js.map → chunk-YZJM6CLF.js.map} +0 -0
- /package/dist/{chunk-LUNJ3WFO.js.map → chunk-ZK4BFABK.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
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill-bundle section of the Codex materializer (issue #2369).
|
|
3
|
+
*
|
|
4
|
+
* Synthetic fixtures only — never real user data.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import test from "node:test";
|
|
8
|
+
import assert from "node:assert/strict";
|
|
9
|
+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
10
|
+
import os from "node:os";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
ensureSentinel,
|
|
15
|
+
materializeForNamespace,
|
|
16
|
+
SENTINEL_FILE,
|
|
17
|
+
} from "./codex-materialize.js";
|
|
18
|
+
import { parseProcedureStepsFromBody } from "../procedural/procedure-types.js";
|
|
19
|
+
import { parseSkillBundle, projectProceduresToSkills } from "../procedural/skill-projection.js";
|
|
20
|
+
import type { MemoryFile } from "../types.js";
|
|
21
|
+
|
|
22
|
+
function makeProcedure(id: string, title: string, updated = "2026-08-18T00:00:00Z"): MemoryFile {
|
|
23
|
+
return {
|
|
24
|
+
path: `/tmp/remnic-test/procedures/${id}.md`,
|
|
25
|
+
frontmatter: {
|
|
26
|
+
id,
|
|
27
|
+
category: "procedure",
|
|
28
|
+
created: "2026-08-18T00:00:00Z",
|
|
29
|
+
updated,
|
|
30
|
+
source: "procedure-miner",
|
|
31
|
+
confidence: 0.8,
|
|
32
|
+
confidenceTier: "implied",
|
|
33
|
+
tags: [],
|
|
34
|
+
} as MemoryFile["frontmatter"],
|
|
35
|
+
content: [title, "", "## Step 1", "", "Read the plan.", "", "## Step 2", "", "Apply the change.", ""].join("\n"),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function makeTempCodexHome(): { root: string; memoriesDir: string } {
|
|
40
|
+
const root = mkdtempSync(path.join(os.tmpdir(), "codex-materialize-skills-"));
|
|
41
|
+
const memoriesDir = path.join(root, "memories");
|
|
42
|
+
mkdirSync(memoriesDir, { recursive: true });
|
|
43
|
+
return { root, memoriesDir };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test("writes skills/<slug>/SKILL.md whose body round-trips to the same steps", () => {
|
|
47
|
+
const { root, memoriesDir } = makeTempCodexHome();
|
|
48
|
+
try {
|
|
49
|
+
ensureSentinel(memoriesDir, "synthetic-ns", new Date("2026-08-18T00:00:00Z"));
|
|
50
|
+
const memories = [makeProcedure("procedure-1", "Ship a focused change")];
|
|
51
|
+
const skills = projectProceduresToSkills(memories);
|
|
52
|
+
|
|
53
|
+
const result = materializeForNamespace("synthetic-ns", { memories, codexHome: root, skills });
|
|
54
|
+
assert.equal(result.wrote, true);
|
|
55
|
+
assert.ok(result.filesWritten.includes(path.join("skills", "ship-a-focused-change", "SKILL.md")));
|
|
56
|
+
|
|
57
|
+
const skillPath = path.join(memoriesDir, "skills", "ship-a-focused-change", "SKILL.md");
|
|
58
|
+
const parsed = parseSkillBundle(readFileSync(skillPath, "utf-8"), "ship-a-focused-change");
|
|
59
|
+
assert.ok(parsed);
|
|
60
|
+
assert.deepEqual(parsed.steps, parseProcedureStepsFromBody(memories[0].content));
|
|
61
|
+
assert.equal(parsed.provenance.memoryId, "procedure-1");
|
|
62
|
+
|
|
63
|
+
const sentinel = JSON.parse(readFileSync(path.join(memoriesDir, SENTINEL_FILE), "utf-8")) as {
|
|
64
|
+
projected_skills?: string[];
|
|
65
|
+
};
|
|
66
|
+
assert.deepEqual(sentinel.projected_skills, ["ship-a-focused-change"]);
|
|
67
|
+
} finally {
|
|
68
|
+
rmSync(root, { recursive: true, force: true });
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test("re-running with unchanged procedures is a hash no-op", () => {
|
|
73
|
+
const { root, memoriesDir } = makeTempCodexHome();
|
|
74
|
+
try {
|
|
75
|
+
ensureSentinel(memoriesDir, "synthetic-ns", new Date("2026-08-18T00:00:00Z"));
|
|
76
|
+
const memories = [makeProcedure("procedure-1", "Ship a focused change")];
|
|
77
|
+
const skills = projectProceduresToSkills(memories);
|
|
78
|
+
|
|
79
|
+
const first = materializeForNamespace("synthetic-ns", { memories, codexHome: root, skills });
|
|
80
|
+
assert.equal(first.wrote, true);
|
|
81
|
+
const second = materializeForNamespace("synthetic-ns", { memories, codexHome: root, skills });
|
|
82
|
+
assert.equal(second.wrote, false);
|
|
83
|
+
assert.equal(second.skippedIdempotent, true);
|
|
84
|
+
assert.deepEqual(second.filesWritten, []);
|
|
85
|
+
assert.ok(existsSync(path.join(memoriesDir, "skills", "ship-a-focused-change", "SKILL.md")));
|
|
86
|
+
} finally {
|
|
87
|
+
rmSync(root, { recursive: true, force: true });
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("retiring a procedure removes its projected folder and leaves hand-created folders alone", () => {
|
|
92
|
+
const { root, memoriesDir } = makeTempCodexHome();
|
|
93
|
+
try {
|
|
94
|
+
ensureSentinel(memoriesDir, "synthetic-ns", new Date("2026-08-18T00:00:00Z"));
|
|
95
|
+
const kept = makeProcedure("procedure-1", "Ship a focused change", "2026-08-18T02:00:00Z");
|
|
96
|
+
const retired = makeProcedure("procedure-2", "Rotate the token", "2026-08-18T01:00:00Z");
|
|
97
|
+
|
|
98
|
+
materializeForNamespace("synthetic-ns", {
|
|
99
|
+
memories: [kept, retired],
|
|
100
|
+
codexHome: root,
|
|
101
|
+
skills: projectProceduresToSkills([kept, retired]),
|
|
102
|
+
});
|
|
103
|
+
assert.ok(existsSync(path.join(memoriesDir, "skills", "rotate-the-token", "SKILL.md")));
|
|
104
|
+
|
|
105
|
+
// A skill folder the user curated by hand — never in projected_skills.
|
|
106
|
+
const handMade = path.join(memoriesDir, "skills", "hand-authored");
|
|
107
|
+
mkdirSync(handMade, { recursive: true });
|
|
108
|
+
writeFileSync(path.join(handMade, "SKILL.md"), "---\nname: hand-authored\n---\n\nMine.\n");
|
|
109
|
+
|
|
110
|
+
materializeForNamespace("synthetic-ns", {
|
|
111
|
+
memories: [kept],
|
|
112
|
+
codexHome: root,
|
|
113
|
+
skills: projectProceduresToSkills([kept]),
|
|
114
|
+
});
|
|
115
|
+
assert.equal(existsSync(path.join(memoriesDir, "skills", "rotate-the-token")), false);
|
|
116
|
+
assert.ok(existsSync(path.join(memoriesDir, "skills", "ship-a-focused-change", "SKILL.md")));
|
|
117
|
+
assert.ok(existsSync(path.join(handMade, "SKILL.md")));
|
|
118
|
+
} finally {
|
|
119
|
+
rmSync(root, { recursive: true, force: true });
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("omitting the skills option leaves an existing skills/ directory untouched", () => {
|
|
124
|
+
const { root, memoriesDir } = makeTempCodexHome();
|
|
125
|
+
try {
|
|
126
|
+
ensureSentinel(memoriesDir, "synthetic-ns", new Date("2026-08-18T00:00:00Z"));
|
|
127
|
+
const kept = makeProcedure("procedure-1", "Ship a focused change");
|
|
128
|
+
materializeForNamespace("synthetic-ns", {
|
|
129
|
+
memories: [kept],
|
|
130
|
+
codexHome: root,
|
|
131
|
+
skills: projectProceduresToSkills([kept]),
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Gate turned off on a later run: `skills` omitted entirely.
|
|
135
|
+
const later = makeProcedure("procedure-1", "Ship a focused change", "2026-08-19T00:00:00Z");
|
|
136
|
+
materializeForNamespace("synthetic-ns", { memories: [later], codexHome: root });
|
|
137
|
+
assert.ok(existsSync(path.join(memoriesDir, "skills", "ship-a-focused-change", "SKILL.md")));
|
|
138
|
+
} finally {
|
|
139
|
+
rmSync(root, { recursive: true, force: true });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
@@ -48,7 +48,18 @@ import { log } from "../logger.js";
|
|
|
48
48
|
import { readEnvVar, resolveHomeDir } from "../runtime/env.js";
|
|
49
49
|
import type { MemoryFile } from "../types.js";
|
|
50
50
|
import { estimateTokenCount } from "../token-estimate.js";
|
|
51
|
+
import type { SkillBundle } from "../procedural/skill-projection.js";
|
|
51
52
|
import { expandTildePath } from "../utils/path.js";
|
|
53
|
+
import { ensureSafeManagedSubdir } from "./materialize-paths.js";
|
|
54
|
+
import {
|
|
55
|
+
commitSkillFiles,
|
|
56
|
+
planSkillFiles,
|
|
57
|
+
retiredSkillsAlreadyRemoved,
|
|
58
|
+
skillFilePath,
|
|
59
|
+
skillFileRelPath,
|
|
60
|
+
stageSkillFiles,
|
|
61
|
+
type SkillFile,
|
|
62
|
+
} from "./materialize-skills.js";
|
|
52
63
|
|
|
53
64
|
// ─── Types ─────────────────────────────────────────────────────────────────
|
|
54
65
|
|
|
@@ -67,6 +78,13 @@ export interface MaterializeOptions {
|
|
|
67
78
|
rolloutRetentionDays?: number;
|
|
68
79
|
/** Per-session rollout summaries to render. */
|
|
69
80
|
rolloutSummaries?: RolloutSummaryInput[];
|
|
81
|
+
/**
|
|
82
|
+
* Projected procedural skill bundles (issue #2369). `undefined` leaves
|
|
83
|
+
* `skills/` untouched; an array — even an empty one — is authoritative for
|
|
84
|
+
* the slugs Remnic projected, so retired procedures get their folder
|
|
85
|
+
* removed. Folders this materializer never projected are never touched.
|
|
86
|
+
*/
|
|
87
|
+
skills?: SkillBundle[];
|
|
70
88
|
/** Current time, injected for deterministic tests. */
|
|
71
89
|
now?: Date;
|
|
72
90
|
/** Optional logger override for tests. */
|
|
@@ -115,6 +133,12 @@ interface SentinelFile {
|
|
|
115
133
|
namespace: string;
|
|
116
134
|
updated_at: string;
|
|
117
135
|
content_hash: string;
|
|
136
|
+
/**
|
|
137
|
+
* Slugs under `skills/` that THIS materializer projected (issue #2369).
|
|
138
|
+
* Absent on sentinels written before skill projection existed, which reads
|
|
139
|
+
* as "we have projected nothing", so hand-created folders stay untouched.
|
|
140
|
+
*/
|
|
141
|
+
projected_skills?: string[];
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
// ─── Constants ─────────────────────────────────────────────────────────────
|
|
@@ -297,6 +321,10 @@ export function materializeForNamespace(
|
|
|
297
321
|
const destRolloutsDir = path.join(memoriesDir, ROLLOUT_SUBDIR);
|
|
298
322
|
const retainedRolloutNames = new Set(rolloutFiles.map((r) => r.name));
|
|
299
323
|
|
|
324
|
+
// Skill bundles (issue #2369) — planning, ownership, and disk layout live in
|
|
325
|
+
// materialize-skills.ts.
|
|
326
|
+
const skillPlan = planSkillFiles(options.skills, existingSentinel.projected_skills ?? []);
|
|
327
|
+
|
|
300
328
|
// ── Idempotence check ──────────────────────────────────────────────────
|
|
301
329
|
const hash = computeContentHash({
|
|
302
330
|
namespace,
|
|
@@ -304,6 +332,7 @@ export function materializeForNamespace(
|
|
|
304
332
|
memoryMd,
|
|
305
333
|
rawMemories,
|
|
306
334
|
rolloutFiles,
|
|
335
|
+
skillFiles: skillPlan.files,
|
|
307
336
|
});
|
|
308
337
|
|
|
309
338
|
if (existingSentinel.content_hash === hash) {
|
|
@@ -318,15 +347,17 @@ export function materializeForNamespace(
|
|
|
318
347
|
path.join(memoriesDir, "MEMORY.md"),
|
|
319
348
|
path.join(memoriesDir, "raw_memories.md"),
|
|
320
349
|
...rolloutFiles.map((r) => path.join(memoriesDir, ROLLOUT_SUBDIR, r.name)),
|
|
350
|
+
...skillPlan.files.map((s) => skillFilePath(memoriesDir, s.slug)),
|
|
321
351
|
];
|
|
322
352
|
const allPresent = requiredFiles.every((f) => fs.existsSync(f));
|
|
323
353
|
const rolloutsClean =
|
|
324
354
|
!rolloutsSupplied ||
|
|
325
355
|
rolloutDirectoryMatchesRetainedSet(
|
|
326
|
-
|
|
356
|
+
ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR),
|
|
327
357
|
retainedRolloutNames,
|
|
328
358
|
);
|
|
329
|
-
|
|
359
|
+
const skillsClean = retiredSkillsAlreadyRemoved(memoriesDir, skillPlan.retiredSlugs);
|
|
360
|
+
if (allPresent && rolloutsClean && skillsClean) {
|
|
330
361
|
logger.debug?.(`no-op materialization for namespace=${namespace} (hash unchanged)`);
|
|
331
362
|
return {
|
|
332
363
|
namespace,
|
|
@@ -403,6 +434,11 @@ export function materializeForNamespace(
|
|
|
403
434
|
filesWritten.push(path.join(ROLLOUT_SUBDIR, rollout.name));
|
|
404
435
|
}
|
|
405
436
|
|
|
437
|
+
stageSkillFiles(tmpDir, skillPlan.files);
|
|
438
|
+
for (const skill of skillPlan.files) {
|
|
439
|
+
filesWritten.push(skillFileRelPath(skill.slug));
|
|
440
|
+
}
|
|
441
|
+
|
|
406
442
|
// Rename into place. Atomic per-file is sufficient — Codex reads each file
|
|
407
443
|
// independently and tolerates an inconsistent in-between snapshot across
|
|
408
444
|
// files for the duration of the rename loop (milliseconds).
|
|
@@ -412,7 +448,7 @@ export function materializeForNamespace(
|
|
|
412
448
|
fs.renameSync(src, dest);
|
|
413
449
|
}
|
|
414
450
|
|
|
415
|
-
const safeDestRolloutsDir =
|
|
451
|
+
const safeDestRolloutsDir = ensureSafeManagedSubdir(memoriesDir, destRolloutsDir, ROLLOUT_SUBDIR);
|
|
416
452
|
// Only garbage-collect rollout files when the caller actually supplied a
|
|
417
453
|
// `rolloutSummaries` array — otherwise we'd wipe legitimately
|
|
418
454
|
// user/Codex-created recap files on every session-end run, since those
|
|
@@ -447,12 +483,17 @@ export function materializeForNamespace(
|
|
|
447
483
|
fs.renameSync(src, dest);
|
|
448
484
|
}
|
|
449
485
|
|
|
486
|
+
commitSkillFiles(memoriesDir, tmpDir, skillPlan);
|
|
487
|
+
|
|
450
488
|
// Update sentinel last so a crash leaves hash mismatched → next run rewrites.
|
|
451
489
|
const sentinel: SentinelFile = {
|
|
452
490
|
version: MATERIALIZE_VERSION,
|
|
453
491
|
namespace,
|
|
454
492
|
updated_at: now.toISOString(),
|
|
455
493
|
content_hash: hash,
|
|
494
|
+
projected_skills: skillPlan.supplied
|
|
495
|
+
? skillPlan.files.map((s) => s.slug)
|
|
496
|
+
: (existingSentinel.projected_skills ?? []),
|
|
456
497
|
};
|
|
457
498
|
writeSentinelAtomically(sentinelPath, sentinel);
|
|
458
499
|
|
|
@@ -805,43 +846,6 @@ function rolloutDirectoryMatchesRetainedSet(
|
|
|
805
846
|
return true;
|
|
806
847
|
}
|
|
807
848
|
|
|
808
|
-
function isPathInside(parent: string, child: string): boolean {
|
|
809
|
-
const relative = path.relative(parent, child);
|
|
810
|
-
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
811
|
-
}
|
|
812
|
-
|
|
813
|
-
function ensureSafeRolloutsDir(memoriesDir: string, rolloutsDir: string): string {
|
|
814
|
-
const memoriesReal = fs.realpathSync(memoriesDir);
|
|
815
|
-
|
|
816
|
-
try {
|
|
817
|
-
const stat = fs.lstatSync(rolloutsDir);
|
|
818
|
-
if (stat.isSymbolicLink()) {
|
|
819
|
-
throw new Error("is a symbolic link");
|
|
820
|
-
}
|
|
821
|
-
if (!stat.isDirectory()) {
|
|
822
|
-
throw new Error("is not a directory");
|
|
823
|
-
}
|
|
824
|
-
} catch (err) {
|
|
825
|
-
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
826
|
-
throw new Error(
|
|
827
|
-
`codex-materialize: unsafe ${ROLLOUT_SUBDIR} directory at ${rolloutsDir}: ${
|
|
828
|
-
err instanceof Error ? err.message : String(err)
|
|
829
|
-
}`,
|
|
830
|
-
);
|
|
831
|
-
}
|
|
832
|
-
fs.mkdirSync(rolloutsDir, { recursive: true });
|
|
833
|
-
}
|
|
834
|
-
|
|
835
|
-
const rolloutsReal = fs.realpathSync(rolloutsDir);
|
|
836
|
-
if (!isPathInside(memoriesReal, rolloutsReal)) {
|
|
837
|
-
throw new Error(
|
|
838
|
-
`codex-materialize: unsafe ${ROLLOUT_SUBDIR} directory at ${rolloutsDir}: resolves outside ${memoriesDir}`,
|
|
839
|
-
);
|
|
840
|
-
}
|
|
841
|
-
|
|
842
|
-
return rolloutsDir;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
849
|
function readSentinel(sentinelPath: string): SentinelFile | null {
|
|
846
850
|
if (!fs.existsSync(sentinelPath)) return null;
|
|
847
851
|
try {
|
|
@@ -857,11 +861,18 @@ function readSentinel(sentinelPath: string): SentinelFile | null {
|
|
|
857
861
|
) {
|
|
858
862
|
throw new Error("invalid sentinel schema");
|
|
859
863
|
}
|
|
864
|
+
// A sentinel written before issue #2369 has no `projected_skills`, which
|
|
865
|
+
// reads as "nothing projected" — so an unrelated skills/ folder written by
|
|
866
|
+
// a user or another tool is never treated as ours.
|
|
867
|
+
const projected = Array.isArray(parsed.projected_skills)
|
|
868
|
+
? parsed.projected_skills.filter((slug): slug is string => typeof slug === "string")
|
|
869
|
+
: [];
|
|
860
870
|
return {
|
|
861
871
|
version: parsed.version,
|
|
862
872
|
namespace: parsed.namespace,
|
|
863
873
|
updated_at: parsed.updated_at,
|
|
864
874
|
content_hash: parsed.content_hash,
|
|
875
|
+
projected_skills: projected,
|
|
865
876
|
};
|
|
866
877
|
} catch (err) {
|
|
867
878
|
throw new Error(
|
|
@@ -1040,6 +1051,7 @@ function computeContentHash(input: {
|
|
|
1040
1051
|
memoryMd: string;
|
|
1041
1052
|
rawMemories: string;
|
|
1042
1053
|
rolloutFiles: Array<{ name: string; body: string }>;
|
|
1054
|
+
skillFiles: Array<{ slug: string; body: string }>;
|
|
1043
1055
|
}): string {
|
|
1044
1056
|
const hash = createHash("sha256");
|
|
1045
1057
|
hash.update(`v${MATERIALIZE_VERSION}\n`);
|
|
@@ -1055,6 +1067,12 @@ function computeContentHash(input: {
|
|
|
1055
1067
|
hash.update(`\n---rollout:${r.name}---\n`);
|
|
1056
1068
|
hash.update(r.body);
|
|
1057
1069
|
}
|
|
1070
|
+
// Sorted by slug so call order cannot flip the hash (§26).
|
|
1071
|
+
const sortedSkills = [...input.skillFiles].sort((a, b) => (a.slug < b.slug ? -1 : a.slug > b.slug ? 1 : 0));
|
|
1072
|
+
for (const s of sortedSkills) {
|
|
1073
|
+
hash.update(`\n---skill:${s.slug}---\n`);
|
|
1074
|
+
hash.update(s.body);
|
|
1075
|
+
}
|
|
1058
1076
|
return hash.digest("hex");
|
|
1059
1077
|
}
|
|
1060
1078
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* materialize-paths.ts — containment guard for the materializer's managed
|
|
3
|
+
* sub-directories (`rollout_summaries/`, `skills/`).
|
|
4
|
+
*
|
|
5
|
+
* Extracted from codex-materialize.ts so the skills section (issue #2369) and
|
|
6
|
+
* the rollout section share ONE containment implementation instead of forking
|
|
7
|
+
* the check (rule 22).
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from "node:fs";
|
|
11
|
+
import path from "node:path";
|
|
12
|
+
|
|
13
|
+
import { pathIsInside } from "../utils/path-containment.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a managed sub-directory of `memoriesDir`, creating it when absent,
|
|
17
|
+
* and refuse a symlinked or escaping target. Returns the (unchanged) path so
|
|
18
|
+
* callers can use it directly.
|
|
19
|
+
*/
|
|
20
|
+
export function ensureSafeManagedSubdir(memoriesDir: string, subdir: string, label: string): string {
|
|
21
|
+
const memoriesReal = fs.realpathSync(memoriesDir);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const stat = fs.lstatSync(subdir);
|
|
25
|
+
if (stat.isSymbolicLink()) {
|
|
26
|
+
throw new Error("is a symbolic link");
|
|
27
|
+
}
|
|
28
|
+
if (!stat.isDirectory()) {
|
|
29
|
+
throw new Error("is not a directory");
|
|
30
|
+
}
|
|
31
|
+
} catch (err) {
|
|
32
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
33
|
+
throw new Error(
|
|
34
|
+
`codex-materialize: unsafe ${label} directory at ${subdir}: ${
|
|
35
|
+
err instanceof Error ? err.message : String(err)
|
|
36
|
+
}`,
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
fs.mkdirSync(subdir, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const subdirReal = fs.realpathSync(subdir);
|
|
43
|
+
if (!pathIsInside(memoriesReal, subdirReal)) {
|
|
44
|
+
throw new Error(
|
|
45
|
+
`codex-materialize: unsafe ${label} directory at ${subdir}: resolves outside ${memoriesDir}`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return path.normalize(subdir);
|
|
50
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* materialize-skills.ts — the `skills/` section of the Codex materializer
|
|
3
|
+
* (issue #2369).
|
|
4
|
+
*
|
|
5
|
+
* Extracted from codex-materialize.ts (which sits at its structural LOC cap)
|
|
6
|
+
* so the skill staging / commit / prune rules live in one small module. Format
|
|
7
|
+
* and slug rules stay in the host-agnostic `procedural/skill-projection.ts`;
|
|
8
|
+
* this module only decides what lands on disk.
|
|
9
|
+
*
|
|
10
|
+
* Ownership rule: Remnic removes ONLY the slugs a previous run recorded in the
|
|
11
|
+
* sentinel's `projected_skills`. A skill folder a user (or another tool)
|
|
12
|
+
* created is never in that list, so it is never a removal candidate.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import fs from "node:fs";
|
|
16
|
+
import path from "node:path";
|
|
17
|
+
|
|
18
|
+
import { renderSkillBundle, SKILL_FILE_NAME, type SkillBundle } from "../procedural/skill-projection.js";
|
|
19
|
+
import { isValidSkillSlug } from "../skills-registry.js";
|
|
20
|
+
import { ensureSafeManagedSubdir } from "./materialize-paths.js";
|
|
21
|
+
|
|
22
|
+
/** Sub-directory for projected procedural skill bundles. */
|
|
23
|
+
export const SKILLS_SUBDIR = "skills";
|
|
24
|
+
|
|
25
|
+
export interface SkillFile {
|
|
26
|
+
slug: string;
|
|
27
|
+
body: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface SkillPlan {
|
|
31
|
+
/** False when the caller omitted `skills` — leave `skills/` untouched. */
|
|
32
|
+
supplied: boolean;
|
|
33
|
+
/** Bundles to write, deduplicated on slug. */
|
|
34
|
+
files: SkillFile[];
|
|
35
|
+
/** Previously projected slugs this run no longer projects. */
|
|
36
|
+
retiredSlugs: string[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Decide what this run writes and removes. `undefined` bundles mean "not our
|
|
41
|
+
* business this run"; an empty array is authoritative and retires everything
|
|
42
|
+
* previously projected.
|
|
43
|
+
*/
|
|
44
|
+
export function planSkillFiles(
|
|
45
|
+
bundles: SkillBundle[] | undefined,
|
|
46
|
+
previouslyProjectedSlugs: readonly string[],
|
|
47
|
+
): SkillPlan {
|
|
48
|
+
const files: SkillFile[] = [];
|
|
49
|
+
const seen = new Set<string>();
|
|
50
|
+
for (const bundle of bundles ?? []) {
|
|
51
|
+
// Invalid or duplicate slugs are dropped so two bundles can never target
|
|
52
|
+
// one folder and leave the second rename with no source (§37).
|
|
53
|
+
if (!isValidSkillSlug(bundle.slug) || seen.has(bundle.slug)) continue;
|
|
54
|
+
seen.add(bundle.slug);
|
|
55
|
+
files.push({ slug: bundle.slug, body: renderSkillBundle(bundle) });
|
|
56
|
+
}
|
|
57
|
+
const previous = previouslyProjectedSlugs.filter((slug) => isValidSkillSlug(slug));
|
|
58
|
+
return {
|
|
59
|
+
supplied: bundles !== undefined,
|
|
60
|
+
files,
|
|
61
|
+
retiredSlugs: bundles === undefined ? [] : previous.filter((slug) => !seen.has(slug)),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Absolute path of a projected bundle's SKILL.md under `memoriesDir`. */
|
|
66
|
+
export function skillFilePath(memoriesDir: string, slug: string): string {
|
|
67
|
+
return path.join(memoriesDir, SKILLS_SUBDIR, slug, SKILL_FILE_NAME);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Relative path recorded in `MaterializeResult.filesWritten`. */
|
|
71
|
+
export function skillFileRelPath(slug: string): string {
|
|
72
|
+
return path.join(SKILLS_SUBDIR, slug, SKILL_FILE_NAME);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* True when no retired folder is still on disk. Guards the idempotent
|
|
77
|
+
* early-return: a hash match is only a safe no-op if the removals also landed.
|
|
78
|
+
*/
|
|
79
|
+
export function retiredSkillsAlreadyRemoved(memoriesDir: string, retiredSlugs: readonly string[]): boolean {
|
|
80
|
+
return retiredSlugs.every((slug) => !fs.existsSync(path.join(memoriesDir, SKILLS_SUBDIR, slug)));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Render bundles into the per-run staging directory. */
|
|
84
|
+
export function stageSkillFiles(tmpDir: string, files: readonly SkillFile[]): void {
|
|
85
|
+
for (const file of files) {
|
|
86
|
+
const stagedDir = path.join(tmpDir, SKILLS_SUBDIR, file.slug);
|
|
87
|
+
fs.mkdirSync(stagedDir, { recursive: true });
|
|
88
|
+
fs.writeFileSync(path.join(stagedDir, SKILL_FILE_NAME), file.body);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Remove retired folders, then rename each staged SKILL.md into place. Per-file
|
|
94
|
+
* renames (never directory renames) so an existing folder cannot cause
|
|
95
|
+
* ENOTEMPTY and so Codex never observes a half-written file.
|
|
96
|
+
*/
|
|
97
|
+
export function commitSkillFiles(memoriesDir: string, tmpDir: string, plan: SkillPlan): void {
|
|
98
|
+
if (!plan.supplied) return;
|
|
99
|
+
if (plan.files.length === 0 && plan.retiredSlugs.length === 0) return;
|
|
100
|
+
|
|
101
|
+
const skillsDir = ensureSafeManagedSubdir(memoriesDir, path.join(memoriesDir, SKILLS_SUBDIR), SKILLS_SUBDIR);
|
|
102
|
+
for (const slug of plan.retiredSlugs) {
|
|
103
|
+
const retiredDir = path.join(skillsDir, slug);
|
|
104
|
+
try {
|
|
105
|
+
// Never follow a symlink out of the managed tree while pruning.
|
|
106
|
+
if (fs.lstatSync(retiredDir).isSymbolicLink()) continue;
|
|
107
|
+
} catch (err) {
|
|
108
|
+
if ((err as NodeJS.ErrnoException).code === "ENOENT") continue;
|
|
109
|
+
throw err;
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
fs.rmSync(retiredDir, { recursive: true, force: true });
|
|
113
|
+
} catch (err) {
|
|
114
|
+
throw new Error(
|
|
115
|
+
`codex-materialize: failed to remove retired skill ${slug}: ${err instanceof Error ? err.message : String(err)}`,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const file of plan.files) {
|
|
120
|
+
const destDir = path.join(skillsDir, file.slug);
|
|
121
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
122
|
+
fs.renameSync(
|
|
123
|
+
path.join(tmpDir, SKILLS_SUBDIR, file.slug, SKILL_FILE_NAME),
|
|
124
|
+
path.join(destDir, SKILL_FILE_NAME),
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -17,9 +17,31 @@ import type { ContradictionVerdict } from "./contradiction-judge.js";
|
|
|
17
17
|
|
|
18
18
|
// ── Types ──────────────────────────────────────────────────────────────────────
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Resolution verbs. The first five are contradiction-pair verbs; the last
|
|
22
|
+
* three resolve a `kind: "preference-drift"` item (issue #2371). Verb validity
|
|
23
|
+
* is per-kind — `executeResolution` rejects a cross-kind verb — but the stored
|
|
24
|
+
* union is shared so one review queue, one `review_resolve` surface, and one
|
|
25
|
+
* resolution record serve both item kinds.
|
|
26
|
+
*/
|
|
27
|
+
export type ResolutionVerb =
|
|
28
|
+
| "keep-a"
|
|
29
|
+
| "keep-b"
|
|
30
|
+
| "merge"
|
|
31
|
+
| "both-valid"
|
|
32
|
+
| "needs-more-context"
|
|
33
|
+
| "keep"
|
|
34
|
+
| "supersede"
|
|
35
|
+
| "archive";
|
|
36
|
+
|
|
37
|
+
/** Review-item kind. Absent on every pair written before issue #2371. */
|
|
38
|
+
export type ReviewItemKind = "contradiction" | "preference-drift";
|
|
39
|
+
|
|
40
|
+
/** Verbs valid for a `kind: "preference-drift"` item. */
|
|
41
|
+
export const PREFERENCE_DRIFT_VERBS: readonly ResolutionVerb[] = ["keep", "supersede", "archive"];
|
|
42
|
+
|
|
43
|
+
/** Verbs valid for a contradiction pair. */
|
|
44
|
+
export const CONTRADICTION_VERBS: readonly ResolutionVerb[] = [
|
|
23
45
|
"keep-a",
|
|
24
46
|
"keep-b",
|
|
25
47
|
"merge",
|
|
@@ -27,11 +49,23 @@ const VALID_RESOLUTION_VERBS: readonly ResolutionVerb[] = [
|
|
|
27
49
|
"needs-more-context",
|
|
28
50
|
];
|
|
29
51
|
|
|
52
|
+
const VALID_RESOLUTION_VERBS: readonly ResolutionVerb[] = [
|
|
53
|
+
...CONTRADICTION_VERBS,
|
|
54
|
+
...PREFERENCE_DRIFT_VERBS,
|
|
55
|
+
];
|
|
56
|
+
|
|
30
57
|
export interface ContradictionPair {
|
|
31
58
|
/** Deterministic pair ID: sha256(sorted(memoryIdA, memoryIdB) plus namespace when scoped). */
|
|
32
59
|
pairId: string;
|
|
33
60
|
/** Memory IDs (sorted). */
|
|
34
61
|
memoryIds: [string, string];
|
|
62
|
+
/**
|
|
63
|
+
* Item kind (issue #2371). Absent on every pair written before drift
|
|
64
|
+
* detection existed, which reads as `"contradiction"`. A
|
|
65
|
+
* `"preference-drift"` item pairs the aging preference (first id) with the
|
|
66
|
+
* recent evidence that pointed away from it (second id).
|
|
67
|
+
*/
|
|
68
|
+
kind?: ReviewItemKind;
|
|
35
69
|
/** Judge verdict. */
|
|
36
70
|
verdict: ContradictionVerdict;
|
|
37
71
|
/** Judge rationale. */
|
|
@@ -85,8 +119,20 @@ export function isDefaultReviewNamespace(
|
|
|
85
119
|
return !requested || requested === defaultNamespace || resolvedNamespace === defaultNamespace;
|
|
86
120
|
}
|
|
87
121
|
|
|
122
|
+
const TERMINAL_RESOLUTIONS: Partial<Record<ResolutionVerb, true>> = {
|
|
123
|
+
"keep-a": true,
|
|
124
|
+
"keep-b": true,
|
|
125
|
+
merge: true,
|
|
126
|
+
// Every preference-drift verb is terminal: the user has answered the "is
|
|
127
|
+
// this preference still true?" question, so the item must leave the
|
|
128
|
+
// unresolved queue and never be re-proposed by a later scan (issue #2371).
|
|
129
|
+
keep: true,
|
|
130
|
+
supersede: true,
|
|
131
|
+
archive: true,
|
|
132
|
+
};
|
|
133
|
+
|
|
88
134
|
function isTerminalResolution(resolution: ResolutionVerb | undefined): boolean {
|
|
89
|
-
return resolution
|
|
135
|
+
return resolution !== undefined && TERMINAL_RESOLUTIONS[resolution] === true;
|
|
90
136
|
}
|
|
91
137
|
|
|
92
138
|
function preservesDirectResolution(resolution: ResolutionVerb | undefined): boolean {
|
|
@@ -380,8 +380,16 @@ function normalizeScanNamespace(namespace: string | undefined): string | undefin
|
|
|
380
380
|
return trimmed ? trimmed : undefined;
|
|
381
381
|
}
|
|
382
382
|
|
|
383
|
-
|
|
384
|
-
|
|
383
|
+
/**
|
|
384
|
+
* Resolve the namespace-scoped storage a scan must read and write through.
|
|
385
|
+
*
|
|
386
|
+
* Exported and narrowed to the fields it actually reads so sibling scans
|
|
387
|
+
* (preference drift, issue #2371) share ONE namespace resolver rather than
|
|
388
|
+
* re-deriving the read/write namespace independently — the divergence the
|
|
389
|
+
* namespace/ACL scenario matrix in AGENTS.md exists to prevent.
|
|
390
|
+
*/
|
|
391
|
+
export async function resolveScanStorage(
|
|
392
|
+
deps: Pick<ScanDependencies, "config" | "storage" | "storageForNamespace">,
|
|
385
393
|
namespace: string | undefined,
|
|
386
394
|
): Promise<ScanStorageResolution> {
|
|
387
395
|
if (!resolveNamespaceCapabilities(deps.config).namespaces) {
|
|
@@ -427,7 +435,10 @@ function isStorageManagerLike(value: unknown): value is StorageManager {
|
|
|
427
435
|
return typeof candidate.readAllMemories === "function";
|
|
428
436
|
}
|
|
429
437
|
|
|
430
|
-
function fallbackResolvedNamespace(
|
|
438
|
+
function fallbackResolvedNamespace(
|
|
439
|
+
deps: Pick<ScanDependencies, "config">,
|
|
440
|
+
namespace: string | undefined,
|
|
441
|
+
): string | undefined {
|
|
431
442
|
if (namespace) return namespace;
|
|
432
443
|
return resolveNamespaceCapabilities(deps.config).namespaces ? deps.config.defaultNamespace : undefined;
|
|
433
444
|
}
|