Merge pull request 'dev/perf-runtime-introspection-syscalls' (#17) from dev/perf-runtime-introspection-syscalls into master
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/head This commit looks good
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/head This commit looks good
Reviewed-on: #17
This commit is contained in:
commit
88eaf16045
@ -68,6 +68,8 @@ pub enum DebugEvent {
|
||||
glyph_slots_total: u32,
|
||||
sound_slots_used: u32,
|
||||
sound_slots_total: u32,
|
||||
scene_slots_used: u32,
|
||||
scene_slots_total: u32,
|
||||
},
|
||||
#[serde(rename = "fault")]
|
||||
Fault {
|
||||
@ -99,6 +101,8 @@ mod tests {
|
||||
glyph_slots_total: 16,
|
||||
sound_slots_used: 2,
|
||||
sound_slots_total: 16,
|
||||
scene_slots_used: 3,
|
||||
scene_slots_total: 16,
|
||||
};
|
||||
|
||||
let json = serde_json::to_string(&event).unwrap();
|
||||
|
||||
@ -64,7 +64,6 @@ pub enum Syscall {
|
||||
AssetCommit = 0x6003,
|
||||
AssetCancel = 0x6004,
|
||||
BankInfo = 0x6101,
|
||||
BankSlotInfo = 0x6102,
|
||||
}
|
||||
|
||||
/// Canonical metadata describing a syscall using the unified slot-based ABI.
|
||||
|
||||
@ -1,12 +1,7 @@
|
||||
use crate::syscalls::{Syscall, SyscallRegistryEntry, caps};
|
||||
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] = &[
|
||||
SyscallRegistryEntry::builder(Syscall::BankInfo, "bank", "info")
|
||||
pub(crate) const ENTRIES: &[SyscallRegistryEntry] =
|
||||
&[SyscallRegistryEntry::builder(Syscall::BankInfo, "bank", "info")
|
||||
.args(1)
|
||||
.rets(1)
|
||||
.caps(caps::BANK),
|
||||
SyscallRegistryEntry::builder(Syscall::BankSlotInfo, "bank", "slot_info")
|
||||
.args(2)
|
||||
.rets(1)
|
||||
.caps(caps::BANK),
|
||||
];
|
||||
.rets(2)
|
||||
.caps(caps::BANK)];
|
||||
|
||||
@ -48,7 +48,6 @@ impl Syscall {
|
||||
0x6003 => Some(Self::AssetCommit),
|
||||
0x6004 => Some(Self::AssetCancel),
|
||||
0x6101 => Some(Self::BankInfo),
|
||||
0x6102 => Some(Self::BankSlotInfo),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -99,7 +98,6 @@ impl Syscall {
|
||||
Self::AssetCommit => "AssetCommit",
|
||||
Self::AssetCancel => "AssetCancel",
|
||||
Self::BankInfo => "BankInfo",
|
||||
Self::BankSlotInfo => "BankSlotInfo",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -249,6 +249,22 @@ fn status_first_syscall_signatures_are_pinned() {
|
||||
let asset_cancel = meta_for(Syscall::AssetCancel);
|
||||
assert_eq!(asset_cancel.arg_slots, 1);
|
||||
assert_eq!(asset_cancel.ret_slots, 1);
|
||||
|
||||
let bank_info = meta_for(Syscall::BankInfo);
|
||||
assert_eq!(bank_info.arg_slots, 1);
|
||||
assert_eq!(bank_info.ret_slots, 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn resolver_rejects_removed_bank_slot_info_identity() {
|
||||
assert!(resolve_syscall("bank", "slot_info", 1).is_none());
|
||||
|
||||
let requested = [SyscallIdentity { module: "bank", name: "slot_info", version: 1 }];
|
||||
let err = resolve_program_syscalls(&requested, caps::ALL).unwrap_err();
|
||||
assert_eq!(
|
||||
err,
|
||||
LoadError::UnknownSyscall { module: "bank".into(), name: "slot_info".into(), version: 1 }
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@ -18,6 +18,8 @@ pub struct TelemetryFrame {
|
||||
pub glyph_slots_total: u32,
|
||||
pub sound_slots_used: u32,
|
||||
pub sound_slots_total: u32,
|
||||
pub scene_slots_used: u32,
|
||||
pub scene_slots_total: u32,
|
||||
|
||||
// RAM (Heap)
|
||||
pub heap_used_bytes: usize,
|
||||
@ -45,6 +47,8 @@ pub struct AtomicTelemetry {
|
||||
pub glyph_slots_total: AtomicU32,
|
||||
pub sound_slots_used: AtomicU32,
|
||||
pub sound_slots_total: AtomicU32,
|
||||
pub scene_slots_used: AtomicU32,
|
||||
pub scene_slots_total: AtomicU32,
|
||||
|
||||
// RAM (Heap)
|
||||
pub heap_used_bytes: AtomicUsize,
|
||||
@ -75,6 +79,8 @@ impl AtomicTelemetry {
|
||||
glyph_slots_total: self.glyph_slots_total.load(Ordering::Relaxed),
|
||||
sound_slots_used: self.sound_slots_used.load(Ordering::Relaxed),
|
||||
sound_slots_total: self.sound_slots_total.load(Ordering::Relaxed),
|
||||
scene_slots_used: self.scene_slots_used.load(Ordering::Relaxed),
|
||||
scene_slots_total: self.scene_slots_total.load(Ordering::Relaxed),
|
||||
heap_used_bytes: self.heap_used_bytes.load(Ordering::Relaxed),
|
||||
heap_max_bytes: self.heap_max_bytes.load(Ordering::Relaxed),
|
||||
logs_count: self.logs_count.load(Ordering::Relaxed),
|
||||
@ -93,6 +99,8 @@ impl AtomicTelemetry {
|
||||
self.glyph_slots_total.store(0, Ordering::Relaxed);
|
||||
self.sound_slots_used.store(0, Ordering::Relaxed);
|
||||
self.sound_slots_total.store(0, Ordering::Relaxed);
|
||||
self.scene_slots_used.store(0, Ordering::Relaxed);
|
||||
self.scene_slots_total.store(0, Ordering::Relaxed);
|
||||
self.heap_used_bytes.store(0, Ordering::Relaxed);
|
||||
self.vm_steps.store(0, Ordering::Relaxed);
|
||||
self.logs_count.store(0, Ordering::Relaxed);
|
||||
|
||||
@ -567,19 +567,8 @@ impl NativeInterface for VirtualMachineRuntime {
|
||||
used_slots: 0,
|
||||
total_slots: 0,
|
||||
});
|
||||
let json = serde_json::to_string(&telemetry).unwrap_or_default();
|
||||
ret.push_string(json);
|
||||
Ok(())
|
||||
}
|
||||
Syscall::BankSlotInfo => {
|
||||
let asset_type = match expect_int(args, 0)? as u32 {
|
||||
0 => BankType::GLYPH,
|
||||
1 => BankType::SOUNDS,
|
||||
_ => return Err(VmFault::Trap(TRAP_TYPE, "Invalid asset type".to_string())),
|
||||
};
|
||||
let slot = SlotRef { asset_type, index: expect_int(args, 1)? as usize };
|
||||
let json = serde_json::to_string(&hw.assets().slot_info(slot)).unwrap_or_default();
|
||||
ret.push_string(json);
|
||||
ret.push_int(telemetry.used_slots as i64);
|
||||
ret.push_int(telemetry.total_slots as i64);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -937,6 +937,60 @@ fn tick_asset_status_unknown_handle_returns_status_not_crash() {
|
||||
assert_eq!(vm.operand_stack_top(1), vec![Value::Int64(LoadStatus::UnknownHandle as i64)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tick_bank_info_returns_slot_summary_not_json() {
|
||||
let mut runtime = VirtualMachineRuntime::new(None);
|
||||
let mut vm = VirtualMachine::default();
|
||||
let mut hardware = Hardware::new();
|
||||
let signals = InputSignals::default();
|
||||
let asset_data = test_glyph_asset_data();
|
||||
hardware.assets.initialize_for_cartridge(
|
||||
vec![test_glyph_asset_entry("tile_asset", asset_data.len())],
|
||||
vec![prometeu_hal::asset::PreloadEntry { asset_id: 7, slot: 0 }],
|
||||
AssetsPayloadSource::from_bytes(asset_data),
|
||||
);
|
||||
let code = assemble("PUSH_I32 0\nHOSTCALL 0\nHALT").expect("assemble");
|
||||
let program = serialized_single_function_module(
|
||||
code,
|
||||
vec![SyscallDecl {
|
||||
module: "bank".into(),
|
||||
name: "info".into(),
|
||||
version: 1,
|
||||
arg_slots: 1,
|
||||
ret_slots: 2,
|
||||
}],
|
||||
);
|
||||
let cartridge = cartridge_with_program(program, caps::BANK);
|
||||
|
||||
runtime.initialize_vm(&mut vm, &cartridge).expect("runtime must initialize");
|
||||
let report = runtime.tick(&mut vm, &signals, &mut hardware);
|
||||
assert!(report.is_none(), "bank summary must not crash");
|
||||
assert!(vm.is_halted());
|
||||
assert_eq!(vm.operand_stack_top(2), vec![Value::Int64(16), Value::Int64(1)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn initialize_vm_rejects_removed_bank_slot_info_syscall_identity() {
|
||||
let mut runtime = VirtualMachineRuntime::new(None);
|
||||
let mut vm = VirtualMachine::default();
|
||||
let code = assemble("PUSH_I32 0\nPUSH_I32 0\nHOSTCALL 0\nHALT").expect("assemble");
|
||||
let program = serialized_single_function_module(
|
||||
code,
|
||||
vec![SyscallDecl {
|
||||
module: "bank".into(),
|
||||
name: "slot_info".into(),
|
||||
version: 1,
|
||||
arg_slots: 2,
|
||||
ret_slots: 1,
|
||||
}],
|
||||
);
|
||||
let cartridge = cartridge_with_program(program, caps::BANK);
|
||||
|
||||
let res = runtime.initialize_vm(&mut vm, &cartridge);
|
||||
|
||||
assert!(matches!(res, Err(CrashReport::VmInit { error: VmInitError::LoaderPatchFailed(_) })));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tick_asset_commit_invalid_transition_returns_status_not_crash() {
|
||||
let mut runtime = VirtualMachineRuntime::new(None);
|
||||
|
||||
@ -7,7 +7,9 @@ use prometeu_vm::LogicalFrameEndingReason;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
impl VirtualMachineRuntime {
|
||||
fn bank_telemetry_summary(hw: &dyn HardwareBridge) -> (BankTelemetry, BankTelemetry) {
|
||||
fn bank_telemetry_summary(
|
||||
hw: &dyn HardwareBridge,
|
||||
) -> (BankTelemetry, BankTelemetry, BankTelemetry) {
|
||||
let telemetry = hw.assets().bank_telemetry();
|
||||
let glyph =
|
||||
telemetry.iter().find(|entry| entry.bank_type == BankType::GLYPH).cloned().unwrap_or(
|
||||
@ -17,8 +19,12 @@ impl VirtualMachineRuntime {
|
||||
telemetry.iter().find(|entry| entry.bank_type == BankType::SOUNDS).cloned().unwrap_or(
|
||||
BankTelemetry { bank_type: BankType::SOUNDS, used_slots: 0, total_slots: 0 },
|
||||
);
|
||||
let scenes =
|
||||
telemetry.iter().find(|entry| entry.bank_type == BankType::SCENE).cloned().unwrap_or(
|
||||
BankTelemetry { bank_type: BankType::SCENE, used_slots: 0, total_slots: 0 },
|
||||
);
|
||||
|
||||
(glyph, sounds)
|
||||
(glyph, sounds, scenes)
|
||||
}
|
||||
|
||||
pub fn debug_step_instruction(
|
||||
@ -148,7 +154,7 @@ impl VirtualMachineRuntime {
|
||||
hw.render_frame();
|
||||
|
||||
// 1. Snapshot full telemetry at logical frame end
|
||||
let (glyph_bank, sound_bank) = Self::bank_telemetry_summary(hw);
|
||||
let (glyph_bank, sound_bank, scene_bank) = Self::bank_telemetry_summary(hw);
|
||||
self.atomic_telemetry
|
||||
.glyph_slots_used
|
||||
.store(glyph_bank.used_slots as u32, Ordering::Relaxed);
|
||||
@ -161,6 +167,12 @@ impl VirtualMachineRuntime {
|
||||
self.atomic_telemetry
|
||||
.sound_slots_total
|
||||
.store(sound_bank.total_slots as u32, Ordering::Relaxed);
|
||||
self.atomic_telemetry
|
||||
.scene_slots_used
|
||||
.store(scene_bank.used_slots as u32, Ordering::Relaxed);
|
||||
self.atomic_telemetry
|
||||
.scene_slots_total
|
||||
.store(scene_bank.total_slots as u32, Ordering::Relaxed);
|
||||
|
||||
self.atomic_telemetry
|
||||
.heap_used_bytes
|
||||
@ -218,7 +230,7 @@ impl VirtualMachineRuntime {
|
||||
|
||||
// 2. High-frequency telemetry update (only if inspection is active)
|
||||
if self.inspection_active {
|
||||
let (glyph_bank, sound_bank) = Self::bank_telemetry_summary(hw);
|
||||
let (glyph_bank, sound_bank, scene_bank) = Self::bank_telemetry_summary(hw);
|
||||
self.atomic_telemetry
|
||||
.glyph_slots_used
|
||||
.store(glyph_bank.used_slots as u32, Ordering::Relaxed);
|
||||
@ -231,6 +243,12 @@ impl VirtualMachineRuntime {
|
||||
self.atomic_telemetry
|
||||
.sound_slots_total
|
||||
.store(sound_bank.total_slots as u32, Ordering::Relaxed);
|
||||
self.atomic_telemetry
|
||||
.scene_slots_used
|
||||
.store(scene_bank.used_slots as u32, Ordering::Relaxed);
|
||||
self.atomic_telemetry
|
||||
.scene_slots_total
|
||||
.store(scene_bank.total_slots as u32, Ordering::Relaxed);
|
||||
|
||||
self.atomic_telemetry
|
||||
.heap_used_bytes
|
||||
|
||||
@ -2,6 +2,7 @@ use prometeu_drivers::hardware::Hardware;
|
||||
use prometeu_firmware::{BootTarget, Firmware};
|
||||
use prometeu_hal::cartridge_loader::CartridgeLoader;
|
||||
use prometeu_hal::debugger_protocol::*;
|
||||
use prometeu_hal::telemetry::{CertificationConfig, TelemetryFrame};
|
||||
use prometeu_system::CrashReport;
|
||||
use std::io::{Read, Write};
|
||||
use std::net::{TcpListener, TcpStream};
|
||||
@ -12,6 +13,8 @@ use std::net::{TcpListener, TcpStream};
|
||||
/// Prometeu Debugger) to observe and control the execution of the virtual machine.
|
||||
///
|
||||
/// Communication is based on JSONL (JSON lines) over TCP.
|
||||
/// Detailed inspection and certification events are synthesized in the host
|
||||
/// from telemetry snapshots and host/runtime integration state.
|
||||
pub struct HostDebugger {
|
||||
/// If true, the VM will not start execution until a 'start' command is received.
|
||||
pub waiting_for_start: bool,
|
||||
@ -230,6 +233,72 @@ impl HostDebugger {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn cert_event_from_snapshot(
|
||||
tag: u16,
|
||||
telemetry: TelemetryFrame,
|
||||
cert_config: &CertificationConfig,
|
||||
frame_index: u64,
|
||||
) -> Option<DebugEvent> {
|
||||
let (rule, used, limit) = match tag {
|
||||
0xCA01 => (
|
||||
"cycles_budget".to_string(),
|
||||
telemetry.cycles_used,
|
||||
cert_config.cycles_budget_per_frame.unwrap_or(0),
|
||||
),
|
||||
0xCA02 => (
|
||||
"max_syscalls".to_string(),
|
||||
telemetry.syscalls as u64,
|
||||
cert_config.max_syscalls_per_frame.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA03 => (
|
||||
"max_host_cpu_us".to_string(),
|
||||
telemetry.host_cpu_time_us,
|
||||
cert_config.max_host_cpu_us_per_frame.unwrap_or(0),
|
||||
),
|
||||
0xCA04 => (
|
||||
"max_glyph_slots_used".to_string(),
|
||||
telemetry.glyph_slots_used as u64,
|
||||
cert_config.max_glyph_slots_used.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA05 => (
|
||||
"max_sound_slots_used".to_string(),
|
||||
telemetry.sound_slots_used as u64,
|
||||
cert_config.max_sound_slots_used.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA06 => (
|
||||
"max_heap_bytes".to_string(),
|
||||
telemetry.heap_used_bytes as u64,
|
||||
cert_config.max_heap_bytes.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA07 => (
|
||||
"max_logs_per_frame".to_string(),
|
||||
telemetry.logs_count as u64,
|
||||
cert_config.max_logs_per_frame.unwrap_or(0) as u64,
|
||||
),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(DebugEvent::Cert { rule, used, limit, frame_index })
|
||||
}
|
||||
|
||||
pub(crate) fn telemetry_event_from_snapshot(telemetry: TelemetryFrame) -> DebugEvent {
|
||||
DebugEvent::Telemetry {
|
||||
frame_index: telemetry.frame_index,
|
||||
vm_steps: telemetry.vm_steps,
|
||||
syscalls: telemetry.syscalls,
|
||||
cycles: telemetry.cycles_used,
|
||||
cycles_budget: telemetry.cycles_budget,
|
||||
host_cpu_time_us: telemetry.host_cpu_time_us,
|
||||
violations: telemetry.violations,
|
||||
glyph_slots_used: telemetry.glyph_slots_used,
|
||||
glyph_slots_total: telemetry.glyph_slots_total,
|
||||
sound_slots_used: telemetry.sound_slots_used,
|
||||
sound_slots_total: telemetry.sound_slots_total,
|
||||
scene_slots_used: telemetry.scene_slots_used,
|
||||
scene_slots_total: telemetry.scene_slots_total,
|
||||
}
|
||||
}
|
||||
|
||||
/// Scans the system for new information to push to the debugger client.
|
||||
fn stream_events(&mut self, firmware: &mut Firmware) {
|
||||
if let Some(report) = firmware.os.last_crash_report.as_ref() {
|
||||
@ -251,46 +320,15 @@ impl HostDebugger {
|
||||
});
|
||||
}
|
||||
|
||||
// Map Certification tags (0xCA01-0xCA03) to 'Cert' protocol events.
|
||||
if event.tag >= 0xCA01 && event.tag <= 0xCA03 {
|
||||
let tel = firmware.os.atomic_telemetry.snapshot();
|
||||
let cert_config = &firmware.os.certifier.config;
|
||||
|
||||
let (rule, used, limit) = match event.tag {
|
||||
0xCA01 => (
|
||||
"cycles_budget".to_string(),
|
||||
tel.cycles_used,
|
||||
cert_config.cycles_budget_per_frame.unwrap_or(0),
|
||||
),
|
||||
0xCA02 => (
|
||||
"max_syscalls".to_string(),
|
||||
tel.syscalls as u64,
|
||||
cert_config.max_syscalls_per_frame.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA03 => (
|
||||
"max_host_cpu_us".to_string(),
|
||||
tel.host_cpu_time_us,
|
||||
cert_config.max_host_cpu_us_per_frame.unwrap_or(0),
|
||||
),
|
||||
0xCA04 => (
|
||||
"max_glyph_slots_used".to_string(),
|
||||
tel.glyph_slots_used as u64,
|
||||
cert_config.max_glyph_slots_used.unwrap_or(0) as u64,
|
||||
),
|
||||
0xCA05 => (
|
||||
"max_sound_slots_used".to_string(),
|
||||
tel.sound_slots_used as u64,
|
||||
cert_config.max_sound_slots_used.unwrap_or(0) as u64,
|
||||
),
|
||||
_ => ("unknown".to_string(), 0, 0),
|
||||
};
|
||||
|
||||
self.send_event(DebugEvent::Cert {
|
||||
rule,
|
||||
used,
|
||||
limit,
|
||||
frame_index: firmware.os.logical_frame_index,
|
||||
});
|
||||
if (0xCA01..=0xCA07).contains(&event.tag)
|
||||
&& let Some(cert_event) = Self::cert_event_from_snapshot(
|
||||
event.tag,
|
||||
firmware.os.atomic_telemetry.snapshot(),
|
||||
&firmware.os.certifier.config,
|
||||
firmware.os.logical_frame_index,
|
||||
)
|
||||
{
|
||||
self.send_event(cert_event);
|
||||
}
|
||||
|
||||
self.send_event(DebugEvent::Log {
|
||||
@ -304,19 +342,7 @@ impl HostDebugger {
|
||||
let current_frame = firmware.os.logical_frame_index;
|
||||
if current_frame > self.last_telemetry_frame {
|
||||
let tel = firmware.os.atomic_telemetry.snapshot();
|
||||
self.send_event(DebugEvent::Telemetry {
|
||||
frame_index: tel.frame_index,
|
||||
vm_steps: tel.vm_steps,
|
||||
syscalls: tel.syscalls,
|
||||
cycles: tel.cycles_used,
|
||||
cycles_budget: tel.cycles_budget,
|
||||
host_cpu_time_us: tel.host_cpu_time_us,
|
||||
violations: tel.violations,
|
||||
glyph_slots_used: tel.glyph_slots_used,
|
||||
glyph_slots_total: tel.glyph_slots_total,
|
||||
sound_slots_used: tel.sound_slots_used,
|
||||
sound_slots_total: tel.sound_slots_total,
|
||||
});
|
||||
self.send_event(Self::telemetry_event_from_snapshot(tel));
|
||||
self.last_telemetry_frame = current_frame;
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,6 +94,7 @@ pub(crate) fn capture_snapshot(stats: &HostStats, firmware: &Firmware) -> Overla
|
||||
let heap_ratio = ratio(tel.heap_used_bytes as u64, heap_total_bytes as u64);
|
||||
let glyph_ratio = ratio(tel.glyph_slots_used as u64, tel.glyph_slots_total as u64);
|
||||
let sound_ratio = ratio(tel.sound_slots_used as u64, tel.sound_slots_total as u64);
|
||||
let scene_ratio = ratio(tel.scene_slots_used as u64, tel.scene_slots_total as u64);
|
||||
|
||||
OverlaySnapshot {
|
||||
rows: vec![
|
||||
@ -163,6 +164,12 @@ pub(crate) fn capture_snapshot(stats: &HostStats, firmware: &Firmware) -> Overla
|
||||
ratio: sound_ratio,
|
||||
warn: tel.sound_slots_total > 0 && tel.sound_slots_used >= tel.sound_slots_total,
|
||||
},
|
||||
OverlayBar {
|
||||
label: "SCENE",
|
||||
value: format!("{} / {} slots", tel.scene_slots_used, tel.scene_slots_total),
|
||||
ratio: scene_ratio,
|
||||
warn: tel.scene_slots_total > 0 && tel.scene_slots_used >= tel.scene_slots_total,
|
||||
},
|
||||
],
|
||||
footer,
|
||||
}
|
||||
|
||||
@ -58,7 +58,8 @@ pub struct HostRunner {
|
||||
|
||||
/// Performance metrics collector.
|
||||
stats: HostStats,
|
||||
/// Remote debugger interface.
|
||||
/// Remote debugger interface. It consumes host-owned telemetry and runtime state
|
||||
/// directly instead of depending on guest-visible inspection syscalls.
|
||||
debugger: HostDebugger,
|
||||
|
||||
/// Flag to enable/disable the technical telemetry display.
|
||||
@ -225,7 +226,8 @@ impl ApplicationHandler for HostRunner {
|
||||
// 1. Process pending debug commands from the network.
|
||||
self.debugger.check_commands(&mut self.firmware, &mut self.hardware);
|
||||
|
||||
// Sync inspection mode state.
|
||||
// Sync inspection mode state. This is host-owned overlay/debugger control,
|
||||
// not a guest-visible debug ABI switch.
|
||||
self.firmware.os.inspection_active = self.overlay_enabled || self.debugger.stream.is_some();
|
||||
|
||||
// 2. Maintain filesystem connection if it was lost (e.g., directory removed).
|
||||
@ -307,9 +309,123 @@ mod tests {
|
||||
use super::*;
|
||||
use prometeu_firmware::BootTarget;
|
||||
use prometeu_hal::debugger_protocol::DEVTOOLS_PROTOCOL_VERSION;
|
||||
use prometeu_hal::telemetry::{CertificationConfig, TelemetryFrame};
|
||||
use std::io::{Read, Write};
|
||||
use std::net::TcpStream;
|
||||
|
||||
#[test]
|
||||
fn host_debugger_maps_cert_events_from_host_owned_sources() {
|
||||
let telemetry = TelemetryFrame {
|
||||
glyph_slots_used: 3,
|
||||
heap_used_bytes: 4096,
|
||||
logs_count: 7,
|
||||
..Default::default()
|
||||
};
|
||||
let config = CertificationConfig {
|
||||
enabled: true,
|
||||
max_glyph_slots_used: Some(2),
|
||||
max_heap_bytes: Some(2048),
|
||||
max_logs_per_frame: Some(5),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match HostDebugger::cert_event_from_snapshot(0xCA04, telemetry, &config, 12) {
|
||||
Some(prometeu_hal::debugger_protocol::DebugEvent::Cert {
|
||||
rule,
|
||||
used,
|
||||
limit,
|
||||
frame_index,
|
||||
}) => {
|
||||
assert_eq!(rule, "max_glyph_slots_used");
|
||||
assert_eq!(used, 3);
|
||||
assert_eq!(limit, 2);
|
||||
assert_eq!(frame_index, 12);
|
||||
}
|
||||
other => panic!("unexpected glyph cert event: {:?}", other),
|
||||
}
|
||||
match HostDebugger::cert_event_from_snapshot(0xCA06, telemetry, &config, 12) {
|
||||
Some(prometeu_hal::debugger_protocol::DebugEvent::Cert {
|
||||
rule,
|
||||
used,
|
||||
limit,
|
||||
frame_index,
|
||||
}) => {
|
||||
assert_eq!(rule, "max_heap_bytes");
|
||||
assert_eq!(used, 4096);
|
||||
assert_eq!(limit, 2048);
|
||||
assert_eq!(frame_index, 12);
|
||||
}
|
||||
other => panic!("unexpected heap cert event: {:?}", other),
|
||||
}
|
||||
match HostDebugger::cert_event_from_snapshot(0xCA07, telemetry, &config, 12) {
|
||||
Some(prometeu_hal::debugger_protocol::DebugEvent::Cert {
|
||||
rule,
|
||||
used,
|
||||
limit,
|
||||
frame_index,
|
||||
}) => {
|
||||
assert_eq!(rule, "max_logs_per_frame");
|
||||
assert_eq!(used, 7);
|
||||
assert_eq!(limit, 5);
|
||||
assert_eq!(frame_index, 12);
|
||||
}
|
||||
other => panic!("unexpected logs cert event: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn host_debugger_maps_telemetry_from_atomic_snapshot_fields() {
|
||||
let telemetry = TelemetryFrame {
|
||||
frame_index: 8,
|
||||
vm_steps: 123,
|
||||
syscalls: 9,
|
||||
cycles_used: 456,
|
||||
cycles_budget: 789,
|
||||
host_cpu_time_us: 321,
|
||||
violations: 2,
|
||||
glyph_slots_used: 1,
|
||||
glyph_slots_total: 16,
|
||||
sound_slots_used: 0,
|
||||
sound_slots_total: 8,
|
||||
scene_slots_used: 2,
|
||||
scene_slots_total: 16,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
match HostDebugger::telemetry_event_from_snapshot(telemetry) {
|
||||
prometeu_hal::debugger_protocol::DebugEvent::Telemetry {
|
||||
frame_index,
|
||||
vm_steps,
|
||||
syscalls,
|
||||
cycles,
|
||||
cycles_budget,
|
||||
host_cpu_time_us,
|
||||
violations,
|
||||
glyph_slots_used,
|
||||
glyph_slots_total,
|
||||
sound_slots_used,
|
||||
sound_slots_total,
|
||||
scene_slots_used,
|
||||
scene_slots_total,
|
||||
} => {
|
||||
assert_eq!(frame_index, 8);
|
||||
assert_eq!(vm_steps, 123);
|
||||
assert_eq!(syscalls, 9);
|
||||
assert_eq!(cycles, 456);
|
||||
assert_eq!(cycles_budget, 789);
|
||||
assert_eq!(host_cpu_time_us, 321);
|
||||
assert_eq!(violations, 2);
|
||||
assert_eq!(glyph_slots_used, 1);
|
||||
assert_eq!(glyph_slots_total, 16);
|
||||
assert_eq!(sound_slots_used, 0);
|
||||
assert_eq!(sound_slots_total, 8);
|
||||
assert_eq!(scene_slots_used, 2);
|
||||
assert_eq!(scene_slots_total, 16);
|
||||
}
|
||||
other => panic!("unexpected telemetry event: {:?}", other),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "requires localhost TCP bind/connect; run via `cargo test -p prometeu-host-desktop-winit --lib -- --ignored`"]
|
||||
fn test_debug_port_opens() {
|
||||
|
||||
29
discussion/.backups/index.ndjson.20260419-085004.bak
Normal file
29
discussion/.backups/index.ndjson.20260419-085004.bak
Normal file
@ -0,0 +1,29 @@
|
||||
{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":18,"PLN":33,"LSN":34,"CLSN":1}}
|
||||
{"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":"workflow/agendas/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":"workflow/decisions/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":"workflow/plans/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":"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"}]}
|
||||
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||
{"type":"discussion","id":"DSC-0022","status":"done","ticket":"tile-bank-vs-glyph-bank-domain-naming","title":"Glyph Bank Domain Naming Contract","created_at":"2026-04-09","updated_at":"2026-04-10","tags":["gfx","runtime","naming","domain-model"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0025","file":"lessons/DSC-0022-glyph-bank-domain-naming/LSN-0025-rename-artifact-by-meaning-not-by-token.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"open","ticket":"runtime-edge-test-plan","title":"Agenda - Runtime Edge Test Plan","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0001","file":"workflow/agendas/AGD-0001-runtime-edge-test-plan.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":"workflow/agendas/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":"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":"workflow/agendas/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":"workflow/agendas/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":"workflow/agendas/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":"workflow/agendas/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-0008","status":"done","ticket":"perf-runtime-telemetry-hot-path","title":"Agenda - [PERF] Runtime Telemetry Hot Path","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[{"id":"AGD-0007","file":"workflow/agendas/AGD-0007-perf-runtime-telemetry-hot-path.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0005","file":"workflow/decisions/DEC-0005-perf-push-based-telemetry-model.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0005","file":"workflow/plans/PLN-0005-perf-push-based-telemetry-implementation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0026","file":"lessons/DSC-0008-perf-runtime-telemetry-hot-path/LSN-0026-push-based-telemetry-model.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"perf-async-background-work-lanes-for-assets-and-fs","title":"Agenda - [PERF] Async Background Work Lanes for Assets and FS","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0008","file":"workflow/agendas/AGD-0008-perf-async-background-work-lanes-for-assets-and-fs.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0010","status":"open","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"perf-gfx-render-pipeline-and-dirty-regions","title":"Agenda - [PERF] GFX Render Pipeline and Dirty Regions","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0010","file":"workflow/agendas/AGD-0010-perf-gfx-render-pipeline-and-dirty-regions.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0012","status":"review","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-04-19","tags":["perf","runtime","syscall","telemetry","debug","asset"],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"accepted","created_at":"2026-03-27","updated_at":"2026-04-18"}],"decisions":[{"id":"DEC-0009","file":"workflow/decisions/DEC-0009-host-owned-debug-and-certification.md","status":"accepted","created_at":"2026-04-18","updated_at":"2026-04-19","ref_agenda":"AGD-0011"}],"plans":[{"id":"PLN-0030","file":"workflow/plans/PLN-0030-dec9-spec-boundary-propagation.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19","ref_decisions":["DEC-0009"]},{"id":"PLN-0031","file":"workflow/plans/PLN-0031-dec9-runtime-bank-abi-cleanup.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19","ref_decisions":["DEC-0009"]},{"id":"PLN-0032","file":"workflow/plans/PLN-0032-dec9-host-debugger-and-certification-alignment.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19","ref_decisions":["DEC-0009"]}],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"type":"discussion","id":"DSC-0025","status":"done","ticket":"scene-bank-and-viewport-cache-refactor","title":"Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-14","tags":["gfx","tilemap","runtime","render"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md","status":"done","created_at":"2026-04-14","updated_at":"2026-04-14"}]}
|
||||
{"type":"discussion","id":"DSC-0026","status":"done","ticket":"render-all-scene-cache-and-camera-integration","title":"Integrate render_all with Scene Cache and Camera","created_at":"2026-04-14","updated_at":"2026-04-18","tags":["gfx","runtime","render","camera","scene"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0031","file":"lessons/DSC-0026-render-all-scene-cache-and-camera-integration/LSN-0031-frame-composition-belongs-above-the-render-backend.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
|
||||
{"type":"discussion","id":"DSC-0027","status":"done","ticket":"frame-composer-public-syscall-surface","title":"Agenda - FrameComposer Public Syscall Surface","created_at":"2026-04-17","updated_at":"2026-04-18","tags":["gfx","runtime","syscall","abi","frame-composer","scene","camera","sprites"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0032","file":"lessons/DSC-0027-frame-composer-public-syscall-surface/LSN-0032-public-abi-must-follow-the-canonical-service-boundary.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
|
||||
{"type":"discussion","id":"DSC-0028","status":"done","ticket":"deferred-overlay-and-primitive-composition","title":"Deferred Overlay and Primitive Composition over FrameComposer","created_at":"2026-04-18","updated_at":"2026-04-18","tags":["gfx","runtime","render","frame-composer","overlay","primitives","hud"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0033","file":"lessons/DSC-0028-deferred-overlay-and-primitive-composition/LSN-0033-debug-primitives-should-be-a-final-overlay-not-part-of-game-composition.md","status":"done","created_at":"2026-04-18","updated_at":"2026-04-18"}]}
|
||||
{"type":"discussion","id":"DSC-0014","status":"open","ticket":"perf-vm-allocation-and-copy-pressure","title":"Agenda - [PERF] VM Allocation and Copy Pressure","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0013","file":"workflow/agendas/AGD-0013-perf-vm-allocation-and-copy-pressure.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0015","status":"open","ticket":"perf-cartridge-boot-and-program-ownership","title":"Agenda - [PERF] Cartridge Boot and Program Ownership","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0014","file":"workflow/agendas/AGD-0014-perf-cartridge-boot-and-program-ownership.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0016","status":"done","ticket":"tilemap-empty-cell-vs-tile-id-zero","title":"Tilemap Empty Cell vs Tile ID Zero","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0015","file":"workflow/agendas/AGD-0015-tilemap-empty-cell-vs-tile-id-zero.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0022","file":"lessons/DSC-0016-tilemap-empty-cell-semantics/LSN-0022-tilemap-empty-cell-convergence.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||
{"type":"discussion","id":"DSC-0017","status":"done","ticket":"asset-entry-metadata-normalization-contract","title":"Asset Entry Metadata Normalization Contract","created_at":"2026-03-27","updated_at":"2026-04-09","tags":[],"agendas":[{"id":"AGD-0016","file":"workflow/agendas/AGD-0016-asset-entry-metadata-normalization-contract.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-09"}],"decisions":[{"id":"DEC-0004","file":"workflow/decisions/DEC-0004-asset-entry-metadata-normalization-contract.md","status":"accepted","created_at":"2026-04-09","updated_at":"2026-04-09"}],"plans":[],"lessons":[{"id":"LSN-0023","file":"lessons/DSC-0017-asset-metadata-normalization/LSN-0023-typed-asset-metadata-helpers.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||
{"type":"discussion","id":"DSC-0018","status":"done","ticket":"asset-load-asset-id-int-contract","title":"Asset Load Asset ID Int Contract","created_at":"2026-03-27","updated_at":"2026-03-27","tags":["asset","runtime","abi"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0019","file":"lessons/DSC-0018-asset-load-asset-id-int-contract/LSN-0019-asset-load-id-abi-convergence.md","status":"done","created_at":"2026-03-27","updated_at":"2026-03-27"}]}
|
||||
{"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":"workflow/agendas/AGD-0017-jenkinsfile-correction.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0002","file":"workflow/decisions/DEC-0002-jenkinsfile-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0002","file":"workflow/plans/PLN-0002-jenkinsfile-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0020","file":"lessons/DSC-0019-jenkins-ci-standardization/LSN-0020-jenkins-standard-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||
@ -1,4 +1,4 @@
|
||||
{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":17,"PLN":30,"LSN":34,"CLSN":1}}
|
||||
{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":18,"PLN":33,"LSN":35,"CLSN":1}}
|
||||
{"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":"workflow/agendas/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":"workflow/decisions/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":"workflow/plans/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":"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"}]}
|
||||
{"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]}
|
||||
{"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]}
|
||||
@ -14,7 +14,7 @@
|
||||
{"type":"discussion","id":"DSC-0009","status":"open","ticket":"perf-async-background-work-lanes-for-assets-and-fs","title":"Agenda - [PERF] Async Background Work Lanes for Assets and FS","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0008","file":"workflow/agendas/AGD-0008-perf-async-background-work-lanes-for-assets-and-fs.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0010","status":"open","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0011","status":"open","ticket":"perf-gfx-render-pipeline-and-dirty-regions","title":"Agenda - [PERF] GFX Render Pipeline and Dirty Regions","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0010","file":"workflow/agendas/AGD-0010-perf-gfx-render-pipeline-and-dirty-regions.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0012","status":"open","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0011","file":"workflow/agendas/AGD-0011-perf-runtime-introspection-syscalls.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]}
|
||||
{"type":"discussion","id":"DSC-0012","status":"done","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-04-19","tags":["perf","runtime","syscall","telemetry","debug","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"lessons/DSC-0012-perf-runtime-introspection-syscalls/LSN-0034-host-owned-debug-boundaries.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19"}]}
|
||||
{"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"type":"discussion","id":"DSC-0024","status":"done","ticket":"generic-memory-bank-slot-contract","title":"Agenda - Generic Memory Bank Slot Contract","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["runtime","asset","memory-bank","slots","host"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0029","file":"lessons/DSC-0024-generic-memory-bank-slot-contract/LSN-0029-slot-first-bank-telemetry-belongs-in-asset-manager.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]}
|
||||
{"type":"discussion","id":"DSC-0025","status":"done","ticket":"scene-bank-and-viewport-cache-refactor","title":"Scene Bank and Viewport Cache Refactor","created_at":"2026-04-11","updated_at":"2026-04-14","tags":["gfx","tilemap","runtime","render"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0030","file":"lessons/DSC-0025-scene-bank-and-viewport-cache-refactor/LSN-0030-canonical-scene-cache-and-resolver-split.md","status":"done","created_at":"2026-04-14","updated_at":"2026-04-14"}]}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
---
|
||||
id: LSN-0034
|
||||
ticket: perf-runtime-introspection-syscalls
|
||||
title: Host-Owned Debug Boundaries and Cheap Machine Diagnostics
|
||||
created: 2026-04-19
|
||||
tags: [runtime, host, debug, certification, telemetry, abi]
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
`DSC-0012` resolved a recurring ambiguity in PROMETEU: whether development diagnostics should be treated as part of the guest/runtime contract or as host tooling concerns. The codebase already had host overlay rendering, atomic telemetry snapshots, and slot-first bank telemetry, but the runtime still exposed JSON-formatted bank inspection syscalls.
|
||||
|
||||
The completed work converged specs, runtime ABI, and host debugger behavior around a single boundary: rich diagnostics belong to the host, while the runtime exports only bounded machine-facing summaries.
|
||||
|
||||
## Key Decisions
|
||||
|
||||
### Host-Owned Debug and Certification (`DEC-0009`)
|
||||
|
||||
**What:**
|
||||
Debug tooling and certification are host-owned concerns. Guest-visible debug convenience APIs are not part of the long-term runtime ABI.
|
||||
|
||||
**Why:**
|
||||
Development inspection, profiling, and certification analysis happen on desktop host environments, not on production handheld/runtime targets. Keeping those concerns in the guest ABI forces production execution to carry tooling-oriented surface area and cost.
|
||||
|
||||
**Trade-offs:**
|
||||
The runtime gives up general introspection syscalls, so host tooling must consume telemetry and internal host/runtime integration points directly. In exchange, the public ABI becomes cheaper, narrower, and easier to reason about.
|
||||
|
||||
## Patterns and Algorithms
|
||||
|
||||
- Treat diagnostics as a layered boundary:
|
||||
The runtime owns deterministic counters, bounded summaries, and machine-facing operational signals.
|
||||
The host owns rendering, protocol projection, certification output, and rich inspection UX.
|
||||
|
||||
- Prefer cheap structured values over textual debug payloads:
|
||||
If a machine-facing diagnostic survives, it should return small canonical stack values such as `(used_slots, total_slots)`, not JSON blobs.
|
||||
|
||||
- Use one telemetry source for all host consumers:
|
||||
Atomic telemetry snapshots should feed debugger streaming, overlays, and certification evaluation so the platform does not fork multiple diagnostic pipelines.
|
||||
|
||||
- Keep telemetry slot-first when the real machine contract is slot-first:
|
||||
Bank occupancy was correctly modeled as slot usage, so the surviving public summary stayed aligned with that semantic model instead of byte-oriented totals or slot-detail dumps.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- Do not let host-only needs backdoor themselves into the guest ABI as "temporary" debug syscalls. They tend to linger and become accidental contract.
|
||||
|
||||
- Do not use JSON-on-the-wire as a fallback ABI for runtime inspection. It is easy to add, but it creates unbounded cost and weakens the canonical machine model.
|
||||
|
||||
- Do not update only specs or only code. This boundary needed spec propagation, runtime ABI cleanup, and host debugger alignment together to avoid split-brain behavior.
|
||||
|
||||
## Takeaways
|
||||
|
||||
- Debug and certification pipelines should be modeled as host products that consume runtime telemetry, not as guest features.
|
||||
- Surviving machine diagnostics must be justified by operational need and expressed as bounded structured values.
|
||||
- The clean boundary is: runtime produces telemetry, host interprets and presents it.
|
||||
@ -1,72 +0,0 @@
|
||||
---
|
||||
id: AGD-0011
|
||||
ticket: perf-runtime-introspection-syscalls
|
||||
title: Agenda - [PERF] Runtime Introspection Syscalls
|
||||
status: open
|
||||
created: 2026-03-27
|
||||
resolved:
|
||||
decision:
|
||||
tags: []
|
||||
---
|
||||
|
||||
# Agenda - [PERF] Runtime Introspection Syscalls
|
||||
|
||||
## Problema
|
||||
|
||||
As syscalls de introspecao ainda carregam custo de serializacao e agregacao demais para algo que deveria ser observabilidade sob demanda.
|
||||
|
||||
Hoje `BankInfo` e `BankSlotInfo` montam JSON por chamada e puxam dados potencialmente caros do asset manager.
|
||||
|
||||
## Dor
|
||||
|
||||
- tooling de debug pode contaminar custo percebido da runtime surface.
|
||||
- serializacao de string/JSON vira alocacao no meio do dispatch.
|
||||
- sem fronteira clara, apps podem abusar de syscalls de introspecao como se fossem baratas.
|
||||
|
||||
## Hotspots Atuais
|
||||
|
||||
- [dispatch.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-system/src/virtual_machine_runtime/dispatch.rs#L481)
|
||||
- [asset.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/console/prometeu-drivers/src/asset.rs#L618)
|
||||
|
||||
## Alvo da Discussao
|
||||
|
||||
Separar claramente custo de introspecao/debug do custo da superficie operacional normal.
|
||||
|
||||
## O Que Precisa Ser Definido
|
||||
|
||||
1. Papel dessas syscalls.
|
||||
Decidir se `BankInfo`/`BankSlotInfo` sao:
|
||||
- superficie publica normal;
|
||||
- superficie de debug;
|
||||
- superficie host/devtools apenas.
|
||||
|
||||
2. Shape de retorno.
|
||||
Definir se JSON continua existindo ou se v1 exige shape mais barato/canonico.
|
||||
|
||||
3. Caching.
|
||||
Delimitar se snapshots de introspecao podem ser cacheados por frame.
|
||||
|
||||
4. Limites de uso.
|
||||
Decidir se o runtime deve impor throttling, budget ou feature gate de debug.
|
||||
|
||||
## Open Questions de Arquitetura
|
||||
|
||||
1. Vale manter JSON na ABI do guest ou isso deveria ficar restrito ao host/debugger?
|
||||
2. Existe um subconjunto de dados numericos suficiente para carts sem tooling externo?
|
||||
3. O certifier deve observar essas chamadas como custo anormal de debug?
|
||||
|
||||
## Dependencias
|
||||
|
||||
- `../specs/10-debug-inspection-and-profiling.md`
|
||||
- `../specs/15-asset-management.md`
|
||||
- `../specs/16-host-abi-and-syscalls.md`
|
||||
- `../specs/16a-syscall-policies.md`
|
||||
|
||||
## Criterio de Saida Desta Agenda
|
||||
|
||||
Pode virar PR quando houver decisao escrita sobre:
|
||||
|
||||
- papel normativo de `BankInfo`/`BankSlotInfo`;
|
||||
- permanencia ou remocao de JSON como shape de retorno;
|
||||
- politica de cache/throttling;
|
||||
- custo aceitavel de introspecao no dispatch.
|
||||
@ -98,7 +98,7 @@ Important properties:
|
||||
|
||||
- events are processed at known points;
|
||||
- no execution occurs outside the frame loop;
|
||||
- frame structure remains observable for tooling and certification.
|
||||
- frame structure remains observable for host tooling and host-owned certification.
|
||||
|
||||
## 7 Determinism and Best Practices
|
||||
|
||||
|
||||
@ -7,19 +7,18 @@ Didactic companion: [`../learn/mental-model-observability-and-debugging.md`](../
|
||||
|
||||
## 1 Scope
|
||||
|
||||
This chapter defines the machine-visible debugging, inspection, and profiling surface of PROMETEU.
|
||||
This chapter defines the machine-visible diagnostics and profiling surface of PROMETEU after `DEC-0009`.
|
||||
|
||||
`DEC-0009` locks debug tooling and certification output as host-owned concerns. The runtime machine contract therefore exposes only bounded operational diagnostics and deterministic telemetry production, not a general-purpose guest-visible debug surface.
|
||||
|
||||
It covers:
|
||||
|
||||
- execution modes;
|
||||
- pause and stepping;
|
||||
- state inspection;
|
||||
- graphics inspection;
|
||||
- runtime-visible execution control used by host tooling;
|
||||
- bounded operational telemetry;
|
||||
- profiling;
|
||||
- breakpoints and watchpoints;
|
||||
- event and fault visibility;
|
||||
- certification-facing diagnostics;
|
||||
- Host-side debug overlay (HUD) isolation.
|
||||
- certification input data;
|
||||
- host-side debug overlay (HUD) isolation.
|
||||
|
||||
## 2 Execution Modes
|
||||
|
||||
@ -34,18 +33,18 @@ PROMETEU operates in three main modes:
|
||||
### 2.2 Debug Mode
|
||||
|
||||
- controlled execution
|
||||
- access to internal state
|
||||
- host-mediated access to internal state
|
||||
- pauses and stepping
|
||||
|
||||
### 2.3 Certification Mode
|
||||
|
||||
- deterministic execution
|
||||
- collected metrics
|
||||
- report generation
|
||||
- host-generated report output
|
||||
|
||||
No mode alters the logical result of the program.
|
||||
|
||||
## 3 Execution Debug
|
||||
## 3 Execution Control
|
||||
|
||||
### 3.1 Pause and Resume
|
||||
|
||||
@ -64,24 +63,26 @@ During pause:
|
||||
|
||||
### 3.2 Step-by-Step
|
||||
|
||||
PROMETEU allows stepping at different levels:
|
||||
PROMETEU allows host tooling to step execution at different levels:
|
||||
|
||||
- **by frame**
|
||||
- **by function**
|
||||
- **by VM instruction**
|
||||
|
||||
Stepping by instruction reveals:
|
||||
When the host activates instruction-level inspection, it may observe:
|
||||
|
||||
- Program Counter (PC)
|
||||
- current instruction
|
||||
- operand stack
|
||||
- call stack
|
||||
|
||||
## 4 State Inspection
|
||||
## 4 State Inspection Boundary
|
||||
|
||||
Detailed state inspection is a host-owned concern. The runtime may expose deterministic machine state to host tooling, but this chapter does not define a general guest ABI for introspection convenience.
|
||||
|
||||
### 4.1 Stacks
|
||||
|
||||
PROMETEU allows inspecting:
|
||||
Host tooling may inspect:
|
||||
|
||||
- **Operand Stack**
|
||||
- **Call Stack**
|
||||
@ -94,7 +95,7 @@ For each frame:
|
||||
|
||||
### 4.2 Heap
|
||||
|
||||
The heap can be inspected in real time:
|
||||
The host may inspect heap state in real time:
|
||||
|
||||
- total size
|
||||
- current usage
|
||||
@ -109,22 +110,22 @@ The programmer can observe:
|
||||
|
||||
### 4.3 Global Space
|
||||
|
||||
Global variables:
|
||||
Host-owned inspection may observe global variables, including:
|
||||
|
||||
- current values
|
||||
- references
|
||||
- initialization
|
||||
|
||||
## 5 Graphics Debug
|
||||
## 5 Graphics Inspection Boundary
|
||||
|
||||
PROMETEU allows inspecting the graphics system:
|
||||
Host tooling may inspect the graphics system:
|
||||
|
||||
- front buffer
|
||||
- back buffer
|
||||
- palette state
|
||||
- active sprites
|
||||
|
||||
It is possible to:
|
||||
The host may:
|
||||
|
||||
- freeze the image
|
||||
- observe buffers separately
|
||||
@ -153,7 +154,7 @@ SYSTEM:612
|
||||
|
||||
### 6.2 Per-Function Profiling
|
||||
|
||||
PROMETEU can associate cycles with:
|
||||
Host tooling may associate cycles with:
|
||||
|
||||
- functions
|
||||
- methods
|
||||
@ -161,7 +162,7 @@ PROMETEU can associate cycles with:
|
||||
|
||||
### 6.3 Per-Instruction Profiling
|
||||
|
||||
At the lowest level, the system can display:
|
||||
At the lowest level, host tooling can display:
|
||||
|
||||
- executed instructions
|
||||
- individual cost
|
||||
@ -185,13 +186,13 @@ Peak:34KB❌
|
||||
Limit:32KB
|
||||
```
|
||||
|
||||
These data directly feed the certification.
|
||||
These data feed host-owned certification.
|
||||
|
||||
### 7.1 Bank Occupancy Profiling
|
||||
|
||||
Bank occupancy diagnostics are slot-first.
|
||||
|
||||
The visible per-bank telemetry used by host inspection surfaces and certification is:
|
||||
The visible per-bank telemetry used by host inspection surfaces and host-owned certification is:
|
||||
|
||||
- `bank_type`
|
||||
- `used_slots`
|
||||
@ -206,9 +207,11 @@ Byte-oriented bank occupancy is not the canonical visible profiling contract.
|
||||
|
||||
## 8 Breakpoints and Watchpoints
|
||||
|
||||
Breakpoints and watchpoints are host-mediated tooling controls. They are not part of the gameplay-facing cartridge contract.
|
||||
|
||||
### 8.1 Breakpoints
|
||||
|
||||
PROMETEU supports breakpoints in:
|
||||
The platform supports host-owned breakpoints in:
|
||||
|
||||
- specific frames
|
||||
- functions
|
||||
@ -222,7 +225,7 @@ Breakpoints:
|
||||
|
||||
### 8.2 Watchpoints
|
||||
|
||||
Watchpoints monitor:
|
||||
Host tooling may monitor watchpoints over:
|
||||
|
||||
- variables
|
||||
- heap addresses
|
||||
@ -233,10 +236,14 @@ Execution can pause when:
|
||||
- a value changes
|
||||
- a limit is exceeded
|
||||
|
||||
## 9 Event and Fault Debugging
|
||||
## 9 Event and Fault Diagnostics
|
||||
|
||||
## 10 Certification Diagnostics
|
||||
|
||||
Certification diagnostics are produced by the host from deterministic runtime telemetry.
|
||||
|
||||
The runtime does not generate the final certification artifact. It only maintains the machine-facing counters and summaries required for host-owned certification.
|
||||
|
||||
Certification diagnostics may enforce bank occupancy ceilings.
|
||||
|
||||
For bank residency, certification uses slot-based limits, such as:
|
||||
@ -246,7 +253,7 @@ For bank residency, certification uses slot-based limits, such as:
|
||||
|
||||
Bank certification MUST NOT depend on `max_gfx_bytes` or `max_audio_bytes`.
|
||||
|
||||
PROMETEU allows observing:
|
||||
Host tooling may observe:
|
||||
|
||||
- event queue
|
||||
- active timers
|
||||
@ -259,7 +266,7 @@ Each event has:
|
||||
- cost
|
||||
- consequence
|
||||
|
||||
## 10 Host-Side Debug Overlay (HUD) Isolation
|
||||
## 11 Host-Side Debug Overlay (HUD) Isolation
|
||||
|
||||
The visual Debug Overlay (HUD) for technical inspection is not part of the emulated machine pipeline.
|
||||
|
||||
@ -270,7 +277,7 @@ The visual Debug Overlay (HUD) for technical inspection is not part of the emula
|
||||
3. **Host overlay module:** The Desktop Host owns a dedicated overlay module that performs host-side text, panel, and simple bar composition.
|
||||
4. **Composition boundary:** The overlay is composed on the Host presentation surface after the emulated frame is ready. Overlay pixels must not be written back into the emulated framebuffer.
|
||||
5. **Host control:** Overlay visibility and presentation policy remain under Host control.
|
||||
2. **Host (Desktop):** Responsible for collecting telemetry from the runtime and rendering the HUD as a native, transparent layer.
|
||||
6. **Host (Desktop):** Responsible for collecting telemetry from the runtime and rendering the HUD as a native, transparent layer.
|
||||
|
||||
### 10.2 Principles
|
||||
|
||||
@ -287,11 +294,11 @@ To ensure zero-impact synchronization between the VM and the Host Debug Overlay,
|
||||
3. **Single Source of Truth:** This model is the exclusive source of truth for both real-time inspection and frame-end certification, replacing legacy per-frame buffered fields.
|
||||
4. **Frame-Closed Log Metric:** `logs_count` in the snapshot represents the number of logs emitted in the last completed logical frame, not a transient in-flight counter.
|
||||
|
||||
## 11 Integration with CAP and Certification
|
||||
## 12 Integration with CAP and Certification
|
||||
|
||||
All debug and profiling data:
|
||||
All machine diagnostics and profiling data:
|
||||
|
||||
- feed the certification report
|
||||
- are collected deterministically
|
||||
- do not depend on external tools
|
||||
- feed the host-owned certification report;
|
||||
- are collected deterministically;
|
||||
- do not require a guest-visible debug ABI;
|
||||
- are consistent regardless of whether the Host HUD is active or not.
|
||||
|
||||
@ -162,7 +162,7 @@ Without changing semantics.
|
||||
|
||||
## 11 Certification and Portability
|
||||
|
||||
The **PROMETEU Certification** is valid for all platforms.
|
||||
The host-owned **PROMETEU Certification** is valid for all platforms.
|
||||
|
||||
If a cartridge:
|
||||
|
||||
|
||||
@ -110,44 +110,44 @@ This table describes content identity and storage layout, not live residency.
|
||||
|
||||
### 4.1 `TILES` asset contract in v1
|
||||
|
||||
Para `BankType::TILES`, o contrato v1 voltado para o runtime é:
|
||||
For `BankType::TILES`, the v1 runtime-facing contract is:
|
||||
|
||||
- `codec = NONE`
|
||||
- pixels serializados usam índices de paleta `u4` empacotados
|
||||
- paletas serializadas usam `RGB565` (`u16`, little-endian)
|
||||
- serialized pixels use packed `u4` palette indices
|
||||
- serialized palettes use `RGB565` (`u16`, little-endian)
|
||||
- `palette_count = 64`
|
||||
- a materialização em runtime pode expandir índices de pixel para um `u8` por pixel
|
||||
- runtime materialization may expand pixel indices to one `u8` per pixel
|
||||
|
||||
`NONE` para `TILES` significa que não há camada de codec genérica adicional além do próprio contrato do banco.
|
||||
For `TILES`, `NONE` means there is no additional generic codec layer beyond the bank contract itself.
|
||||
|
||||
Para a janela de transição atual:
|
||||
For the current transition window:
|
||||
|
||||
- `RAW` é um alias legado e depreciado de `NONE`
|
||||
- novos materiais publicados devem usar `NONE` como valor canônico
|
||||
- `RAW` is a legacy deprecated alias of `NONE`
|
||||
- newly published material must use `NONE` as the canonical value
|
||||
|
||||
Mesmo com `codec = NONE`, `TILES` ainda requer decode específico de banco a partir de seu payload serializado. O layout de bytes serializados não precisa, portanto, ser idêntico ao layout em memória.
|
||||
Even with `codec = NONE`, `TILES` still requires bank-specific decode from its serialized payload. The serialized byte layout therefore does not need to match the in-memory layout.
|
||||
|
||||
#### 4.1.1 Metadata Normalization
|
||||
|
||||
Seguindo a `DEC-0004`, o campo `AssetEntry.metadata` deve ser estruturado de forma segmentada para evitar ambiguidades.
|
||||
Following `DEC-0004`, the `AssetEntry.metadata` field must be structured in segmented form to avoid ambiguity.
|
||||
|
||||
Campos de metadados obrigatórios (efetivos) para `TILES` no nível raiz:
|
||||
Required effective metadata fields for `TILES` at the root level:
|
||||
|
||||
- `tile_size`: aresta do tile em pixels; valores válidos são `8`, `16`, ou `32`
|
||||
- `width`: largura total da folha do banco em pixels
|
||||
- `height`: altura total da folha do banco em pixels
|
||||
- `palette_count`: número de paletas serializadas para o banco
|
||||
- `tile_size`: tile edge in pixels; valid values are `8`, `16`, or `32`
|
||||
- `width`: total sheet width in pixels
|
||||
- `height`: total sheet height in pixels
|
||||
- `palette_count`: number of serialized palettes for the bank
|
||||
|
||||
Subárvores opcionais e informativas:
|
||||
Optional informative subtrees:
|
||||
|
||||
- `metadata.codec`: Configuração específica do codec/compressor (ex: dicionários, flags de compressão).
|
||||
- `metadata.pipeline`: Metadados informativos do processo de build do Studio (ex: source hashes, timestamps, tool versions).
|
||||
- `metadata.codec`: codec/compressor-specific configuration (for example dictionaries or compression flags).
|
||||
- `metadata.pipeline`: informative metadata from the Studio build process (for example source hashes, timestamps, or tool versions).
|
||||
|
||||
Regras de validação para `TILES` v1:
|
||||
Validation rules for `TILES` v1:
|
||||
|
||||
- `palette_count` deve ser `64`
|
||||
- `width * height` define o número de pixels indexados lógicos na folha decodificada
|
||||
- metadados adicionais podem existir, mas o contrato do runtime não deve depender deles para reconstruir o banco em memória (exceto se definidos na raiz como campos efetivos).
|
||||
- `palette_count` must be `64`
|
||||
- `width * height` defines the number of logical indexed pixels in the decoded sheet
|
||||
- extra metadata may exist, but the runtime contract must not depend on it to reconstruct the in-memory bank unless that data is defined at the root as an effective field.
|
||||
|
||||
#### 4.1.2 Payload Layout
|
||||
|
||||
@ -202,7 +202,8 @@ Rules:
|
||||
|
||||
- the visible contract MUST NOT expose byte-oriented bank occupancy as the canonical summary;
|
||||
- canonical bank names are `GLYPH` and `SOUNDS`;
|
||||
- detailed occupancy inspection remains slot-based through slot references, not bank byte totals;
|
||||
- detailed occupancy inspection remains host-owned and slot-based through slot references, not bank byte totals;
|
||||
- public runtime specs MUST NOT treat `bank.slot_info` or JSON bank inspection payloads as the long-term guest ABI after `DEC-0009`;
|
||||
- any residual byte accounting MAY exist internally, but it is not part of the visible bank telemetry contract.
|
||||
|
||||
## 6 Load Lifecycle
|
||||
@ -255,9 +256,9 @@ Therefore:
|
||||
- shutting down a cartridge can release bank residency independently of VM heap behavior.
|
||||
- the runtime must not keep the full `assets.pa` payload resident in RAM as a baseline requirement.
|
||||
|
||||
## 8 Bank Telemetry
|
||||
## 8 Bank Telemetry and Inspection Boundary
|
||||
|
||||
The runtime surfaces bank and slot statistics such as:
|
||||
The runtime may maintain bank and slot statistics such as:
|
||||
|
||||
- total bytes;
|
||||
- used bytes;
|
||||
@ -266,7 +267,11 @@ The runtime surfaces bank and slot statistics such as:
|
||||
- slot occupancy;
|
||||
- resident asset identity per slot.
|
||||
|
||||
These metrics support debugging, telemetry, and certification-oriented inspection.
|
||||
These metrics support host-owned debugging, telemetry, and certification-oriented inspection.
|
||||
|
||||
Only bounded operational summaries belong to the public runtime contract.
|
||||
|
||||
Detailed per-slot inspection is valid for host tooling and runtime internals, but it must not be treated as a general guest-visible debug convenience API.
|
||||
|
||||
## 9 Preload
|
||||
|
||||
|
||||
@ -15,6 +15,8 @@ It focuses on:
|
||||
|
||||
Operational policies such as capabilities, fault classes, determinism, GC interaction, budgeting, and blocking are split into a companion chapter.
|
||||
|
||||
Per `DEC-0009`, debug tooling and certification are host-owned concerns. This chapter therefore excludes general-purpose guest-visible debug syscalls from the canonical public ABI.
|
||||
|
||||
## 1 Design Principles
|
||||
|
||||
The syscall ABI follows these rules:
|
||||
@ -199,6 +201,16 @@ For `asset.load`:
|
||||
- `slot` is the target slot index;
|
||||
- bank kind is resolved from `asset_table` by `asset_id`, not supplied by the caller.
|
||||
|
||||
### Bank diagnostics surface (`bank`, v1)
|
||||
|
||||
`DEC-0009` narrows the public bank contract:
|
||||
|
||||
- `bank.info(bank_type) -> (used_slots, total_slots)` is the only surviving public bank diagnostic shape in v1;
|
||||
- `bank.info` exists only as a cheap deterministic operational summary aligned with the slot-first bank telemetry contract from [`15-asset-management.md`](15-asset-management.md);
|
||||
- `bank.slot_info` is host/debug tooling surface and is not part of the canonical public guest ABI;
|
||||
- JSON-on-the-wire bank inspection payloads are not valid public ABI;
|
||||
- `bank.info` returns stack values, not textual structured payloads.
|
||||
|
||||
### Composition surface (`composer`, v1)
|
||||
|
||||
The canonical frame-orchestration public ABI uses module `composer`.
|
||||
|
||||
@ -9,6 +9,8 @@ It complements [`16-host-abi-and-syscalls.md`](16-host-abi-and-syscalls.md), whi
|
||||
|
||||
Unless a domain chapter explicitly narrows behavior further, this chapter is the transversal policy for all syscalls in v1.
|
||||
|
||||
Per `DEC-0009`, guest-visible syscalls must not exist merely for debug convenience or certification plumbing. Those concerns belong to host-owned tooling.
|
||||
|
||||
## 1 Error Model: Faults vs Status Returns
|
||||
|
||||
Syscalls use a status-first hybrid model.
|
||||
@ -61,6 +63,7 @@ Practical rule:
|
||||
|
||||
- `void` is allowed only for operations whose non-fault path is effectively unconditional success;
|
||||
- any operation with a meaningful operational non-success outcome must surface that outcome through `status`, not through absence of return values.
|
||||
- debug-only or certification-only convenience calls are not justified public ABI even if they could be given a valid return shape.
|
||||
|
||||
### No-op policy
|
||||
|
||||
@ -77,6 +80,14 @@ This means operational problems must not be reclassified as:
|
||||
- `Trap`, when the failure is not structural;
|
||||
- `Panic`, when the failure is not an internal invariant break.
|
||||
|
||||
### Diagnostics boundary
|
||||
|
||||
These policy constraints also apply to observability surfaces:
|
||||
|
||||
- host-owned inspection and certification consumers may use runtime telemetry and internal host/runtime integration paths;
|
||||
- guest-visible syscalls must be justified by machine-facing operational needs, not by tooling convenience;
|
||||
- textual JSON diagnostics are not valid long-term public syscall ABI.
|
||||
|
||||
## 2 Capability System
|
||||
|
||||
Each syscall requires a declared capability.
|
||||
@ -141,7 +152,7 @@ The system may account for:
|
||||
- cycles spent in syscalls;
|
||||
- allocations triggered by syscalls.
|
||||
|
||||
This keeps host interaction visible in certification, telemetry, and profiling.
|
||||
This keeps host interaction visible in host-owned certification, telemetry, and profiling.
|
||||
|
||||
## 6 Blocking and Long Operations
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user