# 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`](../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`](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/runtime/specs/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.