prometeu-runtime/discussion/workflow/plans/PLN-0143-guarantee-cooperative-pause-budget-tick-before-suspension.md

123 lines
5.1 KiB
Markdown

---
id: PLN-0143
ticket: foreground-stack-game-pause-shell-vm-backed
title: Guarantee Cooperative Pause Budget Tick Before Suspension
status: open
created: 2026-07-04
ref_decisions: [DEC-0037]
tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture]
---
## Briefing
`DEC-0037` requires a Game-visible `Paused` event followed by a bounded
cooperative reaction budget before SystemOS imposes `Suspended`. The current
implementation uses a one-tick budget and advances it before `vm.tick` in
`GameRunningStep`, so the Game can be suspended without any runtime tick in
which it could observe or react to pause.
## Objective
Guarantee at least one deterministic VM/runtime delivery point for the Game to
observe pause before forced suspension, while preserving SystemOS authority to
suspend the Game after the budget.
## Dependencies
- Source decision: `DEC-0037`.
- Should be executed after or together with `PLN-0142`, because budget tests
must prove delivered lifecycle events, not only queued OS events.
## Scope
Included:
- Fix pause budget ordering so the pause budget cannot expire before the VM
runtime has a delivery point for `Pause`.
- Define the budget in deterministic machine ticks/frames, not wall-clock time.
- Ensure a Game receives no normal gameplay ticks after it reaches
`PausedSuspended`.
- Preserve the existing forced-suspension authority when the budget expires.
- Update tests that currently assert no VM tick occurs immediately after Home.
Excluded:
- No guest-controlled cancellation of suspension.
- No background execution after suspension.
- No extension of the pause budget based on host timing.
- No direct visual-return behavior; render restore gating remains covered by
the existing render boundary work.
## Non-Goals
- Do not add a general scheduler.
- Do not make pause cooperation mandatory for suspension.
- Do not conflate lifecycle pause with debugger pause.
## Execution Method
1. Redefine pause budget state transitions.
- What changes: `ResidentGameState::PauseRequested` must represent a state
in which one or more delivery ticks remain before `PausedSuspended`.
- How it changes: adjust `ForegroundStack::advance_pause_budget` or split it
into explicit methods such as `mark_pause_delivered` and
`advance_pause_budget_after_delivery`.
- File(s): `crates/console/prometeu-system/src/services/foreground.rs`.
2. Move budget advancement after lifecycle delivery.
- What changes: `GameRunningStep::on_update` must not suspend before the VM
runtime has a chance to receive and process the pause lifecycle event.
- How it changes: reorder the GameRunning update so the event delivery path
runs first, then the budget is advanced, and only a subsequent eligible
boundary can force suspension.
- File(s): `crates/console/prometeu-firmware/src/firmware/firmware_step_game_running.rs`,
`crates/console/prometeu-system/src/os/facades/vm.rs`.
3. Preserve no-tick-after-suspended behavior.
- What changes: once `ResidentGameState::PausedSuspended` and
`TaskState::Suspended` are reached, the Game must not receive normal ticks,
normal input, or frame pacing.
- How it changes: keep the existing early transition to Hub after suspension
expires, but ensure it occurs after the cooperative pause window rather
than before it.
- File(s): `crates/console/prometeu-firmware/src/firmware/firmware_step_game_running.rs`.
4. Update tests to match the corrected semantics.
- What changes: tests must stop asserting that the first tick after Home does
zero VM work purely because Home was requested.
- How it changes: assert that the pause event was delivered during the
cooperative window, then assert that a later deterministic tick forces
suspension and no further Game ticks occur.
- File(s): `crates/console/prometeu-firmware/src/firmware/firmware.rs`,
`crates/console/prometeu-system/src/os/system_os.rs`.
## Acceptance Criteria
- [ ] A Game receives a deterministic pause delivery point before SystemOS
suspends it.
- [ ] SystemOS still suspends the Game after the bounded budget even if the
Game does not cooperate.
- [ ] A suspended Game receives no normal gameplay ticks, normal Game input, or
frame pacing.
- [ ] Tests prove the order: Home request -> pause delivery -> budget expiry ->
suspension.
- [ ] Debugger pause behavior is unchanged.
## Tests
- Unit tests in `prometeu-system` for pause budget transitions.
- Firmware tests for non-cooperative forced suspension after at least one
delivered pause boundary.
- Regression tests proving suspended Game tick count does not advance.
- Run `cargo test -p prometeu-system foreground lifecycle`.
- Run `cargo test -p prometeu-firmware pause`.
- Run `discussion validate`.
## Affected Artifacts
- `crates/console/prometeu-system/src/services/foreground.rs`
- `crates/console/prometeu-system/src/os/facades/lifecycle.rs`
- `crates/console/prometeu-system/src/os/facades/vm.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_game_running.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware.rs`