A floor measured on more than you can use
Our upsell engine waits for sixty baskets before it says anything. It was counting baskets it could not actually learn from — six of them were orders whose every dish had since been archived. Why the number in a refusal has to be the number the decision was made on.
If a kitchen has taken thirty orders, nothing useful can be said about what sells with what. Suggesting a side to go with a burrito on the strength of three baskets is not insight, it is a coin toss with a confident voice. So our upsell engine has a floor: below sixty paid baskets in the window it refuses to run at all, and writes down why.
Writing down why is the part most systems skip, and it is the part that caught this. The refusal is a sentence an operator can read — not enough trade yet to be worth asking: 32 baskets in the period, and it needs 60 — rather than a shrug. Which means the number in it is a claim.
Two numbers for one thing
We run two jobs over the same orders. A nightly one works out which dishes actually get bought together. A weekly one decides whether there is enough trade to be worth asking anything at all. Last week they disagreed: the weekly job recorded thirty-two baskets, the nightly one twenty-six, two days apart.
It could not be the calendar. The venue was newer than the window, so nothing could have aged out of the back of it, and it had no refunded orders. Both numbers reproduced when we ran them at the same moment. The gap was not time. It was that the two jobs meant different things by the word basket.
A basket you cannot learn from is not a basket
The nightly job counts a basket only if it still carries a dish you could actually suggest. That rule exists because a pairing is a prompt on a screen, and a prompt for a dish that is no longer on the menu can never be shown to anybody. The weekly job counted every paid order.
Six orders sat in the gap. All of them had lines, all of them named real dishes — and every one of those dishes had been archived when that kitchen rebuilt its menu. Real trade, honestly recorded, and completely useless as evidence about what to suggest tomorrow.
Why it matters in the direction it does
The floor exists to stop us spending money asking a question that cannot have an answer. Measuring it on the wider population makes the engine keener, not more cautious — it would have started asking earlier than the evidence justified. That is the one direction a cost gate must never err in.
Nothing was actually mis-decided: twenty-six and thirty-two are both a long way below sixty, so the answer was no either way. It is the kind of fault that only shows up in the gap between two honest numbers, and only if somebody goes and reads what the jobs actually wrote rather than what they were expected to write.
What an operator should take from it
When a system tells you it has not got enough data yet, ask what it is counting. Trade that has been superseded — the dishes you took off in spring, the menu you rebuilt — is still trade, and it is still in your sales figures, and it is not evidence about the menu you sell today. Those are different questions and a good tool should not answer one with the other.