packer (WIP)

This commit is contained in:
bQUARKz 2026-03-20 09:32:45 +00:00
parent db8c17864f
commit 67edeaab78
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
3 changed files with 236 additions and 15 deletions

View File

@ -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

View File

@ -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:

View File

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