functionalscript 0.37.0 → 0.38.0
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/README.md +1 -1
- package/{fs → fjs}/asn.1/proof.f.js +32 -94
- package/fjs/asserts/module.f.d.ts +36 -0
- package/fjs/asserts/module.f.js +39 -0
- package/fjs/asserts/proof.f.d.ts +11 -0
- package/fjs/asserts/proof.f.js +18 -0
- package/{fs → fjs}/base_n/proof.f.js +12 -36
- package/{fs → fjs}/basen/base64/proof.f.d.ts +1 -0
- package/{fs → fjs}/basen/base64/proof.f.js +15 -1
- package/{fs → fjs}/basen/cbase32/proof.f.js +15 -42
- package/fjs/bnf/data/module.f.d.ts +52 -0
- package/{fs → fjs}/bnf/data/module.f.js +53 -3
- package/{fs → fjs}/bnf/data/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/data/proof.f.js +54 -19
- package/{fs → fjs}/bnf/descent/module.f.d.ts +4 -14
- package/fjs/bnf/descent/module.f.js +124 -0
- package/{fs → fjs}/bnf/descent/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/descent/proof.f.js +55 -24
- package/{fs → fjs}/bnf/ll1/module.f.d.ts +4 -4
- package/{fs → fjs}/bnf/ll1/module.f.js +7 -5
- package/{fs → fjs}/bnf/ll1/proof.f.d.ts +1 -0
- package/{fs → fjs}/bnf/ll1/proof.f.js +27 -10
- package/{fs → fjs}/bnf/module.f.d.ts +19 -5
- package/{fs → fjs}/bnf/module.f.js +10 -11
- package/fjs/bnf/proof.f.js +69 -0
- package/{fs → fjs}/bnf/testlib.f.js +2 -2
- package/{fs → fjs}/cas/cli/proof.f.d.ts +4 -1
- package/{fs → fjs}/cas/cli/proof.f.js +29 -66
- package/fjs/cas/evo/mcp/module.f.d.ts +19 -0
- package/fjs/cas/evo/mcp/module.f.js +56 -0
- package/fjs/cas/evo/mcp/proof.f.d.ts +9 -0
- package/fjs/cas/evo/mcp/proof.f.js +95 -0
- package/fjs/cas/evo/module.f.d.ts +138 -0
- package/fjs/cas/evo/module.f.js +309 -0
- package/fjs/cas/evo/proof.f.d.ts +32 -0
- package/fjs/cas/evo/proof.f.js +453 -0
- package/fjs/cas/mcp/module.f.d.ts +49 -0
- package/{fs → fjs}/cas/mcp/module.f.js +54 -76
- package/{fs → fjs}/cas/mcp/proof.f.d.ts +4 -1
- package/{fs → fjs}/cas/mcp/proof.f.js +41 -13
- package/{fs → fjs}/cas/module.f.d.ts +10 -0
- package/{fs → fjs}/cas/module.f.js +27 -1
- package/{fs → fjs}/cas/proof.f.d.ts +4 -0
- package/{fs → fjs}/cas/proof.f.js +77 -86
- package/{fs → fjs}/ci/config/module.f.d.ts +5 -5
- package/{fs → fjs}/ci/config/module.f.js +5 -5
- package/{fs → fjs}/ci/proof.f.js +14 -9
- package/{fs → fjs}/ci/rust/module.f.js +9 -1
- package/{fs → fjs}/cli/proof.f.js +22 -63
- package/{fs → fjs}/common/monoid/proof.f.js +4 -9
- package/{fs → fjs}/crypto/hmac/proof.f.js +4 -12
- package/fjs/crypto/pow/proof.f.js +111 -0
- package/{fs → fjs}/crypto/secp/proof.f.js +12 -33
- package/{fs → fjs}/crypto/sha2/proof.f.js +18 -49
- package/{fs → fjs}/crypto/sign/module.f.d.ts +0 -5
- package/{fs → fjs}/crypto/sign/module.f.js +7 -4
- package/{fs → fjs}/crypto/sign/proof.f.js +36 -105
- package/{fs → fjs}/crypto/vdf/proof.f.js +22 -63
- package/{fs → fjs}/dev/package_json/proof.f.js +7 -7
- package/{fs → fjs}/dev/proof.f.js +2 -4
- package/{fs → fjs}/djs/ast/proof.f.js +4 -12
- package/{fs → fjs}/djs/parser/module.f.d.ts +5 -0
- package/{fs → fjs}/djs/parser/module.f.js +20 -0
- package/{fs → fjs}/djs/parser/proof.f.js +138 -400
- package/{fs → fjs}/djs/proof.f.js +13 -36
- package/{fs → fjs}/djs/serializer/proof.f.js +14 -39
- package/fjs/djs/tokenizer/module.f.d.ts +24 -0
- package/fjs/djs/tokenizer/module.f.js +472 -0
- package/{fs/djs/tokenizer-new → fjs/djs/tokenizer}/proof.f.d.ts +4 -3
- package/{fs/djs/tokenizer-new → fjs/djs/tokenizer}/proof.f.js +446 -445
- package/{fs → fjs}/djs/transpiler/proof.f.d.ts +3 -0
- package/{fs → fjs}/djs/transpiler/proof.f.js +29 -30
- package/{fs → fjs}/effects/memory/proof.f.js +8 -21
- package/{fs → fjs}/effects/node/memory/proof.js +5 -12
- package/{fs → fjs}/effects/node/module.d.ts +1 -1
- package/{fs → fjs}/effects/node/module.f.d.ts +1 -1
- package/{fs → fjs}/effects/node/module.js +3 -3
- package/{fs → fjs}/effects/node/proof.f.d.ts +1 -0
- package/{fs → fjs}/effects/node/proof.f.js +106 -292
- package/{fs → fjs}/effects/node/virtual/proof.f.d.ts +1 -0
- package/{fs → fjs}/effects/node/virtual/proof.f.js +36 -29
- package/{fs → fjs}/effects/proof.f.js +16 -45
- package/{fs → fjs}/emergent_testing/proof.f.js +7 -7
- package/{fs → fjs}/fsc/proof.f.js +12 -34
- package/{fs → fjs}/fsm/proof.f.js +5 -12
- package/{fs → fjs}/mcp/module.f.d.ts +7 -0
- package/{fs → fjs}/mcp/module.f.js +9 -2
- package/{fs → fjs}/mcp/proof.f.js +12 -12
- package/{fs → fjs}/mcp/stdio/module.f.d.ts +2 -2
- package/{fs → fjs}/mcp/stdio/module.f.js +2 -2
- package/{fs → fjs}/media/html/proof.f.js +12 -33
- package/{fs → fjs}/media/json/parser/module.f.d.ts +5 -0
- package/{fs → fjs}/media/json/parser/module.f.js +14 -0
- package/{fs → fjs}/media/json/parser/proof.f.js +39 -114
- package/{fs → fjs}/media/json/rpc/module.f.js +1 -1
- package/{fs → fjs}/media/json/schema/module.f.d.ts +2 -2
- package/{fs → fjs}/media/json/schema/module.f.js +23 -39
- package/{fs → fjs}/media/json/schema/proof.f.js +3 -6
- package/{fs → fjs}/media/json/serializer/proof.f.js +10 -27
- package/{fs → fjs}/media/module.f.d.ts +6 -6
- package/{fs → fjs}/media/module.f.js +3 -4
- package/{fs → fjs}/media/proof.f.js +5 -4
- package/{fs → fjs}/media/revision/module.f.d.ts +31 -4
- package/{fs → fjs}/media/revision/module.f.js +35 -23
- package/{fs → fjs}/media/revision/proof.f.d.ts +10 -8
- package/fjs/media/revision/proof.f.js +140 -0
- package/{fs → fjs}/media/type/proof.f.js +2 -6
- package/{fs → fjs}/module.f.js +1 -1
- package/{fs → fjs}/path/proof.f.js +27 -78
- package/{fs → fjs}/proof.f.js +2 -0
- package/{fs → fjs}/sul/id/proof.f.js +7 -21
- package/{fs → fjs}/sul/level/hash/proof.f.js +5 -5
- package/{fs → fjs}/sul/level/literal/proof.f.js +12 -26
- package/fjs/text/ascii/proof.f.d.ts +6 -0
- package/{fs → fjs}/text/ascii/proof.f.js +4 -14
- package/{fs → fjs}/text/code_point/module.f.js +10 -10
- package/{fs → fjs}/text/proof.f.js +4 -9
- package/{fs → fjs}/text/sgr/proof.f.js +6 -15
- package/{fs → fjs}/text/utf16/module.f.js +1 -1
- package/{fs → fjs}/text/utf16/proof.f.js +23 -66
- package/{fs → fjs}/text/utf8/proof.f.js +56 -125
- package/{fs → fjs}/types/array/proof.f.js +18 -52
- package/fjs/types/bigfloat/proof.f.js +217 -0
- package/{fs → fjs}/types/bigint/proof.f.js +49 -145
- package/{fs → fjs}/types/bit_vec/proof.f.js +72 -214
- package/{fs → fjs}/types/btree/find/proof.f.js +23 -66
- package/{fs → fjs}/types/btree/proof.f.js +5 -12
- package/{fs → fjs}/types/btree/remove/proof.f.d.ts +2 -0
- package/{fs → fjs}/types/btree/remove/proof.f.js +83 -230
- package/{fs → fjs}/types/btree/set/module.f.js +5 -2
- package/{fs → fjs}/types/btree/set/proof.f.js +35 -24
- package/{fs → fjs}/types/byte_set/proof.f.js +22 -63
- package/{fs → fjs}/types/function/compare/proof.f.js +13 -36
- package/{fs → fjs}/types/function/operator/proof.f.js +17 -48
- package/{fs → fjs}/types/function/proof.f.js +2 -3
- package/{fs → fjs}/types/list/proof.f.js +55 -163
- package/{fs → fjs}/types/map/proof.f.js +4 -12
- package/{fs → fjs}/types/nibble_set/proof.f.js +16 -45
- package/{fs → fjs}/types/nominal/proof.f.js +5 -10
- package/fjs/types/nullable/proof.f.js +29 -0
- package/{fs → fjs}/types/number/proof.f.js +9 -24
- package/{fs → fjs}/types/object/proof.f.js +3 -6
- package/{fs → fjs}/types/patricia_trie/proof.f.js +21 -21
- package/{fs → fjs}/types/prime_field/module.f.js +2 -7
- package/{fs → fjs}/types/range/module.f.d.ts +1 -1
- package/fjs/types/range/module.f.js +2 -0
- package/fjs/types/range/proof.f.js +9 -0
- package/{fs → fjs}/types/range_map/proof.f.js +28 -81
- package/{fs → fjs}/types/result/proof.f.d.ts +3 -2
- package/fjs/types/result/proof.f.js +31 -0
- package/{fs → fjs}/types/rtti/common/module.f.d.ts +36 -1
- package/{fs → fjs}/types/rtti/common/module.f.js +44 -0
- package/fjs/types/rtti/common/proof.f.d.ts +8 -0
- package/fjs/types/rtti/common/proof.f.js +51 -0
- package/{fs → fjs}/types/rtti/parse/module.f.js +13 -22
- package/{fs → fjs}/types/rtti/parse/proof.f.js +7 -18
- package/{fs → fjs}/types/rtti/ts/module.f.d.ts +10 -4
- package/{fs → fjs}/types/rtti/validate/module.f.js +8 -29
- package/{fs → fjs}/types/rtti/validate/proof.f.js +4 -9
- package/{fs → fjs}/types/sorted_list/proof.f.js +8 -21
- package/{fs → fjs}/types/sorted_set/proof.f.js +14 -39
- package/fjs/types/string/proof.f.js +77 -0
- package/fjs/types/string_set/proof.f.js +43 -0
- package/{fs → fjs}/types/ts/proof.f.js +15 -42
- package/{fs → fjs}/types/uint8array/module.f.js +7 -7
- package/{fs → fjs}/types/uint8array/proof.f.d.ts +4 -1
- package/{fs → fjs}/types/uint8array/proof.f.js +7 -7
- package/{fs → fjs}/website/proof.f.js +3 -6
- package/package.json +6 -6
- package/fs/asserts/module.f.d.ts +0 -4
- package/fs/asserts/module.f.js +0 -9
- package/fs/asserts/proof.f.d.ts +0 -8
- package/fs/asserts/proof.f.js +0 -51
- package/fs/bnf/data/module.f.d.ts +0 -30
- package/fs/bnf/descent/module.f.js +0 -119
- package/fs/bnf/proof.f.js +0 -104
- package/fs/cas/mcp/module.f.d.ts +0 -36
- package/fs/crypto/pow/proof.f.js +0 -161
- package/fs/djs/tokenizer/module.f.d.ts +0 -12
- package/fs/djs/tokenizer/module.f.js +0 -62
- package/fs/djs/tokenizer/proof.f.d.ts +0 -7
- package/fs/djs/tokenizer/proof.f.js +0 -543
- package/fs/djs/tokenizer-new/module.f.d.ts +0 -3
- package/fs/djs/tokenizer-new/module.f.js +0 -155
- package/fs/media/revision/proof.f.js +0 -119
- package/fs/text/ascii/proof.f.d.ts +0 -4
- package/fs/types/bigfloat/proof.f.js +0 -348
- package/fs/types/nullable/proof.f.js +0 -50
- package/fs/types/range/module.f.js +0 -2
- package/fs/types/range/proof.f.js +0 -18
- package/fs/types/result/proof.f.js +0 -52
- package/fs/types/string/proof.f.js +0 -118
- package/fs/types/string_set/proof.f.js +0 -82
- /package/{fs → fjs}/asn.1/module.f.d.ts +0 -0
- /package/{fs → fjs}/asn.1/module.f.js +0 -0
- /package/{fs → fjs}/asn.1/proof.f.d.ts +0 -0
- /package/{fs → fjs}/base_n/module.f.d.ts +0 -0
- /package/{fs → fjs}/base_n/module.f.js +0 -0
- /package/{fs → fjs}/base_n/proof.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/module.f.js +0 -0
- /package/{fs → fjs}/basen/base128/proof.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base128/proof.f.js +0 -0
- /package/{fs → fjs}/basen/base64/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/base64/module.f.js +0 -0
- /package/{fs → fjs}/basen/cbase32/module.f.d.ts +0 -0
- /package/{fs → fjs}/basen/cbase32/module.f.js +0 -0
- /package/{fs → fjs}/basen/cbase32/proof.f.d.ts +0 -0
- /package/{fs → fjs}/bnf/proof.f.d.ts +0 -0
- /package/{fs → fjs}/bnf/testlib.f.d.ts +0 -0
- /package/{fs → fjs}/cas/cli/module.f.d.ts +0 -0
- /package/{fs → fjs}/cas/cli/module.f.js +0 -0
- /package/{fs → fjs}/ci/bun/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/bun/module.f.js +0 -0
- /package/{fs → fjs}/ci/common/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/common/module.f.js +0 -0
- /package/{fs → fjs}/ci/deno/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/deno/module.f.js +0 -0
- /package/{fs → fjs}/ci/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/module.f.js +0 -0
- /package/{fs → fjs}/ci/node/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/node/module.f.js +0 -0
- /package/{fs → fjs}/ci/playwright/module.f.d.ts +0 -0
- /package/{fs → fjs}/ci/playwright/module.f.js +0 -0
- /package/{fs → fjs}/ci/proof.f.d.ts +0 -0
- /package/{fs → fjs}/ci/rust/module.f.d.ts +0 -0
- /package/{fs → fjs}/cli/module.f.d.ts +0 -0
- /package/{fs → fjs}/cli/module.f.js +0 -0
- /package/{fs → fjs}/cli/proof.f.d.ts +0 -0
- /package/{fs → fjs}/common/monoid/module.f.d.ts +0 -0
- /package/{fs → fjs}/common/monoid/module.f.js +0 -0
- /package/{fs → fjs}/common/monoid/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/hmac/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/hmac/module.f.js +0 -0
- /package/{fs → fjs}/crypto/hmac/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/pow/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/pow/module.f.js +0 -0
- /package/{fs → fjs}/crypto/pow/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/secp/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/secp/module.f.js +0 -0
- /package/{fs → fjs}/crypto/secp/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sha2/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sha2/module.f.js +0 -0
- /package/{fs → fjs}/crypto/sha2/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/sign/proof.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/vdf/module.f.d.ts +0 -0
- /package/{fs → fjs}/crypto/vdf/module.f.js +0 -0
- /package/{fs → fjs}/crypto/vdf/proof.f.d.ts +0 -0
- /package/{fs → fjs}/dev/module.f.d.ts +0 -0
- /package/{fs → fjs}/dev/module.f.js +0 -0
- /package/{fs → fjs}/dev/package_json/module.f.d.ts +0 -0
- /package/{fs → fjs}/dev/package_json/module.f.js +0 -0
- /package/{fs → fjs}/dev/package_json/proof.f.d.ts +0 -0
- /package/{fs → fjs}/dev/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/ast/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/ast/module.f.js +0 -0
- /package/{fs → fjs}/djs/ast/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/input.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/input.f.js +0 -0
- /package/{fs → fjs}/djs/examples/m.f.d.ts +0 -0
- /package/{fs → fjs}/djs/examples/m.f.js +0 -0
- /package/{fs → fjs}/djs/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/module.f.js +0 -0
- /package/{fs → fjs}/djs/parser/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/serializer/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/serializer/module.f.js +0 -0
- /package/{fs → fjs}/djs/serializer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/djs/transpiler/module.f.d.ts +0 -0
- /package/{fs → fjs}/djs/transpiler/module.f.js +0 -0
- /package/{fs → fjs}/effects/list/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/list/module.f.js +0 -0
- /package/{fs → fjs}/effects/memory/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/memory/module.f.js +0 -0
- /package/{fs → fjs}/effects/memory/proof.f.d.ts +0 -0
- /package/{fs → fjs}/effects/mock/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/mock/module.f.js +0 -0
- /package/{fs → fjs}/effects/module.d.ts +0 -0
- /package/{fs → fjs}/effects/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/module.f.js +0 -0
- /package/{fs → fjs}/effects/module.js +0 -0
- /package/{fs → fjs}/effects/node/memory/module.d.ts +0 -0
- /package/{fs → fjs}/effects/node/memory/module.js +0 -0
- /package/{fs → fjs}/effects/node/memory/proof.d.ts +0 -0
- /package/{fs → fjs}/effects/node/module.f.js +0 -0
- /package/{fs → fjs}/effects/node/virtual/module.f.d.ts +0 -0
- /package/{fs → fjs}/effects/node/virtual/module.f.js +0 -0
- /package/{fs → fjs}/effects/proof.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/all.test.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/all.test.js +0 -0
- /package/{fs → fjs}/emergent_testing/example.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/example.f.js +0 -0
- /package/{fs → fjs}/emergent_testing/module.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/module.f.js +0 -0
- /package/{fs → fjs}/emergent_testing/proof.f.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/all.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/all.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async-subtests.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/async.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/fail.fail.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/fail.fail.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/return-value.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/return-value.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable2.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/thenable2.pass.js +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/throw.pass.d.ts +0 -0
- /package/{fs → fjs}/emergent_testing/scenarios/throw.pass.js +0 -0
- /package/{fs → fjs}/fsc/bnf.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/bnf.f.js +0 -0
- /package/{fs → fjs}/fsc/json.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/json.f.js +0 -0
- /package/{fs → fjs}/fsc/module.f.d.ts +0 -0
- /package/{fs → fjs}/fsc/module.f.js +0 -0
- /package/{fs → fjs}/fsc/proof.f.d.ts +0 -0
- /package/{fs → fjs}/fsm/module.f.d.ts +0 -0
- /package/{fs → fjs}/fsm/module.f.js +0 -0
- /package/{fs → fjs}/fsm/proof.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/module.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/module.f.js +0 -0
- /package/{fs → fjs}/js/tokenizer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/js/tokenizer/proof.f.js +0 -0
- /package/{fs → fjs}/mcp/proof.f.d.ts +0 -0
- /package/{fs → fjs}/mcp/stdio/proof.f.d.ts +0 -0
- /package/{fs → fjs}/mcp/stdio/proof.f.js +0 -0
- /package/{fs → fjs}/media/html/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/html/module.f.js +0 -0
- /package/{fs → fjs}/media/html/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/module.f.js +0 -0
- /package/{fs → fjs}/media/json/parser/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/proof.f.js +0 -0
- /package/{fs → fjs}/media/json/rpc/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/rpc/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/rpc/proof.f.js +0 -0
- /package/{fs → fjs}/media/json/schema/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/serializer/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/serializer/module.f.js +0 -0
- /package/{fs → fjs}/media/json/serializer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/module.f.js +0 -0
- /package/{fs → fjs}/media/json/tokenizer/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/json/tokenizer/proof.f.js +0 -0
- /package/{fs → fjs}/media/proof.f.d.ts +0 -0
- /package/{fs → fjs}/media/type/module.f.d.ts +0 -0
- /package/{fs → fjs}/media/type/module.f.js +0 -0
- /package/{fs → fjs}/media/type/proof.f.d.ts +0 -0
- /package/{fs → fjs}/module.d.ts +0 -0
- /package/{fs → fjs}/module.f.d.ts +0 -0
- /package/{fs → fjs}/module.js +0 -0
- /package/{fs → fjs}/path/module.f.d.ts +0 -0
- /package/{fs → fjs}/path/module.f.js +0 -0
- /package/{fs → fjs}/path/proof.f.d.ts +0 -0
- /package/{fs → fjs}/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/id/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/id/module.f.js +0 -0
- /package/{fs → fjs}/sul/id/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/hash/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/hash/module.f.js +0 -0
- /package/{fs → fjs}/sul/level/hash/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/literal/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/level/literal/module.f.js +0 -0
- /package/{fs → fjs}/sul/level/literal/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/module.f.d.ts +0 -0
- /package/{fs → fjs}/sul/module.f.js +0 -0
- /package/{fs → fjs}/sul/proof.f.d.ts +0 -0
- /package/{fs → fjs}/sul/proof.f.js +0 -0
- /package/{fs → fjs}/text/ascii/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/ascii/module.f.js +0 -0
- /package/{fs → fjs}/text/code_point/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/code_point/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/code_point/proof.f.js +0 -0
- /package/{fs → fjs}/text/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/module.f.js +0 -0
- /package/{fs → fjs}/text/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/sgr/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/sgr/module.f.js +0 -0
- /package/{fs → fjs}/text/sgr/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf16/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf16/proof.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf8/module.f.d.ts +0 -0
- /package/{fs → fjs}/text/utf8/module.f.js +0 -0
- /package/{fs → fjs}/text/utf8/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/array/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/array/module.f.js +0 -0
- /package/{fs → fjs}/types/array/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigfloat/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigfloat/module.f.js +0 -0
- /package/{fs → fjs}/types/bigfloat/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigint/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bigint/module.f.js +0 -0
- /package/{fs → fjs}/types/bigint/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/bit_vec/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/bit_vec/module.f.js +0 -0
- /package/{fs → fjs}/types/bit_vec/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/find/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/find/module.f.js +0 -0
- /package/{fs → fjs}/types/btree/find/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/module.f.js +0 -0
- /package/{fs → fjs}/types/btree/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/remove/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/remove/module.f.js +0 -0
- /package/{fs → fjs}/types/btree/set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/types/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/btree/types/module.f.js +0 -0
- /package/{fs → fjs}/types/byte_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/byte_set/module.f.js +0 -0
- /package/{fs → fjs}/types/byte_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/compare/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/compare/module.f.js +0 -0
- /package/{fs → fjs}/types/function/compare/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/module.f.js +0 -0
- /package/{fs → fjs}/types/function/operator/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/operator/module.f.js +0 -0
- /package/{fs → fjs}/types/function/operator/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/function/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/list/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/list/module.f.js +0 -0
- /package/{fs → fjs}/types/list/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/map/module.f.js +0 -0
- /package/{fs → fjs}/types/map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nibble_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nibble_set/module.f.js +0 -0
- /package/{fs → fjs}/types/nibble_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nominal/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nominal/module.f.js +0 -0
- /package/{fs → fjs}/types/nominal/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/nullable/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/nullable/module.f.js +0 -0
- /package/{fs → fjs}/types/nullable/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/number/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/number/module.f.js +0 -0
- /package/{fs → fjs}/types/number/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/object/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/object/module.f.js +0 -0
- /package/{fs → fjs}/types/object/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/option/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/option/module.f.js +0 -0
- /package/{fs → fjs}/types/ordered_map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/ordered_map/module.f.js +0 -0
- /package/{fs → fjs}/types/ordered_map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/ordered_map/proof.f.js +0 -0
- /package/{fs → fjs}/types/patricia_trie/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/patricia_trie/module.f.js +0 -0
- /package/{fs → fjs}/types/patricia_trie/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/phantom/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/phantom/module.f.js +0 -0
- /package/{fs → fjs}/types/prime_field/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/prime_field/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/prime_field/proof.f.js +0 -0
- /package/{fs → fjs}/types/range/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/range_map/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/range_map/module.f.js +0 -0
- /package/{fs → fjs}/types/range_map/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/result/module.f.js +0 -0
- /package/{fs → fjs}/types/result/module.js +0 -0
- /package/{fs → fjs}/types/rtti/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/module.f.js +0 -0
- /package/{fs → fjs}/types/rtti/parse/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/parse/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/proof.f.js +0 -0
- /package/{fs → fjs}/types/rtti/ts/module.f.js +0 -0
- /package/{fs → fjs}/types/rtti/ts/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/ts/proof.f.js +0 -0
- /package/{fs → fjs}/types/rtti/validate/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/rtti/validate/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_list/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_list/module.f.js +0 -0
- /package/{fs → fjs}/types/sorted_list/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/sorted_set/module.f.js +0 -0
- /package/{fs → fjs}/types/sorted_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/string/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/string/module.f.js +0 -0
- /package/{fs → fjs}/types/string/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/string_set/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/string_set/module.f.js +0 -0
- /package/{fs → fjs}/types/string_set/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/ts/module.f.d.ts +0 -0
- /package/{fs → fjs}/types/ts/module.f.js +0 -0
- /package/{fs → fjs}/types/ts/proof.f.d.ts +0 -0
- /package/{fs → fjs}/types/uint8array/module.f.d.ts +0 -0
- /package/{fs → fjs}/website/module.f.d.ts +0 -0
- /package/{fs → fjs}/website/module.f.js +0 -0
- /package/{fs → fjs}/website/proof.f.d.ts +0 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
import { assert, assertEq } from '../../asserts/module.f.js';
|
|
2
|
+
import { pure } from '../../effects/module.f.js';
|
|
3
|
+
import { fileCas } from '../module.f.js';
|
|
4
|
+
import { sha256 } from '../../crypto/sha2/module.f.js';
|
|
5
|
+
import { emptyState, virtual } from '../../effects/node/virtual/module.f.js';
|
|
6
|
+
import { vec, vec8 } from '../../types/bit_vec/module.f.js';
|
|
7
|
+
import { cBase32ToVec, vecToCBase32 } from '../../basen/cbase32/module.f.js';
|
|
8
|
+
import { unwrap } from '../../types/nullable/module.f.js';
|
|
9
|
+
import { ok, error } from '../../types/result/module.f.js';
|
|
10
|
+
import { nonEmpty, empty as elEmpty } from '../../effects/list/module.f.js';
|
|
11
|
+
import { tryUtf8 } from '../../text/module.f.js';
|
|
12
|
+
import { dialect as revisionDialect } from '../../media/revision/module.f.js';
|
|
13
|
+
import { buildCache, decodeRevisionBlob, initEvo, evo, emptyCache, syncRevision, } from './module.f.js';
|
|
14
|
+
const home = '.';
|
|
15
|
+
// A `Cas<never>` whose `write` always fails — used to reach `addRevision`'s
|
|
16
|
+
// store-write-failure branch, which real `fileCas` has no easy way to trigger.
|
|
17
|
+
const writeFailingCas = {
|
|
18
|
+
read: () => elEmpty(),
|
|
19
|
+
write: () => pure(error('boom')),
|
|
20
|
+
list: () => pure([]),
|
|
21
|
+
};
|
|
22
|
+
// A `Cas<never>` backed by a fixed set of (hash, content) entries, returned
|
|
23
|
+
// from `list()` in exactly the given order — used to control the order
|
|
24
|
+
// `buildCache` sees hashes in, independent of any real filesystem's
|
|
25
|
+
// (hash-lexical, not causal) directory-listing order.
|
|
26
|
+
const fixedCas = (entries) => ({
|
|
27
|
+
read: hash => {
|
|
28
|
+
const found = entries.find(([h]) => vecToCBase32(h) === vecToCBase32(hash));
|
|
29
|
+
return found === undefined
|
|
30
|
+
? nonEmpty(error('not found'), elEmpty())
|
|
31
|
+
: nonEmpty(ok(found[1]), elEmpty());
|
|
32
|
+
},
|
|
33
|
+
write: () => pure(error('write not supported')),
|
|
34
|
+
list: () => pure(entries.map(([h]) => h)),
|
|
35
|
+
});
|
|
36
|
+
export const proof = {
|
|
37
|
+
buildCacheEmptyStoreYieldsEmptyCache: () => {
|
|
38
|
+
const c = fileCas(sha256)(home);
|
|
39
|
+
const [, cache] = virtual(emptyState)(buildCache(c));
|
|
40
|
+
assertEq(JSON.stringify(cache), JSON.stringify(emptyCache));
|
|
41
|
+
},
|
|
42
|
+
buildCacheSkipsNonRevisionBlob: () => {
|
|
43
|
+
const c = fileCas(sha256)(home);
|
|
44
|
+
const content = vec8(0x41n); // 'A' — valid UTF-8, not revision JSON
|
|
45
|
+
const [state1] = virtual(emptyState)(c.write(nonEmpty(ok(content), elEmpty())));
|
|
46
|
+
const [, cache] = virtual(state1)(buildCache(c));
|
|
47
|
+
assertEq(Object.keys(cache.bySubject).length, 0);
|
|
48
|
+
},
|
|
49
|
+
decodeRevisionBlobMissingHashIsNull: () => {
|
|
50
|
+
const c = fileCas(sha256)(home);
|
|
51
|
+
const [, revision] = virtual(emptyState)(decodeRevisionBlob(c)(vec8(0x99n)));
|
|
52
|
+
assertEq(revision, null);
|
|
53
|
+
},
|
|
54
|
+
decodeRevisionBlobNonUtf8IsNull: () => {
|
|
55
|
+
const c = fileCas(sha256)(home);
|
|
56
|
+
const oddVec = vec(5n)(21n); // not a whole number of bytes
|
|
57
|
+
const [state1, w] = virtual(emptyState)(c.write(nonEmpty(ok(oddVec), elEmpty())));
|
|
58
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
59
|
+
const [, revision] = virtual(state1)(decodeRevisionBlob(c)(w[1]));
|
|
60
|
+
assertEq(revision, null);
|
|
61
|
+
},
|
|
62
|
+
decodeRevisionBlobInvalidJsonIsNull: () => {
|
|
63
|
+
const c = fileCas(sha256)(home);
|
|
64
|
+
const content = vec8(0x7bn); // '{' alone: valid UTF-8, not parseable JSON
|
|
65
|
+
const [state1, w] = virtual(emptyState)(c.write(nonEmpty(ok(content), elEmpty())));
|
|
66
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
67
|
+
const [, revision] = virtual(state1)(decodeRevisionBlob(c)(w[1]));
|
|
68
|
+
assertEq(revision, null);
|
|
69
|
+
},
|
|
70
|
+
decodeRevisionBlobValidRevisionRoundTrips: () => {
|
|
71
|
+
const c = fileCas(sha256)(home);
|
|
72
|
+
const subjectHash = vecToCBase32(vec8(0x11n));
|
|
73
|
+
const text = `{"dialect":"${revisionDialect}","subject":"${subjectHash}","parents":[],"snapshot":"${subjectHash}","generation":0}`;
|
|
74
|
+
const bytes = tryUtf8(text);
|
|
75
|
+
assert(bytes !== null, 'expected the sample revision text to encode as UTF-8');
|
|
76
|
+
const [state1, w] = virtual(emptyState)(c.write(nonEmpty(ok(bytes), elEmpty())));
|
|
77
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
78
|
+
const [, revision] = virtual(state1)(decodeRevisionBlob(c)(w[1]));
|
|
79
|
+
assert(revision !== null, 'expected a decoded revision');
|
|
80
|
+
assertEq(revision?.subject, subjectHash);
|
|
81
|
+
},
|
|
82
|
+
buildCacheIncludesScannedRevision: () => {
|
|
83
|
+
// Unlike the `add`-driven tests below (which fold one revision at a
|
|
84
|
+
// time), this seeds a `vnd.fjs.revision` blob directly into the store
|
|
85
|
+
// and scans it with `buildCache`, covering the "found a revision"
|
|
86
|
+
// branch of the full-store fold.
|
|
87
|
+
const c = fileCas(sha256)(home);
|
|
88
|
+
const subjectHash = vecToCBase32(vec8(0x12n));
|
|
89
|
+
const text = `{"dialect":"${revisionDialect}","subject":"${subjectHash}","parents":[],"snapshot":"${subjectHash}","generation":0}`;
|
|
90
|
+
const bytes = tryUtf8(text);
|
|
91
|
+
assert(bytes !== null, 'expected the sample revision text to encode as UTF-8');
|
|
92
|
+
const [state1, w] = virtual(emptyState)(fileCas(sha256)(home).write(nonEmpty(ok(bytes), elEmpty())));
|
|
93
|
+
assert(w[0] === 'ok', ['expected write ok', w]);
|
|
94
|
+
const [, cache] = virtual(state1)(buildCache(c));
|
|
95
|
+
assertEq(cache.bySubject[subjectHash]?.hashes.length, 1);
|
|
96
|
+
assertEq(cache.bySubject[subjectHash]?.hashes[0], vecToCBase32(w[1]));
|
|
97
|
+
},
|
|
98
|
+
// Regression: `cas.list()` enumerates a real store by hash-sharded path,
|
|
99
|
+
// not revision ancestry, so a child's hash can sort (and therefore be
|
|
100
|
+
// scanned) before its parent's. `buildCache` must still end up with only
|
|
101
|
+
// the child as a head — the whole point of tracking `hashes`/`parents`
|
|
102
|
+
// as separate sets (see the module doc) rather than an incremental head
|
|
103
|
+
// list.
|
|
104
|
+
buildCacheOrderIndependentWhenChildScannedBeforeParent: () => {
|
|
105
|
+
const rootHash = vec8(0xaan);
|
|
106
|
+
const childHash = vec8(0xbbn);
|
|
107
|
+
const rootCBase32 = vecToCBase32(rootHash);
|
|
108
|
+
const childCBase32 = vecToCBase32(childHash);
|
|
109
|
+
const snapshotHash = vecToCBase32(vec8(0xccn));
|
|
110
|
+
const rootText = `{"dialect":"${revisionDialect}","subject":"doc","parents":[],"snapshot":"${snapshotHash}","generation":0}`;
|
|
111
|
+
const childText = `{"dialect":"${revisionDialect}","subject":"doc","parents":["${rootCBase32}"],"snapshot":"${snapshotHash}","generation":1}`;
|
|
112
|
+
const rootBytes = tryUtf8(rootText);
|
|
113
|
+
const childBytes = tryUtf8(childText);
|
|
114
|
+
assert(rootBytes !== null && childBytes !== null, 'expected sample revisions to encode as UTF-8');
|
|
115
|
+
const cas = fixedCas([[childHash, childBytes], [rootHash, rootBytes]]);
|
|
116
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(cas));
|
|
117
|
+
const [, heads] = virtual(state0)(evo(cas)(cacheKey).head('doc'));
|
|
118
|
+
assertEq(heads.length, 1);
|
|
119
|
+
assertEq(heads[0], childCBase32);
|
|
120
|
+
},
|
|
121
|
+
// Regression: `cBase32ToVec` accepts more than one spelling of the same
|
|
122
|
+
// hash (case, and the `i`/`l`/`o` alphabet aliases). A parent reference
|
|
123
|
+
// recorded in a non-canonical spelling must still demote the parent from
|
|
124
|
+
// the head set — `headsOf` compares hash strings directly, so caching
|
|
125
|
+
// the parent verbatim (instead of its canonical `vecToCBase32` spelling)
|
|
126
|
+
// would leave the parent listed as a head alongside its child.
|
|
127
|
+
buildCacheCanonicalizesNonCanonicalParentHashes: () => {
|
|
128
|
+
const rootHash = vec8(0xffn);
|
|
129
|
+
const rootCanonical = vecToCBase32(rootHash); // "zy" — has letters to uppercase
|
|
130
|
+
const rootNonCanonical = rootCanonical.toUpperCase();
|
|
131
|
+
assert(rootNonCanonical !== rootCanonical, 'expected the sample hash to contain letters');
|
|
132
|
+
const childHash = vec8(0xeen);
|
|
133
|
+
const snapshotHash = vecToCBase32(vec8(0xddn));
|
|
134
|
+
const rootText = `{"dialect":"${revisionDialect}","subject":"doc","parents":[],"snapshot":"${snapshotHash}","generation":0}`;
|
|
135
|
+
const childText = `{"dialect":"${revisionDialect}","subject":"doc","parents":["${rootNonCanonical}"],"snapshot":"${snapshotHash}","generation":1}`;
|
|
136
|
+
const rootBytes = tryUtf8(rootText);
|
|
137
|
+
const childBytes = tryUtf8(childText);
|
|
138
|
+
assert(rootBytes !== null && childBytes !== null, 'expected sample revisions to encode as UTF-8');
|
|
139
|
+
const cas = fixedCas([[rootHash, rootBytes], [childHash, childBytes]]);
|
|
140
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(cas));
|
|
141
|
+
const [, heads] = virtual(state0)(evo(cas)(cacheKey).head('doc'));
|
|
142
|
+
assertEq(heads.length, 1);
|
|
143
|
+
assertEq(heads[0], vecToCBase32(childHash));
|
|
144
|
+
},
|
|
145
|
+
// Two concurrent children of one root: both become heads, the root stops
|
|
146
|
+
// being one. Exercises addRevisionToCache's fold across a first insert
|
|
147
|
+
// (no prior heads for the subject), a removal (a parent leaving the head
|
|
148
|
+
// set), and a keep (an unrelated existing head surviving the fold).
|
|
149
|
+
addRevisionBuildsHeadsAcrossChainAndFork: () => {
|
|
150
|
+
const c = fileCas(sha256)(home);
|
|
151
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
152
|
+
const e = evo(c)(cacheKey);
|
|
153
|
+
const snapshotHash = vecToCBase32(vec8(0x22n));
|
|
154
|
+
const rev0 = { parents: [], subject: 'doc', snapshot: snapshotHash };
|
|
155
|
+
const [state1, rev0Result] = virtual(state0)(e.add(rev0));
|
|
156
|
+
assert(rev0Result[0] === 'ok', ['expected rev0 ok', rev0Result]);
|
|
157
|
+
const rev0Hash = rev0Result[1];
|
|
158
|
+
// rev1 inherits rev0's snapshot; rev2 states a different one — so the
|
|
159
|
+
// two concurrent children are genuinely distinct blobs (both children
|
|
160
|
+
// of rev0, same generation), not one deduplicated revision.
|
|
161
|
+
const rev1 = { parents: [rev0Hash], subject: 'doc' };
|
|
162
|
+
const [state2, rev1Result] = virtual(state1)(e.add(rev1));
|
|
163
|
+
assert(rev1Result[0] === 'ok', ['expected rev1 ok', rev1Result]);
|
|
164
|
+
const rev1Hash = rev1Result[1];
|
|
165
|
+
const rev2 = { parents: [rev0Hash], subject: 'doc', snapshot: vecToCBase32(vec8(0x23n)) };
|
|
166
|
+
const [state3, rev2Result] = virtual(state2)(e.add(rev2));
|
|
167
|
+
assert(rev2Result[0] === 'ok', ['expected rev2 ok', rev2Result]);
|
|
168
|
+
const rev2Hash = rev2Result[1];
|
|
169
|
+
const [state4, heads] = virtual(state3)(e.head('doc'));
|
|
170
|
+
assertEq(heads.length, 2);
|
|
171
|
+
assert(heads.includes(rev1Hash), ['expected rev1 to remain a head', heads]);
|
|
172
|
+
assert(heads.includes(rev2Hash), ['expected rev2 to be a head', heads]);
|
|
173
|
+
assert(!heads.includes(rev0Hash), ['expected rev0 to no longer be a head', heads]);
|
|
174
|
+
const [, subjects] = virtual(state4)(e.list());
|
|
175
|
+
assertEq(subjects.length, 1);
|
|
176
|
+
assertEq(subjects[0], 'doc');
|
|
177
|
+
},
|
|
178
|
+
// Adding the exact same revision twice yields the same (deduplicated)
|
|
179
|
+
// content hash and must not duplicate the head entry.
|
|
180
|
+
addRevisionIdempotentOnDuplicateContent: () => {
|
|
181
|
+
const c = fileCas(sha256)(home);
|
|
182
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
183
|
+
const e = evo(c)(cacheKey);
|
|
184
|
+
const input = { parents: [], subject: 'x', snapshot: vecToCBase32(vec8(0x33n)) };
|
|
185
|
+
const [state1, r1] = virtual(state0)(e.add(input));
|
|
186
|
+
assert(r1[0] === 'ok', ['expected first add ok', r1]);
|
|
187
|
+
const [state2, r2] = virtual(state1)(e.add(input));
|
|
188
|
+
assert(r2[0] === 'ok', ['expected second add ok', r2]);
|
|
189
|
+
assertEq(r1[1], r2[1]);
|
|
190
|
+
const [, heads] = virtual(state2)(e.head('x'));
|
|
191
|
+
assertEq(heads.length, 1);
|
|
192
|
+
},
|
|
193
|
+
// Two `add` calls describing the same logical revision but spelling the
|
|
194
|
+
// parent reference differently (canonical vs. an accepted uppercase
|
|
195
|
+
// alias) must serialize identically and dedupe to one head — otherwise
|
|
196
|
+
// `addRevision` itself would be the source of the very spelling drift
|
|
197
|
+
// `canonicalHash` exists to prevent.
|
|
198
|
+
addRevisionCanonicalizesParentSpellingBeforeSerializing: () => {
|
|
199
|
+
const c = fileCas(sha256)(home);
|
|
200
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
201
|
+
const e = evo(c)(cacheKey);
|
|
202
|
+
const root = { parents: [], subject: 'doc', snapshot: vecToCBase32(vec8(0x2en)) };
|
|
203
|
+
const [state1, rootResult] = virtual(state0)(e.add(root));
|
|
204
|
+
assert(rootResult[0] === 'ok', ['expected root ok', rootResult]);
|
|
205
|
+
const rootHash = rootResult[1];
|
|
206
|
+
assert(rootHash !== rootHash.toUpperCase(), 'expected the sample hash to contain letters');
|
|
207
|
+
const child1 = { parents: [rootHash], subject: 'doc' };
|
|
208
|
+
const [state2, child1Result] = virtual(state1)(e.add(child1));
|
|
209
|
+
assert(child1Result[0] === 'ok', ['expected child1 ok', child1Result]);
|
|
210
|
+
const child2 = { parents: [rootHash.toUpperCase()], subject: 'doc' };
|
|
211
|
+
const [state3, child2Result] = virtual(state2)(e.add(child2));
|
|
212
|
+
assert(child2Result[0] === 'ok', ['expected child2 ok', child2Result]);
|
|
213
|
+
assertEq(child1Result[1], child2Result[1]);
|
|
214
|
+
const [, heads] = virtual(state3)(e.head('doc'));
|
|
215
|
+
assertEq(heads.length, 1);
|
|
216
|
+
assertEq(heads[0], child1Result[1]);
|
|
217
|
+
},
|
|
218
|
+
// `subject` omitted with exactly one parent is inherited from that
|
|
219
|
+
// parent's own `subject`.
|
|
220
|
+
addRevisionResolvesSubjectFromSingleParent: () => {
|
|
221
|
+
const c = fileCas(sha256)(home);
|
|
222
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
223
|
+
const e = evo(c)(cacheKey);
|
|
224
|
+
const root = { parents: [], subject: 'inherit-me', snapshot: vecToCBase32(vec8(0x44n)) };
|
|
225
|
+
const [state1, rootResult] = virtual(state0)(e.add(root));
|
|
226
|
+
assert(rootResult[0] === 'ok', ['expected root ok', rootResult]);
|
|
227
|
+
const rootHash = rootResult[1];
|
|
228
|
+
const child = { parents: [rootHash] };
|
|
229
|
+
const [state2, childResult] = virtual(state1)(e.add(child));
|
|
230
|
+
assert(childResult[0] === 'ok', ['expected child ok', childResult]);
|
|
231
|
+
const childHash = childResult[1];
|
|
232
|
+
const [, heads] = virtual(state2)(e.head('inherit-me'));
|
|
233
|
+
assertEq(heads.length, 1);
|
|
234
|
+
assertEq(heads[0], childHash);
|
|
235
|
+
},
|
|
236
|
+
// `add` writes both inference-derived fields explicitly: a root gets
|
|
237
|
+
// `generation` 0 and, with no input `snapshot`, its `subject` (a hash) as
|
|
238
|
+
// the snapshot reference; a single-parent child with no input `snapshot`
|
|
239
|
+
// inherits the parent's stored snapshot and gets `generation` 1.
|
|
240
|
+
addComputesGenerationAndResolvesSnapshot: () => {
|
|
241
|
+
const c = fileCas(sha256)(home);
|
|
242
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
243
|
+
const e = evo(c)(cacheKey);
|
|
244
|
+
const subjectHash = vecToCBase32(vec8(0x71n));
|
|
245
|
+
const [state1, rootResult] = virtual(state0)(e.add({ parents: [], subject: subjectHash }));
|
|
246
|
+
assert(rootResult[0] === 'ok', ['expected root ok', rootResult]);
|
|
247
|
+
const rootHashVec = unwrap(cBase32ToVec(rootResult[1]));
|
|
248
|
+
const [state2, root] = virtual(state1)(decodeRevisionBlob(c)(rootHashVec));
|
|
249
|
+
assert(root !== null, 'expected the stored root to decode');
|
|
250
|
+
assertEq(root?.generation, 0);
|
|
251
|
+
assertEq(root?.snapshot, subjectHash);
|
|
252
|
+
const [state3, childResult] = virtual(state2)(e.add({ parents: [rootResult[1]], subject: subjectHash }));
|
|
253
|
+
assert(childResult[0] === 'ok', ['expected child ok', childResult]);
|
|
254
|
+
const childHashVec = unwrap(cBase32ToVec(childResult[1]));
|
|
255
|
+
const [, child] = virtual(state3)(decodeRevisionBlob(c)(childHashVec));
|
|
256
|
+
assert(child !== null, 'expected the stored child to decode');
|
|
257
|
+
assertEq(child?.generation, 1);
|
|
258
|
+
assertEq(child?.snapshot, subjectHash);
|
|
259
|
+
},
|
|
260
|
+
// A merge takes `1 + max(parents' generations)`: a parent at generation 2
|
|
261
|
+
// and one at generation 1 yield generation 3.
|
|
262
|
+
addComputesMergeGenerationFromMaxOfParents: () => {
|
|
263
|
+
const c = fileCas(sha256)(home);
|
|
264
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
265
|
+
const e = evo(c)(cacheKey);
|
|
266
|
+
const snap = vecToCBase32(vec8(0x72n));
|
|
267
|
+
// Mainline chain: root(gen0) → a(gen1) → b(gen2).
|
|
268
|
+
const [state1, root] = virtual(state0)(e.add({ parents: [], subject: 'm', snapshot: snap }));
|
|
269
|
+
assert(root[0] === 'ok', ['expected root ok', root]);
|
|
270
|
+
const [state2, a] = virtual(state1)(e.add({ parents: [root[1]], subject: 'm', snapshot: snap }));
|
|
271
|
+
assert(a[0] === 'ok', ['expected a ok', a]);
|
|
272
|
+
const [state3, b] = virtual(state2)(e.add({ parents: [a[1]], subject: 'm', snapshot: snap }));
|
|
273
|
+
assert(b[0] === 'ok', ['expected b ok', b]);
|
|
274
|
+
// Side branch off root: c(gen1).
|
|
275
|
+
const [state4, cRev] = virtual(state3)(e.add({ parents: [root[1]], subject: 'm', snapshot: snap }));
|
|
276
|
+
assert(cRev[0] === 'ok', ['expected c ok', cRev]);
|
|
277
|
+
// Merge of b(gen2) and c(gen1) → gen3.
|
|
278
|
+
const [state5, merge] = virtual(state4)(e.add({ parents: [b[1], cRev[1]], subject: 'm', snapshot: snap }));
|
|
279
|
+
assert(merge[0] === 'ok', ['expected merge ok', merge]);
|
|
280
|
+
const mergeHashVec = unwrap(cBase32ToVec(merge[1]));
|
|
281
|
+
const [, mergeRev] = virtual(state5)(decodeRevisionBlob(c)(mergeHashVec));
|
|
282
|
+
assert(mergeRev !== null, 'expected the stored merge to decode');
|
|
283
|
+
assertEq(mergeRev?.generation, 3);
|
|
284
|
+
},
|
|
285
|
+
addRevisionSubjectRequiredForZeroParents: () => {
|
|
286
|
+
const c = fileCas(sha256)(home);
|
|
287
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
288
|
+
const e = evo(c)(cacheKey);
|
|
289
|
+
const [, result] = virtual(state0)(e.add({ parents: [] }));
|
|
290
|
+
assertEq(result[0], 'error');
|
|
291
|
+
assert(result[0] === 'error' && result[1].includes('subject is required'), ['unexpected message', result]);
|
|
292
|
+
},
|
|
293
|
+
// Zero parents and no input `snapshot`: `resolveSnapshot` falls back to
|
|
294
|
+
// `subject` as the reference, which must itself be a hash. A subject with
|
|
295
|
+
// characters outside the cbase32 alphabet ('not-a-hash!') therefore has
|
|
296
|
+
// nothing to resolve the snapshot to and is an error — the format requires
|
|
297
|
+
// an explicit `snapshot`.
|
|
298
|
+
addRevisionNonHashSubjectWithoutSnapshotIsError: () => {
|
|
299
|
+
const c = fileCas(sha256)(home);
|
|
300
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
301
|
+
const e = evo(c)(cacheKey);
|
|
302
|
+
const [, result] = virtual(state0)(e.add({ parents: [], subject: 'not-a-hash!' }));
|
|
303
|
+
assertEq(result[0], 'error');
|
|
304
|
+
assert(result[0] === 'error' && result[1].includes('subject must be a valid hash'), ['unexpected message', result]);
|
|
305
|
+
},
|
|
306
|
+
addRevisionInvalidParentHashIsError: () => {
|
|
307
|
+
const c = fileCas(sha256)(home);
|
|
308
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
309
|
+
const e = evo(c)(cacheKey);
|
|
310
|
+
const [, result] = virtual(state0)(e.add({ parents: ['not a valid cbase32!'] }));
|
|
311
|
+
assertEq(result[0], 'error');
|
|
312
|
+
assert(result[0] === 'error' && result[1].includes('invalid parent hash'), ['unexpected message', result]);
|
|
313
|
+
},
|
|
314
|
+
addRevisionParentNotARevisionIsError: () => {
|
|
315
|
+
const c = fileCas(sha256)(home);
|
|
316
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
317
|
+
const e = evo(c)(cacheKey);
|
|
318
|
+
const missingParent = vecToCBase32(vec8(0x55n));
|
|
319
|
+
const [, result] = virtual(state0)(e.add({ parents: [missingParent] }));
|
|
320
|
+
assertEq(result[0], 'error');
|
|
321
|
+
assert(result[0] === 'error' && result[1].includes('parent is not a revision blob'), ['unexpected message', result]);
|
|
322
|
+
},
|
|
323
|
+
// An explicit `subject` must not bypass parent validation: a missing
|
|
324
|
+
// parent is still an error even though `subject` alone would otherwise
|
|
325
|
+
// resolve without looking at any parent.
|
|
326
|
+
addRevisionValidatesParentsEvenWithExplicitSubject: () => {
|
|
327
|
+
const c = fileCas(sha256)(home);
|
|
328
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
329
|
+
const e = evo(c)(cacheKey);
|
|
330
|
+
const missingParent = vecToCBase32(vec8(0x66n));
|
|
331
|
+
const [, result] = virtual(state0)(e.add({ parents: [missingParent], subject: 'doc' }));
|
|
332
|
+
assertEq(result[0], 'error');
|
|
333
|
+
assert(result[0] === 'error' && result[1].includes('parent is not a revision blob'), ['unexpected message', result]);
|
|
334
|
+
},
|
|
335
|
+
// A revision models one step in the evolution of a single subject: a
|
|
336
|
+
// parent that actually belongs to a *different* subject must be
|
|
337
|
+
// rejected, even though it exists and is a valid revision — otherwise
|
|
338
|
+
// the new revision would silently graft onto an unrelated object's
|
|
339
|
+
// history, and head demotion (scoped to the child's own subject) would
|
|
340
|
+
// never remove the parent from its real subject's head set.
|
|
341
|
+
addRevisionRejectsCrossSubjectParent: () => {
|
|
342
|
+
const c = fileCas(sha256)(home);
|
|
343
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
344
|
+
const e = evo(c)(cacheKey);
|
|
345
|
+
const rootA = { parents: [], subject: 'A', snapshot: vecToCBase32(vec8(0x67n)) };
|
|
346
|
+
const [state1, rootAResult] = virtual(state0)(e.add(rootA));
|
|
347
|
+
assert(rootAResult[0] === 'ok', ['expected rootA ok', rootAResult]);
|
|
348
|
+
const [, result] = virtual(state1)(e.add({ parents: [rootAResult[1]], subject: 'B' }));
|
|
349
|
+
assertEq(result[0], 'error');
|
|
350
|
+
assert(result[0] === 'error' && result[1].includes('different subject'), ['unexpected message', result]);
|
|
351
|
+
},
|
|
352
|
+
// With multiple parents, a failure on an earlier one short-circuits the
|
|
353
|
+
// fold — the second (here, a well-formed but nonexistent) parent is
|
|
354
|
+
// never even looked up.
|
|
355
|
+
addRevisionShortCircuitsOnFirstInvalidParentAmongMultiple: () => {
|
|
356
|
+
const c = fileCas(sha256)(home);
|
|
357
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
358
|
+
const e = evo(c)(cacheKey);
|
|
359
|
+
const missingParent = vecToCBase32(vec8(0x99n));
|
|
360
|
+
const [, result] = virtual(state0)(e.add({ parents: ['not a valid cbase32!', missingParent], subject: 'doc' }));
|
|
361
|
+
assertEq(result[0], 'error');
|
|
362
|
+
assert(result[0] === 'error' && result[1].includes('invalid parent hash'), ['unexpected message', result]);
|
|
363
|
+
},
|
|
364
|
+
// Two *valid* parents without an explicit `snapshot` cannot resolve one
|
|
365
|
+
// (no single parent snapshot to inherit) — a distinct failure from a
|
|
366
|
+
// missing/invalid parent, reported by `resolveSnapshot` at the write
|
|
367
|
+
// boundary now that the format requires an explicit `snapshot`.
|
|
368
|
+
addRevisionInvalidReferencesIsError: () => {
|
|
369
|
+
const c = fileCas(sha256)(home);
|
|
370
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
371
|
+
const e = evo(c)(cacheKey);
|
|
372
|
+
const rootA = { parents: [], subject: 'merge', snapshot: vecToCBase32(vec8(0x77n)) };
|
|
373
|
+
const [state1, rootAResult] = virtual(state0)(e.add(rootA));
|
|
374
|
+
assert(rootAResult[0] === 'ok', ['expected rootA ok', rootAResult]);
|
|
375
|
+
const rootB = { parents: [], subject: 'merge', snapshot: vecToCBase32(vec8(0x88n)) };
|
|
376
|
+
const [state2, rootBResult] = virtual(state1)(e.add(rootB));
|
|
377
|
+
assert(rootBResult[0] === 'ok', ['expected rootB ok', rootBResult]);
|
|
378
|
+
const [, result] = virtual(state2)(e.add({ parents: [rootAResult[1], rootBResult[1]], subject: 'merge' }));
|
|
379
|
+
assertEq(result[0], 'error');
|
|
380
|
+
assert(result[0] === 'error' && !result[1].includes('parent is not a revision blob'), ['unexpected message', result]);
|
|
381
|
+
},
|
|
382
|
+
addRevisionTooLargeToEncodeIsError: () => {
|
|
383
|
+
const c = fileCas(sha256)(home);
|
|
384
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
385
|
+
const e = evo(c)(cacheKey);
|
|
386
|
+
const hugeSubject = 'x'.repeat(200_000);
|
|
387
|
+
const input = { parents: [], subject: hugeSubject, snapshot: vecToCBase32(vec8(0x88n)) };
|
|
388
|
+
const [, result] = virtual(state0)(e.add(input));
|
|
389
|
+
assertEq(result[0], 'error');
|
|
390
|
+
assert(result[0] === 'error' && result[1] === 'revision too large to encode', ['unexpected message', result]);
|
|
391
|
+
},
|
|
392
|
+
addRevisionWriteFailureIsError: () => {
|
|
393
|
+
const [, cacheKey] = virtual(emptyState)(initEvo(writeFailingCas));
|
|
394
|
+
const e = evo(writeFailingCas)(cacheKey);
|
|
395
|
+
const [, result] = virtual(emptyState)(e.add({ parents: [], subject: vecToCBase32(vec8(0x99n)) }));
|
|
396
|
+
assertEq(result[0], 'error');
|
|
397
|
+
assert(result[0] === 'error' && result[1] === 'failed to write revision to CAS', ['unexpected message', result]);
|
|
398
|
+
},
|
|
399
|
+
// A raw CAS write (e.g. `cas_add`) of valid revision content is folded
|
|
400
|
+
// into the cache exactly as `addRevision` would, without going through
|
|
401
|
+
// `evo.add` — this is what keeps `cas_add` and `evo_add` writes to the
|
|
402
|
+
// same store consistent (see `fjs/cas/mcp`).
|
|
403
|
+
syncRevisionFoldsValidRevisionIntoCache: () => {
|
|
404
|
+
const c = fileCas(sha256)(home);
|
|
405
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
406
|
+
const subjectHash = vecToCBase32(vec8(0x13n));
|
|
407
|
+
const text = `{"dialect":"${revisionDialect}","subject":"${subjectHash}","parents":[],"snapshot":"${subjectHash}","generation":0}`;
|
|
408
|
+
const bytes = tryUtf8(text);
|
|
409
|
+
assert(bytes !== null, 'expected sample revision to encode as UTF-8');
|
|
410
|
+
const hashVec = vec8(0x14n);
|
|
411
|
+
const [state1] = virtual(state0)(syncRevision(cacheKey)(hashVec)(bytes));
|
|
412
|
+
const [, heads] = virtual(state1)(evo(c)(cacheKey).head(subjectHash));
|
|
413
|
+
assertEq(heads.length, 1);
|
|
414
|
+
assertEq(heads[0], vecToCBase32(hashVec));
|
|
415
|
+
},
|
|
416
|
+
syncRevisionIgnoresNonRevisionContent: () => {
|
|
417
|
+
const c = fileCas(sha256)(home);
|
|
418
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
419
|
+
const [state1] = virtual(state0)(syncRevision(cacheKey)(vec8(0x15n))(vec8(0x41n)));
|
|
420
|
+
const [, subjects] = virtual(state1)(evo(c)(cacheKey).list());
|
|
421
|
+
assertEq(subjects.length, 0);
|
|
422
|
+
},
|
|
423
|
+
evoHeadUnknownSubjectIsEmpty: () => {
|
|
424
|
+
const c = fileCas(sha256)(home);
|
|
425
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
426
|
+
const e = evo(c)(cacheKey);
|
|
427
|
+
const [, heads] = virtual(state0)(e.head('nope'));
|
|
428
|
+
assertEq(heads.length, 0);
|
|
429
|
+
},
|
|
430
|
+
// Regression: subjects are arbitrary caller-supplied strings, so one can
|
|
431
|
+
// collide with an inherited `Object.prototype` name. Plain bracket
|
|
432
|
+
// indexing on the `bySubject` map would return the inherited value
|
|
433
|
+
// (e.g. the `toString` function) instead of "no entry yet", crashing on
|
|
434
|
+
// `.hashes` — the cache must use an own-property lookup instead.
|
|
435
|
+
evoHeadUnknownPrototypeNamedSubjectIsEmpty: () => {
|
|
436
|
+
const c = fileCas(sha256)(home);
|
|
437
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
438
|
+
const e = evo(c)(cacheKey);
|
|
439
|
+
const [, heads] = virtual(state0)(e.head('constructor'));
|
|
440
|
+
assertEq(heads.length, 0);
|
|
441
|
+
},
|
|
442
|
+
evoAddAndHeadHandlePrototypeNamedSubject: () => {
|
|
443
|
+
const c = fileCas(sha256)(home);
|
|
444
|
+
const [state0, cacheKey] = virtual(emptyState)(initEvo(c));
|
|
445
|
+
const e = evo(c)(cacheKey);
|
|
446
|
+
const input = { parents: [], subject: 'toString', snapshot: vecToCBase32(vec8(0x16n)) };
|
|
447
|
+
const [state1, result] = virtual(state0)(e.add(input));
|
|
448
|
+
assert(result[0] === 'ok', ['expected add ok', result]);
|
|
449
|
+
const [, heads] = virtual(state1)(e.head('toString'));
|
|
450
|
+
assertEq(heads.length, 1);
|
|
451
|
+
assertEq(heads[0], result[1]);
|
|
452
|
+
},
|
|
453
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type Effect } from '../../effects/module.f.ts';
|
|
2
|
+
import { type MemOp } from '../../effects/memory/module.f.ts';
|
|
3
|
+
import { type Read, type Write } from '../../effects/node/module.f.ts';
|
|
4
|
+
import { type McpConfig, type McpHandlers, type ToolEntry } from '../../mcp/module.f.ts';
|
|
5
|
+
import { type FileCasOperation } from '../module.f.ts';
|
|
6
|
+
import { type Cache } from '../evo/module.f.ts';
|
|
7
|
+
import type { Key } from '../../effects/memory/module.f.ts';
|
|
8
|
+
/** Arguments for `cas_add`: content to store, with optional encoding type. */
|
|
9
|
+
export declare const casAddArgs: {
|
|
10
|
+
readonly content: import("../../types/rtti/module.f.ts").String;
|
|
11
|
+
readonly type: import("../../types/rtti/module.f.ts").Or<["text", "base64", undefined]>;
|
|
12
|
+
};
|
|
13
|
+
/** Arguments for `cas_get`: the cBase32 hash to look up; optionally request inline content. */
|
|
14
|
+
export declare const casGetArgs: {
|
|
15
|
+
readonly hash: import("../../types/rtti/module.f.ts").String;
|
|
16
|
+
readonly content: import("../../types/rtti/module.f.ts").Or<readonly [import("../../types/rtti/module.f.ts").Boolean, undefined]>;
|
|
17
|
+
};
|
|
18
|
+
/** Arguments for `cas_list`: none. */
|
|
19
|
+
export declare const casListArgs: {};
|
|
20
|
+
/**
|
|
21
|
+
* Registry of all CAS tools, bound to `home` and the Evo cache at
|
|
22
|
+
* `cacheKey`. `cas_add` is the only tool that writes, so it is the only one
|
|
23
|
+
* that needs `cacheKey`: a successfully stored blob is folded into the Evo
|
|
24
|
+
* cache via `syncRevision` when it happens to be a `vnd.fjs.revision` — a
|
|
25
|
+
* plain `cas_add` and `evo_add` are two ways to reach the same store, and
|
|
26
|
+
* this keeps `evo_list`/`evo_head` honest about either one without a
|
|
27
|
+
* rescan.
|
|
28
|
+
*/
|
|
29
|
+
export declare const casToolRegistry: (home: string) => (cacheKey: Key<Cache>) => readonly ToolEntry<FileCasOperation | MemOp>[];
|
|
30
|
+
/**
|
|
31
|
+
* MCP handlers for `FileCas` plus the Evo API (`fjs/cas/evo`) layered on it,
|
|
32
|
+
* bound to `home` and an already-built Evo cache slot (see `initEvo`).
|
|
33
|
+
*/
|
|
34
|
+
export declare const casMcpHandlers: (home: string) => (cacheKey: Key<Cache>) => McpHandlers<FileCasOperation | MemOp>;
|
|
35
|
+
/**
|
|
36
|
+
* Static MCP configuration for the CAS server: advertises the `tools`
|
|
37
|
+
* capability, identifies the server, and pins the protocol version.
|
|
38
|
+
*/
|
|
39
|
+
export declare const casConfig: McpConfig;
|
|
40
|
+
/**
|
|
41
|
+
* Runs the combined CAS + Evo MCP server over stdio: scans `~/.cas/` once to
|
|
42
|
+
* build the Evo subject/head cache (`initEvo`), allocates the session-state
|
|
43
|
+
* slot, builds the `mcpStep` for the merged tool registry, and drives the
|
|
44
|
+
* read → parse → dispatch → write loop until stdin EOF.
|
|
45
|
+
*/
|
|
46
|
+
export declare const casMcpServer: (home: string) => Effect<Read | Write | MemOp | FileCasOperation, void>;
|
|
47
|
+
export declare const proof: {
|
|
48
|
+
casMcpServer: () => void;
|
|
49
|
+
};
|