prometeu-runtime/discussion/workflow/agendas/AGD-0029-scene-bank-glyph-runtime-binding-leak.md

11 KiB

id ticket title status created resolved decision tags
AGD-0029 scene-bank-glyph-runtime-binding-leak Scene Bank vazando glyph bank id runtime para o formato binario accepted 2026-04-24 2026-04-24 DEC-0021
gfx
runtime
asset
scene
glyph
format
architecture

Contexto

Hoje o payload binario SCENE carrega glyph_bank_id por layer e o runtime usa esse valor como chave operacional para resolver o GlyphBank residente durante o render.

A cadeia atual eh:

  • o decoder de SCENE le glyph_bank_id do payload;
  • SceneLayer preserva esse campo no modelo canonico carregado;
  • SceneViewportCache copia o mesmo id para a cache;
  • o renderer consulta GlyphBankPoolAccess por esse slot/id para desenhar a layer.

Isso cria um acoplamento direto entre formato frio de asset e topologia de residencia runtime. A suspeita levantada eh que esse campo nao deveria existir no wire-format, porque a referencia correta ao glyph bank deveria ser resolvida apenas pelo runtime.

Problema

O contrato atual mistura duas camadas que deveriam permanecer separadas:

  • o asset SCENE como descricao fria de composicao;
  • o binding de slot/banco residente como estado operacional do runtime.

Se glyph_bank_id realmente for um detalhe exclusivamente runtime, o formato binario atual esta errado e o runtime passou a depender de um identificador que nao deveria ser serializado nem publicado como parte do asset.

Isso deixa perguntas abertas sobre:

  • como uma layer de cena passa a apontar para um glyph source sem carregar um slot runtime no payload;
  • onde esse binding deve viver;
  • como preload, install e bind de cena passam a cooperar sem reintroduzir ambiguidade.

Pontos Criticos

  • O renderer atual resolve a bank diretamente a partir de layer_cache.glyph_bank_id, entao qualquer correcao toca formato, modelo em memoria e caminho de render.
  • O payload SCENE ja foi materializado em testes e tooling com esse byte no header da layer, entao a mudanca implica migracao/versionamento ou ruptura controlada.
  • O contrato de asset management enfatiza slots como conceito runtime e resolve contexto de banco via asset_table e preload, o que conflita com SCENE carregar referencia operacional propria.
  • Precisamos evitar uma "correcao" que apenas mova o mesmo acoplamento para outro nome sem restaurar a fronteira correta entre asset frio e binding runtime.

Opcoes

Opcao 1 - Manter glyph_bank_id dentro do formato SCENE

  • Abordagem: aceitar explicitamente que cada layer da cena referencia um slot/runtime glyph bank no proprio payload e documentar isso como contrato oficial.
  • Pros: menor mudanca imediata; preserva compatibilidade com decoder, tests e tooling atuais.
  • Contras: cristaliza o vazamento arquitetural; faz o asset depender de topologia runtime; dificulta relocacao, preload flexivel e reuso de cena em contextos diferentes.
  • Trade-off: simples agora, mais rigido e mais fragil como contrato de longo prazo.

Opcao 2 - Remover o id do wire-format e resolver o binding por runtime ao ativar a cena

  • Abordagem: o payload SCENE deixa de carregar slot/id de glyph bank; a associacao layer -> fonte grafica passa a ser injetada por metadados de runtime, por preload derivado, ou por um binding explicito durante bind_scene.
  • Pros: restaura a separacao asset frio vs residencia runtime; permite relocacao de slots e politica de preload sem contaminar o formato.
  • Contras: exige definir uma nova fonte de verdade para o binding; impacta decoder, modelo de cena, renderer, specs e ferramentas.
  • Trade-off: maior custo de migracao, mas fronteira arquitetural mais coerente.

Opcao 3 - Manter referencia serializada, mas trocar de slot runtime para identidade fria

  • Abordagem: o payload SCENE deixa de carregar glyph_bank_id runtime e passa a carregar uma referencia fria estavel por layer, como asset_id ou handle logico de glyph source; o runtime resolve essa identidade para slot residente quando a cena eh ativada.
  • Pros: preserva auto-descricao da cena sem serializar topologia de residencia; reduz dependencia de slot fixo.
  • Contras: ainda precisamos decidir se a cena deve conhecer assets frios diretamente; adiciona etapa de resolucao e falha operacional nova.
  • Trade-off: melhor que serializar slot runtime, mas ainda pode acoplar demais o asset SCENE ao catalogo de assets.

Sugestao / Recomendacao

Direcao escolhida nesta agenda:

  • seguir pela Opcao 3 com identidade fria por asset_id;
  • remover glyph_bank_id runtime do formato binario SCENE;
  • fazer o SCENE carregar, por layer, o asset_id do glyph dependency;
  • resolver asset_id -> glyph slot no momento de bind_scene;
  • falhar operacionalmente se qualquer dependencia grafica da cena nao estiver comprometida em algum slot glyph;
  • a ordem de carregamento dos assets nos bancos nao importa;
  • sem versionamento e sem compatibilidade retroativa por enquanto.

Motivo:

  • slot de glyph bank eh conceito runtime e nao deve viver no wire-format;
  • asset_id eh identidade fria e estavel dentro do contrato de assets;
  • bind-time resolution preserva a liberdade de preload/commit e evita acoplamento do asset SCENE a uma topologia fixa de slots;
  • a falha operacional em bind_scene mantem o problema na fronteira correta de ativacao.

