diff --git a/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md b/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md deleted file mode 100644 index ffba8bab..00000000 --- a/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md +++ /dev/null @@ -1,236 +0,0 @@ -# PR-001 Runtime Builtin Registry and Intrinsic Metadata - -## Goal - -Introduce the runtime-owned metadata layer required for VM-owned builtin types -and intrinsic operations without touching the host syscall path. - -This PR creates the semantic foundation that the frontend can target later. - -## Why - -Today the host-backed path already exists conceptually: - -- canonical host identity, -- PBX `SYSC`, -- `HOSTCALL`, -- loader resolution, -- final `SYSCALL`. - -Builtin semantics need a different ownership path: - -- runtime-owned builtin type metadata, -- runtime-owned intrinsic metadata, -- flattened slot layouts, -- and VM execution that never crosses the host boundary. - -Without this layer, the runtime will be forced to encode builtin behavior as -ad hoc helpers or as pseudo-syscalls, both of which conflict with the PBS model. - -## Scope - -Add runtime data structures and lookup APIs for: - -- builtin type identity, -- builtin field layout, -- builtin constant identity, -- intrinsic identity, -- intrinsic stack layouts, -- and intrinsic implementation registration. - -Do not add bytecode execution changes in this PR. -Do not add loader-side host changes in this PR. - -## Required Runtime Concepts - -### 1. Builtin type identity - -Canonical builtin identity must be: - -```text -(name, version) -``` - -Examples: - -- `("color", 1)` -- `("vec2", 1)` -- `("pixel", 1)` - -This is distinct from source-visible PBS names such as `Color` or `Vec2`. - -### 2. Builtin layout descriptor - -Introduce a runtime descriptor roughly shaped like: - -```text -BuiltinTypeMeta { - id: u32 - name: string - version: u16 - fields: [BuiltinFieldMeta] - flat_slot_layout: [AbiType] - flat_slot_width: u16 -} -``` - -with: - -```text -BuiltinFieldMeta { - name: string - start_slot: u16 - field_type: BuiltinLayoutType - flat_slot_width: u16 -} -``` - -`BuiltinLayoutType` should support: - -- fixed-width scalar runtime types, -- builtin nominal type references, -- and recursively flattenable aggregate builtin layouts. - -### 3. Builtin constant descriptor - -Introduce a constant registry keyed by: - -```text -(target, name, version) -``` - -Examples: - -- `("vec2", "zero", 1)` - -This registry must return either: - -- direct materialization metadata, -- or a runtime-owned constant implementation hook. - -### 4. Intrinsic descriptor - -Introduce an intrinsic registry keyed by: - -```text -(owner, name, version) -``` - -Examples: - -- `("vec2", "dot", 1)` -- `("vec2", "length", 1)` - -Descriptor shape should include at minimum: - -```text -IntrinsicMeta { - id: u32 - owner: string - name: string - version: u16 - arg_layout: [AbiType] - ret_layout: [AbiType] - deterministic: bool - may_allocate: bool -} -``` - -## Design Rules - -1. This registry is runtime-owned, not host-owned. -2. It must not reuse `SYSC`. -3. It must not depend on capability grants. -4. It must not resolve through the host syscall registry. -5. It must preserve flattened slot width for verifier and executor use. -6. It must preserve nominal builtin identity even when two builtins share the same width. - -## Representation Guidance - -### Scalars - -Support at least: - -- `int` -- `float` -- `bool` -- builtin nominal scalars such as `color` - -For nominal scalars like `color`, allow either: - -- a dedicated runtime value variant, -- or a 1-slot carrier with explicit builtin type tagging in metadata. - -The important requirement is that `color` remain semantically distinct from a -plain `int` even if it shares width. - -### Aggregates - -Builtin aggregates such as `vec2` and `pixel` should remain stack-shaped. - -The registry must treat them as: - -- fixed-width, -- finite, -- flattenable, -- and non-heap in this phase. - -No heap object model is required. - -## Suggested API Surface - -Introduce runtime APIs along these lines: - -- `lookup_builtin_type(name, version) -> BuiltinTypeMeta` -- `lookup_builtin_constant(target, name, version) -> BuiltinConstMeta` -- `lookup_intrinsic(owner, name, version) -> IntrinsicMeta` -- `lookup_intrinsic_by_id(id) -> IntrinsicMeta` - -Avoid exposing host-like resolution APIs for this subsystem. - -## Out of Scope - -- `INTRINSIC` opcode execution -- `INTRCALL` preload resolution -- loader patching -- frontend lowering -- host integration -- HAL color adaptation - -## Acceptance Criteria - -1. Runtime contains a distinct builtin/intrinsic registry subsystem. -2. Registry keys use canonical builtin and intrinsic identities, not source aliases. -3. Builtin layouts support recursive flattening and expose total flat slot width. -4. Builtin constants have a dedicated registry keyed separately from intrinsics. -5. No part of the implementation routes through host syscall metadata. -6. Unit tests cover lookup and flattening for `color`, `vec2`, and `pixel`. - -## Test Cases - -### Builtin layout flattening - -- `color` flattens to width `1` -- `vec2` flattens to width `2` -- `pixel(x: int, y: int, color: color)` flattens to width `3` - -### Nested field offsets - -- `vec2.x` starts at slot `0` -- `vec2.y` starts at slot `1` -- `pixel.color` starts at slot `2` - -### Intrinsic metadata - -- `vec2.dot` has arg width `4` and ret width `1` -- `vec2.length` has arg width `2` and ret width `1` - -## Notes for Follow-up PRs - -This PR should intentionally stop short of execution. - -The next PR should consume these descriptors in: - -- bytecode decoding, -- verifier stack-effect calculation, -- and runtime dispatch for `INTRINSIC `. diff --git a/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md b/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md deleted file mode 100644 index 5fe61b66..00000000 --- a/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md +++ /dev/null @@ -1,168 +0,0 @@ -# PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch - -## Goal - -Add a dedicated runtime execution path for VM-owned intrinsics using the -metadata introduced in PR-001. - -This PR should establish that intrinsic execution is a first-class VM path, -separate from host-backed syscall execution. - -## Why - -The runtime currently has a conceptual host-backed path centered on `SYSCALL`. -Builtin semantics cannot be layered cleanly on top of that path because: - -- intrinsic ownership is VM-owned, not host-owned, -- intrinsic execution must not require host resolution, -- intrinsic execution must not depend on capabilities, -- and verifier stack effects must come from builtin layout metadata. - -The runtime therefore needs its own instruction and dispatch path. - -## MVP Decision - -This PR should implement direct final-form execution: - -```text -INTRINSIC -``` - -Do not implement `INTRCALL` in this PR unless the runtime already has a clear -preload declaration mechanism that can be reused without coupling to `SYSC`. - -The intent is: - -- keep the runtime simple, -- let the frontend eventually emit final intrinsic ids for a selected VM line, -- and avoid pulling loader complexity into the first implementation. - -## Scope - -Add: - -- runtime opcode support for `INTRINSIC `, -- verifier support for intrinsic stack effects, -- execution dispatch by intrinsic id, -- trap behavior for unknown intrinsic ids, -- and tests proving separation from the syscall pipeline. - -Do not add host loader changes in this PR. - -## Required Changes - -### 1. Bytecode/ISA support - -Introduce a dedicated intrinsic opcode in the runtime bytecode interpreter. - -Normative behavior: - -- decode `INTRINSIC `, -- lookup intrinsic metadata by numeric id, -- verify or assume verifier-proven stack shape, -- execute runtime-owned implementation, -- push results back according to intrinsic return layout. - -### 2. Verifier support - -The verifier must derive intrinsic stack effects from runtime intrinsic metadata. - -Required behavior: - -- lookup intrinsic meta by id, -- compute argument slot width from flattened `arg_layout`, -- compute result slot width from flattened `ret_layout`, -- reject underflow, -- reject invalid slot shape, -- and preserve existing verifier guarantees for control flow. - -Examples: - -- `vec2.dot(vec2, vec2) -> float` becomes `pop 4, push 1` -- `vec2.length(vec2) -> float` becomes `pop 2, push 1` - -### 3. Trap behavior - -Add deterministic failure for: - -- unknown intrinsic id, -- malformed intrinsic metadata, -- verifier/runtime disagreement on intrinsic width, -- and execution-time misuse that escapes verifier guarantees. - -If trap enums exist, add a runtime-specific invalid intrinsic trap rather than -reusing invalid syscall traps. - -### 4. Dispatch separation - -Ensure the interpreter or executor has two clearly distinct paths: - -- `SYSCALL ` for host-backed services -- `INTRINSIC ` for VM-owned semantics - -These paths must not share registry lookup semantics. - -## Suggested Runtime Shape - -Use a structure roughly like: - -```text -execute_intrinsic(id, stack, runtime_ctx) -> Result<(), Trap> -``` - -where: - -- `stack` is mutated using metadata-defined widths, -- `runtime_ctx` is VM-internal context only, -- and no host syscall registry access occurs. - -If an execution table already exists for opcodes, add intrinsic dispatch as a -parallel branch rather than as a host-call subtype. - -## Acceptance Criteria - -1. Runtime recognizes and executes `INTRINSIC `. -2. Verifier derives stack effects from intrinsic metadata rather than hardcoded arity alone. -3. Unknown intrinsic ids fail deterministically. -4. `INTRINSIC` does not route through host binding, loader syscall resolution, or capability checks. -5. `SYSCALL` behavior remains unchanged. -6. Tests demonstrate that intrinsic execution and syscall execution are distinct runtime paths. - -## Test Cases - -### Positive - -- execute `vec2.dot` over two canonical `vec2` values and obtain one float result -- execute `vec2.length` over one canonical `vec2` value and obtain one float result - -### Verification - -- verifier accepts a correct stack program using `INTRINSIC ` -- verifier rejects a program with insufficient stack width for `INTRINSIC ` - -### Separation - -- `SYSCALL` still resolves and executes host-backed operations as before -- invalid intrinsic id produces intrinsic-specific failure, not syscall failure - -## Out of Scope - -- frontend parser/lowering changes -- preload `INTRCALL` resolution -- builtin constant source lowering -- new host bindings - -## Notes for Follow-up PRs - -The next PR should populate the registry and executor with the first builtin -set: - -- `color` -- `vec2` -- `pixel` - -and with first intrinsic implementations: - -- `vec2.dot` -- `vec2.length` -- optionally `vec2.distance` diff --git a/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md b/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md deleted file mode 100644 index be74f311..00000000 --- a/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md +++ /dev/null @@ -1,273 +0,0 @@ -# PR-003 Runtime First Builtins: Color, Vec2, Pixel - -## Goal - -Implement the first concrete builtin types, constants, and intrinsic behaviors -so the frontend can target a stable MVP builtin line. - -This PR should be the first runtime feature slice that a PBS frontend can map -to directly. - -## Why - -After PR-001 and PR-002, the runtime has the machinery but not the domain set. -This PR makes the model real by installing the first builtin registry entries -and execution implementations. - -The initial scope should match the current agenda and spec direction: - -- scalar builtin `color` -- aggregate builtin `vec2` -- aggregate builtin `pixel` -- intrinsic methods for `vec2` -- builtin constant for `vec2.zero` - -## Scope - -Add runtime registry entries and implementations for: - -- builtin type `color` -- builtin type `vec2` -- builtin type `pixel` -- builtin constant `("vec2", "zero", 1)` -- intrinsic `("vec2", "dot", 1)` -- intrinsic `("vec2", "length", 1)` - -`("vec2", "distance", 1)` may be included if the numeric contract is already -clear enough for portable behavior. -If not, leave it for a follow-up PR. - -## Builtin Type Contracts - -### 1. `color` - -Canonical identity: - -```text -("color", 1) -``` - -Expected properties: - -- scalar builtin -- flat slot width `1` -- runtime semantic distinctness from plain `int` - -Suggested field model: - -- `raw` carrier field if the runtime benefits from explicit internal naming - -### 2. `vec2` - -Canonical identity: - -```text -("vec2", 1) -``` - -Expected properties: - -- aggregate builtin -- flattened layout `[float, float]` -- field `x` at slot `0` -- field `y` at slot `1` -- flat slot width `2` - -### 3. `pixel` - -Canonical identity: - -```text -("pixel", 1) -``` - -Expected properties: - -- aggregate builtin -- semantic layout `[int, int, color]` -- flattened width `3` -- field `x` at slot `0` -- field `y` at slot `1` -- field `color` at slot `2` - -## Builtin Constant Contract - -### `vec2.zero` - -Canonical identity: - -```text -("vec2", "zero", 1) -``` - -Expected materialized value: - -```text -[0.0, 0.0] -``` - -This constant must be runtime-owned and materialized without touching the host. - -## Intrinsic Contracts - -### 1. `vec2.dot` - -Canonical identity: - -```text -("vec2", "dot", 1) -``` - -Stack contract: - -```text -args: [float, float, float, float] -ret: [float] -``` - -Semantic behavior: - -```text -(x1 * x2) + (y1 * y2) -``` - -### 2. `vec2.length` - -Canonical identity: - -```text -("vec2", "length", 1) -``` - -Stack contract: - -```text -args: [float, float] -ret: [float] -``` - -Semantic behavior: - -```text -sqrt((x * x) + (y * y)) -``` - -### 3. Optional: `vec2.distance` - -Canonical identity: - -```text -("vec2", "distance", 1) -``` - -Stack contract: - -```text -args: [float, float, float, float] -ret: [float] -``` - -Semantic behavior: - -```text -sqrt(((x1 - x2)^2) + ((y1 - y2)^2)) -``` - -Only include this if the runtime already has a clear portable numeric contract -for `sqrt`. - -## Representation Guidance - -### `color` - -Choose one of: - -1. dedicated scalar runtime variant with builtin nominal tag -2. 1-slot scalar carrier plus explicit builtin registry identity - -The critical rule is: - -- `color` must remain semantically a builtin color type, -- even if its carrier width matches `int`. - -### `vec2` and `pixel` - -Do not allocate heap objects for these in the MVP. - -Represent them as: - -- canonical stack-shaped flattened values, -- with runtime metadata describing field offsets and nominal builtin identity. - -## Numeric Contract Note - -`vec2.dot` is straightforward and should land in this PR. - -`vec2.length` and `vec2.distance` depend on the runtime's floating-point -portability story. If that story is not already stable, implement: - -1. `vec2.dot` -2. `vec2.zero` -3. builtin type descriptors for `color`, `vec2`, `pixel` - -and either: - -- gate `length`/`distance` behind the current platform float rules, -- or defer them into a follow-up PR. - -## Acceptance Criteria - -1. Runtime registry contains builtin entries for `color`, `vec2`, and `pixel`. -2. Runtime registry contains builtin constant entry for `("vec2", "zero", 1)`. -3. Runtime registry contains intrinsic entries for at least `vec2.dot` and `vec2.length`. -4. `vec2` layout is width `2` and `pixel` layout is width `3`. -5. `pixel` composes `color` through builtin layout metadata rather than by special-case host code. -6. Executing `vec2.dot` and `vec2.length` through `INTRINSIC ` produces correct runtime results. -7. No part of the implementation routes through `SYSC`, `HOSTCALL`, or `SYSCALL`. - -## Test Cases - -### Builtin metadata - -- `color` width is `1` -- `vec2` width is `2` -- `pixel` width is `3` - -### Constant materialization - -- materializing `("vec2", "zero", 1)` yields `[0.0, 0.0]` - -### Intrinsic execution - -- `dot([1, 2], [3, 4]) == 11` -- `length([3, 4]) == 5` - -### Composition - -- `pixel(x=1, y=2, color=)` uses builtin metadata width `3` -- `pixel.color` points at slot `2` - -## Frontend Alignment - -This PR should be implemented so the following frontend surfaces map naturally: - -```pbs -[BuiltinType(name="vec2", version=1)] -declare builtin type Vec2( - [Slot(0)] pub x: float, - [Slot(1)] pub y: float, -) { - [IntrinsicCall(name="dot")] - fn dot(other: Vec2) -> float; - - [IntrinsicCall(name="length")] - fn length() -> float; -} - -[BuiltinConst(target="vec2", name="zero", version=1)] -declare const ZERO: Vec2; -``` - -The runtime should not care whether the source-visible type name is `Vec2`, -`vec2`, or something else. -It should care only about canonical identities and flattened layout. diff --git a/docs/pull-requests/PR-004-runtime-vfs-path-traversal-hardening.md b/docs/pull-requests/PR-004-runtime-vfs-path-traversal-hardening.md new file mode 100644 index 00000000..b0bddad1 --- /dev/null +++ b/docs/pull-requests/PR-004-runtime-vfs-path-traversal-hardening.md @@ -0,0 +1,102 @@ +# PR-004: Runtime VFS Path Traversal Hardening + +## Briefing + +Hoje o `VirtualFS` normaliza barras, mas nao canonicaliza nem rejeita segmentos `..`. Em seguida, o backend de host concatena o caminho recebido com a raiz montada. Isso abre espaco para escapar da raiz virtual com caminhos como `/user/../../outside.txt`. + +Este PR endurece a fronteira entre o filesystem virtual e o filesystem do host. O objetivo e garantir que toda operacao de `read/write/delete/list/exists` permaneça estritamente dentro da raiz montada. + +## Problema + +- O `VirtualFS` aceita caminhos relativos e absolutos sem validacao estrutural suficiente. +- O backend `HostDirBackend` faz `root.join(path)` sem bloquear traversal. +- O problema afeta confidencialidade, integridade e isolamento do runtime. + +## Escopo + +- Endurecer a normalizacao de caminhos no `VirtualFS`. +- Endurecer a resolucao no `HostDirBackend`. +- Garantir comportamento consistente para `read_file`, `write_file`, `delete`, `list_dir` e `exists`. +- Cobrir casos de traversal em testes unitarios. + +## Fora de Escopo + +- Suporte a links simbolicos com politicas avancadas. +- Politicas de permissao por namespace (`/system`, `/user`, `/apps`, etc). +- Refactor completo da API de filesystem. + +## Abordagem + +1. Introduzir uma regra unica de validacao de caminho virtual: + - converter `\` para `/`; + - exigir caminho absoluto virtual; + - colapsar `.` quando aparecer; + - rejeitar qualquer segmento vazio ambiguo ou `..`; + - retornar erro explicito em vez de tentar "corrigir" traversal. +2. Fazer o `VirtualFS` operar apenas sobre caminhos validados. +3. Endurecer o `HostDirBackend` para nunca confiar apenas na normalizacao acima: + - resolver o caminho relativo a partir da raiz; + - rejeitar novamente qualquer tentativa de escapar; + - manter defesa em profundidade mesmo se outro backend ou chamador evoluir errado. +4. Garantir que operacoes booleanas como `exists` nao silenciem traversal como se fosse "arquivo inexistente" sem distinguir erro estrutural quando isso for relevante para a API. + +## Algoritmo + +### Normalizacao de caminho virtual + +Entrada: `path: &str` + +Saida: caminho virtual sanitizado ou erro. + +Passos: + +1. Substituir `\` por `/`. +2. Se o caminho nao comecar com `/`, prefixar `/`. +3. Separar por `/`. +4. Ignorar segmentos vazios e `.`. +5. Se algum segmento for `..`, falhar com `FsError`. +6. Reconstruir o caminho como `///...`. +7. Preservar `/` como raiz quando nao houver segmentos. + +### Resolucao no backend do host + +Entrada: caminho virtual sanitizado. + +Saida: `PathBuf` dentro de `root` ou erro. + +Passos: + +1. Remover o `/` inicial do caminho virtual. +2. Concatenar cada segmento validado manualmente em um `PathBuf` iniciado em `root`. +3. Nunca aceitar segmentos `..`, `.` ou componentes de prefixo/plataforma. +4. Antes de retornar, garantir que o caminho construido continua sob `root`. + +## Criterios de Aceite + +- Qualquer tentativa de traversal com `..` e rejeitada em `read_file`. +- Qualquer tentativa de traversal com `..` e rejeitada em `write_file`. +- Qualquer tentativa de traversal com `..` e rejeitada em `delete`. +- `exists` e `list_dir` nao acessam caminhos fora da raiz montada. +- Caminhos normais como `/user/save.dat` continuam funcionando. +- O backend de host continua criando subdiretorios validos dentro da raiz. + +## Tests + +- Teste unitario no `VirtualFS` para rejeitar: + - `../x` + - `/../x` + - `/user/../../x` + - `\\user\\..\\..\\x` +- Teste unitario no backend do host validando que um caminho de traversal nao resulta em acesso fora da raiz temporaria. +- Teste positivo para operacoes validas: + - criar arquivo em `/user/test.txt`; + - ler o mesmo arquivo; + - confirmar `exists`; + - apagar o arquivo. +- Rodar: + - `cargo test -p prometeu-system` + - `cargo test -p prometeu-host-desktop-winit` + +## Risco + +Baixo para a arquitetura e medio para compatibilidade, porque caminhos hoje aceitos de forma permissiva podem passar a falhar explicitamente. Esse endurecimento e desejado. diff --git a/docs/pull-requests/PR-005-host-audio-fallible-init-and-headless-tolerance.md b/docs/pull-requests/PR-005-host-audio-fallible-init-and-headless-tolerance.md new file mode 100644 index 00000000..8423dd41 --- /dev/null +++ b/docs/pull-requests/PR-005-host-audio-fallible-init-and-headless-tolerance.md @@ -0,0 +1,87 @@ +# PR-005: Host Audio Fallible Init and Headless Tolerance + +## Briefing + +O host desktop atual assume que audio de saida esta sempre disponivel e funcional. Em ambientes headless, CI, VMs remotas ou sistemas sem device compativel, a inicializacao usa `expect(...)` e encerra o processo. + +Este PR torna a pilha de audio tolerante a falhas de infraestrutura. O runtime deve continuar operando sem audio quando o host nao puder inicializar a saida sonora. + +## Problema + +- `default_output_device()` pode retornar `None`. +- `build_output_stream(...)` pode falhar por formato/configuracao. +- `stream.play()` pode falhar por indisponibilidade do backend. +- Todas essas falhas hoje derrubam o binario com `panic!`. + +## Escopo + +- Trocar inicializacao panica por API fallible. +- Permitir degradacao controlada para "sem audio". +- Manter telemetria/log suficiente para diagnostico. +- Cobrir o fluxo em testes de unidade onde viavel. + +## Fora de Escopo + +- Rework do mixer. +- Selecao automatica de formatos de audio mais sofisticada. +- Hot-reload de device de audio. +- Simulacao de audio em buffer offline. + +## Abordagem + +1. Mudar `HostAudio::init` para retornar `Result<(), HostAudioError>` ou tipo equivalente. +2. Representar explicitamente o estado "audio indisponivel": + - `producer = None` + - `stream = None` + - stats continuam funcionando sem crash. +3. No chamador, registrar aviso e seguir execucao sem audio. +4. Garantir que `send_commands` e `update_stats` sejam no-op seguros quando o audio nao estiver ativo. + +## Algoritmo + +### Inicializacao + +1. Buscar `default_output_device`. +2. Se nao existir: + - retornar erro de inicializacao controlado. +3. Tentar construir `StreamConfig` e `build_output_stream`. +4. Se falhar: + - retornar erro controlado sem panicar. +5. Tentar `play()`. +6. Se falhar: + - retornar erro controlado sem panicar. +7. Apenas em caso de sucesso preencher `producer`, `perf_consumer` e `_stream`. + +### Degradacao + +1. O host chama `init`. +2. Se `Ok`, audio ativo. +3. Se `Err`, loga a falha e continua sem audio. +4. O loop principal segue responsivo e funcional. + +## Criterios de Aceite + +- O runtime nao entra em `panic!` quando nao existe device de audio. +- O runtime nao entra em `panic!` quando `build_output_stream` falha. +- O runtime nao entra em `panic!` quando `play()` falha. +- `send_commands` e `update_stats` continuam seguros sem stream ativo. +- O host continua executando cartridge em modo sem audio. +- Logs deixam claro por que o audio foi desativado. + +## Tests + +- Introduzir testes de unidade para o estado sem audio: + - `send_commands` nao falha quando `producer` e `None`; + - `update_stats` nao falha quando `perf_consumer` e `None`. +- Se a estrutura atual permitir injecao de dependencia: + - testar caminho `no output device`; + - testar falha na criacao do stream; + - testar falha no `play`. +- Se injecao ainda nao existir, criar uma camada minima de abstracao para tornar esses cenarios testaveis sem depender do hardware real. +- Rodar: + - `cargo test -p prometeu-host-desktop-winit` + - `cargo test --workspace` + +## Risco + +Baixo. A mudanca principal e de robustez operacional. O maior cuidado e nao esconder a falha completamente; o modo sem audio precisa ser explicito em logs. diff --git a/docs/pull-requests/PR-006-cli-preserve-child-exit-status.md b/docs/pull-requests/PR-006-cli-preserve-child-exit-status.md new file mode 100644 index 00000000..8db2a506 --- /dev/null +++ b/docs/pull-requests/PR-006-cli-preserve-child-exit-status.md @@ -0,0 +1,72 @@ +# PR-006: CLI Preserve Child Exit Status + +## Briefing + +O wrapper `prometeu` despacha para outros binarios do ecossistema. Hoje, se o processo filho terminar sem exit code convencional, o CLI usa `unwrap_or(0)` e pode reportar sucesso mesmo quando houve abort, sinal ou encerramento anormal. + +Este PR corrige a propagacao de status do processo filho para tornar o CLI confiavel em automacao, CI e uso por scripts. + +## Problema + +- `status.code()` pode retornar `None`. +- `unwrap_or(0)` transforma falha anormal em sucesso. +- Isso mascara erros reais em `run`, `debug`, `build` e `verify`. + +## Escopo + +- Preservar corretamente o resultado do processo filho. +- Melhorar a mensagem de erro quando nao houver codigo numerico. +- Cobrir o comportamento com testes. + +## Fora de Escopo + +- Reestruturar todo o dispatcher. +- Implementar subcomandos ainda nao existentes. +- Alterar o protocolo entre CLI e bins filhos. + +## Abordagem + +1. Remover `unwrap_or(0)` no ponto de saida. +2. Tratar dois casos: + - filho retorna exit code numerico: repassar exatamente; + - filho termina sem codigo numerico: encerrar com codigo nao-zero e mensagem clara. +3. Se necessario, extrair a traducao de `ExitStatus` para uma funcao pequena e testavel. + +## Algoritmo + +Entrada: `ExitStatus` do processo filho. + +Passos: + +1. Chamar `status.code()`. +2. Se retornar `Some(code)`: + - encerrar o wrapper com `code`. +3. Se retornar `None`: + - escrever mensagem de erro indicando encerramento anormal; + - encerrar o wrapper com `1`. + +## Criterios de Aceite + +- Se o processo filho sair com `0`, o wrapper sai com `0`. +- Se o processo filho sair com codigo nao-zero, o wrapper replica o mesmo codigo. +- Se o processo filho terminar sem codigo numerico, o wrapper sai com codigo nao-zero. +- O comportamento fica coberto por teste unitario. + +## Tests + +- Extrair funcao pura ou quase pura para mapear `ExitStatus -> i32` e testá-la. +- Cobrir: + - `0`; + - `1`; + - outro codigo nao-zero; + - status sem code numerico quando a plataforma permitir criar esse caso em teste. +- Se o caso `None` depender de plataforma: + - encapsular sob `cfg(unix)` ou `cfg(windows)` conforme apropriado; + - manter ao menos o contrato da funcao testado por unidade. +- Rodar: + - `cargo test -p prometeu-cli` + - `cargo test --workspace` + +## Risco + +Muito baixo. A mudanca corrige semantica operacional do CLI e tende a melhorar observabilidade sem alterar a logica de dispatch. diff --git a/docs/pull-requests/README.md b/docs/pull-requests/README.md index f5519126..8cf460ff 100644 --- a/docs/pull-requests/README.md +++ b/docs/pull-requests/README.md @@ -1,18 +1,35 @@ -# Runtime PR Series for VM-owned Builtins and Intrinsics +# Pull Requests -This directory contains proposed pull requests for implementing VM-owned builtin -types and intrinsic execution in the runtime. +Este diretório armazena propostas de PRs arquiteturais e de implementação para o runtime. -The series is designed so that the frontend model described in: +## Padrão -- [6. VM-owned vs Host-backed](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.%20VM-owned%20vs%20Host-backed.md) -- [6.1. Intrinsics and Builtin Types Specification](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/specs/pbs/6.1.%20Intrinsics%20and%20Builtin%20Types%20Specification.md) -- [PBS Intrinsics and Builtin Types Agenda](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/agendas/PBS%20Intrinsics%20and%20Builtin%20Types%20Agenda.md) +Toda PR neste diretório deve ser autocontida. -can lower cleanly into the runtime without reusing the host syscall pipeline. +Cada documento deve incluir, no mínimo: -Recommended order: +- `Briefing` +- `Alvo` +- `Critérios de Aceite` +- `Tests`, quando necessário -1. [PR-001 Runtime Builtin Registry and Intrinsic Metadata](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-001-runtime-builtin-registry-and-intrinsic-metadata.md) -2. [PR-002 Runtime INTRINSIC Opcode, Verification, and Dispatch](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-002-runtime-intrinsic-opcode-verification-and-dispatch.md) -3. [PR-003 Runtime First Builtins: Color, Vec2, Pixel](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/studio/docs/pull-requests/PR-003-runtime-first-builtins-color-vec2-pixel.md) +## Barra de Qualidade + +O padrão esperado é JVM-grade. + +Isso implica: + +- arquitetura vem antes de implementação; +- decisões arquiteturais não devem ser tomadas durante a fase de implementação; +- quando a implementação encontrar dúvida arquitetural, a PR deve voltar para discussão de arquitetura; +- diante de ambiguidade estrutural, é preferível interromper a execução da PR e levantar um questionamento severo do que cristalizar uma decisão errada no código. + +## Condução + +Uma PR deste diretório deve: + +- definir claramente o problema; +- delimitar o alvo da mudança; +- explicitar o que está fora de escopo quando houver risco de expansão; +- estabelecer critérios objetivos de aceite; +- definir a estratégia de teste proporcional ao risco da mudança.