prometeu-runtime/discussion/workflow/agendas/AGD-0049-runtime-owned-variable-glyph-bank-palette-protocol.md

221 lines
9.8 KiB
Markdown

---
id: AGD-0049
ticket: runtime-owned-variable-glyph-bank-palette-protocol
title: Runtime-Owned Variable Glyph Bank Palette Protocol
status: accepted
created: 2026-07-14
resolved: 2026-07-14
decision:
tags:
- runtime
- gfx
- assets
- glyph-bank
- palette-serialization
- protocol
---
## Contexto
A agenda `../studio/discussion/workflow/agendas/AGD-0005-variable-tile-bank-palette-serialization.md`
levantou o desperdicio do payload atual de `GLYPH/indexed_v1`: todo glyph bank
carrega `64 * 16 * 4 = 4096` bytes de paletas RGBA8888, mesmo quando o asset
usa poucas paletas.
Esse problema toca o `packer`, mas a decisao do protocolo pertence ao
`runtime`. A especificacao final deve ser definida aqui, no contrato runtime,
e o `packer` deve seguir a spec quando ela estiver pronta. A agenda de `studio`
serve como entrada factual e motivacao, nao como autoridade normativa sobre o
payload, a memoria residente ou a semantica de `palette_id`.
Estado atual no runtime:
- `docs/specs/runtime/15-asset-management.md` documenta `palette_count = 64`;
- `docs/specs/runtime/04-gfx-peripheral.md` documenta `palette_id` em `0..63`;
- `crates/console/prometeu-hal/src/glyph_bank.rs` materializa paletas como
`[[Color; 16]; 64]`;
- `crates/console/prometeu-drivers/src/asset.rs` rejeita metadata cujo
`palette_count` nao seja `64`;
- o decode de glyph bank le um bloco fixo de `64 * 16 * 4` bytes em
`assets.pa`;
- testes de asset e VM ainda calculam payload e decoded size com o bloco fixo.
Decisoes anteriores relevantes:
- `DSC-0022` estabeleceu `GlyphBank` como nome canonico do artefato grafico;
- `DSC-0037` estabeleceu RGBA8888 como contrato runtime, com alpha como dado de
cor e sem indice magico reservado.
## Problema
O runtime precisa decidir se `GLYPH/indexed_v1` continua sendo um contrato de
64 paletas fixas ou se passa a aceitar uma quantidade variavel de paletas
serializadas.
Essa decisao nao e apenas uma otimizacao de tamanho de cartucho. Ela muda:
- o significado de `palette_count`;
- a validacao de `palette_id`;
- a formula de `size` e `decoded_size`;
- a representacao residente de `GlyphBank`;
- o comportamento quando uma cena referencia uma paleta nao carregada;
- a fronteira entre contrato de asset, HAL, composer, testes e tooling.
## Pontos Criticos
- Autoridade: o runtime decide o protocolo publicado; o `packer` segue.
- Compatibilidade: o projeto ainda esta em v1, entao nao ha obrigacao
presumida de preservar o padding fixo antigo.
- Identidade: `palette_id` pode continuar sendo uma identidade direta ou pode
virar indice em uma tabela compactada, mas nao pode ter dois significados.
- Materializacao: economizar bytes no payload nao implica automaticamente
economizar memoria residente, mas manter uma tabela fixa pode preservar
semantica simples para renderizacao e cenas.
- Falhas: se `palette_id` apontar para uma paleta ausente, o runtime precisa
definir se isso falha no load, na composicao, ou se resolve para cor default.
- Propagacao: qualquer decisao precisa mover specs, decode, HAL, fixtures e
testes juntos, como ocorreu na migracao RGBA8888.
## Opcoes
### Opcao A - Manter 64 paletas fixas no protocolo runtime
- **Abordagem:** Preservar `palette_count = 64`, bloco fixo de 4096 bytes e
tabela residente fixa.
- **Pro:** Mantem decode, composicao e limites de `palette_id` simples.
- **Contra:** O runtime continua publicando um custo obrigatorio de payload que
nao representa a maioria dos assets.
- **Manutencao:** Boa para estabilidade local, fraca para alinhamento entre
metadata autoral e payload real.
### Opcao B - Payload variavel, memoria residente fixa de 64 slots
- **Abordagem:** Fazer `palette_count` representar o numero de paletas
serializadas, mas expandir para uma tabela residente fixa de 64 paletas no
load. Paletas nao serializadas ficam em valor default, e `palette_id` continua
sendo identidade direta `0..63`.
- **Pro:** Reduz payload mantendo o contrato de composicao e cena simples.
- **Contra:** Requer decidir se referencias a paletas nao serializadas sao
invalidas no load, invalidas na composicao ou simplesmente resolvem para a
paleta default.
- **Manutencao:** Boa se a spec declarar que `palette_count` mede somente o
prefixo serializado e que o runtime ainda materializa capacidade fixa.
### Opcao C - Payload variavel e memoria residente variavel
- **Abordagem:** Fazer `palette_count` controlar tanto o payload quanto a
quantidade residente de paletas. `palette_id >= palette_count` passa a ser
invalido para aquele glyph bank.
- **Pro:** O contrato fica mais fiel ao asset carregado e reduz memoria
residente por banco.
- **Contra:** A composicao precisa carregar limite por banco e transformar
validacao de `palette_id` em regra dependente do asset.
- **Manutencao:** Forte se o runtime quiser que o banco carregado seja a unica
fonte de verdade; mais invasiva no HAL/composer.
### Opcao D - Paletas compactadas com remapeamento de identidade
- **Abordagem:** Serializar somente paletas usadas em uma tabela densa e
introduzir um mapa entre identidade autoral/esparsa e indice residente.
- **Pro:** Pode minimizar payload mesmo quando indices autorais sao esparsos.
- **Contra:** Introduz um segundo contrato de identidade e exige metadata extra
ou reescrita de cenas/assets dependentes.
- **Manutencao:** Fraca para v1 unless haja uma necessidade clara de preservar
indices esparsos sem preencher lacunas.
## Sugestao / Recomendacao
Adotar a **Opcao C**.
`palette_count` deve ser o contrato real do glyph bank carregado: se o payload
serializa `N` paletas, o runtime materializa `N` paletas e `palette_id >= N`
e invalido para aquele banco.
A **Opcao B** fica descartada porque manter memoria residente fixa preservaria
uma segunda nocao de capacidade que nao corresponde ao asset carregado. A
**Opcao D** tambem fica descartada porque introduzir remapeamento de identidade
transformaria um protocolo simples em uma camada adicional de metadata.
## Perguntas em Aberto
- [x] `palette_count` deve definir tambem a quantidade residente de paletas, ou
apenas o prefixo serializado no payload?
- Resolucao: define tambem a quantidade residente.
- [x] `palette_id` deve ser validado contra `palette_count` por glyph bank ou
continuar limitado globalmente a `0..63`?
- Resolucao: validar contra `palette_count` por glyph bank, mantendo um
limite maximo global separado.
- [x] Quando uma cena referencia uma paleta ausente, o erro deve ocorrer no
load do glyph bank, no load/decode da scene, ou na composicao?
- Resolucao: o glyph bank carrega se o proprio payload e valido. A referencia
ausente falha quando uma scene/sprite tenta usar `palette_id >=
palette_count` contra o banco real; o runtime deve tratar isso como erro
explicito, nao como fallback silencioso para transparente/default.
- [x] O limite maximo de paletas por glyph bank continua sendo `64` em v1?
- Resolucao: sim. A variabilidade deve reduzir `N`, nao abrir uma
quantidade ilimitada de paletas em v1.
- [x] `decoded_size` deve contar apenas paletas materializadas ou manter alguma
nocao de capacidade residente?
- Resolucao: contar apenas paletas materializadas:
`width * height + palette_count * 16 * 4`.
- [x] A mudanca deve manter o nome `GLYPH/indexed_v1` como correcao
incompativel de v1, ou o runtime exige uma nova versao de payload?
- Resolucao: manter `GLYPH/indexed_v1` como correcao incompativel, sem
compatibilidade com o padding fixo antigo.
## Criterio para Encerrar
A agenda pode virar decisao quando o runtime escolher:
- o significado normativo de `palette_count`;
- a relacao entre payload serializado e memoria residente;
- a regra de validade de `palette_id`;
- o ponto de falha para paletas referenciadas mas ausentes;
- a estrategia de versao para `GLYPH/indexed_v1`;
- a lista de specs, crates e testes que precisam ser propagados no plano.
## Discussion
Entrada do usuario em 2026-07-14: o runtime deve decidir o protocolo com base
no que for melhor para o runtime; o `packer` deve seguir a spec quando pronta.
Entrada do usuario em 2026-07-14: preferencia pela Opcao C, se possivel.
Analise atual: a Opcao C e viavel, mas transforma `palette_id` em validacao
dependente do glyph bank carregado. O codigo atual ja centraliza parte desse
risco em `GlyphBank::resolve_color`, que hoje retorna transparente quando a
paleta nao existe. Para a Opcao C virar contrato robusto, a decisao nao deve
depender de fallback silencioso: precisa escolher um ponto explicito de falha
para `palette_id >= palette_count`.
Entrada do usuario em 2026-07-14: aceitar a recomendacao e seguir com a Opcao
C.
## Resolution
Fechar a agenda em favor da **Opcao C - Payload variavel e memoria residente
variavel**.
Contrato a levar para decisao:
- o runtime e a autoridade do protocolo `GLYPH/indexed_v1`;
- o `packer` deve seguir a spec runtime quando ela estiver publicada;
- `palette_count` significa o numero de paletas RGBA8888 serializadas e
materializadas no glyph bank carregado;
- `palette_count` deve estar no intervalo `1..=64`;
- cada paleta continua tendo 16 cores RGBA8888;
- `palette_id` e uma identidade direta dentro do glyph bank carregado, valida
somente quando `palette_id < palette_count`;
- o runtime nao deve remapear paletas esparsas para outra identidade;
- `decoded_size` deve contar apenas as paletas materializadas:
`width * height + palette_count * 16 * 4`;
- a mudanca permanece em `GLYPH/indexed_v1` como correcao incompativel de v1;
- payloads antigos com padding fixo e `palette_count = 64` so continuam
validos se tambem satisfizerem o novo contrato por coincidencia, nao por uma
regra de compatibilidade separada;
- referencias a paletas ausentes devem falhar explicitamente quando
scene/sprite/composer tentarem usar `palette_id >= palette_count` contra o
banco real;
- o plano posterior deve propagar specs, `GlyphBank`, decode de assets,
validacao de scene/sprite/composer, fixtures e testes.