--- id: DEC-0033 ticket: real-render-worker-establishment title: Real Render Worker Contract status: accepted created: 2026-06-15 accepted: agenda: AGD-0043 plans: [PLN-0110, PLN-0111, PLN-0112, PLN-0113, PLN-0114, PLN-0115, PLN-0116, PLN-0117, PLN-0118, PLN-0119, PLN-0120, PLN-0121] tags: [runtime, renderer, worker, concurrency, host, hal, architecture] --- ## Status Decision accepted from agenda `AGD-0043`. This is the normative contract for implementation plans that establish the real render worker for Prometeu. ## Contexto `DEC-0031` established the VM/render boundary around closed render submissions, single-slot handoff, frame pacing, AppMode policy, ownership epoch, and render telemetry. `DEC-0032` and plans `PLN-0098` through `PLN-0109` prepared the platform boundary required for a real worker: - `HardwareBridge` was removed from production/runtime contracts; - `RuntimePlatform` became the runtime-facing platform service boundary; - `RenderSubmissionSink` accepts owned render submissions; - `Game2DFrameComposer` separates logical Game 2D frame closure from backend rendering; - `gfx2d.*` and `gfxui.*` syscalls buffer commands instead of mutating `Gfx` immediately; - firmware, Hub, runtime, host desktop, and tests moved to platform services; - specs now state that worker/render consumers must not depend on `&mut Hardware`, `&mut Gfx`, live `FrameComposer`, or mutable VM state. The remaining work is to replace the cooperative/local `LocalRenderWorker` proof with a real worker that drains render submissions without blocking VM progress and publishes complete RGBA8888 frames for host presentation. ## Decisao Prometeu SHALL implement the real render worker as a runtime-owned worker controller with host-provided backend integration. The worker controller SHALL live in `prometeu-system`, near `RenderManager`, because `RenderManager` owns AppMode policy, ownership/epoch, latest-wins handoff semantics, and render telemetry. Shared contract types and traits SHALL live in `prometeu-hal` when they cross runtime/host/driver boundaries. Local/default and test implementations SHALL live in `prometeu-drivers` or host crates as appropriate. The worker SHALL consume owned `RenderSubmission` values through a thread-safe single-slot latest-wins handoff. The VM producer MUST NOT block on rasterization, publication, presentation, or worker completion. The worker SHALL publish owned RGBA8888 frames, not native window/swapchain objects. The initial shared frame type SHALL be `OwnedRgba8888Frame` in `prometeu-hal`. The host event loop SHALL remain responsible for native window upload/present. The worker MUST NOT depend on winit, pixels, SDL, swapchain handles, native textures, or host window APIs. The agenda may be implemented through multiple plans, but `AGD-0043` is complete only when the worker functions on the real host path, not merely in fake/local tests. ## Rationale The real worker must prove the architecture promised by `DEC-0031`: VM execution and render consumption can proceed independently without crossing mutable runtime state into the renderer. Putting the controller in `prometeu-system` keeps render policy in the same layer that already owns frame lifecycle, ownership epochs, latest-wins behavior, and telemetry. Putting it only in the host would make the contract desktop-specific and harder to test without a window. Publishing an owned RGBA8888 frame keeps the worker host-agnostic. The host can upload that frame to any native presentation backend while the worker stays testable through ordinary memory comparisons. Using a single explicit pending slot directly models the accepted backpressure rule. Channels or queues can accidentally preserve history or block producers. The runtime contract is not "render every produced frame"; it is "the latest complete submission wins and the VM does not wait for the consumer." Read-only bank access by id preserves the no-copy resource boundary. Banks are render resources, not payloads to duplicate into each submission. The worker should resolve resource ids through a compact read-only interface without taking `&mut Hardware`, `&mut Gfx`, a live `FrameComposer`, or VM state. ## Invariantes / Contrato ### 1. Runtime controller ownership The worker controller MUST live in `prometeu-system`. `RenderManager` SHALL remain the authority for: - AppMode render policy; - ownership/epoch; - latest-wins handoff semantics; - render telemetry; - stale submission discard; - shutdown/request-stop coordination visible to runtime policy. Host crates MAY instantiate or wire the controller, but they MUST NOT redefine worker semantics. ### 2. Shared HAL contracts `prometeu-hal` SHALL define shared types/traits that cross the runtime/host/driver boundary. At minimum, the worker work SHALL introduce: - `OwnedRgba8888Frame`; - compact read-only render resource access contracts for bank lookup by id; - typed worker/backend error contracts where they are shared across crates. ### 3. Owned RGBA8888 frame publication `OwnedRgba8888Frame` SHALL represent a completed logical frame ready for host upload/present. It MUST include: - `FrameId`; - render ownership/epoch metadata; - width; - height; - `stride_pixels`; - owned RGBA8888 pixel data as `Vec`. The pixel data MUST use the canonical RGBA8888 raw value contract already used by the runtime specs. It MUST NOT be described as native-endian host pixels, native texture data, or backend-specific surface memory. Repeating the last valid frame SHALL mean reusing the last published `OwnedRgba8888Frame`, not recomposing from VM state or live composer state. ### 4. Thread-safe latest-wins handoff The real handoff SHALL be a thread-safe single-slot latest-wins structure. The initial implementation SHOULD use an explicit slot based on `Mutex> + Condvar`. Producer behavior: - publish replaces the pending submission if one already exists; - replacement increments drop/replacement telemetry; - publish MUST NOT wait for rasterization or present; - publish MUST wake the consumer when needed. Consumer behavior: - wait for pending submission or shutdown; - take ownership of the latest pending submission; - leave the pending slot empty while work is in flight; - discard stale work before publication if ownership/epoch no longer matches. ### 5. Pending and in-flight are separate The worker MUST distinguish pending submissions from in-flight work. Once the worker takes a submission, that submission is in flight. New producer submissions may replace the pending slot while the worker is still rasterizing the previous in-flight submission. Before publishing an in-flight frame, the worker MUST check: - stop/shutdown state; - render owner; - render epoch/generation. If the frame is stale, the worker MUST discard it and update telemetry. It MUST NOT publish stale pixels. ### 6. Shutdown is bounded Worker shutdown MUST be bounded and observable. The shutdown timeout MUST be configurable. The initial default SHOULD be `250ms`. On shutdown: - stop state MUST be signaled; - the worker MUST be woken if it is waiting; - join MUST complete within the configured bound or return/report a `ShutdownTimeout` failure; - in-flight work MAY finish rasterization, but MUST NOT publish after stop/epoch invalidation says it is stale. ### 7. Read-only bank access by id The render backend SHALL resolve render resources through a compact read-only interface by stable ids. Banks are read-only by definition during render consumption. The worker MUST NOT copy entire banks into submissions. The worker MUST NOT require bank snapshots. The worker MUST NOT require `Arc` as part of the public contract. Implementation may use any internal storage strategy that satisfies the public contract, but the render worker contract is ids plus read-only access. Resource installation, mutation, and residency changes remain outside in-flight render consumption. ### 8. Backend and host presentation split The worker backend SHALL consume `RenderSubmission` plus read-only resource access and produce `OwnedRgba8888Frame`. The host event loop SHALL upload/present the latest published frame through its native API. The worker MUST NOT call native window present directly unless a future decision revises the host presentation model. ### 9. Typed error model The worker work SHALL introduce a minimal typed error model, such as `RenderWorkerError`. The error model MUST cover at least: - backend unavailable; - render failed; - publish/present handoff failed; - shutdown timeout; - stale submission discarded; - worker panic captured as internal failure. Panic containment MAY remain as a safety net. Ordinary worker/backend failure MUST NOT rely on panic as the normal reporting path. ### 10. Telemetry Worker telemetry SHALL preserve and extend the existing render telemetry model. At minimum, telemetry SHOULD include: - submissions produced; - pending submissions replaced/dropped; - submissions consumed; - frames published/presented; - stale submissions discarded; - render failures; - repeated-frame count; - shutdown timeout count. Telemetry MUST NOT change VM semantics. ### 11. Test contract The worker contract MUST be proven without a native window. Tests SHALL use deterministic synchronization primitives such as barriers and condvars, not timing sleeps as the primary proof mechanism. The test matrix MUST prove: - VM producer does not block when worker rasterization is held; - latest-wins replacement occurs while a frame is in flight; - stale owner/epoch prevents publication; - shutdown is bounded; - typed errors and telemetry are emitted; - repeat uses the last published `OwnedRgba8888Frame`; - fake/local backend behavior matches the contract before desktop integration. ### 12. Final scope The implementation MAY be split into multiple plans. However, the agenda is not complete until the real host path uses the worker. A fake/local backend is required for contract tests, but it is not sufficient as the final state of `AGD-0043`. ## Impactos ### Spec Runtime specs must document: - `OwnedRgba8888Frame`; - the thread-safe single-slot latest-wins worker handoff; - the worker/host presentation split; - read-only bank access by id; - shutdown and typed error behavior; - telemetry expectations. ### Runtime `prometeu-system` must add the worker controller and integrate it with `RenderManager`. The VM tick path must submit render work without blocking on worker consumption. ### HAL `prometeu-hal` must expose shared worker contracts: - owned RGBA8888 frame type; - render resource read-only access traits; - worker/backend error types as needed. ### Drivers `prometeu-drivers` must provide fake/local implementations suitable for deterministic tests and non-window integration. Concrete local rendering may continue to use existing GFX machinery internally, but must expose the worker-facing contract without leaking `&mut Hardware`, `&mut Gfx`, or live `FrameComposer`. ### Host The desktop host must integrate the real worker path and upload/present the latest published `OwnedRgba8888Frame` through its native window backend. The host owns native presentation; the worker owns render consumption and frame publication. ### Tests Tests must cover concurrency behavior deterministically and must include final host-path integration evidence. ## Referencias - `AGD-0043`: Real Render Worker Establishment. - `AGD-0042`: Host Hardware and Render Boundary Preparation. - `DEC-0031`: VM and Render Parallel Execution Boundary. - `DEC-0032`: Platform Layer and HardwareBridge Elimination. - `LSN-0048`: Render Workers Need a Closed Packet Contract. - `docs/specs/runtime/04-gfx-peripheral.md`. - `docs/specs/runtime/11-portability-and-cross-platform-execution.md`. ## Propagacao Necessaria Create implementation plans before editing specs or code. Recommended plan sequence: 1. define `OwnedRgba8888Frame`, read-only bank access contracts, and worker error types in HAL; 2. introduce the thread-safe latest-wins handoff and deterministic fake/local worker tests; 3. implement worker controller lifecycle, stop token, bounded shutdown, pending/in-flight separation, and telemetry in `prometeu-system`; 4. implement fake/local backend that consumes `RenderSubmission` and produces `OwnedRgba8888Frame`; 5. integrate runtime render submission path with the worker without blocking VM ticks; 6. add stale owner/epoch discard and repeat-last-published-frame behavior; 7. integrate desktop host upload/present from the latest published `OwnedRgba8888Frame`; 8. update specs and final validation tests. ## Revision Log - 2026-06-15: Initial decision draft generated from accepted `AGD-0043`.