prometeu-studio/docs/packer/agendas/Tile Bank Packing Materialization Agenda.md
2026-03-24 13:42:55 +00:00

251 lines
13 KiB
Markdown

# Tile Bank Packing Materialization Agenda
Status: Open
Domain Owner: `docs/packer`
Cross-Domain Impact: `../runtime`, `docs/studio`
## Purpose
Convergir a discussão sobre como um asset `tile bank` deve ser materializado durante o `packing` para produzir payload runtime-facing válido dentro de `assets.pa`.
Esta agenda não trata do workflow operacional do `Pack Wizard`.
Ela trata do contrato técnico de materialização do formato `TILES/indexed_v1`:
- quais arquivos entram no pack;
- como eles viram payload binário final;
- quais campos do `asset_table` são derivados;
- quais metadados convergem para `AssetEntry.metadata`;
- e quais invariantes devem falhar o build.
## Problem
O repositório já tem base suficiente para:
1. descobrir arquivos relevantes de `tile bank`;
2. validar metadados mínimos como `tile_size`;
3. construir snapshots runtime-backed;
4. definir `assets.pa` como artefato autoritativo do runtime.
Mas ainda não existe decisão formal sobre a materialização final de `tile bank` no pack.
Hoje falta fechar, pelo menos:
- qual é o payload binário efetivamente emitido para um `tile bank`;
- como múltiplos artifacts selecionados são agregados no payload final;
- como `bank_type`, `codec`, `size`, `decoded_size` e `metadata` são derivados para a entrada runtime;
- quais dados ficam em `AssetEntry.metadata` versus quais permanecem detalhe interno de pipeline;
- quais condições tornam o pack inválido para esse formato.
Sem isso, o `packWorkspace(...)` pode até ganhar semântica operacional correta, mas ainda ficará sem contrato suficiente para produzir `assets.pa` conformat para `tile bank`.
## Context
O contrato upstream já impõe limites claros:
- `assets.pa` é o artefato runtime-facing autoritativo:
[`../specs/1. Domain and Artifact Boundary Specification.md`](../specs/1.%20Domain%20and%20Artifact%20Boundary%20Specification.md)
- `asset_table` é determinística por `asset_id`, offsets são relativos ao payload region e metadata converge para um sink único:
[`../specs/4. Build Artifacts and Deterministic Packing Specification.md`](../specs/4.%20Build%20Artifacts%20and%20Deterministic%20Packing%20Specification.md)
- o runtime espera `assets.pa` autocontido com `asset_table` e `preload` válidos:
[`../../../runtime/docs/runtime/specs/13-cartridge.md`](../../../runtime/docs/runtime/specs/13-cartridge.md)
- o runtime consome `AssetEntry { asset_id, asset_name, bank_type, offset, size, decoded_size, codec, metadata }`:
[`../../../runtime/docs/runtime/specs/15-asset-management.md`](../../../runtime/docs/runtime/specs/15-asset-management.md)
Contexto atual de código:
- `PackerAssetWalker` já reconhece `OutputFormatCatalog.TILES_INDEXED_V1`;
- `PackerTileBankWalker` já produz probes/metadata family-relevant;
- o snapshot atual já consegue expor arquivos candidatos e metadata de walk;
- ainda não existe materialização final de payload de `tile bank` dentro de `assets.pa`.
Consumer baseline now confirmed in `../runtime`:
- `TILES` now uses `codec = NONE` as the runtime-facing v1 baseline;
- serialized tile pixels are packed `u4` palette indices in payload order;
- the runtime expands those packed indices into one `u8` logical index per pixel in memory after decode;
- tile-bank palettes are serialized as `RGB565` `u16` values in little-endian order;
- runtime-facing v1 uses `64` palettes per tile bank;
- the runtime loader currently requires the following metadata fields for tile banks:
- `tile_size`
- `width`
- `height`
- `palette_count`
- for v1, `palette_count` must be `64`;
- for v1, the serialized tile-bank payload is:
1. packed indexed pixels for the full sheet, using `ceil(width * height / 2)` bytes;
2. one palette block of `64 * 16 * 2 = 2048` bytes;
- for v1, the runtime-side size expectations are:
- `size = ceil(width * height / 2) + 2048`
- `decoded_size = (width * height) + 2048`
- for the producer-side contract discussed here, `tile_id = 0` remains valid and must not be reserved away by the packer.
Relevant confirmed runtime references:
- [`../../../runtime/docs/runtime/specs/15-asset-management.md`](../../../runtime/docs/runtime/specs/15-asset-management.md)
- [`../../../runtime/docs/runtime/specs/04-gfx-peripheral.md`](../../../runtime/docs/runtime/specs/04-gfx-peripheral.md)
- [`../../../runtime/crates/console/prometeu-drivers/src/asset.rs`](../../../runtime/crates/console/prometeu-drivers/src/asset.rs)
- [`../../../runtime/crates/console/prometeu-hal/src/tile_bank.rs`](../../../runtime/crates/console/prometeu-hal/src/tile_bank.rs)
- tilemap empty-cell semantics remain under active runtime discussion and must not currently force the packer to reserve `tile_id = 0`:
[`../../../runtime/docs/runtime/agendas/023-tilemap-empty-cell-vs-tile-id-zero.md`](../../../runtime/docs/runtime/agendas/023-tilemap-empty-cell-vs-tile-id-zero.md)
Isso significa que o problema agora não é descoberta de arquivos.
O lado consumidor já está suficientemente claro.
O problema agora é fechar o contrato produtor `tile bank -> runtime asset entry + payload bytes` no packer sem contradizer esse baseline runtime.
## Options
### Option A - Concatenate selected tile artifacts as a simple raw stream
Cada artifact selecionado do `tile bank` vira um segmento binário simples, e o payload final do asset é a concatenação determinística desses segmentos.
`metadata` carrega apenas o mínimo necessário para o runtime interpretar o asset.
### Option B - Emit one canonical tile-bank payload plus normalized runtime metadata
Os artifacts selecionados são primeiro normalizados para um modelo canônico de `tile bank`, e então o packer emite:
- um único payload binário canônico para o asset;
- um conjunto fechado de campos runtime-facing em `AssetEntry.metadata`.
Qualquer detalhe interno adicional de pipeline fica fora do contrato runtime principal ou vai apenas para tooling metadata.
### Option C - Preserve rich per-artifact structure directly in runtime metadata
O packer mantém estrutura mais rica de artifacts individuais no próprio `AssetEntry.metadata`, expondo para o runtime detalhes mais próximos da pipeline de build.
## Tradeoffs
- Option A é a implementação mais simples, mas corre risco de deixar semântica demais implícita no consumidor.
- Option A também pode dificultar compatibilidade futura se a concatenação simples não codificar claramente limites, forma lógica ou derivação de `decoded_size`.
- Option B exige fechar um modelo canônico do `tile bank`, mas produz o contrato mais limpo entre packer e runtime.
- Option B também respeita melhor a regra já vigente de convergência para `AssetEntry.metadata` sem transformar metadata runtime em espelho da pipeline.
- Option C pode parecer flexível no curto prazo, mas mistura detalhe de pipeline com contrato runtime e aumenta acoplamento.
- Option C tensiona diretamente o guardrail já documentado de que `asset_table[].metadata` não deve virar depósito arbitrário de estrutura interna.
## Recommendation
Adotar `Option B`.
O primeiro formato de packing a ser fechado deve ter payload canônico e metadata runtime-facing normalizada.
### Payload Recommendation
O `tile bank` deve produzir um payload binário único por asset incluído no build.
Regras recomendadas:
- o payload é derivado apenas dos artifacts selecionados que realmente entram no build atual;
- a ordem de agregação dos artifacts deve ser determinística by `artifacts[*].index`;
- for v1, `1 artifact = 1 tile`;
- for the current target, the canonical tile-bank sheet is always `256 x 256`;
- o payload final do asset deve ter fronteiras e interpretação definidas pelo próprio contrato do formato, não por convenção incidental de concatenação;
- para `TILES/indexed_v1`, o payload v1 já deve assumir:
1. plano de pixels packed `u4`;
2. bloco de paletas `64 * 16 * u16`;
- palettes must always be materialized to `RGB565` during pack emission;
- `size` deve representar o tamanho emitido no payload region;
- `decoded_size` deve seguir a convenção runtime já confirmada:
tamanho expandido dos indices em memória mais o bloco de paletas runtime-facing.
### Runtime Entry Recommendation
Cada `tile bank` emitido para o runtime deve preencher, no mínimo:
- `asset_id`
- `asset_name`
- `bank_type = TILES`
- `offset`
- `size`
- `decoded_size`
- `codec`
- `metadata`
O contrato de `bank_type`, `codec` e `decoded_size` não deve ser deixado implícito no packer implementation detail.
Baseline now fixed by the runtime consumer:
- `bank_type = TILES`
- `codec = NONE`
- metadata mínima obrigatória:
- `tile_size`
- `width`
- `height`
- `palette_count = 64`
- `width` and `height` are bank-sheet helpers, not per-artifact dimensions
- with the current v1 target, the emitted bank sheet is fixed at `256 x 256`
### Metadata Recommendation
`AssetEntry.metadata` deve receber apenas os campos runtime-consumable e format-relevant.
Direção inicial recomendada:
- metadados declarativos como `tile_size` entram no sink runtime;
- metadados derivados necessários para leitura correta do runtime entram no sink runtime, pelo menos:
- `width`
- `height`
- `palette_count`;
- `AssetEntry.metadata` should aggregate normalized maps derived from:
- `asset.json.output.metadata`
- `asset.json.output.codec_configuration`
- `asset.json.output.pipeline`;
- bank palettes are declared in `asset.json.output.pipeline.palettes` using explicit `{ index, palette }` entries and emitted in ascending numeric `index` order;
- any tile in the bank may be rendered with any palette in the bank;
- palette assignment is therefore not a per-artifact packing contract and remains a runtime draw-time concern;
- the packer must nevertheless validate whether the declared bank palette set safely covers the indices used by packed tiles.
- detalhes de pipeline úteis apenas para inspeção e tooling não devem dominar `AssetEntry.metadata`;
- quando um detalhe interno for necessário apenas para tooling, ele deve preferir companion tooling data em vez de inflar o contrato runtime.
### Failure Recommendation
O build de `tile bank` deve falhar quando qualquer uma das seguintes condições acontecer:
1. não existir conjunto suficiente de artifacts selecionados para materialização válida;
2. o metadata declarativo obrigatório do formato estiver ausente ou inválido;
3. a normalização dos artifacts para o payload canônico falhar;
4. houver colisão ou ambiguidade ao convergir metadata runtime-facing;
5. o packer não conseguir derivar de forma determinística os campos exigidos para a entry runtime.
Additional first-wave diagnostic expectations:
- bank without declared palettes in `asset.json.output.pipeline.palettes` must emit a diagnostic;
- tile banks whose declared palette list exceeds `64` must fail;
- tiles that use fragile indices, meaning indices not represented safely across the full declared bank palette set, should emit a `WARNING`;
- that fragile-index warning is advisory in the first wave and should not block pack by itself unless later promoted by decision.
### Packing Boundary Recommendation
O seletor de packing para `tile bank` deve operar sobre os probes já descobertos pelo walker family-oriented.
Regras:
- o walker continua generalista e orientado à family;
- a seleção do que entra no payload final acontece na policy/materialization layer de packing;
- somente probes do asset registrado, incluído no build, e efetivamente selecionados pelo contrato do formato entram na materialização final;
- quando o `PackerRuntimeMaterializationConfig` estiver em `PACKING`, esses probes relevantes devem carregar bytes opcionais preenchidos para congelar o input do pack.
- palette declarations in `asset.json.output.pipeline.palettes` carry explicit semantic identity through `index`;
- palette order is ascending numeric `index`, never raw array position;
- palette ids are the normalized declared `index` values from that pipeline palette list;
- all tiles in the bank may use any palette declared in the bank;
- palette selection is a runtime draw concern, not a tile-payload embedding concern.
## Open Questions
1. Given the fixed `256 x 256` bank target, what is the canonical tile placement rule inside that sheet for `tile_size = 8`, `16`, and `32`?
2. Which normalization diagnostics should be `blocking` versus `warning` specifically for:
- artifact index gaps or duplicates
- sheet capacity overflow
- palette list overflow beyond `64`
- banks without declared palettes
- fragile tile indices across the declared bank palette set?
## Expected Follow-up
1. Converter esta agenda em uma `decision` de `docs/packer` para materialização de `tile bank`.
2. Propagar o contrato resultante para:
- `docs/packer/specs/4. Build Artifacts and Deterministic Packing Specification.md`
- specs runtime relevantes em `../runtime`
3. Planejar PR de implementação do materializador de `tile bank` em `prometeu-packer-v1`.
4. Adicionar testes de conformance do formato:
`artifacts -> payload -> asset_table entry -> runtime-read assumptions`.