# A rig your friend already owns — data kit

**What this directory holds.** The receipts behind the exhibit *A rig your friend
already owns* (research.strata2signal.com/a-rig-your-friend-already-owns/index.html):
two runs of a diffusion bench that re-rendered a board-game's own artwork — same
prompts, same seeds, same checkpoint files — on two pieces of ordinary consumer
hardware, and paired every single render against a 96G-class workstation card's own
archived render of the identical cell. **342 renders in all: 171 on each rig, of
which 165 were timed and 6 were untimed warm-ups. Zero failures on either rig.**

The two runs are dated at both ends, UTC:

| run | rig | opened | closed |
|---|---|---|---|
| `rematch-3090-0826` | the consumer desktop — RTX 3090 24G, single GPU | 2026-08-26T05:07:06Z | 2026-08-26T05:42:41Z |
| `rematch-rigB-0826` | the gaming laptop — RTX 5090 Laptop GPU 24G | 2026-08-26T06:24:59Z | 2026-08-26T06:56:58Z |

The baseline both are measured against is not a third run in this kit. It is an
**archive from 2026-08-23**, and it rides inside every row: each manifest row carries
its own `baseline_seconds` — the 96G-class card's recorded seconds for that exact cell
— so the speed ratio is a subtraction a reader can do by hand, never a number we
computed out of view. The desktop's baseline was measured **in the same physical
computer**, three days earlier, with only the graphics card changed between the dates.
The laptop is a different machine on its own cooling budget.

**Licence: CC BY 4.0.** Take these rows, re-plot them, check our arithmetic, publish
what you find. Attribution: strata→signal research, research.strata2signal.com. The
models rendered through are third-party weights under their own licences, enumerated
below. If you find an error in any of this, we want to hear about it:
hello@strata2signal.com.

## What is in here

| file | what it holds | what came out of it | bytes |
|---|---|---|---:|
| `rematch-3090-0826-manifest.json` | The consumer desktop's run: 171 rows, one per render. Each row carries the verbatim prompt, the seed, steps, sampler, scheduler, cfg, the bare checkpoint filename, width and height, the engine's own `render_seconds`, the paired `baseline_seconds` for the identical cell on the 96G-class card, the `baseline_id` it pairs to, the model's licence citation, the UTC instant, the arm, the axis, and the rig in its own `card` field. | the workstation card's model number → its memory class (one field name) | 363,653 |
| `rematch-rigB-0826-manifest.json` | The gaming laptop's run: the same 171 cells in the same order, the same schema, its own `card` field. Same 96G-class baselines in `baseline_seconds`, so the two rigs are comparable row for row. | the workstation card's model number → its memory class (one field name) | 362,970 |
| `rematch-3090-0826.log` | The desktop run's driver log as it printed, live: the seeded subject sample, the worklist, every warm-up announced, and every one of the 165 timed renders numbered `[n/165]` with its seconds and its ratio. It ends `REMATCH COMPLETE`. This is the artefact behind "zero failures" — a failure prints `!!` or `XX`, and neither string is in either file. | the workstation card's model number → its memory class (165 lines) | 28,370 |
| `rematch-rigB-0826.log` | The laptop run's driver log, same shape, same 165 numbered lines, same closing `REMATCH COMPLETE`. | the workstation card's model number → its memory class (165 lines) | 28,352 |
| `graph-flux2-klein-4b.json` | The ComfyUI API-format workflow graph for FLUX.2 klein-4B, as this bench submitted it. | not a copy — emitted here from the harness's own template | 3,531 |
| `graph-ctrl-z-image-turbo.json` | The same, for z-image-turbo. | not a copy — emitted here from the harness's own template | 3,237 |
| `graph-krea2-turbo.json` | The same, for krea2-turbo. | not a copy — emitted here from the harness's own template | 3,099 |
| `graph-hidream-o1-dev.json` | The same, for hidream-o1-dev. | not a copy — emitted here from the harness's own template | 3,391 |
| `graph-kandinsky5-lite.json` | The same, for kandinsky5-lite. | not a copy — emitted here from the harness's own template | 3,313 |
| `graph-z-image-base.json` | The same, for z-image-base. | not a copy — emitted here from the harness's own template | 3,252 |
| `provenance.json` | every file above with both sha256s, the named rule applied to it, and the graph templates' hashes at pack time | — | — |
| `index.json` | this directory, listed: file names, sizes, sha256s, and what each one answers | — | — |

