prometeu-studio/discussion/workflow/agendas/AGD-0008-pbs-low-level-asset-manager-surface.md

12 KiB

id ticket title status created resolved decision tags
AGD-0008 pbs-low-level-asset-manager-surface PBS Low-Level Asset Manager Surface for Runtime AssetManager accepted 2026-03-27 2026-03-27 DEC-0004
compiler
pbs
runtime
asset-manager
host-abi
stdlib
asset

Pain

PBS ainda nao tem uma superficie low-level explicita para operar o AssetManager do ../runtime, apesar de ja existir um contrato host-backed claro para outras areas como log e gfx, e uma superficie VM-owned consolidada para input.

Hoje isso deixa uma lacuna pratica:

  1. o runtime ja publica a familia de syscalls asset.load, asset.status, asset.commit e asset.cancel;
  2. o AssetBridge/AssetManager ja carregam semantica real de slots, handles, lifecycle e status-first;
  3. o SDK PBS ainda nao declara o owner low-level equivalente;
  4. a agenda AGD-0006 discute a superficie simbolica author-facing e o lowering de Addressable para identidade estavel, mas nao fecha o shape minimo do contrato host-backed bruto que deve existir por baixo.

Sem essa camada low-level bem definida, o proximo passo fica mais dificil:

  • nao existe base clara para um futuro declare service Assets ergonomico;
  • nao existe alvo normativo preciso para o frontend PBS validar e lowerar;
  • mesmo com o runtime agora convergido para asset_id, PBS ainda precisa decidir qual shape low-level publicar no SDK e como nomear/encapsular esse contrato.

Context

Domain owner:

  • compiler/pbs

Referenced domains:

  • runtime
  • possivelmente vm-arch se a discussao tocar contrato transversal de handles/status layout

O runtime ja fornece evidencia concreta para esta discussao:

  • ../runtime/crates/console/prometeu-hal/src/syscalls/domains/asset.rs publica module = "asset" com load, status, commit e cancel;
  • ../runtime/docs/specs/runtime/15-asset-management.md fixa o MVP syscall shape como:
    • asset.load(asset_id, slot) -> (status:int, handle:int)
    • asset.status(handle) -> status:int
    • asset.commit(handle) -> status:int
    • asset.cancel(handle) -> status:int
  • ../runtime/crates/console/prometeu-hal/src/asset_bridge.rs agora expõe load(&self, asset_id: AssetId, slot_index: usize) -> Result<HandleId, AssetLoadError>;
  • ../runtime/docs/specs/runtime/16-host-abi-and-syscalls.md reforca que o caller nao fornece asset_name nem bank_type;
  • ../runtime/docs/vm-arch/ISA_CORE.md e ../runtime/docs/vm-arch/ARCHITECTURE.md ja tratam o stack contract canonico como asset_id, slot -> status, handle;
  • o mesmo runtime spec usa asset_id como chave normativa para preload.

No workspace atual, isso elimina a ambiguidade antiga do lado runtime:

  1. o runtime low-level ja convergiu para asset_id + slot;
  2. preload/bootstrap e asset_table usam a mesma identidade;
  3. a tensao restante agora esta quase toda do lado PBS, que ainda precisa conectar essa ABI crua com a futura superficie simbolica discutida em AGD-0006.

Os exemplos existentes no SDK PBS ajudam a enquadrar a forma esperada:

  • log usa declare host LowLog como owner bruto e declare service Log como fachada ergonomica;
  • gfx usa declare host LowGfx e declare service Gfx no mesmo padrao;
  • input nao usa host ABI, porque ja foi modelado como builtin VM-owned, entao ele serve mais como contraexemplo util do que como template direto.

O que esta discussion precisa responder nao e "como o jogo vai referenciar assets de forma simpatica". Essa parte ja esta sendo discutida em outra agenda.

O foco aqui e mais baixo nivel:

  • qual contrato PBS deve declarar para falar com a superficie asset que o runtime ja resolve por host ABI;
  • quais tipos/status/handles/slots precisam existir no SDK/interface module;
  • onde a fronteira entre espelho fiel do runtime atual e normalizacao futura deve ser colocada.

