Aller au contenu
Sandbox

Sémantique des scores

Les nombres rendus par l'API ne sont pas des probabilités : chacun porte une classe qui dit ce qu'il mesure, à quoi il se compare et à quoi il ne se compare pas.

Voir en Markdown

L'API rend une vingtaine de nombres compris entre 0 et 1, sous trois noms : confidence, strength et value. Ils ressemblent à des confiances ; aucun n'en est une. Cette page dit ce que chacun mesure, avec quoi il se compare, et sur quoi décider à la place.

Ce que ces nombres ne sont pas

Aucun nombre rendu par l'API n'est une probabilité. Un confidence.entity à 0,85 ne signifie pas « 85 % de chances que l'entité soit la bonne » ; un match_strength.value à 0,5 ne signifie pas « une chance sur deux ». Le contrat le dit de deux façons :

  • le champ calibration, porté par chaque objet de score (confidence, match_strength, provenance, cadence_detail, calendar_pattern, lifecycle), vaut toujours non_calibree : aucune de ces valeurs n'a été rapportée à une fréquence observée sur un corpus de référence ;
  • l'extension x-noryo-score, portée par chaque nombre du contrat qui ressemble à une confiance, déclare toujours sa class, calibration: non_calibree et is_probability: false, et selon le nombre comparable_within, not_comparable_with, formula, source ou duplicate_of.

non_calibree est la seule valeur que le contrat admet dans cette version, et c'est une contrainte, pas une convention. Ces annotations se lisent sur https://api.noryo.app/openapi.json ou dans la référence générée.

Les six classes

Les classes sont décrites dans components.x-noryo-score-classes du contrat, telles qu'elles sont servies :

ClasseSensMonotoneUsage
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.

Où chaque classe s'applique

ChampClasseComparable avecJamais comparable avec
resolution.confidence.entity, .counterparty, .transaction_type, .category, .locationdeclared_constantrientout autre score
relationships[].match_strength.valueevidence_ratioune relation du même type et de la même detector_versionune relation d'un autre type, series[].match_strength
series[].match_strength.valueevidence_ratioune série de la même detector_versionrelationships[].match_strength, cadence_detail.strength
series[].cadence_detail.strength (repris dans lifecycle.cadence_strength)calendar_fillune série de la même cadenceune autre cadence, match_strength, calendar_pattern.strength
series[].calendar_pattern.strength (repris dans lifecycle.calendar_anchor)anchor_stabilityune série du même type d'ancrage et de la même cadenceun autre type d'ancrage, une autre cadence, cadence_detail.strength, match_strength
resolution.counterparty.semantics.provenance.strengthauthority_tiebreakune source de la même natureune autre nature d'autorité, tout autre score
resolution.counterparty.evidence.coverage, .coveredtext_coveraged'autres libellés (coverage), d'autres cas tronqués (covered)tout score d'identité ou de série (coverage) ; tout autre score (covered)

lifecycle.cadence_strength et lifecycle.calendar_anchor ne sont pas des scores supplémentaires : ce sont des copies (duplicate_of dans le contrat), rendues pour que le cycle de vie se lise seul. Le nom confidence sous resolution est conservé pour la compatibilité de ti_v1 : lisez-le comme « force déclarée du motif », jamais comme une confiance.

Comparer : dans une classe et un type seulement

Un nombre ne se compare qu'à un autre nombre de la même classe, produit pour le même type d'objet, par la même version de détecteur. Prenez evidence_ratio : la valeur est present / possible, et le dénominateur dépend du type (5 signaux possibles pour refund_of, 4 pour reversal_of, 2 pour transfer_pair, 5 critères hétérogènes pour une série). Un même 0.5 vaut donc un signal sur deux pour une paire de virement et deux sur quatre pour une contre-passation :

