Delete Hidden, HiddenProblem, UnreadKeyedMembers/UnreadMembers, Settle's
[MessagePackFormatter] refusals and the door's written-as-object branch.
Classify gains Leaf for attribute-formatted, [DataContract] and string-keyed
types; MembersOf honours the most derived AllowPrivate; the door refuses a
null StandardResolver formatter with the throwing path's text.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MembersOf is now MessagePack's StandardResolver write set: public fields and
properties with a public getter, none of them [IgnoreMember]. UnreadKeyedMembers
(renamed from NonPublicKeyedMembers) is every other [Key] member, including a
public property whose getter is private. IdProblem takes id candidates from every
instance member up the base chain, refuses an id MessagePack does not write, and
refuses a property id with a non-public setter, which MessagePack writes but does
not read back (s4: walk-member-set-differs, private-setter-id-dropped-on-read).
An oracle test pins the member set to MessagePack's ObjectSerializationInfo.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Classify tested IEnumerable<T> before [MessagePackObject], so a keyed class that
enumerates itself recursed until the stack overflowed during registration (s4,
keyed-enumerable-misclassified), and a keyed class that merely enumerates had its
keyed lists neither judged nor minted. Keyed first: MessagePack writes both by key.
VisitMemberType also stops at a type already on its own through chain, which ends
an unkeyed Node : IEnumerable<Node>.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Stryker found the primitive, enum and object tests in Classify redundant with the value-type and unkeyed
branches, so they are gone. The new tests kill the survivors that were behaviour: a nullable keyed struct
walked as its struct, an unannotated struct treated as a value, [MessagePackObject] reaching a subclass,
and a claim on a type StandardResolverAllowPrivate cannot format.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
MessagePack writes a non-public [Key] member only under AllowPrivate, and the element-id walk reads
public members, so the ids such a list holds could never be checked. Graph entries carry Hidden; a hidden
list or a hidden edge whose child reaches adds one problem and nothing to the id path.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
IsLeaf, IsObjectType and DictionaryValueType are deleted. Classify(declared) says Leaf, Map
(IDictionary<,> or IReadOnlyDictionary<,>), Sequence or Owner; a keyed struct is walked as an owner and
is never an element. Plan and Holds take the declared root type and follow declared member types, so a
member declared object or a subclass's extra members under a base-typed member are neither minted into
nor read. Minted path text is unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Graph edges and lists carry the collection types between member and child; Settle adds them to the path so
[MessagePackFormatter] on a collection class and a resolver claim on List<Elem> are judged. Declares replaces the four
MemberInfo.IsDefined member reads, which ignore inherit for properties. Survey.Judged dedupes the unkeyed-element refusal.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Stryker survivors on the id-path walk: dropping the union-subtype edge, dropping the
element base from the path. Both now have a test that fails without them.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Registration: a concrete element type of an object list that is not keyed, and
[MessagePackFormatter] on any type or member on the id path or on the id member, are
refused. The id path is a fixed point over the walk's edges. The codec refuses, once per
document type and on every encode and decode path, a resolver ahead of StandardResolver
that formats a type on that path. UnionArmGuardTests moves StubArm out of the list union.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A rewrite replaces a file only when the runtime's own reader opens it. C#
drops ReadStoreHeader (a second, header-only verdict that let a flush replace
files the reader refuses) and asks DeserializeSnapshot from open, flush and
commit; the reader now requires exactly one array, so C# refuses bytes after
the store on read as TS and Python do. A zero-byte file is an empty store for
all three paths. CultMesh.WriteSingleFileDocument reads the file it replaces
through the Mesh reader before writing. Rust reads and rewrites through one
classification (trailing bytes refused on read; a non-store first slot must be a
legacy envelope array the reader accepts). TypeScript checks a legacy array with
pullAll's own decoder before replacing it. Python already conformed.
Shared byte vectors and per-runtime verdicts live in
tests/vectors/document-variants-c2a/readability; every runtime's test reads
them. Holds gains second-dictionary-value and second-list-item cases. The
persistence format contract now marks v3 by content and states the readability
rule.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
CultElementIds.Holds is the one fact a store marks its header by; a test now
drives it directly over a dictionary value, a list of lists, a list under an
unset element and an element, and over unset ids that hold nothing, so a
mutant that skips any of those branches fails.
C# ReadStoreHeader refused a first-slot string without the cultcache.store.
prefix and then ran RequireSingleFileFormat, which refuses every string that
is not v1, v2 or v3 anyway. The prefix check is gone; a non-header string is
refused as a format this runtime does not read.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Engine tests for the plan (duplicates, format, empty derived source, atomicity, two
cultures, interface unions, key sharing); cache tests for the marker on single-file and
directory stores, override values on write and load, minting that is given back, and the
in-memory-only mark.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
[CultElementId(nameof(Member))] declares an id derived from that member's
invariant text, never random, so content-addressed elements keep encoding to the
same bytes. CultMeshCdnChunkRef derives its id from Offset; PackArtifact sets
it, the Rust pack_content writes it, and the committed content vectors are
re-cut once so both runtimes carry it. Engine tests drive Problems and Assign
directly (InternalsVisibleTo the Caching tests).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>