**Graphs: 6 of 6.** Every model in the run has its graph here. None was reconstructed
by hand or inferred — each one is the harness's own template with its `_`-prefixed note
keys dropped (which is what the engine was handed) and its `{prompt}` / `{width}` /
`{height}` / `{seed}` tokens substituted by the same code path, in the same order, that
the run used.

## The images are not in this kit, and that is deliberate

342 renders is a heavy download for a page about how long they took. **The manifests and
the logs are the receipts here**: every row states its prompt, seed, size, step count and
seconds, and the two logs enumerate all 330 timed renders line by line. Each row's `file`
field still names the image the run wrote — `images/r3090__….jpg` — because that is the
filename the run recorded, and rewriting it would falsify the row. Those files are not in
this directory; the field is a name, not a link.

This matches the shape of the exhibit's sibling kits, none of which ship their image
sets either. Ask us if you want them.

## The counting rules — read these before the numbers

**The baseline.** Every multiplier on the page is against the 96G-class card's OWN
render of the identical cell — same arm, same prompt, same pixels, same seed, same steps
— archived 2026-08-23 and carried in each row's `baseline_seconds`. Six of those archived
cells carry cold-load pollution (the archived render that happened to pay a model's
weight-load time) and show up as absurd better-than-big-card ratios. **We kept them.** The
reporting rule, adopted after seeing the data and disclosed as exactly that — not a
pre-registration — is: *keep every cell, report per-model medians, never a hand-picked
render.* Medians damp the six almost entirely: dropping all of them would move every
model's baseline median by at most 0.005 s and no multiplier by 0.01.

**What a "second" is here.** The engine's own execution window — denoising, image decode
and file save. It is **not** model load: that is what the per-arm warm-ups absorb, and
they are excluded from every table by their unique seed (777333) and by `"axis":
"warmup"`. It is also not network transport, which a player pays on top.

**Rounding.** Every median is rounded half-up to two decimals. Every multiplier is then
the ratio of the two **printed** medians, rounded half-up the same way — so the table
reconciles for a reader with a calculator, rather than reconciling only against
unrounded intermediates they cannot see. One tie is worth naming because it is the only
place the rule visibly bites: the laptop's kandinsky5-lite median falls between 24.36 and
24.55, i.e. 24.455, and prints as **24.46**.

**Ratio of medians, not median of ratios.** The multipliers are ratio-of-medians. The
other statistic — the median of each row's own paired ratio — agrees everywhere within
0.20×. The largest gap in the run is krea2-turbo on the desktop: 4.88× ratio-of-medians
against 4.68× median-of-paired. Every other cell agrees within 0.09×. Both numbers are
computable from the rows in this directory; we print the first and disclose the second.

**Which cells a row belongs to.** `axis` is the honest denominator. A per-model headline
median is taken over ALL of that model's timed renders, mixed axes together. The
resolution-ladder figures are **res-ladder cells only** (n = 6 per cell). The two
questions have two different answers and both are correct: FLUX.2 klein-4B at 768 reads
**1.37 s** on the laptop as a res-ladder cell, and **1.39 s** as the model's
all-axes headline. Neither is a correction of the other.

**One model has thinner evidence.** z-image-base has no resolution ladder — all 12 of its
timed renders are 768×768, against 30 or 31 timed renders each for the other five models.
Its row is published with the same rules and that asterisk.

## The two runs, as this kit computes them

Recomputed from the files in THIS directory, under the rules above:

| model | 96G-class baseline | consumer desktop | gaming laptop | desktop ÷ baseline | laptop ÷ baseline |
|---|---:|---:|---:|---:|---:|
| FLUX.2 klein-4B | 0.48 s | 1.65 s | 1.39 s | 3.44× | 2.90× |
| z-image-turbo | 1.13 s | 4.44 s | 3.80 s | 3.93× | 3.36× |
| krea2-turbo | 1.97 s | 9.62 s | 5.86 s | 4.88× | 2.97× |
| hidream-o1-dev | 2.53 s | 7.34 s | 3.45 s | 2.90× | 1.36× |
| kandinsky5-lite | 6.17 s | 28.95 s | 24.46 s | 4.69× | 3.96× |
| z-image-base (undistilled) | 7.84 s | 33.01 s | 28.88 s | 4.21× | 3.68× |

FLUX.2 klein-4B by resolution — **res-ladder cells only**, steps = 4, n = 6 per cell:

| resolution | 96G-class baseline | consumer desktop | gaming laptop |
|---|---:|---:|---:|
| 512×512 | 0.26 s | 0.88 s | 0.71 s |
| 768×768 | 0.48 s | 1.65 s | 1.37 s |
| 1024×1024 | 0.82 s | 2.86 s | 2.40 s |

