From 013ca4355cf752b242dc927d65bc051f86011da1 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:23:42 +0100 Subject: [PATCH 1/6] Variable Glyph Bank Palette Serialization --- discussion/index.ndjson | 6 +- ...anonical-studio-packer-palette-contract.md | 108 +++++++ ...ariable-tile-bank-palette-serialization.md | 178 +++++++++--- ...1-studio-packer-rgba8888-asset-pipeline.md | 273 ------------------ ...7-studio-packer-rgba8888-asset-pipeline.md | 228 --------------- ...riable-glyph-bank-palette-serialization.md | 208 +++++++++++++ ...8888-packer-and-studio-spec-propagation.md | 136 --------- ...a8888-palette-model-and-argb-conversion.md | 144 --------- ...ba8888-glyph-payload-emission-and-sizes.md | 145 ---------- ...8-packer-projections-and-workspace-apis.md | 141 --------- ...rgba8888-tests-fixtures-and-conformance.md | 141 --------- ...8-final-integration-and-residue-removal.md | 159 ---------- ...variable-glyph-palette-spec-propagation.md | 132 +++++++++ ...-glyph-palette-metadata-and-count-model.md | 140 +++++++++ ...te-payload-emission-and-size-accounting.md | 140 +++++++++ ...projections-for-variable-glyph-palettes.md | 134 +++++++++ ...tte-tests-fixtures-and-final-validation.md | 153 ++++++++++ .../main/assets/.prometeu/cache.json | 162 +++++------ 18 files changed, 1237 insertions(+), 1491 deletions(-) create mode 100644 discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md delete mode 100644 discussion/workflow/agendas/AGD-0041-studio-packer-rgba8888-asset-pipeline.md delete mode 100644 discussion/workflow/decisions/DEC-0037-studio-packer-rgba8888-asset-pipeline.md create mode 100644 discussion/workflow/decisions/DEC-0038-variable-glyph-bank-palette-serialization.md delete mode 100644 discussion/workflow/plans/PLN-0081-rgba8888-packer-and-studio-spec-propagation.md delete mode 100644 discussion/workflow/plans/PLN-0082-rgba8888-palette-model-and-argb-conversion.md delete mode 100644 discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md delete mode 100644 discussion/workflow/plans/PLN-0084-rgba8888-packer-projections-and-workspace-apis.md delete mode 100644 discussion/workflow/plans/PLN-0085-rgba8888-tests-fixtures-and-conformance.md delete mode 100644 discussion/workflow/plans/PLN-0086-rgba8888-final-integration-and-residue-removal.md create mode 100644 discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md create mode 100644 discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md create mode 100644 discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md create mode 100644 discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md create mode 100644 discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 08b39aa7..91256ee0 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ -{"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":38,"PLN":87,"LSN":53,"CLSN":1}} -{"type":"discussion","id":"DSC-0038","status":"open","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-05-23","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23"}],"decisions":[{"id":"DEC-0037","file":"DEC-0037-studio-packer-rgba8888-asset-pipeline.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23","ref_agenda":"AGD-0041"}],"plans":[{"id":"PLN-0081","file":"PLN-0081-rgba8888-packer-and-studio-spec-propagation.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0082","file":"PLN-0082-rgba8888-palette-model-and-argb-conversion.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0083","file":"PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0084","file":"PLN-0084-rgba8888-packer-projections-and-workspace-apis.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0085","file":"PLN-0085-rgba8888-tests-fixtures-and-conformance.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]},{"id":"PLN-0086","file":"PLN-0086-rgba8888-final-integration-and-residue-removal.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]}],"lessons":[]} +{"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":39,"PLN":92,"LSN":54,"CLSN":1}} +{"type":"discussion","id":"DSC-0038","status":"done","ticket":"studio-packer-rgba8888-asset-pipeline","title":"Studio and Packer RGBA8888 Asset Pipeline Alignment","created_at":"2026-05-23","updated_at":"2026-07-14","tags":["studio","packer","assets","glyph-bank","palette","rgba8888","runtime-alignment"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]} {"type":"discussion","id":"DSC-0037","status":"done","ticket":"pbs-autocomplete-parameter-names","title":"PBS autocomplete parameter names for stdlib and method calls","created_at":"2026-05-08","updated_at":"2026-05-14","tags":["compiler-pbs","studio","lsp","autocomplete","signature-help","stdlib"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0052","file":"discussion/lessons/DSC-0037-pbs-autocomplete-parameter-names/LSN-0052-canonical-callable-parameter-names-through-pbs-editor-assistance.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]} {"type":"discussion","id":"DSC-0036","status":"open","ticket":"pbs-symbol-documentation-and-hover-markdown","title":"Modelo de documentacao de simbolos em PBS e consumo markdown no hover","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["compiler","compiler-pbs","studio","lsp","vscode","editor","hover","documentation","markdown"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-pbs-symbol-documentation-and-hover-markdown.md","status":"open","created_at":"2026-05-08","updated_at":"2026-05-08"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0035","status":"done","ticket":"pbs-lsp-editor-assistance-wave-1","title":"Wave 1 de assistencia editorial via LSP para PBS no VS Code","created_at":"2026-05-08","updated_at":"2026-05-08","tags":["studio","lsp","vscode","compiler","compiler-pbs","editor","completion","hover","signature-help"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0051","file":"discussion/lessons/DSC-0035-pbs-lsp-editor-assistance-wave-1/LSN-0051-compiler-backed-editor-assistance-for-pbs.md","status":"done","created_at":"2026-05-08","updated_at":"2026-05-08"}]} @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Tile Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","legacy-import","tile-bank","palette-serialization","versioning"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"open","created_at":"2026-03-26","updated_at":"2026-03-26"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md b/discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md new file mode 100644 index 00000000..5ec5660b --- /dev/null +++ b/discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md @@ -0,0 +1,108 @@ +--- +id: LSN-0053 +ticket: studio-packer-rgba8888-asset-pipeline +title: RGBA8888 Is the Canonical Studio and Packer Palette Contract +created: 2026-07-14 +tags: + - studio + - packer + - assets + - glyph-bank + - palette + - rgba8888 + - runtime-alignment +--- + +# RGBA8888 Is the Canonical Studio and Packer Palette Contract + +### Original Problem + +The runtime moved to RGBA8888 as the canonical logical color and framebuffer +format, but Studio and packer still treated glyph-bank palettes as RGB565-era +data. The old pipeline exposed `convertedRgb565`, preserved ARGB as normal +projected metadata, reserved palette index `0` for transparency, flattened or +discarded alpha semantics, and carried magenta color-key behavior as a hidden +transparency shortcut. + +That made the asset pipeline ambiguous. A glyph-bank asset could look valid to +Studio while still carrying palette data that no longer matched the runtime +contract. + +### Consolidated Decision + +`GLYPH/indexed_v1` remains the runtime-facing format name and keeps its +indexed/paletized glyph-bank identity. The incompatible change is inside the +palette contract: + +1. `rgba8888` is the canonical authored, projected, and emitted palette field. +2. RGBA8888 values are interpreted as `0xRRGGBBAA` in runtime channel order. +3. Java `BufferedImage` ARGB values are input-only host API details and must be + converted deliberately at the packer boundary. +4. Palette index `0` is ordinary. Glyph palettes have 16 usable entries. +5. Transparency, including partial transparency, is represented only by alpha. +6. Magenta color-key behavior is not a normal Studio or packer feature. +7. RGB565 is not a compatibility path for runtime-facing glyph-bank palettes. + +### Implementation Result + +The packer specs now define glyph-bank palette metadata with `rgba8888`, and +the binary `GLYPH/indexed_v1` payload uses a `64 * 16 * 4 = 4096` byte palette +block instead of the old `64 * 16 * 2 = 2048` byte RGB565 block. + +The packer palette model now carries canonical RGBA8888 values. Image import +converts Java ARGB pixels into runtime RGBA values before palette extraction, +and palette identity includes alpha. This allows transparent and partially +transparent colors to be distinct palette entries. + +Packer read, detail, write, and cache paths now use `rgba8888` as the normal +metadata contract. Emission writes palette bytes in `R`, `G`, `B`, `A` order +and no longer emits a synthetic magenta entry for index `0`. + +Tests and fixtures were updated to prove the new contract: RGBA channel order, +alpha preservation, 16 usable colors, index `0` as ordinary data, magenta as +ordinary color data, and 4096-byte palette blocks. Final validation confirmed +that remaining stale-looking references are either normative "not supported" +statements, historical discussion context, or explicitly out-of-scope generated +project cache data. + +### Practical Pattern + +When a host API exposes color in a different layout than the runtime contract, +name the boundary explicitly and keep the canonical field runtime-oriented. +For this pipeline: + +- accept host ARGB only at import/read time; +- convert to RGBA8888 before storing palette metadata; +- project `rgba8888` to Studio and packer clients; +- emit RGBA bytes directly into `assets.pa`; +- convert back to UI-friendly ARGB only inside presentation code. + +This keeps tooling convenient without letting host representation leak into the +runtime asset contract. + +### Common Pitfalls and Anti-patterns + +- Do not treat `originalArgb8888` as canonical pipeline data. ARGB can be a UI + or image-input representation, but `rgba8888` owns the contract. +- Do not reintroduce `convertedRgb565` as a normal projected field or emitted + payload. RGB565 compatibility was deliberately rejected for this path. +- Do not reserve palette index `0` for transparency. Alpha owns transparency. +- Do not use magenta as a hidden color key. A magenta RGBA value is just color + data unless an explicit future import tool defines a separate conversion. +- Do not change scene `palette_id` semantics as part of color-format work. + Scene records still reference glyph-bank palette indices. +- Do not fold `DSC-0005` variable palette-count work into RGBA8888 cleanup. + Palette encoding changed here; palette-count optimization remains separate. + +### References + +- `DEC-0037`: Studio and Packer RGBA8888 Asset Pipeline Contract. +- `PLN-0081`: Packer and Studio spec propagation. +- `PLN-0082`: Palette model and ARGB conversion boundary. +- `PLN-0083`: Glyph payload emission and size accounting. +- `PLN-0084`: Packer projections and workspace APIs. +- `PLN-0085`: Tests, fixtures, and conformance updates. +- `PLN-0086`: Final integration and residue removal. +- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md`. +- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md`. +- `docs/specs/studio/4. Assets Workspace Specification.md`. diff --git a/discussion/workflow/agendas/AGD-0005-variable-tile-bank-palette-serialization.md b/discussion/workflow/agendas/AGD-0005-variable-tile-bank-palette-serialization.md index 018ce38e..a41c2ed6 100644 --- a/discussion/workflow/agendas/AGD-0005-variable-tile-bank-palette-serialization.md +++ b/discussion/workflow/agendas/AGD-0005-variable-tile-bank-palette-serialization.md @@ -1,87 +1,185 @@ --- id: AGD-0005 ticket: variable-tile-bank-palette-serialization -title: Variable Tile Bank Palette Serialization -status: open +title: Variable Glyph Bank Palette Serialization +status: accepted created: 2026-03-26 -resolved: -decision: +resolved: 2026-07-14 +decision: DEC-0038 tags: - packer - legacy-import - - tile-bank + - glyph-bank - palette-serialization - - versioning + - rgba8888 + - runtime-alignment --- ## Pain -The current tile-bank contract serializes a fixed block of `64` palettes in v1 even when an asset authors far fewer palettes. +Domain owner: `packer`, with runtime-facing impact through `assets.pa`. -That keeps decoding simple, but it wastes cartridge space and leaves the system with a deliberate mismatch between authored and serialized palette counts. +The current `GLYPH/indexed_v1` glyph-bank contract serializes a fixed block of +`64` palettes even when an asset authors far fewer palettes. + +After `DSC-0038`, each palette entry is RGBA8888, so the fixed palette block is +now `64 * 16 * 4 = 4096` bytes. That keeps decoding simple, but it wastes +cartridge space and leaves a deliberate mismatch between authored palette count +and serialized palette count. ## Context Legacy source: `docs/packer/agendas/Variable Tile Bank Palette Serialization Agenda.md` -Domain owner: `docs/packer` Cross-domain dependency: - runtime -Current aligned v1 contract: +Runtime follow-up: + +- `../runtime/discussion/workflow/decisions/DEC-0041-variable-glyph-bank-palette-protocol.md` + is accepted and normative for the runtime side. +- Runtime `DSC-0046` keeps `GLYPH/indexed_v1`, adopts variable glyph-bank + palette serialization, and treats this as an incompatible v1 correction. +- Runtime plans `PLN-0167` through `PLN-0172` are done and publish the + downstream handoff. + +Current runtime-owned `GLYPH/indexed_v1` contract: - pixels are serialized as packed `u4`; -- palettes are serialized as `RGB565 u16`; -- `palette_count = 64`; -- payload size includes a fixed `64 * 16 * 2` palette block. +- palettes are serialized as RGBA8888 values in runtime `R`, `G`, `B`, `A` + byte order; +- `palette_count` is the number of serialized and resident palettes; +- `palette_count` must be in `1..=64`; +- payload size includes exactly `palette_count * 16 * 4` palette bytes; +- palette index `0` is ordinary; +- each palette has 16 usable colors; +- transparency is represented by alpha, not by a reserved index or magenta + color-key; +- resident runtime memory materializes exactly `palette_count` palettes; +- `palette_id` is a direct palette identity inside the loaded glyph bank and is + valid only when `palette_id < palette_count`; +- sparse-to-dense palette remapping is not part of v1; +- missing palettes must fail explicitly in scene/sprite/composer use, not + silently resolve to a default color. -The packer now exposes: +Downstream producers must emit: -- `metadata.palette_count = 64` -- `metadata.palette_authored = ` +- root effective metadata fields `tile_size`, `width`, `height`, and + `palette_count`; +- `size = ceil(width * height / 2) + palette_count * 16 * 4`; +- `decoded_size = width * height + palette_count * 16 * 4`; +- exactly `palette_count * 16 * 4` RGBA8888 palette bytes; +- no `GLYPH/indexed_v2` payload for this change; +- no fixed 64-palette padding unless `palette_count = 64` and the payload + directly satisfies the runtime v1 contract; +- no effective runtime behavior based on `palette_authored`. + +`DSC-0038` intentionally did not solve variable palette-count serialization. +It changed the color encoding from RGB565-era semantics to RGBA8888 and kept +the fixed 64-palette model stable for that wave. + +Runtime `DEC-0041` now closes the cross-domain protocol questions that this +agenda previously carried as open. The remaining Studio/packer work is +downstream alignment with the runtime-owned contract. ## Open Questions -- [ ] Should variable palette serialization arrive as a new payload version or as an incompatible change to the current one? -- [ ] If `palette_count` becomes variable, should runtime still materialize a 64-slot resident bank, or truly shrink in-memory representation too? -- [ ] Should sparse authored palette indices remain sparse in serialization, or be canonicalized into a dense runtime block? -- [ ] Which domain owns compatibility for existing cartridges: `packer`, `runtime`, or `shipper`? +- [x] Should variable palette serialization arrive as a new payload version or + as an incompatible change to the current one? + - Runtime `DEC-0041` resolves this as an incompatible correction to + `GLYPH/indexed_v1`, with no v2 format. +- [x] If `palette_count` becomes variable, should runtime still materialize a + 64-slot resident bank, or truly shrink in-memory representation too? + - Runtime `DEC-0041` resolves this: resident runtime memory materializes + exactly `palette_count` palettes. +- [x] Should sparse authored palette indices remain sparse in serialization, or + be canonicalized into a dense runtime block? + - Runtime `DEC-0041` rejects sparse-to-dense remapping. `palette_id` remains + direct identity inside the loaded glyph bank. +- [x] Should this repository create the owner agenda/decision for the runtime + side, or should a matching runtime `discussion/` artifact be opened before + implementation planning? + - Runtime `DSC-0046` now owns the protocol through accepted `DEC-0041`. + Studio/packer must follow that handoff. +- [x] Which domain owns compatibility for existing cartridges: `packer`, + `runtime`, or `shipper`? + - Runtime `DEC-0041` introduces no compatibility mode. Old payloads with + `palette_count = 64` remain valid only when they satisfy the new contract + directly. ## Options -### Option A - Keep fixed 64-palette serialization +### Option A - Keep fixed 64-palette serialization in v1 - **Approach:** Preserve the current fixed v1 payload with zero-filled unused palette slots. - **Pro:** No runtime change and current specs/tests remain stable. -- **Con:** Every glyph bank keeps paying the full palette cost. +- **Con:** Every glyph bank keeps paying the full 4096-byte palette cost. - **Maintainability:** Medium. -### Option B - Move to variable palette serialization now -- **Approach:** Serialize only authored palettes and shrink payload size immediately. -- **Pro:** Better cartridge efficiency and tighter semantics for `palette_count`. -- **Con:** Reopens a just-stabilized cross-domain runtime contract and forces compatibility decisions now. -- **Maintainability:** Medium if done carefully, risky if done incidentally. +### Option B - Align packer output with runtime variable palette serialization +- **Approach:** Keep the `GLYPH/indexed_v1` format name, serialize only + `palette_count` palettes, and make packer metadata, payload sizes, fixtures, + and Studio projections follow runtime `DEC-0041`. +- **Pro:** Removes fixed padding while the project is still in v1, keeps the + public format vocabulary stable, and makes runtime metadata match the payload. +- **Con:** Requires coordinated packer/spec/test changes and fixture + regeneration because the current producer still emits the old fixed-padding + shape. +- **Maintainability:** Strong if implemented as an explicit contract update, + weak if done as an incidental size tweak. Runtime has already closed the + protocol questions. -### Option C - Keep v1 fixed and design variable serialization for v2 -- **Approach:** Preserve v1 stability now and open a later versioned follow-up for variable palette serialization. -- **Pro:** Keeps current work stable while preserving a clean path for future optimization. -- **Con:** Known waste remains in v1. -- **Maintainability:** Strong. +### Option C - Keep fixed external metadata but trim trailing palettes +- **Approach:** Keep some 64-slot assumptions in metadata or runtime memory, but + serialize only a shortened trailing subset of palettes in the payload. +- **Pro:** Can reduce cartridge size while limiting some runtime changes. +- **Con:** Creates a split-brain contract where serialized count, logical count, + and resident count can disagree. +- **Maintainability:** Weak. It preserves the ambiguity this agenda is trying + to remove. ## Discussion -The retained agenda recommendation is already clear: the waste is real, but it is not a correctness bug, and reopening the runtime-facing contract immediately would mix optimization work into a freshly stabilized path. +The retained concern is still valid after `DSC-0038`, but runtime `DEC-0041` +has now closed the protocol. The problem is no longer an open cross-domain +design question; it is a downstream producer-alignment task for Studio/packer. -That makes versioned follow-up a cleaner vehicle than incidental mutation of the current contract. +The old recommendation favored a versioned follow-up because compatibility and +runtime stability were treated as constraints. Runtime `DEC-0041` removes that +constraint: the project is still in v1, keeps `GLYPH/indexed_v1`, and does not +need compatibility for the old fixed 64-palette payload. + +That makes Option B the required direction for this repository. Runtime already +changed the contract directly; Studio/packer must now emit the runtime-owned +shape and stop treating `palette_authored` or the old 64-padding model as +effective runtime behavior. + +Option C should be avoided because it preserves multiple meanings for palette +count. If the payload becomes variable, `palette_count` should mean the number +of serialized palettes, not an unrelated fixed resident capacity. ## Resolution -Recommended direction: adopt **Option C**. +Recommended direction: adopt **Option B**. -Imported retained recommendation: +Updated recommendation: -1. keep the current fixed 64-palette contract for v1; -2. if variable serialization is desired, design it explicitly as a versioned follow-up; -3. treat compatibility, runtime representation, and sparse-vs-dense palette identity as explicit next-wave questions rather than silent payload tweaks. +1. keep the format name `GLYPH/indexed_v1`; +2. follow runtime `DEC-0041` as the protocol authority; +3. remove the fixed 64-palette payload block from packer output; +4. make packer `palette_count` describe the serialized and resident RGBA8888 + palette count; +5. emit exactly `palette_count * 16 * 4` palette bytes; +6. update `size` and `decoded_size` formulas to use variable `palette_count`; +7. do not create a v2 format solely for this change; +8. do not preserve compatibility with the old fixed-padding payload; +9. do not introduce sparse-to-dense palette remapping metadata; +10. treat `palette_authored` as informative only unless a later runtime + decision promotes it to effective metadata; +11. add downstream fixture coverage for `palette_count = 1`, an intermediate + count, and `palette_count = 64`; +12. add a negative producer validation case for metadata/payload mismatch. -Next step suggestion: if the team wants to remove the fixed padding, open the corresponding runtime-side discussion and close the versioning/compatibility story before planning implementation. +Next step suggestion: convert this agenda into a Studio/packer decision that +references runtime `DEC-0041` and scopes implementation to specs, packer +payload emission, Studio projections if needed, tests, and fixtures. diff --git a/discussion/workflow/agendas/AGD-0041-studio-packer-rgba8888-asset-pipeline.md b/discussion/workflow/agendas/AGD-0041-studio-packer-rgba8888-asset-pipeline.md deleted file mode 100644 index 3c1ae0f7..00000000 --- a/discussion/workflow/agendas/AGD-0041-studio-packer-rgba8888-asset-pipeline.md +++ /dev/null @@ -1,273 +0,0 @@ ---- -id: AGD-0041 -ticket: studio-packer-rgba8888-asset-pipeline -title: Agenda - Studio and Packer RGBA8888 Asset Pipeline Alignment -status: accepted -created: 2026-05-23 -resolved: 2026-05-23 -decision: DEC-0037 -tags: - - 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 - -- [x] 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. -- [x] 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. -- [x] 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. -- [x] 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. -- [x] 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. -- [x] 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. -- [x] 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. -- [x] 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. diff --git a/discussion/workflow/decisions/DEC-0037-studio-packer-rgba8888-asset-pipeline.md b/discussion/workflow/decisions/DEC-0037-studio-packer-rgba8888-asset-pipeline.md deleted file mode 100644 index 357738dc..00000000 --- a/discussion/workflow/decisions/DEC-0037-studio-packer-rgba8888-asset-pipeline.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -id: DEC-0037 -ticket: studio-packer-rgba8888-asset-pipeline -title: Studio and Packer RGBA8888 Asset Pipeline Contract -status: accepted -created: 2026-05-23 -accepted: 2026-05-23 -ref_agenda: AGD-0041 -plans: - - PLN-0081 - - PLN-0082 - - PLN-0083 - - PLN-0084 - - PLN-0085 - - PLN-0086 -tags: - - studio - - packer - - assets - - glyph-bank - - palette - - rgba8888 - - runtime-alignment ---- - -## Status - -Accepted. Drafted from accepted agenda `AGD-0041` and accepted on -2026-05-23. - -## Context - -Runtime `DEC-0029` makes RGBA8888 the canonical logical color representation -and physical framebuffer format for Prometeu. It also requires asset package -palettes to use RGBA8888, rejects RGB565 compatibility as normal runtime input, -and defines transparency through alpha rather than a reserved palette index. - -Studio embeds the packer and owns the asset authoring and publication pipeline -that emits `assets.pa`. Before this decision, the Studio/packer glyph-bank path -still carried RGB565 assumptions: - -- `GLYPH/indexed_v1` palette payloads were specified as fixed - `64 * 16 * 2` RGB565 `u16` values. -- `PackerPaletteV1` exposed `originalArgb8888` and `convertedRgb565`. -- `PackerGlyphBankWalker` flattened partial alpha, treated alpha zero and - magenta as transparent index `0`, limited authored colors to 15 usable - entries, and converted colors to RGB565. -- Studio/packer read projections, details APIs, fixtures, and sample assets - exposed `convertedRgb565` as ordinary pipeline data. - -The runtime decision is already normative for the color contract. This decision -locks how Studio and packer align their glyph-bank asset pipeline with it. - -## Decision - -Studio and packer SHALL keep the runtime-facing glyph payload format name -`GLYPH/indexed_v1`. - -The `GLYPH/indexed_v1` glyph-bank model SHALL remain indexed/paletized. Indexed -pixel payloads, fixed emitted sheet shape, scene `palette_id` references, and -the broad glyph-bank identity remain stable. - -The structural change is the palette contract. `GLYPH/indexed_v1` palette data -MUST move from RGB565-derived values to RGBA8888 values in runtime RGBA channel -order. - -Packer output, packer metadata, Studio read/detail projections, tests, and -fixtures MUST stop treating RGB565 as the normal palette representation. -`convertedRgb565` MUST be removed from the normal authored and projected -palette contract. - -The canonical authored/projected palette field for this wave SHALL be -`rgba8888`. - -Java `BufferedImage` and PNG inputs MAY be read as ARGB by host APIs, but ARGB -is only an input representation. The packer boundary MUST convert ARGB input to -runtime RGBA8888 output deliberately before emitting or projecting canonical -palette data. - -Palette index `0` MUST be an ordinary palette index. Glyph palettes SHALL have -16 usable entries, not 15 usable entries plus a reserved transparent index. - -Transparency and partial transparency MUST be represented only by the alpha -channel in the RGBA8888 palette value. - -Magenta color-key behavior MUST be removed completely from the normal Studio -and packer asset pipeline. Magenta MUST NOT remain a hidden compatibility rule, -normal authoring shortcut, or runtime-facing transparency encoding. - -Partial alpha in PNG/glyph inputs SHALL be valid palette data. Packer behavior -that warns about, flattens, rejects, or otherwise strips partial alpha MUST be -removed or rewritten around the RGBA8888 palette contract. - -The fixed 64-palette serialization model remains in scope for this wave unless -another accepted decision explicitly revises it. `DSC-0005` remains a later -palette-count serialization discussion and MUST NOT be folded into this -RGBA8888 migration by implication. - -Existing `main` and `fragments` sample project assets may be regenerated -manually later. Their regeneration is not a blocker for this decision and MUST -NOT justify preserving RGB565 compatibility in the packer. - -## Rationale - -Keeping `GLYPH/indexed_v1` avoids renaming a format whose core identity remains -the same: indexed glyph pixels resolved through palettes. The incompatible part -is specifically the palette encoding and transparency semantics. - -Making RGBA8888 the normal packer-side representation aligns Studio with -runtime `DEC-0029` without introducing a parallel RGB565 compatibility path. -This keeps the asset pipeline direct: authoring input is normalized once at the -packer boundary, and emitted runtime artifacts carry the runtime color contract. - -Treating index `0` as ordinary is required because transparency now belongs to -the alpha channel. This also gives each glyph palette the full 16 authored -entries available from the indexed payload. - -Removing magenta color-key behavior avoids a second transparency mechanism that -would conflict with meaningful alpha. Allowing partial alpha preserves source -image information and supports the broader RGBA8888 renderer direction. - -Keeping fixed 64-palette serialization separates mandatory color-format -migration from later payload-size optimization. Palette count and sparse/dense -serialization remain independent questions. - -## Technical Specification - -### Runtime-Facing Glyph Payload - -- The format name remains `GLYPH/indexed_v1`. -- The indexed pixel plane remains packed `u4`. -- The emitted glyph-bank sheet shape remains unchanged for this wave. -- The palette block changes from 2-byte RGB565 entries to 4-byte RGBA8888 - entries. -- The fixed palette block remains `64 * 16` entries for this wave. -- The byte-size formula for the palette block MUST be updated from - `64 * 16 * 2` to `64 * 16 * 4`. -- Size and decoded-size formulas for glyph-bank payloads MUST be updated - accordingly. -- Palette bytes MUST be interpreted as runtime RGBA channel order. - -### Authored and Projected Palette Data - -- Canonical palette data exposed by Studio/packer SHALL use `rgba8888`. -- `convertedRgb565` SHALL be removed from normal authored pipeline metadata, - details projections, read projections, fixtures, and tests. -- `originalArgb8888` SHALL NOT be the canonical field for runtime-facing or - packer-projected palette data in this wave. -- ARGB values read from Java image APIs MUST be converted to RGBA8888 before - entering canonical packer metadata or emitted payloads. - -### Transparency and Alpha - -- Palette index `0` is ordinary. -- A glyph palette has 16 usable entries. -- Alpha `0`, alpha between `1` and `254`, and alpha `255` are all valid - palette-entry states. -- Partial alpha MUST be preserved as data. -- Packer warnings or validations that describe partial alpha as flattened, - ignored, or unsupported MUST be removed. -- Color limit validation MUST be rewritten for 16 usable palette entries. - -### Removed Behaviors - -- RGB565 palette emission is not a normal packer output. -- RGB565 palette projection is not a normal Studio/packer read or details - contract. -- Magenta color-key transparency is not supported in the normal path. -- Palette index `0` is not reserved for transparency. -- Runtime asset compatibility with stale RGB565 palette payloads is not a - Studio/packer requirement for this wave. - -## Propagation Targets - -### Specs - -- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md` -- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` -- `docs/specs/studio/4. Assets Workspace Specification.md`, if Studio-facing - palette read/projection behavior is documented there. - -### Code - -- `prometeu-packer` palette model types. -- `PackerGlyphBankWalker`. -- `PackerAssetWalker` glyph-bank size and metadata calculations. -- `PackerAssetDetailsService`. -- `PackerReadMessageMapper`. -- Any packer serializer/materializer that emits `assets.pa` glyph payloads. -- Studio asset workspace read/detail surfaces that display or depend on - palette metadata. - -### Tests and Fixtures - -- Packer glyph-bank walker tests. -- Asset declaration parser tests that mention `convertedRgb565`. -- Runtime asset materializer tests. -- File-system workspace service tests. -- Fixture `asset.json` files that still declare RGB565-derived palette data. -- Test expectations for alpha, 16 usable colors, and removed magenta color-key - behavior. - -`main` and `fragments` project assets are expected to be regenerated manually -later and are not blockers for this decision. - -## Constraints - -- This decision MUST NOT introduce an RGB565 compatibility mode. -- This decision MUST NOT rename the runtime-facing format away from - `GLYPH/indexed_v1`. -- This decision MUST NOT change scene `palette_id` semantics except as needed - to ensure referenced glyph palettes now resolve RGBA8888 entries. -- This decision MUST NOT decide variable palette-count serialization. -- This decision MUST NOT close or revise `DSC-0005`; that discussion remains a - later palette-count optimization track. -- Any implementation plan derived from this decision MUST preserve all - normative requirements above unless the user explicitly requests a decision - revision. - -## References - -- Agenda: `AGD-0041` -- Runtime decision: `../runtime/discussion/workflow/decisions/DEC-0029-rgba8888-runtime-pixel-format-contract.md` -- Related future discussion: `DSC-0005` - -## Revision Log - -- 2026-05-23: Initial accepted decision from `AGD-0041`. diff --git a/discussion/workflow/decisions/DEC-0038-variable-glyph-bank-palette-serialization.md b/discussion/workflow/decisions/DEC-0038-variable-glyph-bank-palette-serialization.md new file mode 100644 index 00000000..e8998c37 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0038-variable-glyph-bank-palette-serialization.md @@ -0,0 +1,208 @@ +--- +id: DEC-0038 +ticket: variable-tile-bank-palette-serialization +title: Variable Glyph Bank Palette Serialization for Studio and Packer +status: accepted +created: 2026-07-14 +accepted: 2026-07-14 +ref_agenda: AGD-0005 +plans: + - PLN-0087 + - PLN-0088 + - PLN-0089 + - PLN-0090 + - PLN-0091 +tags: + - packer + - studio + - glyph-bank + - palette-serialization + - rgba8888 + - runtime-alignment +--- + +## Status + +Accepted. Drafted from accepted agenda `AGD-0005` and accepted on +2026-07-14. + +## Context + +This decision belongs to the `packer` domain, with Studio-facing projection and +fixture impact. Runtime protocol ownership remains in `../runtime`. + +Studio/packer already aligned glyph-bank colors with RGBA8888 through +`DSC-0038`. That work kept the `GLYPH/indexed_v1` format name and changed the +palette color encoding from RGB565-era data to RGBA8888 in runtime channel +order. It deliberately preserved the fixed 64-palette payload model for that +wave. + +Runtime `DEC-0041` now changes the authoritative `GLYPH/indexed_v1` contract: + +- `palette_count` is the number of serialized and resident palettes; +- `palette_count` MUST be in `1..=64`; +- payloads contain exactly `palette_count * 16 * 4` RGBA8888 palette bytes; +- `size = ceil(width * height / 2) + palette_count * 16 * 4`; +- `decoded_size = width * height + palette_count * 16 * 4`; +- resident runtime memory materializes exactly `palette_count` palettes; +- `palette_id` is direct identity within the loaded glyph bank and is valid + only when `palette_id < palette_count`; +- v1 has no sparse-to-dense palette remapping metadata; +- this remains `GLYPH/indexed_v1`, not a new v2 payload. + +Studio/packer must now follow that runtime-owned contract as downstream +producers of runtime-conforming `assets.pa` payloads. + +## Decision + +Studio and packer SHALL adopt variable glyph-bank palette serialization for +`GLYPH/indexed_v1`, following runtime `DEC-0041` as the protocol authority. + +Packer MUST stop emitting a fixed 64-palette block for glyph banks unless the +effective `palette_count` is actually `64`. + +Packer MUST emit exactly `palette_count * 16 * 4` palette bytes for each +`GLYPH/indexed_v1` glyph-bank payload. + +Packer MUST compute glyph-bank `size` as: + +```text +size = ceil(width * height / 2) + palette_count * 16 * 4 +``` + +Packer MUST compute glyph-bank `decoded_size` as: + +```text +decoded_size = width * height + palette_count * 16 * 4 +``` + +Packer MUST publish root effective metadata fields required by runtime: + +- `tile_size` +- `width` +- `height` +- `palette_count` + +For `GLYPH/indexed_v1`, `palette_count` MUST describe the number of serialized +RGBA8888 palettes and the number of resident palettes expected by runtime. +`palette_count` MUST be in the inclusive range `1..=64`. + +Packer and Studio MUST NOT introduce `GLYPH/indexed_v2` for this change. + +Packer and Studio MUST NOT preserve compatibility with the old fixed-padding +payload shape as a special mode. + +Packer and Studio MUST NOT introduce sparse-to-dense palette remapping metadata +for v1. + +`palette_authored`, when present in tooling or pipeline metadata, is +informative only. It MUST NOT be treated as effective runtime metadata unless a +later runtime decision promotes it. + +Palette bytes SHALL remain RGBA8888 in runtime `R`, `G`, `B`, `A` byte order. +Palette index `0` and color index `0` remain ordinary indices. Transparency +remains represented by the alpha channel of the resolved RGBA8888 color. + +## Rationale + +Runtime owns the `GLYPH/indexed_v1` wire contract. Once runtime `DEC-0041` +accepted variable palette serialization, keeping packer output fixed at 64 +palettes would make Studio/packer produce stale runtime payloads. + +Making `palette_count` the effective serialized and resident count removes the +old mismatch between authored palette count and payload shape. The packer no +longer needs to pad every glyph bank to 4096 palette bytes unless the bank +really uses all 64 palettes. + +Keeping the existing format name is correct because the project is still in v1 +and runtime explicitly accepted this as an incompatible v1 correction. A v2 +name would add migration surface without protecting any required compatibility +contract. + +Rejecting sparse-to-dense remapping keeps `palette_id` direct. Scene, sprite, +packer output, and runtime lookup all refer to the same palette identity inside +the loaded glyph bank. + +## Implications + +### Specs + +Packer specs MUST be updated so `GLYPH/indexed_v1` no longer describes a fixed +`64 * 16 * 4 = 4096` palette block as the normal payload shape. + +Packer specs MUST define `palette_count` as the effective serialized palette +count for glyph banks, constrained to `1..=64`. + +Studio specs MUST be updated only where Studio-facing projections, asset +details, pack wizard behavior, or fixtures expose the old fixed-padding model. + +### Code + +Packer payload emission MUST write only `palette_count` palettes. + +Packer payload validation/materialization helpers MUST compute size and decoded +size from variable `palette_count`. + +Packer metadata projection and Studio-facing read/detail APIs MUST expose the +runtime-effective `palette_count` correctly. + +Studio code MUST NOT treat `palette_authored` as the runtime-effective count. + +### Tests and Fixtures + +Tests MUST cover: + +- `palette_count = 1`; +- an intermediate `palette_count`; +- `palette_count = 64`; +- size and decoded-size formulas for variable counts; +- emitted RGBA8888 palette byte count; +- metadata/payload mismatch rejection or producer validation. + +Fixtures that encode the old fixed-padding assumption MUST be regenerated or +updated unless they intentionally use `palette_count = 64` and satisfy the new +runtime contract directly. + +### Non-goals + +This decision does not change RGBA8888 channel order. + +This decision does not change the packed `u4` indexed pixel plane. + +This decision does not change scene `palette_id` payload shape. + +This decision does not introduce v2, compatibility branches, or palette +identity remapping. + +## Propagation Targets + +- Specs: + - `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md` + - `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` + - `docs/specs/studio/4. Assets Workspace Specification.md`, if Studio-facing + palette count projection is documented there. +- Code: + - packer glyph-bank payload emission; + - packer asset walking/materialization; + - packer read/detail projections; + - Studio asset details or pack wizard surfaces if they expose palette counts. +- Tests: + - packer parser, walker, materializer, workspace service, and fixture tests; + - Studio tests if Studio projections or UI logic expose palette counts. +- Docs: + - downstream implementation plans derived from this decision. + +## References + +- Agenda: `AGD-0005` +- Runtime decision: + `../runtime/discussion/workflow/decisions/DEC-0041-variable-glyph-bank-palette-protocol.md` +- Runtime handoff: + `../runtime/discussion/workflow/plans/PLN-0172-runtime-spec-handoff-to-packer-and-studio.md` +- Prior Studio/packer RGBA8888 lesson: + `discussion/lessons/DSC-0038-studio-packer-rgba8888-asset-pipeline/LSN-0053-rgba8888-is-the-canonical-studio-packer-palette-contract.md` + +## Revision Log + +- 2026-07-14: Initial accepted decision from `AGD-0005`, aligned with runtime + `DEC-0041`. diff --git a/discussion/workflow/plans/PLN-0081-rgba8888-packer-and-studio-spec-propagation.md b/discussion/workflow/plans/PLN-0081-rgba8888-packer-and-studio-spec-propagation.md deleted file mode 100644 index 150d90eb..00000000 --- a/discussion/workflow/plans/PLN-0081-rgba8888-packer-and-studio-spec-propagation.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -id: PLN-0081 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Packer and Studio Spec Propagation -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - specs - - packer - - studio - - rgba8888 ---- - -## Objective - -Propagate `DEC-0037` into the normative Studio and packer specifications before -code implementation starts. - -## Background - -`DEC-0037` keeps `GLYPH/indexed_v1` but changes its palette contract from -RGB565 to RGBA8888. Specs currently still describe RGB565 palette bytes, -`convertedRgb565`, and a 2048-byte palette block. - -## Scope - -### Included - -- Update packer specs for `asset.json` palette metadata and `assets.pa` - glyph-bank payload layout. -- Update Studio asset workspace specs if they expose palette metadata or - details/read projection behavior. -- Preserve the fixed 64-palette model and explicitly leave `DSC-0005` for a - later palette-count optimization. - -### Excluded - -- Code changes. -- Test changes. -- Variable palette-count serialization. -- Runtime spec changes, except references to runtime `DEC-0029`. - -## Execution Steps - -### Step 1 - Update asset declaration palette fields - -**What:** Replace `originalArgb8888`/`convertedRgb565` examples and rules with -canonical `rgba8888`. - -**How:** Edit the palette portions of the asset declaration spec so -`output.pipeline.palettes[*].palette.rgba8888` is the canonical field. State -that ARGB may be an input API detail but is not canonical authored/projected -palette data. - -**File(s):** - -- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md` - -### Step 2 - Update glyph-bank payload layout - -**What:** Change `GLYPH/indexed_v1` palette layout from RGB565 to RGBA8888. - -**How:** Keep the format name. Change the palette block from -`64 * 16 * 2 = 2048` bytes to `64 * 16 * 4 = 4096` bytes. Update size and -decoded-size formulas. State that palette entries use runtime RGBA channel -order. - -**File(s):** - -- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` - -### Step 3 - Document alpha and index semantics - -**What:** Document that palette index `0` is ordinary and all 16 palette entries -are usable. - -**How:** Add normative rules that transparency and partial transparency are -encoded only by RGBA alpha, magenta color-key is removed, and partial alpha is -valid palette data. - -**File(s):** - -- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md` -- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` - -### Step 4 - Update Studio-facing projection rules - -**What:** Ensure Studio-facing docs use `rgba8888` where palette metadata is -visible. - -**How:** Update asset workspace language only where it describes palette read, -details, scene preview, or palette default behavior. Keep scene `palette_id` -semantics unchanged. - -**File(s):** - -- `docs/specs/studio/4. Assets Workspace Specification.md` - -## Test Requirements - -### Unit Tests - -- Not applicable for this spec-only plan. - -### Integration Tests - -- Not applicable for this spec-only plan. - -### Manual Verification - -- Search specs for stale `RGB565`, `convertedRgb565`, 2048-byte palette block, - reserved index `0`, and magenta color-key language. - -## Acceptance Criteria - -- [x] Packer specs define `rgba8888` as the canonical palette field. -- [x] `GLYPH/indexed_v1` remains named exactly that. -- [x] Palette block formulas use `64 * 16 * 4 = 4096`. -- [x] Specs state palette index `0` is ordinary and all 16 entries are usable. -- [x] Specs state partial alpha is valid and magenta color-key is removed. -- [x] Specs leave `DSC-0005` variable palette-count work out of scope. - -## Dependencies - -- Depends on accepted `DEC-0037`. -- Should complete before code plans are implemented. - -## Risks - -- Leaving stale RGB565 examples in specs will make implementation review - ambiguous. -- Over-editing scene specs could accidentally imply a scene payload change that - `DEC-0037` does not authorize. diff --git a/discussion/workflow/plans/PLN-0082-rgba8888-palette-model-and-argb-conversion.md b/discussion/workflow/plans/PLN-0082-rgba8888-palette-model-and-argb-conversion.md deleted file mode 100644 index ba2219cb..00000000 --- a/discussion/workflow/plans/PLN-0082-rgba8888-palette-model-and-argb-conversion.md +++ /dev/null @@ -1,144 +0,0 @@ ---- -id: PLN-0082 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Palette Model and ARGB Conversion -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - packer - - palette - - rgba8888 - - conversion ---- - -## Objective - -Replace the packer palette model with canonical RGBA8888 data and introduce a -single deliberate ARGB-to-RGBA conversion boundary for image inputs. - -## Background - -`PackerPaletteV1` currently stores `originalArgb8888` and `convertedRgb565`. -`PackerGlyphBankWalker` reads Java ARGB pixels, drops alpha semantics, reserves -index `0`, applies magenta color-key, and converts colors to RGB565. - -## Scope - -### Included - -- Replace `PackerPaletteV1` fields with canonical `rgba8888`. -- Add or localize ARGB-to-RGBA conversion helpers. -- Preserve partial alpha. -- Remove RGB565 conversion from the normal palette model. -- Expand glyph palette extraction from 15 to 16 usable colors. - -### Excluded - -- Binary `assets.pa` emission changes. -- Read/detail API projection changes outside direct model compile fixes. -- Spec edits. -- Fixture regeneration for `main` and `fragments`. - -## Execution Steps - -### Step 1 - Replace the palette record - -**What:** Change the packer palette model to carry canonical RGBA8888 values. - -**How:** Replace `int[] originalArgb8888, short[] convertedRgb565` with -`int[] rgba8888`. Keep the record name only if it remains semantically useful; -otherwise rename only if all callers are updated in the same change. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/models/PackerPaletteV1.java` - -### Step 2 - Convert ARGB image pixels to RGBA - -**What:** Introduce one conversion path from Java `BufferedImage` ARGB to raw -runtime RGBA. - -**How:** Convert `0xAARRGGBB` to `0xRRGGBBAA` when building palette entries. -Do not store ARGB in canonical packer metadata. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` - -### Step 3 - Remove magenta color-key and reserved index behavior - -**What:** Stop treating alpha zero or magenta as special palette-index behavior. - -**How:** Remove `COLOR_KEY_RGB`. Build palette identity from full RGBA8888 -values, including alpha. Assign indices from `0` through `15`. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` - -### Step 4 - Preserve partial alpha - -**What:** Remove partial-alpha warnings and flattening. - -**How:** Delete the `partialAlphaFound` warning path. Ensure pixels with alpha -from `0` through `255` participate in palette extraction by full RGBA value. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` - -### Step 5 - Update color-limit validation - -**What:** Change validation from 15 usable colors to 16 usable colors. - -**How:** Replace `MAX_COLORS_PER_PALETTE = 15` with a 16-entry limit and update -diagnostic wording to remove `indices 1..15`. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` - -## Test Requirements - -### Unit Tests - -- Update `PackerGlyphBankWalkerTest` to assert: - - 16 unique RGBA colors are valid. - - a 17th unique RGBA color is blocking. - - alpha `0`, partial alpha, and alpha `255` are preserved. - - magenta is treated as an ordinary color. - - palette index `0` can hold an ordinary color. - -### Integration Tests - -- None for this plan; binary emission is covered by a later plan. - -### Manual Verification - -- Search packer model and glyph walker sources for `convertedRgb565`, - `originalArgb8888`, `COLOR_KEY_RGB`, `convertToRgb565`, and partial-alpha - warning text. - -## Acceptance Criteria - -- [x] `PackerPaletteV1` exposes `rgba8888` and no RGB565 field. -- [x] `PackerGlyphBankWalker` stores canonical RGBA values. -- [x] Magenta is not special. -- [x] Alpha zero and partial alpha are valid palette data. -- [x] All 16 palette indices are usable. -- [x] Unit tests cover conversion and palette indexing semantics. - -## Dependencies - -- Depends on `PLN-0081` for spec wording. -- Must complete before payload emission and projection plans. - -## Risks - -- Confusing Java ARGB input with runtime RGBA output will create hard-to-debug - byte-order failures. -- Cache reuse may keep stale palette metadata if reusable metadata checks are - not updated with the model change. diff --git a/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md b/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md deleted file mode 100644 index 8ada8be9..00000000 --- a/discussion/workflow/plans/PLN-0083-rgba8888-glyph-payload-emission-and-sizes.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -id: PLN-0083 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Glyph Payload Emission and Size Accounting -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - packer - - assets-pa - - glyph-bank - - rgba8888 ---- - -## Objective - -Change packer glyph-bank runtime payload emission from RGB565 palette bytes to -RGBA8888 palette bytes while keeping `GLYPH/indexed_v1` and the fixed -64-palette model. - -## Background - -`DEC-0037` requires `GLYPH/indexed_v1` to retain its format name and indexed -model but emit RGBA8888 palette entries. Current payload emission in -`FileSystemPackerWorkspaceService` writes RGB565 bytes, reserves index `0`, and -uses color-key bytes. - -## Scope - -### Included - -- Update glyph-bank payload palette byte emission. -- Update measured payload size and decoded-size accounting. -- Remove RGB565 palette constants and palette color-key bytes from emission. -- Keep scene `palette_id` payload semantics unchanged. - -### Excluded - -- Palette model extraction changes covered by `PLN-0082`. -- Read/detail projection changes covered by `PLN-0084`. -- Variable palette count. - -## Execution Steps - -### Step 1 - Update glyph payload constants and formulas - -**What:** Change palette entry width from 2 bytes to 4 bytes. - -**How:** Introduce clear constants for palette count, colors per palette, and -RGBA bytes per color. Use `64 * 16 * 4` for palette block size. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerAssetWalker.java` -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerRuntimeAssetMaterializer.java` - -### Step 2 - Emit RGBA8888 palette bytes - -**What:** Write each palette color as runtime RGBA channel bytes. - -**How:** Replace RGB565 little-endian writes with four byte writes in `R`, `G`, -`B`, `A` order derived from the canonical `rgba8888` integer value. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` - -### Step 3 - Remove reserved color-key emission - -**What:** Stop writing a synthetic color-key value at palette index `0`. - -**How:** Remove `GLYPH_BANK_COLOR_KEY_RGB565` and any emission path that fills -index `0` with magenta. Emit declared RGBA values for index `0` like every -other index. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` - -### Step 4 - Update declared palette lookup - -**What:** Read `rgba8888` from declared pipeline metadata. - -**How:** Replace `originalArgb8888`/`convertedRgb565` lookup paths with -`rgba8888`. Ensure empty or malformed `rgba8888` is structural failure where -emission requires a palette. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerAssetWalker.java` - -### Step 5 - Keep scene payload stable - -**What:** Preserve scene `palette_id` layout. - -**How:** Do not change `writeSceneBankPayload` except compile fixes caused by -shared helper changes. Scene tile records continue carrying `palette_id` as an -index into the referenced glyph palette. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` - -## Test Requirements - -### Unit Tests - -- Add or update tests asserting glyph payload size includes a 4096-byte palette - block. -- Assert emitted palette bytes for a known RGBA value, including alpha. -- Assert index `0` emits declared RGBA data, not magenta. - -### Integration Tests - -- Update workspace build tests that read `build/assets.pa` and assert glyph-bank - offsets/sizes. - -### Manual Verification - -- Search production packer code for `GLYPH_BANK_COLOR_KEY_RGB565`, - `convertedRgb565`, RGB565 palette byte writes, and hard-coded `2048`. - -## Acceptance Criteria - -- [x] Glyph payloads keep `GLYPH/indexed_v1`. -- [x] Glyph palette blocks are 4096 bytes. -- [x] Palette entries are emitted as RGBA bytes in runtime channel order. -- [x] No synthetic magenta/color-key value is emitted. -- [x] Size and decoded-size metadata match the new payload length. -- [x] Scene `palette_id` payload shape is unchanged. - -## Dependencies - -- Depends on `PLN-0082`. -- Should run before tests/fixture conformance in `PLN-0085`. - -## Risks - -- Updating size formulas without updating emitted bytes, or vice versa, will - corrupt payload slicing in `assets.pa`. -- Accidental scene payload edits could widen the change beyond `DEC-0037`. diff --git a/discussion/workflow/plans/PLN-0084-rgba8888-packer-projections-and-workspace-apis.md b/discussion/workflow/plans/PLN-0084-rgba8888-packer-projections-and-workspace-apis.md deleted file mode 100644 index 08581c42..00000000 --- a/discussion/workflow/plans/PLN-0084-rgba8888-packer-projections-and-workspace-apis.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -id: PLN-0084 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Packer Projections and Workspace APIs -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - packer - - studio - - api - - rgba8888 ---- - -## Objective - -Update packer and Studio-facing read/detail/write projections so palette data -is exposed and accepted as `rgba8888`, with no normal `convertedRgb565` or -canonical `originalArgb8888` surface. - -## Background - -`DEC-0037` requires packer metadata, Studio read/detail projections, tests, and -fixtures to stop treating RGB565 as normal palette data. Several services still -parse or project `originalArgb8888` and `convertedRgb565`. - -## Scope - -### Included - -- Update parser and declaration normalization for palette metadata. -- Update read/detail mappers. -- Update palette-overhauling and bank-composition support to emit `rgba8888`. -- Preserve existing DTO shapes except for palette payload field names. - -### Excluded - -- Binary payload byte emission. -- Renderer/runtime changes. -- Manual regeneration of `main` and `fragments`. - -## Execution Steps - -### Step 1 - Update asset declaration parsing - -**What:** Parse canonical `rgba8888` arrays from `asset.json`. - -**How:** Replace palette validation that requires `originalArgb8888` and -`convertedRgb565` with validation for `rgba8888`. Keep numeric validation. -Reject malformed or missing `rgba8888` where a palette payload is required. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java` - -### Step 2 - Update details projection - -**What:** Return `rgba8888` from asset details. - -**How:** Change `palettePayloadFromNode` to project `{ index, rgba8888 }`. -Remove `convertedRgb565` and canonical `originalArgb8888` from details output. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDetailsService.java` - -### Step 3 - Update read message mapping - -**What:** Map `PackerPaletteV1` and cached palette metadata to `rgba8888`. - -**How:** Replace `originalArgb8888` and `convertedRgb565` mapping with a single -`rgba8888` array. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerReadMessageMapper.java` - -### Step 4 - Update workspace write operations - -**What:** Ensure packer write APIs that apply palette changes persist `rgba8888`. - -**How:** Replace palette-overhauling and related write-lane logic that requires -both `originalArgb8888` and `convertedRgb565` with a `rgba8888` contract. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` - -### Step 5 - Update cache reuse and walk projection checks - -**What:** Make cache reuse validate new palette metadata. - -**How:** Replace reusable metadata checks for `originalArgb8888` with -`rgba8888`. Stale cached RGB565-derived metadata must not be considered -reusable. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` -- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerAssetWalker.java` - -## Test Requirements - -### Unit Tests - -- Update parser tests to accept `rgba8888` and reject missing/malformed - `rgba8888`. -- Update details service tests to assert `rgba8888`. -- Update read mapper coverage for `PackerPaletteV1`. -- Update write operation tests for palette overhauling. - -### Integration Tests - -- Exercise a workspace read/build flow from `asset.json` using `rgba8888`. - -### Manual Verification - -- Search `prometeu-packer` for `originalArgb8888` and `convertedRgb565` after - this plan. Remaining matches must be migration-only or removed in later - fixture plan. - -## Acceptance Criteria - -- [x] `asset.json` palette metadata uses `rgba8888`. -- [x] Details/read projections expose `rgba8888`. -- [x] Workspace write operations persist `rgba8888`. -- [x] Stale RGB565-derived cache metadata is not reused as canonical. -- [x] No normal API requires `convertedRgb565`. - -## Dependencies - -- Depends on `PLN-0082`. -- Can run partly in parallel with `PLN-0083` after the palette model is stable. - -## Risks - -- DTO consumers may assume old map keys. Tests must cover the Studio-facing - projection boundary. -- Cache reuse can hide stale behavior if not invalidated by metadata shape. diff --git a/discussion/workflow/plans/PLN-0085-rgba8888-tests-fixtures-and-conformance.md b/discussion/workflow/plans/PLN-0085-rgba8888-tests-fixtures-and-conformance.md deleted file mode 100644 index f0c14c6a..00000000 --- a/discussion/workflow/plans/PLN-0085-rgba8888-tests-fixtures-and-conformance.md +++ /dev/null @@ -1,141 +0,0 @@ ---- -id: PLN-0085 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Tests, Fixtures, and Conformance Updates -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - tests - - fixtures - - conformance - - rgba8888 ---- - -## Objective - -Update packer tests and fixtures so RGBA8888 is the asserted source of truth and -RGB565-specific expectations are removed. - -## Background - -`DEC-0037` requires tests and fixtures to stop proving RGB565 behavior. The code -base has parser, walker, details, materializer, and workspace service tests that -mention `convertedRgb565`, `originalArgb8888`, 15-color limits, magenta -color-key behavior, and RGB565 payload sizes. - -## Scope - -### Included - -- Update packer unit tests and integration-style workspace tests. -- Update fixture `asset.json` files under packer test resources. -- Add conformance-oriented assertions for RGBA channel order, alpha, index `0`, - 16 usable colors, and removed color-key behavior. - -### Excluded - -- Manual regeneration of `test-projects/main` and `fragments`. -- Production code changes except minor compile-fix test helpers. -- Runtime repository tests. - -## Execution Steps - -### Step 1 - Update parser and details tests - -**What:** Replace palette payload fixtures with `rgba8888`. - -**How:** Rewrite test JSON snippets and assertions that mention -`originalArgb8888` or `convertedRgb565`. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java` -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDetailsServiceTest.java` - -### Step 2 - Update glyph walker tests - -**What:** Assert new palette extraction semantics. - -**How:** Add image fixtures in tests that cover: -16 colors, 17-color failure, alpha 0, partial alpha, magenta as ordinary color, -and index `0` as ordinary. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/repositories/PackerGlyphBankWalkerTest.java` - -### Step 3 - Update materializer and workspace service tests - -**What:** Assert RGBA8888 runtime payload and metadata behavior. - -**How:** Update tests that read `assets.pa`, measured bank size, payload offsets, -and palette byte expectations. Replace RGB565 byte checks with RGBA byte checks. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/repositories/PackerRuntimeAssetMaterializerTest.java` -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java` -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerRuntimePatchServiceTest.java` -- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerRuntimeRegistryTest.java` - -### Step 4 - Update packer fixture assets - -**What:** Replace fixture `asset.json` palette fields with `rgba8888`. - -**How:** Edit packer test fixtures under `src/test/resources/fixtures` so -canonical palette declarations do not contain `convertedRgb565`. - -**File(s):** - -- `prometeu-packer/prometeu-packer-v1/src/test/resources/fixtures/**/asset.json` - -### Step 5 - Add stale-contract guards - -**What:** Add tests or quality checks that catch old RGB565 palette contract -residue. - -**How:** Add assertions in existing tests or a focused repository quality test -that normal packer specs/tests/fixtures do not contain `convertedRgb565` or -RGB565 glyph palette payload expectations. - -**File(s):** - -- Existing packer test suites under `prometeu-packer/prometeu-packer-v1/src/test/java` - -## Test Requirements - -### Unit Tests - -- Parser, details, mapper, glyph walker, and workspace service unit tests must - all pass. - -### Integration Tests - -- Run the relevant Gradle test task for `prometeu-packer-v1`. - -### Manual Verification - -- Search for `convertedRgb565`, `originalArgb8888`, `RGB565`, `rgb565`, `2048`, - and magenta color-key references in packer tests and fixtures. - -## Acceptance Criteria - -- [x] Tests use `rgba8888` as canonical palette data. -- [x] Tests assert RGBA channel order and alpha preservation. -- [x] Tests assert 16 usable palette entries. -- [x] Tests assert magenta is ordinary or no longer special. -- [x] Tests assert 4096-byte palette blocks where payload size is checked. -- [x] Packer test fixtures no longer rely on `convertedRgb565`. - -## Dependencies - -- Depends on `PLN-0082`, `PLN-0083`, and `PLN-0084`. - -## Risks - -- Some stale generated fixture data may be easier to regenerate than hand-edit. -- Overbroad residue checks could flag historical discussion artifacts; scope - checks to normal specs, code, tests, and fixtures. diff --git a/discussion/workflow/plans/PLN-0086-rgba8888-final-integration-and-residue-removal.md b/discussion/workflow/plans/PLN-0086-rgba8888-final-integration-and-residue-removal.md deleted file mode 100644 index 56f28883..00000000 --- a/discussion/workflow/plans/PLN-0086-rgba8888-final-integration-and-residue-removal.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -id: PLN-0086 -ticket: studio-packer-rgba8888-asset-pipeline -title: RGBA8888 Final Integration and Residue Removal -status: done -created: 2026-05-23 -completed: 2026-05-23 -ref_decisions: - - DEC-0037 -tags: - - integration - - validation - - residue-removal - - rgba8888 ---- - -## Objective - -Run final integration checks and remove normal-path RGB565 residue after the -spec, model, emission, projection, and test plans are implemented. - -## Background - -`DEC-0037` prohibits RGB565 compatibility mode, normal `convertedRgb565` -projection, magenta color-key behavior, reserved palette index `0`, and partial -alpha flattening. Final validation must prove that the repository implements -those constraints coherently. - -## Scope - -### Included - -- Repository-wide residue audit. -- Full relevant Gradle test execution. -- Discussion workflow validation. -- Final implementation notes for follow-up plan or lesson creation. - -### Excluded - -- New feature design. -- Runtime repository changes. -- Variable palette-count work in `DSC-0005`. -- Manual regeneration of `main` and `fragments`. - -## Execution Steps - -### Step 1 - Run focused residue searches - -**What:** Find stale RGB565 palette-contract residue. - -**How:** Search production specs/code/tests/fixtures for: -`convertedRgb565`, `originalArgb8888`, `RGB565`, `rgb565`, `COLOR_KEY`, -`magenta`, `2048`, `indices 1..15`, and partial-alpha flattening text. -Classify each match as removed, historical discussion-only, or out-of-scope. - -**File(s):** - -- `docs/specs/packer/**` -- `docs/specs/studio/**` -- `prometeu-packer/**` - -### Step 2 - Run packer tests - -**What:** Execute the packer test suite. - -**How:** Run the Gradle test task that covers `prometeu-packer-v1` and related -API modules. - -**File(s):** - -- Gradle modules under `prometeu-packer` - -### Step 3 - Run broader build validation - -**What:** Verify Studio build integration still compiles. - -**How:** Run the repository's standard build or the narrowest existing Gradle -task that compiles Studio plus packer consumers. - -**File(s):** - -- Root Gradle project -- `prometeu-app` -- `prometeu-packer` - -### Step 4 - Validate discussion workflow - -**What:** Ensure discussion artifacts remain consistent. - -**How:** Run `discussion validate` after implementation and before any -housekeeping. - -**File(s):** - -- `discussion/index.ndjson` -- `discussion/workflow/**` - -### Step 5 - Record remaining intentional residue - -**What:** Document any allowed remaining RGB565 references. - -**How:** If matches remain only in historical discussions, runtime references, -or explicit future migration notes, list them in the implementation summary so -housekeeping and lesson work can distinguish intentional context from missed -normal-path behavior. - -**File(s):** - -- Implementation summary or future lesson, after code work is complete. - -## Test Requirements - -### Unit Tests - -- Packer unit tests must pass. - -### Integration Tests - -- Packer workspace build/materialization tests must pass. -- Studio compile/build validation must pass. - -### Manual Verification - -- Residue search results must contain no normal-path `convertedRgb565`, - RGB565 glyph palette payload, magenta color-key, reserved index `0`, or - partial-alpha flattening behavior. - -## Acceptance Criteria - -- [x] `discussion validate` passes. -- [x] Packer tests pass. -- [x] Studio/packer build validation passes. -- [x] Normal specs/code/tests/fixtures contain no stale RGB565 glyph-palette - contract residue. -- [x] Remaining stale-looking matches, if any, are documented as historical or - explicitly out of scope. -- [x] `DSC-0005` remains untouched except by explicit future work. - -## Execution Notes - -- `discussion validate` passed. -- `./gradlew build` passed. -- Residue search found only: - - normative spec statements explicitly saying `convertedRgb565` and magenta - color-key behavior are not normal contract; - - `test-projects/main` asset manifests, which are intentionally out of scope - for this implementation because they will be regenerated manually later. -- `DSC-0005` was not modified. - -## Dependencies - -- Depends on `PLN-0081` through `PLN-0085`. - -## Risks - -- A broad residue search may include historical discussions and cause false - positives. -- Generated project cache files may change during tests; those changes must be - reviewed separately from source edits. diff --git a/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md b/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md new file mode 100644 index 00000000..392bd58b --- /dev/null +++ b/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md @@ -0,0 +1,132 @@ +--- +id: PLN-0087 +ticket: variable-tile-bank-palette-serialization +title: Variable Glyph Palette Spec Propagation +status: open +created: 2026-07-14 +completed: +ref_decisions: + - DEC-0038 +tags: + - specs + - packer + - studio + - glyph-bank + - palette-serialization +--- + +## Objective + +Propagate `DEC-0038` into the canonical Studio and packer specifications before +code changes start. + +## Background + +Runtime `DEC-0041` makes `palette_count` the serialized and resident palette +count for `GLYPH/indexed_v1`. Studio/packer `DEC-0038` adopts that runtime +contract downstream. Current packer specs still describe a fixed +`64 * 16 * 4 = 4096` palette block and `palette_count = 64`. + +## Scope + +### Included + +- Update packer specs for glyph-bank metadata, payload layout, and size formulas. +- Update Studio specs only where Studio-facing palette count projection or asset + details are documented. +- Preserve RGBA8888 channel order, packed `u4` pixels, and `GLYPH/indexed_v1`. + +### Excluded + +- Code changes. +- Fixture regeneration. +- Runtime spec changes. +- Any `GLYPH/indexed_v2` design. + +## Execution Steps + +### Step 1 - Update asset declaration metadata rules + +**What:** Define `palette_count` as the effective runtime metadata field. + +**How:** Update glyph-bank declaration language so `palette_count` means the +number of serialized and resident RGBA8888 palettes, constrained to `1..=64`. +State that `palette_authored`, if present, is informative and not runtime +effective. + +**File(s):** + +- `docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md` + +### Step 2 - Update glyph payload layout + +**What:** Replace fixed 4096-byte palette block text. + +**How:** Change the layout to `palette_count * 16 * 4` palette bytes and update +formulas to: + +```text +size = ceil(width * height / 2) + palette_count * 16 * 4 +decoded_size = width * height + palette_count * 16 * 4 +``` + +**File(s):** + +- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` + +### Step 3 - Preserve v1 boundaries + +**What:** Explicitly prohibit v2, compatibility padding, and remapping. + +**How:** Add rules that this remains `GLYPH/indexed_v1`, old fixed-padding is +not a compatibility mode, and v1 has no sparse-to-dense palette remapping. + +**File(s):** + +- `docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md` + +### Step 4 - Update Studio-facing spec text + +**What:** Align Studio projections if they mention palette count or fixed bank +shape. + +**How:** Search the Studio asset workspace spec for palette projection, details, +or pack wizard language and update only stale fixed-count wording. + +**File(s):** + +- `docs/specs/studio/4. Assets Workspace Specification.md` + +## Test Requirements + +### Unit Tests + +- Not applicable for this spec-only plan. + +### Integration Tests + +- Not applicable for this spec-only plan. + +### Manual Verification + +- Search specs for stale normal-path `palette_count = 64`, `4096`, fixed + 64-palette block, `GLYPH/indexed_v2`, and remapping language. + +## Acceptance Criteria + +- [ ] Packer specs define `palette_count` as runtime-effective `1..=64`. +- [ ] Packer specs use variable palette byte and size formulas. +- [ ] Specs keep `GLYPH/indexed_v1` and reject v2 for this change. +- [ ] Specs reject fixed-padding compatibility and sparse-to-dense remapping. +- [ ] Studio specs contain no stale fixed 64-palette projection wording. + +## Dependencies + +- Depends on accepted `DEC-0038`. +- Should complete before code plans. + +## Risks + +- Leaving stale fixed 4096-byte examples will make implementation review + ambiguous. +- Over-editing Studio specs could imply UI behavior not required by `DEC-0038`. diff --git a/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md b/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md new file mode 100644 index 00000000..234352b3 --- /dev/null +++ b/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md @@ -0,0 +1,140 @@ +--- +id: PLN-0088 +ticket: variable-tile-bank-palette-serialization +title: Variable Glyph Palette Metadata and Count Model +status: open +created: 2026-07-14 +completed: +ref_decisions: + - DEC-0038 +tags: + - packer + - metadata + - glyph-bank + - palette-count +--- + +## Objective + +Make packer metadata compute and expose runtime-effective glyph-bank +`palette_count` from declared palette data instead of hard-coding `64`. + +## Background + +`DEC-0038` requires `palette_count` to describe the number of serialized and +resident palettes expected by runtime. Current packer code emits +`palette_count = 64` and uses `palette_authored` for the actual authored count. +That makes the informative count and effective runtime count diverge. + +## Scope + +### Included + +- Compute effective glyph palette count from declared `output.pipeline.palettes`. +- Validate `palette_count` in `1..=64`. +- Keep palette identity direct; do not remap sparse authored indices. +- Stop using `palette_authored` as a runtime-effective field. + +### Excluded + +- Binary payload byte emission. +- Size formula changes. +- Studio UI changes except compile-safe DTO/projection adjustments. + +## Execution Steps + +### Step 1 - Add a runtime-effective palette count helper + +**What:** Centralize effective glyph palette count calculation. + +**How:** Add or update helper logic so packer derives `palette_count` from +declared palette indices. Because v1 has no remapping, the effective count must +cover the highest direct palette id: `max(index) + 1`. Reject no palettes, +negative indices, duplicate indices, and any effective count above `64`. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerAssetWalker.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java` + +### Step 2 - Replace fixed runtime metadata + +**What:** Stop writing `palette_count = 64` unconditionally. + +**How:** Replace runtime metadata emission so glyph-bank entries publish the +computed runtime-effective `palette_count`. Keep `palette_authored` only if it +is useful as pipeline/tooling information and never as runtime-effective root +metadata. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerRuntimeAssetMaterializer.java` + +### Step 3 - Validate direct palette identity + +**What:** Preserve runtime direct `palette_id` semantics. + +**How:** Ensure packer does not compact or renumber palette indices. If palette +indices are sparse, emitted palette slots up to `palette_count - 1` must keep +their direct identity, with missing slots represented by deterministic default +RGBA8888 palette data only when required to preserve direct ids. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerGlyphBankWalker.java` + +### Step 4 - Update projections that expose metadata + +**What:** Align details/read projections with the effective count. + +**How:** Ensure packer read/details APIs expose `palette_count` consistently +where runtime metadata is projected, and do not present `palette_authored` as +the field that runtime consumes. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDetailsService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerReadMessageMapper.java` + +## Test Requirements + +### Unit Tests + +- Parser/metadata tests for `palette_count = 1`, intermediate count, and `64`. +- Rejection tests for zero effective palettes, duplicate indices, negative + indices, and count above `64`. +- Sparse direct identity tests where palette index `3` implies + `palette_count = 4`, without remapping palette `3` to `0`. + +### Integration Tests + +- Workspace read/build test proving asset table metadata reports variable + `palette_count`. + +### Manual Verification + +- Search packer code for `palette_count = 64` and `GLYPH_BANK_PALETTE_COUNT` + assumptions after the change. + +## Acceptance Criteria + +- [ ] Packer computes runtime-effective `palette_count` from declared palettes. +- [ ] `palette_count` is validated as `1..=64`. +- [ ] Sparse palette ids are not remapped. +- [ ] `palette_authored` is not treated as runtime-effective metadata. +- [ ] Read/details projections do not expose stale fixed-count assumptions. + +## Dependencies + +- Depends on `PLN-0087`. +- Must complete before payload emission changes in `PLN-0089`. + +## Risks + +- Sparse palette handling can accidentally become remapping if implemented by + sorting and compacting declarations. +- Keeping `palette_authored` in tooling may confuse readers unless tests prove + runtime-effective metadata uses `palette_count`. diff --git a/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md b/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md new file mode 100644 index 00000000..c32f6c0f --- /dev/null +++ b/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md @@ -0,0 +1,140 @@ +--- +id: PLN-0089 +ticket: variable-tile-bank-palette-serialization +title: Variable Glyph Palette Payload Emission and Size Accounting +status: open +created: 2026-07-14 +completed: +ref_decisions: + - DEC-0038 +tags: + - packer + - assets-pa + - glyph-bank + - payload +--- + +## Objective + +Change packer `GLYPH/indexed_v1` payload emission from a fixed 64-palette block +to exactly `palette_count * 16 * 4` RGBA8888 bytes, with matching size and +decoded-size accounting. + +## Background + +`FileSystemPackerWorkspaceService` currently defines fixed palette constants +and emits a fixed `GLYPH_BANK_PALETTE_BYTES` block. `DEC-0038` requires packer +to emit only the runtime-effective palette count and compute asset table sizes +from that count. + +## Scope + +### Included + +- Replace fixed palette byte constants with count-dependent formulas. +- Emit exactly `palette_count` palettes in RGBA byte order. +- Update asset table `size` and `decoded_size`. +- Reject metadata/payload mismatches. + +### Excluded + +- Palette model extraction changes covered by `PLN-0088`. +- Studio UI changes. +- Runtime code changes. + +## Execution Steps + +### Step 1 - Replace fixed palette byte constants + +**What:** Remove normal-path fixed `64 * 16 * 4` size assumptions. + +**How:** Keep maximum constants such as `MAX_PALETTE_COUNT = 64`, but compute +payload palette bytes as `palette_count * 16 * 4` at each glyph-bank packing +boundary. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerAssetWalker.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerRuntimeAssetMaterializer.java` + +### Step 2 - Emit variable palette bytes + +**What:** Write only runtime-effective palettes. + +**How:** Update palette byte generation to allocate +`palette_count * 16 * 4` bytes and fill direct palette ids from `0` through +`palette_count - 1`. Each color remains RGBA8888 in `R`, `G`, `B`, `A` order. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` + +### Step 3 - Update size and decoded-size formulas + +**What:** Align asset table sizes with runtime `DEC-0041`. + +**How:** Compute: + +```text +size = ceil(width * height / 2) + palette_count * 16 * 4 +decoded_size = width * height + palette_count * 16 * 4 +``` + +Use these formulas for asset table entries, materializer expectations, and +workspace build outputs. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerRuntimeAssetMaterializer.java` + +### Step 4 - Reject metadata/payload mismatches + +**What:** Prevent stale fixed-padding artifacts. + +**How:** Add validation that emitted palette byte length, root metadata +`palette_count`, `size`, and `decoded_size` agree. Do not allow a fixed +64-palette block when `palette_count < 64`. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/repositories/PackerRuntimeAssetMaterializer.java` + +## Test Requirements + +### Unit Tests + +- Assert emitted palette bytes for `palette_count = 1`, an intermediate count, + and `64`. +- Assert `size` and `decoded_size` formulas for variable counts. +- Assert RGBA byte order is unchanged. + +### Integration Tests + +- Build a workspace and inspect `assets.pa` asset table and payload length for + variable palette counts. + +### Manual Verification + +- Search for fixed normal-path `4096`, `64 * 16 * 4`, and + `GLYPH_BANK_PALETTE_BYTES` residue. + +## Acceptance Criteria + +- [ ] Glyph payloads emit exactly `palette_count * 16 * 4` palette bytes. +- [ ] Asset table `size` and `decoded_size` use variable formulas. +- [ ] RGBA byte order is unchanged. +- [ ] Fixed 64-palette padding is emitted only when `palette_count = 64`. +- [ ] Metadata/payload mismatch is rejected or impossible by construction. + +## Dependencies + +- Depends on `PLN-0088`. + +## Risks + +- Updating metadata without payload length will corrupt runtime slicing. +- Updating payload length without decoded-size metadata will fail runtime asset + validation. diff --git a/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md b/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md new file mode 100644 index 00000000..5e822da9 --- /dev/null +++ b/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md @@ -0,0 +1,134 @@ +--- +id: PLN-0090 +ticket: variable-tile-bank-palette-serialization +title: Studio and Packer Projections for Variable Glyph Palettes +status: open +created: 2026-07-14 +completed: +ref_decisions: + - DEC-0038 +tags: + - studio + - packer + - api + - projections + - glyph-bank +--- + +## Objective + +Align Studio-facing and packer-facing projections so variable glyph +`palette_count` is visible and not confused with `palette_authored`. + +## Background + +`DEC-0038` says packer metadata projection and Studio-facing read/detail APIs +must expose the runtime-effective `palette_count` correctly. Studio code must +not treat `palette_authored` as the runtime-effective count. + +## Scope + +### Included + +- Update packer read/detail DTO projections where runtime metadata is surfaced. +- Update Studio asset details, palette overhauling, schema, or pack wizard code + if it reads fixed counts or authored counts as runtime-effective. +- Keep `rgba8888` color projection unchanged. + +### Excluded + +- Binary payload emission. +- General palette UI redesign. +- `originalArgb8888` UI fallback cleanup unrelated to variable `palette_count`. + +## Execution Steps + +### Step 1 - Audit projection boundaries + +**What:** Find all Studio/packer paths that expose glyph palette metadata. + +**How:** Search for `palette_count`, `palette_authored`, +`GLYPH_BANK_PALETTE_COUNT`, fixed `64`, and related asset details projections. +Classify each match as runtime-effective metadata, tooling-only metadata, UI +fallback, or unrelated. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDetailsService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerReadMessageMapper.java` +- `prometeu-studio/src/main/java/p/studio/workspaces/assets/**` + +### Step 2 - Update packer details/read surfaces + +**What:** Expose runtime-effective `palette_count`. + +**How:** Ensure details/read projections show the `palette_count` that will be +written to the runtime asset table. Preserve `palette_authored` only as +explicitly tooling-only information if it remains useful. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDetailsService.java` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerReadMessageMapper.java` + +### Step 3 - Update Studio consumers + +**What:** Prevent Studio from using authored count as runtime count. + +**How:** Adjust Studio asset details and pack wizard code so any displayed or +validated runtime count comes from effective `palette_count`. Keep palette +color rendering based on `rgba8888`. + +**File(s):** + +- `prometeu-studio/src/main/java/p/studio/workspaces/assets/details/**` +- `prometeu-studio/src/test/java/p/studio/workspaces/assets/details/**` + +### Step 4 - Preserve scene palette id shape + +**What:** Avoid accidental scene payload changes. + +**How:** Confirm scene projections still carry `palette_id` unchanged and only +runtime/packer validation changes count semantics. + +**File(s):** + +- `prometeu-studio/src/main/java/p/studio/workspaces/assets/**` +- `prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java` + +## Test Requirements + +### Unit Tests + +- Packer details/read tests for variable `palette_count`. +- Studio asset details tests proving runtime count and authored/tooling count + are not conflated. + +### Integration Tests + +- Workspace read/build flow where a glyph bank with an intermediate + `palette_count` is projected through packer/Studio surfaces. + +### Manual Verification + +- Search Studio and packer projection code for stale assumptions that + `palette_authored` is runtime-effective. + +## Acceptance Criteria + +- [ ] Packer read/details projections expose effective `palette_count`. +- [ ] Studio consumers do not use `palette_authored` as runtime-effective count. +- [ ] `rgba8888` color projection remains unchanged. +- [ ] Scene `palette_id` payload shape is unchanged. +- [ ] Tests cover variable count projection. + +## Dependencies + +- Depends on `PLN-0088`. +- Can run in parallel with `PLN-0089` after metadata semantics are stable. + +## Risks + +- UI code may still need ARGB helper fields for presentation. This plan must not + turn that into a runtime metadata decision. +- Overbroad projection edits could accidentally change scene contracts. diff --git a/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md b/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md new file mode 100644 index 00000000..6e2ce675 --- /dev/null +++ b/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md @@ -0,0 +1,153 @@ +--- +id: PLN-0091 +ticket: variable-tile-bank-palette-serialization +title: Variable Glyph Palette Tests, Fixtures, and Final Validation +status: open +created: 2026-07-14 +completed: +ref_decisions: + - DEC-0038 +tags: + - tests + - fixtures + - validation + - glyph-bank + - palette-serialization +--- + +## Objective + +Update tests and fixtures to prove Studio/packer emit runtime-conforming +variable glyph palette payloads and contain no stale fixed-padding assumptions. + +## Background + +`DEC-0038` requires downstream fixture coverage for `palette_count = 1`, an +intermediate count, and `palette_count = 64`, plus producer validation for +metadata/payload mismatch. Earlier tests still assert `palette_count = 64`, +4096-byte palette blocks, and fixed glyph payload sizes. + +## Scope + +### Included + +- Update packer unit tests and integration-style workspace tests. +- Update packer fixture `asset.json` files and expected runtime payload checks. +- Update Studio tests only where Studio projections or UI logic expose + effective palette count. +- Run focused and broad validation. + +### Excluded + +- Runtime repository tests. +- New feature design. +- Palette remapping behavior. + +## Execution Steps + +### Step 1 - Update packer parser and metadata tests + +**What:** Prove effective `palette_count` validation. + +**How:** Add tests for `palette_count = 1`, intermediate counts, `64`, +duplicate/sparse direct identity behavior, and rejection above `64`. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java` +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/repositories/PackerGlyphBankWalkerTest.java` + +### Step 2 - Update payload and asset table tests + +**What:** Prove variable payload lengths and size formulas. + +**How:** Replace fixed 4096-byte expectations with +`palette_count * 16 * 4`. Assert `size`, `decoded_size`, payload offsets, and +RGBA bytes for several counts. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java` +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/repositories/PackerRuntimeAssetMaterializerTest.java` +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerRuntimePatchServiceTest.java` +- `prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerRuntimeRegistryTest.java` + +### Step 3 - Update fixtures + +**What:** Replace stale fixed-padding fixtures. + +**How:** Regenerate or edit packer test fixtures so at least one glyph bank uses +`palette_count = 1`, one uses an intermediate count, and one uses `64`. +Fixtures with fixed 64 padding are valid only when metadata says +`palette_count = 64`. + +**File(s):** + +- `prometeu-packer/prometeu-packer-v1/src/test/resources/fixtures/**/asset.json` +- Related binary or generated expected payload fixtures under packer test + resources. + +### Step 4 - Update Studio tests + +**What:** Cover Studio-facing projection changes. + +**How:** Adjust tests only where Studio surfaces effective palette counts or +metadata. Keep color rendering assertions focused on `rgba8888`. + +**File(s):** + +- `prometeu-studio/src/test/java/p/studio/workspaces/assets/details/**` + +### Step 5 - Run validation and residue scans + +**What:** Prove no normal-path fixed-padding residue remains. + +**How:** Run relevant Gradle tests and search normal specs/code/tests/fixtures +for stale `palette_count = 64`, `4096`, fixed `64 * 16 * 4`, `GLYPH/indexed_v2`, +and sparse remapping language. Classify any remaining match as historical, +max-bound, or a bug. + +**File(s):** + +- `docs/specs/packer/**` +- `docs/specs/studio/**` +- `prometeu-packer/**` +- `prometeu-studio/**` + +## Test Requirements + +### Unit Tests + +- Packer parser, walker, materializer, details/read, and workspace service tests + pass. +- Studio asset details tests pass where touched. + +### Integration Tests + +- Packer workspace build/materialization tests pass. +- Repository build or narrow Studio/packer build validation passes. + +### Manual Verification + +- Residue scan finds no normal-path fixed-padding contract text or code. +- `discussion validate` passes. + +## Acceptance Criteria + +- [ ] Tests cover `palette_count = 1`, an intermediate count, and `64`. +- [ ] Tests cover variable `size` and `decoded_size`. +- [ ] Tests cover emitted palette byte length and RGBA order. +- [ ] Tests cover metadata/payload mismatch rejection or producer validation. +- [ ] Fixtures no longer rely on fixed 64-palette padding unless count is `64`. +- [ ] Validation commands pass. +- [ ] Residue scan results are clean or explicitly classified. + +## Dependencies + +- Depends on `PLN-0087`, `PLN-0088`, `PLN-0089`, and `PLN-0090`. + +## Risks + +- Generated project fixtures may require regeneration rather than manual edits. +- Broad residue scans may include historical discussions; scope final checks to + active specs, code, tests, and fixtures. diff --git a/test-projects/main/assets/.prometeu/cache.json b/test-projects/main/assets/.prometeu/cache.json index a120673e..6b0c9b03 100644 --- a/test-projects/main/assets/.prometeu/cache.json +++ b/test-projects/main/assets/.prometeu/cache.json @@ -14,13 +14,13 @@ "last_modified" : 1779659315450, "fingerprint" : "ac565160c0dceb321b8f6c9094f2b5e6ae398396fe32c8ead706f5cc36f465cf", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 673720574, -523190018, -117903106, 945858814, -1600620290, 1484833022 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgICAgICAQAAAAAAAAAAAAABAQEAAAAAAAAAAAAAAAEDBAQEBAQCAQAAAAAAAQEBAQICAgEAAAAAAAAAAAAAAQMEAgUFBQQCAQEBAQECAgICBAQEAgEAAAAAAAAAAAABAwQCBQUFBQQDAwMDAgQEBAQFAgIEAwEBAAAAAAAAAAEDBAIFBQUFAgQEBgYEBQUFBQICAgIEAwMBAQAAAAAAAQMEAgUFBQICAgMDAwIFBQUFBQICAgIGBgMCAQAAAAABAwQCBQUFAgICAgMDAgUFBQUFAgICAwMDBAQCAQEAAAEDBAIFBQUCAgICAwMCBQUFBQUCAgICAwMCAgQFAQAAAQMEAgUFBQICAgIDAwIFBQUFBAQEBAQDAwQEBQEAAAABAwQCBQUFAgICAgMDAgUFBAQFAgICAgYGAgUBAAAAAAEDBAIEBAQEBAICAwMCBQQFBQEBAQEBAwMBAQAAAAAAAQMEBAUFBQUCBAIDAwIEBQEBAAAAAAABAQAAAAAAAAABAwICBQEBAQECBAYGBAUBAAAAAAAAAAAAAAAAAAAAAQECAgIBAAAAAAEDAwICAQAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 673720574, -523190018, -117903106, 945858814, -1600620290, 1484833022 ] } }, "diagnostics" : [ ] @@ -59,13 +59,13 @@ "last_modified" : 1779659315452, "fingerprint" : "6dd024eb2259efaa03908ff0c3b75eb67f9da56d365e4a35d8e619b71c7507db", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 255, -540033025, -134746113, -101191169, 945858815, 1501544959, -1617463297, -1583777281, -1583908353, -1617462785, 929015807, 962701823, 690432511 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgMDBAEBAQEBAAAAAAAAAAAAAAABAQAAAAAAAAAAAAECBQYGBAIHBwgBAAAAAAAAAAEBAQICAQEAAAAAAAAAAQIFAwMGBQUFBQIBAAAAAAEBCQIHBQUDBAEBAAAAAAABAgUDAwIICAoIBQIBAQEBBwcLCwwIAgYGAwMBAAAAAAECBQMDAgoKCgoKBQMDAwIFBQgCCgIKAgIGAwEAAAAAAQIFAwMCCAgICAgCBQYGBQoKCgoCCgICAwMGAwEAAAABAgUDAggICAgICAICAwMCCAgIAggFBQUGBgYDDQAAAAECBgMCCAgICAgIAgIDAggICAgFBQoCAwMDAwQEAQAAAQIGAwIICAgICAgCAgMCCAgIBQgKAQEBAQEBAQQBAAABAgYDAggICAgIAgICAwIKCAUIAQEAAAAAAAAAAQEAAAECBgMCCAgICAUFAgIDAggFCgEAAAAAAAAAAAAAAAAAAQIGAwIICAUFCAIFBQYLBQgBAAAAAAAAAAAAAAAAAAABAgYFBQUFCAoBAQIDBAIJAQAAAAAAAAAAAAAAAAAAAQECAwIICAgBAQAAAQEBAQEAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 255, -540033025, -134746113, -101191169, 945858815, 1501544959, -1617463297, -1583777281, -1583908353, -1617462785, 929015807, 962701823, 690432511 ] } }, "diagnostics" : [ ] @@ -76,13 +76,13 @@ "last_modified" : 1779659315453, "fingerprint" : "c8e30f40473deedb265be26967f6bf5f2ba35a2bd5d0a049dcb8843fa60d5600", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -93,13 +93,13 @@ "last_modified" : 1779659315454, "fingerprint" : "58a6a9bc02d9174fdc6bcd6f71f5fb86c47d506812e83cae5b0e23a1f951dbbf", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQECAgMDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQQEAQICAwMDAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAgEAAAAAAAAAAAAAAAAAAAAAAAAAAQUBBQQFAQICAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgIDAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQBAQgBAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAEICQECAgEAAAAAAAAAAAAAAAAAAAAAAAABCAgBBwEEAQkGAQICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgkJAQUBBgEFAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGAQYBAQEAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEHAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEBBwMBAwMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBCQoBBwEDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCQoBAgIBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAECAgEBAQICAQECAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAQECAgEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAgEBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQELCwoBAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQsLAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -110,13 +110,13 @@ "last_modified" : 1779659315454, "fingerprint" : "110c4f835a40bb370c7bb7761afcd69de0d38e75798d20d50f4c203aa56f213a", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQECAgMDAQEAAAEBAAAAAAAAAAAAAAAAAAAAAAABBAQEAQICAwMDAgEBAwEAAAAAAAAAAAAAAAAAAAAAAAEFBQQEAQICAwICAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAEBBQQFAQICAgICAwEBAAAAAAAAAAAAAAAAAAAAAAAAAQYBBQUFAQIBAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBgcBBQQFAQgBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEIAQcBBAUBCQEBBQUBAAAAAAAAAAAAAAAAAAAAAAABCAgBBwgBBAUBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgkJBgYBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQYGBgYBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJCgEHAwECAwEBAQAAAAAAAAAAAAAAAAAAAAAAAAABAQkKAQcCAQIDAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAEKAQEBAQECAgEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAQEKAQICAQEBAgIBAQoLAQAAAAAAAAAAAAAAAAAAAAAAAQEBAQECAgICAQEAAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -127,13 +127,13 @@ "last_modified" : 1779659315455, "fingerprint" : "2e6fb2cfbf77f4b3c0d116b9b77a3ae228cdc5671bd18320285824faef9674d3", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBCQkGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAABCQoBAQEGBgEBAQUBAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgEHAgEBAQMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwICAQIDAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQECAgMBAQIBAAAAAAAAAAAAAAAAAAAAAAAAAQoBAQIBAgICAgECAQEAAAAAAAAAAAAAAAAAAAAAAAABCgoBAgIBAQEBAgELAQAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQICAgIBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -144,13 +144,13 @@ "last_modified" : 1779659315455, "fingerprint" : "c8e30f40473deedb265be26967f6bf5f2ba35a2bd5d0a049dcb8843fa60d5600", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBBgEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAwECAwIBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAQcHBwECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAEBAQEBAQECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAgEJCgoBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEJCQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEKAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQELCwoKAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -161,13 +161,13 @@ "last_modified" : 1779659315456, "fingerprint" : "94ac699b5e913925cf881e76ff951875147b598b1ee9870187111e7ca0b40d1d", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAQAAAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgMBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAEBCAECAwEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEAQgJAQICAQAAAAAAAAAAAAAAAAAAAAAAAAEICAEHAQQBCQYBAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkBBQEGAQUBAgEAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYBAQEBAQABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQcBAQEDAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAwMBAgcHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQMDAwIBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBAIDAgEKCgECAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAECAQEBAQkJAQIBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQECAgICAQECAQoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQICAgEKCgEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBCgoKAQAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239 ] } }, "diagnostics" : [ ] @@ -178,13 +178,13 @@ "last_modified" : 1779659315457, "fingerprint" : "fc0a623650619ca39c1ce2f9f9e1b0f6951abd194e18ea60c682fae6a769df97", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQICAwMBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEEBAQBAgIDAwMCAQABAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgIBAQMBAAAAAAAAAAAAAAAAAAAAAAAAAQEFBAUBAgICAgIDAwEAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEFBQEAAAAAAAAAAAAAAAAAAAAAAAEICAEHCAEEBQEBBQEBAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBgYGAQIDAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCQEBAQEBAQEHAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBBwcDAgEKCgEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAgIBAwMCAQkJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQIBAgMCAQEBCgEAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQIBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAABCwsKAQICAgIBCgoBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -195,13 +195,13 @@ "last_modified" : 1779659315457, "fingerprint" : "7ada8efefcd6d069b10846fefb9bd9cff1a1fa4c1565bbebfd68fc83645f0732", "metadata" : { - "palette" : { - "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] - }, "tile" : { "width" : 32, "height" : 32, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBAAAAAAEBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQICAwMBAQEBAwEAAAAAAAAAAAAAAAAAAAAAAAABBAQBAgIDAwMCAQMDAQAAAAAAAAAAAAAAAAAAAAAAAQUFBAQBAgIDAgICAwIBAAAAAAAAAAAAAAAAAAAAAAABBQEFBAUBAgICAgMCAQAAAAAAAAAAAAAAAAAAAAAAAAABBgEFBQUBAgECAgIBAAAAAAAAAAAAAAAAAAAAAAAAAAEGBwEFBAUBCAEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQgBBwEEBQEJAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEICAEHCQEEBQEFAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEGCQkGBgEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAABAQEBBgYGAQIDAgEBAAAAAAAAAAAAAAAAAAAAAAAAAAEJAQEBAQEBAgIBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBBwcDAgIBAQoKAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQQBAwMDAgIBCQkBAAAAAAAAAAAAAAAAAAAAAAAAAAEBAgECAwMCAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAABCwYBAgEBAQECAgEKAQAAAAAAAAAAAAAAAAAAAAAAAAELCgYBAgICAgEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAEKCgoBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBAQEBAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 0, 538976511, 1368527103, 1907499263, -205315841, -1014890241, -1302257409, -202116097, -207461889, -476950017, 1631658239, -1300082177 ] } }, "diagnostics" : [ ] @@ -250,13 +250,13 @@ "last_modified" : 1776965154257, "fingerprint" : "8771c3e294d0edbc8dd3aaa6995a6db32166ae6bfb3e063170cc79b298d17e71", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711 ] } }, "diagnostics" : [ ] @@ -267,13 +267,13 @@ "last_modified" : 1776965154257, "fingerprint" : "5d81eef8be13043330b42b546e10beed8ba00dfaa42df67477a8778c2b9484d7", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 1081622783, 677921023, 676868351, 673720575, -2005909249, -1466932993, 1615868159 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAAAAAAAAAEBAQABAQEBAQEBAQIDBAQEBAMCAwQFBQUFBAIDBAUFBgYHAgMEBwUFBwcAAgQEBwcHBg==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 1081622783, 677921023, 676868351, 673720575, -2005909249, -1466932993, 1615868159 ] } }, "diagnostics" : [ ] @@ -284,13 +284,13 @@ "last_modified" : 1776965154258, "fingerprint" : "3250840c4fe08c134ea966ce7c8fcaccae2c2a45660d7173c5e262a2e5076548", "metadata" : { - "palette" : { - "rgba8888" : [ 1081622783, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAABAgIAAAAAAQIDBAAAAAECAwQEAAECAgMDAwMCAgUEBAQEBAMFBAQFBQUFBAQEBQUEBAQEBQUFBAQFBQ==" + }, + "palette" : { + "rgba8888" : [ 1081622783, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] } }, "diagnostics" : [ ] @@ -301,13 +301,13 @@ "last_modified" : 1776965154258, "fingerprint" : "fe3ab2b7eb3b10a042de14484d53e718e6b505edb1ad19053668565bfe3a8f25", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 676868351, 1081622783, -1466932993, 1615868159, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgICAgIDBAABAgICAgMDBAABAgICBAQEBAAAAQIDAwMDAwUAAAUFBQUDAwUEAwMDBQUDAwMFBQMDBQUFAw==" + }, + "palette" : { + "rgba8888" : [ 673720575, 676868351, 1081622783, -1466932993, 1615868159, -2005909249 ] } }, "diagnostics" : [ ] @@ -318,13 +318,13 @@ "last_modified" : 1776965154259, "fingerprint" : "7fcbf90e1e9a69d6ce3be80ea1901d66c9992f68dc72e4c636dcd2ad52fa2898", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 1081622783, 676868351, 673720575, 677921023, -2005909249, 1615868159, -1466932993 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAAAAAAABAQEAAAAAAAEBAQEBAQEAAgMDAwMCBAEDBQUFBQMCBAYHBwUFAwIEBgYFBQYDAgQHBgYGAwMEAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 1081622783, 676868351, 673720575, 677921023, -2005909249, 1615868159, -1466932993 ] } }, "diagnostics" : [ ] @@ -335,13 +335,13 @@ "last_modified" : 1776965154259, "fingerprint" : "451fc8d646049944d5aa7c7dc254636eec0151aaff6e2051059304b9d6ebc31e", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 677921023, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAwMEBQUAAAECAwUFBgAAAAIDBQYGAAAAAwMFBgYAAAMEAwUGBgADBgQDBQYGAwYFBAMFBgYDBgUEAwUGBg==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 677921023, 676868351, 673720575, 1615868159, -1466932993, -2005909249 ] } }, "diagnostics" : [ ] @@ -352,13 +352,13 @@ "last_modified" : 1776965154260, "fingerprint" : "aa757df4600823ec6655235a1081061777124ccee74b31481bbe402e53635f53", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgIAAAAAAQEAAgIAAQEBAAAAAgIBAQEAAAECAwIBAQAAAQIDAwEBAAABAgMDAQEAAAECAwIBAQEAAgMCAQ==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -369,13 +369,13 @@ "last_modified" : 1776965154260, "fingerprint" : "38162157f5685cce25b835d3a2caee3465fd2ec3ee5db2a5089d7d5ae5ea3bb7", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, 1615868159, -1466932993, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQECAAACAAEBAAICAAIBAQAAAAICAQMBAgAAAgIDAwECAAACAgMDAQIAAAICAQMBAgAAAgICAQMBAAICAg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, 1615868159, -1466932993, 673720575 ] } }, "diagnostics" : [ ] @@ -386,13 +386,13 @@ "last_modified" : 1776965154260, "fingerprint" : "8cab5b3d553af9ed371bd19fc624763accc90e5d926d300ba31dd8d9d6bab803", "metadata" : { - "palette" : { - "rgba8888" : [ -1466932993, 1615868159, 673720575, 676868351, 677921023, 1217939711, -2005909249 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAgIDBAUGAAACAwQFBQYGAAIDBQUFBgYAAgIFBQUGBgACAQIFBQYGAAIBBgIFBgYAAgEABgIGBgACAQAGAg==" + }, + "palette" : { + "rgba8888" : [ -1466932993, 1615868159, 673720575, 676868351, 677921023, 1217939711, -2005909249 ] } }, "diagnostics" : [ ] @@ -403,13 +403,13 @@ "last_modified" : 1776965154261, "fingerprint" : "d9ff5a6df0f65f5fcfb8f22376beeb266d429e2c6e9c82f51c12bc6ee4c3fcdc", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 1615868159, -2005909249, -1466932993, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAQEAAwIEAAABAQADAwQFBAABAQADBgUEBAABAAAGBgUFBAAAAQYGBgUEAAICBgYGBgAAAgIGBgYEAAEBAg==" + }, + "palette" : { + "rgba8888" : [ 673720575, 1615868159, -2005909249, -1466932993, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -420,13 +420,13 @@ "last_modified" : 1776965154261, "fingerprint" : "b9ff45c77f7779a6acebcc537c2ddac0e27e91162b656a04dc4772ec5f24fc26", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAEBAgIAAAEAAAICAQEAAAEAAAAAAQEAAQEBAQAAAQEDAgIBAQAAAAIDAgIBAQAAAAIDAgICAQEAAgIDAgICAg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -437,13 +437,13 @@ "last_modified" : 1776965154261, "fingerprint" : "43f370324fedccda888d49409e2a64f182f08b4143b4bdd5bafaf498feebd21a", "metadata" : { - "palette" : { - "rgba8888" : [ -1466932993, -2005909249, 1615868159, 673720575 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAEBAgIAAAEBAQAAAgIBAQEAAAEBAQEAAAABAQAAAAABAQEAAAICAwEBAAACAgMCAAACAgIDAgECAgICAwICAQ==" + }, + "palette" : { + "rgba8888" : [ -1466932993, -2005909249, 1615868159, 673720575 ] } }, "diagnostics" : [ ] @@ -454,13 +454,13 @@ "last_modified" : 1776965154262, "fingerprint" : "cb047e655f4e196f22ca0048149df5dcb959f895faeaeb94920182d4a2d16b38", "metadata" : { - "palette" : { - "rgba8888" : [ -2005909249, -1466932993, 673720575, 1615868159, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAECAwMAAwIBAQIDAwICBAECAwMCBAUEAgIDAgQEBQYDAgIEBQUGBgAAAgQFBgYGAAACAgYGBgYAAwMCBAYGBg==" + }, + "palette" : { + "rgba8888" : [ -2005909249, -1466932993, 673720575, 1615868159, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -471,13 +471,13 @@ "last_modified" : 1776965154262, "fingerprint" : "25eba17b67dd5159f5fb9d3edd531d54a44d1c76f997385840dac53517b98886", "metadata" : { - "palette" : { - "rgba8888" : [ 1217939711, 673720575, -2005909249, 1615868159, 676868351, 677921023 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQICAwMAAAECAgICAwAAAQICAgIDAAABAgIDAQMAAAEDAQQEAQAABAQFBAUEAAAAAAAFAAUAAAAAAAAAAA==" + }, + "palette" : { + "rgba8888" : [ 1217939711, 673720575, -2005909249, 1615868159, 676868351, 677921023 ] } }, "diagnostics" : [ ] @@ -488,13 +488,13 @@ "last_modified" : 1776965154262, "fingerprint" : "32ca96c14290de8009fd2db623f55514bed2345b7d5881a80dd3fe6235012854", "metadata" : { - "palette" : { - "rgba8888" : [ 1615868159, 673720575, 676868351, -2005909249, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAAAAQAAAQEBAAEBAAEAAAEBAgEBAAADAQICAgEAAAMCAgQCAgEAAAQEBQQEAQADBQUFBQUCAQAFBQUFBQUCAQ==" + }, + "palette" : { + "rgba8888" : [ 1615868159, 673720575, 676868351, -2005909249, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -505,13 +505,13 @@ "last_modified" : 1776965154263, "fingerprint" : "7a093fe00c805bcf38d4facff14a6d4c2b8baeaa2d553fa8d3db9f2d76b32f3b", "metadata" : { - "palette" : { - "rgba8888" : [ 673720575, 1615868159, -2005909249, 676868351, 677921023, 1217939711 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAQABAQEBAQABAAABAAIBAQAAAwAAAgEBAAMDAwABAQADAwQDAwIBAAQEBQQEAQADBQUFBQUAAwUFBQUFBQ==" + }, + "palette" : { + "rgba8888" : [ 673720575, 1615868159, -2005909249, 676868351, 677921023, 1217939711 ] } }, "diagnostics" : [ ] @@ -522,13 +522,13 @@ "last_modified" : 1776965154263, "fingerprint" : "77c5277220421226d16f58b1bcfb4eaf157fa4f6c740c5aaebefaf88fb91c22e", "metadata" : { - "palette" : { - "rgba8888" : [ 1615868159, -2005909249, 673720575, 1217939711, 676868351, 677921023 ] - }, "tile" : { "width" : 8, "height" : 8, "paletteIndices" : "AAABAQIDAwMAAQEBAQIDAwABAQEBAgMDAAIAAQECAwMCBAQCAAIDAwQFBAUEBAMDBQMFAwMDAwMDAwMDAwMDAw==" + }, + "palette" : { + "rgba8888" : [ 1615868159, -2005909249, 673720575, 1217939711, 676868351, 677921023 ] } }, "diagnostics" : [ ] -- 2.47.2 From 340442d374a11a4faa669a70f444bcc4eb40bdd1 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:25:52 +0100 Subject: [PATCH 2/6] implements PLN-0087 --- discussion/index.ndjson | 2 +- ...variable-glyph-palette-spec-propagation.md | 14 +++++++------- ...nd Virtual Asset Contract Specification.md | 5 +++++ ...and Deterministic Packing Specification.md | 19 +++++++++++++------ .../4. Assets Workspace Specification.md | 5 +++++ 5 files changed, 31 insertions(+), 14 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 91256ee0..6571931f 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md b/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md index 392bd58b..6c59a310 100644 --- a/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md +++ b/discussion/workflow/plans/PLN-0087-variable-glyph-palette-spec-propagation.md @@ -2,9 +2,9 @@ id: PLN-0087 ticket: variable-tile-bank-palette-serialization title: Variable Glyph Palette Spec Propagation -status: open +status: done created: 2026-07-14 -completed: +completed: 2026-07-14 ref_decisions: - DEC-0038 tags: @@ -114,11 +114,11 @@ or pack wizard language and update only stale fixed-count wording. ## Acceptance Criteria -- [ ] Packer specs define `palette_count` as runtime-effective `1..=64`. -- [ ] Packer specs use variable palette byte and size formulas. -- [ ] Specs keep `GLYPH/indexed_v1` and reject v2 for this change. -- [ ] Specs reject fixed-padding compatibility and sparse-to-dense remapping. -- [ ] Studio specs contain no stale fixed 64-palette projection wording. +- [x] Packer specs define `palette_count` as runtime-effective `1..=64`. +- [x] Packer specs use variable palette byte and size formulas. +- [x] Specs keep `GLYPH/indexed_v1` and reject v2 for this change. +- [x] Specs reject fixed-padding compatibility and sparse-to-dense remapping. +- [x] Studio specs contain no stale fixed 64-palette projection wording. ## Dependencies diff --git a/docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md b/docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md index 25d0fbb8..ca4a2a09 100644 --- a/docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md +++ b/docs/specs/packer/3. Asset Declaration and Virtual Asset Contract Specification.md @@ -121,6 +121,11 @@ Rules: - glyph-bank palette payloads must expose canonical `rgba8888` color values in runtime RGBA channel order; - ARGB values produced by host image APIs are import-side implementation details, not canonical declaration or projection fields; - `convertedRgb565` is not part of the normal palette contract; +- glyph-bank `palette_count` is an effective runtime metadata field and means + the number of serialized and resident RGBA8888 palettes for the bank; +- glyph-bank `palette_count` must be in the inclusive range `1..=64`; +- `palette_authored`, when present, is informative tooling metadata only and + must not be treated as runtime-effective metadata; - the packer must sort such entries by numeric `index`, not by physical array position; - duplicate or malformed indices are structural errors; - missing or malformed `palette` payloads are structural errors; diff --git a/docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md b/docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md index a91b9f1a..b4f9cd80 100644 --- a/docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md +++ b/docs/specs/packer/4. Build Artifacts and Deterministic Packing Specification.md @@ -147,7 +147,8 @@ Offset ambiguity guardrail: ## Format-Specific Baseline: `GLYPH/indexed_v1` -The first-wave producer contract for `GLYPH/indexed_v1` is fixed and runtime-aligned. +The producer contract for `GLYPH/indexed_v1` is runtime-aligned and uses a +variable RGBA8888 palette block. ### Tile Selection and Identity @@ -178,7 +179,7 @@ Rules: - the serialized payload for `GLYPH/indexed_v1` is: 1. one packed `u4` pixel plane for the full emitted sheet; - 2. one palette block of `64 * 16 * 4 = 4096` bytes; + 2. one palette block of `palette_count * 16 * 4` bytes; - packed pixel bytes must be emitted by the packer, not inferred later by the runtime; - the palette block is serialized as RGBA8888 values in runtime RGBA channel order; - each palette entry is emitted as four bytes in `R`, `G`, `B`, `A` order; @@ -196,10 +197,15 @@ Rules: - `width` - `height` - `palette_count` -- tile-bank v1 requires `palette_count = 64`; +- tile-bank v1 requires `palette_count` in the inclusive range `1..=64`; +- `palette_count` is the number of serialized palettes and resident runtime + palettes for the bank; - tile-bank v1 size formulas are: - - `size = ceil(width * height / 2) + 4096` - - `decoded_size = (width * height) + 4096` + - `size = ceil(width * height / 2) + palette_count * 16 * 4` + - `decoded_size = (width * height) + palette_count * 16 * 4` +- fixed 64-palette padding is not a compatibility mode unless + `palette_count = 64` and the payload directly satisfies the v1 contract; +- `GLYPH/indexed_v2` must not be introduced for this palette-count correction. ### Palette Contract @@ -209,7 +215,8 @@ Rules: - each palette declaration uses the shape `{ "index": , "palette": { ... } }`; - each palette payload uses canonical `rgba8888` entries interpreted as `0xRRGGBBAA`; - palette ordering is ascending numeric `index`, never raw array position; -- palette ids in the emitted glyph bank are the normalized declared palette indices; +- palette ids in the emitted glyph bank are direct declared palette indices; +- v1 has no sparse-to-dense palette remapping metadata; - palette index `0` is ordinary and may carry any RGBA8888 value; - glyph palettes have 16 usable entries; - transparency and partial transparency are encoded only by RGBA alpha; diff --git a/docs/specs/studio/4. Assets Workspace Specification.md b/docs/specs/studio/4. Assets Workspace Specification.md index a721f34b..29ac5444 100644 --- a/docs/specs/studio/4. Assets Workspace Specification.md +++ b/docs/specs/studio/4. Assets Workspace Specification.md @@ -226,6 +226,11 @@ Rules: - `preload` - Glyph-bank palette projections must use canonical `rgba8888` values when palette data is shown. +- Glyph-bank runtime output projections must present `palette_count`, when + shown, as the runtime-effective serialized and resident palette count in + `1..=64`. +- Studio-facing glyph palette views must not present `palette_authored` as the + runtime-effective count. - Studio-facing glyph palette views must not expose `convertedRgb565` as normal runtime or tooling truth. - Runtime-facing output information must not require raw JSON inspection. -- 2.47.2 From fae4e9a9fd8a269ecaa8b37c7b70a59bbe77336e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:27:54 +0100 Subject: [PATCH 3/6] implements PLN-0088 --- discussion/index.ndjson | 2 +- ...-glyph-palette-metadata-and-count-model.md | 14 +++--- .../FileSystemPackerWorkspaceService.java | 43 +++++++++++++++++-- .../PackerAssetDeclarationParser.java | 8 ++++ 4 files changed, 55 insertions(+), 12 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 6571931f..81318786 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md b/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md index 234352b3..00790618 100644 --- a/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md +++ b/discussion/workflow/plans/PLN-0088-variable-glyph-palette-metadata-and-count-model.md @@ -2,9 +2,9 @@ id: PLN-0088 ticket: variable-tile-bank-palette-serialization title: Variable Glyph Palette Metadata and Count Model -status: open +status: done created: 2026-07-14 -completed: +completed: 2026-07-14 ref_decisions: - DEC-0038 tags: @@ -121,11 +121,11 @@ the field that runtime consumes. ## Acceptance Criteria -- [ ] Packer computes runtime-effective `palette_count` from declared palettes. -- [ ] `palette_count` is validated as `1..=64`. -- [ ] Sparse palette ids are not remapped. -- [ ] `palette_authored` is not treated as runtime-effective metadata. -- [ ] Read/details projections do not expose stale fixed-count assumptions. +- [x] Packer computes runtime-effective `palette_count` from declared palettes. +- [x] `palette_count` is validated as `1..=64`. +- [x] Sparse palette ids are not remapped. +- [x] `palette_authored` is not treated as runtime-effective metadata. +- [x] Read/details projections do not expose stale fixed-count assumptions. ## Dependencies diff --git a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java index b2e1b2b9..cc8b0760 100644 --- a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java +++ b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java @@ -38,11 +38,11 @@ import java.util.*; import java.util.stream.Stream; public final class FileSystemPackerWorkspaceService implements PackerWorkspaceService { - private static final int GLYPH_BANK_PALETTE_COUNT = 64; + private static final int GLYPH_BANK_MAX_PALETTE_COUNT = 64; private static final int GLYPH_BANK_COLORS_PER_PALETTE = 16; private static final int GLYPH_BANK_RGBA8888_BYTES_PER_COLOR = 4; private static final int GLYPH_BANK_PALETTE_BYTES = - GLYPH_BANK_PALETTE_COUNT * GLYPH_BANK_COLORS_PER_PALETTE * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; + GLYPH_BANK_MAX_PALETTE_COUNT * GLYPH_BANK_COLORS_PER_PALETTE * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; private static final String SCENE_BANK_SUPPORT_FILE = "scene-bank.studio.json"; private static final String SCENE_PACK_REQUEST_FILE = "scene-bank.pack-request.json"; @@ -1125,6 +1125,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe }); final byte[] packedPixels = packNibbles(sheetPixels); + final int paletteCount = runtimeGlyphPaletteCount(declaration); final byte[] paletteBytes = emitGlyphBankPalettes(declaration); final byte[] payload = new byte[packedPixels.length + paletteBytes.length]; System.arraycopy(packedPixels, 0, payload, 0, packedPixels.length); @@ -1134,7 +1135,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe runtimeMetadata.put("tile_size", tileSize); runtimeMetadata.put("width", width); runtimeMetadata.put("height", height); - runtimeMetadata.put("palette_count", GLYPH_BANK_PALETTE_COUNT); + runtimeMetadata.put("palette_count", paletteCount); runtimeMetadata.put("palette_authored", countAuthoredGlyphBankPalettes(declaration)); runtimeMetadata.put("codec", Map.of()); declaration.outputMetadata().forEach((key, value) -> { @@ -1288,7 +1289,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe continue; } final int paletteIndex = indexNode.intValue(); - if (paletteIndex < 0 || paletteIndex >= GLYPH_BANK_PALETTE_COUNT) { + if (paletteIndex < 0 || paletteIndex >= GLYPH_BANK_MAX_PALETTE_COUNT) { continue; } final JsonNode rgbaNode = paletteNode.path("rgba8888"); @@ -1313,6 +1314,40 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe return palettesNode instanceof ArrayNode palettesArray ? palettesArray.size() : 0; } + private int runtimeGlyphPaletteCount(PackerAssetDeclaration declaration) { + final JsonNode palettesNode = declaration.outputPipelineMetadata().get("palettes"); + if (!(palettesNode instanceof ArrayNode palettesArray) || palettesArray.isEmpty()) { + throw new IllegalStateException("Glyph packing requires at least one declared pipeline palette."); + } + int maxPaletteIndex = -1; + final Set seen = new HashSet<>(); + for (JsonNode declarationNode : palettesArray) { + final JsonNode indexNode = declarationNode.path("index"); + final JsonNode paletteNode = declarationNode.path("palette"); + if (!indexNode.isInt() || indexNode.intValue() < 0) { + throw new IllegalStateException("Glyph packing requires non-negative integer palette indices."); + } + final int paletteIndex = indexNode.intValue(); + if (!seen.add(paletteIndex)) { + throw new IllegalStateException("Glyph packing requires unique palette indices."); + } + if (paletteIndex >= GLYPH_BANK_MAX_PALETTE_COUNT) { + throw new IllegalStateException("Glyph packing supports palette indices in 0.." + + (GLYPH_BANK_MAX_PALETTE_COUNT - 1) + "."); + } + if (!paletteNode.path("rgba8888").isArray()) { + throw new IllegalStateException("Glyph packing requires rgba8888 entries in each declared palette."); + } + maxPaletteIndex = Math.max(maxPaletteIndex, paletteIndex); + } + final int paletteCount = maxPaletteIndex + 1; + if (paletteCount < 1 || paletteCount > GLYPH_BANK_MAX_PALETTE_COUNT) { + throw new IllegalStateException("Glyph packing requires palette_count in 1..=" + + GLYPH_BANK_MAX_PALETTE_COUNT + "."); + } + return paletteCount; + } + private byte[] encodeScenePackRequest(ScenePackRequest request) { final ByteArrayOutputStream output = new ByteArrayOutputStream(); writeBytes(output, new byte[]{'S', 'C', 'N', 'E'}); diff --git a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java index 315205b4..346a8458 100644 --- a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java +++ b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/PackerAssetDeclarationParser.java @@ -324,6 +324,14 @@ public final class PackerAssetDeclarationParser { "Field 'output.pipeline.palettes' contains duplicate palette index " + indexNode.intValue() + ".", manifestPath, true)); + } else if (indexNode.intValue() >= MAX_PIPELINE_PALETTES) { + diagnostics.add(new PackerDiagnostic( + PackerDiagnosticSeverity.ERROR, + PackerDiagnosticCategory.STRUCTURAL, + "Field 'output.pipeline.palettes' cannot declare palette index " + indexNode.intValue() + + "; maximum supported index is " + (MAX_PIPELINE_PALETTES - 1) + ".", + manifestPath, + true)); } if (!paletteNode.isObject()) { -- 2.47.2 From 13425cee0384065ba90e7258041f4fe006a011ec Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:29:18 +0100 Subject: [PATCH 4/6] implements PLN-0089 --- discussion/index.ndjson | 2 +- ...te-payload-emission-and-size-accounting.md | 14 ++++++------- .../FileSystemPackerWorkspaceService.java | 20 ++++++++++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 81318786..859764ac 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md b/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md index c32f6c0f..161cdca0 100644 --- a/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md +++ b/discussion/workflow/plans/PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md @@ -2,9 +2,9 @@ id: PLN-0089 ticket: variable-tile-bank-palette-serialization title: Variable Glyph Palette Payload Emission and Size Accounting -status: open +status: done created: 2026-07-14 -completed: +completed: 2026-07-14 ref_decisions: - DEC-0038 tags: @@ -123,11 +123,11 @@ workspace build outputs. ## Acceptance Criteria -- [ ] Glyph payloads emit exactly `palette_count * 16 * 4` palette bytes. -- [ ] Asset table `size` and `decoded_size` use variable formulas. -- [ ] RGBA byte order is unchanged. -- [ ] Fixed 64-palette padding is emitted only when `palette_count = 64`. -- [ ] Metadata/payload mismatch is rejected or impossible by construction. +- [x] Glyph payloads emit exactly `palette_count * 16 * 4` palette bytes. +- [x] Asset table `size` and `decoded_size` use variable formulas. +- [x] RGBA byte order is unchanged. +- [x] Fixed 64-palette padding is emitted only when `palette_count = 64`. +- [x] Metadata/payload mismatch is rejected or impossible by construction. ## Dependencies diff --git a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java index cc8b0760..f1c5fe4b 100644 --- a/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java +++ b/prometeu-packer/prometeu-packer-v1/src/main/java/p/packer/services/FileSystemPackerWorkspaceService.java @@ -41,8 +41,6 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe private static final int GLYPH_BANK_MAX_PALETTE_COUNT = 64; private static final int GLYPH_BANK_COLORS_PER_PALETTE = 16; private static final int GLYPH_BANK_RGBA8888_BYTES_PER_COLOR = 4; - private static final int GLYPH_BANK_PALETTE_BYTES = - GLYPH_BANK_MAX_PALETTE_COUNT * GLYPH_BANK_COLORS_PER_PALETTE * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; private static final String SCENE_BANK_SUPPORT_FILE = "scene-bank.studio.json"; private static final String SCENE_PACK_REQUEST_FILE = "scene-bank.pack-request.json"; @@ -1126,7 +1124,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe final byte[] packedPixels = packNibbles(sheetPixels); final int paletteCount = runtimeGlyphPaletteCount(declaration); - final byte[] paletteBytes = emitGlyphBankPalettes(declaration); + final byte[] paletteBytes = emitGlyphBankPalettes(declaration, paletteCount); final byte[] payload = new byte[packedPixels.length + paletteBytes.length]; System.arraycopy(packedPixels, 0, payload, 0, packedPixels.length); System.arraycopy(paletteBytes, 0, payload, packedPixels.length, paletteBytes.length); @@ -1155,7 +1153,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe "GLYPH", "NONE", payload, - width * height + GLYPH_BANK_PALETTE_BYTES, + width * height + paletteBytes.length, runtimeMetadata, toolingMetadata, declaration.preloadEnabled()); @@ -1276,8 +1274,8 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe return packed; } - private byte[] emitGlyphBankPalettes(PackerAssetDeclaration declaration) { - final byte[] bytes = new byte[GLYPH_BANK_PALETTE_BYTES]; + private byte[] emitGlyphBankPalettes(PackerAssetDeclaration declaration, int paletteCount) { + final byte[] bytes = new byte[glyphBankPaletteBytes(paletteCount)]; final JsonNode palettesNode = declaration.outputPipelineMetadata().get("palettes"); if (!(palettesNode instanceof com.fasterxml.jackson.databind.node.ArrayNode palettesArray)) { return bytes; @@ -1289,7 +1287,7 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe continue; } final int paletteIndex = indexNode.intValue(); - if (paletteIndex < 0 || paletteIndex >= GLYPH_BANK_MAX_PALETTE_COUNT) { + if (paletteIndex < 0 || paletteIndex >= paletteCount) { continue; } final JsonNode rgbaNode = paletteNode.path("rgba8888"); @@ -1309,6 +1307,14 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe return bytes; } + private int glyphBankPaletteBytes(int paletteCount) { + if (paletteCount < 1 || paletteCount > GLYPH_BANK_MAX_PALETTE_COUNT) { + throw new IllegalStateException("Glyph packing requires palette_count in 1..=" + + GLYPH_BANK_MAX_PALETTE_COUNT + "."); + } + return paletteCount * GLYPH_BANK_COLORS_PER_PALETTE * GLYPH_BANK_RGBA8888_BYTES_PER_COLOR; + } + private int countAuthoredGlyphBankPalettes(PackerAssetDeclaration declaration) { final JsonNode palettesNode = declaration.outputPipelineMetadata().get("palettes"); return palettesNode instanceof ArrayNode palettesArray ? palettesArray.size() : 0; -- 2.47.2 From ffa41db99481b44b729356a0ef1e33bbe400b2a1 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:30:53 +0100 Subject: [PATCH 5/6] implements PLN-0090 --- discussion/index.ndjson | 2 +- ...projections-for-variable-glyph-palettes.md | 27 ++++++++++++++----- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 859764ac..8c3e20a8 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md b/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md index 5e822da9..502ad7d2 100644 --- a/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md +++ b/discussion/workflow/plans/PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md @@ -2,9 +2,9 @@ id: PLN-0090 ticket: variable-tile-bank-palette-serialization title: Studio and Packer Projections for Variable Glyph Palettes -status: open +status: done created: 2026-07-14 -completed: +completed: 2026-07-14 ref_decisions: - DEC-0038 tags: @@ -116,11 +116,24 @@ runtime/packer validation changes count semantics. ## Acceptance Criteria -- [ ] Packer read/details projections expose effective `palette_count`. -- [ ] Studio consumers do not use `palette_authored` as runtime-effective count. -- [ ] `rgba8888` color projection remains unchanged. -- [ ] Scene `palette_id` payload shape is unchanged. -- [ ] Tests cover variable count projection. +- [x] Packer read/details projections expose effective `palette_count`. +- [x] Studio consumers do not use `palette_authored` as runtime-effective count. +- [x] `rgba8888` color projection remains unchanged. +- [x] Scene `palette_id` payload shape is unchanged. +- [x] Tests cover variable count projection. + +## Execution Notes + +- Packer runtime output projection is the `assets.pa` asset table generated by + `FileSystemPackerWorkspaceService`; `PLN-0088` and `PLN-0089` now project the + runtime-effective `palette_count` there. +- `PackerAssetDetailsService` and `PackerReadMessageMapper` project palette + color data through `pipelinePalettes` and do not expose + `palette_authored` as runtime-effective metadata. +- Studio asset details mapping forwards packer details without deriving a + runtime count from `palette_authored`. +- No DTO field was added because doing so would create a new Studio/packer API + surface not required by `DEC-0038`. ## Dependencies -- 2.47.2 From ae1ba0d2d3d9cbeb2220ef8215a953e789496f42 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 14 Jul 2026 16:33:59 +0100 Subject: [PATCH 6/6] implements PLN-0091 --- discussion/index.ndjson | 2 +- ...tte-tests-fixtures-and-final-validation.md | 32 ++++++++---- .../FileSystemPackerWorkspaceServiceTest.java | 51 ++++++++++++++++++- .../PackerAssetDeclarationParserTest.java | 33 ++++++++++++ 4 files changed, 107 insertions(+), 11 deletions(-) diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 8c3e20a8..47e97515 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -18,7 +18,7 @@ {"type":"discussion","id":"DSC-0002","status":"done","ticket":"palette-management-in-studio","title":"Palette Management in Studio","created_at":"2026-03-26","updated_at":"2026-04-23","tags":["studio","legacy-import","palette-management","tile-bank","packer-boundary"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0002-palette-management-in-studio/LSN-0042-schema-driven-palette-authoring-and-local-metadata-events.md","status":"done","created_at":"2026-04-23","updated_at":"2026-04-23"}]} {"type":"discussion","id":"DSC-0003","status":"done","ticket":"packer-docs-import","title":"Import docs/packer into discussion-framework artifacts","created_at":"2026-03-26","updated_at":"2026-03-26","tags":["packer","migration","discussion-framework","docs-import"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0009","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0009-mental-model-packer-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0010-asset-identity-and-runtime-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0011-foundations-workspace-runtime-and-build-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0012-runtime-ownership-and-studio-boundary-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0013-metadata-convergence-and-runtime-sink-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0014-pack-wizard-summary-validation-and-pack-execution-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0015-tile-bank-packing-contract-legacy.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0003-packer-docs-import/LSN-0017-packer-docs-import-pattern.md","status":"done","created_at":"2026-03-26","updated_at":"2026-03-26"}]} {"type":"discussion","id":"DSC-0004","status":"abandoned","ticket":"tilemap-and-metatile-runtime-binary-layout","title":"Tilemap and Metatile Runtime Binary Layout","created_at":"2026-03-26","updated_at":"2026-04-24","tags":["packer","legacy-import","tilemap","metatile","runtime-layout"],"agendas":[{"id":"AGD-0004","file":"AGD-0004-tilemap-and-metatile-runtime-binary-layout.md","status":"abandoned","created_at":"2026-03-26","updated_at":"2026-04-24","_override_reason":"Explicit user request on 2026-04-24 to abandon AGD-0004 because the agenda is no longer valid."}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0005","status":"open","ticket":"variable-tile-bank-palette-serialization","title":"Variable Glyph Bank Palette Serialization","created_at":"2026-03-26","updated_at":"2026-07-14","tags":["packer","legacy-import","glyph-bank","palette-serialization","rgba8888","runtime-alignment"],"agendas":[{"id":"AGD-0005","file":"AGD-0005-variable-tile-bank-palette-serialization.md","status":"accepted","created_at":"2026-03-26","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0038","file":"DEC-0038-variable-glyph-bank-palette-serialization.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0005"}],"plans":[{"id":"PLN-0087","file":"PLN-0087-variable-glyph-palette-spec-propagation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0088","file":"PLN-0088-variable-glyph-palette-metadata-and-count-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0089","file":"PLN-0089-variable-glyph-palette-payload-emission-and-size-accounting.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0090","file":"PLN-0090-studio-and-packer-projections-for-variable-glyph-palettes.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]},{"id":"PLN-0091","file":"PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0038"]}],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"done","ticket":"pbs-game-facing-asset-refs-and-call-result-discard","title":"PBS Game-Facing Asset References and Ignored Call Result Lowering","created_at":"2026-03-27","updated_at":"2026-03-30","tags":["compiler","pbs","ergonomics","lowering","runtime","asset-identity","expression-statements"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"discussion/lessons/DSC-0006-pbs-game-facing-asset-refs-and-call-result-discard/LSN-0024-addressable-surface-host-metadata-and-ignored-value-discipline.md","status":"done","created_at":"2026-03-30","updated_at":"2026-03-30"}]} {"type":"discussion","id":"DSC-0007","status":"done","ticket":"pbs-learn-to-discussion-lessons-migration","title":"Migrate PBS Learn Documents into Discussion Lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","migration","discussion-framework","lessons","learn-prune"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0018","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0018-pbs-ast-and-parser-contract-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0019","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0019-pbs-name-resolution-and-linking-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0020","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0020-pbs-runtime-values-identity-memory-boundaries-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0021","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0021-pbs-diagnostics-and-conformance-governance-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0022","file":"discussion/lessons/DSC-0007-pbs-learn-to-discussion-lessons-migration/LSN-0022-pbs-globals-lifecycle-and-published-entrypoint-legacy.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"pbs-low-level-asset-manager-surface","title":"PBS Low-Level Asset Manager Surface for Runtime AssetManager","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["compiler","pbs","runtime","asset-manager","host-abi","stdlib","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0023","file":"discussion/lessons/DSC-0008-pbs-low-level-asset-manager-surface/LSN-0023-lowassets-runtime-aligned-sdk-surface.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} diff --git a/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md b/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md index 6e2ce675..222c681c 100644 --- a/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md +++ b/discussion/workflow/plans/PLN-0091-variable-glyph-palette-tests-fixtures-and-final-validation.md @@ -2,9 +2,9 @@ id: PLN-0091 ticket: variable-tile-bank-palette-serialization title: Variable Glyph Palette Tests, Fixtures, and Final Validation -status: open +status: done created: 2026-07-14 -completed: +completed: 2026-07-14 ref_decisions: - DEC-0038 tags: @@ -134,13 +134,27 @@ max-bound, or a bug. ## Acceptance Criteria -- [ ] Tests cover `palette_count = 1`, an intermediate count, and `64`. -- [ ] Tests cover variable `size` and `decoded_size`. -- [ ] Tests cover emitted palette byte length and RGBA order. -- [ ] Tests cover metadata/payload mismatch rejection or producer validation. -- [ ] Fixtures no longer rely on fixed 64-palette padding unless count is `64`. -- [ ] Validation commands pass. -- [ ] Residue scan results are clean or explicitly classified. +- [x] Tests cover `palette_count = 1`, an intermediate count, and `64`. +- [x] Tests cover variable `size` and `decoded_size`. +- [x] Tests cover emitted palette byte length and RGBA order. +- [x] Tests cover metadata/payload mismatch rejection or producer validation. +- [x] Fixtures no longer rely on fixed 64-palette padding unless count is `64`. +- [x] Validation commands pass. +- [x] Residue scan results are clean or explicitly classified. + +## Execution Notes + +- Added packer workspace coverage for `palette_count = 1` and intermediate + `palette_count = 7`. +- Existing fixture and build paths continue to cover `palette_count = 64` where + a max-count payload is intended. +- Added parser coverage rejecting palette declaration index `64`, preserving + the v1 maximum effective count of `64` through direct ids `0..63`. +- `:prometeu-packer:prometeu-packer-v1:test` passed. +- `./gradlew build` passed. +- Residue scan found only intentional normative statements rejecting + `convertedRgb565`, `GLYPH/indexed_v2`, fixed-padding compatibility, and + sparse-to-dense remapping. ## Dependencies diff --git a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java index a4fa3254..57c287e1 100644 --- a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java +++ b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/FileSystemPackerWorkspaceServiceTest.java @@ -338,8 +338,10 @@ final class FileSystemPackerWorkspaceServiceTest { assertEquals(16, assetTable.get(0).path("metadata").path("tile_size").asInt()); assertEquals(256, assetTable.get(0).path("metadata").path("width").asInt()); assertEquals(256, assetTable.get(0).path("metadata").path("height").asInt()); - assertEquals(64, assetTable.get(0).path("metadata").path("palette_count").asInt()); + assertEquals(1, assetTable.get(0).path("metadata").path("palette_count").asInt()); assertEquals(1, assetTable.get(0).path("metadata").path("palette_authored").asInt()); + assertEquals(32768 + 64, assetTable.get(0).path("size").asInt()); + assertEquals(65536 + 64, assetTable.get(0).path("decoded_size").asInt()); assertTrue(assetTable.get(0).path("metadata").path("pipeline").isMissingNode()); final var preload = MAPPER.readTree(projectRoot.resolve("build/preload.json").toFile()); @@ -354,6 +356,53 @@ final class FileSystemPackerWorkspaceServiceTest { assertEquals(0, assetTableMetadata.get(0).path("metadata").path("pipeline").path("palettes").get(0).path("index").asInt()); } + @Test + void packWorkspaceEmitsIntermediateGlyphPaletteCountWithoutRemappingPaletteIdentity() throws Exception { + final Path projectRoot = copyFixture("workspaces/managed-basic", tempDir.resolve("pack-workspace-palette-count-7")); + final Path assetRoot = projectRoot.resolve("assets/ui/atlas"); + final Path manifestPath = assetRoot.resolve("asset.json"); + writeTilePng(assetRoot.resolve("confirm.png"), 16); + + final ObjectNode manifest = (ObjectNode) MAPPER.readTree(manifestPath.toFile()); + final ObjectNode output = (ObjectNode) manifest.path("output"); + output.putObject("metadata").put("tile_size", "16x16"); + final ObjectNode pipeline = output.putObject("pipeline"); + final var palettes = pipeline.putArray("palettes"); + final ObjectNode palette = palettes.addObject(); + palette.put("index", 6); + palette.putObject("palette") + .putArray("rgba8888").add(0xFF0000FF); + final var artifacts = manifest.putArray("artifacts"); + artifacts.addObject().put("file", "confirm.png").put("index", 0); + MAPPER.writerWithDefaultPrettyPrinter().writeValue(manifestPath.toFile(), manifest); + + final FileSystemPackerWorkspaceService service = service(); + final var result = service.packWorkspace(new PackWorkspaceRequest(project(projectRoot))); + + assertEquals(PackerOperationStatus.SUCCESS, result.status()); + final byte[] assetsPa = Files.readAllBytes(projectRoot.resolve("build/assets.pa")); + final var assetTable = MAPPER.readTree(projectRoot.resolve("build/asset_table.json").toFile()); + assertEquals(7, assetTable.get(0).path("metadata").path("palette_count").asInt()); + assertEquals(1, assetTable.get(0).path("metadata").path("palette_authored").asInt()); + assertEquals(32768 + (7 * 16 * 4), assetTable.get(0).path("size").asInt()); + assertEquals(65536 + (7 * 16 * 4), assetTable.get(0).path("decoded_size").asInt()); + + final int payloadOffset = (int) readLeLong(assetsPa, 12); + final int assetOffset = assetTable.get(0).path("offset").asInt(); + final int packedPixelBytes = (assetTable.get(0).path("metadata").path("width").asInt() + * assetTable.get(0).path("metadata").path("height").asInt()) / 2; + final int paletteStart = payloadOffset + assetOffset + packedPixelBytes; + final int paletteSixStart = paletteStart + (6 * 16 * 4); + assertEquals(0x00, assetsPa[paletteStart] & 0xFF); + assertEquals(0x00, assetsPa[paletteStart + 1] & 0xFF); + assertEquals(0x00, assetsPa[paletteStart + 2] & 0xFF); + assertEquals(0x00, assetsPa[paletteStart + 3] & 0xFF); + assertEquals(0xFF, assetsPa[paletteSixStart] & 0xFF); + assertEquals(0x00, assetsPa[paletteSixStart + 1] & 0xFF); + assertEquals(0x00, assetsPa[paletteSixStart + 2] & 0xFF); + assertEquals(0xFF, assetsPa[paletteSixStart + 3] & 0xFF); + } + @Test void packWorkspaceRemapsGlyphTileIndicesUsingGlyphMaterialSchema() throws Exception { final Path projectRoot = copyFixture("workspaces/managed-basic", tempDir.resolve("pack-workspace-remap-material")); diff --git a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java index 29654ec9..12287161 100644 --- a/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java +++ b/prometeu-packer/prometeu-packer-v1/src/test/java/p/packer/services/PackerAssetDeclarationParserTest.java @@ -215,6 +215,39 @@ final class PackerAssetDeclarationParserTest { assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("duplicate palette index 0"))); } + @Test + void rejectsPaletteDeclarationIndexAboveV1Maximum() throws Exception { + final Path manifest = tempDir.resolve("asset.json"); + Files.writeString(manifest, """ + { + "schema_version": 1, + "asset_uuid": "uuid-palette-too-high", + "name": "palette_asset", + "type": "glyph_bank", + "output": { + "format": "GLYPH/indexed_v1", + "codec": "NONE", + "pipeline": { + "palettes": [ + { + "index": 64, + "palette": { + "rgba8888": [-16776961] + } + } + ] + } + }, + "preload": { "enabled": true } + } + """); + + final var result = parser.parse(manifest); + + assertFalse(result.valid()); + assertTrue(result.diagnostics().stream().anyMatch(diagnostic -> diagnostic.message().contains("maximum supported index is 63"))); + } + @Test void rejectsMalformedJsonWithStructuralDiagnostic() { final var result = parser.parse(PackerFixtureLocator.fixtureRoot("workspaces/invalid-malformed/assets/bad/asset.json")); -- 2.47.2