Salsedine, own product, invite-only alpha
Snap a receipt. See where it goes.
Every answer about your spending is on a receipt. Four seconds later it is in the bin. What you bought, what you paid, which shop, which day, down to the brand and the weight. A household throws that away several times a week and then has no way to tell whether it is paying too much for anything.
Saveri reads it first, and compares it against what the same basket costs elsewhere this week. Underneath all of it sits one design problem: what a system does when it is not sure.
The decision the product rests on
The model's opinion of itself is not evidence.
Every extraction model will tell you how confident it is. That number is cheap, and it is highest exactly where you should worry, because a model that has misread a line is not aware that it has.
So Saveri asks the model for a score on a handful of header fields and never asks it for one per line item. Line-level trust is derived instead, from arithmetic the receipt itself has to satisfy: items plus discounts equal the total, the VAT blocks reconcile, the per-rate sums agree.
Tolerance is two cents. Past that, confidence decays to zero over the next eight. A receipt where every field reads confidently but the sum is out by three euro and forty still fails, and still routes to review. The maths does not have an opinion.
When the answer is genuinely not there
Three real intents, not OK and Cancel.
The Portuguese fiscal reference is the weakest field on a thermal receipt, and when it comes back below the threshold there is no clever recovery. The system has to ask. The design question is what it asks for.
A modal with OK and Cancel assumes the person wants to solve it now. Most do not. They are standing in a car park with a bag of shopping. So the fallback offers the three things a person actually wants at that moment, and none of them block the save.
- Type it now if they have thirty seconds.
- Batch it later, which flags the receipt and puts it in a work queue they can clear at the kitchen table.
- Skip it, stated plainly: the reference will be cleared permanently.
The disclosure pill above it is not decoration either. Under the EU AI Act a person has to be told when they are looking at model output. It sits on the review screen because that is the moment it is true.
Where the improvement comes from
It asks once. Then it remembers.
Retailers do not print product names, they print abbreviations, and every
chain abbreviates differently. IOG NAT MG 4X125
is a four pack of yoghurt in one shop and something else entirely in another.
A correction is therefore stored against the retailer and the raw string, not against that receipt. The next time the string appears it resolves silently. What makes it interesting is who a correction is allowed to speak for, and that is three tiers enforced in the database rather than the client:
- Operator corrections apply to everybody's extraction for that retailer and field.
- Promoted is a user correction a classifier judged to be a genuine typo fix, treated as operator tier.
- User never leaves that person's account.
And the ordering matters more than the tiers. Your own correction outranks an operator's. If somebody has deliberately renamed something for their own reasons, the global default does not get to overrule them. Operator bias is a default, never a veto.
The number it would have been easy to lie about
Two of these are facts. One is an estimate, and it says so.
Spending is arithmetic once a receipt is line items, and on its own it is a guilt machine with a chart on it. Saved is the number that justifies the product, which is exactly why it is the one worth being careful with.
So it is split into tiers with different standing. The discount printed on your receipt is exact, taken straight off the paper. Loyalty card savings are exact too. The comparison against this week's flyer prices is an estimate, visually subordinated, and floored at zero: if you paid above the average it counts as nothing rather than going negative, and products with no price history are left out entirely.
There is a page in the product whose only job is to explain that split. Its source carries an instruction to whoever maintains it: update this whenever the pipeline changes, so the page never claims something the system does not do.
Where the estimate comes from
Every chain publishes its prices. Nobody reads them.
Portuguese and Italian supermarkets put out a folheto or a volantino every week: hundreds of prices, public, and completely unusable by a person who would have to cross-reference it against their own shopping by hand.
Eight chains are fetched automatically before anyone is awake, and the same extraction runs over them as over a receipt. The two halves meet on the product, not on the printed words, through the aliases the correction memory already learned.
Which is the point of the whole architecture. The memory built to stop asking you about a yoghurt is the same mechanism that lets a flyer be compared to your basket.
The screen nobody sees
The least designed page in the product, and the most valuable.
Flyers are far messier than receipts. A chain redesigns its layout without warning, a promotion is printed as a picture, and the failure is silent: it does not error, it produces confident nonsense.
So there is a review queue sorted worst-confidence-first, and it is deliberately plain. Its job is throughput. Accept, fix, reject, next.
What happens to those fixes is the interesting part. Each one is stored with the piece of source text it came from, then classified deterministically by what kind of mistake it was, and the recurring ones are distilled into a rules block that is prepended to the prompt for that retailer and that specific layout. Not a retraining cycle. A product that writes its own briefing notes.
The distillation is also sanitised before it is stored, stripping anything arithmetic, so the loop can never teach itself to invent a price.
Layout-specific rules for continente:magazine, synthesised from 47
corrections on this exact layout. Do not back-compute a shelf price from a percentage badge.
The decision the studio rests on
A receipt says what came in. Subtract what was used, and you have a pantry.
That step is small in the code and large in the product. The moment line items became stock rather than history, the same structure started answering three different questions in three different businesses. Saveri stopped being a receipt app the day the despensa existed.
What shipped
Not a scanner. The layer the other two products stand on.
Invite-only alpha, running against real receipts in two countries, with the extraction quality measured against a labelled corpus rather than asserted. Routina reads its pantry through an API rather than duplicating the data, and the same stock model is what ParrotB uses for business inventory. Three products, two markets, one set of line items.