{
  "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

C'est pourquoi corroborations est rendu à côté de value : sans present et possible, le nombre ne se lit pas. Le match_strength d'une série compte cinq critères (cadence calendaire, montant fixe ou étroit, au moins trois occurrences, entité connue, type spécialisé) : même nom, autre mesure.

Les autres classes suivent la même logique :

  • calendar_fill : entre séries de même cadence. Une hebdomadaire sur huit semaines et une annuelle sur deux ans ne se comparent pas. 0 signifie « aucune hypothèse calendaire retenue » (cadence irregular_recurring), pas « faible ».
  • anchor_stability : entre séries de même type d'ancrage et de même cadence. Un 0.33 en fixed_day_of_month et un 0.3 en flexible_calendar_window ne disent pas la même chose, et flexible_calendar_window change de règle avec la cadence. 0 correspond au type unknown.
  • authority_tiebreak : après la nature d'autorité seulement. L'ordre curated, deterministic, provider, inferred, participant est déclaré, pas déduit d'un nombre : un 0.95 de nature inferred ne l'emporte pas sur un 0.90 de nature curated. strength ne départage que deux sources de même nature.
  • text_coverage : une propriété du texte, la part du libellé utile couverte par le motif (coverage) ou la part d'un motif compact recouverte par un fragment tronqué (covered, voie tronque). Comparable entre libellés, ce n'est pas une preuve d'identité.
Attention

Ne classez jamais deux objets de types différents par leur score, et ne cumulez jamais des scores de classes différentes.

Décider avec policy.outcome, pas avec un seuil

La classe declared_constant est la plus tentante comme seuil. Les cinq nombres de resolution.confidence sont des constantes posées par la personne qui a écrit le motif ou la règle : toute transaction qui touche le même motif reçoit le même nombre. Leur classe est marquée monotonic: false dans le contrat : la précision mesurée, documentée dans la description de la classe, n'est pas monotone en ce nombre, et un seuil dessus ne sépare pas le juste du faux.

Lisez à la place resolution.policy :

  • outcome vaut resolved (toutes les dimensions exigées par l'archétype sont là), partial (la nature est connue, une dimension exigée manque, ou des signaux se contredisent) ou unresolved (la nature même de la transaction est inconnue) ;
  • missing nomme les dimensions absentes : counterparty_entity, counterparty_type, transaction_type ou resolution_policy ;
  • archetype dit ce que « résolu » exige ici : un virement à une personne est resolved sans entité, un retrait d'espèces sans marchand, un achat carte exige sa contrepartie.
{
  "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

Ici confidence.transaction_type vaut 0.95 alors que la transaction n'est pas résolue : le type est connu par une règle de rail, la contrepartie ne l'est pas. Ce sont policy.outcome et policy.missing qui le disent, pas les nombres.

0 a un sens précis par champ : abstention pour entity, rôle inconnu pour counterparty, conflit sans ancêtre commun pour transaction_type ; location vaut toujours 0 dans cette version. Quand signal_conflicts n'est pas vide, outcome est partial : le moteur refuse de conclure. Une abstention d'identité (identity_abstention) laisse en revanche outcome à resolved si l'archétype n'exigeait pas d'entité.

Conserver un nombre : la version à côté

Si vous stockez une valeur, stockez la version qui l'a produite : resolution.versions (engine, resolution_policy, calibration) pour la résolution, detector_version pour une relation ou une série. La même valeur, sous une autre version, peut ne plus mesurer la même chose.

Calibration statistique : indisponible

Aucune calibration statistique n'est disponible dans cette version. Le jour où une calibration réelle existera, elle entrera par une migration déclarée, avec le corpus qui la défend. D'ici là, les valeurs confidence et strength sont des forces d'évidence déterministes : mêmes motif, signaux et version donnent toujours le même nombre. Décidez sur policy.outcome, sur les enums (status, lifecycle.state, identity.status) et sur les preuves (evidence, corroborations, signals.used).

Pour aller plus loin

Publié le 2026-09-17 11:19 UTC (version 1).

Cette page vous a-t-elle aidé ?