CultLib/src/GameCult.Caching/Contracts
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Meta Vens a92381e589 Write an unset CultRecordRef as "" in every position
452f928 made nil the unset wire form, including dictionary keys: a
Dictionary<CultRecordRef<H>, float> holding the empty key encoded it as C0.
Python msgpack refuses nil map keys under strict_map_key, its default, so
cultcache-py cannot decode such a record. Nil cannot be the one canonical
form; "" can, and every runtime reads it.

The writer always writes "". The reader still takes nil as unset, because
452f928/b85a828 stores and Aetheria's Cut 9 import wrote nil; such a record
converts to "" on its next save and is byte-stable after that. The
store-composition contract names "" for value and key position, requires
readers to accept nil, and tells other runtimes to write "".

The tests pin payload bytes, so each claim is consequential: an unset ref
writes "", reloads through a fresh cache and resaves byte-identical; a
nil-written legacy payload reads as unset and resaves as ""; a ref-keyed
dictionary with an empty key writes "", reads back unset and resaves
byte-identical. The nil writer fails every byte assertion, a reader taking
nil as a set key fails the legacy pair, and a reader taking "" as a set key
fails the read-back assertions.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 21:34:23 +02:00
..
cultcache-persistence-format.md Share the cache gate with its stores and make unconditional commit last-writer-wins 2026-09-13 18:45:27 +02:00
cultcache-schema-compatibility.md Persist get-only and readonly members the way MessagePack does 2026-09-14 00:21:21 +02:00
cultcache-store-composition.md Write an unset CultRecordRef as "" in every position 2026-09-14 21:34:23 +02:00