Cravado nesta agenda:

  • SceneBank canonico nao deve carregar slot runtime de glyph;
  • o payload SCENE deve declarar dependencias frias, nao residencia;
  • a vinculacao layer -> glyph slot pertence ao runtime no momento de ativacao da cena;
  • o runtime deve validar dependencias no bind_scene, mas nao deve persistir um snapshot resolvido como dado canonico da cena;
  • no draw de cada layer, o runtime pode consultar novamente qual slot contem o asset_id referido pela cena;
  • ausencia da dependencia em qualquer ponto relevante do fluxo deve produzir erro operacional.
  • a resolucao asset_id -> slot fica interna nesta etapa;
  • a resolucao interna deve ser suportada por indice reverso asset_id -> slot, nao depender apenas de scan linear dos slots;
  • o payload SCENE deve aumentar a largura do campo para comportar AssetId = i32;
  • cada layer publica sua propria dependencia glyph diretamente;
  • falha de dependencia no caminho de draw/composition deve ser tratada como erro fatal da maquina, com log claro.
  • falha de dependencia no bind_scene tambem deve ser tratada como erro fatal da maquina, com log claro.

Perguntas em Aberto

Criterio para Encerrar

Esta agenda pode ser encerrada quando houver resposta clara e defendivel para:

  • como o SCENE publica dependencias por asset_id;
  • como o runtime consulta asset_id -> slot durante bind e draw;
  • qual representacao binaria carregara o asset_id por layer;
  • como o contrato de erro fatal e log claro se aplica em bind e draw.

Discussao

Estado inicial da investigacao:

  • ha vazamento real hoje no codigo e no tooling;
  • nao encontrei decisao normativa registrada que feche explicitamente esse acoplamento;
  • portanto o tema continua aberto e precisa de decisao arquitetural antes de qualquer correcao de spec ou codigo.

Atualizacao de 2026-04-24:

O caminho proposto pelo usuario parece tecnicamente viavel com a infraestrutura atual, embora ainda nao exista como contrato explicito.

O que ja existe hoje:

  • o AssetManager mantem deduplicacao/residencia por asset_id;
  • no commit/preload, cada slot fisico passa a registrar qual asset_id esta instalado nele;
  • portanto o runtime ja possui as duas metades da informacao:
    • asset_id -> resident object;
    • slot -> asset_id.

O que ainda nao existe:

  • uma API canonica asset_id -> slot para lookup de um asset ja comprometido em um banco;
  • uma forma de SceneBank carregar dependencias por asset_id em vez de glyph_bank_id;
  • um bind_scene capaz de validar todas as dependencias da cena e falhar operacionalmente se alguma nao estiver residente em slot algum.

Leitura atual da proposta:

  • o payload SCENE carrega, por layer, o asset_id do glyph dependency;
  • composer.bind_scene(scene_slot) continua selecionando a cena residente;
  • durante o bind, o runtime resolve cada asset_id dependente para o slot glyph atualmente comprometido;
  • durante o draw de cada layer, o runtime pode consultar novamente em qual slot o asset_id esta residente;
  • a ordem de carregamento deixa de importar porque a resolucao eh feita contra o estado runtime no momento da operacao;
  • se qualquer dependencia nao estiver carregada em algum slot glyph, bind_scene retorna falha operacional e nao ativa a cena.

Essa direcao preserva a fronteira correta melhor do que o modelo atual:

  • o SCENE deixa de carregar topologia runtime;
  • a cena continua auto-descritiva o suficiente para declarar suas dependencias frias;
  • o runtime continua dono da residencia e da escolha de slot efetivo.

Ponto de atencao:

  • essa direcao prefere nao manter snapshot resolvido como dado persistido da cena;
  • portanto o contrato precisa dizer com clareza como o sistema reage se uma dependencia desaparecer entre bind e draw.

Direcao aceita na discussao atual:

  • seguir com dependencia fria por asset_id no SCENE;
  • resolver para slot glyph somente no bind_scene;
  • permitir nova consulta asset_id -> slot tambem no draw das layers;
  • nao expor lookup como API publica nesta etapa;
  • manter indice reverso interno asset_id -> slot desde ja, para evitar acoplamento da solucao a scan linear de poucos slots;
  • aumentar a largura do payload para carregar AssetId = i32 no SCENE;
  • tratar dependencia ausente no bind_scene como falha fatal da maquina, com log claro;
  • tratar dependencia ausente no draw/composition como falha fatal da maquina, com log claro;
  • nao fazer versionamento nem camada de compatibilidade nesta etapa.

Resposta consolidada do usuario na discussao:

  • nao devemos materializar esse binding como dado resolvido persistente;
  • devemos checar no bind e tambem quando formos desenhar a layer;
  • a resolucao asset_id -> slot pode e deve evoluir para API publica futuramente, mas fica interna por enquanto;
  • como essa resolucao tende a virar API publica, a base interna deve nascer como indice reverso e nao como mero loop sobre 16 slots;
  • como AssetId canonico eh i32, o payload precisa aumentar a largura do campo serializado;
  • cada layer carrega sua propria dependencia glyph;
  • se a dependencia faltar ou nao puder ser resolvida no bind_scene, isso deve quebrar a maquina com log claro;
  • se a dependencia sumir ou nao puder ser resolvida no caminho de draw/composition, isso tambem deve quebrar a maquina com log claro, porque nao ha como prosseguir corretamente sem as dependencias da cena.

Resolution

Encerrada em 2026-04-24.

Resolucao aceita:

  • SCENE deixa de carregar slot runtime de glyph e passa a carregar AssetId por layer;
  • o runtime resolve asset_id -> slot via indice reverso interno;
  • falta de dependencia fataliza a maquina tanto no bind_scene quanto no draw/composition, com log claro;
  • nao ha versionamento nem compatibilidade retroativa nesta etapa.