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

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](https://developer.noryo.app/fr-FR/transaction-intelligence/reference).

## Les six classes

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

| Classe | Sens | Monotone | Usage |
| --- | --- | --- | --- |
| `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). | false | Ne 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_type | Comparable 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_cadence | Comparable 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_cadence | Comparable 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_nature | Ne 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. | true | Comparable entre libelles. N'en faites pas un seuil d'identite. |

## Où chaque classe s'applique

| Champ | Classe | Comparable avec | Jamais comparable avec |
| --- | --- | --- | --- |
| `resolution.confidence.entity`, `.counterparty`, `.transaction_type`, `.category`, `.location` | `declared_constant` | rien | tout autre score |
| `relationships[].match_strength.value` | `evidence_ratio` | une relation du même `type` et de la même `detector_version` | une relation d'un autre type, `series[].match_strength` |
| `series[].match_strength.value` | `evidence_ratio` | une série de la même `detector_version` | `relationships[].match_strength`, `cadence_detail.strength` |
| `series[].cadence_detail.strength` (repris dans `lifecycle.cadence_strength`) | `calendar_fill` | une série de la même `cadence` | une autre cadence, `match_strength`, `calendar_pattern.strength` |
| `series[].calendar_pattern.strength` (repris dans `lifecycle.calendar_anchor`) | `anchor_stability` | une série du même `type` d'ancrage et de la même cadence | un autre type d'ancrage, une autre cadence, `cadence_detail.strength`, `match_strength` |
| `resolution.counterparty.semantics.provenance.strength` | `authority_tiebreak` | une source de la même `nature` | une autre nature d'autorité, tout autre score |
| `resolution.counterparty.evidence.coverage`, `.covered` | `text_coverage` | d'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 :

```json
{
  "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 }
  }
}
```

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.

```json
{
  "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"
  }
}
```

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

- [Enrichir une transaction](https://developer.noryo.app/fr-FR/transaction-intelligence/enrich-a-transaction)
- [Relations](https://developer.noryo.app/fr-FR/transaction-intelligence/relationships)
- [Séries récurrentes](https://developer.noryo.app/fr-FR/transaction-intelligence/recurring-series)
- [Contreparties et entités](https://developer.noryo.app/fr-FR/transaction-intelligence/counterparties-and-entities)
- [Référence générée](https://developer.noryo.app/fr-FR/transaction-intelligence/reference), chaque champ avec son `x-noryo-score`

---

Page canonique : https://developer.noryo.app/fr-FR/transaction-intelligence/score-semantics
