Flow
Where each row goes
A count decides, not a score.
1Row is missing a hash
Needs more evidence. Nothing is compared.
2Exactly one equal item
Proposed, then waits for my approval.
3Two or more equal items
A tie. I decide.
4Only name and family match
A near match. I decide.
5Nothing close
No match. Get more evidence.
Somebody had to be the matching step, and it was me. The ordering system won't use a supplier's sales history until it knows which catalog item each planned row is. Until then, that row is stuck. So I matched rows by hand in chat. The system showed me rows and candidates as hashes, and I said which went with which. That works for a few rows. It does not work for every supplier the stores buy from.
So I wrote a classifier to do it. Most of my effort went into what it is not allowed to decide. The hand path stayed as the backup.
Equal on all five, or it goes to me
Each row and each catalog item gets five hashes: name, supplier family, category, size and cost. A hash is a short code made from the value. The classifier compares codes and never sees the real names or prices.
Each row goes one of four ways. Missing one of its own hashes? It needs more evidence, and nothing is compared. Exactly one item equal on all five? Accepted. Two items equal, or a near match that shares only name and family? I review it. Nothing close? No match.
If you build one of these, make the rule a count, not a score.
Only a single exact candidate gets proposed.
Two identical items do not make a match more likely. They make it a guess, so a person decides.
With no score, there's nothing to tune. The cost is that real matches get missed. Cost is one of the five, so a price change sends an easy row to review. I'm fine with that. A wrong match puts sales on the wrong product, and nobody notices. A missed match just lands in my review pile.
If the input can't show that raw values were kept out, the classifier stops and returns nothing.
A proposal, then my yes, then nothing saved
An accepted row is only a proposal. The next step checks the classifier's report again instead of trusting it. Then it needs my approval. Then every proposal has to point at a row that is really stuck. If even one doesn't, the whole batch stops. I'd rather know my inputs disagree than have half a batch go through.
The repair runs in memory. Nothing gets saved.
The live run was the easy case
On the real run, every row had one clean match. I approved the batch, and the "unknown product" block cleared for a few dozen product-and-store pairs.
The total number of stuck pairs didn't change. The same pairs were now stuck on missing stock counts. The ready count didn't change either. A product is ready only when it has every piece. A separate change that day, in another part of the pipeline, showed a reviewed cost-and-case rule is one of them. Expect your numbers to shift between columns before they drop.
A veto that has only fired in a test
Nobody measured how accurate it is. The rule that sends ties to me has only fired in one test. Near matches and missing hashes have no test yet, and I want both before a messier supplier shows up.