--- id: AGD-0005 ticket: variable-tile-bank-palette-serialization title: Variable Tile Bank Palette Serialization status: open created: 2026-03-26 resolved: decision: tags: - packer - legacy-import - tile-bank - palette-serialization - versioning --- ## Pain The current tile-bank contract serializes a fixed block of `64` palettes in v1 even when an asset authors far fewer palettes. That keeps decoding simple, but it wastes cartridge space and leaves the system with a deliberate mismatch between authored and serialized palette counts. ## Context Legacy source: `docs/packer/agendas/Variable Tile Bank Palette Serialization Agenda.md` Domain owner: `docs/packer` Cross-domain dependency: - runtime Current aligned v1 contract: - pixels are serialized as packed `u4`; - palettes are serialized as `RGB565 u16`; - `palette_count = 64`; - payload size includes a fixed `64 * 16 * 2` palette block. The packer now exposes: - `metadata.palette_count = 64` - `metadata.palette_authored = ` ## Open Questions - [ ] Should variable palette serialization arrive as a new payload version or as an incompatible change to the current one? - [ ] If `palette_count` becomes variable, should runtime still materialize a 64-slot resident bank, or truly shrink in-memory representation too? - [ ] Should sparse authored palette indices remain sparse in serialization, or be canonicalized into a dense runtime block? - [ ] Which domain owns compatibility for existing cartridges: `packer`, `runtime`, or `shipper`? ## Options ### Option A - Keep fixed 64-palette serialization - **Approach:** Preserve the current fixed v1 payload with zero-filled unused palette slots. - **Pro:** No runtime change and current specs/tests remain stable. - **Con:** Every tile bank keeps paying the full palette cost. - **Maintainability:** Medium. ### Option B - Move to variable palette serialization now - **Approach:** Serialize only authored palettes and shrink payload size immediately. - **Pro:** Better cartridge efficiency and tighter semantics for `palette_count`. - **Con:** Reopens a just-stabilized cross-domain runtime contract and forces compatibility decisions now. - **Maintainability:** Medium if done carefully, risky if done incidentally. ### Option C - Keep v1 fixed and design variable serialization for v2 - **Approach:** Preserve v1 stability now and open a later versioned follow-up for variable palette serialization. - **Pro:** Keeps current work stable while preserving a clean path for future optimization. - **Con:** Known waste remains in v1. - **Maintainability:** Strong. ## Discussion The retained agenda recommendation is already clear: the waste is real, but it is not a correctness bug, and reopening the runtime-facing contract immediately would mix optimization work into a freshly stabilized path. That makes versioned follow-up a cleaner vehicle than incidental mutation of the current contract. ## Resolution Recommended direction: adopt **Option C**. Imported retained recommendation: 1. keep the current fixed 64-palette contract for v1; 2. if variable serialization is desired, design it explicitly as a versioned follow-up; 3. treat compatibility, runtime representation, and sparse-vs-dense palette identity as explicit next-wave questions rather than silent payload tweaks. Next step suggestion: if the team wants to remove the fixed padding, open the corresponding runtime-side discussion and close the versioning/compatibility story before planning implementation.