From f0f3f972ce738f4c0099b9565468b4978409442e Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Wed, 15 Jul 2026 08:01:47 +0100 Subject: [PATCH] fix PBX executable format identity --- crates/console/prometeu-bytecode/src/lib.rs | 2 +- crates/console/prometeu-bytecode/src/model.rs | 22 +- .../prometeu-bytecode/src/program_image.rs | 2 +- .../prometeu-vm/src/virtual_machine.rs | 10 +- .../prometeu-vm/src/virtual_machine/loader.rs | 42 ++-- .../tests/verifier_closure_reject.rs | 4 +- crates/tools/pbxgen-dummy-boy/src/lib.rs | 2 +- discussion/index.ndjson | 4 +- ...identity-must-not-borrow-frontend-names.md | 61 ++++++ ...0051-corrigir-identificacao-formato-pbx.md | 113 ----------- ...DEC-0042-pbx-executable-format-identity.md | 115 ----------- ...PLN-0173-pbx-executable-format-identity.md | 191 ------------------ .../specs/runtime/16-host-abi-and-syscalls.md | 6 + 13 files changed, 113 insertions(+), 461 deletions(-) create mode 100644 discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md delete mode 100644 discussion/workflow/agendas/AGD-0051-corrigir-identificacao-formato-pbx.md delete mode 100644 discussion/workflow/decisions/DEC-0042-pbx-executable-format-identity.md delete mode 100644 discussion/workflow/plans/PLN-0173-pbx-executable-format-identity.md diff --git a/crates/console/prometeu-bytecode/src/lib.rs b/crates/console/prometeu-bytecode/src/lib.rs index 19c898cb..247d266c 100644 --- a/crates/console/prometeu-bytecode/src/lib.rs +++ b/crates/console/prometeu-bytecode/src/lib.rs @@ -19,6 +19,6 @@ pub use assembler::{assemble, AsmError}; pub use decoder::{decode_next, DecodeError}; pub use disassembler::disassemble; pub use layout::{compute_function_layouts, FunctionLayout}; -pub use model::{BytecodeLoader, FunctionMeta, LoadError, SyscallDecl}; +pub use model::{BytecodeLoader, FunctionMeta, LoadError, SyscallDecl, PBX_MAGIC}; pub use program_image::ProgramImage; pub use value::{string_materialization_count, HeapRef, Value}; diff --git a/crates/console/prometeu-bytecode/src/model.rs b/crates/console/prometeu-bytecode/src/model.rs index df2d41a9..f357c917 100644 --- a/crates/console/prometeu-bytecode/src/model.rs +++ b/crates/console/prometeu-bytecode/src/model.rs @@ -80,9 +80,11 @@ const SECTION_KIND_DEBUG: u32 = 3; const SECTION_KIND_EXPORTS: u32 = 4; const SECTION_KIND_SYSCALLS: u32 = 5; -/// Represents the final serialized format of a PBS v0 module. +pub const PBX_MAGIC: [u8; 4] = *b"PBX\0"; + +/// Represents the final serialized format of a PBX v0 module. /// -/// This structure is a pure data container for the PBS format. It does NOT +/// This structure is a pure data container for the PBX format. It does NOT /// contain any linker-like logic (symbol resolution, patching, etc.). /// All multi-module programs must be flattened and linked by the compiler /// before being serialized into this format. @@ -126,8 +128,8 @@ impl BytecodeModule { final_sections.push((SECTION_KIND_SYSCALLS, syscall_data)); let mut out = Vec::new(); - // Magic "PBS\0" - out.extend_from_slice(b"PBS\0"); + // Magic "PBX\0" + out.extend_from_slice(&PBX_MAGIC); // Version 0 out.extend_from_slice(&0u16.to_le_bytes()); // Endianness 0 (Little Endian), Reserved @@ -272,8 +274,8 @@ impl BytecodeLoader { return Err(LoadError::UnexpectedEof); } - // Magic "PBS\0" - if &bytes[0..4] != b"PBS\0" { + // Magic "PBX\0" + if bytes[0..4] != PBX_MAGIC[..] { return Err(LoadError::InvalidMagic); } @@ -708,7 +710,7 @@ mod tests { fn create_header(section_count: u32) -> Vec { let mut h = vec![0u8; 32]; - h[0..4].copy_from_slice(b"PBS\0"); + h[0..4].copy_from_slice(&PBX_MAGIC); h[4..6].copy_from_slice(&0u16.to_le_bytes()); // version h[6] = 0; // endianness h[8..12].copy_from_slice(§ion_count.to_le_bytes()); @@ -727,7 +729,7 @@ mod tests { } } - fn build_pbs_with_sections(sections: Vec<(u32, Vec)>) -> Vec { + fn build_pbx_with_sections(sections: Vec<(u32, Vec)>) -> Vec { let mut data = create_header(sections.len() as u32); let mut offset = 32 + (sections.len() as u32 * 12); @@ -897,7 +899,7 @@ mod tests { #[test] fn test_malformed_sysc_section_is_rejected() { - let data = build_pbs_with_sections(vec![(SECTION_KIND_SYSCALLS, vec![1, 0, 0])]); + let data = build_pbx_with_sections(vec![(SECTION_KIND_SYSCALLS, vec![1, 0, 0])]); assert_eq!(BytecodeLoader::load(&data), Err(LoadError::MalformedSection)); } @@ -914,7 +916,7 @@ mod tests { sysc.extend_from_slice(&0u16.to_le_bytes()); sysc.extend_from_slice(&0u16.to_le_bytes()); - let data = build_pbs_with_sections(vec![(SECTION_KIND_SYSCALLS, sysc)]); + let data = build_pbx_with_sections(vec![(SECTION_KIND_SYSCALLS, sysc)]); assert_eq!(BytecodeLoader::load(&data), Err(LoadError::InvalidUtf8)); } diff --git a/crates/console/prometeu-bytecode/src/program_image.rs b/crates/console/prometeu-bytecode/src/program_image.rs index 66ed722c..bdb1f383 100644 --- a/crates/console/prometeu-bytecode/src/program_image.rs +++ b/crates/console/prometeu-bytecode/src/program_image.rs @@ -4,7 +4,7 @@ use crate::value::Value; use std::collections::HashMap; use std::sync::Arc; -/// Represents a fully linked, executable PBS program image. +/// Represents a fully linked, executable PBX program image. /// /// Under the Prometeu architecture, the ProgramImage is a "closed-world" artifact /// produced by the compiler. All linking, relocation, and symbol resolution diff --git a/crates/console/prometeu-vm/src/virtual_machine.rs b/crates/console/prometeu-vm/src/virtual_machine.rs index 8f5d6002..f6707fd2 100644 --- a/crates/console/prometeu-vm/src/virtual_machine.rs +++ b/crates/console/prometeu-vm/src/virtual_machine.rs @@ -2627,7 +2627,7 @@ mod tests { fn test_loader_hardening_unsupported_version() { let mut vm = VirtualMachine::default(); let mut header = vec![0u8; 32]; - header[0..4].copy_from_slice(b"PBS\0"); + header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC); header[4..6].copy_from_slice(&1u16.to_le_bytes()); // version 1 (unsupported) let res = vm.initialize(header); @@ -2635,16 +2635,16 @@ mod tests { } #[test] - fn test_loader_hardening_malformed_pbs_v0() { + fn test_loader_hardening_malformed_pbx_v0() { let mut vm = VirtualMachine::default(); let mut header = vec![0u8; 32]; - header[0..4].copy_from_slice(b"PBS\0"); + header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC); header[8..12].copy_from_slice(&1u32.to_le_bytes()); // 1 section claimed but none provided let res = vm.initialize(header); match res { Err(VmInitError::ImageLoadFailed(prometeu_bytecode::LoadError::UnexpectedEof)) => {} - _ => panic!("Expected PbsV0LoadFailed(UnexpectedEof), got {:?}", res), + _ => panic!("Expected PBX v0 load failure UnexpectedEof, got {:?}", res), } } @@ -3084,7 +3084,7 @@ mod tests { fn test_loader_hardening_missing_sysc_section() { let mut vm = VirtualMachine::default(); let mut header = vec![0u8; 32]; - header[0..4].copy_from_slice(b"PBS\0"); + header[0..4].copy_from_slice(&prometeu_bytecode::PBX_MAGIC); let res = vm.initialize(header); diff --git a/crates/console/prometeu-vm/src/virtual_machine/loader.rs b/crates/console/prometeu-vm/src/virtual_machine/loader.rs index 21f964ba..192b44ff 100644 --- a/crates/console/prometeu-vm/src/virtual_machine/loader.rs +++ b/crates/console/prometeu-vm/src/virtual_machine/loader.rs @@ -83,30 +83,32 @@ impl VirtualMachine { self.scheduler = Scheduler::new(); self.current_coro = None; - let program = if program_bytes.starts_with(b"PBS\0") { - match prometeu_bytecode::BytecodeLoader::load(&program_bytes) { - Ok(mut module) => { - patch_module_hostcalls(&mut module, self.capabilities) - .map_err(VmInitError::LoaderPatchFailed)?; + let program = match prometeu_bytecode::BytecodeLoader::load(&program_bytes) { + Ok(mut module) => { + patch_module_hostcalls(&mut module, self.capabilities) + .map_err(VmInitError::LoaderPatchFailed)?; - let max_stacks = Verifier::verify(&module.code, &module.functions) - .map_err(|e| VmInitError::VerificationFailed(format!("{:?}", e)))?; + let max_stacks = Verifier::verify(&module.code, &module.functions) + .map_err(|e| VmInitError::VerificationFailed(format!("{:?}", e)))?; - let mut program = ProgramImage::from(module); - let mut functions = program.functions.as_ref().to_vec(); - for (func, max_stack) in functions.iter_mut().zip(max_stacks) { - func.max_stack_slots = max_stack; - } - program.functions = std::sync::Arc::from(functions); - program + let mut program = ProgramImage::from(module); + let mut functions = program.functions.as_ref().to_vec(); + for (func, max_stack) in functions.iter_mut().zip(max_stacks) { + func.max_stack_slots = max_stack; } - Err(prometeu_bytecode::LoadError::InvalidVersion) => { - return Err(VmInitError::UnsupportedFormat); - } - Err(e) => return Err(VmInitError::ImageLoadFailed(e)), + program.functions = std::sync::Arc::from(functions); + program } - } else { - return Err(VmInitError::InvalidFormat); + Err(prometeu_bytecode::LoadError::InvalidVersion) => { + return Err(VmInitError::UnsupportedFormat); + } + Err(prometeu_bytecode::LoadError::InvalidMagic) => { + return Err(VmInitError::InvalidFormat); + } + Err(prometeu_bytecode::LoadError::UnexpectedEof) if program_bytes.len() < 32 => { + return Err(VmInitError::InvalidFormat); + } + Err(e) => return Err(VmInitError::ImageLoadFailed(e)), }; let pc = program diff --git a/crates/dev/prometeu-layer-tests/tests/verifier_closure_reject.rs b/crates/dev/prometeu-layer-tests/tests/verifier_closure_reject.rs index 9d19bb84..25ad069e 100644 --- a/crates/dev/prometeu-layer-tests/tests/verifier_closure_reject.rs +++ b/crates/dev/prometeu-layer-tests/tests/verifier_closure_reject.rs @@ -2,8 +2,8 @@ use prometeu_vm::{VirtualMachine, VmInitError}; #[test] fn invalid_image_format_is_rejected_before_execution() { - // Provide bytes that are not a valid PBS image. The VM must reject it with InvalidFormat. - let program_bytes = b"NOT_PBS_IMAGE".to_vec(); + // Provide bytes that are not a valid PBX image. The VM must reject it with InvalidFormat. + let program_bytes = b"NOT_PBX_IMAGE".to_vec(); let mut vm = VirtualMachine::default(); let result = vm.initialize(program_bytes); assert!(matches!(result, Err(VmInitError::InvalidFormat))); diff --git a/crates/tools/pbxgen-dummy-boy/src/lib.rs b/crates/tools/pbxgen-dummy-boy/src/lib.rs index 4cccf568..9890914c 100644 --- a/crates/tools/pbxgen-dummy-boy/src/lib.rs +++ b/crates/tools/pbxgen-dummy-boy/src/lib.rs @@ -130,7 +130,7 @@ mod tests { fn generated_program_is_pbx_module_with_expected_syscalls() { let bytes = build_program(); - assert!(bytes.starts_with(b"PBS\0")); + assert!(bytes.starts_with(&prometeu_bytecode::PBX_MAGIC)); assert!(bytes.len() > 64); } diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 11313e4e..a13ca07f 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":49,"AGD":52,"DEC":43,"PLN":174,"LSN":56,"CLSN":1}} +{"type":"meta","next_id":{"DSC":49,"AGD":52,"DEC":43,"PLN":174,"LSN":57,"CLSN":1}} {"type":"discussion","id":"DSC-0044","status":"done","ticket":"hub-suspended-game-kill-affordance","title":"Hub Suspended Game Kill Affordance","created_at":"2026-07-05","updated_at":"2026-07-05","tags":["hub","lifecycle","game","ui"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0054","file":"discussion/lessons/DSC-0044-hub-suspended-game-kill-affordance/LSN-0054-manual-hub-kill-must-share-game-termination-cleanup.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]} {"type":"discussion","id":"DSC-0043","status":"done","ticket":"system-os-cartridge-switch-orchestrator","title":"SystemOS Cartridge Switch Orchestrator","created_at":"2026-07-03","updated_at":"2026-07-05","tags":["runtime","os","lifecycle","game","cartridge","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0053","file":"discussion/lessons/DSC-0043-system-os-cartridge-switch-orchestrator/LSN-0053-game-switching-is-lifecycle-replacement-not-loader-work.md","status":"done","created_at":"2026-07-05","updated_at":"2026-07-05"}]} {"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."} @@ -46,4 +46,4 @@ {"type":"discussion","id":"DSC-0037","status":"done","ticket":"rgba8888-framebuffer-and-pixel-format-direction","title":"Agenda - RGBA8888 Framebuffer and Pixel Format Direction","created_at":"2026-05-22","updated_at":"2026-05-23","tags":["gfx","framebuffer","rgb565","rgba8888","renderer","assets","host","backend"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0037-rgba8888-framebuffer-and-pixel-format-direction/LSN-0046-pixel-format-contracts-must-move-as-one-surface.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23"}]} {"type":"discussion","id":"DSC-0046","status":"done","ticket":"runtime-owned-variable-glyph-bank-palette-protocol","title":"Runtime-Owned Variable Glyph Bank Palette Protocol","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["runtime","gfx","assets","glyph-bank","palette-serialization","protocol"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0055","file":"discussion/lessons/DSC-0046-runtime-owned-variable-glyph-bank-palette-protocol/LSN-0055-runtime-owned-asset-protocols-must-align-payload-residency-and-lookup.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14"}]} {"type":"discussion","id":"DSC-0047","status":"open","ticket":"portable-host-backend-strategy","title":"Portable Host Backend Strategy","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["host","desktop","portable","sdl","backend","rendering","input","audio","linux","android","handheld"],"agendas":[{"id":"AGD-0050","file":"AGD-0050-portable-host-backend-strategy.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0048","status":"review","ticket":"corrigir-identificacao-formato-pbx","title":"Corrigir Identificacao do Formato PBX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["runtime","bytecode","pbx","loader","format","architecture"],"agendas":[{"id":"AGD-0051","file":"AGD-0051-corrigir-identificacao-formato-pbx.md","status":"in_progress","created_at":"2026-07-15","updated_at":"2026-07-15"}],"decisions":[{"id":"DEC-0042","file":"DEC-0042-pbx-executable-format-identity.md","status":"accepted","created_at":"2026-07-15","updated_at":"2026-07-15","ref_agenda":"AGD-0051"}],"plans":[{"id":"PLN-0173","file":"PLN-0173-pbx-executable-format-identity.md","status":"review","created_at":"2026-07-15","updated_at":"2026-07-15","ref_decisions":["DEC-0042"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0048","status":"done","ticket":"corrigir-identificacao-formato-pbx","title":"Corrigir Identificacao do Formato PBX","created_at":"2026-07-15","updated_at":"2026-07-15","tags":["runtime","bytecode","pbx","loader","format","architecture"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0056","file":"discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md","status":"done","created_at":"2026-07-15","updated_at":"2026-07-15"}]} diff --git a/discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md b/discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md new file mode 100644 index 00000000..1af0e7ee --- /dev/null +++ b/discussion/lessons/DSC-0048-corrigir-identificacao-formato-pbx/LSN-0056-runtime-artifact-identity-must-not-borrow-frontend-names.md @@ -0,0 +1,61 @@ +--- +id: LSN-0056 +ticket: corrigir-identificacao-formato-pbx +title: Runtime Artifact Identity Must Not Borrow Frontend Names +created: 2026-07-15 +tags: [runtime, bytecode, pbx, frontend, format-boundary] +--- + +## Context + +Prometeu accepts bytecode produced by multiple frontends. PBS is the base +frontend language, while PBX is the executable bytecode artifact consumed by the +runtime. + +The runtime had inherited PBS terminology in the executable bytecode path, +including the serialized magic number, comments, tests, and VM loader checks. +That made one frontend appear to own the runtime executable format. + +## Key Decisions + +### PBX Executable Format Identity + +**What:** PBX is the runtime executable bytecode format, and `PBX\0` is its only +valid magic number. + +**Why:** Runtime artifact identity must be independent from any frontend that can +produce the artifact. Naming the executable format after PBS would make the +runtime boundary look language-specific. + +**Trade-offs:** The correction intentionally rejects old PBS-prefixed executable +artifacts instead of carrying a compatibility alias. This keeps the format +contract singular, but requires stale generated fixtures to be regenerated or +updated. + +## Patterns and Algorithms + +Put file-format identity in the module that serializes and deserializes the +format. Loaders and higher-level runtime code should call that boundary instead +of duplicating magic-number checks. + +When renaming an artifact identity, update all fixture construction and generator +assertions in the same pass as production serialization. Mixed fixture identity +usually means tests are asserting historical spelling rather than current +contract. + +## Pitfalls + +Do not globally erase frontend names. PBS remains correct when the subject is +the PBS language, stdlib, or frontend-facing API. It is wrong only when it names +the executable bytecode artifact. + +Do not preserve old magic values just to make a rename feel less disruptive. If +there is no compatibility requirement for old artifacts, aliases keep the +incorrect model alive. + +## Takeaways + +- Runtime artifact names should describe the runtime contract, not the compiler + or frontend that produced the artifact. +- Magic numbers are normative format identity, not cosmetic labels. +- Loader code should delegate file-format validation to the format owner. diff --git a/discussion/workflow/agendas/AGD-0051-corrigir-identificacao-formato-pbx.md b/discussion/workflow/agendas/AGD-0051-corrigir-identificacao-formato-pbx.md deleted file mode 100644 index 6084e2d2..00000000 --- a/discussion/workflow/agendas/AGD-0051-corrigir-identificacao-formato-pbx.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -id: AGD-0051 -ticket: corrigir-identificacao-formato-pbx -title: Corrigir Identificacao do Formato PBX -status: in_progress -created: 2026-07-15 -resolved: 2026-07-15 -decision: DEC-0042 -tags: [runtime, bytecode, pbx, loader, format, architecture] ---- - -## Contexto - -O formato executavel do Prometeu deve ser identificado como PBX, Prometeu Bytecode Executable. Esse nome representa o artefato binario carregado e executado pelo runtime, independentemente da linguagem ou frontend que gerou o programa. - -Hoje ainda existem referencias a PBS no caminho do bytecode executavel. A busca inicial encontrou `PBS\0` no encoder/decoder de `prometeu-bytecode`, verificacoes diretas no loader da VM, comentarios sobre "PBS format" e testes que constroem imagens usando `PBS\0`. - -Esse estado cria uma associacao indevida entre o formato executavel e o frontend PBS. A direcao desejada e tratar PBX como contrato do runtime e deixar PBS como uma possivel linguagem de origem, nao como identidade do binario. - -## Problema - -O runtime aceita e produz imagens com magic number `PBS\0`, embora o contrato conceitual do executavel seja PBX. Alem disso, a verificacao do magic aparece em mais de um lugar, o que cria risco de divergencia entre o modulo responsavel pelo formato binario e o loader da VM. - -A correcao precisa decidir: - -- onde o magic number canonico deve viver; -- se a transicao deve aceitar apenas `PBX\0` ou preservar algum modo legado temporario; -- quais comentarios, nomes de teste e mensagens de erro devem ser renomeados; -- qual camada deve validar o formato e qual camada deve apenas consumir o resultado decodificado. - -## Pontos Criticos - -- **Fato:** `crates/console/prometeu-bytecode/src/model.rs` escreve e valida `PBS\0` diretamente. -- **Fato:** `crates/console/prometeu-vm/src/virtual_machine/loader.rs` tambem testa `program_bytes.starts_with(b"PBS\0")`. -- **Fato:** testes em `prometeu-vm`, `prometeu-bytecode`, `prometeu-layer-tests` e `pbxgen-dummy-boy` ainda citam PBS ou constroem headers com `PBS\0`. -- **Fato:** a documentacao de arquitetura e ISA ja usa PBX para o artefato de bytecode em pontos relevantes. -- **Risco:** aceitar `PBS\0` e `PBX\0` indefinidamente manteria dois contratos de arquivo para o mesmo formato. -- **Risco:** trocar apenas strings e testes, sem centralizar o magic, pode deixar a duplicacao no loader pronta para regressao futura. -- **Hipotese:** como os cartuchos de teste sao gerados por ferramentas locais (`pbxgen-*`) e nao ha compromisso declarado com executaveis antigos, a mudanca pode ser estrita para `PBX\0`. - -## Opcoes - -### Opcao A - Renomeacao estrita para PBX com magic centralizado - -- **Abordagem:** definir uma constante publica do formato binario, por exemplo `PBX_MAGIC: [u8; 4] = *b"PBX\0"`, no crate/modulo dono da serializacao PBX; fazer encoder, decoder, geradores e testes usarem essa constante; remover do loader da VM a verificacao duplicada por magic e deixar o decoder retornar `InvalidFormat`. -- **Pro:** fecha o contrato com uma unica identidade de arquivo; elimina a associacao PBS no runtime; reduz duplicidade no loader. -- **Contra:** qualquer artefato antigo com `PBS\0` deixa de carregar e precisa ser regenerado. -- **Manutenibilidade:** melhor opcao no longo prazo porque o formato fica nomeado no ponto certo e o loader nao precisa conhecer bytes de cabecalho. - -### Opcao B - Aceitar `PBS\0` como alias legado durante uma janela de transicao - -- **Abordagem:** introduzir `PBX\0` como magic canonico, mas permitir que o decoder aceite `PBS\0` temporariamente, possivelmente emitindo erro, aviso ou marcador de compatibilidade. -- **Pro:** reduz quebra imediata se houver artefatos binarios preexistentes fora dos testes. -- **Contra:** prolonga a existencia de dois magic numbers validos e exige uma politica clara para remover o alias. -- **Manutenibilidade:** aceitavel apenas se houver necessidade real de compatibilidade; sem data de remocao, vira divida permanente. - -### Opcao C - Renomear comentarios/testes, mas manter o magic atual - -- **Abordagem:** trocar nomenclatura superficial de PBS para PBX em comentarios e nomes de teste, sem alterar o magic number nem a validacao duplicada. -- **Pro:** menor alteracao imediata. -- **Contra:** conserva o erro principal no contrato de arquivo e mascara a discrepancia entre nome e bytes reais. -- **Manutenibilidade:** fraca; aumenta a chance de futuras decisoes assumirem que PBX ja esta corrigido quando o magic ainda nao foi corrigido. - -## Sugestao / Recomendacao - -Seguir a Opcao A, salvo evidencia concreta de que precisamos carregar executaveis antigos com `PBS\0`. - -A decisao deveria fixar que: - -- PBX e o nome do formato executavel do runtime; -- o magic canonico e `PBX\0`; -- a constante do magic pertence ao modulo/crate responsavel pela serializacao do formato binario; -- o loader da VM nao deve duplicar a verificacao de magic, apenas chamar o decoder/linker apropriado e propagar erro de formato; -- referencias a PBS devem permanecer apenas quando o assunto for explicitamente a linguagem/frontend PBS, nao o executavel. - -## Perguntas em Aberto - -- [x] Existe algum artefato binario `PBS\0` publicado ou preservado que precise continuar carregando? - - Nao. A correcao deve ser sem compatibilidade legada para `PBS\0`. -- [x] O erro de formato deve mencionar explicitamente `PBX\0` ou apenas "invalid PBX magic"? - - A decisao deve preservar o estilo atual de erro quando possivel; o ponto essencial e trocar a identidade do formato para PBX, nao redesenhar a semantica de diagnostico. -- [x] A constante do magic deve ficar em `prometeu-bytecode::model`, em um modulo dedicado de formato, ou em uma API publica do crate para ser consumida por geradores e testes? - - Nao ha necessidade de redesenhar a organizacao atual do formato. A mudanca deve seguir a mesma estrutura que hoje trata o magic como PBS, corrigindo a identidade para PBX e centralizando o literal no modulo responsavel pelo formato binario. -- [x] A especificacao canonica do formato PBX ja existe em `docs/specs`, ou esta agenda deve originar tambem uma decisao/plano para adicionar esse trecho? - - Sim, a execucao deve atualizar a especificacao canonica em `docs/specs` para registrar PBX como formato executavel do runtime e `PBX\0` como magic number. - -## Criterio para Encerrar - -Encerrar esta agenda quando houver acordo sobre: - -- aceitar apenas `PBX\0` ou manter alias temporario para `PBS\0`; -- o ponto canonico da constante do magic; -- a responsabilidade do loader da VM; -- o escopo de renomeacao em comentarios, testes, geradores e documentacao. - -Com essas respostas, a agenda esta pronta para virar uma decisao normativa e depois um plano de execucao para specs e codigo. - -## Discussion - -Aberta em 2026-07-15 a partir do pedido para corrigir a identificacao do formato PBX e remover referencias indevidas a PBS no runtime. - -2026-07-15: Fechado entendimento de que nao havera compatibilidade com `PBS\0`. A mudanca deve corrigir a identidade do formato de PBS para PBX dentro da organizacao atual do crate de bytecode, evitando redesenho desnecessario. O problema central e separar o frontend PBS do bytecode executavel PBX, ja que o Prometeu aceita multiplos frontends. A execucao deve incluir atualizacao em `docs/specs`. - -## Resolution - -A agenda recomenda decisao normativa com os seguintes pontos: - -- PBX e o formato executavel do runtime, independente do frontend de origem. -- O magic number canonico passa a ser `PBX\0`. -- Nao deve haver alias legado para `PBS\0`. -- A implementacao deve seguir a organizacao atual do crate de bytecode, apenas corrigindo a identidade e centralizando o magic no modulo responsavel pelo formato binario. -- O loader da VM nao deve manter verificacao duplicada do magic quando a validacao pertence ao decoder/modelo do formato. -- A especificacao canonica em `docs/specs` deve registrar o contrato PBX. diff --git a/discussion/workflow/decisions/DEC-0042-pbx-executable-format-identity.md b/discussion/workflow/decisions/DEC-0042-pbx-executable-format-identity.md deleted file mode 100644 index 92080c03..00000000 --- a/discussion/workflow/decisions/DEC-0042-pbx-executable-format-identity.md +++ /dev/null @@ -1,115 +0,0 @@ ---- -id: DEC-0042 -ticket: corrigir-identificacao-formato-pbx -title: PBX Executable Format Identity -status: accepted -created: 2026-07-15 -accepted: 2026-07-15 -agenda: AGD-0051 -plans: [PLN-0173] -tags: [runtime, bytecode, pbx, loader, format, architecture] ---- - -## Status - -Accepted. - -## Contexto - -Prometeu supports multiple frontends. PBS is the base Prometeu frontend language, but it is not the identity of the runtime executable artifact. - -The runtime executable bytecode format is PBX, Prometeu Bytecode Executable. Current runtime code still carries the wrong PBS identity in the executable bytecode path, including the serialized magic number `PBS\0`, comments, tests, and a duplicated VM loader check. - -That naming leak binds the runtime bytecode format to one frontend and weakens the boundary between frontend language output and runtime executable input. - -## Decisao - -PBX SHALL be the canonical identity of the Prometeu runtime executable bytecode format. - -The canonical PBX magic number MUST be `PBX\0`. - -The runtime MUST NOT accept `PBS\0` as a legacy alias for PBX. Existing generated artifacts or tests that use `PBS\0` MUST be regenerated or updated to `PBX\0`. - -The implementation MUST preserve the current bytecode crate organization unless a local code constraint forces a narrower mechanical adjustment. This decision does not authorize a format-module redesign. - -The magic literal MUST be centralized in the module that owns binary bytecode serialization/deserialization. Encoder, decoder, tests, and local PBX generators SHOULD consume that central definition where the existing crate boundaries allow it. - -The VM loader MUST NOT duplicate PBX magic validation when that validation belongs to the bytecode decoder/model layer. The loader SHOULD delegate bytecode format recognition to the bytecode crate and propagate the resulting format error. - -References to PBS MUST remain only where the subject is the PBS frontend language or its frontend-facing API. References to the executable bytecode artifact MUST use PBX. - -The canonical runtime specs under `docs/specs` MUST record PBX as the executable bytecode format and `PBX\0` as its magic number. - -## Rationale - -PBS and PBX name different layers. - -PBS is a frontend language. PBX is the runtime executable artifact. Since Prometeu accepts multiple frontends, naming the executable format as PBS incorrectly implies that the runtime bytecode is tied to the base frontend. - -Rejecting legacy `PBS\0` keeps the file contract singular. Supporting both `PBS\0` and `PBX\0` would preserve the same ambiguity this decision is meant to remove. - -Keeping the current bytecode crate organization limits the change to contract correction and mechanical propagation. The problem is the wrong identity, not the module layout. - -Centralizing the magic number at the bytecode serialization boundary prevents the VM loader, tests, and generators from becoming independent sources of truth for the executable format. - -## Invariantes / Contrato - -- PBX is the runtime executable bytecode format. -- PBS is not the runtime executable bytecode format. -- `PBX\0` is the only valid magic number for PBX artifacts. -- `PBS\0` is invalid as a PBX artifact magic number. -- PBX magic validation belongs to the bytecode format layer. -- VM loader code must not own a separate PBX magic check. -- Tests must express PBX fixture data with the same identity used by production bytecode serialization. -- Runtime specs must describe the PBX executable identity in English. - -## Technical Specification - -The execution plan derived from this decision must update at least these surfaces when present: - -- bytecode serialization and deserialization code that writes or validates `PBS\0`; -- bytecode comments and type documentation that describe the executable format as PBS; -- VM loader logic that checks `program_bytes.starts_with(b"PBS\0")`; -- tests that construct bytecode headers with `PBS\0`; -- local PBX generator tests that assert a `PBS\0` prefix; -- layer tests or diagnostics that describe invalid executable bytes as PBS-specific; -- runtime specs under `docs/specs` that need an explicit PBX executable format contract. - -The execution plan must avoid broad redesign. A small public constant, local constant, or existing-module export is acceptable if it follows the current bytecode crate structure. - -## Constraints - -- No compatibility alias for `PBS\0`. -- No new binary format versioning policy is introduced by this decision. -- No frontend language behavior is changed by this decision. -- No cartridge container magic such as `PMTU` is changed by this decision. -- No asset payload magic values are changed by this decision. -- No loader ownership expansion is allowed; loader responsibility should shrink where duplicate format validation exists. - -## Impactos - -- **Spec:** `docs/specs` must state PBX executable identity and magic number in English. -- **Runtime:** bytecode encoder/decoder and VM loader behavior must converge on `PBX\0`. -- **Host:** no direct host behavior change is expected. -- **Firmware:** no direct firmware behavior change is expected unless firmware tests or generated cartridges embed PBX bytes. -- **Tooling:** local PBX generators and tests must emit/assert `PBX\0`. -- **Tests:** invalid-format and loader-hardening tests must be renamed or adjusted so PBS remains frontend terminology only. - -## Referencias - -- `AGD-0051`: `discussion/workflow/agendas/AGD-0051-corrigir-identificacao-formato-pbx.md` -- `crates/console/prometeu-bytecode/src/model.rs` -- `crates/console/prometeu-vm/src/virtual_machine/loader.rs` -- `docs/specs` - -## Propagacao Necessaria - -- Create an execution plan before editing specs or code. -- Update runtime specs before or alongside code execution. -- Update code and tests in the same implementation pass so no mixed `PBS\0`/`PBX\0` state remains. -- After execution, create or update lesson material only if the implementation reveals a reusable boundary lesson beyond this decision. - -## Revision Log - -- 2026-07-15: Initial draft from AGD-0051. -- 2026-07-15: Accepted by user and linked to PLN-0173. diff --git a/discussion/workflow/plans/PLN-0173-pbx-executable-format-identity.md b/discussion/workflow/plans/PLN-0173-pbx-executable-format-identity.md deleted file mode 100644 index 72bb1b6e..00000000 --- a/discussion/workflow/plans/PLN-0173-pbx-executable-format-identity.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -id: PLN-0173 -ticket: corrigir-identificacao-formato-pbx -title: PBX Executable Format Identity Implementation -status: review -created: 2026-07-15 -completed: -decisions: [DEC-0042] -tags: [runtime, bytecode, pbx, loader, format, tests, specs] ---- - -## Briefing - -Implement `DEC-0042` by correcting the Prometeu runtime executable bytecode identity from PBS to PBX. - -The executable bytecode format must use `PBX\0` as its only valid magic number. `PBS\0` must not remain accepted as an alias. PBS references must remain only when they refer to the PBS frontend language or frontend-facing APIs. - -## Decisions de Origem - -- `DEC-0042` - PBX Executable Format Identity - -## Alvo - -After execution, runtime bytecode serialization, runtime bytecode deserialization, loader behavior, local PBX generators, tests, and runtime specs must agree that: - -- PBX is the runtime executable bytecode format. -- `PBX\0` is the only valid PBX magic number. -- `PBS\0` is invalid executable bytecode magic. -- VM loader code does not own a separate magic-number gate. - -## Escopo - -### Included - -- Add or expose a canonical PBX magic constant in the existing `prometeu-bytecode` format ownership path. -- Replace bytecode serialization and deserialization use of `PBS\0` with `PBX\0`. -- Remove duplicate VM loader magic validation that currently checks `program_bytes.starts_with(b"PBS\0")`. -- Update tests that construct executable bytecode headers with `PBS\0`. -- Update local PBX generator tests that assert the old magic prefix. -- Rename executable-format comments and diagnostics that incorrectly call the executable image PBS. -- Add or update English runtime specs under `docs/specs` to record PBX executable identity and `PBX\0`. - -### Excluded - -- No compatibility path for `PBS\0`. -- No new binary format versioning policy. -- No redesign of the bytecode crate module layout. -- No frontend language behavior changes. -- No changes to cartridge container magic such as `PMTU`. -- No changes to asset payload magic values. -- No broad cleanup of legitimate PBS frontend references in specs. - -## Fora de Escopo - -- Reworking PBX instruction encoding. -- Reworking syscall binding, `SYSC`, `HOSTCALL`, or verifier behavior except where tests depend on the corrected magic. -- Moving bytecode model types into new modules. -- Introducing migration tooling for old `PBS\0` artifacts. - -## Plano de Execucao - -### Step 1 - Accept the decision in discussion metadata - -**What:** Mark `DEC-0042` as accepted and link this plan to it. - -**How:** Update the decision frontmatter and `discussion/index.ndjson` so the decision is accepted, the discussion is ready for planning, and `PLN-0173` is linked through `ref_decisions`. - -**File(s):** - -- `discussion/workflow/decisions/DEC-0042-pbx-executable-format-identity.md` -- `discussion/index.ndjson` - -### Step 2 - Centralize PBX magic in the bytecode format owner - -**What:** Define the canonical PBX magic as `PBX\0` in the current bytecode model/serialization area. - -**How:** Add a constant in `crates/console/prometeu-bytecode/src/model.rs` or the nearest existing module that already owns binary bytecode serialization. Use the current organization; do not create a new format subsystem. - -**File(s):** - -- `crates/console/prometeu-bytecode/src/model.rs` - -### Step 3 - Update bytecode serialization and deserialization - -**What:** Make the bytecode crate write and validate `PBX\0`. - -**How:** Replace direct `b"PBS\0"` writes and comparisons with the centralized PBX magic constant. Update comments that describe the magic and executable image as PBS. Keep current error shape unless the code already names the format in the message. - -**File(s):** - -- `crates/console/prometeu-bytecode/src/model.rs` -- `crates/console/prometeu-bytecode/src/program_image.rs` - -### Step 4 - Remove duplicate VM loader magic ownership - -**What:** Stop the VM loader from performing a separate magic-number gate. - -**How:** Remove the `program_bytes.starts_with(b"PBS\0")` branch from `crates/console/prometeu-vm/src/virtual_machine/loader.rs`. Let the bytecode decoder/model validate the executable format and propagate invalid-format failure. Preserve existing loader behavior for successful PBX artifacts and for invalid bytes. - -**File(s):** - -- `crates/console/prometeu-vm/src/virtual_machine/loader.rs` - -### Step 5 - Update VM and bytecode tests - -**What:** Align all executable bytecode fixtures with PBX. - -**How:** Replace test headers that copy `b"PBS\0"` with the PBX magic constant when crate boundaries allow it, or with `b"PBX\0"` when importing the constant would add inappropriate coupling. Rename comments/test data that call executable images PBS. - -**File(s):** - -- `crates/console/prometeu-vm/src/virtual_machine.rs` -- `crates/console/prometeu-bytecode/src/model.rs` -- `crates/dev/prometeu-layer-tests/tests/verifier_closure_reject.rs` - -### Step 6 - Update local PBX generator assertions - -**What:** Ensure generated cartridges/programs assert PBX executable magic. - -**How:** Change `pbxgen-dummy-boy` tests that currently assert `bytes.starts_with(b"PBS\0")` to assert `PBX\0`, preferably using the bytecode crate constant if it is already accessible to the tool crate. - -**File(s):** - -- `crates/tools/pbxgen-dummy-boy/src/lib.rs` - -### Step 7 - Update runtime specs - -**What:** Record PBX executable identity and magic number in canonical runtime specs. - -**How:** Add a concise English contract section in the most appropriate `docs/specs/runtime` document. The section must state that PBX is the runtime executable bytecode format, `PBX\0` is the only valid magic, and PBS is a frontend name rather than executable-format identity. Do not remove legitimate references to PBS frontend APIs. - -**File(s):** - -- `docs/specs/runtime/16-host-abi-and-syscalls.md` if the PBX pre-load artifact contract is the best local home. -- Another existing `docs/specs/runtime/*.md` file only if inspection shows a more direct bytecode/executable-format location. - -### Step 8 - Verify no mixed executable identity remains - -**What:** Ensure the repository no longer contains executable-format `PBS\0` or PBS image wording. - -**How:** Run literal searches for `PBS\0`, `NOT_PBS_IMAGE`, and executable-format PBS comments. Keep PBS mentions that clearly refer to the frontend language or frontend-facing APIs. - -**File(s):** - -- `crates/` -- `docs/specs/` -- `docs/vm-arch/` - -## Criterios de Aceite - -- [ ] `prometeu-bytecode` writes `PBX\0` for executable bytecode artifacts. -- [ ] `prometeu-bytecode` rejects `PBS\0` as invalid executable magic. -- [ ] The PBX magic literal is centralized in the existing bytecode format ownership path. -- [ ] VM loader code no longer checks `program_bytes.starts_with(b"PBS\0")` or owns any replacement magic check. -- [ ] Tests and local generators no longer construct or assert executable artifacts with `PBS\0`. -- [ ] Legitimate PBS references remain only for the PBS frontend language or frontend-facing APIs. -- [ ] `docs/specs` states the PBX executable identity and `PBX\0` magic contract in English. -- [ ] Repository search finds no `PBS\0` occurrences after execution. - -## Tests / Validacao - -### Unit Tests - -- Run the bytecode crate tests that cover serialization/deserialization and invalid magic behavior. -- Run VM loader tests that cover invalid format and loader hardening. -- Run `pbxgen-dummy-boy` tests that assert generated executable bytes. - -### Integration Tests - -- Run the layer test containing `verifier_closure_reject` after renaming the invalid image fixture. -- Run broader workspace tests if local execution time is acceptable after the targeted tests pass. - -### Manual Verification - -- `rg -n -F "PBS\\0" crates docs/specs docs/vm-arch` must return no results. -- `rg -n -F "NOT_PBS_IMAGE" crates docs/specs docs/vm-arch` must return no results. -- `rg -n -F "PBS" crates docs/specs docs/vm-arch` must show only frontend-language or frontend-facing references. -- `discussion validate` must pass after plan creation and after implementation updates. - -## Dependencies - -- `DEC-0042` must remain accepted before execution starts. -- Existing bytecode crate boundaries must be respected; imports of the PBX magic constant into tools/tests must not create inappropriate dependency cycles. -- The runtime spec location should be chosen from existing `docs/specs/runtime` structure before editing. - -## Riscos - -- Importing the PBX magic constant into all tests may create unwanted crate dependencies; use direct `b"PBX\0"` in tests where that is the least coupled option. -- Removing the loader magic gate may expose assumptions in loader tests that expected early rejection before decoding; update tests to assert behavior, not internal rejection site. -- Broad PBS search results include legitimate frontend references; execution must not erase frontend terminology from specs or APIs. -- If generated test cartridges are checked in elsewhere, they must be regenerated or updated in the same implementation pass. diff --git a/docs/specs/runtime/16-host-abi-and-syscalls.md b/docs/specs/runtime/16-host-abi-and-syscalls.md index 88a4749a..5e341dbb 100644 --- a/docs/specs/runtime/16-host-abi-and-syscalls.md +++ b/docs/specs/runtime/16-host-abi-and-syscalls.md @@ -65,6 +65,12 @@ dedicated `System` profile ABI and stdlib/framework. ## 3 Syscall Resolution +PBX, Prometeu Bytecode Executable, is the runtime executable bytecode format. +Its canonical file magic is `PBX\0`. The former PBS-prefixed magic is not valid +for PBX artifacts: PBS names a frontend language, while PBX names the executable +artifact accepted by the runtime. This distinction is required because Prometeu +bytecode can be produced by multiple frontends. + The host maintains a registry: ```