Skip to content

Do the related cases support this action? (support)

Your model flags a card payment as clean, but the card belongs to an account inside a ring of sixteen accounts sharing eight phones, and thirteen of those accounts were confirmed as fraud. The related cases are strong evidence, and they say "fraud". Passing the payment automatically because the evidence is strong would be a mistake: it is strong evidence against the action. This check holds a decision when the related cases do not point the same way as the proposed action.

This page is for domain owners who decide when the related cases should overrule the model, and for data scientists who build the evidence. It assumes you know that each decision comes with evidence about the related cases (see The six checks). The name of this check in decision records is support.

The question

Of the related cases, what share carry the outcome this action implies, and is that share at least one half?

The other evidence checks ask whether the related cases are worth listening to: neighbour agreement asks whether linked cases agree with each other, the knife-edge check asks whether the link density is too close to your cut-off, and the unusual-cases check asks whether the score looks familiar. None of them asks which outcome the related cases point to. This check does.

The intuition: count the votes for this action

Every proposed action implies an outcome for the related cases. In fraud review, block implies "confirmed fraud" and pass implies "cleared". You tell the library which label the proposed action implies; it counts the related cases carrying that label.

Dense ring, 16 accounts:  F F F F F F F F F F F F F C C C   (F = confirmed fraud, C = cleared)

proposed block  -> needs F -> 13 of 16 = 0.81  -> at least 0.50, pass
proposed pass   -> needs C ->  3 of 16 = 0.19  -> below 0.50, hold

The same evidence passes one action and holds the other. That is the point: the check is about direction, not strength.

Worked example

uv run grounded-decision examples fraud_review

Three card authorisations. The first and third carry the same dense ring of 16 accounts, 13 of them confirmed fraud. The second is linked to four accounts through a chain of shared laptops, two of them confirmed fraud.

Row Event Proposed action Implied label Support share Support check Verdict
0 suspicious block confirmed fraud 13/16 = 0.8125 pass act block
1 suspicious block confirmed fraud 2/4 = 0.5 pass hold (neighbour agreement and knife-edge fail)
2 clean pass cleared 3/16 = 0.1875 fail hold

Row 2 is the case from the opening. Every other check passes; only this one fails:

tick 2/3  event=clean
  why    $12 grocery purchase on a card in the same ring - the model says clean, the related accounts say fraud: held for review
  ...
                   support    share=0.1875  vs min=0.50  does not support the proposed action
  ...
  DECISION
         hold — failed: support
         certificate      PASS  can we compile this policy (star-height ≤ 3)?
         game             PASS  can the policy keep making progress (parity win, nonnegative mean)?
         reconstruction   PASS  do noisy neighbors recover the seed (dλ² > 1+margin)?
         threshold        PASS  is density outside the operational flicker window?
         conformal        PASS  is this candidate weirder than the calibration bag?
         support          FAIL  do the related cases support the proposed action?
                            support 0.19 vs minimum 0.50 (does not support the proposed action)
         → ABSTAIN  because conjunction failed on support; proposed 'pass' is blocked; naive would have fired 'block-or-pass'

The proposal pass stays on the record, so a reviewer sees that the model said clean and the related accounts said fraud.

Row 1 shows the boundary: a share of exactly 0.5 passes, because the rule is "at least the minimum". That row is held anyway, by the checks that judge whether four accounts are enough to say anything.

The example measures support by passing the implied label when it builds the evidence:

from grounded_decision.examples.fraud_review import (
    SUPPORTING_LABEL,  # {"block": CONFIRMED_FRAUD, "pass": CLEARED}
    device_graph_evidence,
)

evidence = device_graph_evidence(
    device_logins,
    last_review_outcome,
    candidate_model_score=model_score_for_this_auth,
    supporting_label=SUPPORTING_LABEL[proposed_action],
)

device_graph_evidence calls snapshot_from_graph(..., supporting_label=...), which sets EvidenceSnapshot.support. If you build the evidence yourself, set support directly.

The exact rule

With \(\ell\) = the label the proposed action implies, \(\ell_v\) = the label of related case \(v\), \(n\) = the number of related cases and \(m\) = Limits.min_support (default 0.5):

\[ \text{support} = \frac{\#\{\, v : \ell_v = \ell \,\}}{n}, \qquad \text{pass} \iff \text{support} \ge m . \]

snapshot_from_graph computes the share over every vertex of the graph, linked or not; an empty graph gives 0. When support is None (you did not measure it), the check passes, unless Limits.require_support is True, in which case it fails with support not measured (require_support).

The record's support entry:

Field Meaning
metrics.support the share (present only when measured; also health.support)
metrics.min_support \(m\)
metrics.require_support the require_support setting
metrics.measured true when support was supplied
trust always operational

It is a practical rule with an explicit constant, not a result from the math catalog, so its trust level is always operational (practical).

What it does not tell you

  • It is off unless you measure it. Every shipped example except fraud_review and clinical_triage leaves support unmeasured, and the check passes with support not measured. Set Limits(require_support=True) once every decision carries it.
  • It does not know which label your action implies. The mapping from action to label (SUPPORTING_LABEL in the examples) is yours. A wrong mapping makes the check hold exactly the decisions it should pass.
  • It counts, it does not weigh. Every related case counts once, however weakly linked. Whether the related cases are informative at all is the job of neighbour agreement and the knife-edge check; a 2-of-4 share passes here and is held there.
  • One half is a starting point, not a result. No theorem says 0.5 is right for your data. Learn it from your history (below).
  • A pass does not say the action is correct. It says most related cases carry the outcome the action implies. Your error rate is what learning with a certificate measures.

What to do when it fails

The reason reads like support 0.19 vs minimum 0.50 (does not support the proposed action).

  • One case held: your model and the related cases disagree. Route it to a person; that disagreement is what a reviewer is for.
  • Many cases held: check the action-to-label mapping first, then whether the related cases are the right population (a graph that mixes unrelated accounts dilutes the share).
  • Choose the minimum from your history: Learn parameters from your history tries minimums 0 (check off), 0.5, 0.6, 0.7, 0.8 and 0.9 alongside the other settings and keeps the combination that acts most while meeting your error target. The learned value becomes Limits.min_support.

Where next