From 0c6a669e6e32f0b6eb68e80bf047f66f1e59c936 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 15 Jun 2026 16:17:16 +0100 Subject: [PATCH] implements PLN-0116 --- crates/console/prometeu-drivers/src/lib.rs | 2 + .../src/local_render_backend.rs | 111 ++++++++++++++++++ crates/console/prometeu-hal/src/lib.rs | 4 +- .../console/prometeu-hal/src/render_worker.rs | 13 ++ crates/console/prometeu-system/src/lib.rs | 5 +- .../src/services/vm_runtime/mod.rs | 4 +- .../src/services/vm_runtime/render_worker.rs | 38 +++--- discussion/index.ndjson | 2 +- ...116-implement-fake-local-render-backend.md | 2 +- 9 files changed, 150 insertions(+), 31 deletions(-) create mode 100644 crates/console/prometeu-drivers/src/local_render_backend.rs diff --git a/crates/console/prometeu-drivers/src/lib.rs b/crates/console/prometeu-drivers/src/lib.rs index c8fe4afd..675eeb0e 100644 --- a/crates/console/prometeu-drivers/src/lib.rs +++ b/crates/console/prometeu-drivers/src/lib.rs @@ -3,6 +3,7 @@ mod audio; mod frame_composer; mod gfx; pub mod hardware; +mod local_render_backend; mod memory_banks; mod pad; mod test_platform; @@ -12,6 +13,7 @@ pub use crate::asset::AssetManager; pub use crate::audio::{Audio, AudioCommand, Channel, MAX_CHANNELS, OUTPUT_SAMPLE_RATE}; pub use crate::frame_composer::{ComposerBuffer, FrameComposer, SceneStatus, SpriteController}; pub use crate::gfx::Gfx; +pub use crate::local_render_backend::LocalFramebufferRenderBackend; pub use crate::memory_banks::{ GlyphBankPoolAccess, GlyphBankPoolInstaller, MemoryBanks, SceneBankPoolAccess, SceneBankPoolInstaller, SoundBankPoolAccess, SoundBankPoolInstaller, diff --git a/crates/console/prometeu-drivers/src/local_render_backend.rs b/crates/console/prometeu-drivers/src/local_render_backend.rs new file mode 100644 index 00000000..87bbe446 --- /dev/null +++ b/crates/console/prometeu-drivers/src/local_render_backend.rs @@ -0,0 +1,111 @@ +use crate::gfx::Gfx; +use crate::memory_banks::GlyphBankPoolAccess; +use prometeu_hal::app_mode::AppMode; +use prometeu_hal::{ + OwnedRgba8888Frame, RenderSubmission, RenderSubmissionPacket, RenderWorkerBackend, + RenderWorkerError, +}; +use std::sync::{Arc, Mutex}; + +pub struct LocalFramebufferRenderBackend { + gfx: Mutex, +} + +impl LocalFramebufferRenderBackend { + pub fn new(width: usize, height: usize, glyph_banks: Arc) -> Self { + Self { gfx: Mutex::new(Gfx::new(width, height, glyph_banks)) } + } + + pub fn render_submission( + &self, + submission: &RenderSubmission, + ) -> Result { + let mut gfx = self.gfx.lock().map_err(|_| RenderWorkerError::InternalFailure)?; + match &submission.packet { + RenderSubmissionPacket::Game2D(packet) if submission.app_mode == AppMode::Game => { + gfx.render_game2d_frame_packet(packet); + } + RenderSubmissionPacket::ShellUi(packet) if submission.app_mode == AppMode::Shell => { + gfx.render_shell_ui_frame_packet(packet); + } + _ => return Err(RenderWorkerError::RenderFailed), + } + + gfx.present(); + let (width, height) = gfx.size(); + OwnedRgba8888Frame::packed( + submission.frame_id, + submission.ownership, + width, + height, + gfx.front_buffer().to_vec(), + ) + .map_err(|_| RenderWorkerError::InternalFailure) + } +} + +impl RenderWorkerBackend for LocalFramebufferRenderBackend { + fn render( + &self, + submission: &RenderSubmission, + ) -> Result { + self.render_submission(submission) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::memory_banks::MemoryBanks; + use prometeu_hal::app_mode::AppMode; + use prometeu_hal::color::Color; + use prometeu_hal::primitives::Rect; + use prometeu_hal::{ + FrameId, Game2DFramePacket, Gfx2dCommand, GfxUiCommand, RenderOwnership, ShellUiFramePacket, + }; + + fn backend() -> LocalFramebufferRenderBackend { + let banks = Arc::new(MemoryBanks::new()); + LocalFramebufferRenderBackend::new(4, 4, banks) + } + + #[test] + fn local_backend_renders_game2d_submission_to_owned_frame() { + let backend = backend(); + let mut packet = Game2DFramePacket::default(); + packet.gfx2d = vec![Gfx2dCommand::FillRect { + rect: Rect { x: 1, y: 1, w: 2, h: 2 }, + color: Color::RED, + }]; + let ownership = RenderOwnership::new(3, AppMode::Game, 9); + let submission = + RenderSubmission::game2d(FrameId::new(5), packet).with_ownership(ownership); + + let frame = backend.render(&submission).expect("game frame should render"); + + assert_eq!(frame.frame_id, FrameId::new(5)); + assert_eq!(frame.ownership, ownership); + assert_eq!(frame.width, 4); + assert_eq!(frame.height, 4); + assert_eq!(frame.pixels[1 + 4], Color::RED.raw()); + assert_eq!(frame.pixels[2 + 2 * 4], Color::RED.raw()); + } + + #[test] + fn local_backend_renders_shell_ui_submission_to_owned_frame() { + let backend = backend(); + let packet = ShellUiFramePacket::new(vec![GfxUiCommand::FillRect { + rect: Rect { x: 0, y: 0, w: 1, h: 1 }, + color: Color::GREEN, + }]); + let ownership = RenderOwnership::new(4, AppMode::Shell, 10); + let submission = + RenderSubmission::shell_ui(FrameId::new(6), packet).with_ownership(ownership); + + let frame = backend.render(&submission).expect("shell frame should render"); + + assert_eq!(frame.frame_id, FrameId::new(6)); + assert_eq!(frame.ownership, ownership); + assert_eq!(frame.pixels[0], Color::GREEN.raw()); + } +} diff --git a/crates/console/prometeu-hal/src/lib.rs b/crates/console/prometeu-hal/src/lib.rs index 62c6863d..106bfc05 100644 --- a/crates/console/prometeu-hal/src/lib.rs +++ b/crates/console/prometeu-hal/src/lib.rs @@ -60,5 +60,7 @@ pub use render_submission::{ Gfx2dCommand, GfxUiCommand, HudCommand, HudPacket, RenderOwnership, RenderSubmission, RenderSubmissionPacket, ShellUiFramePacket, }; -pub use render_worker::{RenderWorkerError, RenderWorkerTelemetry}; +pub use render_worker::{ + RenderWorkerBackend, RenderWorkerError, RenderWorkerFrameSink, RenderWorkerTelemetry, +}; pub use touch_bridge::TouchBridge; diff --git a/crates/console/prometeu-hal/src/render_worker.rs b/crates/console/prometeu-hal/src/render_worker.rs index 44ebbc60..91eae5a4 100644 --- a/crates/console/prometeu-hal/src/render_worker.rs +++ b/crates/console/prometeu-hal/src/render_worker.rs @@ -1,5 +1,7 @@ use std::fmt; +use crate::{OwnedRgba8888Frame, RenderSubmission}; + /// Typed failure surface for the real render worker and its backend. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RenderWorkerError { @@ -30,6 +32,17 @@ impl fmt::Display for RenderWorkerError { impl std::error::Error for RenderWorkerError {} +pub trait RenderWorkerBackend: Send + 'static { + fn render( + &self, + submission: &RenderSubmission, + ) -> Result; +} + +pub trait RenderWorkerFrameSink: Send + 'static { + fn publish(&self, frame: OwnedRgba8888Frame) -> Result<(), RenderWorkerError>; +} + /// Snapshot of render worker handoff, render, publish, and shutdown counters. #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] pub struct RenderWorkerTelemetry { diff --git a/crates/console/prometeu-system/src/lib.rs b/crates/console/prometeu-system/src/lib.rs index d67c855d..8c74e484 100644 --- a/crates/console/prometeu-system/src/lib.rs +++ b/crates/console/prometeu-system/src/lib.rs @@ -6,11 +6,12 @@ mod services; pub use crash_report::CrashReport; pub use os::{LifecycleError, LifecycleOperation, SystemOS}; pub use programs::{NativeShellApp, PrometeuHub, SystemProfileAction, SystemProfileUpdate}; +pub use prometeu_hal::{RenderWorkerBackend, RenderWorkerFrameSink}; pub use services::fs; pub use services::process; pub use services::task; pub use services::vm_runtime::{ - RenderWorkerBackend, RenderWorkerConfig, RenderWorkerController, RenderWorkerFrameSink, - RenderWorkerHandoff, RenderWorkerHandoffWait, VirtualMachineRuntime, + RenderWorkerConfig, RenderWorkerController, RenderWorkerHandoff, RenderWorkerHandoffWait, + VirtualMachineRuntime, }; pub use services::windows; 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 2a5813a6..d3319452 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/mod.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/mod.rs @@ -21,9 +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::{ - RenderWorkerBackend, RenderWorkerConfig, RenderWorkerController, RenderWorkerFrameSink, -}; +pub use render_worker::{RenderWorkerConfig, RenderWorkerController}; pub use render_worker_handoff::{RenderWorkerHandoff, RenderWorkerHandoffWait}; use std::collections::HashMap; use std::sync::Arc; 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 b89a8919..1792e790 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,6 @@ use crate::services::vm_runtime::{RenderWorkerHandoff, RenderWorkerHandoffWait}; use prometeu_hal::{ - FrameId, OwnedRgba8888Frame, RenderSubmission, RenderWorkerError, RenderWorkerTelemetry, + FrameId, RenderWorkerBackend, RenderWorkerError, RenderWorkerFrameSink, RenderWorkerTelemetry, }; use std::panic::{AssertUnwindSafe, catch_unwind}; use std::sync::mpsc::{self, Receiver, RecvTimeoutError}; @@ -8,17 +8,6 @@ use std::sync::{Arc, Mutex}; use std::thread::{self, JoinHandle}; use std::time::Duration; -pub trait RenderWorkerBackend: Send + 'static { - fn render( - &self, - submission: &RenderSubmission, - ) -> Result; -} - -pub trait RenderWorkerFrameSink: Send + 'static { - fn publish(&self, frame: OwnedRgba8888Frame) -> Result<(), RenderWorkerError>; -} - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct RenderWorkerConfig { pub shutdown_timeout: Duration, @@ -173,20 +162,23 @@ mod tests { use crate::services::vm_runtime::render_worker_test_harness::{ FakeRenderBackend, RenderGate, game_submission, }; - use prometeu_hal::{FrameId, OwnedRgba8888Frame}; + use prometeu_hal::{FrameId, OwnedRgba8888Frame, RenderSubmission}; - impl RenderWorkerBackend for Arc { + #[derive(Clone, Debug)] + struct SharedFakeBackend(Arc); + + impl RenderWorkerBackend for SharedFakeBackend { fn render( &self, submission: &RenderSubmission, ) -> Result { - FakeRenderBackend::render(self, submission) + self.0.render(submission) } } - impl RenderWorkerFrameSink for Arc { + impl RenderWorkerFrameSink for SharedFakeBackend { fn publish(&self, frame: OwnedRgba8888Frame) -> Result<(), RenderWorkerError> { - FakeRenderBackend::publish(self, frame); + self.0.publish(frame); Ok(()) } } @@ -219,8 +211,8 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig::default(), Arc::clone(&handoff), - Arc::clone(&backend), - backend, + SharedFakeBackend(Arc::clone(&backend)), + SharedFakeBackend(backend), ); assert_eq!(controller.stop(), Ok(())); @@ -234,8 +226,8 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig::default(), Arc::clone(&handoff), - Arc::clone(&backend), - Arc::clone(&backend), + SharedFakeBackend(Arc::clone(&backend)), + SharedFakeBackend(Arc::clone(&backend)), ); handoff.publish(game_submission(11, 1, 1)); @@ -255,8 +247,8 @@ mod tests { let mut controller = RenderWorkerController::start( RenderWorkerConfig { shutdown_timeout: Duration::from_millis(1) }, Arc::clone(&handoff), - Arc::clone(&backend), - Arc::clone(&backend), + SharedFakeBackend(Arc::clone(&backend)), + SharedFakeBackend(Arc::clone(&backend)), ); handoff.publish(game_submission(12, 1, 1)); diff --git a/discussion/index.ndjson b/discussion/index.ndjson index cbce166c..138b7cf0 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":"open","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":"open","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-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":"open","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-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-0116-implement-fake-local-render-backend.md b/discussion/workflow/plans/PLN-0116-implement-fake-local-render-backend.md index f1c94e45..4aacc4bf 100644 --- a/discussion/workflow/plans/PLN-0116-implement-fake-local-render-backend.md +++ b/discussion/workflow/plans/PLN-0116-implement-fake-local-render-backend.md @@ -2,7 +2,7 @@ id: PLN-0116 ticket: real-render-worker-establishment title: Implement Fake Local Render Backend -status: open +status: done created: 2026-06-15 completed: ref_decisions: [DEC-0033]