prometeu-runtime/docs/runtime/agendas/025-cartridge-manifest-entrypoint-removal-and-runtime-protocol.md

7.5 KiB

025-cartridge-manifest-entrypoint-removal-and-runtime-protocol

Status: Closed Domain Owner: runtime Cross-Domain Impact: compiler/PBS, firmware, loader, VM, spec 13 Resolution: materialized as ../decisions/025-cartridge-manifest-entrypoint-removal-and-runtime-protocol.md

Contexto

O runtime atual ainda modela entrypoint como metadado autoritativo vindo de manifest.json.

Esse contrato aparece hoje em mais de uma camada:

  • CartridgeManifest.entrypoint;
  • CartridgeDTO.entrypoint;
  • Cartridge.entrypoint;
  • VirtualMachineRuntime::initialize_vm(...), que repassa esse valor para a VM;
  • VirtualMachine::initialize(program_bytes, entrypoint), que resolve boot por string nominal, índice numérico ou fallback implícito para a primeira função;
  • VirtualMachine::prepare_call(entrypoint), que também aceita string nominal ou índice e cai em 0 como fallback local.

Ao mesmo tempo, a direção nova do compiler/PBS é diferente:

  • o compiler publica um wrapper sintético como entrypoint físico do artefato;
  • esse wrapper deve ocupar o índice físico 0;
  • o boot deixa de ser escolha configurável em manifesto e passa a ser protocolo fixo do executável.

Isso cria conflito direto entre o contrato atual do runtime e a direção desejada do artefato compilado.

Além disso, a spec vigente ainda normatiza entrypoint como campo obrigatório em 13-cartridge.md.

Problema

Precisamos decidir se o runtime deve remover entrypoint do contrato do cartucho e endurecer o boot para um protocolo fixo em que a função inicial válida é sempre func_id = 0.

O ponto principal nao e apenas remover um campo JSON.

A agenda precisa fechar quem tem autoridade sobre o boot do cartucho:

  • se o manifesto continua escolhendo callable inicial;
  • ou se o artefato compilado passa a carregar esse contrato de forma estrutural e obrigatoria.

Pontos Criticos

Fatos observados

  • o loader de diretorio hoje falha sem manifest.json, mas nao valida nenhum protocolo de boot alem de desserializar entrypoint;
  • a VM aceita tres formas de boot no init: string vazia, indice numerico textual e nome de export;
  • prepare_call() tem fallback local para 0, o que mantem comportamento implicito mesmo fora do boot inicial;
  • o runtime system ainda rastreia current_entrypoint, reforcando que a escolha de callable continua exposta como estado;
  • a spec atual do cartucho ainda descreve entrypoint como obrigatorio.

Riscos

  • manter entrypoint no manifesto preserva autoridade duplicada entre runtime e compiler;
  • aceitar nome de export, indice textual e fallback vazio enfraquece determinismo e piora observabilidade de erro;
  • deixar compatibilidade transitoria mal definida cria zona cinzenta entre cartucho legado e protocolo novo;
  • endurecer o protocolo sem erro canonico claro pode produzir falhas opacas de bootstrap.

Tradeoffs

  • remover entrypoint simplifica o contrato e centraliza a autoridade no artefato, mas exige propagacao coordenada em spec, loader, system e VM;
  • manter compatibilidade temporaria reduz friccao de migracao, mas prolonga um contrato que ja ficou estruturalmente errado;
  • rejeitar manifestos legados cedo reduz ambiguidade, mas pode bloquear artefatos intermediarios durante a virada de pipeline.

Hipoteses que precisam ser assumidas explicitamente

  • o compiler/PBS realmente consegue garantir func_id = 0 como wrapper fisico estavel do programa publicado;
  • exports nominais continuam existindo para linking, debug ou introspection, mas deixam de participar da autoridade de boot;
  • o runtime nao precisa mais expor escolha textual de entrypoint depois da migracao.

