A reviewer sent us a screenshot of two numbers that could not both be true.
The score said the text leaned one way. The explanation underneath listed the contributing features, and the percentages next to them added up to a different story: one feature was credited with more influence than the whole measurement had moved.
Nobody had typed a wrong number. The explanation layer had recomputed influence on its own. It read the same features, applied its own weighting, and produced a second opinion that happened to live in the same response as the first one. Two code paths, two answers, one UI.
That cost us a day of bisecting the wrong file. We kept reading the scale, because that is where measurement lives, and the scale was fine.
Here is what we do differently now in our open-source project proseprobe: the explanation layer is deliberately arithmetic-free. It is allowed to copy and to divide, and nothing else.
The headline is the score's own summary. The notes are the score's own notes. The features arrive in the order the scale put them, largest shift first, and every field travels through untouched: name, value, unit, description, the two means, the shift, the direction.
The only numbers the explainer forms are derived. Total movement is the sum of the absolute shifts. A feature's share is its shift over that total, and zero when the total is zero. Nothing is weighted twice.
Even the wording of magnitude is a lookup rather than a judgement. Four named bands (negligible, slight, moderate, strong) whose floors and ceilings tile the whole range up to infinity, and the first band the size fits under wins. No thresholds scattered across call sites.
Quoting is the part that surprised us. The explainer walks the evidence, collapses whitespace, takes the first non-empty quote and shortens it on a word boundary past the halfway mark. When there is no span, it does not reach for nearby prose to look complete. It says there is no excerpt. An empty quote is information, while a plausible wrong quote is a bug report six weeks later.
The general rule we took out of it: an explanation is a projection of a decision, not a second decision. The moment it can compute an opinion, it can disagree, and when it does, your users have to guess which half of your own output to trust.
So if you ship model or scoring output with reasons attached, it is probably worth tracing where those reasons get their numbers from: the decision itself, or a recalculation sitting next to it.