Skip to content
Sandbox

Score semantics

The numbers the API returns are not probabilities: each one carries a class that says what it measures, what it can be compared with and what it cannot.

View as Markdown

The API returns around twenty numbers between 0 and 1, under three names: confidence, strength and value. They look like confidence levels; none of them is one. This page explains what each number measures, what it may be compared with, and what to read instead when you need to decide.

What these numbers are not

No number returned by the API is a probability. A confidence.entity of 0.85 does not mean "an 85 % chance that the entity is right"; a match_strength.value of 0.5 does not mean "one chance in two". The contract says so in two ways:

  • the calibration field, carried by every score object (confidence, match_strength, provenance, cadence_detail, calendar_pattern, lifecycle), is always non_calibree: none of these values has been related to an observed frequency on a reference corpus;
  • the x-noryo-score extension, carried by every number in the contract that looks like a confidence, always declares its class, calibration: non_calibree and is_probability: false, and depending on the number comparable_within, not_comparable_with, formula, source or duplicate_of.

non_calibree is the only value the contract admits in this version, and that is a constraint, not a convention. These annotations can be read at https://api.noryo.app/openapi.json or in the generated reference.

The six classes

The classes are described under components.x-noryo-score-classes in the contract, exactly as served:

ClassMeaningMonotonicUse
declared_constant
constante declaree
Une valeur POSEE par la personne qui a ecrit le motif ou la regle, lue telle quelle. Elle ne resulte d'aucun calcul sur la transaction : toute transaction qui touche le meme motif recoit le meme nombre. Mesure sur 644 libelles : la precision n'est PAS monotone en ce nombre (0,85 -> 0,86 ; 0,88 -> 0,33 ; 0,92 -> 0,25 ; 0,97 -> 0,79).falseNe l'utilisez ni comme seuil ni comme rang. Utilisez `policy.outcome`.
evidence_ratio
part des signaux corroborants
`present / possible` : combien de signaux corroborants ce TYPE sait produire, et combien sont effectivement la. Le denominateur DEPEND du type — 5 pour `refund_of`, 4 pour `reversal_of`, 2 pour `transfer_pair`, 5 criteres heterogenes pour une serie — et `corroborations` le rend a cote, parce que sans lui le nombre ne se lit pas.within_typeComparable entre deux objets du MEME type et de la meme `detector_version`. Jamais entre un `refund_of` et un `transfer_pair`, jamais entre une relation et une serie.
calendar_fill
taux de remplissage calendaire
La part des periodes calendaires de l'etendue observee qui portent au moins une occurrence, pour l'hypothese de cadence retenue. ★ `0` signifie « aucune hypothese calendaire n'a ete retenue » (cadence `irregular_recurring`), pas « faible ».within_cadenceComparable entre deux series de MEME cadence. Une hebdomadaire sur 8 semaines et une annuelle sur 2 ans ne se comparent pas.
anchor_stability
stabilite de l'ancrage
Un jeu de constantes par TYPE d'ancrage (1,0 pour un jour fixe de semaine, 0,9 pour un jour ajuste au jour ouvre) et deux formules lineaires sur l'etendue des jours pour `fixed_day_of_month` et `flexible_calendar_window`. `0` pour `unknown`. ★ `flexible_calendar_window` a DEUX regles selon la cadence : une constante 0,3 sans `day_range` en cadence `weekly`/`biweekly`, et `1 - etendue/10` (plancher 0,1) avec `day_range` en cadence mensuelle ou plus longue.within_anchor_type_and_cadenceComparable entre deux series de MEME type d'ancrage ET de MEME cadence. Un 0,33 `fixed_day_of_month` et un 0,3 `flexible_calendar_window` ne disent pas la meme chose ; un 0,3 `flexible_calendar_window` hebdomadaire et un 0,3 mensuel non plus.
authority_tiebreak
departage a autorite egale
La confiance declaree de la source d'une activite. Elle n'entre en jeu qu'APRES la nature d'autorite (`curated` > `deterministic` > `provider` > `inferred` > `participant`), pour departager deux sources de meme nature.within_natureNe compare jamais deux natures : un 0,95 `inferred` ne l'emporte pas sur un 0,90 `curated`.
text_coverage
couverture textuelle
Un rapport de longueurs : la part du libelle utile que le motif apparie couvre, ou la part d'un motif compact qu'un fragment tronque recouvre. C'est une propriete du TEXTE, pas une preuve d'identite : un seuil dessus couterait 61 justes pour ecarter 17 faux.trueComparable entre libelles. N'en faites pas un seuil d'identite.

Where each class applies

FieldClassComparable withNever comparable with
resolution.confidence.entity, .counterparty, .transaction_type, .category, .locationdeclared_constantnothingany other score
relationships[].match_strength.valueevidence_ratioa relationship of the same type and the same detector_versiona relationship of another type, series[].match_strength
series[].match_strength.valueevidence_ratioa series of the same detector_versionrelationships[].match_strength, cadence_detail.strength
series[].cadence_detail.strength (repeated in lifecycle.cadence_strength)calendar_filla series of the same cadenceanother cadence, match_strength, calendar_pattern.strength
series[].calendar_pattern.strength (repeated in lifecycle.calendar_anchor)anchor_stabilitya series of the same anchor type and the same cadenceanother anchor type, another cadence, cadence_detail.strength, match_strength
resolution.counterparty.semantics.provenance.strengthauthority_tiebreaka source of the same natureanother nature of authority, any other score
resolution.counterparty.evidence.coverage, .coveredtext_coverageother descriptors (coverage), other truncated cases (covered)any identity or series score (coverage); any other score (covered)

