--- 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.