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

9.8 KiB

id ticket title status created resolved decision tags
AGD-0049 runtime-owned-variable-glyph-bank-palette-protocol Runtime-Owned Variable Glyph Bank Palette Protocol accepted 2026-07-14 2026-07-14
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

  • palette_count deve definir tambem a quantidade residente de paletas, ou apenas o prefixo serializado no payload?
    • Resolucao: define tambem a quantidade residente.
  • 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.
  • 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.
  • 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.
  • 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.
  • 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.