Compare commits

..

No commits in common. "7307870414ec195fc534202db951fda3a2ced28b" and "23d3ed641e75becdc21d2a8e58fcaaaf5b506454" have entirely different histories.

15 changed files with 48 additions and 729 deletions

View File

@ -179,7 +179,7 @@ mod tests {
use prometeu_hal::cartridge::AssetsPayloadSource; use prometeu_hal::cartridge::AssetsPayloadSource;
use prometeu_hal::color::Color; use prometeu_hal::color::Color;
use prometeu_hal::primitives::Rect; use prometeu_hal::primitives::Rect;
use prometeu_hal::syscalls::{Syscall, caps}; use prometeu_hal::syscalls::caps;
use prometeu_system::CrashReport; use prometeu_system::CrashReport;
use prometeu_system::process::ProcessState; use prometeu_system::process::ProcessState;
use prometeu_system::task::{TaskId, TaskState}; use prometeu_system::task::{TaskId, TaskState};
@ -576,19 +576,4 @@ mod tests {
assert!(matches!(firmware.state, FirmwareState::GameRunning(_))); assert!(matches!(firmware.state, FirmwareState::GameRunning(_)));
assert_eq!(firmware.os.windows().window_count(), 0); assert_eq!(firmware.os.windows().window_count(), 0);
} }
#[test]
fn direct_game_boot_does_not_depend_on_userland_run_cart_syscall() {
assert!(Syscall::from_u32(0x0002).is_none());
let mut firmware = Firmware::new(None);
let mut platform = TestPlatform::new();
let signals = InputSignals::default();
firmware.load_cartridge(valid_cartridge(AppMode::Game));
firmware.tick(&signals, &mut platform);
assert!(matches!(firmware.state, FirmwareState::GameRunning(_)));
assert_eq!(firmware.os.vm().current_cartridge_title(), "Valid Cart");
}
} }

View File