Opcoes

Opcao A - Manter entrypoint no manifesto como autoridade de boot

O runtime continua lendo manifest.json e escolhendo o callable inicial por string ou indice textual.

Consequencia:

  • preserva o modelo atual;
  • continua divergindo da direcao do compiler;
  • mantem duplicidade de autoridade e superficie de erro desnecessaria.

Opcao B - Remover entrypoint do manifesto e migrar o boot para protocolo fixo em func_id = 0

O loader deixa de carregar entrypoint, a VM endurece o init para boot protocolar e o runtime deixa de rastrear entrypoint textual como parte do contrato.

Consequencia:

  • o artefato compilado vira a unica autoridade de boot;
  • o manifesto volta a ser metadata de pacote, nao controle de execucao;
  • exige plano de transicao explicito para cartuchos legados.

Opcao C - Manter entrypoint apenas como compatibilidade, mas ignorar no runtime novo

O manifesto antigo continua aceito por algum tempo, porem entrypoint vira campo sem efeito operacional.

Consequencia:

  • reduz quebra imediata;
  • mas preserva ambiguidade documental e risco de produtores continuarem emitindo dado morto.

Sugestao / Recomendacao

Adotar Opcao B, sem compatibilidade transitoria normativa no runtime.

Direcao recomendada:

  1. o contrato final do cartucho remove entrypoint de manifest.json;
  2. o boot do programa passa a ser sempre protocolar em func_id = 0;
  3. CartridgeManifest, CartridgeDTO e Cartridge deixam de carregar entrypoint;
  4. VirtualMachine::initialize(...) deve endurecer para init sem parametro textual de entrypoint;
  5. VirtualMachineRuntime deixa de rastrear current_entrypoint como estado de boot;
  6. exports nominais continuam permitidos para linking/introspection, mas deixam de participar do boot;
  7. cartucho que nao oferecer funcao valida em 0 deve falhar com erro canonico de inicializacao, sem fallback implicito para outra funcao.

Compatibilidade recomendada:

  • o runtime nao deve manter compatibilidade para cartuchos legados baseados em entrypoint;
  • a unica excecao pratica do ciclo atual e manter o stress test rodando ate a propagacao correspondente no gerador;
  • essa excecao nao muda o contrato final e nao deve virar regra normativa de runtime.

Perguntas Resolvidas

  1. Compatibilidade transitoria: nao deve existir no runtime como contrato. A migracao deve ser feita no producer pipeline. A excecao pragmatica do ciclo e apenas nao quebrar o stress test antes da propagacao do gerador correspondente.

  2. Erro canonico: a falha de boot protocolar em func_id = 0 deve reutilizar VmInitError::EntrypointNotFound, agora com semantica endurecida para "entrypoint protocolar ausente ou invalido".

  3. prepare_call(): o endurecimento obrigatorio desta agenda cobre o boot do cartucho. A eventual permanencia ou remocao de exports nominais em prepare_call() para chamadas nao relacionadas a boot fica fora do fechamento arquitetural desta agenda e pode ser tratada em ciclo separado, desde que nao preserve autoridade textual de boot.

  4. Dependencia de current_entrypoint: o codigo atual nao revela dependencia host/debug relevante alem do proprio caminho de boot do runtime. O estado existe hoje para alimentar vm.prepare_call(&self.current_entrypoint) e para testes associados, nao como contrato externo autonomo.

Criterio para Encerrar

Esta agenda ja possui definicao suficiente para virar decision, com os seguintes pontos fechados:

  • contrato final de manifest.json sem entrypoint;
  • ausencia de compatibilidade normativa no runtime para cartuchos legados;
  • contrato da VM e do runtime para boot fixo em func_id = 0;
  • reutilizacao de VmInitError::EntrypointNotFound como erro canonico;
  • e propagacao minima esperada para spec 13, loader, system, VM e testes.