From 6b5b27d068cbe9aa574a6a5ebb9c93ce9738567f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Tue, 16 Jun 2026 05:38:02 +0100 Subject: [PATCH] implements PLN-0118 --- crates/console/prometeu-system/src/lib.rs | 2 +- .../src/services/vm_runtime/lifecycle.rs | 9 ++ .../src/services/vm_runtime/mod.rs | 3 +- .../src/services/vm_runtime/render_worker.rs | 132 ++++++++++++++++-- .../vm_runtime/render_worker_test_harness.rs | 9 +- .../src/services/vm_runtime/tick.rs | 1 + discussion/index.ndjson | 2 +- ...d-stale-epoch-and-repeat-frame-behavior.md | 2 +- 8 files changed, 147 insertions(+), 13 deletions(-) diff --git a/crates/console/prometeu-system/src/lib.rs b/crates/console/prometeu-system/src/lib.rs index 8c74e484..8822e7ea 100644 --- a/crates/console/prometeu-system/src/lib.rs +++ b/crates/console/prometeu-system/src/lib.rs @@ -12,6 +12,6 @@ pub use services::process; pub use services::task; pub use services::vm_runtime::{ RenderWorkerConfig, RenderWorkerController, RenderWorkerHandoff, RenderWorkerHandoffWait, - VirtualMachineRuntime, + RenderWorkerOwnership, VirtualMachineRuntime, }; pub use services::windows; diff --git a/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs b/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs index 09478c82..68c58069 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs @@ -27,6 +27,7 @@ impl VirtualMachineRuntime { render_capabilities: RenderRuntimeCapabilities::default(), render_manager: RenderManager::new(AppMode::Game), render_worker_handoff: Arc::new(RenderWorkerHandoff::default()), + render_worker_ownership: RenderWorkerOwnership::default(), render_worker_controller: None, gfx2d_commands: Vec::new(), gfxui_commands: Vec::new(), @@ -129,6 +130,8 @@ impl VirtualMachineRuntime { self.render_manager = RenderManager::new(AppMode::Game); let _ = self.stop_render_worker(); self.render_worker_handoff = Arc::new(RenderWorkerHandoff::default()); + self.render_worker_ownership = + RenderWorkerOwnership::new(self.render_manager.active_ownership()); self.gfx2d_commands.clear(); self.gfxui_commands.clear(); self.logs_written_this_frame.clear(); @@ -159,9 +162,11 @@ impl VirtualMachineRuntime { { let _ = self.stop_render_worker(); self.render_worker_handoff = Arc::new(RenderWorkerHandoff::default()); + self.render_worker_ownership.set(self.render_manager.active_ownership()); self.render_worker_controller = Some(RenderWorkerController::start( config, Arc::clone(&self.render_worker_handoff), + self.render_worker_ownership.clone(), backend, sink, )); @@ -184,6 +189,10 @@ impl VirtualMachineRuntime { true } + pub(crate) fn sync_render_worker_ownership(&self) { + self.render_worker_ownership.set(self.render_manager.active_ownership()); + } + pub fn initialize_vm( &mut self, log_service: &mut LogService, diff --git a/crates/console/prometeu-system/src/services/vm_runtime/mod.rs b/crates/console/prometeu-system/src/services/vm_runtime/mod.rs index d0f69ebe..5312ec3f 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/mod.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/mod.rs @@ -21,7 +21,7 @@ use prometeu_hal::telemetry::{AtomicTelemetry, CertificationConfig, Certifier}; use prometeu_hal::{Gfx2dCommand, GfxUiCommand}; use prometeu_vm::VirtualMachine; pub use render_manager::{RenderManager, RenderRuntimeCapabilities}; -pub use render_worker::{RenderWorkerConfig, RenderWorkerController}; +pub use render_worker::{RenderWorkerConfig, RenderWorkerController, RenderWorkerOwnership}; pub use render_worker_handoff::{RenderWorkerHandoff, RenderWorkerHandoffWait}; use std::collections::HashMap; use std::sync::Arc; @@ -42,6 +42,7 @@ pub struct VirtualMachineRuntime { pub render_capabilities: RenderRuntimeCapabilities, pub render_manager: RenderManager, pub render_worker_handoff: Arc, + pub render_worker_ownership: RenderWorkerOwnership, pub render_worker_controller: Option, pub gfx2d_commands: Vec, pub gfxui_commands: Vec, diff --git a/crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs b/crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs index 1464f477..7993ec8f 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs @@ -1,6 +1,8 @@ use crate::services::vm_runtime::{RenderWorkerHandoff, RenderWorkerHandoffWait}; +use prometeu_hal::app_mode::AppMode; use prometeu_hal::{ - FrameId, RenderWorkerBackend, RenderWorkerError, RenderWorkerFrameSink, RenderWorkerTelemetry, + FrameId, OwnedRgba8888Frame, RenderOwnership, RenderWorkerBackend, RenderWorkerError, + RenderWorkerFrameSink, RenderWorkerTelemetry, }; use std::panic::{AssertUnwindSafe, catch_unwind}; use std::sync::mpsc::{self, Receiver, RecvTimeoutError}; @@ -23,12 +25,39 @@ impl Default for RenderWorkerConfig { struct RenderWorkerState { telemetry: RenderWorkerTelemetry, last_error: Option, + latest_published_frame: Option, +} + +#[derive(Clone, Debug)] +pub struct RenderWorkerOwnership { + active: Arc>, +} + +impl Default for RenderWorkerOwnership { + fn default() -> Self { + Self::new(RenderOwnership::new(0, AppMode::Game, 0)) + } +} + +impl RenderWorkerOwnership { + pub fn new(active: RenderOwnership) -> Self { + Self { active: Arc::new(Mutex::new(active)) } + } + + pub fn snapshot(&self) -> RenderOwnership { + *self.active.lock().unwrap() + } + + pub fn set(&self, active: RenderOwnership) { + *self.active.lock().unwrap() = active; + } } #[derive(Debug)] pub struct RenderWorkerController { config: RenderWorkerConfig, handoff: Arc, + ownership: RenderWorkerOwnership, state: Arc>, handle: Option>, done_rx: Receiver>, @@ -38,6 +67,7 @@ impl RenderWorkerController { pub fn start( config: RenderWorkerConfig, handoff: Arc, + ownership: RenderWorkerOwnership, backend: B, sink: S, ) -> Self @@ -47,13 +77,14 @@ impl RenderWorkerController { { let state = Arc::new(Mutex::new(RenderWorkerState::default())); let worker_handoff = Arc::clone(&handoff); + let worker_ownership = ownership.clone(); let worker_state = Arc::clone(&state); let panic_state = Arc::clone(&state); let (done_tx, done_rx) = mpsc::channel(); let handle = thread::spawn(move || { let result = catch_unwind(AssertUnwindSafe(|| { - run_worker_loop(worker_handoff, worker_state, backend, sink); + run_worker_loop(worker_handoff, worker_ownership, worker_state, backend, sink); })) .map_err(|_| RenderWorkerError::WorkerPanic); if let Err(error) = result { @@ -62,7 +93,7 @@ impl RenderWorkerController { let _ = done_tx.send(result); }); - Self { config, handoff, state, handle: Some(handle), done_rx } + Self { config, handoff, ownership, state, handle: Some(handle), done_rx } } pub fn stop(&mut self) -> Result<(), RenderWorkerError> { @@ -95,8 +126,12 @@ impl RenderWorkerController { telemetry.render_failures = state.telemetry.render_failures; telemetry.publish_failures = state.telemetry.publish_failures; telemetry.present_failures = state.telemetry.present_failures; + telemetry.stale_submission_discards = state.telemetry.stale_submission_discards; + telemetry.repeated_frames = state.telemetry.repeated_frames; telemetry.shutdown_timeouts = state.telemetry.shutdown_timeouts; telemetry.worker_panics = state.telemetry.worker_panics; + telemetry.last_presented_frame_id = state.telemetry.last_presented_frame_id; + telemetry.last_dropped_frame_id = state.telemetry.last_dropped_frame_id; telemetry.last_published_frame_id = state.telemetry.last_published_frame_id; telemetry.last_error_frame_id = state.telemetry.last_error_frame_id; telemetry @@ -105,6 +140,21 @@ impl RenderWorkerController { pub fn last_error(&self) -> Option { self.state.lock().unwrap().last_error } + + pub fn active_ownership(&self) -> RenderOwnership { + self.ownership.snapshot() + } + + pub fn latest_published_frame(&self) -> Option { + self.state.lock().unwrap().latest_published_frame.clone() + } + + pub fn repeat_latest_frame(&self) -> Option { + let mut state = self.state.lock().unwrap(); + let frame = state.latest_published_frame.clone()?; + state.telemetry.record_repeated_frame(frame.frame_id.get()); + Some(frame) + } } impl Drop for RenderWorkerController { @@ -117,6 +167,7 @@ impl Drop for RenderWorkerController { fn run_worker_loop( handoff: Arc, + ownership: RenderWorkerOwnership, state: Arc>, backend: B, sink: S, @@ -141,17 +192,28 @@ fn run_worker_loop( } }; - let publish_result = catch_unwind(AssertUnwindSafe(|| sink.publish(frame))) + if frame.ownership != ownership.snapshot() { + record_stale_discard(&state, frame_id); + continue; + } + + let publish_result = catch_unwind(AssertUnwindSafe(|| sink.publish(frame.clone()))) .map_err(|_| RenderWorkerError::WorkerPanic); match publish_result { - Ok(Ok(())) => record_published(&state, frame_id), + Ok(Ok(())) => record_published(&state, frame), Ok(Err(error)) | Err(error) => record_error(&state, error, frame_id), } } } -fn record_published(state: &Arc>, frame_id: FrameId) { - state.lock().unwrap().telemetry.record_published(frame_id.get()); +fn record_published(state: &Arc>, frame: OwnedRgba8888Frame) { + let mut state = state.lock().unwrap(); + state.telemetry.record_published(frame.frame_id.get()); + state.latest_published_frame = Some(frame); +} + +fn record_stale_discard(state: &Arc>, frame_id: FrameId) { + state.lock().unwrap().telemetry.record_stale_submission_discarded(frame_id.get()); } fn record_error( @@ -171,7 +233,10 @@ mod tests { use crate::services::vm_runtime::render_worker_test_harness::{ FakeRenderBackend, RenderGate, game_submission, }; - use prometeu_hal::{FrameId, Game2DFramePacket, OwnedRgba8888Frame, RenderSubmission}; + use prometeu_hal::app_mode::AppMode; + use prometeu_hal::{ + FrameId, Game2DFramePacket, OwnedRgba8888Frame, RenderOwnership, RenderSubmission, + }; #[derive(Clone, Debug)] struct SharedFakeBackend(Arc); @@ -220,6 +285,7 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig::default(), Arc::clone(&handoff), + RenderWorkerOwnership::default(), SharedFakeBackend(Arc::clone(&backend)), SharedFakeBackend(backend), ); @@ -235,6 +301,7 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig::default(), Arc::clone(&handoff), + RenderWorkerOwnership::new(RenderOwnership::new(1, AppMode::Game, 1)), SharedFakeBackend(Arc::clone(&backend)), SharedFakeBackend(Arc::clone(&backend)), ); @@ -256,6 +323,7 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig { shutdown_timeout: Duration::from_millis(1) }, Arc::clone(&handoff), + RenderWorkerOwnership::default(), SharedFakeBackend(Arc::clone(&backend)), SharedFakeBackend(Arc::clone(&backend)), ); @@ -278,6 +346,7 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig::default(), Arc::clone(&handoff), + RenderWorkerOwnership::default(), PanickingBackend, NoopSink, ); @@ -290,6 +359,53 @@ mod tests { assert_eq!(controller.telemetry().last_error_frame_id, 13); } + #[test] + fn render_worker_controller_discards_stale_frame_before_publish() { + let handoff = Arc::new(RenderWorkerHandoff::default()); + let gate = RenderGate::default(); + let backend = Arc::new(FakeRenderBackend::with_gate(gate.clone())); + let ownership = RenderWorkerOwnership::new(RenderOwnership::new(1, AppMode::Game, 1)); + let mut controller = RenderWorkerController::start( + RenderWorkerConfig::default(), + Arc::clone(&handoff), + ownership.clone(), + SharedFakeBackend(Arc::clone(&backend)), + SharedFakeBackend(Arc::clone(&backend)), + ); + + handoff.publish(game_submission(21, 1, 1)); + gate.wait_for_entries(1); + ownership.set(RenderOwnership::new(2, AppMode::Game, 1)); + gate.release_one(); + + assert_eq!(controller.stop(), Ok(())); + assert!(backend.published_frames().is_empty()); + assert_eq!(controller.telemetry().stale_submission_discards, 1); + } + + #[test] + fn render_worker_controller_repeats_latest_published_frame_without_rendering() { + let handoff = Arc::new(RenderWorkerHandoff::default()); + let backend = Arc::new(FakeRenderBackend::default()); + let mut controller = RenderWorkerController::start( + RenderWorkerConfig::default(), + Arc::clone(&handoff), + RenderWorkerOwnership::new(RenderOwnership::new(1, AppMode::Game, 1)), + SharedFakeBackend(Arc::clone(&backend)), + SharedFakeBackend(Arc::clone(&backend)), + ); + + handoff.publish(game_submission(22, 1, 1)); + assert_eq!(controller.stop(), Ok(())); + + let latest = controller.latest_published_frame().expect("latest frame"); + let repeated = controller.repeat_latest_frame().expect("repeated frame"); + + assert_eq!(latest, repeated); + assert_eq!(backend.published_frames().len(), 1); + assert_eq!(controller.telemetry().repeated_frames, 1); + } + #[test] fn runtime_publishes_game_submissions_to_worker_without_waiting_for_render() { let gate = RenderGate::default(); diff --git a/crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs b/crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs index 205b7544..2a6511f6 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs @@ -72,7 +72,14 @@ impl FakeRenderBackend { return Err(error); } - Ok(owned_frame(submission.frame_id, 0xff00_0000 | submission.frame_id.get() as u32)) + OwnedRgba8888Frame::packed( + submission.frame_id, + submission.ownership, + 1, + 1, + vec![0xff00_0000 | submission.frame_id.get() as u32], + ) + .map_err(|_| RenderWorkerError::InternalFailure) } pub(crate) fn publish(&self, frame: OwnedRgba8888Frame) { diff --git a/crates/console/prometeu-system/src/services/vm_runtime/tick.rs b/crates/console/prometeu-system/src/services/vm_runtime/tick.rs index a2dad5e0..78da52bd 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/tick.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/tick.rs @@ -246,6 +246,7 @@ impl VirtualMachineRuntime { self.current_cartridge_app_mode, self.current_app_id, ); + self.sync_render_worker_ownership(); if self.current_cartridge_app_mode == AppMode::Game { let mut packet = platform.game2d_frame_composer().close_game2d_packet(); packet.gfx2d = std::mem::take(&mut self.gfx2d_commands); diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 8b340908..5e175e79 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -2,7 +2,7 @@ {"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-0041","status":"open","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-06-05","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":"open","created_at":"2026-06-05","updated_at":"2026-06-05"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0042","status":"in_progress","ticket":"real-render-worker-establishment","title":"Real Render Worker Establishment","created_at":"2026-06-06","updated_at":"2026-06-15","tags":["runtime","renderer","worker","concurrency","host","hal","architecture"],"agendas":[{"id":"AGD-0042","file":"AGD-0042-host-hardware-render-boundary-preparation.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-06"},{"id":"AGD-0043","file":"AGD-0043-real-render-worker-establishment.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-15"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-platform-layer-and-hardwarebridge-elimination.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-06","ref_agenda":"AGD-0042"},{"id":"DEC-0033","file":"DEC-0033-real-render-worker-contract.md","status":"accepted","created_at":"2026-06-15","updated_at":"2026-06-15","ref_agenda":"AGD-0043"}],"plans":[{"id":"PLN-0098","file":"PLN-0098-define-platform-facade-contracts.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0099","file":"PLN-0099-introduce-owned-render-submission-sink.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0100","file":"PLN-0100-migrate-local-render-publication-to-sink.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0101","file":"PLN-0101-remove-immediate-gfx-syscall-rendering.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0102","file":"PLN-0102-introduce-game2d-frame-composer-service.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0103","file":"PLN-0103-introduce-runtime-platform-and-testplatform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0104","file":"PLN-0104-migrate-vm-runtime-hostcontext-to-platform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0105","file":"PLN-0105-migrate-firmware-and-hub-to-platform-services.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0106","file":"PLN-0106-migrate-desktop-host-to-platform-services.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0107","file":"PLN-0107-migrate-remaining-platform-domains.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0108","file":"PLN-0108-migrate-tests-to-testplatform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0109","file":"PLN-0109-remove-hardwarebridge-and-update-specs.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0110","file":"PLN-0110-define-owned-rgba8888-frame-contract.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0111","file":"PLN-0111-define-read-only-render-resource-access.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0112","file":"PLN-0112-define-render-worker-errors-and-telemetry.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0113","file":"PLN-0113-implement-thread-safe-latest-wins-handoff.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0114","file":"PLN-0114-add-deterministic-render-worker-test-harness.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0115","file":"PLN-0115-implement-render-worker-controller-lifecycle.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0116","file":"PLN-0116-implement-fake-local-render-backend.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0117","file":"PLN-0117-integrate-runtime-submission-with-worker.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0118","file":"PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0119","file":"PLN-0119-integrate-desktop-host-worker-presentation.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0120","file":"PLN-0120-update-real-render-worker-specs.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0121","file":"PLN-0121-final-worker-path-validation-and-hardening.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0042","status":"in_progress","ticket":"real-render-worker-establishment","title":"Real Render Worker Establishment","created_at":"2026-06-06","updated_at":"2026-06-16","tags":["runtime","renderer","worker","concurrency","host","hal","architecture"],"agendas":[{"id":"AGD-0042","file":"AGD-0042-host-hardware-render-boundary-preparation.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-06"},{"id":"AGD-0043","file":"AGD-0043-real-render-worker-establishment.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-15"}],"decisions":[{"id":"DEC-0032","file":"DEC-0032-platform-layer-and-hardwarebridge-elimination.md","status":"accepted","created_at":"2026-06-06","updated_at":"2026-06-06","ref_agenda":"AGD-0042"},{"id":"DEC-0033","file":"DEC-0033-real-render-worker-contract.md","status":"accepted","created_at":"2026-06-15","updated_at":"2026-06-15","ref_agenda":"AGD-0043"}],"plans":[{"id":"PLN-0098","file":"PLN-0098-define-platform-facade-contracts.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0099","file":"PLN-0099-introduce-owned-render-submission-sink.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0100","file":"PLN-0100-migrate-local-render-publication-to-sink.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0101","file":"PLN-0101-remove-immediate-gfx-syscall-rendering.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0102","file":"PLN-0102-introduce-game2d-frame-composer-service.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0103","file":"PLN-0103-introduce-runtime-platform-and-testplatform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0104","file":"PLN-0104-migrate-vm-runtime-hostcontext-to-platform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0105","file":"PLN-0105-migrate-firmware-and-hub-to-platform-services.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0106","file":"PLN-0106-migrate-desktop-host-to-platform-services.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0107","file":"PLN-0107-migrate-remaining-platform-domains.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0108","file":"PLN-0108-migrate-tests-to-testplatform.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0109","file":"PLN-0109-remove-hardwarebridge-and-update-specs.md","status":"done","created_at":"2026-06-06","updated_at":"2026-06-15","ref_decisions":["DEC-0032"]},{"id":"PLN-0110","file":"PLN-0110-define-owned-rgba8888-frame-contract.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0111","file":"PLN-0111-define-read-only-render-resource-access.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0112","file":"PLN-0112-define-render-worker-errors-and-telemetry.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0113","file":"PLN-0113-implement-thread-safe-latest-wins-handoff.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0114","file":"PLN-0114-add-deterministic-render-worker-test-harness.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0115","file":"PLN-0115-implement-render-worker-controller-lifecycle.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0116","file":"PLN-0116-implement-fake-local-render-backend.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0117","file":"PLN-0117-integrate-runtime-submission-with-worker.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0118","file":"PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md","status":"done","created_at":"2026-06-15","updated_at":"2026-06-16","ref_decisions":["DEC-0033"]},{"id":"PLN-0119","file":"PLN-0119-integrate-desktop-host-worker-presentation.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0120","file":"PLN-0120-update-real-render-worker-specs.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]},{"id":"PLN-0121","file":"PLN-0121-final-worker-path-validation-and-hardening.md","status":"open","created_at":"2026-06-15","updated_at":"2026-06-15","ref_decisions":["DEC-0033"]}],"lessons":[]} {"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-0034","status":"done","ticket":"system-os-domain-facades","title":"Agenda - SystemOS Domain Facades","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","services","api-surface","lifecycle","fs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]} diff --git a/discussion/workflow/plans/PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md b/discussion/workflow/plans/PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md index 343ac32d..59301fa6 100644 --- a/discussion/workflow/plans/PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md +++ b/discussion/workflow/plans/PLN-0118-add-stale-epoch-and-repeat-frame-behavior.md @@ -2,7 +2,7 @@ id: PLN-0118 ticket: real-render-worker-establishment title: Add Stale Epoch and Repeat Frame Behavior -status: open +status: done created: 2026-06-15 completed: ref_decisions: [DEC-0033]