Aller au contenu

ADR-0016 — Corpus de validation actuarielle (Green / Red / Kill)

Statut Accepté — 2026-06-17
Portée Process de validation métier (actuariel) ; structure des jeux de données et des sorties attendues ; runner
Décision Un répertoire validation/ regroupe jeux de données versionnés + manifestes de scénarios (green / red / kill) + un runner qui rejoue tout ; les oracles hand-computed restent en pytest
Réf. Vision — Trajectoires/émergence (garde-fou 3) ; ADR-0005 ; ADR-0015

🎯 À retenir

Un répertoire validation/ regroupe des jeux de données versionnés + des manifestes de scénarios (green / red / kill) + un runner mince qui rejoue tout. Le runner appelle les mêmes fonctions que l'app (source de vérité unique) ; les oracles hand-computed restent en pytest, le corpus les délègue, jamais ne les recopie. Un actuaire étend le corpus sans coder.

Contexte

L'objectif déclaré est une campagne de validation sur de vrais jeux de données, pour éprouver le côté actuariel. Trois constats rendent le moment juste :

  1. Les jeux de test (photos-flavorB/) vivaient hors du dépôt git (à la racine BFEV-Projects/) — non versionnés, perdables, invisibles à la CI.
  2. Les suites pytest (114 lib + 152 backend) sont orientées développeur : excellentes pour le moteur, mais ni lisibles ni extensibles par un actuaire qui veut ajouter un scénario réglementaire sans écrire de Python.
  3. Le futur jeu multi-entités de l'étage 2 (mobilité groupe) allait naître comme un énième CSV perdu, faute de structure d'accueil.

Il manque une couche métier, data-driven, auditable : jeux de données + sorties attendues explicites + traçabilité réglementaire, rejouables d'une commande.

Options considérées

  • A — Corpus data-driven séparé (validation/, manifestes YAML, runner mince) : l'actuaire écrit des données + un attendu ; le code reste la source de vérité du moteur.
  • B — Tout en pytest : ajouter chaque scénario comme test Python.
  • C — Ad hoc : des scripts/CSV au cas par cas, comme aujourd'hui.
Critère A — corpus B — pytest C — ad hoc
Authorable par un actuaire (sans Python) ✅ YAML + CSV ⚠️
Source de vérité moteur unique ✅ (réutilise les fns app) ⚠️ dérive
Rapport lisible métier (Green/Red) ❌ (sortie pytest)
Oracles hand-computed scellés ✅ délégation kill ✅ natif ⚠️
Traçabilité réglementaire ✅ champ reference ⚠️ commentaires
Coût faible (runner mince) faible nul mais dette

Décision

Option A, avec ces partis pris :

  • D-CORPUS-1 — Trois types de scénario. green (golden-master / oracle numérique tolérancé — ce qui doit marcher), red (negative testing — une anomalie de reconstruction DOIT remonter, ce qui doit être refusé), kill (oracle scellé — délégué au node pytest qui le porte).
  • D-CORPUS-2 — Source de vérité unique. Les pipelines du runner appellent les mêmes fonctions que l'app (calculer_dbo_jeu, reconstruire). Aucune logique actuarielle n'est recopiée. Les oracles hand-computed (K1, K-WATERFALL-B…) restent en pytest ; le corpus les regroupe par délégation, jamais par copie.
  • D-CORPUS-3 — Jeux de données versionnés dans le dépôt (validation/datasets/), par famille (mono-entreprise/, multi-entites/). Fin des CSV hors-git. Cohérent avec le garde-fou 3 (« ne jamais jeter »).
  • D-CORPUS-4 — Traçabilité réglementaire obligatoire. Chaque manifeste porte un champ reference (CIMA art., IAS 19 §, ou contrôle interne nommé). Un scénario sans base citée n'est pas auditable.
  • D-CORPUS-5 — Pas de DSL. YAML + runner mince ; le champ pipeline pointe un petit registre de mécanismes connus (dbo, trajectoires, … étendus au besoin).
  • D-CORPUS-6 — Runner standalone, sous le venv backend, à code de sortie 1 si un scénario échoue. L'intégration à la CI (un test qui rejoue Green+Red) viendra quand le corpus grossira ; le kill reste en pytest natif (pas de récursion).

Conséquences

  • Le jeu multi-entités de l'étage 2 naît dans le corpus (premier citoyen de multi-entites/), avec ses Green (bouclage par entité) et Red (mutation ré-initialisant l'ancienneté alors que la convention la dit portable).
  • Un actuaire étend le corpus sans coder : dépose un CSV, écrit un manifeste, cite la réglementation, lance le runner.
  • Golden-master ≠ oracle : un green gelé sur la sortie moteur protège de la régression (le moteur ne doit pas se mettre à produire autre chose), mais ne prouve pas l'exactitude dans l'absolu — c'est le rôle des kill (hand-computed). Les deux coexistent, nommés franchement.

⚠️ Piège

Un green ne prouve pas l'exactitude : c'est un golden-master qui gèle la sortie moteur et n'attrape que la régression. Seuls les kill (oracles hand-computed) attestent la justesse dans l'absolu. Ne pas lire un corpus tout-vert comme une preuve de correction actuarielle.

Déclencheur de réexamen (pré-enregistré)

Si le nombre de scénarios rend le runner standalone insuffisant (besoin de parallélisme, de fixtures partagées, de paramétrage massif), réexaminer pour intégrer le corpus à pytest (paramétrage sur les manifestes) — en gardant la lisibilité métier du rapport.