diff --git a/crates/console/prometeu-drivers/src/hardware.rs b/crates/console/prometeu-drivers/src/hardware.rs index 6646e461..cd4d3cf9 100644 --- a/crates/console/prometeu-drivers/src/hardware.rs +++ b/crates/console/prometeu-drivers/src/hardware.rs @@ -33,6 +33,8 @@ use std::sync::Arc; /// - **Audio**: Stereo, Command-based mixing. /// - **Input**: 12-button Digital Gamepad + Absolute Touch/Mouse. pub struct Hardware { + /// Shared physical memory bank ownership used by peripherals and worker backends. + pub memory_banks: Arc, /// The Graphics Processing Unit (GPU). Handles drawing primitives, sprites, and tilemaps. pub gfx: Gfx, /// Canonical frame orchestration owner for scene/camera/cache/resolver/sprites. @@ -216,6 +218,7 @@ impl Hardware { ); let glyph_slot_index = assets.glyph_asset_slot_index(); Self { + memory_banks: Arc::clone(&memory_banks), gfx: Gfx::new( Self::W, Self::H, diff --git a/crates/console/prometeu-drivers/src/local_render_backend.rs b/crates/console/prometeu-drivers/src/local_render_backend.rs index 87bbe446..2bed802c 100644 --- a/crates/console/prometeu-drivers/src/local_render_backend.rs +++ b/crates/console/prometeu-drivers/src/local_render_backend.rs @@ -1,5 +1,7 @@ +use crate::asset::GlyphAssetSlotIndex; +use crate::frame_composer::FrameComposer; use crate::gfx::Gfx; -use crate::memory_banks::GlyphBankPoolAccess; +use crate::memory_banks::{GlyphBankPoolAccess, MemoryBanks, SceneBankPoolAccess}; use prometeu_hal::app_mode::AppMode; use prometeu_hal::{ OwnedRgba8888Frame, RenderSubmission, RenderSubmissionPacket, RenderWorkerBackend, @@ -9,11 +11,51 @@ use std::sync::{Arc, Mutex}; pub struct LocalFramebufferRenderBackend { gfx: Mutex, + frame_composer: Mutex, } impl LocalFramebufferRenderBackend { pub fn new(width: usize, height: usize, glyph_banks: Arc) -> Self { - Self { gfx: Mutex::new(Gfx::new(width, height, glyph_banks)) } + Self::new_with_parts( + width, + height, + glyph_banks, + Arc::new(MemoryBanks::new()), + GlyphAssetSlotIndex::new(), + ) + } + + pub fn new_with_memory_banks( + width: usize, + height: usize, + memory_banks: Arc, + glyph_slot_index: GlyphAssetSlotIndex, + ) -> Self { + Self::new_with_parts( + width, + height, + Arc::clone(&memory_banks) as Arc, + memory_banks, + glyph_slot_index, + ) + } + + fn new_with_parts( + width: usize, + height: usize, + glyph_banks: Arc, + scene_banks: Arc, + glyph_slot_index: GlyphAssetSlotIndex, + ) -> Self { + Self { + gfx: Mutex::new(Gfx::new(width, height, glyph_banks)), + frame_composer: Mutex::new(FrameComposer::new( + width, + height, + scene_banks, + glyph_slot_index, + )), + } } pub fn render_submission( @@ -23,7 +65,16 @@ impl LocalFramebufferRenderBackend { 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); + if packet.composer.bound_scene.is_none() { + gfx.render_game2d_frame_packet(packet); + } else { + let mut frame_composer = self + .frame_composer + .lock() + .map_err(|_| RenderWorkerError::InternalFailure)?; + frame_composer.render_game2d_frame_packet(packet, &mut *gfx); + gfx.apply_gfx2d_commands(&packet.gfx2d); + } } RenderSubmissionPacket::ShellUi(packet) if submission.app_mode == AppMode::Shell => { gfx.render_shell_ui_frame_packet(packet); diff --git a/crates/console/prometeu-system/src/os/facades/vm.rs b/crates/console/prometeu-system/src/os/facades/vm.rs index f2d3f065..20cecd80 100644 --- a/crates/console/prometeu-system/src/os/facades/vm.rs +++ b/crates/console/prometeu-system/src/os/facades/vm.rs @@ -1,9 +1,13 @@ use crate::CrashReport; use crate::os::SystemOS; +use crate::{RenderWorkerConfig, RenderWorkerController}; use prometeu_hal::app_mode::AppMode; use prometeu_hal::cartridge::Cartridge; use prometeu_hal::telemetry::{CertificationConfig, TelemetryFrame}; -use prometeu_hal::{InputSignals, RuntimePlatform}; +use prometeu_hal::{ + InputSignals, OwnedRgba8888Frame, RenderWorkerBackend, RenderWorkerError, + RenderWorkerFrameSink, RuntimePlatform, +}; use prometeu_vm::VirtualMachine; use std::sync::atomic::Ordering; @@ -96,6 +100,30 @@ impl<'a> VmFacade<'a> { self.os.vm_runtime.atomic_telemetry.snapshot() } + pub fn start_render_worker(&mut self, config: RenderWorkerConfig, backend: B, sink: S) + where + B: RenderWorkerBackend, + S: RenderWorkerFrameSink, + { + self.os.vm_runtime.start_render_worker(config, backend, sink); + } + + pub fn stop_render_worker(&mut self) -> Result<(), RenderWorkerError> { + self.os.vm_runtime.stop_render_worker() + } + + pub fn render_worker_controller(&self) -> Option<&RenderWorkerController> { + self.os.vm_runtime.render_worker_controller.as_ref() + } + + pub fn latest_render_worker_frame(&self) -> Option { + self.os.vm_runtime.latest_render_worker_frame() + } + + pub fn repeat_latest_render_worker_frame(&self) -> Option { + self.os.vm_runtime.repeat_latest_render_worker_frame() + } + pub fn cert_config(&self) -> &CertificationConfig { &self.os.vm_runtime.certifier.config } 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 68c58069..7463e0c1 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs @@ -3,7 +3,9 @@ use crate::CrashReport; use crate::fs::{FsBackend, FsState, VirtualFS}; use prometeu_hal::cartridge::Cartridge; use prometeu_hal::log::{LogLevel, LogSource}; -use prometeu_hal::{RenderWorkerBackend, RenderWorkerError, RenderWorkerFrameSink}; +use prometeu_hal::{ + OwnedRgba8888Frame, RenderWorkerBackend, RenderWorkerError, RenderWorkerFrameSink, +}; use std::collections::HashMap; impl VirtualMachineRuntime { @@ -193,6 +195,14 @@ impl VirtualMachineRuntime { self.render_worker_ownership.set(self.render_manager.active_ownership()); } + pub fn latest_render_worker_frame(&self) -> Option { + self.render_worker_controller.as_ref()?.latest_published_frame() + } + + pub fn repeat_latest_render_worker_frame(&self) -> Option { + self.render_worker_controller.as_ref()?.repeat_latest_frame() + } + pub fn initialize_vm( &mut self, log_service: &mut LogService, diff --git a/crates/host/prometeu-host-desktop-winit/src/runner.rs b/crates/host/prometeu-host-desktop-winit/src/runner.rs index 53235b3d..9354b54b 100644 --- a/crates/host/prometeu-host-desktop-winit/src/runner.rs +++ b/crates/host/prometeu-host-desktop-winit/src/runner.rs @@ -4,14 +4,16 @@ use crate::fs_backend::HostDirBackend; use crate::input::HostInputHandler; use crate::log_sink::HostConsoleSink; use crate::stats::HostStats; -use crate::utilities::draw_rgba8888_to_rgba8; +use crate::utilities::{draw_owned_rgba8888_frame_to_rgba8, draw_rgba8888_to_rgba8}; use pixels::wgpu::PresentMode; use pixels::{Pixels, PixelsBuilder, SurfaceTexture}; -use prometeu_drivers::AudioCommand; use prometeu_drivers::hardware::Hardware; +use prometeu_drivers::{AudioCommand, LocalFramebufferRenderBackend, MemoryBanks}; use prometeu_firmware::{BootTarget, Firmware, FirmwareState}; -use prometeu_hal::RuntimePlatform; use prometeu_hal::telemetry::CertificationConfig; +use prometeu_hal::{OwnedRgba8888Frame, RenderWorkerError, RenderWorkerFrameSink, RuntimePlatform}; +use prometeu_system::RenderWorkerConfig; +use std::sync::Arc; use std::time::{Duration, Instant}; use winit::application::ApplicationHandler; use winit::dpi::LogicalSize; @@ -22,6 +24,15 @@ use winit::window::{Window, WindowAttributes, WindowId}; const IDLE_HOST_POLL_DT: Duration = Duration::from_millis(100); +#[derive(Debug, Clone, Copy)] +struct HostWorkerFrameSink; + +impl RenderWorkerFrameSink for HostWorkerFrameSink { + fn publish(&self, _frame: OwnedRgba8888Frame) -> Result<(), RenderWorkerError> { + Ok(()) + } +} + #[derive(Debug, Clone)] struct PresentationState { latest_published_frame: u64, @@ -153,8 +164,20 @@ impl HostRunner { firmware.os.fs().mount(Box::new(backend)); } - let hardware = Hardware::new(); + let memory_banks = Arc::new(MemoryBanks::new()); + let hardware = Hardware::new_with_memory_banks(Arc::clone(&memory_banks)); let display_size = hardware.display_size(); + let worker_backend = LocalFramebufferRenderBackend::new_with_memory_banks( + display_size.0, + display_size.1, + memory_banks, + hardware.assets.glyph_asset_slot_index(), + ); + firmware.os.vm().start_render_worker( + RenderWorkerConfig::default(), + worker_backend, + HostWorkerFrameSink, + ); Self { window: None, @@ -278,10 +301,17 @@ impl ApplicationHandler for HostRunner { // Mutable borrow of the frame (lasts only within this block) let frame = pixels.frame_mut(); - // Immutable borrow of prometeu-core (different field, ok) - let src = self.hardware.gfx.front_buffer(); - - draw_rgba8888_to_rgba8(src, frame); + let use_worker_frame = + matches!(self.firmware.state, FirmwareState::GameRunning(_)); + if use_worker_frame + && let Some(worker_frame) = + self.firmware.os.vm().repeat_latest_render_worker_frame() + { + draw_owned_rgba8888_frame_to_rgba8(&worker_frame, frame); + } else { + let src = self.hardware.gfx.front_buffer(); + draw_rgba8888_to_rgba8(src, frame); + } } // <- frame borrow ends here if pixels.render().is_err() { @@ -372,7 +402,14 @@ impl ApplicationHandler for HostRunner { self.stats.record_frame(); } - self.presentation.note_published_frame(self.firmware.os.frame_index()); + let use_worker_frame = matches!(self.firmware.state, FirmwareState::GameRunning(_)); + if use_worker_frame + && let Some(worker_frame) = self.firmware.os.vm().latest_render_worker_frame() + { + self.presentation.note_published_frame(worker_frame.frame_id.get()); + } else { + self.presentation.note_published_frame(self.firmware.os.frame_index()); + } if was_debugger_connected != self.debugger.stream.is_some() || was_waiting_for_start != self.debugger.waiting_for_start diff --git a/crates/host/prometeu-host-desktop-winit/src/utilities.rs b/crates/host/prometeu-host-desktop-winit/src/utilities.rs index 30eb7933..fe6c9ad1 100644 --- a/crates/host/prometeu-host-desktop-winit/src/utilities.rs +++ b/crates/host/prometeu-host-desktop-winit/src/utilities.rs @@ -1,3 +1,5 @@ +use prometeu_hal::OwnedRgba8888Frame; + /// Copies RGBA8888 pixels in canonical RGBA raw order into the `pixels` RGBA8 frame. pub fn draw_rgba8888_to_rgba8(src: &[u32], dst_rgba: &mut [u8]) { for (i, &px) in src.iter().enumerate() { @@ -9,9 +11,15 @@ pub fn draw_rgba8888_to_rgba8(src: &[u32], dst_rgba: &mut [u8]) { } } +pub fn draw_owned_rgba8888_frame_to_rgba8(frame: &OwnedRgba8888Frame, dst_rgba: &mut [u8]) { + draw_rgba8888_to_rgba8(&frame.pixels[..frame.required_pixel_len()], dst_rgba); +} + #[cfg(test)] mod tests { - use super::draw_rgba8888_to_rgba8; + use super::{draw_owned_rgba8888_frame_to_rgba8, draw_rgba8888_to_rgba8}; + use prometeu_hal::app_mode::AppMode; + use prometeu_hal::{FrameId, OwnedRgba8888Frame, RenderOwnership}; #[test] fn draw_rgba8888_to_rgba8_preserves_channel_order_and_alpha() { @@ -22,4 +30,21 @@ mod tests { assert_eq!(dst, [0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01]); } + + #[test] + fn draw_owned_frame_to_rgba8_uses_owned_rgba8888_pixels() { + let frame = OwnedRgba8888Frame::packed( + FrameId::new(3), + RenderOwnership::new(1, AppMode::Game, 7), + 1, + 1, + vec![0x10203040], + ) + .expect("test frame should be valid"); + let mut dst = [0; 4]; + + draw_owned_rgba8888_frame_to_rgba8(&frame, &mut dst); + + assert_eq!(dst, [0x10, 0x20, 0x30, 0x40]); + } } diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 5e175e79..29ccbc53 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-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-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":"done","created_at":"2026-06-15","updated_at":"2026-06-16","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-0119-integrate-desktop-host-worker-presentation.md b/discussion/workflow/plans/PLN-0119-integrate-desktop-host-worker-presentation.md index 2c97edd8..843e2f09 100644 --- a/discussion/workflow/plans/PLN-0119-integrate-desktop-host-worker-presentation.md +++ b/discussion/workflow/plans/PLN-0119-integrate-desktop-host-worker-presentation.md @@ -2,7 +2,7 @@ id: PLN-0119 ticket: real-render-worker-establishment title: Integrate Desktop Host Worker Presentation -status: open +status: done created: 2026-06-15 completed: ref_decisions: [DEC-0033]