2026-09-04 - (/loop) The translator draws

phase 6 step (c) DONE - a translated `exp mrt0` puts its colour on the screen
BLOCKED is now empty; exp is in SUPPORTED
suites 136   clippy/fmt/identity clean on both repos

Thirty-ninth cron tick. No guest binary (checked, one command).

The first end-to-end check this project has been able to make

Phase 6's page states the cost of building ahead of the spine: everything in it is verified against material this project generated, so it cannot be wrong in a way its own tests would notice. The framebuffer oracle was built to break that, and this is the first thing through it.

tests/translated_export.rs draws twice over the same red clear - once with the hand-assembled fragment shader, once with a module the translator produced from guest instruction words - and compares every pixel of the two frames. Neither side checks itself. A differential, which is the shape every later comparison takes.

The fragment stage

Three differences from a compute module: the execution model, OriginUpperLeft, and whether the epilogue writes the observation window. The last is not cosmetic - a fragment shader may write a storage buffer only where fragmentStoresAndAtomics is enabled, and this device requests no features (D552). Skipping the epilogue keeps the module inside what the device runs, and removes the only static use of the observation buffer so no descriptor is needed.

The export

Four sources read for lane zero, bitcast rather than converted - a register holds the colour's bit pattern, and a conversion would scale every channel - assembled into a vec4 and stored. Three refusals, each separate: a module with no colour output; any target but mrt0 (which attachment another selects needs a capture, D104); and the compressed/done flags and write mask, which are not among the solved operands and so may not be claimed.

orbistoun-spirv gained OpCompositeConstruct and its shape row.

Three breaks, and the one that did not fire is the useful one

Reversing the components fails the frame comparison, every pixel. Accepting a different target fails at translation. Reading lane one instead of lane zero passes - because the shader's registers are set by literal moves and a literal move writes every active lane, so the choice is unobservable. Distinguishing them needs a shader whose lanes differ, which needs interpolation.

Written into the test. A break that does not fire is evidence about the test's reach, and reporting only the two that worked would have overstated it.

What this does not do

It does not make a real shader translate. Four moves and an export; no interpolation, no fragment inputs, no blending, no depth, one attachment, one target. exp is unblocked for the narrowest case - the one the oracle can check, and the only one that could have been checked first.

Roadmap step (c), G11 and the refused-instruction list rewritten (check 13).

Decision: D553.