Step 3: Run it

    This ordering is the whole efficiency argument. “Peanut satay skewers” contains the word peanut, and satay. No model needs to be consulted about that. On a real catalog the rules routinely settle most of it, and your model bill is for the remainder.

    For what is left, the model is asked one record at a time, constrained to your allowed values, and told plainly that abstaining beats guessing. Here is how our four rows come out:

    What the run decides, row by row
    Tomato soup           dairy       rule    "cream" → dairy
    Peanut satay skewers  peanut      rule    "peanut" → peanut, "satay" → peanut
    Garden salad          (none)      model   confidence 0.91, nothing indicates an allergen
    Chef's tart           —           abstain the record does not say what is in it

    Three settled, one refused. The tart is not a failure: the model was asked what is in a dish whose description is “Ask your server”, and correctly declined to invent an answer. It gets a receipt too — receipts are written for refusals, not just for stored values, and that is the half people find most useful later.

    The receipt behind one stored value
    {
      "method": "rule",
      "confidence": 1,
      "contract_version": 3,
      "decided_by": null
    }

    The method on a receipt is one of rule, model, rule+model, unchanged, abstain, low_confidence, ratchet_blocked or human. The last four are the interesting ones: they are the run telling you, in writing, why it did not store something.