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 em0como 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 desserializarentrypoint; - a VM aceita tres formas de boot no init: string vazia, indice numerico textual e nome de export;
prepare_call()tem fallback local para0, 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
entrypointcomo obrigatorio.
Riscos
- manter
entrypointno 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
entrypointsimplifica 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 = 0como 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:
- o contrato final do cartucho remove
entrypointdemanifest.json; - o boot do programa passa a ser sempre protocolar em
func_id = 0; CartridgeManifest,CartridgeDTOeCartridgedeixam de carregarentrypoint;VirtualMachine::initialize(...)deve endurecer para init sem parametro textual de entrypoint;VirtualMachineRuntimedeixa de rastrearcurrent_entrypointcomo estado de boot;- exports nominais continuam permitidos para linking/introspection, mas deixam de participar do boot;
- cartucho que nao oferecer funcao valida em
0deve 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
-
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.
-
Erro canonico: a falha de boot protocolar em
func_id = 0deve reutilizarVmInitError::EntrypointNotFound, agora com semantica endurecida para "entrypoint protocolar ausente ou invalido". -
prepare_call(): o endurecimento obrigatorio desta agenda cobre o boot do cartucho. A eventual permanencia ou remocao de exports nominais emprepare_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. -
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 alimentarvm.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.jsonsementrypoint; - 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::EntrypointNotFoundcomo erro canonico; - e propagacao minima esperada para
spec 13, loader, system, VM e testes.