Watch It Animate, It Said
The welcome card promised an animated star. It rendered a frozen one, in the corner, forever. Every patch in Lux was checked on the way in except the ones a new artist actually opens. Now they are checked too, and they do what their cards say.

The SDF Stars card in the welcome grid has a one line caption, and the caption is “Watch it animate.”
It did not animate.

Inside that patch was a Time node, sitting on the canvas, wired to nothing at all. It ticked away perfectly correctly and told absolutely no one. The star it was supposed to be driving held one shape from the first frame to the last, in the top left quadrant of an otherwise empty window, which is a bold interpretation of the word “animate”.
Here is what the card actually shipped, rendered a full sixty frames in:

That is not a still taken at the wrong moment. That is frame sixty. Frame zero is the same picture, to the pixel, and so is every frame after it.
The gate that checked everything except the important part
Lux has had a corpus gate for a while. It walks every .lux patch, loads
it against the real node registry, and fails the build if the loader raises
a single warning: an unknown node, a dead pin, a wire pointing at nothing.
It is a good gate. It has caught real rot.
It walked app/patches, the test corpus. It did not walk app/samples, the
twelve patches on the welcome screen. So the only patches in the entire
project that a first time artist is guaranteed to open were the only patches
nothing was checking, and they had rotted exactly the way you would expect
something to rot when nobody is looking at it.
The PBR Chrome card, for instance, poses its camera at a considered 42
degrees. It sets that on a pin called fov_degrees. The camera’s pin is
called fov_y. The loader spotted this, shrugged, dropped the value, and
handed the camera its 60 degree default, which is how that card had been
framed for months: not badly, just not the way anyone chose. The same card
also set prefilter_mips on its environment map, a pin removed some time
ago and mourned by nobody.
And there was a twelfth sample file, hello_washer_ring, that no card has
ever pointed at. No preview was baked for it. No code referenced it. It sat
in the directory carrying the same dead camera pin as the chrome card,
rotting quietly, unopened, unloved. It has been deleted. A sample nothing
opens is a sample nothing checks.
Loading clean is a lower bar than being right
The obvious fix is to point the gate at app/samples too, and that is done.
Every shipped sample now loads with zero warnings or the build goes red.
But “loads without complaint” and “does what the card says” are different claims, and only one of them is interesting to an artist. A patch whose Time node is wired to nothing loads perfectly cleanly. It is a completely valid graph. It is also a lie.
So the samples get two more checks that the loader structurally cannot make. The chrome card’s camera is now read back after evaluation and asserted to actually be running at the 42 degrees the patch asked for, not the 60 it was quietly falling back to. And the star card is rendered twice, once at the first frame and once sixty frames later, and the two frames have to differ. If someone unhooks that Time node again, the test that fails is not a vague snapshot wobble. It says the card’s promise is a lie, and it says how many pixels moved to prove it. Currently: zero out of six hundred and forty thousand.
The star now morphs its points from sharp to blunt and back, driven by Time through a sine, which is the chain the card claimed to be teaching all along. It also fills the frame, which it turns out is more appealing than occupying one quarter of it and leaving the rest as flat grey.

One more dead pin, lying in wait
While chasing fov_degrees through the tree it turned up somewhere less
decorative than a sample file: the editor’s auto wiring planner. The idea is
that you drop a 3D node on the canvas and Lux quietly builds you a camera, a
light, and a present chain, so the thing appears lit and framed instead of
invisible. The planner is written. It is not yet reachable from the drop
handler, so nothing in the shipping editor calls it, and no artist has ever
been handed a camera by it.
Which is the only reason nobody had been bitten. The camera it plans was pre posed at 50 degrees, on the same pin that does not exist, so the day someone finishes wiring the planner to the canvas it would have quietly served the 60 degree default and none of the intent. A bug with a start date.
The unit test covering that line asserted the pin was spelled fov_degrees.
It was not checking the camera. It was checking that we had typed the same
wrong word twice, and it passed every single time, faithfully.
The editor cannot see the plugins (it does not link them, by design), so no test living there can tell a real pin name from a fictional one. That check now lives where the registry actually exists: every pin the auto wiring pre poses is resolved against the shipped node, and a name that no node answers to fails the build. When it fires it names the pin, the node, and the pins that node does have, which is the difference between a test that catches a bug and a test that merely disagrees with you.
The one we only found because we went looking
Fixing the two bugs we knew about would have left the interesting question unanswered: how many more are there? So the check was written as a rule rather than as two assertions. Every shipped sample is now walked, and any node whose output reaches nothing, is never drawn, and is not the patch’s output gets the file named and the build failed.
It caught one immediately. Hello Shadertoy also carried a Time node wired to
nothing, and this one could never have been wired at all: the Shadertoy node
has no time input, because it drives the shader’s iTime itself. The patch’s
own description promised it was “driven by Time”. It was driven by Time. Just
not by that one, which sat on the canvas doing an impression of a wire.
It is a gentler bug than the frozen stars, since the shader animates regardless and the card’s promise is kept. But it is a dead node on the first canvas a new artist ever opens, quietly teaching them that this is normal. It is gone, and the rule is what keeps the next one from arriving.
Twelve samples went in. Eleven came out, all of them checked, all of them doing the thing printed on the card.