Replaces the false comment that reopening never compares type names with the
end-to-end pin: id, content hash and a member type name moved together are
refused; the same patch without the type name opens.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Under thing2:ruling:payload-bytes-read-only the payload holds a copy made at
construction (wire bytes unchanged). New tests: a T[] argument (including
through Builders.Boxed) is copied; no list of any decoded golden is writable;
a caller's buffer written after construction does not change the payload. The
byte[] exemption in the mutable-collection scan is removed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reopening a single-file store at CultLib b3bd8dd5 does not compare recorded type names (a store
patched in id and Int64 opens and reads), so the test hands ResolvePersistedSchema a persisted
catalog entry with one member type changed (and one with Assets as a List): both are refused,
and the same entry with a moved id and unchanged names resolves.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A store whose id still matches the local registry is not compared, so the patched store changes
the id and Int64 together, as a real shape change does. Presence threshold set to the measured
174 required slots. goldens/README.md is the base file plus the nil-vector section (the earlier
commit rewrote its line endings).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
catalog-members.tsv (27 rows) and type-names.txt (168 types) are generated from the C# types on
Yggdrasil at CultLib b3bd8dd5 and read by NameSetTests; the package owns the names, every other
runtime is held to them. NameSetTests also patches System.Int64 to System.Int32 in a store C#
wrote and requires reopen to refuse. Presence and list tests no longer count ThingDomainException
as a door.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Deleted the 38 + 17 + 3 internal static Instance fields and public static unit-arm properties.
Unit arms are built with new ImageFitContain() and told by a type test; the arm constructors are
public. Builders rewritten (65 uses); UnitArmTests replaces the SameAs assertions: every decoded
unit arm is its arm type, no union base exposes a static member of its own kind, and
new ImageFitFill() still writes 92 02 90.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ThingDomain.Present and Items; every constructor, factory and key builder passes each non-nullable
reference parameter through Present (refusal names the slot, never a value) and each list through
Items (a private read-only copy, nil items refused). Lists are IReadOnlyList on every type.
TextInputNode's slot 2 property and parameter are InputKind, matching Rust input_kind.
Tests: NilPositionTests reads the Rust vector row by row; PresenceTests and ReadOnlyListTests
walk every door by reflection; InputKindNameTests. NameSetTests and the unit-arm rewrite follow.
Unit-arm statics are still present in this commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Goldens, refusals, store read, keys, domains at every constructor and every door (CultLib
MessagePack, MessagePack Standard, System.Text.Json), factories-only reflection, deepest chain
the 256 bound admits. Goldens are linked from crates/thing-contract/tests/goldens, read only.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>