From 569707d0029d7adfe4c51afb77f5a49008aedc59 Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Fri, 15 May 2026 05:32:42 +0100 Subject: [PATCH] implements PLN-0055 systemos lifecycle api --- crates/console/prometeu-system/src/lib.rs | 2 +- .../prometeu-system/src/os/lifecycle.rs | 18 ++++ crates/console/prometeu-system/src/os/mod.rs | 2 + .../prometeu-system/src/os/system_os.rs | 84 ++++++++++++++++++- discussion/index.ndjson | 2 +- .../PLN-0055-systemos-lifecycle-core-api.md | 2 +- 6 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 crates/console/prometeu-system/src/os/lifecycle.rs diff --git a/crates/console/prometeu-system/src/lib.rs b/crates/console/prometeu-system/src/lib.rs index 78a9ef7f..1773a865 100644 --- a/crates/console/prometeu-system/src/lib.rs +++ b/crates/console/prometeu-system/src/lib.rs @@ -4,7 +4,7 @@ mod programs; mod services; pub use crash_report::CrashReport; -pub use os::SystemOS; +pub use os::{LifecycleError, LifecycleOperation, SystemOS}; pub use programs::PrometeuHub; pub use services::fs; pub use services::process; diff --git a/crates/console/prometeu-system/src/os/lifecycle.rs b/crates/console/prometeu-system/src/os/lifecycle.rs new file mode 100644 index 00000000..bd771d47 --- /dev/null +++ b/crates/console/prometeu-system/src/os/lifecycle.rs @@ -0,0 +1,18 @@ +use crate::process::ProcessId; +use crate::task::{TaskId, TaskState}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LifecycleOperation { + SetForeground, + Suspend, + Resume, + Close, + Crash, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum LifecycleError { + TaskNotFound(TaskId), + ProcessNotFound(ProcessId), + InvalidTransition { task_id: TaskId, from: TaskState, operation: LifecycleOperation }, +} diff --git a/crates/console/prometeu-system/src/os/mod.rs b/crates/console/prometeu-system/src/os/mod.rs index 61995fd9..5a2e6d76 100644 --- a/crates/console/prometeu-system/src/os/mod.rs +++ b/crates/console/prometeu-system/src/os/mod.rs @@ -1,3 +1,5 @@ +mod lifecycle; mod system_os; +pub use lifecycle::{LifecycleError, LifecycleOperation}; pub use system_os::SystemOS; diff --git a/crates/console/prometeu-system/src/os/system_os.rs b/crates/console/prometeu-system/src/os/system_os.rs index 8f9fecee..cfc8a92c 100644 --- a/crates/console/prometeu-system/src/os/system_os.rs +++ b/crates/console/prometeu-system/src/os/system_os.rs @@ -1,11 +1,12 @@ use crate::CrashReport; use crate::VirtualMachineRuntime; use crate::fs::{FsBackend, FsState, VirtualFS}; +use crate::os::{LifecycleError, LifecycleOperation}; use crate::process::ProcessManager; use crate::services::memcard::MemcardService; use crate::services::window_manager::WindowManager; -use crate::task::TaskId; use crate::task::TaskManager; +use crate::task::{TaskId, TaskState}; use prometeu_hal::cartridge::Cartridge; use prometeu_hal::log::{LogLevel, LogService, LogSource}; use prometeu_hal::telemetry::CertificationConfig; @@ -102,7 +103,8 @@ impl SystemOS { let title = title.into(); let process_id = self.process_manager.spawn_vm_game(app_id, title.clone()); let task_id = self.task_manager.create_game_task(process_id, app_id, title); - self.task_manager.set_foreground(task_id); + self.set_foreground_task(task_id) + .expect("newly created game task should have an associated process"); task_id } @@ -111,7 +113,8 @@ impl SystemOS { let title = title.into(); let process_id = self.process_manager.spawn_vm_shell(app_id, title.clone()); let task_id = self.task_manager.create_shell_task(process_id, app_id, title); - self.task_manager.set_foreground(task_id); + self.set_foreground_task(task_id) + .expect("newly created shell task should have an associated process"); task_id } @@ -120,8 +123,81 @@ impl SystemOS { let title = title.into(); let process_id = self.process_manager.spawn_native_shell(app_id, title.clone()); let task_id = self.task_manager.create_shell_task(process_id, app_id, title); - self.task_manager.set_foreground(task_id); + self.set_foreground_task(task_id) + .expect("newly created native shell task should have an associated process"); task_id } + + pub fn set_foreground_task(&mut self, task_id: TaskId) -> Result<(), LifecycleError> { + let process_id = self.process_id_for_task(task_id)?; + + self.task_manager.set_foreground(task_id); + self.process_manager.mark_running(process_id); + + Ok(()) + } + + pub fn suspend_task(&mut self, task_id: TaskId) -> Result<(), LifecycleError> { + let process_id = self.process_id_for_task(task_id)?; + + self.task_manager.mark_suspended(task_id); + self.process_manager.mark_suspended(process_id); + + Ok(()) + } + + pub fn resume_task(&mut self, task_id: TaskId) -> Result<(), LifecycleError> { + let task = self.task_manager.get(task_id).ok_or(LifecycleError::TaskNotFound(task_id))?; + + if task.state != TaskState::Suspended { + return Err(LifecycleError::InvalidTransition { + task_id, + from: task.state, + operation: LifecycleOperation::Resume, + }); + } + + let process_id = self.process_id_for_task(task_id)?; + + self.task_manager.set_foreground(task_id); + self.process_manager.mark_running(process_id); + + Ok(()) + } + + pub fn close_task(&mut self, task_id: TaskId) -> Result<(), LifecycleError> { + let process_id = self.process_id_for_task(task_id)?; + + self.task_manager.close_task(task_id); + self.process_manager.mark_stopped(process_id); + + Ok(()) + } + + pub fn crash_task( + &mut self, + task_id: TaskId, + _report: Option<&CrashReport>, + ) -> Result<(), LifecycleError> { + let process_id = self.process_id_for_task(task_id)?; + + self.task_manager.mark_crashed(task_id); + self.process_manager.mark_crashed(process_id); + + Ok(()) + } + + fn process_id_for_task( + &self, + task_id: TaskId, + ) -> Result { + let task = self.task_manager.get(task_id).ok_or(LifecycleError::TaskNotFound(task_id))?; + + if !self.process_manager.contains(task.process_id) { + return Err(LifecycleError::ProcessNotFound(task.process_id)); + } + + Ok(task.process_id) + } } diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 089be638..b506b2c9 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -30,5 +30,5 @@ {"type":"discussion","id":"DSC-0019","status":"done","ticket":"jenkinsfile-correction","title":"Jenkinsfile Correction and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins"],"agendas":[{"id":"AGD-0017","file":"AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"discussion/lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0030","status":"done","ticket":"internal-viewport-270p","title":"Agenda - Internal Viewport 270p (480x270)","created_at":"2026-04-27","updated_at":"2026-04-28","tags":["gfx","runtime","viewport","resolution","frame-composer","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0039","file":"discussion/lessons/DSC-0030-internal-viewport-270p/LSN-0039-resolution-baseline-changes-are-runtime-wide-contracts.md","status":"done","created_at":"2026-04-28","updated_at":"2026-04-28"}]} {"type":"discussion","id":"DSC-0031","status":"done","ticket":"runtime-mode-separation-game-system","title":"Agenda - Runtime Mode Separation: Game and System","created_at":"2026-05-11","updated_at":"2026-05-14","tags":["runtime","firmware","hub","system-apps","game-mode","scheduler"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0040","file":"discussion/lessons/DSC-0031-runtime-mode-separation-game-system/LSN-0040-system-pipeline-separation.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14"}]} -{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"system-os-lifecycle-process-task-contract","title":"Agenda - SystemOS Lifecycle, Process and Task Contract","created_at":"2026-05-14","updated_at":"2026-05-15","tags":["runtime","os","lifecycle","process","task","shell","firmware"],"agendas":[{"id":"AGD-0032","file":"AGD-0032-system-os-lifecycle-process-task-contract.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-15"}],"decisions":[{"id":"DEC-0025","file":"DEC-0025-systemos-lifecycle-authority-for-tasks-and-processes.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15","ref_agenda":"AGD-0032"}],"plans":[{"id":"PLN-0055","file":"PLN-0055-systemos-lifecycle-core-api.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]},{"id":"PLN-0056","file":"PLN-0056-firmware-lifecycle-delegation.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]},{"id":"PLN-0057","file":"PLN-0057-lifecycle-tests-and-invariants.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0032","status":"in_progress","ticket":"system-os-lifecycle-process-task-contract","title":"Agenda - SystemOS Lifecycle, Process and Task Contract","created_at":"2026-05-14","updated_at":"2026-05-15","tags":["runtime","os","lifecycle","process","task","shell","firmware"],"agendas":[{"id":"AGD-0032","file":"AGD-0032-system-os-lifecycle-process-task-contract.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-15"}],"decisions":[{"id":"DEC-0025","file":"DEC-0025-systemos-lifecycle-authority-for-tasks-and-processes.md","status":"accepted","created_at":"2026-05-15","updated_at":"2026-05-15","ref_agenda":"AGD-0032"}],"plans":[{"id":"PLN-0055","file":"PLN-0055-systemos-lifecycle-core-api.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]},{"id":"PLN-0056","file":"PLN-0056-firmware-lifecycle-delegation.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]},{"id":"PLN-0057","file":"PLN-0057-lifecycle-tests-and-invariants.md","status":"open","created_at":"2026-05-15","updated_at":"2026-05-15","ref_decisions":["DEC-0025"]}],"lessons":[]} {"type":"discussion","id":"DSC-0033","status":"in_progress","ticket":"system-os-service-ownership-and-module-layout","title":"Agenda - SystemOS Service Ownership and Module Layout","created_at":"2026-05-14","updated_at":"2026-05-14","tags":["runtime","os","services","module-layout","vm","window-manager","logging"],"agendas":[{"id":"AGD-0033","file":"AGD-0033-system-os-service-ownership-and-module-layout.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-14"}],"decisions":[{"id":"DEC-0024","file":"DEC-0024-systemos-service-ownership-and-module-layout.md","status":"accepted","created_at":"2026-05-14","updated_at":"2026-05-14","ref_agenda":"AGD-0033"}],"plans":[{"id":"PLN-0051","file":"PLN-0051-move-vm-runtime-into-services.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0024"]},{"id":"PLN-0052","file":"PLN-0052-promote-window-manager-to-systemos-service.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0024"]},{"id":"PLN-0053","file":"PLN-0053-move-logging-ownership-to-systemos.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0024"]},{"id":"PLN-0054","file":"PLN-0054-move-fs-and-memcard-ownership-to-systemos.md","status":"done","created_at":"2026-05-14","updated_at":"2026-05-14","ref_decisions":["DEC-0024"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0055-systemos-lifecycle-core-api.md b/discussion/workflow/plans/PLN-0055-systemos-lifecycle-core-api.md index 100b3d60..51bfd989 100644 --- a/discussion/workflow/plans/PLN-0055-systemos-lifecycle-core-api.md +++ b/discussion/workflow/plans/PLN-0055-systemos-lifecycle-core-api.md @@ -2,7 +2,7 @@ id: PLN-0055 ticket: system-os-lifecycle-process-task-contract title: SystemOS Lifecycle Core API -status: open +status: done created: 2026-05-15 ref_decisions: [DEC-0025] tags: [runtime, os, lifecycle, process, task, shell, firmware]