@ -29,6 +29,7 @@ pub use resolver::{
#[repr(u32)] #[repr(u32)]
pub enum Syscall { pub enum Syscall {
SystemHasCart = 0x0001, SystemHasCart = 0x0001,
SystemRunCart = 0x0002,
GfxClear = 0x1001, GfxClear = 0x1001,
GfxFillRect = 0x1002, GfxFillRect = 0x1002,
GfxDrawLine = 0x1003, GfxDrawLine = 0x1003,

View File

@ -1,6 +1,11 @@
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps}; use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
&[SyscallRegistryEntry::builder(Syscall::SystemHasCart, "system", "has_cart") SyscallRegistryEntry::builder(Syscall::SystemHasCart, "system", "has_cart")
.rets(1) .rets(1)
.caps(caps::SYSTEM)]; .caps(caps::SYSTEM),
SyscallRegistryEntry::builder(Syscall::SystemRunCart, "system", "run_cart")
.caps(caps::SYSTEM)
.non_deterministic()
.cost(50),
];

View File

@ -13,6 +13,7 @@ impl Syscall {
pub fn from_u32(id: u32) -> Option<Self> { pub fn from_u32(id: u32) -> Option<Self> {
match id { match id {
0x0001 => Some(Self::SystemHasCart), 0x0001 => Some(Self::SystemHasCart),
0x0002 => Some(Self::SystemRunCart),
0x1001 => Some(Self::GfxClear), 0x1001 => Some(Self::GfxClear),
0x1002 => Some(Self::GfxFillRect), 0x1002 => Some(Self::GfxFillRect),
0x1003 => Some(Self::GfxDrawLine), 0x1003 => Some(Self::GfxDrawLine),
@ -74,6 +75,7 @@ impl Syscall {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
match self { match self {
Self::SystemHasCart => "SystemHasCart", Self::SystemHasCart => "SystemHasCart",
Self::SystemRunCart => "SystemRunCart",
Self::GfxClear => "GfxClear", Self::GfxClear => "GfxClear",
Self::GfxFillRect => "GfxFillRect", Self::GfxFillRect => "GfxFillRect",
Self::GfxDrawLine => "GfxDrawLine", Self::GfxDrawLine => "GfxDrawLine",

View File

@ -72,33 +72,6 @@ fn resolver_rejects_removed_legacy_gfx_set_sprite_identity() {
assert_eq!(err, LoadError::UnknownSyscall { module: "gfx2d", name: "set_sprite", version: 1 }); assert_eq!(err, LoadError::UnknownSyscall { module: "gfx2d", name: "set_sprite", version: 1 });
} }
#[test]
fn resolver_rejects_userland_system_run_cart_identity() {
assert!(Syscall::from_u32(0x0002).is_none());
assert!(resolve_syscall("system", "run_cart", 1).is_none());
let requested = [SyscallIdentity { module: "system", name: "run_cart", version: 1 }];
let err = resolve_program_syscalls(&requested, caps::ALL).unwrap_err();
assert_eq!(err, LoadError::UnknownSyscall { module: "system", name: "run_cart", version: 1 });
let declared = [prometeu_bytecode::SyscallDecl {
module: "system".into(),
name: "run_cart".into(),
version: 1,
arg_slots: 0,
ret_slots: 0,
}];
let err = resolve_declared_program_syscalls(&declared, caps::ALL).unwrap_err();
assert_eq!(
err,
DeclaredLoadError::UnknownSyscall {
module: "system".into(),
name: "run_cart".into(),
version: 1,
}
);
}
#[test] #[test]
fn resolver_enforces_capabilities() { fn resolver_enforces_capabilities() {
let requested = [SyscallIdentity { module: "gfx2d", name: "clear", version: 1 }]; let requested = [SyscallIdentity { module: "gfx2d", name: "clear", version: 1 }];

View File

@ -168,9 +168,13 @@ impl NativeInterface for VmRuntimeHost<'_> {
VmFault::Trap(TRAP_INVALID_SYSCALL, format!("Unknown syscall: 0x{:08X}", id)) VmFault::Trap(TRAP_INVALID_SYSCALL, format!("Unknown syscall: 0x{:08X}", id))
})?; })?;
if syscall == Syscall::SystemHasCart { match syscall {
ret.push_bool(true); Syscall::SystemHasCart => {
return Ok(()); ret.push_bool(true);
return Ok(());
}
Syscall::SystemRunCart => return Ok(()),
_ => {}
} }
self.ensure_game_profile_syscall(syscall)?; self.ensure_game_profile_syscall(syscall)?;
@ -179,6 +183,7 @@ impl NativeInterface for VmRuntimeHost<'_> {
match syscall { match syscall {
Syscall::SystemHasCart => unreachable!(), Syscall::SystemHasCart => unreachable!(),
Syscall::SystemRunCart => unreachable!(),
Syscall::GfxClear => { Syscall::GfxClear => {
let color = self.get_color(expect_int(args, 0)?)?; let color = self.get_color(expect_int(args, 0)?)?;
self.gfx2d_commands.push(Gfx2dCommand::Clear { color }); self.gfx2d_commands.push(Gfx2dCommand::Clear { color });

View File

@ -1,5 +1,4 @@
{"type":"meta","next_id":{"DSC":44,"AGD":45,"DEC":36,"PLN":132,"LSN":51,"CLSN":1}} {"type":"meta","next_id":{"DSC":43,"AGD":44,"DEC":35,"PLN":129,"LSN":51,"CLSN":1}}
{"type":"discussion","id":"DSC-0043","status":"open","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-03","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[{"id":"AGD-0044","file":"AGD-0044-systemos-cartridge-switch-orchestrator.md","status":"open","created_at":"2026-07-03","updated_at":"2026-07-03"}],"decisions":[],"plans":[],"lessons":[]}
{"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-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-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-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":[]}
@ -14,7 +13,7 @@
{"type":"discussion","id":"DSC-0001","status":"done","ticket":"legacy-runtime-learn-import","title":"Import legacy runtime learn into discussion lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["migration","tech-debt"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0001-prometeu-learn-index.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0002-historical-asset-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0003-historical-audio-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0004-historical-cartridge-boot-protocol-and-manifest-authority.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0005-historical-game-memcard-slots-surface-and-semantics.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0006-historical-gfx-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0007-historical-retired-fault-and-input-decisions.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0008-historical-vm-core-and-assets.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0009","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0010-mental-model-audio.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0012-mental-model-input.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0013-mental-model-observability-and-debugging.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0014-mental-model-portability-and-cross-platform.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0015-mental-model-save-memory-and-memcard.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0016-mental-model-status-first-and-fault-thinking.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0017-mental-model-time-and-cycles.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0018","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0018-mental-model-touch.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]} {"type":"discussion","id":"DSC-0001","status":"done","ticket":"legacy-runtime-learn-import","title":"Import legacy runtime learn into discussion lessons","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["migration","tech-debt"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0001","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0001-prometeu-learn-index.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0002","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0002-historical-asset-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0003","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0003-historical-audio-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0004","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0004-historical-cartridge-boot-protocol-and-manifest-authority.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0005","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0005-historical-game-memcard-slots-surface-and-semantics.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0006","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0006-historical-gfx-status-first-fault-and-return-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0007","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0007-historical-retired-fault-and-input-decisions.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0008","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0008-historical-vm-core-and-assets.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0009","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0009-mental-model-asset-management.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0010","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0010-mental-model-audio.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0011","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0011-mental-model-gfx.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0012","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0012-mental-model-input.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0013","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0013-mental-model-observability-and-debugging.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0014","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0014-mental-model-portability-and-cross-platform.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0015","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0015-mental-model-save-memory-and-memcard.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0016","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0016-mental-model-status-first-and-fault-thinking.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0017","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0017-mental-model-time-and-cycles.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"},{"id":"LSN-0018","file":"discussion/lessons/DSC-0001-runtime-learn-legacy-import/LSN-0018-mental-model-touch.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
{"type":"discussion","id":"DSC-0002","status":"done","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-04-21","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0002-runtime-edge-test-plan/LSN-0037-domain-gates-must-be-owned-by-the-repository.md","status":"done","created_at":"2026-04-21","updated_at":"2026-04-21"}]} {"type":"discussion","id":"DSC-0002","status":"done","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-04-21","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0037","file":"discussion/lessons/DSC-0002-runtime-edge-test-plan/LSN-0037-domain-gates-must-be-owned-by-the-repository.md","status":"done","created_at":"2026-04-21","updated_at":"2026-04-21"}]}
{"type":"discussion","id":"DSC-0003","status":"open","ticket":"packed-cartridge-loader-pmc","title":"Agenda - Packed Cartridge Loader PMC","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0002","file":"AGD-0002-packed-cartridge-loader-pmc.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0003","status":"open","ticket":"packed-cartridge-loader-pmc","title":"Agenda - Packed Cartridge Loader PMC","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0002","file":"AGD-0002-packed-cartridge-loader-pmc.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0004","status":"in_progress","ticket":"system-run-cart","title":"Agenda - System Run Cart","created_at":"2026-03-27","updated_at":"2026-07-03","tags":[],"agendas":[{"id":"AGD-0003","file":"AGD-0003-system-run-cart.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-07-03"}],"decisions":[{"id":"DEC-0035","file":"DEC-0035-remove-userland-system-run-cart-and-preserve-direct-boot.md","status":"accepted","created_at":"2026-07-03","updated_at":"2026-07-03","ref_agenda":"AGD-0003"}],"plans":[{"id":"PLN-0129","file":"PLN-0129-remove-userland-run-cart-abi-surface.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0035"]},{"id":"PLN-0130","file":"PLN-0130-remove-runtime-run-cart-stub-dispatch.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0035"]},{"id":"PLN-0131","file":"PLN-0131-preserve-direct-cartridge-boot-coverage.md","status":"done","created_at":"2026-07-03","updated_at":"2026-07-03","ref_decisions":["DEC-0035"]}],"lessons":[]} {"type":"discussion","id":"DSC-0004","status":"open","ticket":"system-run-cart","title":"Agenda - System Run Cart","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0003","file":"AGD-0003-system-run-cart.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0005","status":"open","ticket":"system-fault-semantics-and-control-surface","title":"Agenda - System Fault Semantics and Control Surface","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0004","file":"AGD-0004-system-fault-semantics-and-control-surface.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0005","status":"open","ticket":"system-fault-semantics-and-control-surface","title":"Agenda - System Fault Semantics and Control Surface","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0004","file":"AGD-0004-system-fault-semantics-and-control-surface.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0006","status":"open","ticket":"vm-owned-random-service","title":"Agenda - VM-Owned Random Service","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0005","file":"AGD-0005-vm-owned-random-service.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0006","status":"open","ticket":"vm-owned-random-service","title":"Agenda - VM-Owned Random Service","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0005","file":"AGD-0005-vm-owned-random-service.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
{"type":"discussion","id":"DSC-0007","status":"open","ticket":"app-home-filesystem-surface-and-semantics","title":"Agenda - App Home Filesystem Surface and Semantics","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0006","file":"AGD-0006-app-home-filesystem-surface-and-semantics.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0007","status":"open","ticket":"app-home-filesystem-surface-and-semantics","title":"Agenda - App Home Filesystem Surface and Semantics","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0006","file":"AGD-0006-app-home-filesystem-surface-and-semantics.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}

View File

@ -2,7 +2,7 @@
id: AGD-0003 id: AGD-0003
ticket: system-run-cart ticket: system-run-cart
title: Agenda - System Run Cart title: Agenda - System Run Cart
status: accepted status: open
created: 2026-03-27 created: 2026-03-27
resolved: resolved:
decision: decision:
@ -13,14 +13,11 @@ tags: []
## Problema ## Problema
`system.run_cart` existe na ABI pública, mas hoje não produz efeito real no runtime. A syscall `system.run_cart` existe na ABI pública, mas hoje não produz efeito real no runtime.
Isso expõe duas questões: a superfície atual é um placebo e, mesmo quando houver
fluxo real, rodar cartuchos não deve ser uma operação userland. A autoridade
para iniciar cartuchos deve pertencer ao sistema/firmware.
Isso cria uma falsa promessa de plataforma: Isso cria uma falsa promessa de plataforma:
- o programa consegue declarar e chamar uma operação que aparenta iniciar cartuchos; - o programa consegue declarar e chamar a syscall;
- o loader aceita sua existência; - o loader aceita sua existência;
- o runtime retorna sucesso vazio; - o runtime retorna sucesso vazio;
- nenhuma troca de cartucho, transição de firmware, validação de alvo ou política de segurança ocorre. - nenhuma troca de cartucho, transição de firmware, validação de alvo ou política de segurança ocorre.
@ -28,92 +25,56 @@ Isso cria uma falsa promessa de plataforma:
## Dor ## Dor
- A ABI expõe uma capability de sistema que, na prática, nao existe. - A ABI expõe uma capability de sistema que, na prática, nao existe.
- Mesmo se implementada, a operação não deve ser uma syscall userland comum:
apps não devem iniciar cartuchos diretamente.
- O guest pode acreditar que solicitou uma troca de app quando nada aconteceu. - O guest pode acreditar que solicitou uma troca de app quando nada aconteceu.
- Isso corrói a confiabilidade da plataforma: a interface pública deixa de ser contrato e vira placebo. - Isso corrói a confiabilidade da plataforma: a interface pública deixa de ser contrato e vira placebo.
- Qualquer ferramenta, SDK ou documentação construída sobre essa syscall passa a modelar um comportamento inexistente. - Qualquer ferramenta, SDK ou documentação construída sobre essa syscall passa a modelar um comportamento inexistente.
## Alvo da Discussao ## Alvo da Discussao
Definir o contrato real da troca de cartucho iniciada pelo sistema do ponto de vista: Definir o contrato real de `system.run_cart` do ponto de vista:
- do guest; - do guest;
- do runtime; - do runtime;
- do firmware; - do firmware;
- do host/cartridge loader. - do host/cartridge loader.
Ao final da discussão, deve ficar claro se a superfície atual: Ao final da discussão, deve ficar claro se a syscall:
- permanece apenas como mecanismo interno do sistema e sai da ABI userland; ou - permanece na ABI e ganha implementação completa; ou
- permanece na ABI somente como superfície privilegiada impossível de chamar por apps comuns; ou
- sai temporariamente da ABI até existir fluxo fechado. - sai temporariamente da ABI até existir fluxo fechado.
Esta discussao nao deve depender do fechamento previo do formato `.pmc`.
Para o primeiro fluxo fechado, `system.run_cart` pode resolver um alvo por
um loader ja disponivel, incluindo cartucho em diretorio ou fixture de teste.
O suporte ao artefato empacotado `.pmc` permanece responsabilidade da
`DSC-0003 / packed-cartridge-loader-pmc` e nao deve bloquear a prova inicial
de troca `Shell/Hub -> Game`.
Tambem precisa ficar claro que `run_cart`, se existir, nao e o orquestrador da
troca. No boot direto por linha de comando, carregar um cartucho e simples
porque o runtime nasce ja apontado para aquele jogo. Com o SO em execucao, o
caso real e diferente: pode haver um Game residente/rodando, o usuario volta
para Home, e o sistema decide iniciar outro Game. Nesse caso o SO precisa
orquestrar fechamento/suspensao descartada do app atual, limpeza de estado,
resolucao do novo alvo, carregamento e transicao para o proximo estado de
firmware. O carregador de cartucho e apenas uma etapa desse fluxo.
A direcao preferida e que a orquestracao de troca de cartucho viva no
SystemOS. Porem, essa agenda nao deve capturar o caso `Game -> Home -> mesmo
Game`: esse e o escopo da `AGD-0041`, que precisa fechar foreground,
pausa/suspensao e retorno ao mesmo Game. A troca `Home -> outro Game`, com
fechamento do jogo atual e carregamento de outro cartucho, pode merecer uma
agenda propria depois da `AGD-0041`, derivada do contrato de foreground que ela
fechar.
## O Que Precisa Ser Definido ## O Que Precisa Ser Definido
1. Semântica da operação. 1. Semântica da operação.
O que significa "run cart" quando existe SO: trocar imediatamente, O que significa "run cart": trocar imediatamente, agendar para o próximo frame, retornar ao firmware, reiniciar VM atual, ou apenas emitir uma intenção?
agendar para o próximo frame, iniciar uma transicao orquestrada pelo
sistema, ou apenas carregar bytes de cartucho como etapa interna?
2. Origem do alvo. 2. Origem do alvo.
Como o guest identifica o cartucho alvo: id numérico, nome canônico, path virtual, handle, manifesto, ou nenhum argumento nesta primeira versão? Como o guest identifica o cartucho alvo: id numérico, nome canônico, path virtual, handle, manifesto, ou nenhum argumento nesta primeira versão?
Para v1, uma opcao aceitavel e limitar a resolucao a alvos conhecidos pelo host/test harness e carregaveis pelo loader de diretorio, deixando `.pmc` fora do caminho critico.
3. Modelo de segurança. 3. Modelo de segurança.
Nenhum app/userland deve chamar `run_cart`. O sistema/firmware e o caminho Quem pode chamar isso, sob qual capability, e com quais restrições para evitar que um app force navegação arbitrária do sistema?
host/CLI/debug devem ser as unicas autoridades para iniciar cartuchos.
Se apps precisarem solicitar navegacao no futuro, isso deve ser uma
superficie nova e mediada pelo sistema.
4. Ponto de integração. 4. Ponto de integração.
Onde a transição vive: `VirtualMachineRuntime`, firmware, host, SystemOS, Onde a transição vive: `VirtualMachineRuntime`, firmware, host, ou combinação dos três?
ou combinação dos três? Para esta agenda, a decisao minima e separar o boot
direto host/CLI/debug da ABI guest. A orquestracao `Home -> outro Game`
pertence a `DSC-0043 / AGD-0044`.
5. Efeitos observáveis. 5. Efeitos observáveis.
O que acontece quando um guest tenta chamar a superficie removida, e como O que acontece com:
ferramentas/boot direto continuam carregando cartuchos sem depender de uma - estado do app atual;
syscall userland? - FS aberto;
- assets carregados;
- telemetria;
- crash reports;
- logs.
6. Contrato de erro. 6. Contrato de erro.
Remocao da ABI significa erro de build/declaracao, syscall desconhecida, Quais falhas retornam trap ao guest e quais viram evento de sistema.
ou bloqueio em registro/capability ate a limpeza completa das declaracoes?
## O Que Necessita Para Resolver ## O Que Necessita Para Resolver
- remocao de `system.run_cart` da ABI userland; - fluxo fechado entre syscall -> runtime -> firmware -> loader -> novo app;
- definicao de que boot direto continua por caminho host/CLI/debug, nao por - modelo explícito para seleção do alvo;
syscall guest; - definição de lifecycle da troca de cartucho;
- separacao explicita entre boot direto, loader interno e orquestracao - testes de integração cobrindo transição bem-sucedida, alvo inválido, capability insuficiente e cleanup de estado.
`Home -> outro Game` da `DSC-0043 / AGD-0044`;
- testes garantindo que guest/userland nao pode declarar/chamar `run_cart`;
- testes garantindo que boot direto de cartucho continua funcional.
## Fora de Escopo ## Fora de Escopo
@ -121,82 +82,13 @@ fechar.
- UX final do launcher/hub; - UX final do launcher/hub;
- resolução remota ou download de cartuchos; - resolução remota ou download de cartuchos;
- política de marketplace/distribuição. - política de marketplace/distribuição.
- obrigatoriedade de boot a partir de `.pmc` no primeiro fluxo funcional.
## Sugestao / Recomendacao
Recomendo remover `system.run_cart` da ABI userland para v1. Nao ha necessidade
de compatibilidade com a superficie atual: ela nao deve permanecer como stub,
syscall reservada chamavel por guest, nem sucesso vazio.
Rodar cartuchos deve ser uma operacao interna do SystemOS/firmware ou do
caminho host/CLI/debug, nunca uma syscall de app. O boot direto deve continuar
existindo porque e o fluxo essencial para testar cartuchos em desenvolvimento e
tambem representa o modo futuro de executar um jogo unico, como em uma
integracao tipo Steam.
Recomendo tambem separar dois conceitos:
- **boot direto:** usado por linha de comando/debug, inicia o runtime ja com um
cartucho alvo e pode continuar simples;
- **troca via SO:** fluxo orquestrado pelo SystemOS, que fecha o app
atual quando necessario, limpa estado cartridge-scoped, resolve o proximo
alvo e so entao chama o carregador.
Essa agenda nao deve implementar o fluxo `Game -> Home -> mesmo Game`; esse
trabalho pertence a `AGD-0041`. Depois dela, a troca `Home -> outro Game` deve
ser aberta ou refinada como discussao propria, porque adiciona fechamento do
jogo atual, limpeza cartridge-scoped, resolucao de novo alvo e falhas de load.
Se a plataforma precisar de uma ação solicitável por apps no futuro, ela deve
ser modelada separadamente como pedido de navegação mediado pelo sistema, com
nome e erros que não prometam boot direto.
## Respostas Atuais
- `system.run_cart` deve ser removido da ABI userland.
- Nao precisamos manter compatibilidade com a superficie atual.
- Nao deve existir syscall publica para app iniciar cartucho.
- Boot direto por linha de comando, host, debug ou fluxo equivalente de jogo
unico deve permanecer.
- O carregamento interno pode continuar usando loader ja disponivel, incluindo
cartucho em diretorio/fixture.
- `.pmc`, catalogo, UX final de launcher e troca `Game A -> Home -> Game B`
ficam fora desta agenda.
- Se no futuro apps precisarem pedir navegacao, isso deve ser uma nova
superficie mediada pelo sistema, nao a volta de `run_cart` userland.
## Critério de Saida Desta Agenda ## Critério de Saida Desta Agenda
Esta agenda só pode virar PR de implementação quando existir decisão escrita para: Esta agenda só pode virar PR de implementação quando existir decisão escrita para:
- retirada da superfície userland atual; - assinatura final da syscall;
- preservacao explicita do boot direto host/CLI/debug; - local canônico da troca de estado;
- comportamento esperado para declaracao/chamada guest obsoleta; - política de erro;
- fronteira com `AGD-0041` e `AGD-0044`; - limpeza de recursos;
- cobertura minima de testes para remocao userland e boot direto. - cobertura mínima de testes de integração.
## Discussao
- 2026-07-03: A agenda deve ser aberta antes da `AGD-0041` como habilitadora
de validacao do ciclo `Shell/Hub -> Game`. Ficou definido como premissa de
agenda que o primeiro `system.run_cart` testavel nao depende de `.pmc`; ele
pode usar cartucho em diretorio ou fixture resolvida pelo host/test harness.
- 2026-07-03: Direcao ajustada: `run_cart` nao deve ser uma operacao userland.
A autoridade de iniciar cartuchos deve pertencer ao sistema/firmware; apps
podem, no maximo, solicitar navegacao por uma superficie separada e mediada.
- 2026-07-03: Direcao refinada: `run_cart` simples nao resolve o caso com SO.
Boot direto por linha de comando continua sendo um caminho simples, mas
iniciar outro jogo a partir do Home exige um orquestrador do SO/firmware que
fecha o app atual, limpa estado e so entao carrega o novo cartucho.
- 2026-07-03: Escopo refinado: `Game -> Home -> mesmo Game` pertence a
`AGD-0041`. A agenda atual nao deve absorver esse trabalho. Depois da
`AGD-0041`, a troca `Home -> outro Game` pode ser aberta ou refinada como
agenda propria para o orquestrador de troca de cartucho no SystemOS.
- 2026-07-03: A troca `Game A -> Home -> Game B` foi separada para
`DSC-0043 / AGD-0044`, mantendo esta agenda focada na superficie
`run_cart`/loader e sua remocao ou restricao como operacao userland.
- 2026-07-03: Direcao aceita para esta agenda: remover `system.run_cart` da ABI
userland sem necessidade de compatibilidade, manter boot direto para
CLI/debug/teste de cartuchos e futuro modo de jogo unico, e deixar navegacao
mediada por apps para uma superficie futura separada se ela vier a existir.

View File

@ -1,145 +0,0 @@
---
id: AGD-0044
ticket: system-os-cartridge-switch-orchestrator
title: SystemOS Cartridge Switch Orchestrator
status: open
created: 2026-07-03
resolved:
decision:
tags: [runtime, os, lifecycle, game, cartridge, architecture]
---
## Contexto
A `AGD-0041` cobre o caso `Game -> Home/Shell -> mesmo Game`: o usuario sai do
foreground do jogo, o SO assume a tela, Shell/Hub pode rodar, e depois o mesmo
Game e retomado.
Existe um segundo caso, diferente, que nao deve ser escondido dentro da
`AGD-0041`: `Game A -> Home -> Game B`.
Nesse fluxo, o usuario esta com um Game rodando, aperta Home, volta para o SO e
pede para iniciar outro jogo. O SystemOS nao deve simplesmente chamar um loader
por cima do estado atual. Ele precisa orquestrar a substituicao do app corrente:
fechar ou descartar o Game residente, limpar estado cartridge-scoped, resolver o
novo alvo, carregar o proximo cartucho e entrar no novo estado de firmware.
Essa agenda tambem se relaciona com a `AGD-0003 / system-run-cart`: `run_cart`,
se existir, nao e userland e nao e o orquestrador. O carregador de cartucho e
apenas uma etapa dentro de uma transicao comandada pelo SystemOS.
## Problema
Sem um orquestrador explicito de troca de cartucho no SystemOS, a plataforma
pode cair em estados incoerentes:
- carregar um novo Game sem fechar corretamente o Game anterior;
- reaproveitar estado VM, assets, input, audio, render ou telemetria do cartucho
anterior;
- misturar boot direto por linha de comando com troca de app sob o SO;
- deixar o loader decidir lifecycle, quando ele deveria apenas materializar o
cartucho alvo;
- tentar implementar `Home -> outro Game` antes de existir o contrato de
foreground/pausa definido pela `AGD-0041`.
## Pontos Criticos
- Esta agenda deve ser executada depois da `AGD-0041`.
- `Game -> Home -> mesmo Game` fica fora desta agenda.
- O SystemOS deve ser a autoridade da troca entre cartuchos sob o SO.
- O loader nao deve possuir politica de fechamento, pausa, foreground ou
cleanup.
- Boot direto por CLI/debug continua sendo caminho separado e mais simples.
- A troca para outro Game deve tratar falha de load sem deixar o sistema em
estado parcialmente substituido.
- `.pmc`, catalogo completo e UX final de launcher continuam fora de escopo,
salvo se forem necessarios para definir o contrato minimo.
## Opcoes
### Opcao A - Adiar tudo para depois da AGD-0041
- **Abordagem:** manter esta agenda como registro de escopo futuro; primeiro
fechar e implementar o contrato `Game -> Home -> mesmo Game`.
- **Pro:** evita misturar pausa/resume com substituicao de cartucho; reduz risco
de reabrir arquitetura durante a `AGD-0041`.
- **Contra:** a plataforma continua sem troca `Home -> outro Game` ate uma etapa
posterior.
- **Manutenibilidade:** alta, porque cada agenda fecha um eixo de lifecycle.
### Opcao B - Definir agora o contrato conceitual, implementar depois
- **Abordagem:** fechar uma decisao curta ja dizendo que o orquestrador pertence
ao SystemOS, que `run_cart` nao e userland, e que a execucao depende da
`AGD-0041`; o plano de codigo fica para depois.
- **Pro:** reduz ambiguidade enquanto trabalhamos na `AGD-0041`.
- **Contra:** pode produzir uma decisao com pouca evidencia operacional antes
do contrato de foreground estar fechado.
- **Manutenibilidade:** boa se a decisao for claramente marcada como dependente
da `AGD-0041`.
### Opcao C - Implementar o orquestrador completo agora
- **Abordagem:** tentar resolver `Game A -> Home -> Game B` antes ou junto da
`AGD-0041`.
- **Pro:** ataca o fluxo final diretamente.
- **Contra:** mistura pausa/resume, fechamento, cleanup, resolucao de alvo e
falha de load em uma unica frente; alto risco de contrato instavel.
- **Manutenibilidade:** baixa para v1, porque a troca completa depende do
contrato de foreground ainda aberto.
## Sugestao / Recomendacao
Recomendo a Opcao A agora, com esta agenda aberta como marcador explicito de
escopo futuro.
A ordem preferida passa a ser:
1. fechar a `AGD-0041` para definir foreground, pausa/suspensao, Shell no
foreground e retorno ao mesmo Game;
2. voltar para esta agenda e decidir o contrato do orquestrador de troca de
cartucho no SystemOS;
3. so entao planejar a execucao de `Game A -> Home -> Game B`.
Se durante a `AGD-0041` aparecer uma decisao que exige antecipar parte do
orquestrador, esta agenda deve ser reaberta/atualizada com a dependencia
concreta em vez de esconder a troca de cartucho dentro da agenda de foreground.
## Perguntas em Aberto
- [ ] Depois da `AGD-0041`, qual estado representa um Game que sera descartado
em vez de retomado?
- [ ] O fechamento do Game atual e observavel para o firmware/game, ou e uma
destruicao interna do SystemOS?
- [ ] Quais estados cartridge-scoped devem ser limpos antes do novo load: VM,
assets, FS handles, input, audio, render ownership, telemetry, logs?
- [ ] Se o novo cartucho falha ao carregar, o sistema volta ao Home, mostra uma
tela de erro, ou tenta preservar o Game anterior?
- [ ] Como a resolucao do novo alvo e representada sem depender de catalogo
completo ou `.pmc`?
- [ ] Qual evidencia minima prova `Game A -> Home -> Game B` sem depender de UX
final de launcher?
## Criterio para Encerrar
A agenda pode virar decisao quando:
- a `AGD-0041` tiver fechado o contrato de foreground/pausa/resume;
- estiver claro que o orquestrador pertence ao SystemOS;
- `run_cart`/loader estiver limitado a etapa interna, nao userland;
- existir regra para fechar/descartar o Game atual;
- existir contrato de limpeza de estado cartridge-scoped;
- existir politica para falha de carregamento do novo Game;
- houver criterio de teste minimo para `Game A -> Home -> Game B`.
## Discussao
- 2026-07-03: Agenda criada a partir da separacao entre `AGD-0041`
(`Game -> Home -> mesmo Game`) e `AGD-0003` (`run_cart`/loader nao userland).
O novo escopo cobre a troca posterior `Game A -> Home -> Game B`, com
orquestracao pelo SystemOS depois que o contrato de foreground estiver
fechado.
## Resolution
Ainda em aberto.

View File

@ -1,136 +0,0 @@
---
id: DEC-0035
ticket: system-run-cart
title: Remove Userland system.run_cart and Preserve Direct Boot
status: accepted
created: 2026-07-03
ref_agenda: AGD-0003
tags: []
---
## Status
Accepted.
## Contexto
`system.run_cart` existe na ABI publica, mas nao possui comportamento real de
troca de cartucho. Isso cria uma falsa promessa: um guest pode declarar/chamar
uma operacao que aparenta iniciar outro cartucho, enquanto o runtime retorna
sucesso vazio ou nao executa uma transicao completa.
A discussao fechou tres separacoes:
- boot direto por host/CLI/debug e necessario e deve permanecer;
- apps/userland nao devem iniciar cartuchos diretamente;
- troca `Game A -> Home -> Game B` exige um orquestrador de SystemOS proprio,
separado em `DSC-0043 / AGD-0044`.
`AGD-0041` permanece responsavel por `Game -> Home -> mesmo Game`, foreground,
pausa/suspensao e retorno ao mesmo Game.
## Decisao
`system.run_cart` MUST be removed from the userland guest ABI.
No app, cartridge, Shell app, or other userland guest code MAY directly request
cartridge boot through `system.run_cart`.
The platform MUST NOT preserve compatibility for the current userland
`system.run_cart` surface. It MUST NOT remain as a callable stub, reserved
guest syscall that returns success, or capability-gated userland escape hatch.
Direct boot MUST remain supported through host/CLI/debug or equivalent
single-game launch paths. This direct boot path is a host/system entrypoint,
not a guest syscall.
Internal cartridge loading MAY continue to use the existing loader path,
including directory cartridges and test fixtures. `.pmc` support is not required
by this decision.
If apps ever need to request navigation in the future, that MUST be designed as
a separate SystemOS-mediated surface with different naming and semantics. It
MUST NOT reintroduce userland `run_cart` as direct cartridge boot.
## Rationale
Direct cartridge boot is essential for development, debugging, automated tests,
and future distribution modes where the runtime launches as a single game. That
use case does not require a guest-visible syscall.
Userland cartridge boot would give app code authority over system navigation,
lifecycle, cleanup, target resolution, and failure policy. Those concerns belong
to SystemOS/firmware and later to the cartridge switch orchestrator, not to a VM
guest syscall.
Keeping a stub or compatibility surface would preserve the current ambiguity.
The public ABI should not advertise an operation that either does nothing or
looks like direct app-controlled navigation.
## Invariantes / Contrato
- Guest/userland MUST NOT expose or call `system.run_cart`.
- The public syscall registry, declarations, generated bindings, and docs MUST
stop presenting `system.run_cart` as an app-callable operation.
- Booting a cartridge directly MUST remain available from host/CLI/debug flows.
- Direct boot MUST enter the runtime with a selected cartridge target; it MUST
NOT depend on a guest syscall issued after VM startup.
- Loader code MAY remain reusable by host/firmware/SystemOS internals.
- Loader code MUST NOT become lifecycle orchestration authority.
- `Game -> Home -> same Game` remains owned by `AGD-0041`.
- `Game A -> Home -> Game B` remains owned by `DSC-0043 / AGD-0044`.
- `.pmc`, app catalog, launcher UX, marketplace/distribution, and full cartridge
replacement under Home are outside this decision.
## Impactos
- **Spec / ABI:** remove or retire `system.run_cart` from the userland syscall
surface. Any syscall table, PBS declarations, generated metadata, or docs
must stop advertising it to apps.
- **Runtime / VM:** guest dispatch must no longer treat `system.run_cart` as a
valid userland operation. If obsolete bytecode or declarations still reach the
runtime during migration, they must fail explicitly rather than report success.
- **Firmware / Host:** direct boot remains supported for command-line,
debugger, test harness, and future single-game launch flows.
- **SystemOS:** no new cart-switch orchestrator is required by this decision.
That work is deferred to `DSC-0043 / AGD-0044`.
- **Tooling:** tools must continue to support direct cartridge launch for
development and test workflows, without relying on a guest syscall.
- **Tests:** coverage must prove both sides: userland cannot declare/call
`system.run_cart`, and direct boot of a cartridge still works.
## Alternativas Descartadas
- **Implement `system.run_cart` as a normal syscall:** rejected because it gives
userland direct navigation authority and mixes guest execution with system
lifecycle.
- **Keep a compatibility stub:** rejected because no compatibility is required
and a stub preserves the false contract.
- **Make `system.run_cart` privileged but still guest-visible:** rejected for v1
because it keeps the ambiguous idea that some guest profile may directly boot
cartuchos.
- **Implement full `Home -> another Game` now:** rejected for this decision; it
requires SystemOS orchestration after the `AGD-0041` foreground contract.
## Referencias
- Agenda: `AGD-0003`
- Foreground/pause scope: `AGD-0041`
- Future cartridge switch orchestrator: `DSC-0043 / AGD-0044`
- Related lessons: `LSN-0041` SystemOS lifecycle authority, `LSN-0042`
SystemOS service ownership boundary, `LSN-0043` SystemOS domain facades.
## Propagacao Necessaria
- Remove `SystemRunCart` from userland ABI declarations and generated syscall
metadata.
- Remove or rewrite runtime dispatch paths that return success for
`system.run_cart`.
- Preserve host/CLI/debug direct boot paths and add regression tests for them.
- Add negative tests for guest/userland declaration or call attempts.
- Update any documentation/spec text that describes `system.run_cart` as
app-callable.
## Revision Log
- 2026-07-03: Initial draft from `AGD-0003`.

View File

@ -1,90 +0,0 @@
---
id: PLN-0129
ticket: system-run-cart
title: Remove Userland Run Cart ABI Surface
status: done
created: 2026-07-03
ref_decisions: [DEC-0035]
tags: []
---
## Briefing
`DEC-0035` removes `system.run_cart` from the userland guest ABI. This plan
covers the public ABI, syscall registry/declaration surface, generated metadata,
and documentation/spec propagation. It does not change runtime dispatch behavior
or direct boot tests; those are covered by `PLN-0130` and `PLN-0131`.
## Objective
Remove `system.run_cart` from every app-callable/userland ABI surface while
preserving non-guest direct boot entrypoints.
## Dependencies
- Source decision: `DEC-0035`.
- Must stay scoped away from `AGD-0041` and `AGD-0044`.
- Coordinate with `PLN-0130` so runtime dispatch does not retain a callable
success path after the declaration is removed.
## Scope
- Remove or retire `Syscall::SystemRunCart` from userland-visible syscall
declarations in `crates/console/prometeu-hal/src/syscalls.rs`.
- Remove the `system.run_cart` registry entry from
`crates/console/prometeu-hal/src/syscalls/domains/system.rs` and
`crates/console/prometeu-hal/src/syscalls/registry.rs`, unless implementation
discovers an internal-only registry distinct from guest ABI.
- Remove generated/static bytecode or VM-facing declarations that expose
`system.run_cart`, including known references in
`crates/console/prometeu-bytecode/src/model.rs` and
`crates/console/prometeu-vm/src/virtual_machine.rs` if they include it.
- Update docs/specs that mention `system.run_cart` as app-callable.
- Update `AGD-0004` references only if they become factually misleading after
removal; do not close or reinterpret that agenda.
## Non-Goals
- Do not implement `Home -> another Game`.
- Do not add a replacement app navigation syscall.
- Do not implement `.pmc`.
- Do not change direct host/CLI/debug boot behavior.
- Do not add compatibility stubs for obsolete guest code.
## Execution Method
1. Search for `SystemRunCart`, `run_cart`, and `"system", "run_cart"` across
`crates/`, `docs/`, and `discussion/`.
2. Remove `system.run_cart` from userland syscall domain declarations and
lookup/name registries.
3. Remove generated/static guest-facing metadata entries that advertise
`system.run_cart`.
4. Update docs/specs to state that cartridges are booted by host/system paths,
not by guest syscall.
5. Compile the workspace or targeted crates to find stale references.
## Acceptance Criteria
- No userland ABI declaration advertises `system.run_cart`.
- No generated guest metadata exposes `run_cart` as callable.
- Documentation/spec text no longer describes app-callable cartridge boot.
- Any retained code path is clearly internal-only and is not reachable through
guest syscall lookup.
## Tests
- Add or update syscall registry tests to assert `system.run_cart` is absent
from the public/userland registry.
- Run targeted tests for `prometeu-hal`, `prometeu-bytecode`, and
`prometeu-vm` if available.
- Run repository validation commands used for syscall declaration consistency.
## Affected Artifacts
- `crates/console/prometeu-hal/src/syscalls.rs`
- `crates/console/prometeu-hal/src/syscalls/domains/system.rs`
- `crates/console/prometeu-hal/src/syscalls/registry.rs`
- `crates/console/prometeu-bytecode/src/model.rs`
- `crates/console/prometeu-vm/src/virtual_machine.rs`
- `docs/specs/runtime/`
- `discussion/workflow/agendas/AGD-0004-system-fault-semantics-and-control-surface.md`

View File

@ -1,79 +0,0 @@
---
id: PLN-0130
ticket: system-run-cart
title: Remove Runtime Run Cart Stub Dispatch
status: done
created: 2026-07-03
ref_decisions: [DEC-0035]
tags: []
---
## Briefing
`DEC-0035` forbids a callable userland `system.run_cart` stub. This plan covers
runtime and VM dispatch cleanup so obsolete calls cannot silently succeed.
Public ABI removal is handled by `PLN-0129`; direct boot preservation is handled
by `PLN-0131`.
## Objective
Remove the runtime no-op dispatch path for `SystemRunCart` and ensure stale or
obsolete userland attempts fail explicitly rather than returning success.
## Dependencies
- Source decision: `DEC-0035`.
- Depends on the ABI direction in `PLN-0129`, but can be implemented in the same
PR if the public enum/registry removal and dispatch cleanup move together.
## Scope
- Remove the `Syscall::SystemRunCart => return Ok(())` path from
`crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs`.
- Update any match arms made unreachable or obsolete by removing
`SystemRunCart`.
- Ensure stale numeric syscall ids or stale bytecode declarations fail with the
repository's existing unknown/invalid syscall behavior.
- Add negative coverage for userland attempts to invoke the removed operation,
using the closest existing VM runtime syscall tests.
## Non-Goals
- Do not implement a replacement navigation operation.
- Do not implement the `Home -> another Game` orchestrator.
- Do not alter direct host/CLI/debug cartridge boot paths.
- Do not change `system.has_cart` behavior unless required by compile fallout.
## Execution Method
1. Inspect `dispatch.rs` for all `SystemRunCart` match arms.
2. Remove the no-op success path and any unreachable arms tied only to
`SystemRunCart`.
3. If the public enum variant is removed by `PLN-0129`, update exhaustiveness
and registry mapping accordingly.
4. Add or update VM runtime tests that demonstrate `system.run_cart` is not
callable from guest/userland.
5. Run targeted runtime tests and compile checks.
## Acceptance Criteria
- There is no runtime path where a guest `system.run_cart` call returns `Ok(())`.
- Stale/obsolete attempts fail explicitly through existing invalid syscall or
declaration validation behavior.
- `system.has_cart` and unrelated system syscalls keep their current behavior.
- Runtime dispatch remains exhaustive and clear after removing `SystemRunCart`.
## Tests
- Add a negative test in `crates/console/prometeu-system/src/services/vm_runtime`
for stale userland `run_cart` attempts, if the test harness can express it.
- Run `cargo test` for `prometeu-system` and any impacted syscall crates.
- Run a workspace compile/test command if targeted tests reveal cross-crate enum
fallout.
## Affected Artifacts
- `crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs`
- `crates/console/prometeu-system/src/services/vm_runtime/tests.rs`
- `crates/console/prometeu-hal/src/syscalls.rs`
- `crates/console/prometeu-hal/src/syscalls/registry.rs`

View File

@ -1,83 +0,0 @@
---
id: PLN-0131
ticket: system-run-cart
title: Preserve Direct Cartridge Boot Coverage
status: done
created: 2026-07-03
ref_decisions: [DEC-0035]
tags: []
---
## Briefing
`DEC-0035` removes userland `system.run_cart`, but direct cartridge boot remains
mandatory for development, debugging, automated tests, and future single-game
launch scenarios. This plan protects that path while the guest syscall is
removed.
## Objective
Preserve and test host/CLI/debug direct cartridge boot without relying on a
guest syscall.
## Dependencies
- Source decision: `DEC-0035`.
- Can be implemented after or alongside `PLN-0129` and `PLN-0130`.
- Must not depend on `.pmc`, app catalog, launcher UX, `AGD-0041`, or
`AGD-0044`.
## Scope
- Identify direct boot entrypoints in `crates/tools/prometeu-cli/src/main.rs`,
`crates/host/prometeu-host-desktop-winit/src/lib.rs`,
`crates/host/prometeu-host-desktop-winit/src/debugger.rs`, and firmware
cartridge loading code.
- Add or preserve tests showing a cartridge can be loaded directly into
firmware/runtime from host or CLI paths.
- Ensure these paths do not call or require `system.run_cart`.
- Document the distinction between direct boot and guest navigation where
runtime specs describe boot behavior.
## Non-Goals
- Do not implement `Home -> another Game`.
- Do not add app-callable navigation.
- Do not require `.pmc`.
- Do not redesign cartridge loader internals beyond what is required to keep
direct boot working.
## Execution Method
1. Trace the CLI/debug direct boot path from cartridge path argument through
loader, firmware `load_cartridge`, and runtime initialization.
2. Add regression tests at the lowest practical layer proving direct boot still
reaches `GameRunning` for a valid game cartridge.
3. Add a guard or assertion that direct boot does not depend on `system.run_cart`
metadata.
4. Update docs/specs to describe direct boot as host/system-controlled.
5. Run targeted CLI/firmware/host tests.
## Acceptance Criteria
- A valid game cartridge can still boot directly from host/CLI/debug paths.
- Direct boot does not depend on `system.run_cart` being in the guest syscall
registry.
- Existing debugger/handshake metadata that reports cartridge info still works.
- The direct boot behavior is documented as host/system entry, not guest ABI.
## Tests
- Add or preserve firmware tests around `load_cartridge` and `GameRunning`.
- Add or preserve host/CLI tests for cartridge path boot when practical.
- Run `cargo test` for `prometeu-firmware`, `prometeu-host-desktop-winit`, and
`prometeu-cli` where available.
## Affected Artifacts
- `crates/tools/prometeu-cli/src/main.rs`
- `crates/host/prometeu-host-desktop-winit/src/lib.rs`
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware.rs`
- `crates/console/prometeu-firmware/src/firmware/firmware_step_load_cartridge.rs`
- `docs/specs/runtime/`

View File

@ -62,11 +62,6 @@ Typical host-facing boot intents are:
The CLI is an entry surface for boot target selection; the firmware contract remains the same underneath. The CLI is an entry surface for boot target selection; the firmware contract remains the same underneath.
Host CLI, debugger, and equivalent single-game launch flows are the supported
direct cartridge boot surfaces. Direct boot is not requested by guest bytecode
through a `system.run_cart` syscall or any other app-callable cartridge boot
ABI.
## 5 Firmware State Relationship ## 5 Firmware State Relationship
Boot target selection feeds into firmware states such as: Boot target selection feeds into firmware states such as:

View File

@ -52,11 +52,6 @@ This identity is:
Input queries are VM-owned intrinsic calls in v1 and are outside the syscall identity space. Input queries are VM-owned intrinsic calls in v1 and are outside the syscall identity space.
Cartridge boot is also outside the guest syscall identity space. A cartridge,
Shell app, or other userland guest must not declare or call `system.run_cart`.
Direct cartridge boot is a host/system boot-profile entrypoint, not an
app-callable syscall.
Syscall identity is transport, not the conceptual boundary for runtime Syscall identity is transport, not the conceptual boundary for runtime
profiles. `Game` and `System` may both use syscall transport internally or at profiles. `Game` and `System` may both use syscall transport internally or at
their ABI edge, but that does not make their public authoring surfaces the same their ABI edge, but that does not make their public authoring surfaces the same