4.2 KiB
Tile Bank Packing Contract
Original Problem
After the generic pack execution boundary was closed, tile bank still lacked one explicit producer contract.
The repository needed to settle:
- how selected tile artifacts become one packed payload;
- how palette identity is declared and normalized;
- which runtime fields are derived for
AssetEntry; - which structural problems block packing before byte emission.
Consolidated Decision
The first-wave tile bank producer contract is:
- one canonical
TILES/indexed_v1payload per asset; 1 artifact = 1 tile;- artifacts are normalized by explicit
artifacts[*].index; - the emitted sheet is fixed at
256 x 256and row-major; - tile pixels are packed
u4; - bank palettes are emitted as
RGB565u16; - palette declarations use explicit
{ index, palette }; - structural diagnostics are produced early in walker/materialization and therefore participate in validation.
Final Model
1. Payload Shape
The payload is not a concatenation of artifact-local binaries. It is one canonical bank raster:
- packed
u4pixel indices for the full sheet; - one
64 * 16 * 2palette block.
2. Artifact and Tile Identity
- artifacts are normalized by ascending declared
index; tile_idmatches the normalized artifact index;- placement is row-major in the fixed sheet;
- v1 capacities depend on
tile_size:8 -> 102416 -> 25632 -> 64
3. Palette Contract
- palette identity is semantic, not positional;
- ordering is ascending numeric
index, never raw list order; - any tile may be rendered with any bank palette at runtime;
- palette selection is a draw-time concern, not an embedded per-tile payload field.
4. Metadata Contract
AssetEntry.metadata keeps runtime-required fields readable at the root while preserving segmented subtrees:
output.metadata -> metadataoutput.codec_configuration -> metadata.codecoutput.pipeline -> metadata.pipeline
For tile banks, that means root readability for values such as:
tile_sizewidthheightpalette_count
5. Validation Boundary
Tile-bank structural issues belong in the walker/materialization path, not in a late pack-only surprise phase.
Blocking conditions include:
- duplicate artifact indices;
- gaps in normalized artifact indices;
- fixed-sheet overflow;
- missing palettes;
- palette count above
64; - malformed palette declarations;
- missing required metadata;
- normalization failure.
Fragile tile indices are warnings in the first wave, not blockers by themselves.
Examples
Example: Why palette index must be explicit
If palette identity depends on array position, a harmless editorial reorder can silently change runtime meaning.
Using { index, palette } makes semantic identity reviewable and stable.
Example: Why validation must see tile-bank structure early
If duplicate artifact indices are discovered only during final byte emission, the wizard reaches Packing too late.
The correct behavior is for validation to surface the blocker before emission begins, and for pack execution to rerun that same gate on a fresh execution snapshot.
Common Pitfalls and Anti-Patterns
- Treating artifact declaration order as semantic tile identity.
- Packing per-artifact fragments instead of one canonical sheet.
- Embedding palette choice per tile in the packed payload.
- Flattening all metadata into one ambiguous map.
- Discovering tile-bank blockers only during late byte emission.
References
- Specs:
- Cross-domain:
- Related learn: