2026-09-30 01:59:28 +02:00
""" Generates the shared store-readability vectors. Every runtime ' s tests read the committed bytes and the verdicts in
manifest . txt ; nothing regenerates them at test time . Run : python generate . py ( needs msgpack ) .
A file may be replaced by a flush or a commit exactly when the runtime ' s own reader opens it, so one verdict per runtime
covers open , flush and commit . Each vector is the bytes named ; the trailing and truncated ones are cut from v3 - base .
"""
import pathlib
import msgpack
here = pathlib . Path ( __file__ ) . resolve ( ) . parent
whole = ( here . parent / " v3-base.msgpack " ) . read_bytes ( )
pack = lambda value : msgpack . packb ( value , use_bin_type = True )
Store readability: one typed refusal, one full reader, one store shape
CultStoreUnreadableException (a NotSupportedException) is the one refusal for a store file this runtime cannot read, thrown
by the single-file reader, the rewriting paths and CultMesh's reads, with the cause as the inner exception. The reader is exactly
one array of three slots (or an empty array): a header alone and an extra top-level slot are refused instead of read as empty or
skipped. CultMesh's older-catalog fallback is the same reader with the older entry reader, so it also requires one array.
Vectors: bad-body, header-only, missing-schema, variant-slot, extra-top-slot in the readability set, and a legacy-catalog store
with and without bytes after it for CultMesh. The persistence contract says what is true.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 04:06:44 +02:00
base = msgpack . unpackb ( whole , raw = False )
2026-09-30 01:59:28 +02:00
vectors = {
" zero-byte " : b " " ,
" empty-array " : pack ( [ ] ) ,
# A legacy envelope array: an array of maps. Rust, TypeScript and Python read it; C# has no legacy reader.
" legacy-envelopes " : pack ( [ { " key " : " old " , " type " : " old.type " , " payload " : pack ( [ ] ) , " storedAt " : " 2026-01-01T00:00:00Z " } ] ) ,
2026-09-30 02:39:29 +02:00
" legacy-trailing " : None , # filled below: the legacy array plus bytes after it
2026-09-30 01:59:28 +02:00
" ints " : pack ( [ 1 , 2 , 3 ] ) ,
" nil-first " : pack ( [ None , " x " ] ) ,
" nested-array " : pack ( [ [ " cultcache.store.v9 " , [ ] , [ ] ] ] ) ,
" string-first " : pack ( [ " hello " , 1 ] ) ,
" header-v9 " : pack ( [ " cultcache.store.v9 " , [ ] , [ ] ] ) ,
2026-10-02 21:05:37 +02:00
# A header stored as MessagePack bin, not str: every runtime refuses it as unreadable, never reads or names it.
" bin-header-v1 " : pack ( [ b " cultcache.store.v1 " , [ ] , [ ] ] ) ,
" bin-header-v3 " : pack ( [ b " cultcache.store.v3 " , [ ] , [ ] ] ) ,
" bin-header-v9 " : pack ( [ b " cultcache.store.v9 " , [ ] , [ ] ] ) ,
2026-09-30 01:59:28 +02:00
" scalar " : b " \x01 " ,
" map " : b " \x80 " ,
" truncated " : whole [ : - 1 ] ,
2026-10-02 23:53:36 +02:00
" trailing-byte " : whole + b " \x01 " ,
2026-09-30 01:59:28 +02:00
" trailing-bytes " : whole + b " \x01 \x02 \x03 " ,
" trailing-store " : whole + whole ,
Store readability: one typed refusal, one full reader, one store shape
CultStoreUnreadableException (a NotSupportedException) is the one refusal for a store file this runtime cannot read, thrown
by the single-file reader, the rewriting paths and CultMesh's reads, with the cause as the inner exception. The reader is exactly
one array of three slots (or an empty array): a header alone and an extra top-level slot are refused instead of read as empty or
skipped. CultMesh's older-catalog fallback is the same reader with the older entry reader, so it also requires one array.
Vectors: bad-body, header-only, missing-schema, variant-slot, extra-top-slot in the readability set, and a legacy-catalog store
with and without bytes after it for CultMesh. The persistence contract says what is true.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 04:06:44 +02:00
# A header and a body of the wrong shape, for both readable headers.
" bad-body-v1 " : pack ( [ " cultcache.store.v1 " , 5 , 6 ] ) ,
" bad-body-v3 " : pack ( [ " cultcache.store.v3 " , 5 , 6 ] ) ,
# A header and nothing else: not a store, whatever the header says.
" header-only-v1 " : pack ( [ " cultcache.store.v1 " ] ) ,
" header-only-v3 " : pack ( [ " cultcache.store.v3 " ] ) ,
# v3-base with its schema catalog emptied: every record names a schema the store does not publish.
" missing-schema-v3 " : pack ( [ base [ 0 ] , [ ] , base [ 2 ] ] ) ,
2026-09-30 05:53:01 +02:00
# The same, with each payload opening with its schema version: no runtime recovers a schema from a payload.
" missing-schema-versioned-v3 " : pack ( [ base [ 0 ] , [ ] , [ record [ : 3 ] + [ pack ( [ " vectors.item.v1 " , " n " , 1 ] ) ] for record in base [ 2 ] ] ] ) ,
2026-09-30 06:54:17 +02:00
# The record names its schema by an id the catalog publishes only as a compatible id of an entry with another id.
" compatible-id-only-v3 " : pack ( [ base [ 0 ] , [ [ base [ 1 ] [ 0 ] [ 0 ] + " .next " ] + base [ 1 ] [ 0 ] [ 1 : ] ] , base [ 2 ] ] ) ,
2026-09-30 08:31:12 +02:00
# An id that one entry owns and a later entry lists as compatible names the entry that owns it (here, vectors.item, which does not list itself as compatible).
" own-id-over-compatible-v3 " : pack ( [ base [ 0 ] , [ base [ 1 ] [ 0 ] [ : 5 ] + [ [ ] ] + base [ 1 ] [ 0 ] [ 6 : ] ] + [ [ " vectors.item.next " , " vectors.other " , " vectors.other.v1 " , " vectors.item.next " , " {} " , [ " vectors.item " ] , [ ] ] ] , base [ 2 ] ] ) ,
2026-09-30 09:01:00 +02:00
# The same, with the entry that lists the id as compatible before the entry that owns it: a reader that takes the first entry
# naming an id in one pass reads the record as vectors.other.
" compatible-before-owner-v3 " : pack ( [ base [ 0 ] , [ [ " vectors.item.next " , " vectors.other " , " vectors.other.v1 " , " vectors.item.next " , " {} " , [ " vectors.item " ] , [ ] ] , base [ 1 ] [ 0 ] [ : 5 ] + [ [ ] ] + base [ 1 ] [ 0 ] [ 6 : ] ] , base [ 2 ] ] ) ,
2026-09-30 04:21:23 +02:00
# v3-base plus a variant of alpha: a fifth record slot, [baseKey, overrides[]], over an empty payload, overriding the name. Only C# reads it.
" variant-slot-v3 " : pack ( [ base [ 0 ] , base [ 1 ] , base [ 2 ] + [ [ " gamma " ] + base [ 2 ] [ 0 ] [ 1 : 3 ] + [ b " " , [ " alpha " , [ [ 0 , [ [ 0 , " " ] ] , " " , " gamma " ] ] ] ] ] ] ) ,
Store readability: one typed refusal, one full reader, one store shape
CultStoreUnreadableException (a NotSupportedException) is the one refusal for a store file this runtime cannot read, thrown
by the single-file reader, the rewriting paths and CultMesh's reads, with the cause as the inner exception. The reader is exactly
one array of three slots (or an empty array): a header alone and an extra top-level slot are refused instead of read as empty or
skipped. CultMesh's older-catalog fallback is the same reader with the older entry reader, so it also requires one array.
Vectors: bad-body, header-only, missing-schema, variant-slot, extra-top-slot in the readability set, and a legacy-catalog store
with and without bytes after it for CultMesh. The persistence contract says what is true.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 04:06:44 +02:00
# v3-base with a fourth top-level slot after the records.
" extra-top-slot " : pack ( base + [ 0 ] ) ,
2026-09-30 01:59:28 +02:00
}
Store readability: one typed refusal, one full reader, one store shape
CultStoreUnreadableException (a NotSupportedException) is the one refusal for a store file this runtime cannot read, thrown
by the single-file reader, the rewriting paths and CultMesh's reads, with the cause as the inner exception. The reader is exactly
one array of three slots (or an empty array): a header alone and an extra top-level slot are refused instead of read as empty or
skipped. CultMesh's older-catalog fallback is the same reader with the older entry reader, so it also requires one array.
Vectors: bad-body, header-only, missing-schema, variant-slot, extra-top-slot in the readability set, and a legacy-catalog store
with and without bytes after it for CultMesh. The persistence contract says what is true.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 04:06:44 +02:00
vectors [ " legacy-trailing " ] = vectors [ " legacy-envelopes " ] + b " \x01 \x02 \x03 "
2026-09-30 01:59:28 +02:00
for name , data in vectors . items ( ) :
( here / f " { name } .bin " ) . write_bytes ( data )
print ( len ( vectors ) , " vectors " )