prometeu-studio/discussion/workflow/agendas/AGD-0041-studio-packer-rgba8888-asset-pipeline.md

13 KiB

id ticket title status created resolved decision tags
AGD-0041 studio-packer-rgba8888-asset-pipeline Agenda - Studio and Packer RGBA8888 Asset Pipeline Alignment accepted 2026-05-23 2026-05-23 DEC-0037
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

  • 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.
  • 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.
  • 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.
  • 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.
  • 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.
  • 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.
  • 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.
  • 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.