Either all four values (active/passive think + move) conform to the
creature's speed entry - elided as a set - or the creature is fully
custom and all four serialize. Partial conformance cannot exist on the
wire, so no value is ever left silently tracking the table beside a
hand-tuned sibling.
"Fully custom" is a real state: SpeedLevel.Custom (None already means
"resolve by type list" for the type-listed species, so it cannot double
as the custom marker). Tuning any speed flips the bucket to Custom (the
label never lies), Custom resolves no entry and short-circuits the
conformance check, a custom creature is its own GetSpeeds reference
(paragon snap becomes a natural no-op), and assigning a real bucket
un-customs it via ApplySpeedClass. A re-entrancy guard keeps the flip
from misreading ApplySpeedClass's half-assigned block, and constructors
seed raw fields so DefaultSpeedClass types do not flip at birth.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>