prometeu-studio/discussion/workflow/decisions/DEC-0038-variable-glyph-bank-palette-serialization.md

209 lines
7.1 KiB
Markdown

---
id: DEC-0038
ticket: variable-tile-bank-palette-serialization
title: Variable Glyph Bank Palette Serialization for Studio and Packer
status: accepted
created: 2026-07-14
accepted: 2026-07-14
ref_agenda: AGD-0005
plans:
- PLN-0087
- PLN-0088
- PLN-0089
- PLN-0090
- PLN-0091
tags:
- packer
- studio
- glyph-bank
- palette-serialization
- rgba8888
- runtime-alignment
---
## Status
Accepted. Drafted from accepted agenda `AGD-0005` and accepted on
2026-07-14.
## Context
This decision belongs to the `packer` domain, with Studio-facing projection and
fixture impact. Runtime protocol ownership remains in `../runtime`.
Studio/packer already aligned glyph-bank colors with RGBA8888 through
`DSC-0038`. That work kept the `GLYPH/indexed_v1` format name and changed the
palette color encoding from RGB565-era data to RGBA8888 in runtime channel
order. It deliberately preserved the fixed 64-palette payload model for that
wave.
Runtime `DEC-0041` now changes the authoritative `GLYPH/indexed_v1` contract:
- `palette_count` is the number of serialized and resident palettes;
- `palette_count` MUST be in `1..=64`;
- payloads contain exactly `palette_count * 16 * 4` RGBA8888 palette bytes;
- `size = ceil(width * height / 2) + palette_count * 16 * 4`;
- `decoded_size = width * height + palette_count * 16 * 4`;
- resident runtime memory materializes exactly `palette_count` palettes;
- `palette_id` is direct identity within the loaded glyph bank and is valid
only when `palette_id < palette_count`;
- v1 has no sparse-to-dense palette remapping metadata;
- this remains `GLYPH/indexed_v1`, not a new v2 payload.
Studio/packer must now follow that runtime-owned contract as downstream
producers of runtime-conforming `assets.pa` payloads.
## Decision
Studio and packer SHALL adopt variable glyph-bank palette serialization for
`GLYPH/indexed_v1`, following runtime `DEC-0041` as the protocol authority.
Packer MUST stop emitting a fixed 64-palette block for glyph banks unless the
effective `palette_count` is actually `64`.
Packer MUST emit exactly `palette_count * 16 * 4` palette bytes for each
`GLYPH/indexed_v1` glyph-bank payload.
Packer MUST compute glyph-bank `size` as:
```text
size = ceil(width * height / 2) + palette_count * 16 * 4
```
Packer MUST compute glyph-bank `decoded_size` as:
```text
decoded_size = width * height + palette_count * 16 * 4
```
Packer MUST publish root effective metadata fields required by runtime:
- `tile_size`
- `width`
- `height`
- `palette_count`
For `GLYPH/indexed_v1`, `palette_count` MUST describe the number of serialized
RGBA8888 palettes and the number of resident palettes expected by runtime.
`palette_count` MUST be in the inclusive range `1..=64`.
Packer and Studio MUST NOT introduce `GLYPH/indexed_v2` for this change.
Packer and Studio MUST NOT preserve compatibility with the old fixed-padding
payload shape as a special mode.
Packer and Studio MUST NOT introduce sparse-to-dense palette remapping metadata
for v1.
`palette_authored`, when present in tooling or pipeline metadata, is
informative only. It MUST NOT be treated as effective runtime metadata unless a
later runtime decision promotes it.
Palette bytes SHALL remain RGBA8888 in runtime `R`, `G`, `B`, `A` byte order.
Palette index `0` and color index `0` remain ordinary indices. Transparency
remains represented by the alpha channel of the resolved RGBA8888 color.
## Rationale
Runtime owns the `GLYPH/indexed_v1` wire contract. Once runtime `DEC-0041`
accepted variable palette serialization, keeping packer output fixed at 64
palettes would make Studio/packer produce stale runtime payloads.
Making `palette_count` the effective serialized and resident count removes the
old mismatch between authored palette count and payload shape. The packer no
longer needs to pad every glyph bank to 4096 palette bytes unless the bank
really uses all 64 palettes.
Keeping the existing format name is correct because the project is still in v1
and runtime explicitly accepted this as an incompatible v1 correction. A v2
name would add migration surface without protecting any required compatibility
contract.
Rejecting sparse-to-dense remapping keeps `palette_id` direct. Scene, sprite,
packer output, and runtime lookup all refer to the same palette identity inside
the loaded glyph bank.
## Implications
### Specs
Packer specs MUST be updated so `GLYPH/indexed_v1` no longer describes a fixed
`64 * 16 * 4 = 4096` palette block as the normal payload shape.
Packer specs MUST define `palette_count` as the effective serialized palette
count for glyph banks, constrained to `1..=64`.
Studio specs MUST be updated only where Studio-facing projections, asset
details, pack wizard behavior, or fixtures expose the old fixed-padding model.
### Code
Packer payload emission MUST write only `palette_count` palettes.
Packer payload validation/materialization helpers MUST compute size and decoded
size from variable `palette_count`.
Packer metadata projection and Studio-facing read/detail APIs MUST expose the
runtime-effective `palette_count` correctly.
Studio code MUST NOT treat `palette_authored` as the runtime-effective count.
### Tests and Fixtures
Tests MUST cover:
- `palette_count = 1`;
- an intermediate `palette_count`;
- `palette_count = 64`;
- size and decoded-size formulas for variable counts;
- emitted RGBA8888 palette byte count;
- metadata/payload mismatch rejection or producer validation.
Fixtures that encode the old fixed-padding assumption MUST be regenerated or
updated unless they intentionally use `palette_count = 64` and satisfy the new
runtime contract directly.
### Non-goals
This decision does not change RGBA8888 channel order.
This decision does not change the packed `u4` indexed pixel plane.
This decision does not change scene `palette_id` payload shape.
This decision does not introduce v2, compatibility branches, or palette
identity remapping.
## Propagation Targets
- Specs:
- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md`
- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md`
- `docs/specs/studio/4. Assets Workspace Specification.md`, if Studio-facing
palette count projection is documented there.
- Code:
- packer glyph-bank payload emission;
- packer asset walking/materialization;
- packer read/detail projections;
- Studio asset details or pack wizard surfaces if they expose palette counts.
- Tests:
- packer parser, walker, materializer, workspace service, and fixture tests;
- Studio tests if Studio projections or UI logic expose palette counts.
- Docs:
- downstream implementation plans derived from this decision.
## References
- Agenda: `AGD-0005`
- Runtime decision:
`../runtime/discussion/workflow/decisions/DEC-0041-variable-glyph-bank-palette-protocol.md`
- Runtime handoff:
`../runtime/discussion/workflow/plans/PLN-0172-runtime-spec-handoff-to-packer-and-studio.md`
- Prior Studio/packer RGBA8888 lesson:
`discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md`
## Revision Log
- 2026-07-14: Initial accepted decision from `AGD-0005`, aligned with runtime
`DEC-0041`.