From 28105c2bf2805dc64717fe82d198bbfac3d25400 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 15 Jun 2026 16:11:34 +0100 Subject: [PATCH] implements PLN-0114 --- .../src/services/vm_runtime/mod.rs | 2 + .../vm_runtime/render_worker_handoff.rs | 2 +- .../vm_runtime/render_worker_test_harness.rs | 166 ++++++++++++++++++ .../services/vm_runtime/tests_asset_bank.rs | 11 +- discussion/index.ndjson | 2 +- ...eterministic-render-worker-test-harness.md | 2 +- 6 files changed, 179 insertions(+), 6 deletions(-) create mode 100644 crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs 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 ab562aaa..66709b9b 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/mod.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/mod.rs @@ -6,6 +6,8 @@ mod lifecycle; pub mod render_manager; pub mod render_worker_handoff; #[cfg(test)] +pub(crate) mod render_worker_test_harness; +#[cfg(test)] mod tests; mod tick; diff --git a/crates/console/prometeu-system/src/services/vm_runtime/render_worker_handoff.rs b/crates/console/prometeu-system/src/services/vm_runtime/render_worker_handoff.rs index 1630dbb3..5cae6c74 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/render_worker_handoff.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/render_worker_handoff.rs @@ -122,7 +122,7 @@ mod tests { } #[test] - fn render_worker_handoff_waits_for_publish_without_sleep() { + fn render_worker_handoff_waits_for_publish_without_timing_delay() { let handoff = Arc::new(RenderWorkerHandoff::default()); let consumer_handoff = Arc::clone(&handoff); let (waiting_tx, waiting_rx) = mpsc::channel(); 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 new file mode 100644 index 00000000..205b7544 --- /dev/null +++ b/crates/console/prometeu-system/src/services/vm_runtime/render_worker_test_harness.rs @@ -0,0 +1,166 @@ +use prometeu_hal::app_mode::AppMode; +use prometeu_hal::{ + FrameId, Game2DFramePacket, OwnedRgba8888Frame, RenderOwnership, RenderSubmission, + RenderWorkerError, ShellUiFramePacket, +}; +use std::sync::{Arc, Condvar, Mutex}; + +#[derive(Debug, Default)] +struct RenderGateState { + entered: u64, + released: u64, +} + +#[derive(Clone, Debug, Default)] +pub(crate) struct RenderGate { + state: Arc<(Mutex, Condvar)>, +} + +impl RenderGate { + pub(crate) fn block_until_released(&self) { + let (lock, condvar) = &*self.state; + let mut state = lock.lock().unwrap(); + state.entered = state.entered.wrapping_add(1); + let entry = state.entered; + condvar.notify_all(); + while state.released < entry { + state = condvar.wait(state).unwrap(); + } + } + + pub(crate) fn wait_for_entries(&self, count: u64) { + let (lock, condvar) = &*self.state; + let mut state = lock.lock().unwrap(); + while state.entered < count { + state = condvar.wait(state).unwrap(); + } + } + + pub(crate) fn release_one(&self) { + let (lock, condvar) = &*self.state; + let mut state = lock.lock().unwrap(); + state.released = state.released.wrapping_add(1); + condvar.notify_all(); + } +} + +#[derive(Debug, Default)] +pub(crate) struct FakeRenderBackend { + gate: Option, + next_error: Mutex>, + published_frames: Mutex>, +} + +impl FakeRenderBackend { + pub(crate) fn with_gate(gate: RenderGate) -> Self { + Self { gate: Some(gate), ..Default::default() } + } + + pub(crate) fn fail_next(&self, error: RenderWorkerError) { + *self.next_error.lock().unwrap() = Some(error); + } + + pub(crate) fn render( + &self, + submission: &RenderSubmission, + ) -> Result { + if let Some(gate) = &self.gate { + gate.block_until_released(); + } + + if let Some(error) = self.next_error.lock().unwrap().take() { + return Err(error); + } + + Ok(owned_frame(submission.frame_id, 0xff00_0000 | submission.frame_id.get() as u32)) + } + + pub(crate) fn publish(&self, frame: OwnedRgba8888Frame) { + self.published_frames.lock().unwrap().push(frame); + } + + pub(crate) fn published_frames(&self) -> Vec { + self.published_frames.lock().unwrap().clone() + } +} + +pub(crate) fn game_submission(frame_id: u64, epoch: u64, app_id: u32) -> RenderSubmission { + RenderSubmission::game2d(FrameId::new(frame_id), Game2DFramePacket::default()) + .with_ownership(RenderOwnership::new(epoch, AppMode::Game, app_id)) +} + +pub(crate) fn shell_submission(frame_id: u64, epoch: u64, app_id: u32) -> RenderSubmission { + RenderSubmission::shell_ui(FrameId::new(frame_id), ShellUiFramePacket::new(Vec::new())) + .with_ownership(RenderOwnership::new(epoch, AppMode::Shell, app_id)) +} + +pub(crate) fn owned_frame(frame_id: FrameId, pixel: u32) -> OwnedRgba8888Frame { + OwnedRgba8888Frame::packed( + frame_id, + RenderOwnership::new(0, AppMode::Game, 0), + 1, + 1, + vec![pixel], + ) + .expect("test frame should be valid") +} + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::mpsc; + use std::thread; + + #[test] + fn render_worker_harness_blocks_and_releases_render_without_timing_delay() { + let gate = RenderGate::default(); + let backend = Arc::new(FakeRenderBackend::with_gate(gate.clone())); + let render_backend = Arc::clone(&backend); + let submission = game_submission(4, 1, 9); + let (done_tx, done_rx) = mpsc::channel(); + + let worker = thread::spawn(move || { + let frame = render_backend.render(&submission).expect("render should succeed"); + done_tx.send(frame.frame_id).unwrap(); + }); + + gate.wait_for_entries(1); + assert!(done_rx.try_recv().is_err()); + gate.release_one(); + + assert_eq!(done_rx.recv().expect("render should finish"), FrameId::new(4)); + worker.join().expect("worker thread should finish"); + } + + #[test] + fn render_worker_harness_records_published_owned_frames() { + let backend = FakeRenderBackend::default(); + let frame = owned_frame(FrameId::new(8), 0xff00_ff00); + + backend.publish(frame.clone()); + + assert_eq!(backend.published_frames(), vec![frame]); + } + + #[test] + fn render_worker_harness_injects_backend_errors() { + let backend = FakeRenderBackend::default(); + backend.fail_next(RenderWorkerError::RenderFailed); + + let error = backend.render(&game_submission(5, 1, 1)).expect_err("render should fail"); + + assert_eq!(error, RenderWorkerError::RenderFailed); + assert!(backend.render(&game_submission(6, 1, 1)).is_ok()); + } + + #[test] + fn render_worker_harness_builds_game_and_shell_submissions() { + let game = game_submission(1, 2, 3); + let shell = shell_submission(4, 5, 6); + + assert_eq!(game.frame_id, FrameId::new(1)); + assert_eq!(game.ownership, RenderOwnership::new(2, AppMode::Game, 3)); + assert_eq!(shell.frame_id, FrameId::new(4)); + assert_eq!(shell.ownership, RenderOwnership::new(5, AppMode::Shell, 6)); + } +} diff --git a/crates/console/prometeu-system/src/services/vm_runtime/tests_asset_bank.rs b/crates/console/prometeu-system/src/services/vm_runtime/tests_asset_bank.rs index ccf91534..45ae5a2e 100644 --- a/crates/console/prometeu-system/src/services/vm_runtime/tests_asset_bank.rs +++ b/crates/console/prometeu-system/src/services/vm_runtime/tests_asset_bank.rs @@ -391,15 +391,20 @@ fn tick_asset_cancel_invalid_transition_returns_status_not_crash() { runtime.initialize_vm(&mut log_service, &mut vm, &cartridge).expect("runtime must initialize"); - loop { + let mut asset_ready = false; + for _ in 0..1_000 { match platform.local_hardware().assets.status(handle) { - LoadStatus::READY => break, + LoadStatus::READY => { + asset_ready = true; + break; + } LoadStatus::PENDING | LoadStatus::LOADING => { - std::thread::sleep(std::time::Duration::from_millis(1)); + std::thread::yield_now(); } other => panic!("unexpected asset status before commit: {:?}", other), } } + assert!(asset_ready, "asset did not become ready before commit"); assert_eq!(platform.local_hardware().assets.commit(handle), AssetOpStatus::Ok); platform.local_hardware().assets.apply_commits(); diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 7bb1ff99..a73aa74f 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":"open","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":"open","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":"open","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-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-0114-add-deterministic-render-worker-test-harness.md b/discussion/workflow/plans/PLN-0114-add-deterministic-render-worker-test-harness.md index 065b48f4..cba2fb1e 100644 --- a/discussion/workflow/plans/PLN-0114-add-deterministic-render-worker-test-harness.md +++ b/discussion/workflow/plans/PLN-0114-add-deterministic-render-worker-test-harness.md @@ -2,7 +2,7 @@ id: PLN-0114 ticket: real-render-worker-establishment title: Add Deterministic Render Worker Test Harness -status: open +status: done created: 2026-06-15 completed: ref_decisions: [DEC-0033]