4.3 KiB
| id | ticket | title | created | tags | decision | |||||
|---|---|---|---|---|---|---|---|---|---|---|
| LSN-0055 | runtime-owned-variable-glyph-bank-palette-protocol | Runtime-Owned Asset Protocols Must Align Payload, Residency, and Lookup | 2026-07-14 |
|
DEC-0041 |
Context
The runtime changed the GLYPH/indexed_v1 glyph-bank palette contract from a
fixed 64-palette payload and resident table to variable palette serialization
and variable resident palette storage.
The initiating pressure came from packer/studio: fixed RGBA8888 palette padding
made small glyph banks pay for 64 * 16 * 4 palette bytes even when they used
far fewer palettes. The important architectural point was that the runtime, not
the packer, had to decide the protocol. The packer can only emit payloads that
conform to the runtime contract once the runtime spec is published.
Key Decisions
Variable Glyph Bank Palette Protocol
What:
palette_count became the number of serialized palettes and the number of
resident palettes in the loaded GlyphBank. The valid range is 1..=64.
palette_id remains a direct palette identity and is valid only when
palette_id < palette_count for the referenced resident bank.
Why: Keeping serialized count variable while retaining a fixed 64-slot resident table would preserve two meanings for palette capacity. The runtime would save payload bytes but still carry a split contract between payload shape, resident shape, and lookup validity. Making all three agree gives the runtime one source of truth.
Trade-offs:
Palette validity is now bank-dependent. Scene and sprite composition must check
the referenced loaded bank instead of relying on a global 0..63 rule. This
adds validation work, but it prevents invalid references from silently becoming
transparent or default colors.
Patterns and Algorithms
Let the runtime own runtime-facing asset protocols. Tooling can discover pain, but the runtime spec must define effective metadata, payload shape, resident shape, and failure semantics.
Make count fields material. A count such as palette_count should not describe
only what the producer authored or only what the payload happens to include. If
runtime lookup depends on it, the count must also define resident state and
validation boundaries.
Keep identity direct unless a real remapping problem exists. Sparse-to-dense
palette remapping was rejected because it would add a second identity layer
across scenes, sprites, packer output, and runtime lookup. V1 keeps palette id
N as palette slot N in the resident bank.
Separate transparent color from invalid lookup. RGBA alpha is valid color data.
An invalid palette reference must be observable as invalid; it must not be
collapsed into Color::TRANSPARENT.
Use residue scans after protocol migrations. Search for fixed byte formulas, old constants, fixture helpers, and spec phrases. Legitimate hits should be renamed as maximum-bound concepts, not left as accidental active contracts.
Pitfalls
Partially variable specs are worse than fixed specs. The asset spec already had
variable size formulas in some places but still required palette_count = 64
elsewhere. That contradiction made it unclear which rule was canonical.
Resident data structures can preserve obsolete protocol assumptions after the
payload changes. A fixed array in GlyphBank would have kept the old model
alive even if decode accepted variable payloads.
Fallback rendering hides contract errors. Returning transparent for an invalid palette id makes bad assets and bad scene references look like intentional alpha, which is exactly the wrong failure mode for a runtime protocol.
Fixture generators are part of the contract surface. Stress cartridges and test payload builders must express whether they are using a variable count or the v1 maximum; otherwise they reintroduce fixed-padding assumptions.
Takeaways
- Runtime-facing asset protocols should align payload size, resident memory, and lookup validity.
palette_countis effective runtime metadata, not producer commentary.- Direct identity is simpler than remapping until a concrete remapping need exists.
- Invalid palette references should fail explicitly; transparent remains a valid RGBA color, not an error substitute.
- Protocol migrations need spec edits, code changes, fixture updates, and residue scans in the same workflow.