prometeu-runtime/discussion/lessons/DSC-0046-runtime-owned-variable-glyph-bank-palette-protocol/LSN-0055-runtime-owned-asset-protocols-must-align-payload-residency-and-lookup.md
bQUARKz 7cced0709b
Some checks failed
Intrepid/Prometeu/Runtime/pipeline/head There was a failure building this commit
Intrepid/Prometeu/Runtime/pipeline/pr-master There was a failure building this commit
housekeep DSC-0046 variable glyph palette protocol
2026-07-14 16:08:17 +01:00

98 lines
4.3 KiB
Markdown

---
id: LSN-0055
ticket: runtime-owned-variable-glyph-bank-palette-protocol
title: Runtime-Owned Asset Protocols Must Align Payload, Residency, and Lookup
created: 2026-07-14
tags: [runtime, assets, glyph-bank, palette-serialization, protocol]
decision: 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_count` is 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.