v0.34.0 - X-Trans colour, hardened budgets, typed scopes
Autoshop v0.34.0 — the R28 round: X-Trans colour, hardened budgets, typed scopes
Five batches, all landed 2026-08-20. No recipe-schema changes: a v0.33.0
binary reads a v0.34.0 recipe and vice versa — the first feature release
since v0.30 with no forward break.
The headline: Fujifilm X-Trans renders correct colour
Through v0.33.0, X-Trans RAFs developed visibly green and dark. The root cause
was starker than a detail approximation: the Bayer demosaic's chroma pass
assumes the right/down neighbours of a green photosite carry the two chroma
colours, and inside X-Trans's four 2×2 all-green blocks per tile that
assumption fails 16 times per 36 pixels — R was never written (left at zero)
at 8 of every 36 photosites, B at another 8. No white balance can repair a
per-channel hole.
v0.34.0 demosaics non-Bayer RGB arrays in-tree over the array's own geometry:
every channel is interpolated only from photosites that actually measured it,
with per-phase plane-fit weights (convex, no ringing). Measured on the release
binary against the CC0 X-S10 zoo sample: whole-frame G/R 1.5503 → 0.9473
(the camera's own preview reads 0.95), per-phase channel spread R 157.8 % →
0.34 %. All eight Bayer-format zoo renders hash byte-identical before and
after. Fine detail remains softer than a dedicated X-Trans converter and the
render's disclosure line says so — the old line's "colour, tone and framing
are unaffected" clause was measured false and is gone.
Behaviour changes (all deliberate, all disclosed)
- Negative Texture is band-limited.
texture = −100used to degenerate to
a full Gaussian blur (the transfer's endpoint was literally the blurred
frame). It is now a mid-band smoothing: at −100 a 4 px pattern keeps 96 % of
its contrast while a 16 px pattern still loses 71 %. The positive branch is
untouched (it was measured against Lightroom in R27). The negative curve is
ours and stated as unmeasured — there is no LR ground truth for it in the
tree, and the sidecar still carries the raw slider value. - A RAW too big to develop is refused by name. The RAW door gains the same
4 GiB per-file peak ceiling the baked door has had for months, charged on a
header read before any sensor row is decompressed. At the measured
31 bytes/pixel that is ~138.5 MP and up (a 150 MP back is caught; a 102 MP
GFX is well clear). The message names the estimate, its basis, and says
outright that--jobs 1will not help. Such files used to be attempted and
would page the machine. - AI-mask alphas re-derive once. The segmentation cache key now records
the frame (quarter turns) it was computed in — closing a bug where a mask
clicked exactly at the frame centre kept serving its pre-rotation alpha
sideways. Every alpha cached by v0.33.0 re-runs the local segmenter on its
first develop (seconds of GPU per mask), reported as a normal re-derivation. - AI masks on a saved retouch master now render. The resolver takes the
photo for identity and the render source for pixels; a baked master used to
fail the RAW-only staging decoder and the mask was carried inert. - The eval hue rows changed meaning. The four
color_grade.*_huerows
count a photo only when BOTH sides put saturation on that wheel — a hue at
zero saturation renders nothing, and the old rule manufactured a 141°
"disagreement" between two colourless wheels. The report discloses that
these rows are not comparable with pre-v0.34.0 runs. - The style-embedding sidecar loads in half precision by default and is
single-flighted (one resident model regardless of worker count):
4 × 1.50 GB of fp32 SigLIP weights becomes 1 × 0.75 GB.
AUTOSHOP_EMBED_FP32=1restores the old arithmetic exactly. - Batch transcripts are attributable. Worker-reachable warnings carry
their photo's stem, andbatchrenders the proposer's note channel into
each photo's own output block the wayevalalways did.
Hardening (defect classes closed, each with a gate that keeps it closed)
- Every store-file read goes through the capped readers (four bypasses closed;
a source-scanning test now fails on any new bare read). - Brush-dab truncation cuts on token boundaries and is disclosed on every
surface; one dab token is bounded at 256 bytes; the import-side clamp
summary is no longer discarded. - XMP read scope is a type (
TagvsScope): a per-element read can no
longer silently become a subtree search. Four adversarial scope fixtures pin
the difference; the 16 real-Lightroom sidecars byte-round-trip unchanged,
which is the proof the redesign moved no real-LR behaviour. - The docs gate lexers handle block comments, cross-check literal counts
against[&str; N], and mask quoted spans in the TOML census. - The
--jobsplanner consults per-file peaks where headers are free (a
native-resolution 16-bit TIFF from LR's "Edit in…" can exceed the corpus
constant on its own, and now says so); the 1,800 MB constant was re-measured
with the full-resolution render included (peak 1,771 MB — the render tail
does not raise it) and the probe harness is now in-tree and re-runnable.
Gates at release (both build configurations)
clippy clean ×2 · 727 library (9 #[ignore]d forensic probes) / 11
CLI / 131 GUI / 2+2 contract · RAW zoo 9/9 (full test name) · 16/16 real
Lightroom radial sidecars byte-round-tripped · M-B forensic corpus 42/42 masks
· i18n audit 0 · doc-drift gate 11/11 with the release battery transcript.
The format-strip .raf tile in the README was re-rendered with this release.
Also in this release
Cross-platform compilation is CI-verified on ubuntu-latest and
macos-latest in both feature configurations on every push to main (compile
only — no tests run in CI, and no binary has been executed on either
platform). Prebuilt binaries remain Windows-only.