# Globals, Synthetic Module Init, and FRAME_RET Agenda ## Status Open ## Purpose Define how PBS should introduce runtime globals and lifecycle-driven executable bootstrap without changing the runtime contract in this phase. This document is the umbrella agenda for topic `19`. It exists to: - keep the full problem framed in one place; - define the dependency order between discussions; - prevent later discussions from re-opening earlier boundaries casually; - and provide the parent reference for any follow-up agendas created under this topic. This agenda must converge on: - the source-level model for mutable module storage; - the lifecycle model for module init, optional program init, and frame execution; - the ownership of `FRAME_RET` once the published entrypoint stops being the user's `frame()` directly; - the migration path from explicit `FrontendSpec` entrypoint configuration to source-derived PBS entrypoint discovery. ## Domain Owner `docs/compiler/pbs` Este tema pertence ao domínio PBS do compiler porque afeta diretamente: - a surface language de declarações top-level; - a detecção de entrypoints pelo frontend PBS; - o modelo de inicialização de módulo e programa; - o lowering de entrypoint de frame; - a relação entre entrypoint lógico do usuário e entrypoint publicado no artefato; - o contrato interno entre frontend, `IRBackend`, `IRVM` lowering e bytecode final. Nesta fase, o owner continua sendo `compiler/pbs` mesmo quando o resultado reutilizar capacidades já existentes da VM, porque a discussão é sobre como o compiler vai expor e orquestrar essas capacidades. ## Problema Hoje o PBS não expõe variáveis globais mutáveis de módulo. O topo do arquivo aceita `declare const`, mas `declare const` é compile-time e não storage runtime. Isso impede formas como: ```pbs declare struct Vec2(x: int, y: int); declare global origin: Vec2 = new Vec2(0, 0); ``` Ao mesmo tempo: 1. a VM já tem suporte operacional para globals por slot; 2. o compiler não modela globals no IR executável atual; 3. o entrypoint de frame do usuário hoje coincide, na prática, com a função que delimita o frame lógico; 4. o pipeline atual usa `FRAME_RET` no final desse fluxo de frame lógico. 5. a seleção do entrypoint ainda depende de configuração explícita em `FrontendSpec`, em vez de ser derivada da própria source language do PBS. Se introduzirmos `declare global`, o compiler precisará definir: 1. como globals são inicializados; 2. quando essa inicialização roda; 3. como garantir execução uma única vez; 4. como conviver com um `init()` custom do usuário; 5. como detectar de forma canônica quais funções do usuário exercem os papéis de `init` e `frame`; 6. como preservar o contrato de frame lógico quando a função publicada deixar de ser a função `frame()` original do usuário. ## Contexto O estado atual do sistema é: - PBS proíbe `let` top-level e não expõe storage mutável de módulo; - `declare const` é avaliado em compile time e pode ser inlinado/foldado; - inicializadores não constantes como `new`, call sugar, `some`, `none`, `if`, `switch` e outras formas executáveis não pertencem ao modelo de `declare const`; - a VM do runtime já possui `GetGlobal` e `SetGlobal`; - o `IRBackend` executável atual modela locals, calls, jumps e literais, mas não modela globals; - o entrypoint de frame hoje é tratado como raiz do frame lógico, inclusive para o ponto final onde `FRAME_RET` é emitido; - o frontend PBS ainda depende de configuração explícita em `FrontendSpec` para saber qual callable é o entrypoint publicado; - hoje isso aparece como acoplamento a nomes/configuração que deveriam ser deduzidos pela própria linguagem. O cenário motivador é permitir globals de módulo no PBS sem exigir, nesta fase, mudança de runtime. Também queremos aproveitar essa discussão para mover a detecção de entrypoint para a source language do PBS, usando atributos explícitos: ```pbs [Init] fn init() -> void {} [Frame] fn frame() -> void {} ``` Essa direção permitiria ao frontend PBS: 1. localizar explicitamente o init do usuário; 2. localizar explicitamente o frame root do usuário; 3. montar o wrapper sintético final sem depender de configuração paralela em `FrontendSpec`; 4. eliminar, nesta linha de evolução, a configuração explícita atual de entrypoint no registry/spec do frontend. Esta agenda também cobre a extensão desse modelo para discutir: 1. se `[Init]` deve existir apenas como hook final de programa ou também como surface por módulo; 2. qual é exatamente o comportamento operacional de `[Frame]` como root lógico de frame do usuário; 3. como `[Init]` por módulo, `[Init]` final de programa, wrapper sintético e `FRAME_RET` se compõem sem ambiguidade. Isso empurra a solução para o compiler: 1. synth de init por módulo; 2. synth de wrapper do frame published entrypoint; 3. eventual símbolo privado `boot_done`; 4. redefinição do ponto onde o frame lógico realmente termina; 5. detecção de `init`/`frame` a partir de atributos de source; 6. remoção progressiva das configs explícitas atuais em `FrontendSpec`. ## Inputs Relevant inputs already present in the repository: - `docs/vm-arch/ISA_CORE.md` already exposes `GET_GLOBAL` and `SET_GLOBAL`; - `docs/compiler/pbs/specs/13. Lowering IRBackend Specification.md` currently requires a canonical executable entrypoint to be declared through `FrontendSpec`; - `docs/compiler/pbs/specs/7. Cartridge Manifest and Runtime Capabilities Specification.md` currently expects PBS v1 manifest `entrypoint` to align with frontend-declared `frame`. The discussion here must preserve compatibility with those contracts unless it explicitly proposes the propagation work needed to evolve them. ## Core Questions 1. PBS deve introduzir `declare global` como declaração top-level distinta de `declare const`? 2. `declare global` deve aceitar inicializadores executáveis como `new Vec2(...)`, calls e outras expressões lowerables? 3. O compiler deve sintetizar um module init por módulo que contenha `declare global`? 4. A inicialização deve rodar eager no boot lógico do programa ou lazy no primeiro frame? 5. Deve existir um `init()` custom do usuário que roda depois de todos os module inits e antes do primeiro `frame()`? 6. O PBS deve introduzir atributos explícitos `[Init]` e `[Frame]` para identificar as funções corretas do usuário? 7. A descoberta de entrypoint no frontend PBS deve deixar de depender de configuração explícita em `FrontendSpec`? 8. `[Init]` deve poder existir também em escopo/módulo de forma declarativa para orientar module init explícito, ou o compiler deve manter module init sempre totalmente sintético? 9. Qual é o contrato preciso de comportamento de `[Frame]` no PBS: callable obrigatório, assinatura fixa, frequência esperada e relação com o frame lógico publicado? 10. O published frame entrypoint deve passar a ser um wrapper sintético, por exemplo `__pbs_frame()`, em vez do `frame()` do usuário? 11. `FRAME_RET` deve continuar significando "fim do frame lógico" e apenas mudar de owner, saindo da função do usuário para o wrapper sintético? 12. Como o compiler deve tratar ordem topológica, dependências e ciclos entre globals de módulos distintos? 13. Qual política vale quando algum module init ou `init()` do usuário falha: retry no próximo frame, fail-fast, ou outra forma? 14. Globals exportados por `mod.barrel` devem se comportar como storage compartilhado de módulo ou como snapshot/importação por valor? ## Inputs Already Fixed Elsewhere Os seguintes pontos já parecem fixos ou fortemente estabelecidos e não devem ser contraditos nesta agenda: - a VM já suporta globals em nível de bytecode/execução; - `declare const` não é storage mutável/runtime-initialized; - o runtime já sabe executar um entrypoint published por frame; - `FRAME_RET` já é usado como marcador do fim de um frame lógico; - o frontend PBS hoje ainda carrega configuração explícita de entrypoint fora da source language; - nesta fase queremos evitar mudanças novas no runtime e concentrar a evolução no compiler. ## Decisions To Produce Como umbrella agenda, esta agenda não deve tentar fechar toda a solução normativa de uma vez. Ela deve sair com: 1. a decomposição oficial do tema em discussões derivadas; 2. a ordem canônica dessas discussões; 3. os inputs e outputs esperados de cada boundary; 4. a lista de artefatos que não podem ser editados antes do boundary anterior fechar. Depois que as discussões derivadas fecharem, o conjunto deve produzir direção suficiente para virar uma `decision` cobrindo pelo menos: 1. a surface syntax e o modelo semântico de `declare global`; 2. o modelo de bootstrap entre module init sintético, `[Init]` de programa e `[Frame]`; 3. o owner real do frame lógico publicado e o ponto correto de emissão de `FRAME_RET`; 4. a política de descoberta de entrypoint a partir da source language do PBS; 5. a política de ordenação, ciclos e falhas para globals e module init; 6. a política de imports/exports para globals entre módulos. ## Options ### Option A Adicionar `declare global`, introduzir `[Init]` e `[Frame]` como superfícies explícitas para lifecycle/entrypoint, discutir `[Init]` final vs `[Init]` por módulo, gerar module init sintético por módulo, gerar wrapper sintético de frame published entrypoint e mover o `FRAME_RET` para esse wrapper. ### Option B Adicionar `declare global`, mas exigir init totalmente estático ou restrito, sem `init()` custom do usuário e sem wrapper published separado do `frame()` atual. ### Option C Não adicionar `declare global` agora; manter apenas `declare const` e postergar a discussão até existir um modelo maior de bootstrap/program lifecycle. ### Option D Adicionar `declare global`, mas exigir lazy materialization no primeiro acesso em vez de module init explícito por ordem topológica. ## Tradeoffs ### Option A - Prós: - modelo explícito e fácil de explicar; - acomoda `declare global` com inicializadores realmente executáveis; - faz o PBS declarar na própria linguagem quais são os callables de `init` e `frame`; - abre espaço para discutir de forma unificada `init` por módulo, `init` final e root de frame; - permite `init()` custom do usuário sem mudar o runtime; - preserva o significado de `FRAME_RET` como fim do frame lógico; - remove um acoplamento indesejado entre frontend PBS e configuração manual de entrypoint em `FrontendSpec`. - Contras: - exige nova modelagem no compiler para globals, init synthesis e published frame wrapper; - exige regras novas de atributo e validação de unicidade para `[Init]` e `[Frame]`; - obriga decisão clara sobre ordem, ciclos e falhas; - muda a relação atual entre `frame()` do usuário e entrypoint publicado. ### Option B - Prós: - escopo menor; - reduz a superfície de lifecycle; - pode evitar parte da complexidade de wrapper e boot state. - Contras: - resolve mal o caso motivador com `new Vec2(...)`; - produz uma feature de globais com restrição semântica forte demais; - deixa o `init()` do usuário para outra rodada e pode forçar redesign posterior. ### Option C - Prós: - nenhum risco imediato em pipeline/backend; - preserva o estado atual do compiler. - Contras: - não resolve o caso desejado; - mantém uma lacuna entre capacidade da VM e surface language do PBS; - posterga um problema arquitetural que já apareceu de forma concreta. ### Option D - Prós: - evita bootstrap eager explícito; - pode reduzir custo de init em módulos não usados. - Contras: - complica determinismo e observabilidade; - torna mais difícil explicar dependências entre módulos; - aumenta risco semântico para reentrância, ciclos e ordem de efeitos; - parece desnecessariamente sofisticado para v1. ## Recommendation Seguir com a **Option A**. Direção recomendada para discussão: 1. introduzir `declare global` como nova declaração top-level distinta de `declare const`; 2. permitir inicializadores executáveis lowerables, incluindo `new` e calls compatíveis com o modelo de lowering executável; 3. sintetizar um module init por módulo owner de globals; 4. ordenar os module inits de forma determinística e topológica; 5. introduzir `[Init]` e `[Frame]` como superfícies explícitas de detecção do init/frame do usuário; 6. remover da evolução do PBS a dependência de configuração explícita de entrypoint em `FrontendSpec`, migrando a seleção para a análise da source language; 7. discutir explicitamente se `[Init]` por módulo será uma surface do usuário ou se módulo continuará com init apenas sintético; 8. permitir um `init()` custom opcional do usuário, executado depois de todos os module inits; 9. publicar um wrapper sintético de frame, por exemplo `__pbs_frame()`, como verdadeiro frame root; 10. tratar `frame()` do usuário como callable normal invocado por esse wrapper; 11. manter `FRAME_RET` como marcador do fim do frame lógico, mas emitido no wrapper sintético publicado em vez de no `frame()` do usuário; 12. manter toda a primeira fase restrita ao compiler e ao backend pipeline, sem novos requisitos para o runtime além dos contratos já existentes. Essa recomendação ainda deixa alguns pontos para fechamento na `decision`, mas já estabelece um shape arquitetural coerente: - storage global pertence ao módulo owner; - bootstrap observável pertence ao compiler, não ao runtime; - `frame()` do usuário deixa de ser o entrypoint publicado e passa a ser o root lógico invocado pelo wrapper; - `FRAME_RET` continua significando fim do frame lógico, apenas com novo owner sintético; - a seleção de entrypoint deixa de ser configuração paralela e vira semântica explícita da linguagem. ## Open Questions 1. O nome surface deve ser exatamente `declare global`, ou outra forma top-level? 2. Globals devem exigir initializer obrigatório em v1, ou existirão shells reservados parecidos com builtin const? 3. `[Init]` e `[Frame]` devem ser atributos reservados do PBS ou outra forma de marker surface? 4. `[Init]` deve exigir assinatura fixa `fn init() -> void`? 5. `[Frame]` deve exigir assinatura fixa `fn frame() -> void`? 6. Deve existir no máximo um `[Init]` e um `[Frame]` por programa, por módulo owner, ou por outro escopo? 7. Module init deve permanecer sempre sintético em v1, ou o usuário pode anotar hooks por módulo em alguma forma futura? 8. A política de falha de init deve ser fail-fast definitivo no boot, ou existe algum caso legítimo para retry controlado? 9. Reexport de globals entre módulos deve preservar identidade de storage do owner original ou materializar aliases/import bindings sem storage próprio? 10. O manifest `entrypoint` deve continuar expondo `frame` por compatibilidade nominal ou passar a refletir o símbolo sintético publicado? ## Main Difficulties Os principais pontos de dificuldade desta agenda não são sintáticos; eles estão na composição entre contratos já existentes. ### 1. `declare global` colide com o recorte atual de `declare const` Hoje a semântica estática do PBS fixa que: - `declare const` entra no value namespace; - `declare const` não materializa storage mutável runtime; - inicializadores de `declare const` pertencem a um subset estritamente compile-time; - dependências entre `declare const` são acíclicas e resolvidas por análise de dependência, não por ordem textual. Introduzir `declare global` exige decidir o que é reaproveitado desse modelo e o que deixa de valer: - namespace e visibilidade podem reaproveitar parte do modelo atual; - constant evaluation não pode ser reutilizada como está; - o modelo de dependência deixa de ser apenas compile-time e passa a produzir efeitos runtime. ### 2. A surface de atributos hoje tem um conjunto reservado fechado O PBS já trata atributos como metadata compile-time com lowering explícito apenas quando outra spec define esse efeito. Isso é favorável para `[Init]` e `[Frame]`, mas cria trabalho em três frentes: - reservar novos atributos no conjunto normativo; - definir targets válidos, unicidade e diagnóstico; - definir o lowering sem deixar atributos "soltos" como metadata sem efeito operacional claro. ### 3. O entrypoint publicado hoje ainda está acoplado ao `FrontendSpec` Existe uma obrigação atual em `13. Lowering IRBackend Specification.md` para o frontend declarar um `EntrypointRef` canônico. A agenda 19 quer mover a descoberta para a source language, mas isso abre uma transição delicada: - PBS precisa derivar esse `EntrypointRef` da source language; - o contrato de `IRBackend` não deve perder determinismo; - a migração não pode deixar coexistirem por muito tempo duas autoridades independentes para entrypoint. ### 4. O manifest ainda assume `frame` como callable publicado `7. Cartridge Manifest and Runtime Capabilities Specification.md` hoje sugere alinhamento nominal entre manifest `entrypoint` e callable `frame`. Se o compiler publicar `__pbs_frame()`: - ou o manifest passa a refletir o símbolo sintético real; - ou o manifest preserva um nome lógico enquanto o símbolo real do artefato muda; - ou a pipeline passa a distinguir entrypoint lógico e entrypoint físico. Sem fechar isso, a solução de wrapper fica tecnicamente incompleta. ### 5. `FRAME_RET` hoje coincide com o fim do callable do usuário O ponto difícil não é só "mover um opcode". É redefinir qual callable delimita semanticamente o frame lógico: - `frame()` do usuário continua sendo apenas código de frame; - o wrapper sintético vira o owner do frame published entrypoint; - `FRAME_RET` continua com o mesmo significado semântico, mas sua posição material muda. Isso afeta lowering, testes de conformance e a forma de explicar o modelo da linguagem. ### 6. Globals intermodulares introduzem um problema novo de identidade e ordem Hoje `declare const` exportado via `mod.barrel` é simples porque não há storage mutável compartilhado. Com `declare global`, a agenda precisa fechar: - quem é o owner real do storage; - o que um import recebe: binding para o owner ou cópia/snapshot; - como ciclos entre módulos são detectados; - se init pode ler globals de módulos predecessores; - qual é a ordem determinística entre módulos quando há efeitos de inicialização. ### 7. A política de falha deixa de ser apenas rejeição de build Hoje boa parte do pipeline falha antes da emissão. Com module init e `init()` do usuário, surge um problema runtime-observable: - o que acontece quando o boot parcial falha; - se o programa entra em estado terminal; - se existe retry; - como isso se relaciona com o fato de `FRAME_SYNC` permanecer o safepoint normativo. ## Work Boundaries Para manter a agenda executável e evitar mistura de artefatos, o trabalho pode ser separado nos seguintes boundaries. ### Boundary A. Surface Language and AST Owner principal: syntax + AST. Inclui: - gramática de `declare global`; - superfície de atributos `[Init]` e `[Frame]`; - targets permitidos desses atributos; - novos nós ou flags obrigatórios no AST para globals e lifecycle markers. Pergunta de fechamento: - o parser apenas aceita as superfícies ou já impõe parte das restrições estruturais de target/shape? ### Boundary B. Static Semantics and Linking Owner principal: static semantics + linking. Inclui: - namespace e visibilidade de `declare global`; - regras de initializer obrigatório ou opcional; - compatibilidade de tipo do initializer; - unicidade e assinatura válida para `[Init]` e `[Frame]`; - regras de import/export/barrel para globals; - detecção de ciclos de dependência entre globals; - política de identidade do storage através de imports e reexports. Pergunta de fechamento: - globals entram no mesmo value namespace de `let`/`declare const` ou exigem distinção semântica adicional apesar do namespace compartilhado? ### Boundary C. Dynamic Semantics and Lifecycle Model Owner principal: dynamic semantics. Inclui: - ordem observável entre module init, `[Init]` de programa e `[Frame]`; - definição de boot one-shot; - política de falha de init; - contrato semântico de `[Frame]` como raiz lógica do tick/frame do usuário; - relação entre frame lógico do usuário e entrypoint efetivamente publicado. Pergunta de fechamento: - o programa tem dois conceitos distintos, `logical frame root` e `published runtime entrypoint`, ou a spec tenta esconder essa distinção do usuário? ### Boundary D. IR and Backend Lowering Owner principal: lowering executável. Inclui: - representação de globals no `IRBackend` ou boundary imediatamente anterior; - synthesis de module init; - synthesis de wrapper published entrypoint; - materialização do guard one-shot de boot; - reposicionamento do `FRAME_RET`; - preservação do `EntrypointRef` canônico para o restante do backend. Pergunta de fechamento: - globals entram como primitivo explícito no IR ou aparecem apenas em lowering posterior antes de IRVM/bytecode? ### Boundary E. Artifact and Manifest Publication Owner principal: artifact contracts. Inclui: - nome do entrypoint exposto no manifest; - relação entre callable do usuário, símbolo sintético e entrypoint published; - compatibilidade com o contrato atual do cartridge manifest; - possíveis ajustes na leitura de tooling sobre qual callable é o entrypoint "real". Pergunta de fechamento: - o manifest publica identidade lógica da linguagem ou identidade física do artefato executável? ### Boundary F. Diagnostics and Conformance Owner principal: diagnostics + fixture model. Inclui: - diagnósticos para target inválido de `[Init]` e `[Frame]`; - duplicidade ou ausência de markers obrigatórios; - initializer inválido de `declare global`; - ciclos intra/inter-módulo; - imports/reexports ilegais de globals; - fixture coverage para init ordering, wrapper published entrypoint e `FRAME_RET`. Pergunta de fechamento: - quais erros pertencem ao frontend/linking e quais só podem ser cobertos por fixtures de toolchain completo? ## Discussion Order As discussões derivadas desta umbrella agenda devem seguir a ordem abaixo. O objetivo da ordem é simples: - fechar primeiro autoridade semântica e surface; - depois fechar comportamento observável; - só então descer para lowering, artefato publicado e conformance. ### Stage 1. Globals Surface and Static Identity Boundary owner: - `Boundary A. Surface Language and AST` - `Boundary B. Static Semantics and Linking` Esta discussão deve fechar primeiro porque todas as outras dependem da definição do que é um global no PBS. Ela precisa decidir: - a forma exata de `declare global`; - initializer obrigatório ou opcional; - namespace, visibilidade e barrel/export/import; - identidade do storage owner; - política de reexport; - ciclos e dependências entre globals em nível de linking/static semantics. Sem esse fechamento: - lifecycle ainda não sabe o que precisa inicializar; - lowering ainda não sabe que entidade precisa materializar; - manifest ainda não sabe se está publicando símbolos que dependem de storage global importado. ### Stage 2. Lifecycle Markers and Program Bootstrap Semantics Boundary owner: - `Boundary C. Dynamic Semantics and Lifecycle Model` Esta discussão vem depois de Stage 1 porque init e frame só fazem sentido quando o modelo de globals já estiver fixado. Ela precisa decidir: - se `[Init]` e `[Frame]` entram como superfícies oficiais; - unicidade e assinatura desses markers; - ordem entre module init, `[Init]` de programa e `[Frame]`; - política de boot one-shot; - política de falha; - papel semântico exato de `frame()` do usuário. Sem esse fechamento: - o wrapper sintético não tem contrato observável estável; - `FRAME_RET` não tem owner definido; - qualquer modelagem de IR corre risco de materializar o comportamento errado. ### Stage 3. Published Entrypoint, Wrapper Ownership, and `FRAME_RET` Boundary owner: - `Boundary C. Dynamic Semantics and Lifecycle Model` - `Boundary D. IR and Backend Lowering` - `Boundary E. Artifact and Manifest Publication` Esta discussão depende de Stage 2 porque ela não decide mais "o que é lifecycle"; ela decide como lifecycle é publicado. Ela precisa decidir: - se o published entrypoint é um wrapper sintético; - qual é a relação entre `frame()` do usuário e esse wrapper; - onde `FRAME_RET` passa a ser emitido; - se o manifest expõe entrypoint lógico, entrypoint físico ou ambos; - como o `EntrypointRef` do frontend continua determinístico durante a transição. Sem esse fechamento: - não existe contrato estável para lowering final; - specs de manifest e `IRBackend` ficam em tensão; - o tooling pode continuar com duas autoridades concorrentes para entrypoint. ### Stage 4. IR Representation and Lowering Mechanics Boundary owner: - `Boundary D. IR and Backend Lowering` Esta discussão vem depois de Stage 3 porque a forma do IR depende do que exatamente precisa ser publicado e executado. Ela precisa decidir: - se globals entram como primitivo explícito do IR ou apenas em lowering posterior; - como module init é representado; - como o guard de boot é materializado; - como o wrapper published entrypoint é emitido; - como `FRAME_RET` é reposicionado mantendo o mesmo significado. Sem esse fechamento: - código pode ser implementado cedo demais sobre contratos ainda móveis; - a propagação para specs gerais de lowering fica prematura; - testes de backend podem congelar um shape errado. ### Stage 5. Diagnostics, Gates, and Conformance Coverage Boundary owner: - `Boundary F. Diagnostics and Conformance` Esta discussão deve vir por último porque ela consolida o que as anteriores já fixaram. Ela precisa decidir: - catálogo mínimo de diagnósticos novos; - divisão entre erro de syntax/AST, linking/static semantics, lowering e toolchain; - fixtures obrigatórios para globals, lifecycle, wrapper e entrypoint publication; - critérios de aceite para a migração de `FrontendSpec` entrypoint config para source-derived entrypoint discovery. Fazer isso antes cria dois riscos: - congelar diagnósticos para regras ainda instáveis; - ou escrever fixtures de conformance que depois precisam ser reabertas por mudança arquitetural. ## Derived Agenda Outline Se quisermos quebrar a umbrella agenda em agendas filhas, a ordem recomendada é: 1. `19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda` 2. `19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda` 3. `19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda` 4. `19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda` 5. `19.5. Diagnostics, Manifest Propagation, and Conformance Coverage Agenda` Cada agenda filha deve declarar explicitamente: - que deriva da umbrella agenda `19`; - quais stages anteriores já são input fixo; - e quais outputs ela precisa entregar para a agenda seguinte. ## Boundary Locking Rules Para evitar que discussões posteriores prejudiquem as anteriores, esta umbrella agenda fixa as seguintes regras de sequenciamento: 1. `19.2` não redefine surface syntax ou identidade de globals já fechadas em `19.1`. 2. `19.3` não redefine o significado semântico de `[Init]`, `[Frame]` ou boot ordering já fechados em `19.2`. 3. `19.4` não reabre decisões de linguagem ou de lifecycle; ela apenas escolhe a representação e o mecanismo de lowering compatíveis com elas. 4. `19.5` não reabre arquitetura; ela consolida diagnostics, manifest propagation e coverage. 5. Qualquer ponto que force reabertura de stage anterior deve voltar explicitamente para a agenda filha owner correta, em vez de ser resolvido informalmente na etapa posterior. ## Likely Propagation Targets Mesmo sem virar `decision` ainda, esta agenda já mostra impacto provável nos seguintes artefatos. ### PBS Specs - `3. Core Syntax Specification.md` - `4. Static Semantics Specification.md` - `9. Dynamic Semantics Specification.md` - `11. AST Specification.md` - `12. Diagnostics Specification.md` - `13. Lowering IRBackend Specification.md` - `7. Cartridge Manifest and Runtime Capabilities Specification.md` ### Cross-Domain / VM Architecture - `docs/vm-arch/ISA_CORE.md` provavelmente não precisa mudar em capability, mas precisa ser referenciado explicitamente como base de `GET_GLOBAL`/`SET_GLOBAL`; - specs gerais de lowering fora de `docs/compiler/pbs` podem precisar propagação posterior se `IRBackend` ganhar representação explícita de globals ou novo contrato para entrypoint published. ### Compiler / Implementation Areas - parser e AST model; - linking/resolution; - static semantics; - IR model do frontend PBS; - executable lowering para `IRBackend` e `IRVM`; - montagem do manifest/cartridge metadata; - suites de fixture de frontend, lowering e toolchain. ## Boundary Risks Se os boundaries acima não forem respeitados, os riscos mais prováveis são: 1. criar `declare global` como açúcar superficial sem lifecycle coerente; 2. introduzir `[Init]` e `[Frame]` sem autoridade clara sobre `FrontendSpec`; 3. mover `FRAME_RET` sem redefinir com precisão o owner do frame lógico; 4. resolver globals intra-módulo mas deixar imports/reexports semanticamente ambíguos; 5. fechar a solução do compiler sem fechar o contrato do manifest; 6. misturar nesta agenda decisões de produto/runtime que deveriam continuar fora de escopo. ## Expected Spec Material Se esta agenda virar `decision`, a propagação esperada deve atingir pelo menos: - spec de declarações top-level do PBS para introduzir `declare global`; - spec de lifecycle/entrypoint attributes para `[Init]` e `[Frame]`; - spec de lowering executável/`IRBackend` para module init synthesis, wrapper published entrypoint e ownership de `FRAME_RET`; - spec de cartridge manifest para esclarecer a relação entre entrypoint lógico do usuário e entrypoint publicado no artefato; - diagnósticos de validação para unicidade, assinatura inválida, ciclos de init e uso incorreto de globals. ## Non-Goals Esta agenda não deve: 1. redesenhar o runtime ou introduzir novas instruções de VM; 2. escrever a spec normativa final de globals e lifecycle; 3. redefinir o modelo geral de módulos do compiler fora do necessário para globals/init; 4. resolver todos os possíveis hooks futuros de programa além de `[Init]` e `[Frame]`; 5. discutir otimizações de performance de init além do necessário para garantir semântica determinística. ## Next Step Usar esta agenda como parent reference e abrir as agendas filhas na ordem abaixo: 1. `19.1. PBS Globals Surface, Identity, and Module Boundaries Agenda` 2. `19.2. PBS Lifecycle Markers, Program Init, and Frame Root Semantics Agenda` 3. `19.3. Published Entrypoint, Synthetic Wrapper, and FRAME_RET Ownership Agenda` 4. `19.4. Globals and Lifecycle Lowering to IRBackend/IRVM Agenda` 5. `19.5. Diagnostics, Manifest Propagation, and Conformance Coverage Agenda` Somente depois do fechamento dessas agendas derivadas esta linha deve virar uma `decision` consolidada em `docs/compiler/pbs/decisions`.