PD-296 — Scénarios de tests contractuels
1. Références
- Spécification : PD-296-specification.md
- Epic : EPIC-XX
2. Matrice de couverture
| ID Invariant | ID Critère | ID Test | Couverture | Commentaire |
| INV-296-01 | CA-296-02, CA-296-07 | TC-NOM-07 | Oui | Vérifie exactement 5 checkpoints officiels par story et sur tous les projets ciblés. |
| INV-296-02 | CA-296-01 | TC-NOM-01, TC-ERR-04 | Oui | STEP1_SPEC_COHERENCE requis avant passage step 2. |
| INV-296-03 | CA-296-02 | TC-NOM-02, TC-ERR-05 | Oui | STEP4_CONTRACTS_FORMAL avant Gate 5. |
| INV-296-04 | CA-296-12 | TC-NOM-03, TC-ERR-05 | Oui | /gov-check-plan phase formelle pré-Gate 5 obligatoire. |
| INV-296-05 | CA-296-02 | TC-NOM-04, TC-ERR-06 | Oui | STEP6_CODE_FORMAL avant step 7. |
| INV-296-06 | CA-296-02 | TC-NOM-05, TC-ERR-07 | Oui | GATE8_FINAL_FORMAL avant Gate 8. |
| INV-296-07 | CA-296-03 | TC-ERR-04, TC-ERR-05, TC-ERR-06, TC-ERR-07 | Oui | Tout FAIL bloque la transition aval. |
| INV-296-08 | CA-296-04, CA-296-10 | TC-ERR-08, TC-ERR-09 | Oui | Fail-closed sur indisponibilité et timeout. |
| INV-296-09 | CA-296-08 | TC-ERR-13 | Oui | Jira Done interdit si FAIL formel ouvert. |
| INV-296-10 | CA-296-07 | TC-NOM-07 | Oui | Pas d’exception projet/domaine. |
| INV-296-11 | CA-296-05, CA-296-06 | TC-NOM-08 | Oui | Article VIII présent et référencé. |
| INV-296-12 | CA-296-11 | TC-INV-01, TC-NEG-02 | Oui | FSM fermée aux 4 états autorisés. |
| INV-296-13 | CA-296-03 | TC-INV-02, TC-NEG-03, TC-NEG-12 | Oui | Toute transition hors §5.4 rejetée. |
| INV-296-14 | CA-296-11 | TC-NOM-09, TC-ERR-03 | Oui | Contrat D-296-14 strictement validé. |
| INV-296-15 | CA-296-09 | TC-NOM-10, TC-NOM-12, TC-ERR-10, TC-ERR-11, TC-NEG-09 | Oui | Lock, idempotence, réconciliation, rate-limit couverts. |
| INV-296-16 | CA-296-11 | TC-ERR-01, TC-ERR-02, TC-NEG-01, TC-NEG-04, TC-NEG-05, TC-NEG-06, TC-NEG-07, TC-NEG-08 | Oui | Données invalides rejetées avec blocage. |
| INV-296-17 | CA-296-03 | TC-INV-03, TC-ERR-12 | Oui | Aucun mode warning/informative/skip. |
| INV-296-18 | CA-296-01..CA-296-12 | TC-INV-04 | Partielle | Couverture définie intégralement, réserves de testabilité listées en §9. |
3. Scénarios de test – Flux nominaux
TEST-ID: TC-NOM-01
Référence spec: INV-296-02, CA-296-01
GIVEN
- Story `PD-296`, projet `ia-governance`, spec valide sauvegardée
- Environnement de test déterministe avec journal d’audit horodaté UTC
WHEN
- L’événement `SPEC_SAVED` déclenche `STEP1_SPEC_COHERENCE` avec verdict `GO`
THEN
- La transition d’état suit `PENDING -> RUNNING -> PASSED`
- La transition step 1 -> step 2 est autorisée
AND
- Un résultat `formal_check_result_json` conforme `D-296-14` est archivé
TEST-ID: TC-NOM-02
Référence spec: INV-296-03, CA-296-02
GIVEN
- `PD-296-plan.md` et `code-contracts.yaml` valides sauvegardés
WHEN
- L’événement `PLAN_AND_CONTRACTS_SAVED` déclenche `STEP4_CONTRACTS_FORMAL` avec verdict `GO`
THEN
- Le checkpoint `STEP4_CONTRACTS_FORMAL` passe à `PASSED`
- La story devient éligible au pré-Gate 5
AND
- Aucun blocage Gate 5 n’est présent
TEST-ID: TC-NOM-03
Référence spec: INV-296-04, CA-296-12
GIVEN
- Step 4 validé et session `/gov-check-plan` en phase 4
WHEN
- L’événement `CHECK_PLAN_PHASE4_START` déclenche `GATE5_PLAN_FORMAL` avec verdict `GO`
THEN
- Le checkpoint `GATE5_PLAN_FORMAL` est `PASSED`
- La soumission Gate 5 est autorisée
AND
- La phase formelle est visible dans les traces avant le verdict Gate 5
TEST-ID: TC-NOM-04
Référence spec: INV-296-05, CA-296-02
GIVEN
- Step 6c terminé pour `PD-296`
WHEN
- L’événement `STEP6C_DONE` déclenche `STEP6_CODE_FORMAL` avec verdict `GO`
THEN
- Le checkpoint `STEP6_CODE_FORMAL` est `PASSED`
- La transition step 6 -> step 7 est autorisée
AND
- L’audit lie explicitement `story_id`, `checkpoint_id`, `verdict`
TEST-ID: TC-NOM-05
Référence spec: INV-296-06, CA-296-02
GIVEN
- `/gov-accept` a terminé la phase 2 pour `PD-296`
WHEN
- L’événement `GOV_ACCEPT_PHASE2_DONE` déclenche `GATE8_FINAL_FORMAL` avec verdict `GO`
THEN
- Le checkpoint `GATE8_FINAL_FORMAL` est `PASSED`
- La soumission Gate 8 est autorisée
AND
- Aucune fermeture n’est bloquée par un FAIL formel
TEST-ID: TC-NOM-06
Référence spec: CA-296-01
GIVEN
- Story `PD-296` exécutée depuis step 0 puis step 1
WHEN
- Les contrôles de cohérence sont lancés au step 0 puis au step 1
THEN
- Deux exécutions distinctes de `coherence` sont observables dans les traces
- Les deux exécutions portent des `correlation_id` distincts
AND
- L’exécution step 1 est rattachée à `STEP1_SPEC_COHERENCE`
TEST-ID: TC-NOM-07
Référence spec: INV-296-01, INV-296-10, CA-296-07
GIVEN
- 8 stories de test, une par `project_code`: backend, app, site, infra, doc, formal, pixel-governance, ia-governance
- Toutes les entrées D-296 valides
WHEN
- Le workflow `/gov` complet est exécuté avec verdicts `GO`
THEN
- Chaque story exécute exactement les 5 `checkpoint_id` canoniques, une seule fois chacun
- Aucun filtre projet/domaine n’exclut un checkpoint
AND
- Les transitions aval sont autorisées uniquement après `PASSED`
TEST-ID: TC-NOM-08
Référence spec: INV-296-11, CA-296-05, CA-296-06
GIVEN
- Révision de dépôt figée
WHEN
- Contrôle de contenu sur `governance/CONSTITUTIONAL.md` et `CLAUDE.md`
THEN
- L’Article VIII "Vérification formelle" est détectable et exact dans `CONSTITUTIONAL.md`
- `CLAUDE.md` contient une référence explicite à l’Article VIII
AND
- Les deux preuves sont archivées en export probatoire
TEST-ID: TC-NOM-09
Référence spec: INV-296-14, CA-296-11
GIVEN
- Une exécution complète avec 5 checkpoints `PASSED`
WHEN
- Chaque `formal_check_result_json` est validé contre D-296-14 + contraintes D-296-01..D-296-15
THEN
- Les clés requises sont toutes présentes
- Les formats/regex/tailles sont conformes
AND
- La validation schéma réussit pour chaque checkpoint
TEST-ID: TC-NOM-10
Référence spec: INV-296-15, CA-296-09
GIVEN
- Checkpoint déjà exécuté avec `idempotency_key=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef`
WHEN
- La même requête (clé identique, payload identique) est rejouée dans `idempotency_window_h`
THEN
- Le résultat retourné est identique (verdict, état, code d’échec, détails)
- Aucun second run n’est créé
AND
- L’audit marque le replay idempotent sans effet secondaire
TEST-ID: TC-NOM-11
Référence spec: INV-296-13, §5.4 retour `FAILED_BLOCKING -> PENDING`
GIVEN
- Un checkpoint en `FAILED_BLOCKING` avec `details[]` renseigné
- Artefact corrigé et nouvel événement déclencheur valide
WHEN
- Une relance est demandée
THEN
- La transition suit `FAILED_BLOCKING -> PENDING -> RUNNING -> PASSED`
- Les `details[]` historiques d’échec restent conservés
AND
- Les verrous aval restent actifs jusqu’au nouveau `PASSED`
TEST-ID: TC-NOM-12
Référence spec: INV-296-15
GIVEN
- Un run orphelin en `RUNNING` au-delà de `orphan_threshold_sec`
- État dégradé actif nécessitant `clearing_success_cycles_required=2`
WHEN
- Le scanner de réconciliation s’exécute puis deux cycles consécutifs `PASSED` sont observés
THEN
- Le run orphelin est converti en `FAILED_BLOCKING` avec `failure_code=INTERNAL_ERROR`
- L’état dégradé est levé seulement après 2 cycles `PASSED` consécutifs
AND
- Les traces montrent l’intervalle de scan appliqué (`reconciliation_interval_sec`)
4. Scénarios de test – Cas d’erreur
TEST-ID: TC-ERR-01
Référence spec: ERR-296-01, D-296-01, INV-296-16
GIVEN
- Payload avec `story_id="pd-296"` (regex invalide)
WHEN
- Le checkpoint est soumis
THEN
- Rejet immédiat avec état `FAILED_BLOCKING`
- Progression aval interdite
AND
- Aucun run `RUNNING` n’est démarré
TEST-ID: TC-ERR-02
Référence spec: ERR-296-02, D-296-03, INV-296-16
GIVEN
- Payload avec `checkpoint_id="STEP9_UNKNOWN"`
WHEN
- Le checkpoint est soumis
THEN
- Rejet immédiat avec `FAILED_BLOCKING`
- Aucun mapping step/gate n’est exécuté
AND
- L’erreur est journalisée en audit
TEST-ID: TC-ERR-03
Référence spec: ERR-296-03, D-296-14, INV-296-14
GIVEN
- Résultat formel sans clé obligatoire `details`
WHEN
- Le moteur tente d’enregistrer `formal_check_result_json`
THEN
- Rejet avec `failure_code=INTERNAL_ERROR`
- État checkpoint `FAILED_BLOCKING`
AND
- Aucune transition aval n’est autorisée
TEST-ID: TC-ERR-04
Référence spec: ERR-296-04, INV-296-07, CA-296-03
GIVEN
- `STEP1_SPEC_COHERENCE` retourne `verdict=FAIL`, `failure_code=CONTRADICTION_DETECTED`
WHEN
- La progression vers step 2 est demandée
THEN
- Step 2 est refusé
- Les contradictions sont visibles dans `details[]`
AND
- Le blocage est tracé avec `checkpoint_id` concerné
TEST-ID: TC-ERR-05
Référence spec: ERR-296-05, INV-296-07
GIVEN
- `STEP4_CONTRACTS_FORMAL` ou `GATE5_PLAN_FORMAL` retourne `FAIL`
WHEN
- Une soumission Gate 5 est tentée
THEN
- Gate 5 est refusée
- Le checkpoint reste `FAILED_BLOCKING`
AND
- Aucun verdict Gate 5 n’est publié
TEST-ID: TC-ERR-06
Référence spec: ERR-296-06, INV-296-07
GIVEN
- `STEP6_CODE_FORMAL` retourne `FAIL`
WHEN
- Une transition vers step 7 est tentée
THEN
- Step 7 est interdit
- La story reste bloquée sur la boucle de correction step 6
AND
- Le blocage persiste jusqu’à nouveau `PASSED`
TEST-ID: TC-ERR-07
Référence spec: ERR-296-07, INV-296-07
GIVEN
- `GATE8_FINAL_FORMAL` retourne `FAIL`
WHEN
- Une soumission Gate 8 est tentée
THEN
- Gate 8 est refusée
- La clôture reste interdite
AND
- Le statut Jira n’atteint pas `Done`
TEST-ID: TC-ERR-08
Référence spec: ERR-296-08, INV-296-08, CA-296-04
GIVEN
- Outil formel indisponible au déclenchement checkpoint
WHEN
- Le checkpoint démarre
THEN
- Résultat `verdict=FAIL`, `failure_code=TOOL_UNAVAILABLE`
- État final `FAILED_BLOCKING`
AND
- Aucun mode dégradé non bloquant n’est appliqué
TEST-ID: TC-ERR-09
Référence spec: ERR-296-09, INV-296-08, CA-296-10
GIVEN
- Checkpoint en `RUNNING` dépasse son SLA configuré
WHEN
- L’échéance timeout est atteinte
THEN
- Transition forcée `RUNNING -> FAILED_BLOCKING`
- `failure_code=TIMEOUT`
AND
- La progression aval reste interdite
TEST-ID: TC-ERR-10
Référence spec: ERR-296-10, INV-296-15
GIVEN
- Un lock distribué actif sur (`story_id=PD-296`, `checkpoint_id=STEP4_CONTRACTS_FORMAL`)
WHEN
- Un second déclenchement concurrent est reçu sur le même scope
THEN
- La requête concurrente retourne `verdict=FAIL`, `failure_code=CONCURRENT_RUN`
- Le checkpoint est bloquant pour cette tentative
AND
- Aucun second run parallèle n’est créé
TEST-ID: TC-ERR-11
Référence spec: ERR-296-11, INV-296-15
GIVEN
- Requête A enregistrée avec `idempotency_key=K1`
WHEN
- Requête B est rejouée avec `idempotency_key=K1` et payload différent
THEN
- Rejet explicite de la relance
- Blocage de progression maintenu
AND
- Le résultat de la requête A n’est pas écrasé
TEST-ID: TC-ERR-12
Référence spec: ERR-296-12, INV-296-17
GIVEN
- Un checkpoint `FAILED_BLOCKING` ouvert
WHEN
- Une tentative de bypass/force passage est soumise
THEN
- Rejet explicite de la tentative
- État de blocage inchangé
AND
- Traçabilité d’audit obligatoire présente
TEST-ID: TC-ERR-13
Référence spec: ERR-296-13, INV-296-09, CA-296-08
GIVEN
- Au moins un checkpoint formel `FAILED_BLOCKING` non corrigé
WHEN
- Transition Jira vers `Done` demandée
THEN
- Transition refusée
- Statut Jira inchangé
AND
- Motif de refus lié au checkpoint formel enregistré
5. Tests d’invariants (non négociables)
| Invariant | Test(s) dédiés | Observable | Commentaire |
| INV-296-01 | TC-NOM-07 | Compte exact des 5 checkpoints canoniques par story | Exécution systématique. |
| INV-296-02 | TC-NOM-01, TC-ERR-04 | STEP1_SPEC_COHERENCE avant step 2 | Blocage si FAIL. |
| INV-296-03 | TC-NOM-02, TC-ERR-05 | STEP4_CONTRACTS_FORMAL avant Gate 5 | Aucun passage sans PASSED. |
| INV-296-04 | TC-NOM-03 | Phase formelle visible en pré-Gate 5 | Vérification de séquencement. |
| INV-296-05 | TC-NOM-04, TC-ERR-06 | STEP6_CODE_FORMAL avant step 7 | Blocage déterministe. |
| INV-296-06 | TC-NOM-05, TC-ERR-07 | GATE8_FINAL_FORMAL avant Gate 8 | Clôture interdite sur FAIL. |
| INV-296-07 | TC-ERR-04..TC-ERR-07 | Aucune transition aval avec FAIL | Fail blocking strict. |
| INV-296-08 | TC-ERR-08, TC-ERR-09 | TOOL_UNAVAILABLE/TIMEOUT => FAIL | Fail-closed. |
| INV-296-09 | TC-ERR-13 | Jira Done interdit avec FAIL ouvert | Contrôle cross-module. |
| INV-296-10 | TC-NOM-07 | Même comportement sur 8 project_code | Sans exception. |
| INV-296-11 | TC-NOM-08 | Article VIII présent + référence CLAUDE | Contrôle documentaire. |
| INV-296-12 | TC-INV-01, TC-NEG-02 | États autorisés uniquement: PENDING/RUNNING/PASSED/FAILED_BLOCKING | FSM fermée. |
| INV-296-13 | TC-INV-02, TC-NEG-03, TC-NEG-12 | Transitions non listées rejetées | Terminalité incluse. |
| INV-296-14 | TC-NOM-09, TC-ERR-03 | Validation schéma D-296-14 | Machine-readable obligatoire. |
| INV-296-15 | TC-NOM-10, TC-NOM-12, TC-ERR-10, TC-ERR-11, TC-NEG-09 | Lock/idempotence/réconciliation/rate-limit actifs | Concurrence robuste. |
| INV-296-16 | TC-ERR-01, TC-ERR-02, TC-NEG-01, TC-NEG-04..08 | Toute donnée invalide rejetée + blocage | Intégrité des entrées. |
| INV-296-17 | TC-INV-03, TC-ERR-12 | Absence totale de mode warning only, informative only, skip | Non contournable. |
| INV-296-18 | TC-INV-04 | Audit de couverture INV/CA vs tests | Réserves de testabilité §9. |
6. Tests de non-régression
| Test ID | Objet | Observable | Commentaire |
| TC-NR-01 | Mapping déterministe step/gate -> checkpoint_id (F-296-01..05) | Même mapping sur replays identiques | Détecte dérive de routage. |
| TC-NR-02 | Scope du guard limité aux commandes /gov listées §5.7 | Aucun blocage hors scope /gov | Évite effet global non voulu. |
| TC-NR-03 | Conservation de l’historique après cycle correction | details[] d’échec toujours présents après FAILED_BLOCKING -> PENDING -> PASSED | Non-régression auditabilité. |
| TC-NR-04 | Interdiction d’auto-retry (formal_retry_on_failure=0) | Aucune relance automatique observée en erreur | Contrat fail-closed préservé. |
| TC-NR-05 | Terminalité PASSED stable | Toute transition sortante depuis PASSED rejetée | Non-régression FSM. |
7. Tests négatifs et adversariaux
| Test ID | Entrée invalide / abus | Résultat attendu | Observable |
| TC-NEG-01 | project_code="mobile" (hors enum D-296-02) | Rejet + FAILED_BLOCKING | Réponse erreur + audit INPUT_INVALID. |
| TC-NEG-02 | checkpoint_state="DONE" | Rejet immédiat | État inchangé, pas de transition aval. |
| TC-NEG-03 | Tentative RUNNING -> PENDING sans verdict | Rejet transition interdite | Journal FSM explicite. |
| TC-NEG-04 | Payload avec verdict=FAIL et blocking=false | Rejet du payload | Contrôle cohérence D-296-08. |
| TC-NEG-05 | artifact_path relatif ou hors racine autorisée | Rejet + blocage | Regex D-296-10 non satisfaite. |
| TC-NEG-06 | idempotency_key non hex/longueur !=64 | Rejet + blocage | Validation D-296-11 échoue. |
| TC-NEG-07 | correlation_id non UUID v4 | Rejet + blocage | Validation D-296-12 échoue. |
| TC-NEG-08 | details[] >200 items ou item >500 chars | Rejet + blocage | Validation D-296-15 échoue. |
| TC-NEG-09 | Dépassement rate_limit_checks_per_min_per_story | Rejet (équivalent 429), pas de progression | Compteur rate-limit incrémenté et refus tracé. |
| TC-NEG-10 | Configuration formal_retry_on_failure=1 | Rejet config + blocage | Contrat §5.2 respecté. |
| TC-NEG-11 | Configuration distributed_lock_ttl_sec=30 (hors bornes) | Rejet config + blocage | Validation bornes §5.2. |
| TC-NEG-12 | Tentative de sortie depuis état PASSED | Rejet (état terminal) | FSM inchangée, trace de refus. |
8. Observabilité requise pour les tests
- État système : snapshot FSM par
story_id/checkpoint_id, état Jira, état des verrous distribués, compteurs rate-limit. - Réponse API : statut de réponse, corps complet (
checkpoint_state, verdict, failure_code, blocking, correlation_id), motif de rejet. - Journal d’audit : événements horodatés UTC incluant
story_id, project_code, checkpoint_id, transition source/cible, acteur, décision. - Événement signé / horodaté : preuve d’intégrité (hash/signature) associée à chaque résultat formel et à chaque refus de transition.
- Export probatoire : paquet vérifiable (JSON/JSONL + logs) corrélant entrées, verdicts, transitions FSM, refus Jira
Done, et traces de concurrence/idempotence.
9. Règles non testables
| Règle | Raison | Impact |
mandatory_gates_formal=3 (G3/G5/G8) | Aucun checkpoint_id Gate 3 dans D-296-03 et aucun flux Gate 3 en §5.5 | Bloquant |
| CA-296-01 vs INV-296-01 (step 0 + step 1 vs “exactement 5 checkpoints”) | Le statut de l’exécution coherence au step 0 dans le décompte contractuel n’est pas explicitement défini | Majeur |
| Configurabilité des SLA §5.3 | Nommage exact des clés de configuration non fourni (Q-296-04), test admin non déterministe | Majeur |
Percentile P95 de formal_timeout_sec | Matériel/protocole de référence non spécifiés (Q-296-05), comparabilité objective impossible | Majeur |
Nature du mapping GO|FAIL (natif vs adaptateur) | Ambiguïté contractuelle (Q-296-02), vérification boîte blanche non définie | Majeur |
| Référence Epic exacte | Identifiant parent non fourni dans l’entrée (Q-296-01) | Mineur |
10. Verdict QA
- ✅ Testable intégralement : Non
- ⚠️ Testable partiellement (avec réserves listées) : Oui
- ❌ Non testable (refus contractuel) : Non