--- id: DEC-0038 ticket: foreground-stack-game-pause-shell-vm-backed title: VM Session Ownership for VM-Backed Processes status: accepted created: 2026-07-04 ref_agenda: AGD-0046 tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture] --- ## Status Open for review. ## Contexto `DEC-0037` established the foreground stack and Game pause contract for `Game -> Home/Shell -> same Game`. It requires a suspended resident Game to stop receiving normal gameplay ticks, input, and frame pacing while remaining resident for later resume. The current implementation works for native Shell apps because native Shell apps do not use the VM. It does not fully support VM-backed Shell coexistence: `Firmware` owns a single global `VirtualMachine` (`Firmware.vm`), so loading a VM-backed Shell can overwrite the suspended Game context that should remain resident. `AGD-0046` closes this gap by separating VM execution context ownership from foreground ownership. A foreground owner decides who receives visual/input authority. A VM execution context decides where PC, stack, heap, globals, handles, cartridge identity, lifecycle delivery state, and VM-scoped runtime state live. ## Decisao PROMETEU MUST make VM execution context session-owned for VM-backed processes. Every VM-backed process MUST have its own `VmSession` or equivalent session-owned context. A VM-backed Game and a VM-backed Shell MUST NOT share the same mutable `VirtualMachine` instance, stack, heap, PC, globals, open handles, cartridge identity, or VM-scoped lifecycle state. `Firmware.vm` MUST NOT remain the canonical owner of all VM-backed app context. Firmware MAY continue to orchestrate macro states such as loading, Home, Shell, and GameRunning, but it MUST delegate VM session creation, activation, lookup, and ticking to SystemOS/session services. For v1, the system MAY still enforce: - at most one resident Game; - at most one foreground Shell; - no Game-to-Game switching; - no general background execution. Those restrictions MUST NOT be implemented by relying on a single global VM context. They must be expressed as lifecycle/session policy. Each VM-backed Shell MUST receive its own VM session. If future Shell persistence allows more than one Shell app to remain in memory, each retained VM-backed Shell MUST still have distinct mutable VM context. A suspended resident Game MUST preserve its VM session. Suspension means the session is not eligible for normal foreground ticks, normal Game input, or normal frame pacing. It does not mean serializing, deleting, or overwriting the VM context. Foreground ownership and execution eligibility MUST be separate concepts: - foreground ownership controls visual owner, primary input, render ownership, and normal foreground frame pacing; - execution eligibility controls which sessions may receive ticks or restricted callbacks while not foreground. Background execution, including music players or background services, is out of scope for the first implementation of this decision. However, the session model MUST be compatible with adding background-capable scheduling soon. The initial model MUST NOT bake in assumptions that only the foreground session can ever be eligible to execute. Render ownership MUST remain a global SystemOS authority. VM sessions may produce render submissions, but they MUST NOT decide whether those submissions can be presented. SystemOS/render ownership policy remains responsible for active owner, epoch/generation validity, stale submission rejection, and final publication authority. `LoadCartridgeStep` MUST stop initializing a global firmware VM directly as the long-term model. Cartridge load/activation MUST be delegated to a sessions or VM-session facade that can create a new VM session, activate an existing VM session, or reject an unsupported transition according to lifecycle policy. ## Rationale The foreground stack is already task/process-oriented. VM execution context must follow the same ownership model. Otherwise the system can mark a Game as resident and suspended while the only real VM context has already been reused for a Shell. Session ownership solves the actual coexistence problem without requiring VM snapshot/restore. A suspended Game is simply a live session that is not scheduled for normal ticks. A VM-backed Shell is another session with its own mutable state. Keeping background execution out of the first implementation avoids expanding this work into a general scheduler. At the same time, making execution eligibility separate from foreground ownership prevents an immediate future background audio/player feature from requiring another foundational refactor. Keeping render ownership global preserves the contract from `DEC-0037` and the render ownership model from `DSC-0040`: sessions can generate frames, but only the current foreground/render owner can publish valid current-epoch output. ## Invariantes / Contrato - VM-backed mutable execution state is owned by a VM session, not by a global firmware VM. - A VM-backed Game and VM-backed Shell never share mutable VM context. - A suspended resident Game retains its VM session. - Suspension prevents normal foreground Game ticks/input/frame pacing; it does not destroy or overwrite VM state. - Native Shell apps do not require VM sessions. - VM-backed Shell apps always require VM sessions. - Each VM-backed Shell gets its own mutable VM session. - Foreground ownership and execution eligibility are distinct. - General background execution is out of scope for the initial implementation, but the model must support adding it without replacing session ownership. - SystemOS remains lifecycle and render ownership authority. - Render ownership and stale frame rejection remain global policy, not per-VM session policy. - Cartridge load/activation must go through session services rather than initializing one global firmware VM. - V1 restrictions on one resident Game and one foreground Shell remain policy, not a consequence of single-VM storage. ## Impactos - **Runtime / SystemOS:** add a VM session model or equivalent service that stores VM-backed process execution context and maps it to task/process lifecycle. - **Firmware:** remove `Firmware.vm` as the canonical VM context owner for all apps. Firmware should request session creation/activation/tick from SystemOS. - **VM:** support multiple distinct `VirtualMachine` instances or equivalent isolated VM contexts in one OS lifetime. - **Lifecycle:** task/process states must control session scheduling eligibility without conflating foreground ownership with future background execution. - **Hub / Shell:** VM-backed Shell load must create or activate a Shell VM session without overwriting a resident Game session. - **Game:** Game pause/suspend/resume must preserve the Game VM session and deliver lifecycle events to that session. - **Renderer:** render manager stays global and validates ownership/epoch for submissions produced by sessions. - **FS / Memcard / Assets:** mutable handles and per-app runtime handles must be evaluated for session scoping. Durable memcard/app data can remain keyed by `app_id`; open handles and staging state should not accidentally leak across sessions. - **Tests:** add coverage proving VM-backed Shell creation does not overwrite a suspended Game session, and that only eligible sessions tick. ## Alternativas Descartadas - **Keep one global firmware VM and block VM-backed Shell when a Game is resident:** rejected because it leaves `DEC-0037` incomplete and creates divergent Shell behavior. - **Serialize/snapshot the Game VM on suspension:** rejected because snapshot correctness is harder than needed for v1 and would include VM, handles, render state, assets, and side effects. - **Hard-code two VM slots (`game_vm`, `shell_vm`):** rejected as a permanent model because it encodes a short-term limit as architecture. It may only be acceptable as an internal stepping stone if represented through the same session abstraction. - **Treat background-capable apps as hidden foreground owners:** rejected because it would violate foreground ownership semantics and make render/input authority ambiguous. ## Referencias - Source agenda: `AGD-0046` - Foreground stack and Game pause contract: `DEC-0037` - Runtime mode separation: `DSC-0031` - SystemOS lifecycle/process/task authority: `DSC-0032` - VM render parallel execution boundary: `DSC-0040` - Future Game-to-Game switching: `DSC-0043` ## Propagacao Necessaria - Add implementation plans for introducing VM sessions and moving VM context out of `Firmware`. - Add implementation plans for separating VM-scoped runtime state from global SystemOS/render state. - Update runtime/firmware specs to describe session-owned VM context and the distinction between foreground ownership and execution eligibility. - Update tests for Game resident suspension, VM-backed Shell creation, and session isolation. - Keep future background execution as out of scope for first implementation, but document that the model must support background-capable scheduling. ## Revision Log - 2026-07-04: Initial decision draft from `AGD-0046`.