prometeu-runtime/discussion/workflow/plans/PLN-0122-unify-render-worker-publication-store.md
bQUARKz 506eb36786
All checks were successful
Intrepid/Prometeu/Runtime/pipeline/pr-master This commit looks good
Real Render Worker Establishment
2026-06-20 09:16:38 +01:00

7.3 KiB

id ticket title status created completed ref_decisions tags
PLN-0122 real-render-worker-establishment Unify Render Worker Publication Store done 2026-06-20 2026-06-20
DEC-0033
runtime
renderer
worker
host
publication

Objective

Make worker frame publication have one observable authority by moving latest published frame storage behind the RenderWorkerFrameSink implementation used by the desktop host.

Background

DEC-0033 requires the worker to publish owned OwnedRgba8888Frame values while the host event loop remains responsible for native upload and present. The current desktop integration starts the worker with a host sink that accepts frames but discards them, while host presentation reads the latest frame from RenderWorkerController.

That works mechanically, but it weakens the publication model: the sink is not the observable publication boundary, and the controller becomes both lifecycle owner and frame store. This plan tightens the implementation without changing the DEC-0033 architecture.

Scope

Included

  • Introduce an explicit latest-frame publication store that implements RenderWorkerFrameSink.
  • Make the desktop host pass that store to the worker and read frames from the same store for upload/present.
  • Keep native upload and present in the host event loop.
  • Keep RenderWorkerController responsible for worker lifecycle, handoff, shutdown, typed errors, and telemetry.
  • Preserve repeat-latest-frame semantics using the stored OwnedRgba8888Frame.
  • Add tests proving the sink/store is the observable publication authority.

Excluded

  • No change to worker scheduling, latest-wins handoff, or AppMode render policy.
  • No change to OwnedRgba8888Frame layout or pixel format.
  • No native window, pixels, winit, SDL, swapchain, or texture dependency inside worker/runtime crates.
  • No move of native present into the worker thread.

Execution Steps

Step 1 - Add latest-frame store contract

What: Add a small thread-safe store for the latest published OwnedRgba8888Frame.

How: Implement a RenderWorkerFrameSink storage type using a lock-protected Option<OwnedRgba8888Frame>. It must provide read APIs for latest_frame() and repeat_latest_frame() or equivalent names that make host presentation read from the same publication authority used by publish().

File(s): crates/console/prometeu-hal/src/render_worker.rs or crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs, depending on whether the store is shared as a HAL utility or kept runtime/host integration-local.

Step 2 - Remove controller-owned latest frame storage

What: Stop treating RenderWorkerController as the frame publication store.

How: Remove or narrow latest_published_frame from controller state. record_published should update telemetry and rely on the sink/store for frame retention. Controller APIs that expose latest frames should either be removed or delegated explicitly to the publication store so there is not a second authoritative copy.

File(s): crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs, crates/console/prometeu-system/src/services/vm_runtime/lifecycle.rs, crates/console/prometeu-system/src/os/facades/vm.rs.

Step 3 - Wire desktop host to the publication store

What: Replace the no-op desktop sink with a real store-backed sink.

How: Add the store as host runner state, pass a clone to start_render_worker, and update redraw/presentation logic to read latest/repeated frames from that store. Delete the sink implementation that discards frames.

File(s): crates/host/prometeu-host-desktop-winit/src/runner.rs.

Step 4 - Preserve host presentation split

What: Keep upload/present in the winit event loop while publication remains worker-owned.

How: Continue copying RGBA8888 pixels into the existing pixels frame only from WindowEvent::RedrawRequested. The store must contain owned memory only and must not expose native host resources to worker/runtime code.

File(s): crates/host/prometeu-host-desktop-winit/src/runner.rs, crates/host/prometeu-host-desktop-winit/src/utilities.rs if helper changes are needed.

Step 5 - Add focused tests

What: Prove one-publication-authority behavior.

How: Add tests that publish through the sink and read the same frame through the store, prove repeat uses the stored frame without rendering again, and prove desktop presentation state observes store publication rather than controller-private storage.

File(s): crates/console/prometeu-system/src/services/vm_runtime/render_worker.rs, crates/host/prometeu-host-desktop-winit/src/runner.rs, and any new store module tests.

Test Requirements

Unit Tests

  • Store publishes and returns the latest OwnedRgba8888Frame.
  • Multiple publishes keep only the newest frame observable.
  • Repeat returns the stored frame and records repeat telemetry through the existing runtime path.
  • Controller publication telemetry remains correct after frame retention moves to the sink/store.

Integration Tests

  • cargo test -p prometeu-system
  • cargo test -p prometeu-host-desktop-winit
  • cargo test -p prometeu-hal if the store lives in HAL.

Manual Verification

  • Run the desktop host with a simple game cartridge and verify the host presents worker-produced frames.

Acceptance Criteria

  • Desktop host no longer uses a no-op RenderWorkerFrameSink that discards frames.
  • The same sink/store that receives publish(frame) is the source used by host presentation.
  • RenderWorkerController no longer owns an independent authoritative latest-frame store.
  • Worker/runtime crates remain free of native window and presentation APIs.
  • Existing worker lifecycle, shutdown, stale epoch, repeat, and telemetry tests pass.
  • Focused host tests prove the real publication store drives redraw/presentation.

Dependencies

  • DEC-0033 remains the governing decision.
  • PLN-0118 repeat/stale behavior and PLN-0119 desktop presentation integration are the implementation context being tightened.

Risks

  • Moving frame retention out of the controller can accidentally split repeat telemetry from host presentation; keep repeat accounting in one explicit runtime path.
  • Placing the store in HAL may overexpose a host convenience type; placing it in system may require a narrower host-facing API. Choose the smallest layer that avoids circular dependencies and keeps DEC-0033 boundaries intact.
  • Holding a mutex while copying pixels into the host frame would increase present latency; clone or take the owned frame before doing host upload work.

Validation Evidence

  • cargo fmt --check: passed.
  • cargo test -p prometeu-system -p prometeu-host-desktop-winit: passed.
  • cargo test --workspace: passed.
  • Publication residue scan: no HostWorkerFrameSink, latest_render_worker_frame, repeat_latest_render_worker_frame, controller latest_published_frame storage API, or repeat_latest_frame API remains in production crates.
  • Native presentation dependency scan: worker/runtime console code remains free of native window/presentation APIs; matches containing pixels are HAL pixel field names, not pixels/winit host APIs.
  • Manual desktop window run was not performed in this environment; host_presentation_observes_worker_publication_store covers the host publication/redraw boundary without native window setup.