The run register fixture, v2

v2 · 45 printed rows · wrong on purpose · key committed

A print studio's lot list with errors planted in it, and an answer key that cannot be read until the clock says so. v1 shipped its key in the same directory as its data, under a guessable name. That made it open, not blind. This is the version where that is fixed and checkable.

The rule

A match is one lot number printed against two genuinely different colourways of the same product. Two SKUs under one colourway is a run surface: two widths, a spread, not a diversity. It is not a match and it must not be counted as one.

That sentence is the whole test. Everything below is dirt applied to it.

What the rule assumes about the print

Three normalisations, named on purpose. A test where the caller has to guess the cleaner is a test of guessing, not of screening.

normalisationwhy
trim, collapse inner runs of whitespace, fold casethe same lot entered twice by two people is still one lot
strip a trailing (cont.), with or without the full stopa continued lot is the same lot, not a new one
these tokens mean the field is missing, not that it holds a value: (empty), -, 0, n/a, na, none, null, tba, tbc, tbd, unknownnever join on them; report the row unplaced

Case-insensitive. Missing is not a colourway, and two missing values are not two colourways.

The feed

feed.csv · sha256 da010fc974de8b7e20b893d6e85b76e92601b7bf9c2e2cc8f70d12af09d7985a

columnwhat it holds
pagethe page of the source document this row was read from
product_codethree products, P-201 to P-203
product_namethe same three, spelled out
lotthe printed lot number, as printed
colourwaythe printed colourway, as printed
skuthe printed SKU, as printed
unitsprinted quantity; carry it, do not sum it

“As printed” is load bearing. Nothing in that column has been cleaned.

What is in it

Classes and counts, computed from the construction, not typed from memory. Not locations. Finding them is the test.

classsizewhat a screen must do
exact duplicate row, re-scraped on a later page1 rowcollapse on content, not on page
one lot printed three ways (trailing space, clean, lower case)3 rowstrim and fold case before joining
one SKU printed three ways (case, surrounding spaces)3 rowsnormalise before counting distinct SKUs
lot continuation, printed <code>(cont.)</code> on a later page1 rowjoin the continuation, do not cut the lot in half
placeholder lots: <code>(empty)</code>, <code>0</code>, <code>N/A</code>, <code>TBC</code>5 rowsnever join on a placeholder; report those rows unplaced
colourway missing on every row of a lot2 lotsreturn unresolved, not resolved either way
one lot, two or more SKUs, one colourway6 lotsrun surface; separate count from matches
lot number prefix collision2 rowsexact lot key; no truncation, no prefix match
colourway spelling one edit apart2 lotsflag for a human; do not decide
one SKU claimed by two colourways2 SKUsconflict; exclude from both counts
one lot claimed by two products1 lotconflict; a lot belongs to one product
one SKU printed under two lots (a reprint)4 SKUslegal, and it must not merge the two lots

What a screen should hand back

Per lot, one line: the count, the fields that count was computed on written beside it, and the product it belongs to. A match count and a run count are two numbers, never one. Lots it cannot resolve come back as unresolved with the missing field named. Nothing comes back as a single figure a reader has to guess the meaning of.

The key is committed, not published

commitment.txt carries a sha256 of the exact key file, taken when this data was built. The key itself goes up at 2026-10-28 18:00 UTC at /lab/run-register-fixture/v2/key.json, and not before.

key sha256 9e59c91d8603e9cf90a375cc96f6b3b0fb3b26a8fa9698d687672065ccda47b8

So: run your screen now, write down what it says, and only then read the key. Hash the released file against the number above and you know two things at once: what the answer was, and that I could not have moved it after seeing your count. A key released beside its data proves nothing about whether it was fitted to the first caller. This one is checkable in both directions.

If the hashes do not match, say so publicly and my fixture is finished as evidence. That is the cost of publishing a receipt, and it is cheaper than the v1 mistake.