prometeu-runtime/discussion/workflow/decisions/DEC-0041-variable-glyph-bank-palette-protocol.md

203 lines
8.1 KiB
Markdown

---
id: DEC-0041
ticket: runtime-owned-variable-glyph-bank-palette-protocol
title: Variable Glyph Bank Palette Protocol
status: accepted
created: 2026-07-14
accepted: 2026-07-14
ref_agenda: AGD-0049
tags: [runtime, gfx, assets, glyph-bank, palette-serialization, protocol]
---
## Status
Accepted.
## Contexto
`AGD-0049` resolved that the runtime must own the `GLYPH/indexed_v1` palette
serialization protocol. `studio` and `packer` may motivate the change, but
they do not define the runtime wire contract. Once this decision is accepted,
the packer must follow the published runtime spec.
The current runtime still contains fixed-palette assumptions:
- `docs/specs/runtime/15-asset-management.md` says `palette_count = 64` and
validates `palette_count` as exactly `64`;
- `docs/specs/runtime/04-gfx-peripheral.md` documents `palette_id` as a
runtime-facing palette index;
- `crates/console/prometeu-hal/src/glyph_bank.rs` stores palettes as
`[[Color; 16]; 64]`;
- `crates/console/prometeu-drivers/src/asset.rs` rejects any glyph metadata
whose `palette_count` is not `64`;
- glyph decode reads a fixed `64 * 16 * 4` byte palette block;
- tests and fixtures calculate glyph payload and decoded size with the fixed
palette block.
Prior decisions remain in force:
- `DSC-0022` established `GlyphBank` as the canonical artifact name;
- `DSC-0037` established RGBA8888 as the runtime color contract, with alpha as
color data and no reserved magic palette index.
## Decisao
The runtime SHALL adopt variable glyph-bank palette serialization for
`GLYPH/indexed_v1`.
For `BankType::GLYPH` in v1:
- `palette_count` MUST mean the number of RGBA8888 palettes serialized in the
payload and materialized in the resident `GlyphBank`;
- `palette_count` MUST be in the inclusive range `1..=64`;
- each palette MUST contain exactly `16` RGBA8888 colors in canonical `R, G, B,
A` byte order;
- the serialized payload MUST contain only `palette_count` palettes, not a
fixed 64-palette block;
- resident runtime memory MUST materialize exactly `palette_count` palettes for
the bank;
- `palette_id` MUST be interpreted as a direct palette identity within the
loaded glyph bank;
- `palette_id` MUST be valid only when `palette_id < palette_count` for the
loaded glyph bank being referenced;
- the runtime MUST NOT remap sparse authored palette identities into a separate
dense identity space;
- missing palettes MUST NOT silently resolve to transparent, black, or any
other default color in canonical scene/sprite composition;
- references to `palette_id >= palette_count` MUST fail explicitly when
scene/sprite/composer logic attempts to use that palette against the loaded
bank;
- the format name remains `GLYPH/indexed_v1`; this is an incompatible v1
correction, not a new v2 format.
The v1 payload size formulas SHALL be:
```text
serialized_pixel_bytes = ceil(width * height / 2)
palette_bytes = palette_count * 16 * 4
size = serialized_pixel_bytes + palette_bytes
decoded_size = (width * height) + palette_bytes
```
`width * height` is the number of logical indexed pixels. Serialized pixels
remain packed `u4`; decoded runtime pixels may remain expanded to one `u8`
index per pixel.
## Rationale
This makes `palette_count` a real runtime contract instead of a decorative
metadata field. If a glyph bank carries `N` palettes, runtime storage, payload
validation, `decoded_size`, and palette lookup all agree on `N`.
Keeping a fixed 64-slot resident table while trimming only the payload would
preserve two meanings for palette capacity: serialized count and resident
capacity. That would keep the ambiguity this decision is intended to remove.
Adding sparse-to-dense palette remapping is also rejected. It would introduce a
second identity layer and force scenes, sprites, packer output, and runtime
lookup to coordinate additional metadata. V1 should keep `palette_id` as a
direct identity inside the loaded glyph bank.
Keeping the name `GLYPH/indexed_v1` is acceptable because the project is still
in v1 and there is no required compatibility owner for the old fixed-padding
payload. The runtime should correct the v1 contract now instead of publishing a
second format solely to remove padding.
## Invariantes / Contrato
- The runtime is the protocol authority for `GLYPH/indexed_v1`.
- The packer is a producer of runtime-conforming payloads, not the source of
truth for the protocol.
- RGBA8888 remains the only valid glyph palette color encoding.
- Palette index `0` remains an ordinary palette index.
- Color index `0` remains an ordinary color index inside a palette.
- Transparency is represented by the RGBA alpha channel.
- `palette_count` is both serialized palette count and resident palette count.
- `palette_count` has a maximum of `64` in v1.
- `palette_id` validity is bank-dependent: `palette_id < palette_count`.
- No compatibility mode for the old fixed 64-palette padding is introduced.
- Old payloads with `palette_count = 64` remain valid only if they satisfy the
new contract directly, not because of a special legacy branch.
## Impactos
### Specs
- `docs/specs/runtime/15-asset-management.md` must remove the exact
`palette_count = 64` requirement and define `palette_count` as `1..=64`.
- The same spec must align `size` and `decoded_size` formulas with variable
`palette_count`.
- `docs/specs/runtime/04-gfx-peripheral.md` must define `palette_id` validity
as dependent on the loaded glyph bank's `palette_count`, not as a standalone
global `0..63` acceptance rule.
- Any public wording that suggests fixed resident `64` palettes per glyph bank
must be updated or marked historical.
### Runtime Code
- `GlyphBank` must stop exposing a fixed `[[Color; 16]; 64]` resident palette
table as the canonical representation.
- Glyph decode must accept `palette_count` in `1..=64`.
- Glyph decode must read exactly `palette_count * 16 * 4` palette bytes.
- Glyph decode must validate `size` and `decoded_size` using the variable
formulas.
- Palette lookup must expose enough information for scene/sprite/composer logic
to fail invalid `palette_id` explicitly instead of silently resolving a
default color.
### Scene, Sprite, and Composer
- Scene and sprite composition must treat `palette_id >= palette_count` for the
referenced glyph bank as an explicit invalid reference.
- The implementation plan must choose the concrete status/fault path for this
invalid reference using existing runtime error semantics where possible.
- Canonical composition must not continue by substituting transparent/default
colors for invalid palette references.
### Firmware / Host / Tooling
- Firmware/system surfaces that expose asset metadata or debug information must
report the variable `palette_count`.
- Packer/studio fixtures must emit runtime-conforming `GLYPH/indexed_v1`
payloads after the runtime spec is updated.
- Tooling must not generate sparse-to-dense remapping metadata for v1 unless a
later decision introduces that feature.
### Tests
- Tests must cover minimum and maximum valid palette counts: `1` and `64`.
- Tests must reject `palette_count = 0` and `palette_count > 64`.
- Tests must validate serialized and decoded size formulas for non-64 counts.
- Tests must verify palette bytes are read in RGBA order for variable counts.
- Tests must cover invalid `palette_id >= palette_count` behavior for scene or
sprite composition.
- Residue scans must check for fixed `64 * 16 * 4` payload assumptions that are
still active contract text or code.
## Referencias
- Agenda: `AGD-0049`
- Runtime naming precedent: `DSC-0022`
- RGBA8888 contract precedent: `DSC-0037`
- Spec target: `docs/specs/runtime/15-asset-management.md`
- Spec target: `docs/specs/runtime/04-gfx-peripheral.md`
- Code target: `crates/console/prometeu-hal/src/glyph_bank.rs`
- Code target: `crates/console/prometeu-drivers/src/asset.rs`
## Propagacao Necessaria
This decision must be followed by an executable plan before spec or code
changes.
The plan must separate:
- spec edits;
- runtime decode/materialization changes;
- scene/sprite/composer invalid-palette handling;
- tests and fixtures;
- downstream packer/studio alignment after the runtime spec is updated.
## Revision Log
- 2026-07-14: Initial decision draft from `AGD-0049`.