prometeu-studio/docs/compiler/pbs/agendas/19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda.md

204 lines
7.6 KiB
Markdown

# Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda
## Status
Open
## Parent Agenda
This agenda derives from:
- `19. Globals, Synthetic Module Init, and FRAME_RET Agenda`
Expected fixed inputs from previous stages:
- `19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda`
- `19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda`
## Purpose
Define how PBS lifecycle is published into the executable artifact once globals and lifecycle semantics are already fixed.
This agenda must close:
- whether the published entrypoint becomes a synthetic wrapper;
- the semantic and publication relationship between user `frame()` and the published entrypoint;
- the new owner of `FRAME_RET`;
- and the contract boundary between source-derived entrypoint discovery, `FrontendSpec`, and cartridge manifest publication.
## Domain Owner
`docs/compiler/pbs`
Este tema pertence ao domínio PBS porque decide a fronteira entre semântica da linguagem, entrypoint publicado e artefato executável.
## Context
Se `frame()` do usuário deixar de ser o callable publicado diretamente, o compiler precisará publicar outro root executável.
Isso abre quatro perguntas acopladas:
- quem é o entrypoint físico do artefato;
- qual callable continua sendo o root lógico do código do usuário;
- onde `FRAME_RET` passa a ser emitido;
- e como manifest e `FrontendSpec` representam isso sem ambiguidade.
Esta agenda existe para fechar esse contrato antes de discutir detalhe de representação de IR.
## Inputs Already Fixed Elsewhere
Os seguintes inputs devem ser tratados como fixos aqui:
- o modelo de globals vindo de `19.1`;
- o modelo de lifecycle e markers vindo de `19.2`;
- `FRAME_RET` continua significando fim do frame lógico;
- o runtime continua esperando um entrypoint published por frame.
## Decisions To Produce
Esta agenda deve produzir direção suficiente para fechar:
1. se o published entrypoint é um wrapper sintético;
2. qual é a relação entre `frame()` do usuário e esse wrapper;
3. onde `FRAME_RET` passa a viver;
4. como a autoridade de entrypoint sai de `FrontendSpec` e passa ao compiler PBS;
5. como o protocolo de runtime/manifest representa esse entrypoint.
## Core Questions
1. O compiler deve publicar um wrapper sintético como entrypoint real?
2. `frame()` do usuário deixa de ser o callable publicado e passa a ser apenas root lógico interno?
3. `FRAME_RET` deve ser emitido no wrapper, não mais no callable do usuário?
4. O compiler PBS deve se tornar a única autoridade para definir o entrypoint publicado?
5. O wrapper sintético deve ocupar protocolarmente o entrypoint físico `0`?
6. O campo `entrypoint` deve deixar de existir no `manifest.json` como estado alvo do protocolo?
7. Existe algum caso em que o wrapper não seja necessário depois de `19.2`?
## Options
### Option A
Publicar um wrapper sintético como entrypoint físico, tratar `frame()` do usuário como root lógico interno, mover `FRAME_RET` para o wrapper, tornar o compiler PBS a autoridade exclusiva de entrypoint e fixar protocolarmente o entrypoint físico em `0`.
### Option B
Manter `frame()` do usuário como entrypoint publicado e tentar acoplar boot/lifecycle diretamente nele.
### Option C
Publicar wrapper sintético, mas manter `entrypoint` no manifest como autoridade nominal paralela.
## Tradeoffs
### Option A
- Prós:
- separa lifecycle publicado do callable do usuário;
- acomoda boot one-shot de forma limpa;
- preserva o significado de `FRAME_RET` com owner mais correto.
- alinha melhor o protocolo físico do artefato com a política já existente de `func_id = 0` como entrypoint;
- remove autoridade duplicada entre compiler, manifest e `FrontendSpec`.
- Contras:
- exige trabalho claro de migração em manifest, runtime e `FrontendSpec`;
- torna a relação lógico/físico explicitamente dupla.
### Option B
- Prós:
- preserva a superfície atual de publicação.
- Contras:
- mistura responsabilidades demais no callable do usuário;
- enfraquece a clareza do lifecycle.
### Option C
- Prós:
- parece reduzir custo de transição imediata.
- Contras:
- mantém duas autoridades para entrypoint;
- cria dívida documental e de runtime desnecessária;
- enfraquece a ideia de entrypoint como protocolo fixo do artefato.
## Recommendation
Seguir com a **Option A**.
## Current Direction
Os pontos abaixo já podem ser tratados como direção fechada desta agenda, salvo objeção nova forte:
1. o compiler deve publicar um wrapper sintético como entrypoint físico real;
2. esse wrapper deve conter:
- boot one-shot,
- os inits necessários apenas uma vez,
- a chamada ao `frame()` do usuário,
- e o `FRAME_RET` final;
3. `frame()` anotado com `[Frame]` permanece como root lógico do usuário;
4. o wrapper sintético é o root físico publicado;
5. `FRAME_RET` sai do final do `frame()` do usuário e passa a existir no wrapper;
6. `FrontendSpec` perde autoridade para referenciar quem é o entrypoint;
7. a autoridade de entrypoint fica outorgada exclusivamente ao compiler PBS;
8. o wrapper sintético deve ser compilado no entrypoint físico `0`;
9. o estado alvo do protocolo deve remover `entrypoint` do `manifest.json`;
10. o runtime/loader deve tratar o entrypoint como protocolo fixo do artefato, não como metadado nominal configurável no manifest.
## Manifest and Runtime Direction
Esta agenda também já aponta para a seguinte direção de contrato:
1. o campo `entrypoint` deve deixar de existir no `manifest.json` como estado final do protocolo;
2. o runtime deve assumir protocolarmente o entrypoint físico `0`;
3. o compiler garante que esse índice `0` pertence ao wrapper sintético publicado;
4. export nominal do callable deixa de ser a autoridade de boot;
5. qualquer compatibilidade temporária com manifest nominal deve ser tratada apenas como transição, não como contrato final desejado.
## Exports Boundary
Esta agenda também fecha a seguinte separação:
1. exports nominais de funções podem continuar existindo no artefato;
2. esses exports deixam de ser usados como autoridade de loader/boot;
3. boot passa a depender exclusivamente do entrypoint físico `0` publicado pelo compiler;
4. exports nominais permanecem apenas como superfície útil para tooling, debug, introspection e casos correlatos.
## Remaining Open Points
Com a direção acima, os pontos que ainda pedem fechamento real nesta agenda ficam reduzidos a:
1. a forma de propagação normativa dessa mudança para specs gerais de bytecode, lowering e cartridge contract.
## Runtime Propagation
Esta agenda também deve referenciar explicitamente a discussão correspondente no domínio runtime:
- `../runtime/docs/runtime/agendas/025-cartridge-manifest-entrypoint-removal-and-runtime-protocol.md`
Direção fechada desta agenda:
1. não há linha de compatibilidade desejada como estado-alvo;
2. a remoção de `entrypoint` do runtime deve ser executada em prioridade alinhada ao compiler;
3. a agenda de runtime é o owner da discussão operacional de loader/VM/manifest no outro domínio.
## Expected Spec Material
Se esta agenda fechar, a propagação esperada atinge pelo menos:
- `9. Dynamic Semantics Specification.md`
- `13. Lowering IRBackend Specification.md`
- `7. Cartridge Manifest and Runtime Capabilities Specification.md`
- `12. Diagnostics Specification.md`
## Non-Goals
Esta agenda não deve:
1. escolher o encoding exato do wrapper no IR;
2. definir estrutura detalhada de module init lowering;
3. escrever fixtures completos de conformance.
## Next Step
Depois de fechar esta agenda, abrir ou aprofundar:
- `19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda`