--- id: AGD-0041 ticket: studio-packer-rgba8888-asset-pipeline title: Agenda - Studio and Packer RGBA8888 Asset Pipeline Alignment status: accepted created: 2026-05-23 resolved: 2026-05-23 decision: DEC-0037 tags: - studio - packer - assets - glyph-bank - palette - rgba8888 - runtime-alignment --- ## Pain Domain owner: `studio`, with direct subdomain ownership in `packer` and cross-domain dependency on `runtime`. The runtime RGBA8888 migration changes the color contract underneath the Studio asset pipeline. Runtime `DEC-0029` says RGBA8888 is the single canonical logical color and physical framebuffer format, and that asset packages must encode palettes as RGBA8888 without preserving RGB565 compatibility. Studio still carries RGB565 in the packer-facing asset pipeline: - `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` defines `GLYPH/indexed_v1` palette payloads as `64 * 16 * 2` bytes of little-endian `RGB565` values. - `PackerPaletteV1` stores both `originalArgb8888` and `convertedRgb565`. - `PackerGlyphBankWalker` drops partial alpha, treats alpha 0 and magenta as transparent index `0`, stores only RGB identity for palette lookup, and converts palette colors to RGB565. - `PackerAssetDetailsService`, `PackerReadMessageMapper`, test fixtures, and project `asset.json` files expose `convertedRgb565` as normal pipeline data. The problem is not only changing one serializer. The Studio/packer side must decide how authoring metadata, palette UI/data, emitted `assets.pa`, tests, and existing project fixtures align with runtime RGBA channel order and meaningful alpha. ## Context Runtime discussion context: - `../runtime/discussion/workflow/agendas/AGD-0037-rgba8888-framebuffer-and-pixel-format-direction.md` was consulted as the originating discussion. - `../runtime/discussion/workflow/decisions/DEC-0029-rgba8888-runtime-pixel-format-contract.md` is accepted and normative for runtime. - Runtime plans already split execution across specs, HAL/ABI, renderer, asset palettes/tooling, host presentation, and validation. Relevant runtime invariants for this Studio discussion: - raw color values use RGBA channel order; - asset package palettes must be RGBA8888; - old RGB565 palette assets are not compatible runtime input; - indexed tile/sprite payloads may remain indexed/paletized; - transparency is represented by alpha in the resolved palette entry, not by reserving palette index `0` as a special transparent index; - RGB565 helpers may exist only as temporary migration utilities, not the normal runtime path. Relevant Studio/packer state: - `assets.pa` is the authoritative runtime-facing artifact owned by the packer. - `output.pipeline` is tooling-only by default, but current glyph palette data lives there and is used by packer details/read flows. - `GLYPH/indexed_v1` currently emits a fixed 256x256 packed `u4` pixel plane plus a fixed 64-palette RGB565 block. - `DSC-0005` is still open around variable tile-bank palette serialization. That discussion optimizes fixed-vs-variable palette count. RGBA8888 changes the color encoding and transparency semantics first, so it should supersede or reframe any RGB565 assumptions before variable palette work continues. - Studio scene publication currently carries `palette_id` in scene pack requests. Scene payload shape is mostly unaffected by color format, but scene previews, palette defaults, validation, and any editor-visible palette data must remain consistent with the glyph-bank contract. ## Open Questions - [x] Should Studio keep the runtime-facing format name `GLYPH/indexed_v1` and make it an incompatible v1 contract update, or should packer emit a new explicit format/version such as `GLYPH/indexed_rgba8888_v1`? - Keep `GLYPH/indexed_v1`. The structural change is in palette encoding; the remaining glyph payload model stays stable. - [x] What is the canonical authoring-side palette field name: keep `originalArgb8888`, rename to `rgba8888`, or store structured channel data? - Use `rgba8888` unless the decision stage finds a concrete tooling reason to choose a more explicit variant. - [x] How should Java `BufferedImage` ARGB input be converted to runtime RGBA raw values without confusing storage order, JSON numeric representation, or signed `int` display in tooling? - Convert ARGB input to RGBA output directly at the packer boundary. - [x] Does palette index `0` remain an ordinary palette slot immediately, as runtime `DEC-0029` requires, or does Studio need a temporary migration step to rewrite existing transparent-index assets into alpha-bearing palette entries? - Palette index `0` becomes an ordinary palette slot. Glyph palettes therefore have 16 usable colors, not 15 plus a reserved transparent index. - [x] Should magenta color-key support disappear from Studio authoring now, or survive only as an explicit import/conversion helper outside the normal pack path? - Magenta color-key support should disappear completely. - [x] Should partial alpha in PNG tiles become first-class palette data, or should the packer still reject/diagnose partial alpha until renderer behavior is fully proven? - Partial alpha becomes valid palette data now. Existing validations and warnings that flatten or reject partial alpha should be removed. - [x] Which existing fixtures and sample projects should be regenerated versus deleted because they encode RGB565-specific expectations? - `main` and `fragments` will be regenerated manually later; they should not block the Studio/packer decision. - [x] How should this agenda relate to `DSC-0005`: close it as superseded, revise it after RGBA8888, or keep it open as a later palette-count optimization? - `DSC-0005` remains a later step. RGBA8888 should not absorb variable palette-count serialization. ## Options ### Option A - Minimal serializer swap inside current names - **Approach:** Keep current public names and `GLYPH/indexed_v1`, replace the palette block with fixed `64 * 16 * 4` RGBA8888 entries, remove `convertedRgb565`, and update tests/specs in place. - **Pro:** Smallest naming churn and likely the fastest path to unblock runtime asset decode. - **Con:** The `v1` label would silently change binary meaning, which is risky for fixtures, docs, and any stale build output. - **Maintainability:** Medium. Fast, but it relies on the repository accepting a coordinated breaking change with no compatibility ambiguity. ### Option B - Explicit RGBA8888 glyph payload format - **Approach:** Add an explicit runtime-facing glyph format/version for the RGBA8888 palette payload, retire RGB565 output from the normal pack path, and update asset declarations, specs, materialization, tests, fixtures, and sample projects to the new format. - **Pro:** Makes the breaking contract visible in file format names, tests, and diagnostics while still obeying the runtime decision not to support RGB565 as compatible input. - **Con:** More code and fixture churn; requires clear migration handling for stale project declarations and generated build artifacts. - **Maintainability:** Strong. The format boundary becomes explicit and easier to audit. ### Option C - Broaden the wave into full palette model redesign - **Approach:** Use the RGBA8888 migration to redesign palette count, sparse vs dense indices, material palettes, import/export, alpha authoring UI, and scene palette defaults in one decision. - **Pro:** Could produce a cleaner long-term asset model and resolve `DSC-0005` at the same time. - **Con:** Mixes a mandatory runtime alignment with optional model improvements, increasing risk and delaying the renderer/asset migration. - **Maintainability:** Weak for this wave. Better reserved for follow-up after the RGBA8888 contract is stable. ## Discussion The discussion converged toward an in-place `GLYPH/indexed_v1` structural update rather than a new format name. This keeps the glyph-bank identity stable: indexed pixels, fixed emitted sheet shape, scene `palette_id` references, and the broad runtime glyph-bank model remain the same. The incompatible change is the palette block and palette metadata moving from RGB565-derived values to raw RGBA8888. The authoring/read projection should expose `rgba8888` as the canonical palette field. Java image inputs may still arrive as ARGB through `BufferedImage`, but that is an input representation only. The packer boundary converts ARGB to runtime RGBA and the rest of the pipeline should speak RGBA8888. Palette index `0` is no longer special. It becomes a normal usable palette entry, which gives glyph palettes 16 usable colors. Transparency comes from the alpha byte in the RGBA8888 palette value. As a consequence, the old magenta color-key behavior should be removed completely, not retained as a normal authoring shortcut or hidden compatibility rule. Partial alpha is valid data in this model. The packer should preserve it in the palette instead of warning, flattening, or rejecting it. Existing validations around partial alpha and the 15-color limit are therefore stale and should be rewritten around the new 16-entry RGBA palette contract. Existing sample projects and fixtures that still carry RGB565 assumptions are not part of the discussion blocker. `main` and `fragments` will be regenerated later. `DSC-0005` remains a separate future discussion for palette-count serialization and should not be folded into this RGBA8888 wave. ## Tradeoffs ### Compatibility vs explicit break Runtime `DEC-0029` already rejects RGB565 compatibility for this migration. Studio therefore should not preserve RGB565 input as a normal path. The open tradeoff is whether the packer should make the break visible through a new format/version or simply mutate the existing v1 meaning. ### Authoring convenience vs runtime truth Java image tooling naturally reads pixels as ARGB ints. Runtime wants raw RGBA channel order. Studio can keep ARGB only as an import-side implementation detail, but packer output, public metadata, and tests need one unambiguous RGBA8888 representation. ### Indexed art identity vs alpha semantics The indexed/palette model can remain. What changes is that every palette entry, including index `0`, should be a real RGBA color. Transparent pixels should be encoded by alpha, not by a hardwired index rule or magenta color key. ### Scope control vs complete cleanup It is tempting to combine RGBA8888 with variable palette serialization from `DSC-0005`. That should be resisted unless the decision explicitly expands scope. RGBA8888 changes bytes per palette entry and transparency semantics; palette count optimization is a separate axis. ## Recommendation Adopt a refined Option A. The Studio/packer decision should keep `GLYPH/indexed_v1` as the runtime-facing format name, but redefine its palette block and palette metadata around RGBA8888. This is an intentional structural break in the palette contract, not a new glyph-bank format. The recommended shape for the decision is: 1. emit palette entries as raw RGBA8888 values in runtime RGBA channel order; 2. replace `convertedRgb565` with canonical `rgba8888` data in authoring and read/detail projections; 3. treat Java/PNG ARGB as an input decoding detail and convert deliberately at the packer boundary; 4. make palette index `0` ordinary, yielding 16 usable palette entries; 5. represent transparency and partial transparency only through RGBA alpha; 6. remove magenta color-key behavior completely; 7. remove partial-alpha flattening/rejection and preserve partial alpha as valid palette data; 8. preserve fixed 64-palette serialization for this wave unless a decision explicitly revises `DSC-0005`; 9. regenerate or rewrite RGB565 fixtures instead of supporting stale RGB565 assets at runtime. ## Next Step The agenda is ready to move to decision if the refined recommendation is accepted. The next artifact should be a Studio/packer decision that references runtime `DEC-0029`, leaves `DSC-0005` for a later palette-count step, and defines propagation targets for: - `docs/specs/packer`; - `docs/specs/studio`; - `prometeu-packer` models, walkers, serializers, services, fixtures, and tests; - sample project assets; - any Studio asset workspace UI/read projections that expose palette data. ## Resolution Accepted on 2026-05-23. The discussion is closed in favor of decision `DEC-0037`. The accepted direction keeps `GLYPH/indexed_v1`, moves its palette contract to RGBA8888, uses `rgba8888` as the canonical palette field, makes palette index `0` ordinary, removes magenta color-key behavior completely, accepts partial alpha as valid palette data, and leaves `DSC-0005` for a later palette-count serialization step.