implements PLN-0151
This commit is contained in:
parent
fa2e329d4b
commit
f26731413f
@ -37,13 +37,11 @@ impl GameRunningStep {
|
|||||||
return Some(FirmwareState::AppCrashes(AppCrashesStep { report }));
|
return Some(FirmwareState::AppCrashes(AppCrashesStep { report }));
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.os.vm().deliver_pending_game_lifecycle_events();
|
|
||||||
|
|
||||||
let pause_requested = matches!(
|
let pause_requested = matches!(
|
||||||
ctx.os.lifecycle().resident_game().map(|game| game.state),
|
ctx.os.lifecycle().resident_game().map(|game| game.state),
|
||||||
Some(ResidentGameState::PauseRequested { .. })
|
Some(ResidentGameState::PauseRequested { .. })
|
||||||
);
|
);
|
||||||
let result = ctx.os.vm().tick(ctx.vm, ctx.signals, ctx.platform);
|
let result = ctx.os.vm().tick_session(self.task_id, ctx.signals, ctx.platform);
|
||||||
|
|
||||||
if let Some(report) = result {
|
if let Some(report) = result {
|
||||||
let _ = ctx.os.lifecycle().crash_task(self.task_id, Some(&report));
|
let _ = ctx.os.lifecycle().crash_task(self.task_id, Some(&report));
|
||||||
|
|||||||
@ -76,7 +76,7 @@ impl ShellRunningStep {
|
|||||||
|
|
||||||
let outcome = match process_kind {
|
let outcome = match process_kind {
|
||||||
ProcessKind::VmShell => {
|
ProcessKind::VmShell => {
|
||||||
ctx.hub.update_shell_profile(ctx.os, ctx.vm, ctx.signals, ctx.platform)
|
ctx.hub.update_vm_shell_profile(ctx.os, self.task_id, ctx.signals, ctx.platform)
|
||||||
}
|
}
|
||||||
ProcessKind::NativeShell => ctx.hub.update_native_shell_profile(ctx.os, ctx.platform),
|
ProcessKind::NativeShell => ctx.hub.update_native_shell_profile(ctx.os, ctx.platform),
|
||||||
ProcessKind::VmGame => {
|
ProcessKind::VmGame => {
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
use crate::CrashReport;
|
use crate::CrashReport;
|
||||||
use crate::os::{GameLifecycleEvent, SystemOS};
|
use crate::os::{GameLifecycleEvent, SystemOS};
|
||||||
|
use crate::task::TaskId;
|
||||||
|
use crate::vm_session::VmSession;
|
||||||
use crate::{RenderWorkerConfig, RenderWorkerController};
|
use crate::{RenderWorkerConfig, RenderWorkerController};
|
||||||
use prometeu_hal::app_mode::AppMode;
|
use prometeu_hal::app_mode::AppMode;
|
||||||
use prometeu_hal::cartridge::Cartridge;
|
use prometeu_hal::cartridge::Cartridge;
|
||||||
@ -46,6 +48,34 @@ impl<'a> VmFacade<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tick_session(
|
||||||
|
&mut self,
|
||||||
|
task_id: TaskId,
|
||||||
|
signals: &InputSignals,
|
||||||
|
platform: &mut dyn RuntimePlatform,
|
||||||
|
) -> Option<CrashReport> {
|
||||||
|
self.deliver_pending_game_lifecycle_events_to_session(task_id);
|
||||||
|
|
||||||
|
let Some(session) = self.os.vm_sessions.for_task_mut(task_id) else {
|
||||||
|
return Some(CrashReport::VmPanic {
|
||||||
|
message: format!("task {:?} has no VM session", task_id),
|
||||||
|
pc: None,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
session.runtime.tick(
|
||||||
|
&mut self.os.log_service,
|
||||||
|
&mut self.os.fs,
|
||||||
|
&mut session.fs_state,
|
||||||
|
&mut self.os.memcard,
|
||||||
|
&mut session.open_files,
|
||||||
|
&mut session.next_handle,
|
||||||
|
&mut session.vm,
|
||||||
|
signals,
|
||||||
|
platform,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deliver_pending_game_lifecycle_events(&mut self) {
|
pub fn deliver_pending_game_lifecycle_events(&mut self) {
|
||||||
if self.os.vm_runtime.current_cartridge_app_mode == AppMode::Game {
|
if self.os.vm_runtime.current_cartridge_app_mode == AppMode::Game {
|
||||||
let resident_game_task = self.os.foreground_stack.resident_game_task();
|
let resident_game_task = self.os.foreground_stack.resident_game_task();
|
||||||
@ -65,6 +95,32 @@ impl<'a> VmFacade<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deliver_pending_game_lifecycle_events_to_session(&mut self, task_id: TaskId) {
|
||||||
|
let Some(session) = self.os.vm_sessions.for_task(task_id) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if session.runtime.current_cartridge_app_mode != AppMode::Game {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut retained = Vec::new();
|
||||||
|
let mut delivered = Vec::new();
|
||||||
|
|
||||||
|
for event in self.os.game_lifecycle_events.drain(..) {
|
||||||
|
if event.task_id == task_id {
|
||||||
|
delivered.push(event);
|
||||||
|
} else {
|
||||||
|
retained.push(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.os.game_lifecycle_events = retained;
|
||||||
|
if let Some(session) = self.os.vm_sessions.for_task_mut(task_id) {
|
||||||
|
session.runtime.deliver_game_lifecycle_events(delivered);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self, vm: &mut VirtualMachine) {
|
pub fn reset(&mut self, vm: &mut VirtualMachine) {
|
||||||
self.os.vm_runtime.reset(vm);
|
self.os.vm_runtime.reset(vm);
|
||||||
}
|
}
|
||||||
@ -78,55 +134,106 @@ impl<'a> VmFacade<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn paused(&self) -> bool {
|
pub fn paused(&self) -> bool {
|
||||||
self.os.vm_runtime.paused
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.paused)
|
||||||
|
.unwrap_or(self.os.vm_runtime.paused)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_paused(&mut self, paused: bool) {
|
pub fn set_paused(&mut self, paused: bool) {
|
||||||
|
if let Some(session) = self.active_session_mut() {
|
||||||
|
session.runtime.paused = paused;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.os.vm_runtime.paused = paused;
|
self.os.vm_runtime.paused = paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_inspection_active(&mut self, active: bool) {
|
pub fn set_inspection_active(&mut self, active: bool) {
|
||||||
|
if let Some(session) = self.active_session_mut() {
|
||||||
|
session.runtime.inspection_active = active;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.os.vm_runtime.inspection_active = active;
|
self.os.vm_runtime.inspection_active = active;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_debug_step(&mut self) {
|
pub fn request_debug_step(&mut self) {
|
||||||
|
if let Some(session) = self.active_session_mut() {
|
||||||
|
session.runtime.debug_step_request = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
self.os.vm_runtime.debug_step_request = true;
|
self.os.vm_runtime.debug_step_request = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn debug_step_requested(&self) -> bool {
|
pub fn debug_step_requested(&self) -> bool {
|
||||||
self.os.vm_runtime.debug_step_request
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.debug_step_request)
|
||||||
|
.unwrap_or(self.os.vm_runtime.debug_step_request)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logical_frame_active(&self) -> bool {
|
pub fn logical_frame_active(&self) -> bool {
|
||||||
self.os.vm_runtime.logical_frame_active
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.logical_frame_active)
|
||||||
|
.unwrap_or(self.os.vm_runtime.logical_frame_active)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delivered_game_lifecycle_events(&self) -> &[GameLifecycleEvent] {
|
pub fn delivered_game_lifecycle_events(&self) -> &[GameLifecycleEvent] {
|
||||||
self.os.vm_runtime.delivered_game_lifecycle_events()
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.delivered_game_lifecycle_events())
|
||||||
|
.unwrap_or_else(|| self.os.vm_runtime.delivered_game_lifecycle_events())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_delivered_game_lifecycle_events(&mut self) -> Vec<GameLifecycleEvent> {
|
pub fn take_delivered_game_lifecycle_events(&mut self) -> Vec<GameLifecycleEvent> {
|
||||||
|
if let Some(session) = self.active_session_mut() {
|
||||||
|
return session.runtime.take_delivered_game_lifecycle_events();
|
||||||
|
}
|
||||||
|
|
||||||
self.os.vm_runtime.take_delivered_game_lifecycle_events()
|
self.os.vm_runtime.take_delivered_game_lifecycle_events()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick_index(&self) -> u64 {
|
pub fn tick_index(&self) -> u64 {
|
||||||
self.os.vm_runtime.tick_index
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.tick_index)
|
||||||
|
.unwrap_or(self.os.vm_runtime.tick_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logical_frame_index(&self) -> u64 {
|
pub fn logical_frame_index(&self) -> u64 {
|
||||||
self.os.vm_runtime.logical_frame_index
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.logical_frame_index)
|
||||||
|
.unwrap_or(self.os.vm_runtime.logical_frame_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_frame_cpu_time_us(&self) -> u64 {
|
pub fn last_frame_cpu_time_us(&self) -> u64 {
|
||||||
self.os.vm_runtime.last_frame_cpu_time_us
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.last_frame_cpu_time_us)
|
||||||
|
.unwrap_or(self.os.vm_runtime.last_frame_cpu_time_us)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn completed_logical_frames(&self) -> u64 {
|
pub fn completed_logical_frames(&self) -> u64 {
|
||||||
self.os.vm_runtime.atomic_telemetry.completed_logical_frames.load(Ordering::Relaxed).into()
|
self.active_session()
|
||||||
|
.map(|session| {
|
||||||
|
session
|
||||||
|
.runtime
|
||||||
|
.atomic_telemetry
|
||||||
|
.completed_logical_frames
|
||||||
|
.load(Ordering::Relaxed)
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
self.os
|
||||||
|
.vm_runtime
|
||||||
|
.atomic_telemetry
|
||||||
|
.completed_logical_frames
|
||||||
|
.load(Ordering::Relaxed)
|
||||||
|
.into()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn telemetry_snapshot(&self) -> TelemetryFrame {
|
pub fn telemetry_snapshot(&self) -> TelemetryFrame {
|
||||||
self.os.vm_runtime.atomic_telemetry.snapshot()
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.atomic_telemetry.snapshot())
|
||||||
|
.unwrap_or_else(|| self.os.vm_runtime.atomic_telemetry.snapshot())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_render_worker<B, S>(&mut self, config: RenderWorkerConfig, backend: B, sink: S)
|
pub fn start_render_worker<B, S>(&mut self, config: RenderWorkerConfig, backend: B, sink: S)
|
||||||
@ -164,22 +271,54 @@ impl<'a> VmFacade<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn last_crash_report(&self) -> Option<&CrashReport> {
|
pub fn last_crash_report(&self) -> Option<&CrashReport> {
|
||||||
self.os.vm_runtime.last_crash_report.as_ref()
|
self.active_session()
|
||||||
|
.and_then(|session| session.runtime.last_crash_report.as_ref())
|
||||||
|
.or(self.os.vm_runtime.last_crash_report.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_app_id(&self) -> u32 {
|
pub fn current_app_id(&self) -> u32 {
|
||||||
self.os.vm_runtime.current_app_id
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.current_app_id)
|
||||||
|
.unwrap_or(self.os.vm_runtime.current_app_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_cartridge_title(&self) -> String {
|
pub fn current_cartridge_title(&self) -> String {
|
||||||
self.os.vm_runtime.current_cartridge_title.clone()
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.current_cartridge_title.clone())
|
||||||
|
.unwrap_or_else(|| self.os.vm_runtime.current_cartridge_title.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_cartridge_app_version(&self) -> String {
|
pub fn current_cartridge_app_version(&self) -> String {
|
||||||
self.os.vm_runtime.current_cartridge_app_version.clone()
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.current_cartridge_app_version.clone())
|
||||||
|
.unwrap_or_else(|| self.os.vm_runtime.current_cartridge_app_version.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn current_cartridge_app_mode(&self) -> AppMode {
|
pub fn current_cartridge_app_mode(&self) -> AppMode {
|
||||||
self.os.vm_runtime.current_cartridge_app_mode
|
self.active_session()
|
||||||
|
.map(|session| session.runtime.current_cartridge_app_mode)
|
||||||
|
.unwrap_or(self.os.vm_runtime.current_cartridge_app_mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn active_session(&self) -> Option<&VmSession> {
|
||||||
|
self.os
|
||||||
|
.task_manager
|
||||||
|
.foreground_task()
|
||||||
|
.and_then(|task_id| self.os.vm_sessions.for_task(task_id))
|
||||||
|
.or_else(|| {
|
||||||
|
self.os
|
||||||
|
.foreground_stack
|
||||||
|
.resident_game_task()
|
||||||
|
.and_then(|task_id| self.os.vm_sessions.for_task(task_id))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn active_session_mut(&mut self) -> Option<&mut VmSession> {
|
||||||
|
let task_id = self
|
||||||
|
.os
|
||||||
|
.task_manager
|
||||||
|
.foreground_task()
|
||||||
|
.or_else(|| self.os.foreground_stack.resident_game_task())?;
|
||||||
|
self.os.vm_sessions.for_task_mut(task_id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use crate::task::TaskId;
|
||||||
use crate::{CrashReport, GameLibrary, SystemOS};
|
use crate::{CrashReport, GameLibrary, SystemOS};
|
||||||
use prometeu_hal::color::Color;
|
use prometeu_hal::color::Color;
|
||||||
use prometeu_hal::primitives::Rect;
|
use prometeu_hal::primitives::Rect;
|
||||||
@ -194,6 +195,29 @@ impl PrometeuHub {
|
|||||||
SystemProfileUpdate { crash, action }
|
SystemProfileUpdate { crash, action }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_vm_shell_profile(
|
||||||
|
&mut self,
|
||||||
|
os: &mut SystemOS,
|
||||||
|
task_id: TaskId,
|
||||||
|
signals: &InputSignals,
|
||||||
|
platform: &mut dyn RuntimePlatform,
|
||||||
|
) -> SystemProfileUpdate {
|
||||||
|
let mut crash = None;
|
||||||
|
let mut action = self.gui_update(os, platform);
|
||||||
|
|
||||||
|
if os.windows().focused_window().is_some() {
|
||||||
|
if platform.input().pad().start().down {
|
||||||
|
action = Some(SystemProfileAction::CloseShell);
|
||||||
|
} else if action != Some(SystemProfileAction::CloseShell) {
|
||||||
|
crash = os.vm().tick_session(task_id, signals, platform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.render(os, platform);
|
||||||
|
|
||||||
|
SystemProfileUpdate { crash, action }
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update_native_shell_profile(
|
pub fn update_native_shell_profile(
|
||||||
&mut self,
|
&mut self,
|
||||||
os: &mut SystemOS,
|
os: &mut SystemOS,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
{"type":"discussion","id":"DSC-0043","status":"open","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-03","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[{"id":"AGD-0044","file":"AGD-0044-systemos-cartridge-switch-orchestrator.md","status":"open","created_at":"2026-07-03","updated_at":"2026-07-03"}],"decisions":[],"plans":[],"lessons":[]}
|
{"type":"discussion","id":"DSC-0043","status":"open","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-03","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[{"id":"AGD-0044","file":"AGD-0044-systemos-cartridge-switch-orchestrator.md","status":"open","created_at":"2026-07-03","updated_at":"2026-07-03"}],"decisions":[],"plans":[],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
|
{"type":"discussion","id":"DSC-0039","status":"abandoned","ticket":"render-pipeline-family-and-future-3d","title":"Render Pipeline Family and Future 3D","created_at":"2026-06-04","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","architecture","pipeline"],"agendas":[{"id":"AGD-0039","file":"AGD-0039-render-pipeline-family-and-future-3d.md","status":"abandoned","created_at":"2026-06-04","updated_at":"2026-06-04","_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}],"decisions":[],"plans":[],"lessons":[],"_override_reason":"User explicitly chose to close this agenda without a new decision because DSC-0038 already established enough architecture for future extension, and 3D is intentionally deferred."}
|
||||||
{"type":"discussion","id":"DSC-0040","status":"done","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-06","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0040-vm-render-parallel-execution-boundary/LSN-0048-render-workers-need-a-closed-packet-contract.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-06"}]}
|
{"type":"discussion","id":"DSC-0040","status":"done","ticket":"vm-render-parallel-execution-boundary","title":"VM and Render Parallel Execution Boundary","created_at":"2026-06-04","updated_at":"2026-06-06","tags":["runtime","renderer","vm","concurrency","architecture","perf"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0048","file":"discussion/lessons/DSC-0040-vm-render-parallel-execution-boundary/LSN-0048-render-workers-need-a-closed-packet-contract.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-06"}]}
|
||||||
{"type":"discussion","id":"DSC-0041","status":"in_progress","ticket":"foreground-stack-game-pause-shell-vm-backed","title":"Foreground Stack, Game Pause, and VM-Backed Shell Coexistence","created_at":"2026-06-05","updated_at":"2026-07-04","tags":["runtime","os","lifecycle","shell","game","vm","foreground","architecture"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-foreground-stack-game-pause-shell-vm-backed.md","status":"accepted","created_at":"2026-06-05","updated_at":"2026-07-03"},{"id":"AGD-0046","file":"AGD-0046-vm-context-ownership-for-resident-game-and-vm-backed-shell.md","status":"accepted","created_at":"2026-07-04","updated_at":"2026-07-04"}],"decisions":[{"id":"DEC-0037","file":"DEC-0037-foreground-stack-and-game-pause-contract.md","status":"accepted","created_at":"2026-07-03","updated_at":"2026-07-03","ref_agenda":"AGD-0041"},{"id":"DEC-0038","file":"DEC-0038-vm-session-ownership-for-vm-backed-processes.md","status":"accepted","created_at":"2026-07-04","updated_at":"2026-07-04","ref_agenda":"AGD-0046"}],"plans":[{"id":"PLN-0136","file":"PLN-0136-route-desktop-home-key-outside-guest-input.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0137","file":"PLN-0137-implement-systemos-foreground-stack-state.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0138","file":"PLN-0138-specify-foreground-pause-and-home-contract.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0139","file":"PLN-0139-validate-game-home-shell-game-end-to-end.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0140","file":"PLN-0140-deliver-game-pause-resume-and-suspension.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0141","file":"PLN-0141-integrate-render-audio-and-input-pause-boundaries.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0142","file":"PLN-0142-deliver-game-lifecycle-events-to-vm-runtime.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0143","file":"PLN-0143-guarantee-cooperative-pause-budget-tick-before-suspension.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0144","file":"PLN-0144-suspend-resident-game-when-shell-takes-foreground.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0145","file":"PLN-0145-centralize-resident-game-resume-transition.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0146","file":"PLN-0146-consolidate-lifecycle-process-lookup-helpers.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0147","file":"PLN-0147-move-native-shell-profile-update-into-hub.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0148","file":"PLN-0148-introduce-vm-session-registry-and-identity.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0149","file":"PLN-0149-move-vm-runtime-state-into-vm-sessions.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0150","file":"PLN-0150-route-cartridge-loading-through-vm-sessions.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0151","file":"PLN-0151-schedule-foreground-vm-session-ticks.md","status":"open","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0152","file":"PLN-0152-validate-game-and-vm-shell-session-coexistence.md","status":"open","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0153","file":"PLN-0153-specify-vm-session-ownership-and-background-ready-scheduling.md","status":"open","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0041","status":"in_progress","ticket":"foreground-stack-game-pause-shell-vm-backed","title":"Foreground Stack, Game Pause, and VM-Backed Shell Coexistence","created_at":"2026-06-05","updated_at":"2026-07-04","tags":["runtime","os","lifecycle","shell","game","vm","foreground","architecture"],"agendas":[{"id":"AGD-0041","file":"AGD-0041-foreground-stack-game-pause-shell-vm-backed.md","status":"accepted","created_at":"2026-06-05","updated_at":"2026-07-03"},{"id":"AGD-0046","file":"AGD-0046-vm-context-ownership-for-resident-game-and-vm-backed-shell.md","status":"accepted","created_at":"2026-07-04","updated_at":"2026-07-04"}],"decisions":[{"id":"DEC-0037","file":"DEC-0037-foreground-stack-and-game-pause-contract.md","status":"accepted","created_at":"2026-07-03","updated_at":"2026-07-03","ref_agenda":"AGD-0041"},{"id":"DEC-0038","file":"DEC-0038-vm-session-ownership-for-vm-backed-processes.md","status":"accepted","created_at":"2026-07-04","updated_at":"2026-07-04","ref_agenda":"AGD-0046"}],"plans":[{"id":"PLN-0136","file":"PLN-0136-route-desktop-home-key-outside-guest-input.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0137","file":"PLN-0137-implement-systemos-foreground-stack-state.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0138","file":"PLN-0138-specify-foreground-pause-and-home-contract.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0139","file":"PLN-0139-validate-game-home-shell-game-end-to-end.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0140","file":"PLN-0140-deliver-game-pause-resume-and-suspension.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0141","file":"PLN-0141-integrate-render-audio-and-input-pause-boundaries.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0037"]},{"id":"PLN-0142","file":"PLN-0142-deliver-game-lifecycle-events-to-vm-runtime.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0143","file":"PLN-0143-guarantee-cooperative-pause-budget-tick-before-suspension.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0144","file":"PLN-0144-suspend-resident-game-when-shell-takes-foreground.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0145","file":"PLN-0145-centralize-resident-game-resume-transition.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0146","file":"PLN-0146-consolidate-lifecycle-process-lookup-helpers.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0147","file":"PLN-0147-move-native-shell-profile-update-into-hub.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0037"]},{"id":"PLN-0148","file":"PLN-0148-introduce-vm-session-registry-and-identity.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0149","file":"PLN-0149-move-vm-runtime-state-into-vm-sessions.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0150","file":"PLN-0150-route-cartridge-loading-through-vm-sessions.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0151","file":"PLN-0151-schedule-foreground-vm-session-ticks.md","status":"done","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0152","file":"PLN-0152-validate-game-and-vm-shell-session-coexistence.md","status":"open","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]},{"id":"PLN-0153","file":"PLN-0153-specify-vm-session-ownership-and-background-ready-scheduling.md","status":"open","created_at":"2026-07-04","updated_at":"2026-07-04","ref_decisions":["DEC-0038"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0042","status":"done","ticket":"real-render-worker-establishment","title":"Real Render Worker Establishment","created_at":"2026-06-06","updated_at":"2026-06-20","tags":["runtime","renderer","worker","concurrency","host","hal","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0049","file":"discussion/lessons/DSC-0042-real-render-worker-establishment/LSN-0049-render-worker-publication-boundary.md","status":"done","created_at":"2026-06-20","updated_at":"2026-06-20"}]}
|
{"type":"discussion","id":"DSC-0042","status":"done","ticket":"real-render-worker-establishment","title":"Real Render Worker Establishment","created_at":"2026-06-06","updated_at":"2026-06-20","tags":["runtime","renderer","worker","concurrency","host","hal","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0049","file":"discussion/lessons/DSC-0042-real-render-worker-establishment/LSN-0049-render-worker-publication-boundary.md","status":"done","created_at":"2026-06-20","updated_at":"2026-06-20"}]}
|
||||||
{"type":"discussion","id":"DSC-0038","status":"done","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0038-render-frame-packet-boundary/LSN-0047-typed-render-submissions-preserve-domain-boundaries.md","status":"done","created_at":"2026-06-04","updated_at":"2026-06-04"}]}
|
{"type":"discussion","id":"DSC-0038","status":"done","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-06-04","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0047","file":"discussion/lessons/DSC-0038-render-frame-packet-boundary/LSN-0047-typed-render-submissions-preserve-domain-boundaries.md","status":"done","created_at":"2026-06-04","updated_at":"2026-06-04"}]}
|
||||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
id: PLN-0151
|
id: PLN-0151
|
||||||
ticket: foreground-stack-game-pause-shell-vm-backed
|
ticket: foreground-stack-game-pause-shell-vm-backed
|
||||||
title: Schedule Foreground VM Session Ticks
|
title: Schedule Foreground VM Session Ticks
|
||||||
status: open
|
status: done
|
||||||
created: 2026-07-04
|
created: 2026-07-04
|
||||||
ref_decisions: [DEC-0038]
|
ref_decisions: [DEC-0038]
|
||||||
tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture]
|
tags: [runtime, os, lifecycle, shell, game, vm, foreground, architecture]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user