--- id: PLN-0149 ticket: foreground-stack-game-pause-shell-vm-backed title: Move VM Runtime State Into VM Sessions status: done created: 2026-07-04 ref_decisions: [DEC-0038] tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture] --- ## Briefing DEC-0038 states that mutable VM context must belong to the VM-backed process session, not to firmware or a single global runtime slot. The current split has `Firmware.vm: VirtualMachine` and `SystemOS.vm_runtime: VirtualMachineRuntime`, which makes a suspended Game vulnerable to VM-backed Shell execution. This plan migrates mutable per-application VM runtime state into the session model introduced by PLN-0148 while keeping global OS services global. ## Objective Make each VM session own the state needed to suspend and later resume that VM-backed process without being overwritten by another VM-backed process. ## Dependencies - Source decision: DEC-0038. - Requires PLN-0148. - Must precede full cartridge-loading and scheduler migration in PLN-0150 and PLN-0151. ## Scope - Classify `VirtualMachineRuntime` fields into session-owned versus global OS-owned state. - Move session-owned fields into the `VmSession` context. - Keep global services in `SystemOS`, including: - `LogService`; - process/task/window managers; - foreground stack; - durable `MemcardService`; - global render publication authority or worker coordination that must remain host-facing. - Treat these as session-owned unless proven otherwise during implementation: - `VirtualMachine`; - current cartridge identity; - frame and tick counters; - lifecycle delivery bookkeeping; - crash report for that session; - pause/debug flags that apply to that session; - per-session open files, handles, and staging state used by VM syscalls. - Keep durable memcard contents keyed by `app_id`; do not turn save data into session-private durable storage. - Update `VmFacade` and VM runtime helpers so callers can operate on a selected session. ## Non-Goals - Do not redesign render workers beyond separating session-local render command state from global presentation authority. - Do not implement background execution. - Do not change syscall semantics except where required to route state through the active session. - Do not remove host debugger features; preserve or adapt their access path. ## Execution Method 1. Add an internal field-by-field classification comment or test-only assertion near `VirtualMachineRuntime` before moving fields. 2. Introduce a session runtime/context type in the VM session module or by splitting `VirtualMachineRuntime` into: - session-local runtime; - global render/log/runtime services. 3. Move `VirtualMachine` ownership from firmware placeholder/session stub into the session context. 4. Move per-cartridge and per-frame state from `SystemOS.vm_runtime` into the session context. 5. Move `open_files`, `next_handle`, and VM syscall staging state out of global `SystemOS` if they are VM-session specific. 6. Update `VmRuntimeHost` in `crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs` to receive session-local state plus references to required global services. 7. Update `VmFacade` in `crates/console/prometeu-system/src/os/facades/vm.rs` with explicit session-targeted methods. 8. Preserve temporary compatibility methods only where needed for existing host/debugger code, and mark them as active-session views rather than canonical global ownership. 9. Add tests proving two VM sessions can hold different app identity and counters at the same time. ## Acceptance Criteria - No canonical VM state lives in `Firmware`. - `SystemOS` can hold at least two VM sessions with independent `VirtualMachine` and per-session runtime state. - VM session A and VM session B can have different `app_id`, title, frame counters, lifecycle delivery history, crash report, open file handles, and debug pause state. - Durable memcard contents remain shared by `app_id` according to the existing memcard contract. - Global render ownership remains controlled by SystemOS/host-facing runtime services, not by individual sessions. - Existing `prometeu-system` VM runtime tests still pass after adapting their setup. ## Tests - `cargo test -p prometeu-system` - `cargo test -p prometeu-firmware` - Add tests for: - independent session app identity; - independent tick/logical-frame counters; - independent lifecycle delivery bookkeeping; - VM Shell session initialization does not mutate resident Game session identity; - session-scoped file handles do not collide across sessions. ## Affected Artifacts - `crates/console/prometeu-system/src/services/vm_runtime/` - VM session module introduced by PLN-0148 - `crates/console/prometeu-system/src/os/facades/vm.rs` - `crates/console/prometeu-system/src/os/system_os.rs` - `crates/console/prometeu-system/src/os/facades/fs.rs` - `crates/console/prometeu-firmware/src/firmware/firmware.rs` - `crates/host/prometeu-host-desktop-winit/src/debugger.rs` - `crates/host/prometeu-host-desktop-winit/src/runner.rs` - `crates/host/prometeu-host-desktop-winit/src/stats.rs`