dev/ajustments-asset-entry #12
@ -1,6 +1,6 @@
|
||||
{"type":"meta","next_id":{"DSC":22,"AGD":20,"DEC":6,"PLN":5,"LSN":24,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":22,"AGD":20,"DEC":6,"PLN":5,"LSN":25,"CLSN":1}}
|
||||
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||
{"type":"discussion","id":"DSC-0021","status":"open","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[{"id":"AGD-0019","file":"AGD-0019-asset-entry-codec-enum-with-metadata.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0005","file":"DEC-0005-asset-entry-codec-enum-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09","ref_agenda":"AGD-0019"}],"plans":[{"id":"PLN-0004","file":"PLN-0004-asset-entry-codec-enum-execution.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09","ref_decisions":["DEC-0005"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"legacy-runtime-learn-import","title":"Import legacy runtime learn into discussion lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["migration","tech-debt"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0001-prometeu-learn-index.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0002","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0002-historical-asset-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0003","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0003-historical-audio-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0004","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0004-historical-cartridge-boot-protocol-and-manifest-authority.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0005","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0005-historical-game-memcard-slots-surface-and-semantics.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0006","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0006-historical-gfx-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0007","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0007-historical-retired-fault-and-input-decisions.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0008","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0008-historical-vm-core-and-assets.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0009","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0010","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0010-mental-model-audio.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0011","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0012","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0012-mental-model-input.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0013","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0013-mental-model-observability-and-debugging.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0014","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0014-mental-model-portability-and-cross-platform.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0015","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0015-mental-model-save-memory-and-memcard.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0016","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0016-mental-model-status-first-and-fault-thinking.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0017","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0017-mental-model-time-and-cycles.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0018","file":"lessons/DSC-0001-runtime-learn-legacy-import/LSN-0018-mental-model-touch.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"type":"discussion","id":"DSC-0002","status":"open","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0001","file":"workflow/agendas/AGD-0001-runtime-edge-test-plan.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0003","status":"open","ticket":"packed-cartridge-loader-pmc","title":"Agenda - Packed Cartridge Loader PMC","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0002","file":"workflow/agendas/AGD-0002-packed-cartridge-loader-pmc.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
---
|
||||
id: LSN-0024
|
||||
ticket: asset-entry-codec-enum-with-metadata
|
||||
title: String on the Wire, Enum in the Runtime
|
||||
created: 2026-04-09
|
||||
tags: [asset, runtime, codec, rust, contract]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
This discussion closed the contract for `AssetEntry.codec` in the runtime asset model. The system already serialized `assets.pa` as JSON produced by the Studio in Java, while the runtime consumed that JSON in Rust. The original runtime model kept `codec` as a free-form `String`, which allowed legacy aliases such as `RAW` and pushed validation and branching into scattered string comparisons.
|
||||
|
||||
The implemented change moved the runtime to a typed enum while preserving the existing transport simplicity of the pack format.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Asset Entry Codec Enum Contract
|
||||
|
||||
**What:**
|
||||
Keep `codec` as a JSON string in `assets.pa`, but deserialize it directly into a Rust enum in `AssetEntry`. The initial codec set contains only `None`, serialized canonically as `NONE` in `SCREAMING_SNAKE_CASE`.
|
||||
|
||||
**Why:**
|
||||
This preserves a simple cross-language wire contract for the Studio packer while making the runtime honest about the domain model it operates on. The loader now rejects unknown codecs early, and runtime consumers branch on enum variants instead of raw strings.
|
||||
|
||||
**Trade-offs:**
|
||||
The runtime loses open-ended tolerance for arbitrary codec names, which is intentional. Future codecs with payload-specific metadata still require a dedicated follow-up decision once a real codec exists.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
- Use a stable textual discriminant on the wire and a typed enum in the runtime model.
|
||||
- Let deserialization enforce the supported variant set instead of adding compatibility shims deeper in the execution path.
|
||||
- Keep the discriminant contract canonical across producers and consumers; do not allow per-producer aliases.
|
||||
- Preserve editorial or bank-specific metadata outside the codec discriminant so future codec payload metadata can be added without collapsing the whole asset model into an untyped blob.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- A runtime that accepts legacy aliases such as `RAW` keeps historical ambiguity alive and makes it harder to reason about the true contract.
|
||||
- If fixtures are constructed directly in tests, typed metadata helpers can expose missing required fields that were previously masked by weaker validation.
|
||||
- Cross-language contracts become fragile if the wire spelling is not explicitly canonized. The producer must conform exactly to the runtime contract.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Use a string on the wire when cross-language transport simplicity matters, but deserialize into an enum as soon as the runtime needs semantic guarantees.
|
||||
- Canonical spelling belongs to the shared contract, not to whichever producer happens to serialize first.
|
||||
- Rejecting unknown codec values at asset-entry validation time keeps failures local, early, and easier to debug.
|
||||
@ -1,183 +0,0 @@
|
||||
---
|
||||
id: AGD-0019
|
||||
ticket: asset-entry-codec-enum-with-metadata
|
||||
title: Agenda - Asset Entry Codec as Enum with Metadata
|
||||
status: accepted
|
||||
created: 2026-04-09
|
||||
resolved: 2026-04-09
|
||||
decision: DEC-0005
|
||||
tags: [asset, runtime, codec, metadata]
|
||||
---
|
||||
|
||||
# Agenda - Asset Entry Codec as Enum with Metadata
|
||||
|
||||
## Contexto
|
||||
|
||||
A `DSC-0017` consolidou a normalizacao de `AssetEntry.metadata`, separando campos criticos na raiz e empurrando detalhes tecnicos para subarvores como `codec` e `pipeline`.
|
||||
|
||||
Isso resolveu a organizacao do contrato, mas nao fechou a representacao tipada de `codec` dentro do runtime. Hoje o dado ainda e percebido mais como JSON dinamico do que como parte explicita do modelo de dominio.
|
||||
|
||||
O tema desta agenda e decidir se `codec` em `AssetEntry` deve deixar de ser apenas um blob/subarvore e passar a ser um enum tipado, capaz de carregar os metadados pertinentes a cada codec.
|
||||
|
||||
## Problema
|
||||
|
||||
Quando `codec` e tratado como JSON generico ou como informacao frouxa em metadados, o runtime perde:
|
||||
|
||||
- clareza sobre quais codecs existem de fato;
|
||||
- validacao estrutural forte por variante;
|
||||
- ergonomia para loaders e drivers;
|
||||
- separacao nitida entre metadata do banco e metadata do codec.
|
||||
|
||||
Ao mesmo tempo, tipar `codec` cedo demais ou de forma larga demais pode misturar responsabilidades e transformar o enum em um deposito generico de qualquer detalhe tecnico do asset.
|
||||
|
||||
## Pontos Criticos
|
||||
|
||||
1. Limite de responsabilidade.
|
||||
`codec` deve carregar apenas dados necessarios para decodificacao, nao toda a metadata do asset.
|
||||
|
||||
2. Compatibilidade com a normalizacao anterior.
|
||||
A agenda nao deve reabrir a decisao de segmentar metadata; ela deve apenas fechar como o segmento `codec` vira modelo tipado no runtime.
|
||||
|
||||
3. Evolucao de formato.
|
||||
O modelo precisa permitir codecs sem payload adicional e codecs com configuracao especifica, sem cair em campos opcionais demais.
|
||||
|
||||
4. Unknown/forward compatibility.
|
||||
Precisamos decidir se codecs desconhecidos falham no parse, se ficam preservados como raw JSON, ou se existe modo hibrido.
|
||||
|
||||
5. Impacto nos callers.
|
||||
A mudanca afeta serializacao/deserializacao, helpers, validacao de cart e ergonomia dos loaders.
|
||||
|
||||
## Opcoes
|
||||
|
||||
### Opcao A - Manter `codec` como JSON dinamico
|
||||
|
||||
- **Abordagem:** manter `codec` como subarvore em `metadata` ou como `serde_json::Value`, usando helpers tipados apenas nos pontos de consumo.
|
||||
- **Pro:** menor migracao imediata e maior flexibilidade para formatos experimentais.
|
||||
- **Con:** o contrato real continua implicito, com checagens espalhadas e mais risco de drift entre parser e consumidores.
|
||||
- **Tradeoff:** adia a decisao de dominio e preserva a ambiguidade exatamente no ponto onde o runtime precisa de semantica forte.
|
||||
|
||||
### Opcao B - Tornar `codec` um enum tipado com payload por variante
|
||||
|
||||
- **Abordagem:** introduzir algo como `AssetCodec`, com variantes explicitas (`None`, `Png { ... }`, `Jpeg { ... }`, etc.) carregando apenas os metadados do proprio codec.
|
||||
- **Pro:** o runtime ganha exaustividade, parse centralizado e um modelo de dominio mais honesto.
|
||||
- **Con:** exige decidir fronteiras claras entre metadata do codec e metadata do banco/asset; tambem aumenta custo de evolucao quando novos codecs surgem.
|
||||
- **Tradeoff:** troca flexibilidade irrestrita por contrato forte e melhor ergonomia operacional.
|
||||
|
||||
### Opcao C - Separar `codec_kind` de um payload opcional tipado
|
||||
|
||||
- **Abordagem:** usar um enum leve para o tipo de codec e um campo separado para configuracao adicional.
|
||||
- **Pro:** reduz acoplamento do discriminante com o payload e pode simplificar alguns formatos.
|
||||
- **Con:** reintroduz estados invalidos (`kind` e payload divergentes), exigindo validacao cruzada manual.
|
||||
- **Tradeoff:** parece mais flexivel, mas perde a principal vantagem de um tagged enum: coerencia estrutural por construcao.
|
||||
|
||||
## Sugestao / Recomendacao
|
||||
|
||||
Seguir com a **Opcao B**.
|
||||
|
||||
`codec` em `AssetEntry` deveria ser um enum tipado e capaz de carregar os metadados estritamente relativos a ele. Isso fecha melhor o modelo de dominio: o runtime deixa de tratar codec como detalhe textual solto e passa a reconhece-lo como parte semantica do contrato do asset.
|
||||
|
||||
A recomendacao, no entanto, vem com uma fronteira explicita:
|
||||
|
||||
- metadata especifica de decodificacao fica dentro do enum do codec;
|
||||
- metadata do banco/formato de consumo continua fora dele;
|
||||
- metadata editorial ou operacional do asset tambem continua fora dele.
|
||||
|
||||
Em outras palavras, a discussao nao e "colocar toda metadata dentro de `codec`", e sim "dar ao segmento `codec` uma representacao tipada, exaustiva e com payload por variante quando necessario".
|
||||
|
||||
Com as respostas atuais, a recomendacao fica mais concreta:
|
||||
|
||||
- o JSON serializado pelo Studio dentro de `asset.pa` pode manter `codec` como string opaca;
|
||||
- o runtime Rust deve desserializar essa string diretamente para um enum em `AssetEntry`;
|
||||
- o nome canonico de cada codec no JSON deve seguir o contrato definido pelo runtime, e o Studio/paker deve se conformar exatamente a ele;
|
||||
- a variante inicial canonica e apenas `None`;
|
||||
- `Raw` deve ser considerada removida do modelo;
|
||||
- codec desconhecido no runtime e erro fatal de carregamento e deve impedir a execucao do cartucho;
|
||||
- `pipeline` nao deve sobreviver no runtime e pode ser descartado completamente desse lado.
|
||||
|
||||
## Perguntas em Aberto
|
||||
|
||||
- Como o modelo evolui quando surgir o primeiro codec real com payload adicional sem perder a separacao entre o discriminante string no JSON e a interpretacao tipada no runtime?
|
||||
|
||||
## Discussao
|
||||
|
||||
### Direcao fechada ate aqui
|
||||
|
||||
1. **Serializacao no Studio**
|
||||
O JSON serializado pelo Studio dentro de `asset.pa` deve expor `codec` como string opaca.
|
||||
|
||||
2. **Desserializacao no runtime**
|
||||
O runtime Rust deve carregar essa string diretamente em um enum no proprio `AssetEntry`. O wire format continua string, mas o modelo carregado no runtime passa a ser tipado.
|
||||
|
||||
3. **Canon do nome**
|
||||
O nome textual do codec no JSON nao e arbitrario por produtor. Ele deve seguir exatamente o canon definido pelo contrato. O canon fechado para este tema e `SCREAMING_SNAKE_CASE`, alinhado a `BankType`, e o packer deve seguir esse formato sem aliases livres.
|
||||
|
||||
4. **Variante inicial**
|
||||
O unico codec canonico agora e `None`.
|
||||
|
||||
5. **Fim de `Raw`**
|
||||
`Raw` nao deve mais existir como conceito no modelo.
|
||||
|
||||
6. **Codecs desconhecidos**
|
||||
Nao devem ser empacotados. Se mesmo assim chegarem ao runtime, isso e erro de validacao do `AssetEntry` e o cartucho deve ser fechado antes de seguir.
|
||||
|
||||
7. **Escopo atual de codecs**
|
||||
Como ainda nao existe codec real implementado, a primeira versao do enum pode ser minima e conter apenas `None`.
|
||||
|
||||
8. **Destino de `pipeline`**
|
||||
`pipeline` nao tem valor operacional no runtime atual e pode ser descartado completamente desse lado.
|
||||
|
||||
### Leitura arquitetural dessas respostas
|
||||
|
||||
As respostas empurram a agenda para um contrato bem mais estrito do que o texto inicial sugeria:
|
||||
|
||||
- `codec` existe como conceito de dominio mesmo antes de haver codecs concretos alem de `None`;
|
||||
- o JSON de `asset.pa` pode manter um discriminante simples e opaco, enquanto o runtime desserializa isso diretamente para enum e usa esse valor para escolher a interpretacao tipada de `metadata.codec`;
|
||||
- a autoridade sobre o spelling do codec pertence ao contrato compartilhado, nao ao Studio isoladamente;
|
||||
- o runtime nao deve carregar extensibilidade aberta para codecs desconhecidos;
|
||||
- a compatibilidade futura deve ser dirigida pelo Studio e pelo empacotamento, nao por tolerancia dinamica no runtime;
|
||||
- `pipeline` deixa de disputar espaco conceitual com `codec` no runtime.
|
||||
|
||||
Isso favorece um modelo de enum fechado, validado cedo e com semantica fail-fast.
|
||||
|
||||
## Criterio para Encerrar
|
||||
|
||||
Esta agenda pode ser encerrada quando houver consenso escrito sobre:
|
||||
|
||||
- o papel exato de `codec` no modelo de dominio do `AssetEntry`;
|
||||
- a fronteira entre payload do codec e restante da metadata;
|
||||
- a estrategia para codecs sem metadata adicional e para codecs desconhecidos;
|
||||
- o shape string de `codec` no JSON e sua relacao com o enum carregado no runtime e com `metadata.codec`;
|
||||
- o proximo passo normativo para transformar isso em decisao sem reabrir `DSC-0017`.
|
||||
|
||||
## Resolucao Provisoria
|
||||
|
||||
Ha consenso provisoriamente estabelecido sobre os seguintes pontos:
|
||||
|
||||
- `codec` deve existir como enum tipado no modelo do runtime;
|
||||
- a variante inicial unica e `None`;
|
||||
- `Raw` sai do contrato;
|
||||
- codecs desconhecidos sao invalidos e devem falhar de forma fatal no carregamento do cartucho;
|
||||
- `pipeline` pode ser descartado do runtime;
|
||||
- o JSON de `asset.pa` deve serializar `codec` como string opaca;
|
||||
- o runtime Rust deve desserializar essa string diretamente para enum no `AssetEntry`;
|
||||
- o nome textual do codec no JSON deve seguir `SCREAMING_SNAKE_CASE`, e o Studio deve se conformar exatamente a ele;
|
||||
- codec desconhecido deve falhar na validacao do `AssetEntry`, antes de qualquer carga efetiva.
|
||||
|
||||
O unico ponto em aberto passa a ser a politica de evolucao para o primeiro codec real com payload, preservando a distincao entre:
|
||||
|
||||
- discriminante string no JSON do asset; e
|
||||
- shape tipado de `metadata.codec` no runtime.
|
||||
|
||||
## Resolucao
|
||||
|
||||
A agenda fica encerrada com a seguinte orientacao:
|
||||
|
||||
- `codec` permanece `string` no JSON de `asset.pa`;
|
||||
- o runtime Rust deve desserializar essa string diretamente para enum no `AssetEntry`;
|
||||
- o nome textual do codec segue `SCREAMING_SNAKE_CASE`, alinhado a `BankType`;
|
||||
- `None` e a unica variante inicial;
|
||||
- `Raw` sai do contrato;
|
||||
- codec desconhecido falha na validacao do `AssetEntry` e fecha o cartucho;
|
||||
- `pipeline` e descartado do runtime.
|
||||
|
||||
A evolucao para codecs com payload adicional fica explicitamente adiada para uma decisao futura motivada por um codec real.
|
||||
@ -1,91 +0,0 @@
|
||||
---
|
||||
id: DEC-0005
|
||||
ticket: asset-entry-codec-enum-with-metadata
|
||||
title: Asset Entry Codec Enum Contract
|
||||
status: accepted
|
||||
created: 2026-04-09
|
||||
accepted: 2026-04-09
|
||||
agenda: AGD-0019
|
||||
plans: [PLN-0004]
|
||||
tags: [asset, runtime, codec, metadata]
|
||||
---
|
||||
|
||||
## Status
|
||||
|
||||
Accepted on 2026-04-09.
|
||||
|
||||
## Contexto
|
||||
|
||||
A discussao `AGD-0019` fechou que o campo `codec` de `AssetEntry` faz parte do contrato de dominio do runtime e nao deve permanecer como texto frouxo consumido ad hoc por loaders.
|
||||
|
||||
Hoje o empacotamento e produzido no Studio em Java/Jackson e o runtime consome o header JSON de `asset.pa` em Rust. Portanto, o contrato precisa distinguir claramente:
|
||||
|
||||
- o wire format serializado pelo Studio;
|
||||
- o modelo tipado carregado pelo runtime;
|
||||
- a relacao entre o discriminante do codec e qualquer metadata especifica de codec.
|
||||
|
||||
A decisao tambem precisa consolidar o fim do alias legado `RAW` e a politica de falha para codecs desconhecidos.
|
||||
|
||||
## Decisao
|
||||
|
||||
1. `AssetEntry.codec` no runtime MUST ser representado por um enum tipado, e MUST NOT permanecer como `String` no modelo carregado.
|
||||
2. O JSON serializado em `asset.pa` MUST continuar representando `codec` como uma `string`.
|
||||
3. O runtime Rust MUST desserializar essa `string` diretamente para o enum de codec no proprio `AssetEntry`.
|
||||
4. O spelling textual do codec no JSON MUST seguir exatamente o canon definido por este contrato. O canon inicial MUST ser `SCREAMING_SNAKE_CASE`, alinhado ao padrao ja usado por `BankType`. O Studio/paker MUST emitir exatamente esse spelling e MUST NOT introduzir aliases livres.
|
||||
5. A variante inicial unica do enum MUST ser `None`.
|
||||
6. O alias/conceito `Raw` MUST be removed from the contract and MUST NOT be emitted pelo Studio nem aceito como shape valido futuro.
|
||||
7. Se o runtime encontrar um codec desconhecido para aquele binario, a validacao de `AssetEntry` MUST falhar antes de qualquer carga efetiva do asset, e o cartucho MUST ser rejeitado.
|
||||
8. `pipeline` MUST NOT fazer parte do modelo operacional do runtime para esse contrato e MAY ser descartado completamente no lado do runtime.
|
||||
9. Metadados especificos de codec, quando existirem, MUST ser interpretados a partir do codec resolvido e MUST permanecer separados da metadata editorial ou da metadata propria do banco consumidor.
|
||||
10. A estrategia para o primeiro codec com payload adicional is deferred. Esta decisao fecha apenas o contrato atual e o ponto de extensao, sem antecipar um shape normativo para codecs futuros com payload.
|
||||
|
||||
## Rationale
|
||||
|
||||
- O wire format em `string` preserva simplicidade e compatibilidade com o Studio em Java/Jackson.
|
||||
- O enum no runtime torna o contrato exaustivo, evita parsing textual espalhado e reduz drift entre loader, validacao e consumidores.
|
||||
- Rejeitar codec desconhecido cedo mantem o sistema fail-fast e evita estados parcialmente carregados.
|
||||
- Remover `Raw` evita manter semantica historica ambigua em paralelo ao contrato novo.
|
||||
- Expulsar `pipeline` do runtime reduz ruido conceitual e impede sobreposicao de responsabilidade com `codec`.
|
||||
- Adiar o desenho de codecs com payload evita overdesign antes de existir um caso concreto.
|
||||
|
||||
## Invariantes / Contrato
|
||||
|
||||
- O valor de `codec` no JSON de `asset.pa` e um discriminante textual canonico.
|
||||
- O discriminante textual canonico de `codec` no JSON usa `SCREAMING_SNAKE_CASE`.
|
||||
- O valor de `codec` carregado em Rust e um enum fechado para o conjunto de codecs suportados por aquele runtime.
|
||||
- O Studio e o runtime compartilham o mesmo spelling canonico para cada variante.
|
||||
- O runtime nao oferece modo tolerante para codecs desconhecidos.
|
||||
- O contrato inicial possui uma unica variante valida: `None`.
|
||||
- `Raw` nao pertence mais ao contrato canonico.
|
||||
- `pipeline` nao participa do contrato operacional do runtime.
|
||||
- Quando `metadata.codec` existir para algum codec futuro, sua interpretacao dependera do discriminante ja validado.
|
||||
|
||||
## Impactos
|
||||
|
||||
- `prometeu-hal` deve trocar `AssetEntry.codec: String` por um enum serializavel/desserializavel com canon textual explicito.
|
||||
- `prometeu-drivers` deve remover a aceitacao de `RAW` como alias legado e passar a operar sobre enum, nao sobre comparacao textual solta.
|
||||
- O loader/validacao do cart deve falhar cedo se a desserializacao ou validacao do codec falhar.
|
||||
- O Studio/paker deve emitir exatamente o nome canonico definido para o codec.
|
||||
- O nome canonico inicial de `None` no JSON deve ser `NONE`.
|
||||
- Nao ha necessidade de definir agora um DTO separado apenas para codec; o proprio `AssetEntry` continua sendo o contrato serializado e desserializado.
|
||||
|
||||
## Referencias
|
||||
|
||||
- AGD-0019: Asset Entry Codec as Enum with Metadata
|
||||
- DSC-0017: Asset Entry Metadata Normalization Contract
|
||||
- LSN-0023: Typed Helpers for Asset Metadata
|
||||
- `crates/console/prometeu-hal/src/asset.rs`
|
||||
- `crates/console/prometeu-hal/src/cartridge_loader.rs`
|
||||
- `crates/console/prometeu-drivers/src/asset.rs`
|
||||
|
||||
## Propagacao Necessaria
|
||||
|
||||
- Atualizar o modelo Rust de `AssetEntry` para usar enum de codec.
|
||||
- Atualizar a validacao/desserializacao do header de `asset.pa`.
|
||||
- Atualizar drivers para abandonar `RAW` e comparacoes por `String`.
|
||||
- Ajustar o Studio/paker para emitir o spelling canonico escolhido pelo contrato.
|
||||
- Escrever um plano de execucao antes de alterar spec/codigo.
|
||||
|
||||
## Revision Log
|
||||
|
||||
- 2026-04-09: Initial accepted decision from AGD-0019.
|
||||
@ -1,141 +0,0 @@
|
||||
---
|
||||
id: PLN-0004
|
||||
ticket: asset-entry-codec-enum-with-metadata
|
||||
title: Asset Entry Codec Enum Execution
|
||||
status: accepted
|
||||
created: 2026-04-09
|
||||
completed:
|
||||
tags: [asset, runtime, codec, metadata]
|
||||
---
|
||||
|
||||
## Briefing
|
||||
|
||||
Implement DEC-0005 by replacing `AssetEntry.codec: String` with a typed Rust enum while keeping the `assets.pa` JSON wire format as a canonical `SCREAMING_SNAKE_CASE` string. The initial supported codec set contains only `None`, serialized as `NONE`. Unknown codecs must fail during `AssetEntry` validation, `RAW` must be removed from the accepted contract, and runtime code must stop relying on free-form string comparisons.
|
||||
|
||||
## Decisions de Origem
|
||||
|
||||
- DEC-0005: Asset Entry Codec Enum Contract
|
||||
|
||||
## Alvo
|
||||
|
||||
Land a runtime-side implementation that:
|
||||
|
||||
- introduces a serializable/deserializable `AssetCodec` enum in `prometeu-hal`;
|
||||
- migrates `AssetEntry` to use the enum directly;
|
||||
- rejects unknown codec strings during `assets.pa` parsing/validation;
|
||||
- removes legacy `RAW` handling from runtime consumers and tests;
|
||||
- preserves the current JSON transport contract for the Studio packer: `codec` remains a `SCREAMING_SNAKE_CASE` string in `assets.pa`.
|
||||
|
||||
## Escopo
|
||||
|
||||
- Runtime contract changes in `prometeu-hal` for `AssetEntry` and codec serialization.
|
||||
- Cartridge loading and `assets.pa` validation behavior.
|
||||
- Asset driver logic and tests that currently assume `codec` is a `String`.
|
||||
- Runtime test fixtures that construct `AssetEntry` instances directly.
|
||||
|
||||
## Fora de Escopo
|
||||
|
||||
- Studio/Java packer implementation work.
|
||||
- Introduction of any real codec beyond `None`.
|
||||
- Design or implementation of `metadata.codec` payload shapes for future codecs.
|
||||
- Discussion or implementation of a separate DTO just for `AssetEntry`.
|
||||
|
||||
## Plano de Execucao
|
||||
|
||||
### Step 1 - Introduce `AssetCodec` in `prometeu-hal`
|
||||
|
||||
**What:**
|
||||
Define the runtime enum for asset codecs and migrate `AssetEntry.codec` from `String` to that enum.
|
||||
|
||||
**How:**
|
||||
Add `AssetCodec` to `crates/console/prometeu-hal/src/asset.rs` with idiomatic Rust variant naming and explicit serde mapping to `SCREAMING_SNAKE_CASE`. The initial enum must contain only `None`, serialized as `NONE`. Update `AssetEntry` to use `AssetCodec` and remove the legacy comment about `RAW`.
|
||||
|
||||
**File(s):**
|
||||
- `crates/console/prometeu-hal/src/asset.rs`
|
||||
|
||||
### Step 2 - Make `assets.pa` parsing fail on unknown codecs
|
||||
|
||||
**What:**
|
||||
Ensure unknown codec strings are rejected before any asset load path proceeds.
|
||||
|
||||
**How:**
|
||||
Rely on enum deserialization failure or an explicit validation hook during `assets.pa` header parsing so that invalid codec values produce `CartridgeError::InvalidFormat`. Keep the failure at `AssetEntry` validation time inside cartridge loading, not delayed to driver execution.
|
||||
|
||||
**File(s):**
|
||||
- `crates/console/prometeu-hal/src/cartridge_loader.rs`
|
||||
- Any supporting type definitions in `crates/console/prometeu-hal/src/cartridge.rs` if required by parsing flow
|
||||
|
||||
### Step 3 - Remove runtime string-based codec branching
|
||||
|
||||
**What:**
|
||||
Update asset runtime behavior to consume the enum directly and remove legacy `RAW` acceptance.
|
||||
|
||||
**How:**
|
||||
Replace `codec_is_none_or_legacy_raw` and string matches in `crates/console/prometeu-drivers/src/asset.rs` with enum-based matching on `AssetCodec`. Ensure unsupported codecs remain an error path, but `RAW` is no longer recognized anywhere in runtime logic.
|
||||
|
||||
**File(s):**
|
||||
- `crates/console/prometeu-drivers/src/asset.rs`
|
||||
|
||||
### Step 4 - Update test fixtures and regression coverage
|
||||
|
||||
**What:**
|
||||
Bring existing tests and fixtures in line with the new typed contract and add regression tests for rejection behavior.
|
||||
|
||||
**How:**
|
||||
Replace direct string fixture values such as `"NONE"` and `"RAW"` with enum construction where tests instantiate `AssetEntry` directly. Add or update loader tests to cover:
|
||||
|
||||
- successful parse of `codec: "NONE"`;
|
||||
- failure on unknown codec strings;
|
||||
- failure on legacy `RAW` if it still appears in serialized input.
|
||||
|
||||
Update driver tests to assert enum-based behavior for the supported codec set.
|
||||
|
||||
**File(s):**
|
||||
- `crates/console/prometeu-hal/src/cartridge_loader.rs`
|
||||
- `crates/console/prometeu-drivers/src/asset.rs`
|
||||
- `crates/console/prometeu-system/src/virtual_machine_runtime/tests.rs`
|
||||
|
||||
### Step 5 - Align downstream packer work item
|
||||
|
||||
**What:**
|
||||
Capture the non-runtime propagation requirement for the Studio packer.
|
||||
|
||||
**How:**
|
||||
Record in implementation notes, issue tracking, or follow-up execution context that the Studio/Java packer must emit canonical `SCREAMING_SNAKE_CASE` codec strings and must stop producing `RAW`. No runtime code should add compatibility shims for packer drift.
|
||||
|
||||
**File(s):**
|
||||
- No runtime file changes required in this repository for this step
|
||||
|
||||
## Criterios de Aceite
|
||||
|
||||
- `AssetEntry.codec` is an enum in Rust, not a `String`.
|
||||
- `assets.pa` still serializes/deserializes codec as a JSON string.
|
||||
- The canonical wire spelling for the initial codec is `NONE`.
|
||||
- Unknown codec strings cause cartridge loading to fail before asset loading proceeds.
|
||||
- `RAW` is no longer accepted by runtime code or runtime tests.
|
||||
- Asset driver code branches on `AssetCodec`, not string literals.
|
||||
- Existing runtime tests pass after fixture migration, and regression tests cover the new failure behavior.
|
||||
|
||||
## Tests / Validacao
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- Serialization/deserialization tests for `AssetCodec` proving `AssetCodec::None <-> "NONE"`.
|
||||
- Asset driver tests that match on enum variants instead of strings.
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- Cartridge loader test that accepts `assets.pa` headers containing `codec: "NONE"`.
|
||||
- Cartridge loader test that rejects an unknown codec string.
|
||||
- Cartridge loader test that rejects legacy `RAW`.
|
||||
|
||||
### Manual Verification
|
||||
|
||||
- Inspect generated `assets.pa` header JSON from a known-good sample and verify `codec` remains a string field with `SCREAMING_SNAKE_CASE`.
|
||||
- Run the relevant Rust test suites for `prometeu-hal`, `prometeu-drivers`, and any affected runtime tests.
|
||||
|
||||
## Riscos
|
||||
|
||||
- Existing tests and fixtures may be numerous because `AssetEntry` is widely constructed directly.
|
||||
- If deserialization failure maps too generically, debugging bad packer output may become opaque unless tests assert the intended failure path clearly.
|
||||
- Studio work is out of scope for this repository, so rollout coordination is required to avoid runtime/packer contract skew.
|
||||
Loading…
x
Reference in New Issue
Block a user