Files
DarkRoom/core/dr-pipeline/ops/texture.yaml
T
dtourolleandClaude Opus 5 e235e99cce Move the film to Effect in the descriptor that is actually read
An earlier commit claimed to move `film_sim` from `[tone, colour]` to
`[effect]` and did not. It edited `ops/film_sim.yaml`, where `attributes:` is
read, validated against the vocabulary, and then dropped: a `rust:` node
publishes its own descriptor, and the type still said tone and colour. The
stock went on appearing in the Light group beside exposure and again in Colour
beside white balance, exactly as before, and every test passed.

Nothing caught it because nothing could. The declaration parsed, the parity
tests compare ids rather than attributes, and an operation filed under the
wrong groups renders perfectly. It surfaced only on screen, as a missing
Effects tab — which is indistinguishable from a category that genuinely has
nothing in it, and is precisely how `Optics` looked for as long as it was
empty.

So three changes rather than one:

`FilmSim`'s descriptor declares `Attribute::Effect`, which is the move the
earlier commit described.

`attributes:` joins the keys a `rust:` node may not carry, beside `params`,
`uniforms`, `wgsl`, `helpers`, `define` and `label`. The rule was already
written — "its descriptor comes from the type" — and attributes were the one
field that slipped past it. A key that is silently ignored is worse than one
that is rejected, because it reads as though it worked; the eight hand-written
declarations lose a line that never did anything.

And a test asserts that every attribute the chain carries reaches the tab
strip. That is the property that was actually broken, and its failure mode is
invisible from every direction: the controls exist, they are in the shader,
and there is no way to filter to them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-05 18:28:59 +02:00

23 lines
928 B
YAML

# A hand-written node — see `clarity.yaml`, whose implementation this shares.
id: texture
order: 140
rust: Texture
why_rust: |
The same neighbourhood operation as clarity, at a tenth of the scale: one
implementation in `src/ops/local_contrast.rs`, parameterised by the band it
acts on. Two nodes rather than one node with two sliders because the radius
is the *definition* of each control rather than a setting of it, and because
a texture at zero must then cost nothing at all — which `is_active()` gives
for free and a merged node would have had to hand-write.
placement: |
Immediately after clarity, and for the same reasons: after noise reduction,
which must not be handed amplified grain, and before capture sharpening,
which belongs last.
After clarity specifically, so that the fine base is computed on the
modelling the coarse control has already settled rather than the other way
round.