Measured Behaviour
Published
A lifetime trace is only as good as the identifier it is keyed on. Most animals carry two real numbers - one unique across a country, one unique across a shed - and both retrieve a genuine animal. We measured what happens when the software stops being able to tell you which one it used.
Two true numbers, one of which is unique
An official ear tag is unique nationally by construction: a country prefix, the herd mark of the holding of birth, and a serial. A management number is the number the farmer paints on the animal, and it is unique across one shed - because it starts at one on every farm in the country.
Both numbers are on the record. Both are true. A trace keyed on either will return an animal that really exists and really has the history printed against it. Only one of them returns THE animal.
We built a register of five animals on three holdings. Two of them are cows born five years apart on farms two hundred miles apart, and both wear management number 40122, because both farmers number their heifers from one. Their official tags differ in the herd mark, which is exactly the part a management number does not have. Five movements follow, each carrying the official tag, because that is what a movement document is printed with.
The correct run resolves all five movements, each to the animal that made it, with nothing ambiguous and nothing unresolved. The companion measurement, where a restriction stops being about a place at all, is in the standstill article.
A successful lookup against the wrong animal
We renamed the option that says which identifier to match on. The library fell back to its default, which is the management number - a defensible default, because that is the number a stockman can read across a yard and it is what on-farm software has keyed on for decades. It stops being unambiguous the moment two holdings are in the same database.
On both member-renaming presets the counters agree. Movements stayed at 5. Resolved stayed at 5. Unresolved stayed at 0. Ambiguous went from 0 to 2, and misattributed - movements filed against an animal that is not the animal that moved, measured against the paper passports held outside the bundle - went from 0 to 1.
Read the resolved count again. It did not fall. A trace keyed on a less specific identifier does not fail more often; it succeeds more often, because more things match. The abattoir's own trace check passed: it asserts that every movement resolved or was reported unresolved and that the counts reconcile, and both held.
The one movement that went wrong is the heifer off the second farm. Her movement document carries her own official tag; the derivation of a management number from it lands on 40122; the index under 40122 holds two animals; the library takes the first, which is a five-year-old cow on a different farm. A whole life history came back. All of it belongs to somebody else's animal.
The negative control failed, and the failure was the result
We build a negative control for every area we measure, and the first one we wrote for this area failed - loudly, and for a reason we had not anticipated.
The idea was simple: make every management number unique and the arm should go inert. We did it by prefixing each management number with the herd mark. The arm did not go inert. It went to five unresolved movements out of five, because prefixing also destroyed the library's derivation of a management number from a movement document.
That is worth more than the control we were trying to build. When the fallback identifier cannot be derived at all, the failure is loud: nothing resolves, somebody notices within an hour. The dangerous case is precisely the one where it CAN be derived and collides, because then everything resolves and the count is clean. A defect that breaks a lookup completely is a good day. The bad day is the one where the lookup works.
The corrected control - the same animals with one serial changed so that no two management numbers collide - is inert on every counter, and it is the register almost anybody would write by hand. Nobody writes the same number twice on purpose.
What a recall actually needs
The reason this matters more than a mis-keyed row is what a trace is for. When something is found in the food chain, the trace decides which animals came off which holdings and therefore which holdings go under restriction and which product is withdrawn. A misattributed movement does not produce a gap in that answer. It produces a complete answer that names the wrong farm.
One movement in five is a rate. Across a national database of fourteen million movements a year, that scale of collision is not a rounding difference, and it is concentrated exactly where collisions are most likely - common serials, large holdings, animals numbered from one.
Renaming the record field carrying the official tag, by contrast, fails loudly: every animal is rejected by the format check and nothing resolves at all. Same control, two names, and the option is the quiet one. The same option-versus-record split appears in the herd-testing article.
What to do about it
First the reassurance. We protected this bundle on five profiles - the ES5 target, the modern target, both emit-gate configurations and the string-encoding profile - and all five produced behaviour identical to the unprotected original, measured twice and diffed. Obfuscation does not break a trace. A member-renaming pattern that reaches the option naming your join key does.
Scope member renaming to names you own on both sides of every boundary. An option key handed to an installed library is the clearest case of a name you do not own on both sides, and it is the one that moved this result. The member renaming options carry the regexp that scopes it.
Then make ambiguity fatal rather than resolvable. Our library counted two candidates and took the first, which is what most index lookups do. A trace that refuses to answer when more than one animal matches turns this entire failure into a loud one, and the cost of that refusal is a support call rather than a recall against the wrong farm.
Finally, measure attribution, not resolution. Resolved, unresolved and traced all reconciled in every arm here. The only figure that moved was the count of movements filed against an animal that did not make them - and that figure needs a source of truth your software did not compute, which in this industry is a piece of paper that travelled with the animal.
Frequently asked questions
Does JavaScript obfuscation break livestock traceability?
Not by itself. We protected the same traceability bundle on five profiles - the ES5 target, the modern target, both emit-gate configurations and the string-encoding profile - and all five produced behaviour identical to the unprotected original, measured twice and diffed. The failure needs member renaming pointed at the option that names the join key.
What happened when the match-on option was renamed?
The library fell back to its default and matched on the management number instead of the official ear tag. Resolved stayed at 5 of 5 and unresolved stayed at 0, but ambiguous went from 0 to 2 and one movement in five was filed against an animal that did not make it.
Did the trace fail or report an error?
Neither. It succeeded more often, not less - a less specific identifier matches more things. The abattoir's own trace check passed, because it asserts that movements resolved or were reported unresolved and that the counts reconcile, and they did.
Why does a wrong trace matter more than a missing one?
Because a missing trace is investigated and a wrong one is acted on. A trace decides which holdings go under restriction and which product is withdrawn. A misattributed movement does not leave a gap in that answer; it produces a complete answer naming the wrong farm.
Your negative control failed. Is the measurement still valid?
The first one failed and the failure is reported in the article because it is informative. Making management numbers unique by prefixing them also destroyed the library's derivation of a management number from a movement document, so the arm went to five unresolved out of five instead of going inert. The corrected control - one serial changed so no two numbers collide - is inert on every counter.
Is renaming the official tag field the same failure?
No, it is the opposite. With the official tag field renamed every animal fails the format check, nothing resolves at all, and somebody notices immediately. The option key is the quiet name; the record field is the loud one.
What should we change in software like this?
Scope member renaming so it never reaches an option object you hand to a library. Make an ambiguous match fatal rather than first-wins - the cost is a support call instead of a recall against the wrong farm. And measure attribution against a source of truth your software did not compute, because resolution counts reconcile in every arm.
Related reading