prometeu-runtime/discussion/workflow/agendas/AGD-0046-vm-context-ownership-for-resident-game-and-vm-backed-shell.md

187 lines
9.0 KiB
Markdown

---
id: AGD-0046
ticket: foreground-stack-game-pause-shell-vm-backed
title: VM Context Ownership for Resident Game and VM-Backed Shell
status: accepted
created: 2026-07-04
resolved:
decision: DEC-0038
tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture]
---
## Contexto
`DEC-0037` define que o v1 deve suportar o fluxo `Game -> Home/Shell -> same
Game`, com o Game residente pausado/suspenso enquanto Hub ou Shell possuem o
foreground. A implementacao atual ja impede que Shell nativo ticke o Game
suspenso, porque Shell nativo nao usa a VM.
A lacuna aparece quando o Shell tambem eh VM-backed. Hoje `Firmware` possui um
unico `VirtualMachine` global (`Firmware.vm`). O Game residente e um Shell
VM-backed competem por esse mesmo contexto. Se o Shell VM-backed inicializa uma
nova cartridge nesse objeto, ele sobrescreve o contexto do Game que deveria
permanecer residente/suspenso.
Isso significa que o modelo de foreground/task/process ja avancou, mas o modelo
de contexto VM ainda esta acoplado ao firmware global.
## Problema
Precisamos decidir onde vive o contexto de execucao VM quando existem, ao mesmo
tempo, um Game residente suspenso e um Shell VM-backed foreground.
O problema nao eh apenas pausar ticks. Para coexistencia real, cada VM-backed
process precisa preservar seu proprio estado: PC, stack, heap, globals,
cartridge identity, runtime services escopados, render ownership metadata e
eventos lifecycle pendentes.
Enquanto `Firmware.vm` for unico, "suspender" um Game VM nao preserva o
contexto se outra cartridge VM-backed for carregada.
## Pontos Criticos
- `DEC-0037` diz que um Game suspenso nao recebe ticks/input/frame pacing, mas
continua residente para voltar ao mesmo Game.
- Shell nativo nao precisa de VM context proprio, mas Shell VM-backed precisa.
- `SystemOS` ja eh autoridade de lifecycle/process/task, entao eh candidato
natural para possuir ou localizar contextos VM por sessao.
- `Firmware` deve orquestrar macro estados, mas nao deveria ser dono unico do
contexto de todos os processos VM-backed.
- `VirtualMachineRuntime` contem estado atualmente misto: identidade da
cartridge atual, render manager, lifecycle delivery, fs/memcard/open handles
e telemetria. Precisamos separar o que eh global do OS do que eh por sessao
VM-backed.
- A solucao deve preservar a restricao v1: no maximo um Game residente e no
maximo um Shell foreground. Ela nao deve abrir multitasking geral.
- Game-to-Game switching continua fora desta agenda e pertence a `DSC-0043`.
## Opcoes
### Opcao A - Manter VM global no Firmware e bloquear Shell VM-backed com Game residente
- **Abordagem:** documentar que Shell VM-backed nao pode abrir enquanto um Game
VM esta residente; apenas Shell nativo coexiste com Game suspenso.
- **Pro:** menor implementacao imediata.
- **Contra:** contradiz a intencao de coexistencia de VM-backed Shell em
`DEC-0037` e deixa a arquitetura incompleta.
- **Manutenibilidade:** baixa, porque o sistema teria regras diferentes para
Shell nativo e Shell VM-backed sem uma fronteira clara de sessao.
### Opcao B - Serializar o Game VM ao suspender e restaurar ao resumir
- **Abordagem:** ao suspender Game, extrair snapshot do `VirtualMachine` e do
runtime associado; ao resumir, restaurar snapshot depois do Shell VM-backed.
- **Pro:** preserva a ideia de um unico VM executor ativo.
- **Contra:** exige serializacao profunda e correta de todo o estado VM/runtime,
incluindo handles, assets, render state e side effects. Isso eh muito mais
complexo que a necessidade v1.
- **Manutenibilidade:** baixa a media; snapshots viram contrato dificil e
fragil antes de termos necessidade de hibernacao real.
### Opcao C - Tornar o contexto VM propriedade da sessao/processo VM-backed
- **Abordagem:** cada processo VM-backed possui seu proprio `VirtualMachine` e
seu contexto runtime VM-scoped. O scheduler/firmware seleciona qual sessao
recebe tick conforme foreground/lifecycle. Game suspenso simplesmente deixa
de ser tickado, mas seu contexto permanece armazenado na sessao Game.
- **Pro:** alinha com task/process/lifecycle, suporta Game residente + Shell
VM-backed sem sobrescrever contexto, e prepara o terreno para futuras sessoes
sem implementar multitasking geral agora.
- **Contra:** exige separar estado hoje concentrado em `Firmware.vm` e
`SystemOS.vm_runtime`, decidindo o que eh global do OS e o que eh por sessao.
- **Manutenibilidade:** alta, porque a posse do contexto acompanha o processo
que executa a VM.
### Opcao D - Criar apenas dois slots VM fixos: Game VM e Shell VM
- **Abordagem:** manter um slot `game_vm` e um slot `shell_vm`, em vez de uma VM
por processo/sessao.
- **Pro:** mais simples que uma tabela geral de sessoes.
- **Contra:** codifica uma limitacao acidental. Ainda precisariamos decidir
ownership, runtime scoped state e lifecycle por slot. Pode virar refactor
duplo quando mais de um Shell ou Game switching aparecer.
- **Manutenibilidade:** media; aceitavel como stepping stone somente se modelado
internamente como sessao, nao como campos especiais permanentes.
## Sugestao / Recomendacao
Seguir a Opcao C: contexto VM deve pertencer a uma sessao/processo VM-backed,
nao ao `Firmware` global.
Para v1, a implementacao pode continuar limitada a uma sessao Game residente e
uma sessao Shell foreground, mas o modelo deve ser "session-owned VM context".
Isso permite que Shell VM-backed rode enquanto o Game fica suspenso sem perder
PC/stack/heap/estado runtime.
O firmware deve deixar de possuir a VM como estado global de todos os apps e
passar a pedir ao SystemOS/runtime scheduler o contexto VM ativo para o owner
foreground. `SystemOS` deve continuar sendo a autoridade de lifecycle; o
runtime deve separar estado VM-scoped de estado global de OS/render/telemetria
conforme necessario.
## Perguntas em Aberto
- [ ] Qual objeto deve representar a sessao VM-backed: `Process`, novo
`VmSession`, ou uma tabela separada ligada a `ProcessId`/`TaskId`?
- [ ] Quais campos de `VirtualMachineRuntime` sao por sessao VM-backed e quais
devem permanecer globais em `SystemOS`?
- [ ] O render manager fica global por foreground owner ou dentro de cada
contexto VM com handoff global?
- [ ] Handles de FS, memcard, assets e open files devem ser por sessao,
por app_id, ou globais com namespace por processo?
- [ ] Como `LoadCartridgeStep` deve mudar: criar sessao VM nova, ativar sessao
existente, ou delegar tudo para uma facade de sessions?
- [ ] Como preservar os testes e invariantes de `DEC-0037` durante a migracao
incremental sem abrir multitasking geral?
- [ ] Como processos background-capable, como um player de musica, entram no
modelo sem confundir foreground visual ownership com elegibilidade de
execucao?
- [ ] Cada Shell VM-backed deve ter uma VM propria, mesmo quando existe mais de
um Shell em memoria no futuro?
## Criterio para Encerrar
Esta agenda pode virar decision quando definirmos:
- o proprietario canonico do contexto VM;
- a fronteira entre estado VM-scoped e estado global do OS;
- como firmware seleciona/ticka a sessao VM ativa;
- como Game residente suspenso e Shell VM-backed foreground coexistem;
- quais restricoes v1 permanecem explicitamente fora de escopo.
## Discussion
- 2026-07-04: Aberta a partir da observacao de que Shell nativo coexiste com
Game suspenso, mas Shell VM-backed ainda conflita com o `Firmware.vm` unico.
- 2026-07-04: Discussao adicional separou foreground ownership de background
execution. A recomendacao atual eh que todo processo VM-backed tenha sua
propria `VmSession`; processos background-capable devem ser modelados como
sessoes com classe/politica de scheduling propria, nao como foreground owners.
## Resolution
Resolvido em 2026-07-04:
- O modelo deve seguir a Opcao C: todo processo VM-backed deve possuir uma
`VmSession` propria, ligada ao lifecycle/task/process, em vez de depender de
um `Firmware.vm` global.
- Cada Shell VM-backed deve ter sua propria sessao VM. Ele pode compartilhar a
engine/runtime e caches imutaveis, mas nao stack, heap, PC, globals, handles
ou identidade mutavel de execucao.
- O Game residente suspenso preserva seu contexto porque sua `VmSession`
continua viva; ele apenas deixa de ser elegivel para ticks normais enquanto
Hub/Shell possui foreground.
- Foreground ownership e background execution sao conceitos separados.
Foreground ownership decide input visual, render ownership e frame pacing
normal. Execution eligibility decide quais sessoes podem receber ticks sem
serem foreground.
- Background execution, como player de musica ou background services, nao entra
na primeira implementacao desta agenda. Mesmo assim, o modelo de `VmSession`
deve ser obrigatoriamente compativel com essa evolucao em um futuro proximo.
- Render ownership permanece autoridade global do SystemOS. Sessoes VM-backed
produzem frames, mas nao decidem se podem apresentar.
- `LoadCartridgeStep` nao deve inicializar uma VM global diretamente. Ele deve
delegar criacao/ativacao de sessao para uma facade de sessions/scheduler.
Esta agenda esta pronta para virar decision normativa.