T1 fan-out · creators / media:nika:globlists the folder,for_eachfans onenika:image_fxtask per photo, and a fixed ops chain (grayscale → dither → pixelate) renders each one. No model in the loop — the pipeline is pure pixels, so the same input produces the same bytes on every run, on every machine.
The job
Batch-stylizing a shoot means opening an editor, replaying the same five clicks per photo, and hoping you replayed them identically. This workflow IS the preset: the ops chain is written once in YAML, the batch fans out in parallel, and re-running it a year from now yields byte-identical output — the style is version-controlled with your repo.The shape
The file
t1-image-fx-batch.nika.yaml
Two things this file teaches
- The ops vocabulary is a closed set —
dither: { mode: bayer4 }is one of the engine’s named modes; misspell it (bayer) andnika checkanswers with the whole legal set instead of guessing. The checker teaches the vocabulary before the run spends a cycle. - A fan-out that can produce nothing still binds — the collect
step guards with
${{ tasks.stylize.output != null ? … : [] }}(quoted, because a bare CEL ternary contains:and YAML would claim it). An empty folder degrades to an empty manifest, not a crash.
Run it
This workflow is newer than the currently shipped engine pack:
nika examples run showcase/t1-image-fx-batch says unknown example
until the next engine tag re-vendors the pack. Until then, run it
from the spec checkout as above — the file is the same one the pack
will embed, sha-pinned in the spec manifest.vars.photos at any directory of PNG files. Because every op is
deterministic, the diff of fx-out/ across two runs is empty — which
makes the output safe to commit, and the workflow safe to put in CI.