diff --git a/crates/console/prometeu-drivers/src/gfx.rs b/crates/console/prometeu-drivers/src/gfx.rs index 22b6ff47..e3334e83 100644 --- a/crates/console/prometeu-drivers/src/gfx.rs +++ b/crates/console/prometeu-drivers/src/gfx.rs @@ -5,7 +5,7 @@ use prometeu_hal::glyph_bank::GlyphBank; use prometeu_hal::scene_viewport_cache::{CachedTileEntry, SceneViewportCache}; use prometeu_hal::scene_viewport_resolver::{LayerCopyRequest, ResolverUpdate}; use prometeu_hal::sprite::Sprite; -use prometeu_hal::{Game2DFramePacket, Gfx2dCommand, GfxBridge}; +use prometeu_hal::{Game2DFramePacket, Gfx2dCommand, GfxBridge, GfxUiCommand, ShellUiFramePacket}; use std::sync::Arc; /// Blending modes inspired by classic 16-bit hardware. @@ -714,6 +714,12 @@ impl Gfx { } } + pub fn render_shell_ui_frame_packet(&mut self, packet: &ShellUiFramePacket) { + for command in &packet.commands { + self.apply_gfxui_command(command); + } + } + fn apply_gfx2d_command(&mut self, command: &Gfx2dCommand) { match command { Gfx2dCommand::Clear { color } => self.clear(*color), @@ -738,6 +744,30 @@ impl Gfx { } } + fn apply_gfxui_command(&mut self, command: &GfxUiCommand) { + match command { + GfxUiCommand::Clear { color } => self.clear(*color), + GfxUiCommand::FillRect { rect, color } => { + self.fill_rect(rect.x, rect.y, rect.w, rect.h, *color); + } + GfxUiCommand::DrawLine { x0, y0, x1, y1, color } => { + self.draw_line(*x0, *y0, *x1, *y1, *color); + } + GfxUiCommand::DrawCircle { x, y, radius, color } => { + self.draw_circle(*x, *y, *radius, *color); + } + GfxUiCommand::DrawDisc { x, y, radius, border_color, fill_color } => { + self.draw_disc(*x, *y, *radius, *border_color, *fill_color); + } + GfxUiCommand::DrawSquare { rect, border_color, fill_color } => { + self.draw_square(rect.x, rect.y, rect.w, rect.h, *border_color, *fill_color); + } + GfxUiCommand::DrawText { x, y, text, color } => { + self.draw_text(*x, *y, text, *color); + } + } + } + fn populate_layer_buckets(&mut self) { for bucket in self.layer_buckets.iter_mut() { bucket.clear(); diff --git a/crates/console/prometeu-drivers/src/hardware.rs b/crates/console/prometeu-drivers/src/hardware.rs index 724ba47f..44852431 100644 --- a/crates/console/prometeu-drivers/src/hardware.rs +++ b/crates/console/prometeu-drivers/src/hardware.rs @@ -8,10 +8,10 @@ use crate::memory_banks::{ }; use crate::pad::Pad; use crate::touch::Touch; -use prometeu_hal::Game2DFramePacket; use prometeu_hal::cartridge::AssetsPayloadSource; use prometeu_hal::sprite::Sprite; use prometeu_hal::{AssetBridge, AudioBridge, GfxBridge, HardwareBridge, PadBridge, TouchBridge}; +use prometeu_hal::{Game2DFramePacket, ShellUiFramePacket}; use std::sync::Arc; /// Aggregate structure for all virtual hardware peripherals. @@ -72,6 +72,10 @@ impl HardwareBridge for Hardware { self.frame_composer.close_game2d_packet() } + fn render_shell_ui_packet(&mut self, packet: &ShellUiFramePacket) { + self.gfx.render_shell_ui_frame_packet(packet); + } + fn render_frame(&mut self) { if self.frame_composer.active_scene_id().is_none() { let packet = self.frame_composer.close_game2d_packet(); @@ -81,6 +85,10 @@ impl HardwareBridge for Hardware { } } + fn present(&mut self) { + self.gfx.present(); + } + fn has_glyph_bank(&self, bank_id: usize) -> bool { self.gfx.glyph_banks.glyph_bank_slot(bank_id).is_some() } diff --git a/crates/console/prometeu-hal/src/hardware_bridge.rs b/crates/console/prometeu-hal/src/hardware_bridge.rs index 639cbffa..5c74454d 100644 --- a/crates/console/prometeu-hal/src/hardware_bridge.rs +++ b/crates/console/prometeu-hal/src/hardware_bridge.rs @@ -2,7 +2,7 @@ use crate::asset_bridge::AssetBridge; use crate::audio_bridge::AudioBridge; use crate::gfx_bridge::GfxBridge; use crate::pad_bridge::PadBridge; -use crate::render_submission::Game2DFramePacket; +use crate::render_submission::{Game2DFramePacket, ShellUiFramePacket}; use crate::sprite::Sprite; use crate::touch_bridge::TouchBridge; @@ -13,7 +13,9 @@ pub trait HardwareBridge { fn set_camera(&mut self, x: i32, y: i32); fn emit_sprite(&mut self, sprite: Sprite) -> bool; fn close_game2d_packet(&self) -> Game2DFramePacket; + fn render_shell_ui_packet(&mut self, packet: &ShellUiFramePacket); fn render_frame(&mut self); + fn present(&mut self); fn has_glyph_bank(&self, bank_id: usize) -> bool; fn gfx(&self) -> &dyn GfxBridge; diff --git a/crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs b/crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs index 89e30089..86c59616 100644 --- a/crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs +++ b/crates/console/prometeu-system/src/programs/prometeu_hub/prometeu_hub.rs @@ -1,8 +1,7 @@ use crate::{CrashReport, SystemOS}; use prometeu_hal::color::Color; -use prometeu_hal::gfx_bridge::GfxBridge; use prometeu_hal::primitives::Rect; -use prometeu_hal::{HardwareBridge, InputSignals}; +use prometeu_hal::{GfxUiCommand, HardwareBridge, InputSignals, ShellUiFramePacket}; use prometeu_vm::VirtualMachine; const SHELL_A_BUTTON: Rect = Rect { x: 112, y: 108, w: 112, h: 48 }; @@ -101,8 +100,6 @@ impl PrometeuHub { os: &mut SystemOS, hw: &mut dyn HardwareBridge, ) -> Option { - hw.gfx_mut().clear(Color::INDIGO); - let in_shell = os.windows().focused_window().is_some(); if !in_shell { @@ -127,21 +124,23 @@ impl PrometeuHub { let pointer_x = hw.touch().x(); let pointer_y = hw.touch().y(); - if os.windows().window_count() == 0 { - render_home(hw.gfx_mut(), pointer_x, pointer_y); - return; - } - - for window in os.windows().windows() { - render_shell_window( - hw.gfx_mut(), - window.viewport, - window.color, - &window.title, - pointer_x, - pointer_y, - ); - } + let packet = if os.windows().window_count() == 0 { + render_home_packet(pointer_x, pointer_y) + } else { + let mut commands = Vec::new(); + for window in os.windows().windows() { + append_shell_window_commands( + &mut commands, + window.viewport, + window.color, + &window.title, + pointer_x, + pointer_y, + ); + } + ShellUiFramePacket::new(commands) + }; + hw.render_shell_ui_packet(&packet); } pub fn update_shell_profile( @@ -163,7 +162,7 @@ impl PrometeuHub { } self.render(os, hw); - hw.gfx_mut().present(); + hw.present(); SystemProfileUpdate { crash, action } } @@ -192,15 +191,29 @@ fn activation_input_down(hw: &dyn HardwareBridge) -> bool { hw.touch().f().down || hw.pad().a().down || hw.pad().b().down || hw.pad().start().down } -fn render_home(gfx: &mut dyn GfxBridge, pointer_x: i32, pointer_y: i32) { - gfx.fill_rect(VIEWPORT.x, VIEWPORT.y, VIEWPORT.w, VIEWPORT.h, COLOR_BG); - draw_panel(gfx, TITLE_PANEL, COLOR_PANEL_DARK, COLOR_BORDER); - draw_buffer_text(gfx, TITLE_PANEL.x + 58, TITLE_PANEL.y + 9, "PROMETEU HUB", COLOR_TEXT); - - draw_panel(gfx, HOME_PANEL, COLOR_PANEL, COLOR_BORDER); - draw_buffer_text(gfx, HOME_PANEL.x + 26, HOME_PANEL.y + 22, "Native Shell Apps", COLOR_TEXT); +fn render_home_packet(pointer_x: i32, pointer_y: i32) -> ShellUiFramePacket { + let mut commands = Vec::new(); + commands.push(GfxUiCommand::Clear { color: COLOR_BG }); + fill_rect(&mut commands, VIEWPORT, COLOR_BG); + draw_panel(&mut commands, TITLE_PANEL, COLOR_PANEL_DARK, COLOR_BORDER); draw_buffer_text( - gfx, + &mut commands, + TITLE_PANEL.x + 58, + TITLE_PANEL.y + 9, + "PROMETEU HUB", + COLOR_TEXT, + ); + + draw_panel(&mut commands, HOME_PANEL, COLOR_PANEL, COLOR_BORDER); + draw_buffer_text( + &mut commands, + HOME_PANEL.x + 26, + HOME_PANEL.y + 22, + "Native Shell Apps", + COLOR_TEXT, + ); + draw_buffer_text( + &mut commands, HOME_PANEL.x + 26, HOME_PANEL.y + 40, "first retro ui slice", @@ -209,50 +222,105 @@ fn render_home(gfx: &mut dyn GfxBridge, pointer_x: i32, pointer_y: i32) { for button in HOME_BUTTONS { let hovered = rect_contains(button.rect, pointer_x, pointer_y); - draw_button(gfx, button.rect, button.label, hovered); + draw_button(&mut commands, button.rect, button.label, hovered); } + + ShellUiFramePacket::new(commands) } -fn render_shell_window( - gfx: &mut dyn GfxBridge, +fn append_shell_window_commands( + commands: &mut Vec, viewport: Rect, color: Color, title: &str, pointer_x: i32, pointer_y: i32, ) { - gfx.fill_rect(VIEWPORT.x, VIEWPORT.y, VIEWPORT.w, VIEWPORT.h, COLOR_BG); - draw_panel(gfx, viewport, COLOR_PANEL_DARK, COLOR_BORDER); - gfx.fill_rect(viewport.x + 4, viewport.y + 24, viewport.w - 8, viewport.h - 28, color); - draw_buffer_text(gfx, viewport.x + 10, viewport.y + 8, title, COLOR_TEXT); - draw_buffer_text(gfx, viewport.x + 18, viewport.y + 44, "native fake shell", COLOR_PANEL_DARK); + fill_rect(commands, VIEWPORT, COLOR_BG); + draw_panel(commands, viewport, COLOR_PANEL_DARK, COLOR_BORDER); + fill_rect( + commands, + Rect { x: viewport.x + 4, y: viewport.y + 24, w: viewport.w - 8, h: viewport.h - 28 }, + color, + ); + draw_buffer_text(commands, viewport.x + 10, viewport.y + 8, title, COLOR_TEXT); + draw_buffer_text( + commands, + viewport.x + 18, + viewport.y + 44, + "native fake shell", + COLOR_PANEL_DARK, + ); let close_hovered = rect_contains(CLOSE_BUTTON, pointer_x, pointer_y); let close_fill = if close_hovered { COLOR_HILITE } else { COLOR_BUTTON }; - gfx.fill_rect(CLOSE_BUTTON.x, CLOSE_BUTTON.y, CLOSE_BUTTON.w, CLOSE_BUTTON.h, close_fill); - gfx.draw_rect(CLOSE_BUTTON.x, CLOSE_BUTTON.y, CLOSE_BUTTON.w, CLOSE_BUTTON.h, COLOR_BORDER); - draw_buffer_text(gfx, CLOSE_BUTTON.x + 5, CLOSE_BUTTON.y + 4, "x", COLOR_TEXT); + fill_rect(commands, CLOSE_BUTTON, close_fill); + draw_rect(commands, CLOSE_BUTTON, COLOR_BORDER); + draw_buffer_text(commands, CLOSE_BUTTON.x + 5, CLOSE_BUTTON.y + 4, "x", COLOR_TEXT); } -fn draw_panel(gfx: &mut dyn GfxBridge, rect: Rect, fill: Color, border: Color) { - gfx.fill_rect(rect.x, rect.y, rect.w, rect.h, fill); - gfx.draw_rect(rect.x, rect.y, rect.w, rect.h, border); - gfx.draw_rect(rect.x + 2, rect.y + 2, rect.w - 4, rect.h - 4, COLOR_MUTED); +fn fill_rect(commands: &mut Vec, rect: Rect, color: Color) { + commands.push(GfxUiCommand::FillRect { rect, color }); } -fn draw_button(gfx: &mut dyn GfxBridge, rect: Rect, label: &str, hovered: bool) { +fn draw_rect(commands: &mut Vec, rect: Rect, color: Color) { + commands.push(GfxUiCommand::DrawLine { + x0: rect.x, + y0: rect.y, + x1: rect.x + rect.w - 1, + y1: rect.y, + color, + }); + commands.push(GfxUiCommand::DrawLine { + x0: rect.x, + y0: rect.y + rect.h - 1, + x1: rect.x + rect.w - 1, + y1: rect.y + rect.h - 1, + color, + }); + commands.push(GfxUiCommand::DrawLine { + x0: rect.x, + y0: rect.y, + x1: rect.x, + y1: rect.y + rect.h - 1, + color, + }); + commands.push(GfxUiCommand::DrawLine { + x0: rect.x + rect.w - 1, + y0: rect.y, + x1: rect.x + rect.w - 1, + y1: rect.y + rect.h - 1, + color, + }); +} + +fn draw_panel(commands: &mut Vec, rect: Rect, fill: Color, border: Color) { + fill_rect(commands, rect, fill); + draw_rect(commands, rect, border); + draw_rect( + commands, + Rect { x: rect.x + 2, y: rect.y + 2, w: rect.w - 4, h: rect.h - 4 }, + COLOR_MUTED, + ); +} + +fn draw_button(commands: &mut Vec, rect: Rect, label: &str, hovered: bool) { let fill = if hovered { COLOR_BUTTON_ACTIVE } else { COLOR_BUTTON }; let border = if hovered { COLOR_HILITE } else { COLOR_BORDER }; - gfx.fill_rect(rect.x, rect.y, rect.w, rect.h, fill); - gfx.draw_rect(rect.x, rect.y, rect.w, rect.h, border); - gfx.draw_rect(rect.x + 3, rect.y + 3, rect.w - 6, rect.h - 6, COLOR_MUTED); - gfx.fill_rect(rect.x + 12, rect.y + 12, 16, 24, border); - gfx.draw_rect(rect.x + 34, rect.y + 12, 62, 24, COLOR_PANEL_DARK); - draw_buffer_text(gfx, rect.x + 40, rect.y + 21, label, COLOR_TEXT); + fill_rect(commands, rect, fill); + draw_rect(commands, rect, border); + draw_rect( + commands, + Rect { x: rect.x + 3, y: rect.y + 3, w: rect.w - 6, h: rect.h - 6 }, + COLOR_MUTED, + ); + fill_rect(commands, Rect { x: rect.x + 12, y: rect.y + 12, w: 16, h: 24 }, border); + draw_rect(commands, Rect { x: rect.x + 34, y: rect.y + 12, w: 62, h: 24 }, COLOR_PANEL_DARK); + draw_buffer_text(commands, rect.x + 40, rect.y + 21, label, COLOR_TEXT); } -fn draw_buffer_text(gfx: &mut dyn GfxBridge, x: i32, y: i32, text: &str, color: Color) { - gfx.draw_text(x, y, text, color); +fn draw_buffer_text(commands: &mut Vec, x: i32, y: i32, text: &str, color: Color) { + commands.push(GfxUiCommand::DrawText { x, y, text: text.to_string(), color }); } #[cfg(test)] @@ -321,6 +389,16 @@ mod tests { assert_eq!(HOME_BUTTONS[1].app, NativeShellApp::ShellB); } + #[test] + fn home_render_produces_shell_ui_packet_commands() { + let packet = render_home_packet(SHELL_A_BUTTON.x, SHELL_A_BUTTON.y); + + assert!(matches!(packet.commands.first(), Some(GfxUiCommand::Clear { .. }))); + assert!(packet.commands.iter().any(|command| { + matches!(command, GfxUiCommand::DrawText { text, .. } if text == "PROMETEU HUB") + })); + } + #[test] fn shell_close_button_sits_inside_shell_frame() { assert!(rect_contains(SHELL_FRAME, CLOSE_BUTTON.x, CLOSE_BUTTON.y)); diff --git a/discussion/index.ndjson b/discussion/index.ndjson index f0776047..a2cd986c 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,5 +1,5 @@ {"type":"meta","next_id":{"DSC":39,"AGD":39,"DEC":31,"PLN":87,"LSN":47,"CLSN":1}} -{"type":"discussion","id":"DSC-0038","status":"in_progress","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-05-25","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-renderframepacket-boundary-for-classic-2d-renderer.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25"}],"decisions":[{"id":"DEC-0030","file":"DEC-0030-logical-render-pipeline-command-boundary.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0073","file":"PLN-0073-render-contract-specs.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0074","file":"PLN-0074-hal-render-submission-types.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0076","file":"PLN-0076-capabilities-and-abi-domain-split.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0077","file":"PLN-0077-composer-buffer-and-game2d-packet.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0078","file":"PLN-0078-classic2d-game-renderer-consumer.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0079","file":"PLN-0079-gfx2d-primitive-domain.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0080","file":"PLN-0080-shell-ui-packet-and-gfxui-domain.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0081","file":"PLN-0081-shell-hub-migration.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0082","file":"PLN-0082-frame-publication-and-present-boundary.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0083","file":"PLN-0083-fade-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0084","file":"PLN-0084-host-debug-overlay-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0085","file":"PLN-0085-pbs-stdlib-and-syscall-declarations.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0086","file":"PLN-0086-end-to-end-render-boundary-validation.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0038","status":"in_progress","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-05-25","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-renderframepacket-boundary-for-classic-2d-renderer.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25"}],"decisions":[{"id":"DEC-0030","file":"DEC-0030-logical-render-pipeline-command-boundary.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0073","file":"PLN-0073-render-contract-specs.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0074","file":"PLN-0074-hal-render-submission-types.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0076","file":"PLN-0076-capabilities-and-abi-domain-split.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0077","file":"PLN-0077-composer-buffer-and-game2d-packet.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0078","file":"PLN-0078-classic2d-game-renderer-consumer.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0079","file":"PLN-0079-gfx2d-primitive-domain.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0080","file":"PLN-0080-shell-ui-packet-and-gfxui-domain.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0081","file":"PLN-0081-shell-hub-migration.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0082","file":"PLN-0082-frame-publication-and-present-boundary.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0083","file":"PLN-0083-fade-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0084","file":"PLN-0084-host-debug-overlay-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0085","file":"PLN-0085-pbs-stdlib-and-syscall-declarations.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0086","file":"PLN-0086-end-to-end-render-boundary-validation.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]}],"lessons":[]} {"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"}]} {"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"discussion/lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} diff --git a/discussion/workflow/plans/PLN-0081-shell-hub-migration.md b/discussion/workflow/plans/PLN-0081-shell-hub-migration.md index dc39c7d7..3ecfaef2 100644 --- a/discussion/workflow/plans/PLN-0081-shell-hub-migration.md +++ b/discussion/workflow/plans/PLN-0081-shell-hub-migration.md @@ -2,7 +2,7 @@ id: PLN-0081 ticket: render-frame-packet-boundary title: Shell Hub Migration -status: open +status: done created: 2026-05-25 ref_decisions: [DEC-0030] tags: [gfx, renderer, runtime, frame-composer, architecture, ui, pipeline]