Clarification:

  • despite the user shorthand "assets.load", the concrete runtime surface checked on 2026-03-27 in ../runtime is still module = "asset" and name = "load";
  • the substantive update is the argument contract, now asset_id, slot, not asset_name, kind, slot.
  • the canonical capability name checked on 2026-03-27 is also asset in the singular:
    • runtime caps publish ASSET;
    • runtime cartridge capability mapping uses "asset" -> ASSET;
    • PBS capability spelling examples follow singular names such as "gfx" and should stay aligned with the runtime capability registry.

Open Questions

  • Qual deve ser o owner low-level em PBS: LowAsset, LowAssets, LowAssetManager, ou outro naming alinhado ao padrao existente?
  • A primeira versao do contrato PBS deve espelhar exatamente o runtime atual (asset.load(asset_id, slot)), ou ainda vale esconder parte disso atras de wrappers nominais mais fortes?
  • Devemos modelar a entrada de load em PBS low-level como int asset_id cru, como um nominal type dedicado (AssetId), ou como um builtin reservado com semantica de runtime id?
  • O baixo nivel deve assumir apenas o ABI do runtime publicado hoje, deixando qualquer lowering de Addressable para uma camada superior, ou deve nascer ja preparado para metadata reservada de asset lowering?
  • Como representar slot na interface PBS: int cru, nominal SlotIndex, ou algum wrapper pequeno que continue baixando para o mesmo slot integer da ABI?
  • Devemos refletir normativamente que bank kind nao e mais argumento publico de asset.load, porque o runtime o deriva de asset_table?
  • handle deve ser um int cru no MVP, ou um builtin/nominal type dedicado para evitar mistura acidental com outros ids?
  • Os status de load, status, commit e cancel devem ficar como int cru no low-level, ou o SDK PBS deve declarar enums dedicados desde o inicio?
  • bank_info e slot_info, que existem no runtime como modulo bank, fazem parte da mesma discussion ou devem ficar fora do primeiro recorte do asset low-level?
  • O contrato PBS low-level deve cobrir somente load/status/commit/cancel, ou tambem preparar desde ja preload/bootstrap observability e telemetry adjacentes?
  • A surface low-level deve ser totalmente host-backed via declare host, com um declare service Assets opcional depois, seguindo log/gfx?
  • A agenda deve assumir como principio que PBS nunca fala diretamente com AssetManager, e sim apenas com a ABI module/name/version publicada pelo runtime?
  • Qual parte desta decisao precisa propagar para specs PBS (6.2, stdlib surface, talvez runtime capabilities) e qual parte fica apenas como implementacao de SDK/resources?

Options

Option A - Mirror The Current Runtime ABI Exactly

  • Approach: declarar em PBS um declare host que reflita exatamente asset.load(asset_id, slot), asset.status(handle), asset.commit(handle) e asset.cancel(handle), usando int cru em todos os pontos onde a ABI hoje e inteira.
  • Pro: reduz risco de desalinhamento com o runtime atual e facilita implementacao incremental rapida.
  • Con: empurra pouca semantica para o SDK e deixa PBS exposto a mistura acidental entre asset_id, slot e handle.
  • Maintainability: media. O alinhamento ABI e forte, mas a superficie editorial continua pobre.

Option B - Publish A Low-Level PBS Surface That Is ABI-Faithful But Type-Normalized

  • Approach: manter alinhamento estrito com module = "asset" e com os nomes/version atuais, mas permitir que PBS exponha wrappers nominais/enums/structs para asset_id, handle, slot e status, desde que o lowering final preserve o ABI publicado.
  • Pro: segue o padrao de log/gfx, melhora legibilidade do SDK e deixa o compiler com um alvo mais seguro sem esconder que a ownership continua no runtime ABI.
  • Con: exige decidir cedo quais normalizacoes de tipo sao so editoriais e quais ja implicam semantica nova.
  • Maintainability: alta. A ABI continua estavel, mas a superficie PBS nao precisa ficar presa a int solto para sempre.

