123 lines
5.1 KiB
Markdown
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: done
|
|
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`
|