## The id-prefix wart — the `card` field is authoritative

**Both runs' render ids begin `r3090__`.** The harness stamped that prefix from the run
it was first written for, and the laptop run inherited it verbatim when it re-ran the
same worklist. It is a harness tag, **not a rig label**, and an id alone will tell you
nothing about which machine paid for the render.

Two more surfaces carry the same wart, for the same reason:

- every row of **both** manifests says `"file": "images/r3090__….jpg"`;
- the laptop log's per-render lines read `rematch-rigB-0826/r3090__…`, its run directory
  and the harness tag side by side in one string.

**The authority is each row's `card` field**, and it disagrees with the prefix on
purpose: `RTX 3090 24G, single GPU (consumer desktop)` in one manifest,
`RTX 5090 Laptop GPU 24G (gaming laptop)` in the other. Every row in a file carries the
same value, so the file you opened is never ambiguous. The filename is the second
authority — `rematch-3090-0826-*` is the desktop, `rematch-rigB-0826-*` is the laptop —
and `rigB` is simply what the second rig was called on the night; it names no host and
no place.

## The models, and the licences we read

Each manifest row carries a `model_licence` string with the citation and, where the
vendor ships a licence file we hashed, that file's sha256 prefix. Those strings are the
record; this table is their summary. **These are our readings, on the dates stated, not
legal advice** — every text carries terms beyond the one clause we quote here, and the
full texts are not reproduced in this kit.

| model | checkpoint file | licence | the copy we read |
|---|---|---|---|
| FLUX.2 klein-4B | `flux-2-klein-4b.safetensors` | Apache License 2.0 — commercial use permitted | vendor `LICENSE.md` opened 2026-08-23, sha256 `ca02bc51…` |
| z-image-turbo | `z_image_turbo_bf16.safetensors` | Apache-2.0 — commercial use permitted | vendor GitHub `LICENSE` opened 2026-08-23; **no file hash recorded in the row** |
| krea2-turbo | `krea2_turbo_fp8_scaled.safetensors` | Krea 2 Community License Agreement v.1 (2026-06-22) — commercial use of outputs permitted **only while company-wide trailing-twelve-month revenue is under US $1 M** | licence PDF read in full 2026-08-23, sha256 `b82a2805…` |
| hidream-o1-dev | `hidream_o1_image_dev_fp8_scaled.safetensors` | MIT — commercial use permitted | vendor GitHub `LICENSE` opened 2026-08-23, sha256 `05660a75…` |
| kandinsky5-lite | `kandinsky5lite_t2i.safetensors` | MIT — commercial use permitted | vendor GitHub `LICENSE` opened 2026-08-23, 1,099 bytes, sha256 `94946098…` |
| z-image-base | `z_image_bf16.safetensors` | Apache-2.0 — commercial use permitted | vendor GitHub `LICENSE` opened 2026-08-23; **no file hash recorded in the row** |

Two of the six rows carry no licence-file hash: both Z-Image entries cite the vendor's
GitHub `LICENSE` by URL and opening date, and note that the Hugging Face copy is
metadata-only. That is what the run recorded, and it is published as recorded rather
than back-filled.

Krea's clause is the one that can bite a reader who is not us: it is **company-wide**
revenue, not the product's. Read `model_licence` on any `krea2-turbo` row for the full
citation, including the clause numbers.

## Reproducing a render from the graphs

Each `graph-*.json` is a complete ComfyUI API-format graph — the thing the engine was
POSTed — at the settings of the standard 768×768 subject cell, which every model in the
run shares. To reproduce any other row:

1. Open the graph for that row's `arm`.
2. Replace the positive prompt text with the row's `prompt`, verbatim.
3. Replace the seed with the row's `seed`.
4. If the row is a ladder cell, set `width`, `height` and `steps` to the row's values.
   Everything else already matches.

Three properties of these files are deliberate and worth stating so they do not read as
sloppiness:

- **The prompt and seed in the file are a fixture.** They are the real values of one
  named published row — `_fixture.fixture_row_id` says which — standing in for whichever
  row you actually want. Substituting is the whole workflow.
- **`width`, `height` and `seed` appear as JSON strings, not numbers.** The harness
  substitutes into a quoted token and the engine coerces. Published as submitted rather
  than tidied, because tidying it would be publishing a graph nothing ran.
- **The `_fixture` key is a note, not a node.** Every `_`-prefixed key is dropped before
  submission — that is the harness's own rule, and it is why the templates' comment
  blocks are absent here. What remains is exactly the node set that ran.