Option C - Skip The Raw Surface And Design Only The Author-Facing Assets API

  • Approach: postergar a definicao low-level e discutir apenas a futura fachada Assets baseada em Addressable/asset_id, deixando o contrato host-backed implicito por enquanto.
  • Pro: conversa mais proxima da experiencia do autor de jogo.
  • Con: deixa o pipeline sem camada de base; mistura decisao ergonomica com decisao de ABI; repete exatamente o tipo de ambiguidade que log/gfx evitaram ao separar owner bruto de fachada.
  • Maintainability: baixa. A implementacao tendera a inventar detalhes sem uma superficie canonica intermediaria.

Discussion

No estado atual, a direcao mais coerente parece ser a Option B.

Motivos:

  1. log e gfx ja mostraram um padrao util: owner low-level explicito via declare host, opcionalmente embrulhado por declare service;
  2. input reforca que nem toda superficie do SDK precisa ser host-backed, entao esta agenda deve ser cuidadosa para nao confundir "API de jogo" com "contrato ABI";
  3. a agenda AGD-0006 precisa de uma base concreta onde o lowering author-facing possa cair;
  4. o runtime ja tem ABI publicada para asset, entao PBS nao deve inventar uma forma paralela nem falar com AssetManager de forma privilegiada;
  5. o runtime recente removeu a maior parte da ambiguidade de carga ao convergir para asset_id + slot, entao a agenda PBS pode ficar mais assertiva e menos especulativa;
  6. ainda assim, espelhar apenas int/int/int sem nenhuma disciplina editorial empurra custo cognitivo desnecessario para o SDK e para os testes do compiler.

O principal cuidado e separar dois eixos:

  • fidelidade ABI:
    • module, name, version, aridade e retorno precisam permanecer alinhados ao runtime;
  • editorial/type shape em PBS:
    • wrappers nominais, enums ou pequenos value types podem ser aceitaveis se o lowering terminar no mesmo contrato host-backed.

The recent runtime change also sharpens the recommendation:

  • this agenda no longer needs to entertain a name-based low-level path as a first-class candidate;
  • if PBS wants Addressable or symbolic authoring, that should lower into asset_id before the final host call;
  • the low-level owner should be designed around the runtime contract that actually exists now, not around the retired asset_name surface.

Current convergence already accepted in discussion:

  1. the low-level PBS owner name should be LowAssets;
  2. the first PBS low-level surface should keep int raw for asset_id and slot;
  3. the declaration shape should be declare host LowAssets { ... };
  4. capability spelling should remain asset, not assets, to preserve alignment with the runtime capability and syscall registries even if the PBS owner type is pluralized.

Illustrative direction:

declare host LowAssets {
  [Host(module = "asset", name = "load", version = 1)]
  [Capability(name = "asset")]
  fn load(asset_id: int, slot: int) -> (status: int, loading_handle: int);

  [Host(module = "asset", name = "status", version = 1)]
  [Capability(name = "asset")]
  fn status(loading_handle: int) -> int;

  [Host(module = "asset", name = "commit", version = 1)]
  [Capability(name = "asset")]
  fn commit(loading_handle: int) -> int;

  [Host(module = "asset", name = "cancel", version = 1)]
  [Capability(name = "asset")]
  fn cancel(loading_handle: int) -> int;
}

This keeps one deliberate naming asymmetry:

  • source owner: LowAssets
  • runtime module/capability: asset

That asymmetry looks acceptable because source declaration ownership is editorial, while module/name/version and capability strings are operational identities that must stay runtime-aligned.

Tambem parece importante explicitar o limite desta agenda:

  • ela nao deve fechar a politica author-facing completa de asset references;
  • ela deve produzir um alvo low-level suficiente para que a proxima decision possa dizer como Assets.load(assets.foo.bar, slot) baixa para a chamada host-backed final baseada em asset_id.

Resolution

Accepted on 2026-03-27.

Locked points:

  1. the low-level PBS owner is LowAssets;
  2. the low-level declaration shape is declare host LowAssets { ... };
  3. the runtime binding stays on module = "asset" with capability asset in the singular;
  4. v1 keeps raw int for asset_id, slot, handle, and status values;
  5. any future symbolic author-facing asset surface must lower into this runtime-aligned low-level contract.