--- id: AGD-0029 ticket: scene-bank-glyph-runtime-binding-leak title: Scene Bank vazando glyph bank id runtime para o formato binario status: accepted created: 2026-04-24 resolved: 2026-04-24 decision: DEC-0021 tags: [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.