packer (WIP)
This commit is contained in:
parent
db8c17864f
commit
67edeaab78
@ -138,6 +138,12 @@ Regras recomendadas:
|
||||
- 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`;
|
||||
- tile placement inside that fixed sheet is row-major;
|
||||
- `tile_id` is the linear row-major slot and therefore matches the normalized `artifacts[*].index`;
|
||||
- resulting capacity is therefore:
|
||||
- `tile_size = 8` -> `32 x 32 = 1024` tiles
|
||||
- `tile_size = 16` -> `16 x 16 = 256` tiles
|
||||
- `tile_size = 32` -> `8 x 8 = 64` tiles
|
||||
- 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`;
|
||||
@ -173,6 +179,10 @@ Baseline now fixed by the runtime consumer:
|
||||
- `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`
|
||||
- producer-side metadata normalization must emit what the consumer requires while preserving segmented authoring meaning:
|
||||
- `asset.json.output.metadata` -> `AssetEntry.metadata`
|
||||
- `asset.json.output.codec_configuration` -> `AssetEntry.metadata.codec`
|
||||
- `asset.json.output.pipeline` -> `AssetEntry.metadata.pipeline`
|
||||
|
||||
### Metadata Recommendation
|
||||
|
||||
@ -185,10 +195,10 @@ Direção inicial recomendada:
|
||||
- `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`;
|
||||
- `AssetEntry.metadata` should aggregate normalized maps using this structure:
|
||||
- `asset.json.output.metadata` -> `metadata`
|
||||
- `asset.json.output.codec_configuration` -> `metadata.codec`
|
||||
- `asset.json.output.pipeline` -> `metadata.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;
|
||||
@ -208,10 +218,14 @@ O build de `tile bank` deve falhar quando qualquer uma das seguintes condições
|
||||
|
||||
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.
|
||||
- duplicate `artifacts[*].index` is `blocking`;
|
||||
- gap in normalized `artifacts[*].index` ordering is `blocking`;
|
||||
- sheet-capacity overflow for the fixed `256 x 256` target is `blocking`;
|
||||
- bank without declared palettes in `asset.json.output.pipeline.palettes` is `blocking`;
|
||||
- declared palette list above `64` is `blocking`;
|
||||
- malformed palette declarations are `blocking`;
|
||||
- tiles that use fragile indices, meaning indices not represented safely across the full declared bank palette set, emit a `WARNING`;
|
||||
- that fragile-index warning is advisory in the first wave and does not block pack by itself unless later promoted by decision.
|
||||
|
||||
### Packing Boundary Recommendation
|
||||
|
||||
@ -231,13 +245,7 @@ Regras:
|
||||
|
||||
## 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?
|
||||
1. None at this stage for the tile-bank v1 producer contract.
|
||||
|
||||
## Expected Follow-up
|
||||
|
||||
|
||||
@ -6,8 +6,10 @@ Retained packer decision records:
|
||||
|
||||
- [`Concurrency, Observability, and Studio Adapter Boundary Decision.md`](./Concurrency,%20Observability,%20and%20Studio%20Adapter%20Boundary%20Decision.md)
|
||||
- [`Filesystem-First Operational Runtime and Reconcile Boundary Decision.md`](./Filesystem-First%20Operational%20Runtime%20and%20Reconcile%20Boundary%20Decision.md)
|
||||
- [`Metadata Convergence to AssetEntry.metadata Decision.md`](./Metadata%20Convergence%20to%20AssetEntry.metadata%20Decision.md)
|
||||
- [`Pack Wizard Summary and Validation Contracts Decision.md`](./Pack%20Wizard%20Summary%20and%20Validation%20Contracts%20Decision.md)
|
||||
- [`Pack Wizard Pack Execution Semantics Decision.md`](./Pack%20Wizard%20Pack%20Execution%20Semantics%20Decision.md)
|
||||
- [`Tile Bank Packing Materialization Decision.md`](./Tile%20Bank%20Packing%20Materialization%20Decision.md)
|
||||
|
||||
The first packer decision wave was already consolidated into:
|
||||
|
||||
|
||||
@ -0,0 +1,211 @@
|
||||
# Tile Bank Packing Materialization Decision
|
||||
|
||||
Status: Accepted
|
||||
Date: 2026-03-20
|
||||
Domain Owner: `docs/packer`
|
||||
Cross-Domain Impact: `../runtime`, `docs/studio`
|
||||
|
||||
## Context
|
||||
|
||||
The packer execution contract for `packWorkspace(...)` is already closed.
|
||||
|
||||
What remained open for `tile bank` was the format-specific producer contract:
|
||||
|
||||
- which selected files become part of the packed asset;
|
||||
- how those files become the canonical `TILES/indexed_v1` payload;
|
||||
- how `AssetEntry` fields are derived for runtime consumption;
|
||||
- how bank palettes are declared and normalized;
|
||||
- which diagnostics block the build for this format.
|
||||
|
||||
The agenda that closed this discussion is:
|
||||
|
||||
- [`../agendas/Tile Bank Packing Materialization Agenda.md`](../agendas/Tile%20Bank%20Packing%20Materialization%20Agenda.md)
|
||||
|
||||
Relevant upstream references are:
|
||||
|
||||
- [`../decisions/Pack Wizard Pack Execution Semantics Decision.md`](../decisions/Pack%20Wizard%20Pack%20Execution%20Semantics%20Decision.md)
|
||||
- [`../specs/3. Asset Declaration and Virtual Asset Contract Specification.md`](../specs/3.%20Asset%20Declaration%20and%20Virtual%20Asset%20Contract%20Specification.md)
|
||||
- [`../specs/4. Build Artifacts and Deterministic Packing Specification.md`](../specs/4.%20Build%20Artifacts%20and%20Deterministic%20Packing%20Specification.md)
|
||||
- [`../pull-requests/PR-32-palette-declarations-with-explicit-index-contract.md`](../pull-requests/PR-32-palette-declarations-with-explicit-index-contract.md)
|
||||
- [`../../../runtime/docs/runtime/specs/04-gfx-peripheral.md`](../../../runtime/docs/runtime/specs/04-gfx-peripheral.md)
|
||||
- [`../../../runtime/docs/runtime/specs/15-asset-management.md`](../../../runtime/docs/runtime/specs/15-asset-management.md)
|
||||
- [`../../../runtime/docs/runtime/agendas/024-asset-entry-metadata-normalization-contract.md`](../../../runtime/docs/runtime/agendas/024-asset-entry-metadata-normalization-contract.md)
|
||||
|
||||
## Decision
|
||||
|
||||
The first-wave packer materialization contract for `tile bank` adopts the following direction:
|
||||
|
||||
1. `TILES/indexed_v1` emits one canonical payload per asset.
|
||||
2. `1 artifact = 1 tile` in the first wave.
|
||||
3. Artifacts are ordered by normalized `artifacts[*].index`.
|
||||
4. Tile placement is row-major in one fixed `256 x 256` sheet.
|
||||
5. `tile_id` is the linear row-major slot and therefore matches the normalized artifact index.
|
||||
6. Tile pixels are serialized as packed `u4` indices.
|
||||
7. Bank palettes are serialized as `RGB565` `u16` values.
|
||||
8. Palette declarations use explicit semantic identity through `{ index, palette }`.
|
||||
9. `AssetEntry.metadata` keeps required runtime fields readable at the root while preserving segmented codec and pipeline subtrees.
|
||||
10. Format-structural diagnostics are raised in the walker/materialization path and therefore participate in validation before pack execution reruns the gate.
|
||||
|
||||
## Adopted Constraints
|
||||
|
||||
### 1. Canonical Payload Shape
|
||||
|
||||
- the payload is produced from build-selected artifacts only;
|
||||
- the payload is the canonical bank sheet raster, not a concatenation of per-artifact binary fragments;
|
||||
- for `TILES/indexed_v1`, the serialized payload shape is:
|
||||
1. packed `u4` pixel indices for the full emitted sheet;
|
||||
2. one palette block of `64 * 16 * 2` bytes;
|
||||
- palettes are always materialized to `RGB565` during pack emission;
|
||||
- the producer-side payload contract is aligned to what the runtime loader already requires.
|
||||
|
||||
### 2. Artifact-to-Tile Contract
|
||||
|
||||
- `1 artifact = 1 tile` in v1;
|
||||
- artifacts are normalized by `artifacts[*].index`;
|
||||
- `tile_id = artifacts[*].index` after normalization;
|
||||
- the canonical emitted sheet is always `256 x 256`;
|
||||
- placement is row-major within that fixed sheet.
|
||||
|
||||
Resulting tile capacities:
|
||||
|
||||
- `tile_size = 8` -> `32 x 32 = 1024` tiles
|
||||
- `tile_size = 16` -> `16 x 16 = 256` tiles
|
||||
- `tile_size = 32` -> `8 x 8 = 64` tiles
|
||||
|
||||
### 3. Runtime Entry Contract
|
||||
|
||||
Each emitted `tile bank` runtime entry must populate:
|
||||
|
||||
- `asset_id`
|
||||
- `asset_name`
|
||||
- `bank_type = TILES`
|
||||
- `offset`
|
||||
- `size`
|
||||
- `decoded_size`
|
||||
- `codec = NONE`
|
||||
- `metadata`
|
||||
|
||||
For v1:
|
||||
|
||||
- `size = ceil(width * height / 2) + 2048`
|
||||
- `decoded_size = (width * height) + 2048`
|
||||
- `width = 256`
|
||||
- `height = 256`
|
||||
- `palette_count = 64`
|
||||
|
||||
### 4. Palette Contract
|
||||
|
||||
- bank palettes are declared in `asset.json.output.pipeline.palettes`;
|
||||
- each palette declaration must use explicit shape `{ index, palette }`;
|
||||
- semantic ordering is ascending numeric `index`, never raw array position;
|
||||
- palette ids are the normalized declared `index` values;
|
||||
- any tile in the bank may be rendered with any palette in the bank;
|
||||
- palette choice is a runtime draw-time concern and is not embedded per tile in the packed payload.
|
||||
|
||||
### 5. Metadata Normalization Contract
|
||||
|
||||
`AssetEntry.metadata` keeps runtime-required fields readable while preserving authoring segmentation:
|
||||
|
||||
- `asset.json.output.metadata` -> `AssetEntry.metadata`
|
||||
- `asset.json.output.codec_configuration` -> `AssetEntry.metadata.codec`
|
||||
- `asset.json.output.pipeline` -> `AssetEntry.metadata.pipeline`
|
||||
|
||||
For tile-bank v1 this means:
|
||||
|
||||
- `tile_size`, `width`, `height`, and `palette_count` remain directly readable at the metadata root;
|
||||
- codec-specific data is nested under `metadata.codec`;
|
||||
- pipeline-derived data is nested under `metadata.pipeline`.
|
||||
|
||||
This packer decision intentionally aligns with the runtime-side follow-up agenda rather than flattening everything into one ambiguous map.
|
||||
|
||||
### 6. Diagnostics and Failure Semantics
|
||||
|
||||
The following conditions are blocking for tile-bank v1:
|
||||
|
||||
- duplicate `artifacts[*].index`
|
||||
- gaps in normalized `artifacts[*].index`
|
||||
- fixed-sheet capacity overflow
|
||||
- bank without declared palettes
|
||||
- palette declaration count above `64`
|
||||
- malformed palette declarations
|
||||
- missing or invalid required format metadata
|
||||
- any failure to normalize artifacts into one deterministic payload
|
||||
|
||||
The following condition is warning-only in the first wave:
|
||||
|
||||
- fragile tile indices, meaning tile indices that are not safely represented across the full declared bank palette set
|
||||
|
||||
### 7. Walker and Validation Boundary
|
||||
|
||||
- family walkers remain discovery-oriented;
|
||||
- tile-bank structural diagnostics must be produced in the walker/materialization path;
|
||||
- validation consumes those diagnostics naturally;
|
||||
- pack execution reruns the validation gate on a newly created frozen execution snapshot before materialization begins.
|
||||
|
||||
## Why This Direction Was Chosen
|
||||
|
||||
- It matches the runtime consumer contract instead of inventing a producer-local interpretation.
|
||||
- It keeps `tile bank` payload semantics explicit and deterministic.
|
||||
- It avoids embedding per-artifact or per-draw palette assignment into the packed bytes.
|
||||
- It preserves stable palette identity through explicit `index` declarations.
|
||||
- It keeps validation early without weakening the pack-time rerun gate.
|
||||
- It gives the runtime a metadata shape that is readable and still semantically segmented.
|
||||
|
||||
## Explicit Non-Decisions
|
||||
|
||||
This decision does not yet define:
|
||||
|
||||
- future support for `1 artifact -> many tiles`;
|
||||
- non-`256 x 256` tile-bank targets;
|
||||
- alternative tile-bank codecs beyond `NONE`;
|
||||
- future palette compaction or palette-id remapping strategies;
|
||||
- the runtime-side final decision for general `AssetEntry.metadata` normalization helpers;
|
||||
- future sprite or tilemap semantic adjustments unrelated to packer-owned payload production.
|
||||
|
||||
## Implications
|
||||
|
||||
- tile-bank packing implementation must materialize a full sheet raster rather than artifact fragments;
|
||||
- tile-bank payload generation must pack `u4` indices explicitly in the packer;
|
||||
- palette declarations and palette overhauling flows must preserve explicit palette `index`;
|
||||
- runtime-entry metadata emission must preserve both root-required fields and segmented nested maps;
|
||||
- tile-bank validation logic belongs in the walker/materialization path and must be reused by pack execution gate reruns.
|
||||
|
||||
## Propagation Targets
|
||||
|
||||
Specs:
|
||||
|
||||
- [`../specs/3. Asset Declaration and Virtual Asset Contract Specification.md`](../specs/3.%20Asset%20Declaration%20and%20Virtual%20Asset%20Contract%20Specification.md)
|
||||
- [`../specs/4. Build Artifacts and Deterministic Packing Specification.md`](../specs/4.%20Build%20Artifacts%20and%20Deterministic%20Packing%20Specification.md)
|
||||
|
||||
Plans:
|
||||
|
||||
- [`../pull-requests/PR-32-palette-declarations-with-explicit-index-contract.md`](../pull-requests/PR-32-palette-declarations-with-explicit-index-contract.md)
|
||||
- future packer PR for tile-bank payload materialization
|
||||
- future packer PR for tile-bank validation diagnostics
|
||||
|
||||
Cross-domain references:
|
||||
|
||||
- [`../../../runtime/docs/runtime/specs/04-gfx-peripheral.md`](../../../runtime/docs/runtime/specs/04-gfx-peripheral.md)
|
||||
- [`../../../runtime/docs/runtime/specs/15-asset-management.md`](../../../runtime/docs/runtime/specs/15-asset-management.md)
|
||||
- [`../../../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)
|
||||
- [`../../../runtime/docs/runtime/agendas/024-asset-entry-metadata-normalization-contract.md`](../../../runtime/docs/runtime/agendas/024-asset-entry-metadata-normalization-contract.md)
|
||||
|
||||
Implementation surfaces:
|
||||
|
||||
- `prometeu-packer-v1` tile-bank payload materializer
|
||||
- `prometeu-packer-v1` tile-bank diagnostics in walker/materialization path
|
||||
- `prometeu-packer-v1` metadata convergence for `AssetEntry`
|
||||
- Studio tile-bank authoring and inspection surfaces that expose palettes or bank composition
|
||||
|
||||
## Validation Notes
|
||||
|
||||
This decision is correctly implemented only when all of the following are true:
|
||||
|
||||
- artifact normalization produces one deterministic row-major `256 x 256` bank sheet;
|
||||
- emitted tile ids match normalized artifact indices;
|
||||
- emitted pixel bytes are packed as `u4`;
|
||||
- emitted palette bytes are `RGB565` `u16`;
|
||||
- palette declarations are read and written by explicit `index`;
|
||||
- runtime-required metadata fields remain readable at the root;
|
||||
- codec and pipeline metadata survive under `metadata.codec` and `metadata.pipeline`;
|
||||
- structural blockers are visible during validation and are rerun by pack execution before emission.
|
||||
Loading…
x
Reference in New Issue
Block a user