dev/studio-packer-rgba8888-asset-pipeline #11

Merged
bquarkz merged 10 commits from dev/studio-packer-rgba8888-asset-pipeline into master 2026-05-24 21:46:24 +00:00
5 changed files with 33 additions and 35 deletions
Showing only changes of commit cfb842c56f - Show all commits

View File

@ -1,5 +1,5 @@
{"type":"meta","next_id":{"DSC":39,"AGD":42,"DEC":38,"PLN":87,"LSN":53,"CLSN":1}} {"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":"review","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":"review","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":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]}],"lessons":[]} {"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":"review","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":"review","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0037"]}],"lessons":[]}
{"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-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-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"}]} {"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"}]}

View File

@ -2,9 +2,9 @@
id: PLN-0084 id: PLN-0084
ticket: studio-packer-rgba8888-asset-pipeline ticket: studio-packer-rgba8888-asset-pipeline
title: RGBA8888 Packer Projections and Workspace APIs title: RGBA8888 Packer Projections and Workspace APIs
status: review status: done
created: 2026-05-23 created: 2026-05-23
completed: completed: 2026-05-23
ref_decisions: ref_decisions:
- DEC-0037 - DEC-0037
tags: tags:
@ -123,11 +123,11 @@ reusable.
## Acceptance Criteria ## Acceptance Criteria
- [ ] `asset.json` palette metadata uses `rgba8888`. - [x] `asset.json` palette metadata uses `rgba8888`.
- [ ] Details/read projections expose `rgba8888`. - [x] Details/read projections expose `rgba8888`.
- [ ] Workspace write operations persist `rgba8888`. - [x] Workspace write operations persist `rgba8888`.
- [ ] Stale RGB565-derived cache metadata is not reused as canonical. - [x] Stale RGB565-derived cache metadata is not reused as canonical.
- [ ] No normal API requires `convertedRgb565`. - [x] No normal API requires `convertedRgb565`.
## Dependencies ## Dependencies

View File

@ -1775,18 +1775,15 @@ public final class FileSystemPackerWorkspaceService implements PackerWorkspaceSe
final ArrayNode palettesNode = pipelineNode.putArray("palettes"); final ArrayNode palettesNode = pipelineNode.putArray("palettes");
for (int paletteOrder = 0; paletteOrder < request.selectedPalettes().size(); paletteOrder += 1) { for (int paletteOrder = 0; paletteOrder < request.selectedPalettes().size(); paletteOrder += 1) {
final Map<String, Object> palette = request.selectedPalettes().get(paletteOrder); final Map<String, Object> palette = request.selectedPalettes().get(paletteOrder);
final List<Integer> originalArgb8888 = integerList(palette.get("originalArgb8888")); final List<Integer> rgba8888 = integerList(palette.get("rgba8888"));
final List<Integer> convertedRgb565 = integerList(palette.get("convertedRgb565")); if (rgba8888.isEmpty()) {
if (originalArgb8888.isEmpty() || convertedRgb565.isEmpty()) { throw new IllegalArgumentException("Each selected palette must contain rgba8888 entries.");
throw new IllegalArgumentException("Each selected palette must contain originalArgb8888 and convertedRgb565 entries.");
} }
final ObjectNode paletteNode = palettesNode.addObject(); final ObjectNode paletteNode = palettesNode.addObject();
paletteNode.put("index", paletteIndex(palette, paletteOrder)); paletteNode.put("index", paletteIndex(palette, paletteOrder));
final ObjectNode payloadNode = paletteNode.putObject("palette"); final ObjectNode payloadNode = paletteNode.putObject("palette");
final ArrayNode originalNode = payloadNode.putArray("originalArgb8888"); final ArrayNode rgbaNode = payloadNode.putArray("rgba8888");
originalArgb8888.forEach(originalNode::add); rgba8888.forEach(rgbaNode::add);
final ArrayNode convertedNode = payloadNode.putArray("convertedRgb565");
convertedRgb565.forEach(convertedNode::add);
} }
if (palettesNode.isEmpty()) { if (palettesNode.isEmpty()) {
throw new IllegalArgumentException("At least one palette must be selected."); throw new IllegalArgumentException("At least one palette must be selected.");

View File

@ -336,17 +336,27 @@ public final class PackerAssetDeclarationParser {
continue; continue;
} }
final JsonNode originalNode = paletteNode.path("originalArgb8888"); final JsonNode rgbaNode = paletteNode.path("rgba8888");
final JsonNode convertedNode = paletteNode.path("convertedRgb565"); if (!rgbaNode.isArray()) {
if (!originalNode.isArray() || !convertedNode.isArray()) {
diagnostics.add(new PackerDiagnostic( diagnostics.add(new PackerDiagnostic(
PackerDiagnosticSeverity.ERROR, PackerDiagnosticSeverity.ERROR,
PackerDiagnosticCategory.STRUCTURAL, PackerDiagnosticCategory.STRUCTURAL,
"Each palette payload must contain array fields 'originalArgb8888' and 'convertedRgb565'.", "Each palette payload must contain array field 'rgba8888'.",
manifestPath, manifestPath,
true)); true));
continue; continue;
} }
for (JsonNode colorNode : rgbaNode) {
if (!colorNode.canConvertToInt()) {
diagnostics.add(new PackerDiagnostic(
PackerDiagnosticSeverity.ERROR,
PackerDiagnosticCategory.STRUCTURAL,
"Palette field 'rgba8888' must contain integer color values.",
manifestPath,
true));
break;
}
}
} }
if (paletteCount > MAX_PIPELINE_PALETTES) { if (paletteCount > MAX_PIPELINE_PALETTES) {

View File

@ -190,29 +190,20 @@ public final class PackerAssetDetailsService {
if (!indexNode.isInt() || indexNode.intValue() < 0 || !(payloadNode instanceof ObjectNode payloadObject)) { if (!indexNode.isInt() || indexNode.intValue() < 0 || !(payloadNode instanceof ObjectNode payloadObject)) {
return Map.of(); return Map.of();
} }
final JsonNode originalNode = payloadObject.path("originalArgb8888"); final JsonNode rgbaNode = payloadObject.path("rgba8888");
final JsonNode convertedNode = payloadObject.path("convertedRgb565"); if (!rgbaNode.isArray()) {
if (!originalNode.isArray() || !convertedNode.isArray()) {
return Map.of(); return Map.of();
} }
final List<Integer> originalArgb8888 = new ArrayList<>(); final List<Integer> rgba8888 = new ArrayList<>();
for (JsonNode colorNode : originalNode) { for (JsonNode colorNode : rgbaNode) {
if (!colorNode.canConvertToInt()) { if (!colorNode.canConvertToInt()) {
return Map.of(); return Map.of();
} }
originalArgb8888.add(colorNode.intValue()); rgba8888.add(colorNode.intValue());
}
final List<Integer> convertedRgb565 = new ArrayList<>();
for (JsonNode colorNode : convertedNode) {
if (!colorNode.canConvertToInt()) {
return Map.of();
}
convertedRgb565.add(colorNode.intValue());
} }
return Map.of( return Map.of(
"index", indexNode.intValue(), "index", indexNode.intValue(),
"originalArgb8888", List.copyOf(originalArgb8888), "rgba8888", List.copyOf(rgba8888));
"convertedRgb565", List.copyOf(convertedRgb565));
} }
private Optional<PackerBankCompositionFile> resolveSelectedBankFile( private Optional<PackerBankCompositionFile> resolveSelectedBankFile(