Checkpoint files are named bare, as filenames. Where to obtain them is the licence table
above; nothing in these graphs points at a machine of ours.

## Sanitised at the pen, not copied

Nothing here is a raw copy. Each file was read, walked and rewritten, and the transform
has a NAME that `provenance.json` prints per file — so a reader can see which rule
touched a file and be sure nothing else did. One rule was needed:

- **`server-card-model-to-vram-class`** — the baseline card is a workstation part, and
  the house publishes it by memory class rather than by model, which the two consumer
  cards under test are not: they are the page's subject and are named. Two surfaces
  carried the model number and now carry the class. In the manifests it was a **field
  name**: `speed_ratio_vs_<card-model>` reads `speed_ratio_vs_baseline`, on all 171 rows
  of both files, **values untouched**. In the logs it was the per-render ratio
  annotation, which named the card by model and now reads `(3.12x vs 96G-class)`, on 165
  lines of each file. (This paragraph writes the old field name with the model elided,
  because the gate that keeps that card out of public text is not going to make an
  exception for a sentence explaining the gate.) Nothing else in either file was altered
  — the manifests were verified to round-trip
  byte-for-byte through the writer before the rename was applied, so the rename is
  provably the only difference.

Every timing, seed, prompt, step count, dimension, checkpoint name, licence citation,
UTC instant and count is published as recorded. The `card` and `baseline_card` fields
were already class-correct in the run's own records and were not touched.

The six graphs are not copies of a published original at all: they are emitted here from
the harness's templates by the same substitution the run used. `provenance.json` records
each template's sha256 at pack time; the templates themselves are not published in this
kit.

## Receipts

The ten data files as published (sha256 of the bytes in this directory):

    rematch-3090-0826-manifest.json  aa95171f9a14764d6a83f79f3611677b1f9e483f7f83fdf2425437f1d48316ca
    rematch-rigB-0826-manifest.json  dfb67b0e7a7bd45d764f3a062549b2768c20ef32976c3f09d7147e3746dfbb2d
    rematch-3090-0826.log            ef1013cd94d6bf3a65a7077d77d3ba92f3798c460dcdf5e19c00dd006581c2fc
    rematch-rigB-0826.log            86fad12c9038448de4077f553cd0e1a5c6e0406e61f588d0e300299a4f2f984a
    graph-flux2-klein-4b.json        a3509ba5d34f4d57a3ae117c9eae089e14fc4ea4c57b2cc2861d454ba8256a0a
    graph-ctrl-z-image-turbo.json    a5173248654f0489e6e67b6fdf3ed2e0b48b37bdcbb97a2c4b810bfaa47602c0
    graph-krea2-turbo.json           98502b344f87b804ee40265cbec6600a55357bbaa0b6f4cf37341190a51d3fdc
    graph-hidream-o1-dev.json        f7a7c2e85464a4bd3fae991bd5656a55a9fa8bb084f67d99c4416c6bbe1c90c9
    graph-kandinsky5-lite.json       0b7183f539f9eb7d078c9de15e50636e486928f41d1397ec242b7838d54351d2
    graph-z-image-base.json          4ae2dfb2238f00261c2b65c90026557356eab33a7fa182e3ff6616c48e0512a4

The graph templates the six graphs were emitted from, hashed at pack time (the templates
themselves are not published in this kit):

    diffusion-0823/wave1-klein4b-bf16        59184c1f85d8220761c0947c4460116d985285b364884128c34ad95cc3130b14
    diffusion-0823/ctrl-z-image-turbo        eb02ea8252d7bc633d2b5d1dfec848ac49ace13ddc67a90d8570630861630708
    diffusion-0823/wave1-krea2-turbo-fp8     1d99fe8bee0b0c4dcbc0c7b0e2772b09fb8ae8a6c826125db59c79b514c6a12f
    diffusion-0823/wave1-hidream-o1-dev-fp8  861f31267c3c51624b34143a91dc020a35a6bd27ea3db530109df48fef3aed22
    diffusion-0823/p2-kandinsky5-lite-bf16   a96799f2d1b5b2b60acdb7205cc6b1d37884cc7b0d2c896f87cbc8f1dc035f85
    diffusion-0823/wave1-zimage-base-bf16    6d90bb6ad3a1b4da96043b492d575579556a7d13dfe5b56b2de6c6cdc95da7e4

`index.json` lists every file in this directory, including this README and
`provenance.json`, with its size and sha256 re-read off disk. `index.html` is the same
listing, browsable.
