@remnic/core 9.3.703 → 9.3.705
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-boundary.d.ts +8 -8
- package/dist/access-boundary.js +27 -27
- package/dist/access-cli.js +57 -56
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +7 -7
- package/dist/access-http.js +32 -31
- package/dist/access-mcp.d.ts +7 -7
- package/dist/access-mcp.js +31 -30
- package/dist/access-operations-batch.d.ts +2 -0
- package/dist/access-operations-batch.js +120 -0
- package/dist/access-operations.d.ts +8 -7
- package/dist/access-operations.js +30 -29
- package/dist/access-schema.js +3 -3
- package/dist/{access-service-COCzhgEL.d.ts → access-service-C8hc8N2i.d.ts} +4 -4
- package/dist/access-service.d.ts +7 -7
- package/dist/access-service.js +26 -26
- package/dist/access-surface-catalog.d.ts +7 -7
- package/dist/access-surface-catalog.js +57 -54
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/action-confidence.d.ts +3 -3
- package/dist/active-memory-bridge.d.ts +3 -3
- package/dist/active-recall.d.ts +3 -3
- package/dist/{auto-sync-3AAP25FV.js → auto-sync-24NNS3GU.js} +3 -3
- package/dist/behavior-learner.d.ts +3 -3
- package/dist/behavior-signals.d.ts +3 -3
- package/dist/bootstrap.d.ts +6 -6
- package/dist/briefing.d.ts +3 -3
- package/dist/briefing.js +5 -5
- package/dist/buffer-surprise-report.d.ts +3 -3
- package/dist/buffer.d.ts +3 -3
- package/dist/bulk-import/index.d.ts +4 -4
- package/dist/calibration.d.ts +3 -3
- package/dist/capabilities.d.ts +3 -3
- package/dist/{capsule-crypto-YO5QJ6L3.js → capsule-crypto-7FJQINUR.js} +2 -2
- package/dist/{catalog-DxCzhjE6.d.ts → catalog-CAeU0e1C.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +3 -3
- package/dist/causal-behavior.js +5 -5
- package/dist/causal-chain.js +3 -3
- package/dist/causal-consolidation.d.ts +3 -3
- package/dist/causal-consolidation.js +9 -9
- package/dist/causal-retrieval.js +3 -3
- package/dist/causal-trajectory-graph.js +2 -2
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-BXLOS5AJ.js → chunk-2NLLXCJG.js} +2 -2
- package/dist/{chunk-EOOVJK2U.js → chunk-2SYPOX45.js} +10 -10
- package/dist/{chunk-64XXOQRW.js → chunk-47LPHBIP.js} +2 -2
- package/dist/{chunk-QGJAGC2J.js → chunk-5DTWZ66X.js} +2 -2
- package/dist/chunk-5DTWZ66X.js.map +1 -0
- package/dist/{chunk-6VVP6NK7.js → chunk-6GJ2WQRK.js} +2 -2
- package/dist/{chunk-4NFVPDIL.js → chunk-74MYJSKB.js} +5 -5
- package/dist/{chunk-X5J3JZR3.js → chunk-773DPI6T.js} +6 -6
- package/dist/{chunk-FVI5B7DE.js → chunk-7ARKLLCV.js} +6 -6
- package/dist/{chunk-ZCEI242W.js → chunk-7L54YZUI.js} +411 -401
- package/dist/chunk-7L54YZUI.js.map +1 -0
- package/dist/{chunk-AGNBY3VG.js → chunk-APJQ6UEA.js} +4 -4
- package/dist/{chunk-CI7RKSRE.js → chunk-AQEJKOKI.js} +2 -1
- package/dist/{chunk-DL6H3D7S.js → chunk-ARV3AUOM.js} +2 -2
- package/dist/{chunk-JTKFZMZ7.js → chunk-BKBSE3BU.js} +3 -3
- package/dist/{chunk-TGAHHCB6.js → chunk-BMKGG7GC.js} +2 -2
- package/dist/{chunk-GFIARMA7.js → chunk-C2EHWNP2.js} +13 -13
- package/dist/{chunk-VKJHM6PL.js → chunk-DGTDRIUO.js} +5 -5
- package/dist/chunk-GI3MTYDU.js +1303 -0
- package/dist/chunk-GI3MTYDU.js.map +1 -0
- package/dist/{chunk-5VXVXJH6.js → chunk-GT4VBKM4.js} +59 -5
- package/dist/chunk-GT4VBKM4.js.map +1 -0
- package/dist/{chunk-KC6TCAWV.js → chunk-HEHPVBWA.js} +6 -6
- package/dist/{chunk-MDJURR27.js → chunk-HW5EF6LV.js} +2 -2
- package/dist/{chunk-BMFZLLNI.js → chunk-ICP53SKG.js} +2 -2
- package/dist/{chunk-YOI3ELXF.js → chunk-IF362TF6.js} +2 -2
- package/dist/{chunk-ABCGDW3A.js → chunk-IFR23TC5.js} +4 -4
- package/dist/{chunk-OXEAMU42.js → chunk-JHAYR2JY.js} +33 -33
- package/dist/{chunk-CZJ6QSKG.js → chunk-JZCKDTAS.js} +4 -4
- package/dist/{chunk-CZJ6QSKG.js.map → chunk-JZCKDTAS.js.map} +1 -1
- package/dist/{chunk-VPAFWWCL.js → chunk-K22IJO4R.js} +2 -2
- package/dist/{chunk-JMA4RYRN.js → chunk-KFU2SKDD.js} +2 -2
- package/dist/{chunk-VDX2J7OX.js → chunk-KQAFEZQX.js} +2 -2
- package/dist/{chunk-AMNLZ6SF.js → chunk-KZMMAVR2.js} +2 -2
- package/dist/{chunk-EZR35XHX.js → chunk-LY4FJLPT.js} +2 -2
- package/dist/{chunk-NUIJEGVD.js → chunk-M5MWSG4S.js} +7 -7
- package/dist/{chunk-Z7XEIAV4.js → chunk-MNH2OODZ.js} +2 -2
- package/dist/{chunk-MXEWQKM7.js → chunk-NFGJBEPT.js} +6 -6
- package/dist/{chunk-Q4O3ET6F.js → chunk-NUWZFSKC.js} +2 -2
- package/dist/{chunk-6TAETM63.js → chunk-OM6ETLLH.js} +2 -2
- package/dist/{chunk-QQW2LIEA.js → chunk-OMSTU233.js} +7 -7
- package/dist/{chunk-XGMCUY5P.js → chunk-S3WYRPSA.js} +64 -64
- package/dist/{chunk-QIMFOCSH.js → chunk-S5APSA3U.js} +2 -2
- package/dist/{chunk-IX72AAMZ.js → chunk-SY6WG6DB.js} +2 -2
- package/dist/{chunk-MBUM2Y3L.js → chunk-ULVM34NP.js} +5 -5
- package/dist/{chunk-DQEMWVMT.js → chunk-X7Y7WX73.js} +1 -1
- package/dist/{chunk-7WWURLG6.js → chunk-XPOOY35N.js} +2 -2
- package/dist/{chunk-EYJD6KIO.js → chunk-Y4PMATX2.js} +6 -6
- package/dist/{chunk-KF74X62T.js → chunk-YGKUAX2B.js} +4 -4
- package/dist/{chunk-YN4ZT4CW.js → chunk-YI7RZO7Y.js} +1 -1
- package/dist/{cli-BM4xQPp4.d.ts → cli-ChE0XlJY.d.ts} +6 -6
- package/dist/cli.d.ts +9 -9
- package/dist/cli.js +55 -54
- package/dist/compounding/engine.d.ts +3 -3
- package/dist/compounding/engine.js +5 -5
- package/dist/compounding/preference-consolidator.d.ts +3 -3
- package/dist/compression-optimizer.d.ts +3 -3
- package/dist/config.d.ts +3 -3
- package/dist/connectors/codex-materialize-runner.d.ts +3 -3
- package/dist/connectors/codex-materialize-runner.js +5 -5
- package/dist/connectors/codex-materialize.d.ts +3 -3
- package/dist/connectors/index.d.ts +3 -3
- package/dist/connectors/index.js +5 -5
- package/dist/consolidation-provenance-check.d.ts +3 -3
- package/dist/consolidation-undo.d.ts +3 -3
- package/dist/contradiction/index.d.ts +3 -3
- package/dist/conversation-index/backend.d.ts +3 -3
- package/dist/conversation-index/chunker.d.ts +3 -3
- package/dist/conversation-index/faiss-adapter.d.ts +3 -3
- package/dist/conversation-index/indexer.d.ts +3 -3
- package/dist/conversation-index/search.d.ts +3 -3
- package/dist/day-summary.d.ts +3 -3
- package/dist/delinearize.d.ts +3 -3
- package/dist/direct-answer-wiring.d.ts +3 -3
- package/dist/direct-answer.d.ts +3 -3
- package/dist/embedding-fallback.d.ts +3 -3
- package/dist/enrichment/index.d.ts +3 -3
- package/dist/entity-retrieval.d.ts +3 -3
- package/dist/entity-retrieval.js +5 -5
- package/dist/entity-schema.d.ts +3 -3
- package/dist/explicit-capture.d.ts +6 -6
- package/dist/extraction-faithfulness.d.ts +3 -3
- package/dist/extraction-judge-telemetry.d.ts +3 -3
- package/dist/extraction-judge-training.d.ts +3 -3
- package/dist/extraction-judge.d.ts +3 -3
- package/dist/extraction.d.ts +3 -3
- package/dist/extraction.js +2 -2
- package/dist/fallback-llm.d.ts +3 -3
- package/dist/{graph-edge-decay-D7OESCBR.js → graph-edge-decay-JLOF3YW4.js} +3 -3
- package/dist/graph-snapshot.js +3 -3
- package/dist/graph.js +2 -2
- package/dist/identity-continuity.d.ts +3 -3
- package/dist/importance.d.ts +3 -3
- package/dist/importers/index.d.ts +2 -2
- package/dist/index.d.ts +14 -29
- package/dist/index.js +100 -99
- package/dist/index.js.map +1 -1
- package/dist/intent.d.ts +3 -3
- package/dist/lcm/archive.d.ts +1 -1
- package/dist/lcm/archive.js +2 -2
- package/dist/lcm/engine.d.ts +3 -3
- package/dist/lcm/engine.js +5 -5
- package/dist/lcm/index.d.ts +3 -3
- package/dist/lcm/index.js +7 -7
- package/dist/lcm/queue.d.ts +1 -1
- package/dist/lcm/recall.d.ts +1 -1
- package/dist/lcm/summarizer.d.ts +1 -1
- package/dist/lcm/summarizer.js +3 -3
- package/dist/lcm/tools.d.ts +3 -3
- package/dist/lifecycle.d.ts +3 -3
- package/dist/live-connectors-runner.d.ts +3 -3
- package/dist/local-llm.d.ts +3 -3
- package/dist/maintenance/memory-governance.d.ts +3 -3
- package/dist/maintenance/memory-governance.js +6 -6
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -5
- package/dist/maintenance/rebuild-memory-projection.js +7 -7
- package/dist/mcp-memory-inspector-app.d.ts +7 -7
- package/dist/memory-action-policy.d.ts +3 -3
- package/dist/memory-cache.d.ts +3 -3
- package/dist/memory-lifecycle-ledger-utils.d.ts +3 -3
- package/dist/memory-projection-store.d.ts +3 -3
- package/dist/memory-provenance.d.ts +3 -3
- package/dist/memory-worth-outcomes.d.ts +3 -3
- package/dist/{index-DJ9QWMw-.d.ts → message-parts/index.d.ts} +2 -1
- package/dist/message-parts/index.js +24 -0
- package/dist/message-parts/index.js.map +1 -0
- package/dist/models-json.d.ts +3 -3
- package/dist/namespaces/migrate.d.ts +4 -4
- package/dist/namespaces/migrate.js +10 -10
- package/dist/namespaces/principal.d.ts +3 -3
- package/dist/namespaces/search.d.ts +3 -3
- package/dist/namespaces/search.js +4 -4
- package/dist/namespaces/storage.d.ts +4 -4
- package/dist/namespaces/storage.js +5 -5
- package/dist/native-knowledge.d.ts +3 -3
- package/dist/objective-state-writers.d.ts +1 -1
- package/dist/objective-state-writers.js +2 -2
- package/dist/operator-toolkit.d.ts +3 -3
- package/dist/operator-toolkit.js +17 -17
- package/dist/orchestration/maintenance.d.ts +4 -4
- package/dist/orchestration/maintenance.js +7 -7
- package/dist/{orchestrator-C9CDWAm6.d.ts → orchestrator-m_PnhyHj.d.ts} +4 -4
- package/dist/orchestrator.d.ts +6 -6
- package/dist/orchestrator.js +44 -44
- package/dist/patterns-cli.d.ts +3 -3
- package/dist/{pipeline-BSTuml0d.d.ts → pipeline-DmqtvION.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +3 -3
- package/dist/provenance.d.ts +3 -3
- package/dist/qmd-recall-cache.d.ts +3 -3
- package/dist/qmd.d.ts +3 -3
- package/dist/recall-disclosure-escalation.d.ts +3 -3
- package/dist/recall-explain-renderer.d.ts +3 -3
- package/dist/recall-planner-llm.d.ts +3 -3
- package/dist/recall-state.d.ts +3 -3
- package/dist/recall-tag-filter.d.ts +3 -3
- package/dist/recall-xray-cli.d.ts +3 -3
- package/dist/recall-xray-renderer.d.ts +3 -3
- package/dist/recall-xray.d.ts +3 -3
- package/dist/replay/normalizers/chatgpt.d.ts +1 -1
- package/dist/replay/normalizers/claude.d.ts +1 -1
- package/dist/replay/normalizers/openclaw.d.ts +1 -1
- package/dist/replay/normalizers/shared.d.ts +1 -1
- package/dist/replay/runner.d.ts +1 -1
- package/dist/replay/types.d.ts +1 -1
- package/dist/resolve-auth-token.d.ts +3 -3
- package/dist/resume-bundles.js +1 -1
- package/dist/retrieval-agents.d.ts +3 -3
- package/dist/retrieval-tiers.d.ts +3 -3
- package/dist/routing/engine.d.ts +3 -3
- package/dist/routing/store.d.ts +3 -3
- package/dist/search/embed-helper.d.ts +3 -3
- package/dist/search/factory.d.ts +3 -3
- package/dist/search/factory.js +3 -3
- package/dist/search/index.d.ts +3 -3
- package/dist/search/index.js +7 -7
- package/dist/search/lancedb-backend.d.ts +3 -3
- package/dist/search/meilisearch-backend.d.ts +3 -3
- package/dist/search/noop-backend.d.ts +3 -3
- package/dist/search/orama-backend.d.ts +3 -3
- package/dist/search/port.d.ts +3 -3
- package/dist/search/remote-backend.d.ts +3 -3
- package/dist/{semantic-consolidation-DgFXyALl.d.ts → semantic-consolidation-DVBbq6Wr.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -4
- package/dist/semantic-consolidation.js +7 -7
- package/dist/semantic-rule-promotion.js +5 -5
- package/dist/semantic-rule-verifier.d.ts +3 -3
- package/dist/semantic-rule-verifier.js +6 -6
- package/dist/session-observer-bands.d.ts +3 -3
- package/dist/session-observer-state.d.ts +3 -3
- package/dist/shared-context/manager.d.ts +3 -3
- package/dist/signal.d.ts +3 -3
- package/dist/storage.d.ts +3 -3
- package/dist/storage.js +4 -4
- package/dist/summarizer.d.ts +3 -3
- package/dist/summary-snapshot.d.ts +3 -3
- package/dist/temporal-supersession.d.ts +3 -3
- package/dist/temporal-validity.d.ts +3 -3
- package/dist/threading.d.ts +3 -3
- package/dist/tier-migration.d.ts +3 -3
- package/dist/tier-routing.d.ts +3 -3
- package/dist/topics.d.ts +3 -3
- package/dist/transcript.d.ts +3 -3
- package/dist/transfer/backup.js +2 -2
- package/dist/transfer/capsule-export.js +2 -2
- package/dist/transfer/capsule-import.js +2 -2
- package/dist/transfer/import-sqlite.js +2 -2
- package/dist/{types-MWKPZnM0.d.ts → types-CJrvHJjx.d.ts} +2 -2
- package/dist/{types-ByK7T3L6.d.ts → types-gb_SNtjR.d.ts} +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/utility-runtime.d.ts +3 -3
- package/dist/utils/path.d.ts +17 -0
- package/dist/utils/path.js +9 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/verified-recall.js +6 -6
- package/package.json +27 -2
- package/src/access-boundary.ts +102 -1
- package/src/access-http.ts +54 -0
- package/src/access-operations-batch.ts +1468 -0
- package/src/access-operations.ts +4 -0
- package/src/access-surface-catalog.test.ts +17 -1
- package/src/access-surface-catalog.ts +57 -54
- package/src/cli/creation-ledger-commands.ts +346 -0
- package/src/cli/research-status-commands.ts +256 -0
- package/src/cli.ts +7 -516
- package/src/storage-contract/atomicity.test.ts +113 -0
- package/src/storage-contract/cache-coherence.test.ts +100 -0
- package/src/storage-contract/content-hash.test.ts +102 -0
- package/src/storage-contract/failure-semantics.test.ts +108 -0
- package/src/storage-contract/harness.ts +148 -0
- package/src/storage-contract/namespace-routing.test.ts +135 -0
- package/src/storage-contract/round-trip.test.ts +226 -0
- package/src/storage-contract/surface.test.ts +90 -0
- package/src/storage-contract/versioning.test.ts +139 -0
- package/dist/chunk-5VXVXJH6.js.map +0 -1
- package/dist/chunk-QGJAGC2J.js.map +0 -1
- package/dist/chunk-ZCEI242W.js.map +0 -1
- package/dist/path-X2K5XCHL.js +0 -9
- /package/dist/{capsule-crypto-YO5QJ6L3.js.map → access-operations-batch.js.map} +0 -0
- /package/dist/{auto-sync-3AAP25FV.js.map → auto-sync-24NNS3GU.js.map} +0 -0
- /package/dist/{path-X2K5XCHL.js.map → capsule-crypto-7FJQINUR.js.map} +0 -0
- /package/dist/{chunk-BXLOS5AJ.js.map → chunk-2NLLXCJG.js.map} +0 -0
- /package/dist/{chunk-EOOVJK2U.js.map → chunk-2SYPOX45.js.map} +0 -0
- /package/dist/{chunk-64XXOQRW.js.map → chunk-47LPHBIP.js.map} +0 -0
- /package/dist/{chunk-6VVP6NK7.js.map → chunk-6GJ2WQRK.js.map} +0 -0
- /package/dist/{chunk-4NFVPDIL.js.map → chunk-74MYJSKB.js.map} +0 -0
- /package/dist/{chunk-X5J3JZR3.js.map → chunk-773DPI6T.js.map} +0 -0
- /package/dist/{chunk-FVI5B7DE.js.map → chunk-7ARKLLCV.js.map} +0 -0
- /package/dist/{chunk-AGNBY3VG.js.map → chunk-APJQ6UEA.js.map} +0 -0
- /package/dist/{chunk-CI7RKSRE.js.map → chunk-AQEJKOKI.js.map} +0 -0
- /package/dist/{chunk-DL6H3D7S.js.map → chunk-ARV3AUOM.js.map} +0 -0
- /package/dist/{chunk-JTKFZMZ7.js.map → chunk-BKBSE3BU.js.map} +0 -0
- /package/dist/{chunk-TGAHHCB6.js.map → chunk-BMKGG7GC.js.map} +0 -0
- /package/dist/{chunk-GFIARMA7.js.map → chunk-C2EHWNP2.js.map} +0 -0
- /package/dist/{chunk-VKJHM6PL.js.map → chunk-DGTDRIUO.js.map} +0 -0
- /package/dist/{chunk-KC6TCAWV.js.map → chunk-HEHPVBWA.js.map} +0 -0
- /package/dist/{chunk-MDJURR27.js.map → chunk-HW5EF6LV.js.map} +0 -0
- /package/dist/{chunk-BMFZLLNI.js.map → chunk-ICP53SKG.js.map} +0 -0
- /package/dist/{chunk-YOI3ELXF.js.map → chunk-IF362TF6.js.map} +0 -0
- /package/dist/{chunk-ABCGDW3A.js.map → chunk-IFR23TC5.js.map} +0 -0
- /package/dist/{chunk-OXEAMU42.js.map → chunk-JHAYR2JY.js.map} +0 -0
- /package/dist/{chunk-VPAFWWCL.js.map → chunk-K22IJO4R.js.map} +0 -0
- /package/dist/{chunk-JMA4RYRN.js.map → chunk-KFU2SKDD.js.map} +0 -0
- /package/dist/{chunk-VDX2J7OX.js.map → chunk-KQAFEZQX.js.map} +0 -0
- /package/dist/{chunk-AMNLZ6SF.js.map → chunk-KZMMAVR2.js.map} +0 -0
- /package/dist/{chunk-EZR35XHX.js.map → chunk-LY4FJLPT.js.map} +0 -0
- /package/dist/{chunk-NUIJEGVD.js.map → chunk-M5MWSG4S.js.map} +0 -0
- /package/dist/{chunk-Z7XEIAV4.js.map → chunk-MNH2OODZ.js.map} +0 -0
- /package/dist/{chunk-MXEWQKM7.js.map → chunk-NFGJBEPT.js.map} +0 -0
- /package/dist/{chunk-Q4O3ET6F.js.map → chunk-NUWZFSKC.js.map} +0 -0
- /package/dist/{chunk-6TAETM63.js.map → chunk-OM6ETLLH.js.map} +0 -0
- /package/dist/{chunk-QQW2LIEA.js.map → chunk-OMSTU233.js.map} +0 -0
- /package/dist/{chunk-XGMCUY5P.js.map → chunk-S3WYRPSA.js.map} +0 -0
- /package/dist/{chunk-QIMFOCSH.js.map → chunk-S5APSA3U.js.map} +0 -0
- /package/dist/{chunk-IX72AAMZ.js.map → chunk-SY6WG6DB.js.map} +0 -0
- /package/dist/{chunk-MBUM2Y3L.js.map → chunk-ULVM34NP.js.map} +0 -0
- /package/dist/{chunk-DQEMWVMT.js.map → chunk-X7Y7WX73.js.map} +0 -0
- /package/dist/{chunk-7WWURLG6.js.map → chunk-XPOOY35N.js.map} +0 -0
- /package/dist/{chunk-EYJD6KIO.js.map → chunk-Y4PMATX2.js.map} +0 -0
- /package/dist/{chunk-KF74X62T.js.map → chunk-YGKUAX2B.js.map} +0 -0
- /package/dist/{chunk-YN4ZT4CW.js.map → chunk-YI7RZO7Y.js.map} +0 -0
- /package/dist/{graph-edge-decay-D7OESCBR.js.map → graph-edge-decay-JLOF3YW4.js.map} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #1533 — Phase A contract test: write/read/list/delete round-trips.
|
|
3
|
+
*
|
|
4
|
+
* For EVERY category directory (iterated from ALL_CATEGORY_DIRS, never hardcoded
|
|
5
|
+
* — rule 53's cousin), exercises the documented public surface end to end:
|
|
6
|
+
*
|
|
7
|
+
* writeMemory → readMemoryByPath → getMemoryById → readAllMemories → invalidateMemory
|
|
8
|
+
*
|
|
9
|
+
* Asserts content fidelity, frontmatter integrity, hash identity, and that
|
|
10
|
+
* deleted memories disappear from every read path. This is the round-trip
|
|
11
|
+
* contract that the 51 importers depend on; Phase B moves MUST keep it green.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import assert from "node:assert/strict";
|
|
15
|
+
import type { MemoryCategory } from "../types.js";
|
|
16
|
+
import test from "node:test";
|
|
17
|
+
|
|
18
|
+
import { StorageManager } from "../storage.js";
|
|
19
|
+
import {
|
|
20
|
+
ALL_CATEGORY_DIRS,
|
|
21
|
+
ALL_CATEGORY_KEYS,
|
|
22
|
+
CATEGORY_DIR_MAP,
|
|
23
|
+
RECALL_NON_MEMORY_DIRS,
|
|
24
|
+
categoryDirName,
|
|
25
|
+
} from "../utils/category-dir.js";
|
|
26
|
+
import { makeStorage } from "./harness.js";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The singular category keys writeMemory accepts, minus "entity" (entities use
|
|
30
|
+
* a separate write path: writeEntity) and "question" (questions are a
|
|
31
|
+
* non-memory QUEUE dir — RECALL_NON_MEMORY_DIRS — surfaced through
|
|
32
|
+
* writeQuestion/readQuestions, NOT readAllMemories; see question-queue test).
|
|
33
|
+
*/
|
|
34
|
+
const ROUND_TRIP_CATEGORIES = ALL_CATEGORY_KEYS.filter(
|
|
35
|
+
(k) => k !== "entity" && k !== "question",
|
|
36
|
+
) as MemoryCategory[];
|
|
37
|
+
|
|
38
|
+
test("round-trip: writeMemory returns a stable id and persists to the category dir", async () => {
|
|
39
|
+
const { storage, cleanup } = await makeStorage();
|
|
40
|
+
try {
|
|
41
|
+
const id = await storage.writeMemory("fact", "The sky is blue", {
|
|
42
|
+
tags: ["contract"],
|
|
43
|
+
});
|
|
44
|
+
assert.equal(typeof id, "string");
|
|
45
|
+
assert.match(id, /^fact-/);
|
|
46
|
+
|
|
47
|
+
const byId = await storage.getMemoryById(id);
|
|
48
|
+
assert.ok(byId, "getMemoryById must find the just-written memory");
|
|
49
|
+
assert.equal(byId!.frontmatter.id, id);
|
|
50
|
+
assert.equal(byId!.content, "The sky is blue");
|
|
51
|
+
} finally {
|
|
52
|
+
await cleanup();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test("round-trip: readAllMemories returns written memories from every category dir", async () => {
|
|
57
|
+
const { storage, cleanup } = await makeStorage();
|
|
58
|
+
try {
|
|
59
|
+
const written: string[] = [];
|
|
60
|
+
for (const category of ROUND_TRIP_CATEGORIES) {
|
|
61
|
+
const id = await storage.writeMemory(
|
|
62
|
+
category,
|
|
63
|
+
`content for ${category}`,
|
|
64
|
+
{ confidence: 0.9 },
|
|
65
|
+
);
|
|
66
|
+
written.push(id);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const all = await storage.readAllMemories();
|
|
70
|
+
const ids = new Set(all.map((m) => m.frontmatter.id));
|
|
71
|
+
for (const id of written) {
|
|
72
|
+
assert.ok(ids.has(id), `readAllMemories missing memory ${id} (${ROUND_TRIP_CATEGORIES.find((c) => id.startsWith(c))})`);
|
|
73
|
+
}
|
|
74
|
+
} finally {
|
|
75
|
+
await cleanup();
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
for (const category of ROUND_TRIP_CATEGORIES) {
|
|
80
|
+
test(`round-trip [${category}]: write → read-by-path → read-by-id → list → delete`, async () => {
|
|
81
|
+
const { storage, cleanup } = await makeStorage();
|
|
82
|
+
try {
|
|
83
|
+
const content = `fact body for category ${category}`;
|
|
84
|
+
const id = await storage.writeMemory(category, content, {
|
|
85
|
+
tags: ["round-trip"],
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// getMemoryById
|
|
89
|
+
const byId = await storage.getMemoryById(id);
|
|
90
|
+
assert.ok(byId, "getMemoryById returned null");
|
|
91
|
+
assert.equal(byId!.content, content);
|
|
92
|
+
assert.equal(byId!.frontmatter.category, category);
|
|
93
|
+
|
|
94
|
+
// readMemoryByPath — the path comes from the byId result
|
|
95
|
+
const byPath = await storage.readMemoryByPath(byId!.path);
|
|
96
|
+
assert.ok(byPath, "readMemoryByPath returned null");
|
|
97
|
+
assert.equal(byPath!.content, content);
|
|
98
|
+
assert.equal(byPath!.frontmatter.id, id);
|
|
99
|
+
|
|
100
|
+
// The file landed under the right category dir
|
|
101
|
+
const expectedDir = categoryDirName(category);
|
|
102
|
+
assert.ok(
|
|
103
|
+
byId!.path.includes(`/${expectedDir}/`),
|
|
104
|
+
`${category} memory landed in ${byId!.path}, expected under ${expectedDir}/`,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// list contains it
|
|
108
|
+
const all = await storage.readAllMemories();
|
|
109
|
+
assert.ok(
|
|
110
|
+
all.some((m) => m.frontmatter.id === id),
|
|
111
|
+
"readAllMemories did not include the written memory",
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
// delete (invalidate) removes it from every read path
|
|
115
|
+
const deleted = await storage.invalidateMemory(id);
|
|
116
|
+
assert.equal(deleted, true, "invalidateMemory should return true on success");
|
|
117
|
+
|
|
118
|
+
const afterDelete = await storage.getMemoryById(id);
|
|
119
|
+
assert.equal(afterDelete, null, "getMemoryById must return null after invalidateMemory");
|
|
120
|
+
|
|
121
|
+
const allAfter = await storage.readAllMemories();
|
|
122
|
+
assert.ok(
|
|
123
|
+
!allAfter.some((m) => m.frontmatter.id === id),
|
|
124
|
+
"readAllMemories must not include deleted memory",
|
|
125
|
+
);
|
|
126
|
+
} finally {
|
|
127
|
+
await cleanup();
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
test("round-trip: invalidateMemory returns false for a non-existent id (not a throw)", async () => {
|
|
133
|
+
const { storage, cleanup } = await makeStorage();
|
|
134
|
+
try {
|
|
135
|
+
const result = await storage.invalidateMemory("does-not-exist-12345");
|
|
136
|
+
assert.equal(result, false);
|
|
137
|
+
} finally {
|
|
138
|
+
await cleanup();
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("round-trip: getMemoryById returns null for a non-existent id", async () => {
|
|
143
|
+
const { storage, cleanup } = await makeStorage();
|
|
144
|
+
try {
|
|
145
|
+
const result = await storage.getMemoryById("missing-id");
|
|
146
|
+
assert.equal(result, null);
|
|
147
|
+
} finally {
|
|
148
|
+
await cleanup();
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("round-trip: readMemoryByPath returns null for a non-existent path", async () => {
|
|
153
|
+
const { storage, baseDir, cleanup } = await makeStorage();
|
|
154
|
+
try {
|
|
155
|
+
const result = await storage.readMemoryByPath(
|
|
156
|
+
`${baseDir}/facts/2026-01-01/nonexistent.md`,
|
|
157
|
+
);
|
|
158
|
+
assert.equal(result, null);
|
|
159
|
+
} finally {
|
|
160
|
+
await cleanup();
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("round-trip: ALL_CATEGORY_DIRS is exactly facts + every CATEGORY_DIR_MAP value", () => {
|
|
165
|
+
// ALL_CATEGORY_DIRS must contain directory NAMES (facts, decisions, ...) not
|
|
166
|
+
// singular keys (fact, decision, ...). This guards the parity between
|
|
167
|
+
// categoryDirName() and the scan roots — a divergence would silently drop
|
|
168
|
+
// a category from recall.
|
|
169
|
+
const expected = new Set(["facts", ...Object.values(CATEGORY_DIR_MAP)]);
|
|
170
|
+
assert.deepEqual(new Set(ALL_CATEGORY_DIRS), expected);
|
|
171
|
+
// No singular keys leaked in
|
|
172
|
+
for (const dir of ALL_CATEGORY_DIRS) {
|
|
173
|
+
assert.ok(!Object.hasOwn(CATEGORY_DIR_MAP, dir),
|
|
174
|
+
`${dir} is a singular category key, not a directory name`);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("round-trip: StorageManager.dir exposes the base directory", async () => {
|
|
179
|
+
const { storage, baseDir, cleanup } = await makeStorage();
|
|
180
|
+
try {
|
|
181
|
+
assert.equal(storage.dir, baseDir);
|
|
182
|
+
} finally {
|
|
183
|
+
await cleanup();
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("question-queue: writeQuestion → readQuestions → resolveQuestion round-trip (questions are NOT in readAllMemories)", async () => {
|
|
188
|
+
const { storage, cleanup } = await makeStorage();
|
|
189
|
+
try {
|
|
190
|
+
const id = await storage.writeQuestion("What database are we on?", "infra context", 3);
|
|
191
|
+
assert.equal(typeof id, "string");
|
|
192
|
+
assert.match(id, /^q-/);
|
|
193
|
+
|
|
194
|
+
// readQuestions returns it
|
|
195
|
+
const questions = await storage.readQuestions();
|
|
196
|
+
const q = questions.find((x) => x.id === id);
|
|
197
|
+
assert.ok(q, "readQuestions must include the just-written question");
|
|
198
|
+
assert.equal(q!.question, "What database are we on?");
|
|
199
|
+
assert.equal(q!.resolved, false);
|
|
200
|
+
|
|
201
|
+
// questions/ is a RECALL_NON_MEMORY_DIRS entry — it must NOT appear in readAllMemories
|
|
202
|
+
const all = await storage.readAllMemories();
|
|
203
|
+
assert.ok(
|
|
204
|
+
!all.some((m) => m.frontmatter.id === id),
|
|
205
|
+
"questions must not leak into the memory corpus (readAllMemories)",
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
// unresolvedOnly filter works
|
|
209
|
+
const unresolved = await storage.readQuestions({ unresolvedOnly: true });
|
|
210
|
+
assert.ok(unresolved.some((x) => x.id === id));
|
|
211
|
+
|
|
212
|
+
// resolve marks it resolved
|
|
213
|
+
const resolved = await storage.resolveQuestion(id);
|
|
214
|
+
assert.equal(resolved, true);
|
|
215
|
+
|
|
216
|
+
const afterResolve = await storage.readQuestions({ unresolvedOnly: true });
|
|
217
|
+
assert.ok(!afterResolve.some((x) => x.id === id), "resolved question must not appear in unresolvedOnly");
|
|
218
|
+
|
|
219
|
+
const allAfter = await storage.readQuestions();
|
|
220
|
+
const resolvedQ = allAfter.find((x) => x.id === id);
|
|
221
|
+
assert.ok(resolvedQ, "resolved question should still be readable without the filter");
|
|
222
|
+
assert.equal(resolvedQ!.resolved, true);
|
|
223
|
+
} finally {
|
|
224
|
+
await cleanup();
|
|
225
|
+
}
|
|
226
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #1533 — Phase A contract test: public-surface enumeration.
|
|
3
|
+
*
|
|
4
|
+
* Phase A step 1: enumerate the public surface of storage.ts so the contract
|
|
5
|
+
* suite has an explicit inventory. This test pins the exported symbols the 51+
|
|
6
|
+
* importers depend on. When Phase B extracts seams, every entry here must still
|
|
7
|
+
* resolve — either on storage.ts or on the storage/* module that absorbed it.
|
|
8
|
+
*
|
|
9
|
+
* This is NOT a behavior test; it is a surface-stability guard. It documents
|
|
10
|
+
* what the MemoryStorage interface must cover.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import assert from "node:assert/strict";
|
|
14
|
+
import test from "node:test";
|
|
15
|
+
|
|
16
|
+
import * as storageModule from "../storage.js";
|
|
17
|
+
|
|
18
|
+
test("surface: StorageManager class is exported and constructible", () => {
|
|
19
|
+
assert.equal(typeof storageModule.StorageManager, "function");
|
|
20
|
+
assert.equal(storageModule.StorageManager.name, "StorageManager");
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("surface: ContentHashIndex class is exported", () => {
|
|
24
|
+
assert.equal(typeof storageModule.ContentHashIndex, "function");
|
|
25
|
+
assert.equal(storageModule.ContentHashIndex.name, "ContentHashIndex");
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test("surface: entity helpers are exported (parseEntityFile, serializeEntityFile, normalizeEntityName)", () => {
|
|
29
|
+
assert.equal(typeof storageModule.parseEntityFile, "function");
|
|
30
|
+
assert.equal(typeof storageModule.serializeEntityFile, "function");
|
|
31
|
+
assert.equal(typeof storageModule.normalizeEntityName, "function");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test("surface: StorageManager exposes the documented memory CRUD methods", () => {
|
|
35
|
+
const proto = storageModule.StorageManager.prototype;
|
|
36
|
+
const required = [
|
|
37
|
+
"writeMemory",
|
|
38
|
+
"readAllMemories",
|
|
39
|
+
"readMemoryByPath",
|
|
40
|
+
"getMemoryById",
|
|
41
|
+
"invalidateMemory",
|
|
42
|
+
"updateMemory",
|
|
43
|
+
"ensureDirectories",
|
|
44
|
+
"setVersioningConfig",
|
|
45
|
+
"isSecureStoreUnlocked",
|
|
46
|
+
"getMemoryStatusVersion",
|
|
47
|
+
];
|
|
48
|
+
for (const method of required) {
|
|
49
|
+
assert.equal(
|
|
50
|
+
typeof (proto as unknown as Record<string, unknown>)[method],
|
|
51
|
+
"function",
|
|
52
|
+
`StorageManager.prototype.${method} must be a function (documented public surface)`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("surface: StorageManager exposes the question-queue methods", () => {
|
|
58
|
+
const proto = storageModule.StorageManager.prototype;
|
|
59
|
+
assert.equal(typeof proto.writeQuestion, "function");
|
|
60
|
+
assert.equal(typeof proto.readQuestions, "function");
|
|
61
|
+
assert.equal(typeof proto.resolveQuestion, "function");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("surface: StorageManager exposes cache invalidation methods (rule 37)", () => {
|
|
65
|
+
const proto = storageModule.StorageManager.prototype;
|
|
66
|
+
assert.equal(typeof proto.invalidateAllMemoriesCacheForDir, "function");
|
|
67
|
+
assert.equal(typeof proto.invalidateMemoryCachesForTiers, "function");
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("surface: StorageManager has a static clearAllStaticCaches for test isolation", () => {
|
|
71
|
+
assert.equal(
|
|
72
|
+
typeof storageModule.StorageManager.clearAllStaticCaches,
|
|
73
|
+
"function",
|
|
74
|
+
"clearAllStaticCaches is the test-isolation chokepoint",
|
|
75
|
+
);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("surface: ContentHashIndex exposes computeHash and normalizeContent (rule 23)", () => {
|
|
79
|
+
assert.equal(typeof storageModule.ContentHashIndex.computeHash, "function");
|
|
80
|
+
assert.equal(typeof storageModule.ContentHashIndex.normalizeContent, "function");
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
test("surface: StorageManager.dir getter returns the base directory string", () => {
|
|
84
|
+
const desc = Object.getOwnPropertyDescriptor(
|
|
85
|
+
storageModule.StorageManager.prototype,
|
|
86
|
+
"dir",
|
|
87
|
+
);
|
|
88
|
+
assert.ok(desc, "dir must be a property on the prototype");
|
|
89
|
+
assert.equal(typeof desc?.get, "function", "dir must have a getter");
|
|
90
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Issue #1533 — Phase A contract test: page versioning snapshots.
|
|
3
|
+
*
|
|
4
|
+
* When versioning is enabled, overwriting a FIXED-PATH file produces a numbered
|
|
5
|
+
* snapshot in the `.versions/` sidecar. Revert restores a prior version.
|
|
6
|
+
* This pins the versioning contract the consolidation/provenance paths rely on.
|
|
7
|
+
*
|
|
8
|
+
* NOTE: `writeMemory` generates a unique path per id, so the first write to a
|
|
9
|
+
* path never has pre-existing content to snapshot. The versioning integration
|
|
10
|
+
* is exercised through `writeProfile` — a fixed-path write that calls
|
|
11
|
+
* `snapshotBeforeWrite` before overwriting. The direct `createVersion`/
|
|
12
|
+
* `revertToVersion` API is tested separately.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import assert from "node:assert/strict";
|
|
16
|
+
import { mkdtemp, rm, readFile, writeFile } from "node:fs/promises";
|
|
17
|
+
import os from "node:os";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import test from "node:test";
|
|
20
|
+
|
|
21
|
+
import {
|
|
22
|
+
createVersion,
|
|
23
|
+
listVersions,
|
|
24
|
+
revertToVersion,
|
|
25
|
+
getVersion,
|
|
26
|
+
type VersioningConfig,
|
|
27
|
+
} from "../page-versioning.js";
|
|
28
|
+
import { StorageManager } from "../storage.js";
|
|
29
|
+
import { resetStaticCaches } from "./harness.js";
|
|
30
|
+
|
|
31
|
+
const VERSIONING_CONFIG: VersioningConfig = {
|
|
32
|
+
enabled: true,
|
|
33
|
+
maxVersionsPerPage: 10,
|
|
34
|
+
sidecarDir: ".versions",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
test("versioning: overwrite of a fixed-path file (writeProfile) produces a numbered snapshot", async () => {
|
|
38
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-ver-snapshot-"));
|
|
39
|
+
try {
|
|
40
|
+
resetStaticCaches();
|
|
41
|
+
const storage = new StorageManager(dir);
|
|
42
|
+
await storage.ensureDirectories();
|
|
43
|
+
storage.setVersioningConfig(VERSIONING_CONFIG);
|
|
44
|
+
|
|
45
|
+
const profilePath = path.join(dir, "profile.md");
|
|
46
|
+
await storage.writeProfile("first version of profile");
|
|
47
|
+
|
|
48
|
+
// Overwrite the same fixed path → snapshotBeforeWrite fires
|
|
49
|
+
await storage.writeProfile("second version of profile");
|
|
50
|
+
|
|
51
|
+
const versions = await listVersions(profilePath, VERSIONING_CONFIG);
|
|
52
|
+
assert.ok(
|
|
53
|
+
versions.versions.length >= 1,
|
|
54
|
+
"at least one snapshot must exist after overwriting a fixed-path file",
|
|
55
|
+
);
|
|
56
|
+
assert.equal(versions.versions[0].trigger, "consolidation");
|
|
57
|
+
} finally {
|
|
58
|
+
resetStaticCaches();
|
|
59
|
+
await rm(dir, { recursive: true, force: true });
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("versioning: snapshot captures the PRE-overwrite content", async () => {
|
|
64
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-ver-pre-"));
|
|
65
|
+
try {
|
|
66
|
+
resetStaticCaches();
|
|
67
|
+
const storage = new StorageManager(dir);
|
|
68
|
+
await storage.ensureDirectories();
|
|
69
|
+
storage.setVersioningConfig(VERSIONING_CONFIG);
|
|
70
|
+
|
|
71
|
+
const profilePath = path.join(dir, "profile.md");
|
|
72
|
+
await storage.writeProfile("ORIGINAL PROFILE");
|
|
73
|
+
await storage.writeProfile("REPLACEMENT PROFILE");
|
|
74
|
+
|
|
75
|
+
const versions = await listVersions(profilePath, VERSIONING_CONFIG);
|
|
76
|
+
assert.ok(versions.versions.length >= 1);
|
|
77
|
+
|
|
78
|
+
// Read the snapshot — it must contain the ORIGINAL, not the replacement
|
|
79
|
+
const snapshot = await getVersion(profilePath, versions.versions[0].versionId, VERSIONING_CONFIG);
|
|
80
|
+
assert.ok(snapshot, "snapshot content must be readable");
|
|
81
|
+
assert.ok(
|
|
82
|
+
snapshot!.includes("ORIGINAL PROFILE"),
|
|
83
|
+
"the snapshot must contain the pre-overwrite content",
|
|
84
|
+
);
|
|
85
|
+
assert.ok(
|
|
86
|
+
!snapshot!.includes("REPLACEMENT"),
|
|
87
|
+
"the snapshot must NOT contain the replacement content",
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// The live file has the replacement
|
|
91
|
+
const live = await readFile(profilePath, "utf-8");
|
|
92
|
+
assert.ok(live.includes("REPLACEMENT PROFILE"));
|
|
93
|
+
} finally {
|
|
94
|
+
resetStaticCaches();
|
|
95
|
+
await rm(dir, { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test("versioning: disabled by default — no snapshots created", async () => {
|
|
100
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-ver-disabled-"));
|
|
101
|
+
try {
|
|
102
|
+
resetStaticCaches();
|
|
103
|
+
const storage = new StorageManager(dir);
|
|
104
|
+
await storage.ensureDirectories();
|
|
105
|
+
// Do NOT call setVersioningConfig — default is disabled
|
|
106
|
+
await storage.writeProfile("v1");
|
|
107
|
+
await storage.writeProfile("v2");
|
|
108
|
+
|
|
109
|
+
const profilePath = path.join(dir, "profile.md");
|
|
110
|
+
const versions = await listVersions(profilePath, VERSIONING_CONFIG);
|
|
111
|
+
assert.equal(versions.versions.length, 0, "no snapshots when versioning was disabled at write time");
|
|
112
|
+
} finally {
|
|
113
|
+
resetStaticCaches();
|
|
114
|
+
await rm(dir, { recursive: true, force: true });
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("versioning: createVersion → revertToVersion round-trip restores content", async () => {
|
|
119
|
+
const dir = await mkdtemp(path.join(os.tmpdir(), "remnic-ver-revert-"));
|
|
120
|
+
try {
|
|
121
|
+
const filePath = path.join(dir, "doc.md");
|
|
122
|
+
await writeFile(filePath, "alpha", "utf-8");
|
|
123
|
+
|
|
124
|
+
await createVersion(filePath, "alpha", "manual", VERSIONING_CONFIG);
|
|
125
|
+
await writeFile(filePath, "beta", "utf-8");
|
|
126
|
+
await createVersion(filePath, "beta", "manual", VERSIONING_CONFIG);
|
|
127
|
+
|
|
128
|
+
const versions = await listVersions(filePath, VERSIONING_CONFIG);
|
|
129
|
+
assert.ok(versions.versions.length >= 2);
|
|
130
|
+
|
|
131
|
+
const firstVersionId = versions.versions[0].versionId;
|
|
132
|
+
await revertToVersion(filePath, firstVersionId, VERSIONING_CONFIG);
|
|
133
|
+
|
|
134
|
+
const restored = await readFile(filePath, "utf-8");
|
|
135
|
+
assert.equal(restored, "alpha", "revert must restore the version-1 content");
|
|
136
|
+
} finally {
|
|
137
|
+
await rm(dir, { recursive: true, force: true });
|
|
138
|
+
}
|
|
139
|
+
});
|