lifecycle.cadence_strength and lifecycle.calendar_anchor are not additional scores: they are copies (duplicate_of in the contract), returned so that the lifecycle can be read on its own. The name confidence under resolution is kept for ti_v1 compatibility: read it as "declared strength of the pattern", never as a confidence.

Comparing: only within a class and a type

A number may only be compared with another number of the same class, produced for the same kind of object, by the same detector version. Take evidence_ratio: the value is present / possible, and the denominator depends on the type (5 possible signals for refund_of, 4 for reversal_of, 2 for transfer_pair, 5 heterogeneous criteria for a series). The same 0.5 is therefore one signal out of two for a transfer pair and two out of four for a reversal:

{
  "type": "transfer_pair",
  "match_strength": {
    "value": 0.5,
    "calibration": "non_calibree",
    "corroborations": { "present": 1, "possible": 2 }
  }
}
JSON
{
  "type": "reversal_of",
  "match_strength": {
    "value": 0.5,
    "calibration": "non_calibree",
    "corroborations": { "present": 2, "possible": 4 }
  }
}
JSON

This is why corroborations is returned next to value: without present and possible, the number cannot be read. A series match_strength counts five criteria (calendar cadence, fixed or narrow amount, at least three occurrences, known entity, specialised type): same name, different measure.

The other classes follow the same logic:

  • calendar_fill: between series of the same cadence. A weekly series over eight weeks and a yearly one over two years cannot be compared. 0 means "no calendar hypothesis was retained" (cadence irregular_recurring), not "weak".
  • anchor_stability: between series of the same anchor type and the same cadence. A 0.33 on fixed_day_of_month and a 0.3 on flexible_calendar_window do not say the same thing, and flexible_calendar_window changes its rule with the cadence. 0 corresponds to the unknown type.
  • authority_tiebreak: only after the nature of authority. The order curated, deterministic, provider, inferred, participant is declared, not derived from a number: a 0.95 of nature inferred does not beat a 0.90 of nature curated. strength only separates two sources of the same nature.
  • text_coverage: a property of the text, the share of the useful descriptor covered by the pattern (coverage) or the share of a compact pattern covered by a truncated fragment (covered, the tronque route). Comparable between descriptors, it is not proof of identity.
Warning

Never rank two objects of different types by their score, and never add up scores of different classes.

Decide with policy.outcome, not with a threshold

The declared_constant class is the most tempting one to use as a threshold. The five numbers under resolution.confidence are constants set by the person who wrote the pattern or the rule: every transaction that hits the same pattern receives the same number. Their class is marked monotonic: false in the contract: the measured precision, documented in the class description, is not monotone in this number, and a threshold on it does not separate right from wrong.

Read resolution.policy instead:

  • outcome is resolved (every dimension the archetype requires is present), partial (the nature is known, a required dimension is missing, or signals contradict each other) or unresolved (even the nature of the transaction is unknown);
  • missing names the absent dimensions: counterparty_entity, counterparty_type, transaction_type or resolution_policy;
  • archetype says what "resolved" requires here: a transfer to a person is resolved without any entity, a cash withdrawal without a merchant, a card purchase requires its counterparty.
{
  "policy": {
    "outcome": "partial",
    "archetype": "achat_carte",
    "missing": ["counterparty_entity"],
    "policy_version": "ti_resolution_v1"
  },
  "counterparty": null,
  "transaction_type": { "canonical": "card_purchase", "evidence": "rail_rule", "contradiction": null },
  "confidence": {
    "entity": 0,
    "counterparty": 0,
    "transaction_type": 0.95,
    "category": 0,
    "location": 0,
    "calibration": "non_calibree"
  }
}
JSON

Here confidence.transaction_type is 0.95 even though the transaction is not resolved: the type is known from a rail rule, the counterparty is not. It is policy.outcome and policy.missing that tell you so, not the numbers.

0 has a precise meaning per field: abstention for entity, unknown role for counterparty, conflict with no common ancestor for transaction_type; location is always 0 in this version. When signal_conflicts is not empty, outcome is partial: the engine declines to conclude. An identity abstention (identity_abstention), by contrast, leaves outcome at resolved if the archetype did not require an entity.

Keeping a number: keep the version with it

If you store a value, store the version that produced it: resolution.versions (engine, resolution_policy, calibration) for the resolution, detector_version for a relationship or a series. The same value, under another version, may no longer measure the same thing.

Statistical calibration: not available

No statistical calibration is available in this version. When a real calibration exists, it will enter through a declared migration, together with the corpus that supports it. Until then, the confidence and strength values are deterministic evidence strengths: the same pattern, signals and version always give the same number. Decide on policy.outcome, on the enums (status, lifecycle.state, identity.status) and on the evidence (evidence, corroborations, signals.used).

Further reading

Published on 2026-09-17 11:19 UTC (version 1).

Was this page helpful?