Dictionary<int2, PersistentBehaviorData[]> has no hash-resistant comparer
under CultCache's UntrustedData security, so any run store holding an
entity threw MessagePackSerializationException on reopen, even when the
dictionary was empty. EntityPack.PersistedBehaviors (key 5, unchanged)
becomes (int2 position, PersistentBehaviorData[] data)[], matching
Equipment/CargoBays/DockingBays. Pack writes pairs; Unpack builds a local
lookup before restoring behaviors.
PersistentBehaviorData had no concrete leaf and no Union, so nothing could
ever exercise its wire format; added MarkerPersistentBehaviorData as the
one placeholder leaf so ReopenedPackKeepsPersistedBehaviors can round-trip
real data ahead of a real IPersistentBehavior implementer landing.
Tests: RunSaveTests.BarePack uses an empty pairs array.
Added ReopenedPackKeepsPersistedBehaviors (a hand-built pack with two
positions, each with one persisted behavior, round-trips through commit
and reopen) and ReopenSurvivesAGeneratedShipWithEntities (a real ship from
LoadoutGenerator against a catalog fixture, committed into a SavedZone and
reopened, pinning the defect at the layer Soul's probe found it).
MaterializedLotsSurviveSaveAndReload and CommitKeepsOnlyReachableLots go
green; 36 of 36 tests pass.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>