Record

Where every rule came from, including the ones we could not establish.

A specification with no account of its own evidence is a list of assertions. This is the account — what we read, what we measured, what we broke on purpose, and what we went looking for and did not find.

Four sources, ranked

Every rule carries the strongest evidence we actually have for it, and the tag is not decoration — it is enforced in code.

Documentation · 15 rules
Stated by the platform’s own documentation. The strongest source available without touching a store — and, twice, wrong in ways only a store revealed.
The corpus · 0 rules
Observed in a real supplier export, with counts. 21 files, 19,885 rows, 5 to 614 columns, 6 source platforms.
Probe · 4 rules
Measured against a real store through its API, recorded verbatim. Genuine observation — and not the same thing as running a file through the importer, because they are not the same code path.
Third-party assertion · 1 rules
Claimed by someone other than the platform, and not found in the platform’s own docs. Treated as unconfirmed, and capped accordingly.

A measurement may lower a severity. It may never raise it.

This is the rule that governs everything above, and it is an asymmetry rather than a doubt about the measurement.

If a platform’s API rejects something, its importer might still accept it — a file never reaches the layer the API speaks to. So an observed rejection is not grounds for telling you your import will fail. If the API accepts something we had flagged, we have caught ourselves crying wolf, and one false alarm costs the whole report its credibility.

So measurement is always enough to stop us shouting, and never enough to start. The cap is applied in one place in the engine rather than left to whoever writes the next rule, and right now it changes nothing: all 20 rules rest on evidence strong enough for the severity they carry. That is worth stating plainly rather than quietly, because it has not always been true and may not stay true — the mechanism exists precisely so that a rule added on a weaker footing is capped automatically instead of being argued about.

The only thing that promotes a rule back is a real file through a real importer. That is what closed the Shopify gate, and it is what the WooCommerce writer is waiting on.

What breaking a store on purpose taught us

  • A file we wrote passed our own validator and the real importer refused it. That is a false negative — the only defect this product genuinely cannot afford — and only a real import surfaced it.
  • Two products whose handles collide become one product, silently, under a banner reporting success.
  • A single deficient row does not get truncated. Its whole product is dropped, and the run still reports success.
  • The import preview counts the rows it is about to discard. We saw it promise five products while three were about to vanish.

14 pages at /fix are written from 15 recorded observations like these.

The corpus, and why synthetic tests were not enough

4 defects it caught

That 140 hand-written tests did not. 2 of them would have corrupted a catalogue while reporting nothing at all.

Written by nobody who knew our rules

A fixture written by the same person who wrote the rule tests the rule against itself. Real supplier exports do not cooperate — including one workbook that crashes the reader, which is reported as a file we could not read.

19,885 rows, 0 contract failures

The whole corpus, end to end, on the acceptance run of 2026-09-05. Every model response is checked against the shape it promised; anything that fails is abstained from rather than parsed optimistically.

The searches that returned nothing

Looking for open catalogue data to widen the corpus, we swept 546 sources, inspected 250 files, and found 0 we could use. The well was wrong, not the filter.

We publish that for the same reason we publish an unbuilt pipeline stage: a method that only reports its successes is not a method. It is also, practically, the least copyable thing on this site. Anyone can restate our rules in an afternoon. Nobody can restate a search they did not run.

The gap it leaves is real and we would rather name it: the corpus is public supplier and store exports. Nobody sent these files to a merchant. The category still missing is the one we exist to serve — the file a supplier emails monthly, hand-edited by somebody in a hurry, in a different shape each time.

The most valuable file we do not have is a genuinely ambiguous variant grouping, and it is the one we cannot honestly manufacture, because inventing the case means inventing its answer. That is why that stage is not built.

Check the method against your own file.

Everything described here runs on the free report. If it finds nothing, that is a result too, and it will say which rules could not run.

Check a file free