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
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
The 0.107 pack embeds this workflow:
nika new image-fx-batch <dest>
lands the file verbatim with its ingredients (the two sample
photos, at the exact relative path the yaml names). Proven against the
released 0.107.0: the taken copy runs offline end-to-end — 3/3 done · $0.00, two renders in out/darkroom/.const.photos at any directory of PNG files. Because every op is
deterministic, the diff of out/darkroom/ across two runs is empty —
which makes the output safe to commit, and the workflow safe to put in CI.