Aller au contenu

PD-297 — Scénarios de tests contractuels

1. Références

  • Spécification : PD-297-specification.md
  • Epic : EPIC-XX

2. Matrice de couverture

ID Invariant ID Critère ID Test Couverture Commentaire
INV-297-01 CA-297-03, CA-297-13 TC-ERR-05, TC-NOM-05, TC-NR-01 Oui Append-only vérifié sur run nominal, rerun et cycle de correction.
INV-297-02 CA-297-02 TC-NOM-02, TC-NEG-01 Oui Traçabilité story_id + trace_source obligatoire pour toute persistance.
INV-297-03 CA-297-03 TC-NOM-05, TC-ERR-03 Oui Idempotence stricte et détection de collision couvertes.
INV-297-04 CA-297-09 TC-ERR-04 Oui Erreur extraction/persistance force la dégradation.
INV-297-05 CA-297-09 TC-ERR-07, TC-ERR-08, TC-ERR-13 Oui Fail-closed en indisponibilité, timeout et erreur interne.
INV-297-06 CA-297-06, CA-297-07, CA-297-08 TC-NOM-04, TC-ERR-09 Oui Sorties scopes limitées à GO|FAIL, SKIP interdit.
INV-297-07 CA-297-04 TC-NOM-03, TC-NEG-03 Oui Validation impossible sans 4 formalismes.
INV-297-08 CA-297-05 TC-NOM-04, TC-NR-02 Oui Non-régression exécutée post-enrichissement avant clôture.
INV-297-09 CA-297-14 TC-NEG-01, TC-ERR-11 Oui FSM fermée aux états contractuels ; état terminal respecté.
INV-297-10 CA-297-14 TC-ERR-10, TC-NEG-05 Oui Toute transition hors §5.5 rejetée avec état inchangé.
INV-297-11 CA-297-15 TC-NOM-01 Oui Entrée nominale unique validée.
INV-297-12 CA-297-04 TC-NOM-03, TC-NEG-03 Oui EXTRACTING -> ENRICHED uniquement si 4 formalismes OK.
INV-297-13 CA-297-12 TC-ERR-04 Oui Timeout/erreur extraction/persistance -> ENRICHMENT_DEGRADED.
INV-297-14 CA-297-06, CA-297-07, CA-297-08 TC-NOM-04 Oui VERIFICATION_PASSED uniquement si non-régression GO + 3 scopes GO.
INV-297-15 CA-297-10 TC-ERR-06, TC-ERR-08, TC-ERR-09 Oui Tout FAIL/ERROR/SKIP bloque le run.
INV-297-16 CA-297-10 TC-ERR-04, TC-ERR-06 Oui Dégradé mène obligatoirement à blocage.
INV-297-17 CA-297-15 TC-NOM-04 Oui Clôture réussie unique VERIFICATION_PASSED -> DONE.
INV-297-18 CA-297-13 TC-NOM-06, TC-NR-05 Oui Transition retour unique et conservation d’historique.
INV-297-19 CA-297-14 TC-ERR-11 Oui DONE terminal, aucune sortie autorisée.
INV-297-20 CA-297-11, CA-297-12 TC-ERR-02, TC-ERR-03, TC-NR-03, TC-NR-04, TC-NEG-09 Oui Lock, idempotence, réconciliation, rate-limit, clearing couverts.
INV-297-21 CA-297-15 TC-NOM-07, TC-NEG-04 Oui Guard de clôture step 10 actif tant que job_state != DONE.
INV-297-22 CA-297-01..CA-297-16 TC-NOM-01..08, TC-ERR-01..13, TC-NR-01..05, TC-NEG-01..10 Oui Couverture globale fournie ; ambiguïtés classées NON TESTABLE en §9.

3. Scénarios de test – Flux nominaux

TEST-ID: TC-NOM-01
Référence spec: F-297-01, INV-297-11, CA-297-15

GIVEN
  - story_id=PD-297, story_version=1, project_code=ia-governance, domain_slug=formal
  - idempotency_key=1111111111111111111111111111111111111111111111111111111111111111
  - Payload conforme D-297-01..D-297-21
  - Aucun lock actif sur formal_enrich:PD-297:v1
WHEN
  - Le trigger step 10 démarre le run
THEN
  - Transition observée: PENDING -> EXTRACTING
  - Lock distribué acquis avant toute écriture
AND
  - Audit signé contenant story_id, lock_key, correlation_id, timestamp_utc
TEST-ID: TC-NOM-02
Référence spec: F-297-02, INV-297-02, CA-297-01, CA-297-02

GIVEN
  - Story éligible à la clôture step 10
  - Artefacts source (`spec_markdown`, `code_contracts`) figés
  - Cible D-297-10 valide
WHEN
  - Extraction Prolog et persistance append-only sont exécutées
THEN
  - Fichier PD-297.pl présent dans coherence/ontology/stories
  - Chaque entrée persistée porte story_id=PD-297 et trace_source conforme D-297-16
AND
  - Aucun prédicat préexistant n’est modifié/supprimé
TEST-ID: TC-NOM-03
Référence spec: F-297-03, INV-297-07, INV-297-12, CA-297-04

GIVEN
  - Run en EXTRACTING
  - Cibles valides pour formalism=prolog,tla,alloy,z
WHEN
  - L’enrichissement des invariants dérivés des code-contracts se termine sans erreur
THEN
  - Nouveaux artefacts observables pour les 4 formalismes
  - Transition observée: EXTRACTING -> ENRICHED
AND
  - Toute absence d’un formalisme invalide le passage à ENRICHED
TEST-ID: TC-NOM-04
Référence spec: F-297-04, F-297-05, F-297-06, INV-297-06, INV-297-14, INV-297-17, CA-297-05, CA-297-06, CA-297-07, CA-297-08

GIVEN
  - État ENRICHED
  - Non-régression verdict=GO
  - contracts=GO, code=GO, full=GO
WHEN
  - Agrégation finale des vérifications
THEN
  - Transitions observées: ENRICHED -> VERIFICATION_PASSED -> DONE
  - Les scopes ne retournent que GO ou FAIL
AND
  - Rapport de non-régression post-enrichissement archivé avant clôture
TEST-ID: TC-NOM-05
Référence spec: INV-297-01, INV-297-03, CA-297-03

GIVEN
  - Run initial exécuté avec idempotency_key=1111111111111111111111111111111111111111111111111111111111111111
  - Même payload, même clé, replay dans idempotency_window_h
WHEN
  - Le run est rejoué strictement à l’identique
THEN
  - formal_result_json identique bit-à-bit au run initial
  - Compte des prédicats persistés inchangé
AND
  - Fingerprints D-297-12 inchangés
TEST-ID: TC-NOM-06
Référence spec: INV-297-18, CA-297-13

GIVEN
  - Run en FAILED_BLOCKING après défaut corrigé explicitement
  - Historique d’exécution déjà archivé
WHEN
  - Relance explicite demandée
THEN
  - Transition observée: FAILED_BLOCKING -> PENDING
  - Historique et artefacts existants conservés
AND
  - Nouvelle tentative autorisée sous lock/rate-limit contractuels
TEST-ID: TC-NOM-07
Référence spec: INV-297-21, CA-297-15

GIVEN
  - job_state != DONE
WHEN
  - Une clôture step 10 est demandée
THEN
  - Clôture refusée
  - job_state inchangé
AND
  - Refus tracé avec motif de guard cross-module
TEST-ID: TC-NOM-08
Référence spec: CA-297-16

GIVEN
  - Révision figée des fichiers .claude/rules/procedures.md et .claude/rules/workflow-rules.md
WHEN
  - Contrôle documentaire PD-297 exécuté
THEN
  - Les deux documents reflètent le contrat PD-297 (états, fail-closed, GO|FAIL, pas SKIP)
  - Cohérence inter-documents vérifiée
AND
  - Tout écart est reporté comme non-conformité bloquante

4. Scénarios de test – Cas d’erreur

TEST-ID: TC-ERR-01
Référence spec: ERR-297-01, D-297-01

GIVEN
  - story_id="pd-297" (invalide)
WHEN
  - Soumission du run
THEN
  - Rejet immédiat
  - job_state=FAILED_BLOCKING, failure_code=INPUT_INVALID
AND
  - Aucun lock ni write formel effectué
TEST-ID: TC-ERR-02
Référence spec: ERR-297-02, INV-297-20, CA-297-11

GIVEN
  - Lock déjà détenu sur formal_enrich:PD-297:v1
WHEN
  - Un second run concurrent est soumis
THEN
  - Verdict FAIL, failure_code=CONCURRENT_RUN
  - Run concurrent rejeté
AND
  - Aucun write append-only supplémentaire
TEST-ID: TC-ERR-03
Référence spec: ERR-297-03, INV-297-03, INV-297-20

GIVEN
  - Requête A avec idempotency_key=2222222222222222222222222222222222222222222222222222222222222222
  - Requête B avec la même clé et payload différent
WHEN
  - Soumission de la requête B dans la fenêtre d’idempotence
THEN
  - Verdict FAIL, failure_code=IDEMPOTENCY_CONFLICT
  - Résultat de la requête A non modifié
AND
  - Aucun artefact additionnel persisté
TEST-ID: TC-ERR-04
Référence spec: ERR-297-04, INV-297-04, INV-297-13, INV-297-16

GIVEN
  - Run en EXTRACTING
  - Timeout ou erreur explicite sur extraction/persistance
WHEN
  - Expiration de la fenêtre SLA concernée
THEN
  - Transition EXTRACTING -> ENRICHMENT_DEGRADED
  - Puis transition ENRICHMENT_DEGRADED -> FAILED_BLOCKING
AND
  - Toute clôture reste interdite
TEST-ID: TC-ERR-05
Référence spec: ERR-297-05, INV-297-01

GIVEN
  - Base formelle contenant des faits déjà persistés
WHEN
  - Tentative de mutation/suppression d’un fait existant
THEN
  - Verdict FAIL, failure_code=PERSISTENCE_ERROR
  - État bloquant conservé
AND
  - Diff stockage: 0 suppression, 0 modification
TEST-ID: TC-ERR-06
Référence spec: ERR-297-06, INV-297-15, CA-297-10

GIVEN
  - État ENRICHED
  - Non-régression retourne contradiction
WHEN
  - Agrégation des résultats
THEN
  - Transition ENRICHED -> FAILED_BLOCKING
  - failure_code=NON_REGRESSION_CONTRADICTION
AND
  - Clôture step 10 interdite
TEST-ID: TC-ERR-07
Référence spec: ERR-297-07, INV-297-05, CA-297-09

GIVEN
  - formal-verify indisponible
WHEN
  - Exécution d’un scope formel
THEN
  - Verdict FAIL, failure_code=TOOL_UNAVAILABLE
  - État final FAILED_BLOCKING
AND
  - Aucun GO possible
TEST-ID: TC-ERR-08
Référence spec: ERR-297-08, INV-297-05, INV-297-15

GIVEN
  - Un check scope/non-régression dépasse son SLA
WHEN
  - Timeout atteint
THEN
  - Verdict FAIL, failure_code=TIMEOUT
  - Transition ENRICHED -> FAILED_BLOCKING
AND
  - Aucune transition aval autorisée
TEST-ID: TC-ERR-09
Référence spec: ERR-297-09, INV-297-06, INV-297-15, CA-297-06, CA-297-07, CA-297-08

GIVEN
  - Un scope retourne SKIP
WHEN
  - Le résultat est traité
THEN
  - SKIP est converti en FAIL
  - failure_code=SKIP_FORBIDDEN
AND
  - Transition ENRICHED -> FAILED_BLOCKING
TEST-ID: TC-ERR-10
Référence spec: ERR-297-10, INV-297-10

GIVEN
  - Run dans un état valide
WHEN
  - Demande d’une transition non listée en §5.5
THEN
  - Rejet explicite de transition
  - État courant conservé
AND
  - Événement d’audit de rejet horodaté
TEST-ID: TC-ERR-11
Référence spec: ERR-297-11, INV-297-19, CA-297-14

GIVEN
  - État DONE
WHEN
  - Toute transition sortante est demandée
THEN
  - Rejet explicite "état terminal"
  - État DONE inchangé
AND
  - Aucune sortie FSM autorisée
TEST-ID: TC-ERR-12
Référence spec: ERR-297-12, D-297-21

GIVEN
  - formal_result_json sans clé obligatoire (ex: details)
WHEN
  - Enregistrement du résultat demandé
THEN
  - Rejet + FAILED_BLOCKING
  - Résultat non conforme non archivé
AND
  - Preuve d’échec de validation schéma en audit
TEST-ID: TC-ERR-13
Référence spec: INV-297-05, CA-297-09

GIVEN
  - Erreur interne non mappée pendant la vérification formelle
WHEN
  - Calcul du verdict final
THEN
  - Verdict forcé à FAIL
  - failure_code=INTERNAL_ERROR
AND
  - Aucun chemin de succès tant que l’erreur persiste

5. Tests d’invariants (non négociables)

Invariant Test(s) dédiés Observable Commentaire
INV-297-01 TC-ERR-05, TC-NOM-05, TC-NR-01 Diff append-only, pas de mutation/suppression Prévention des régressions silencieuses.
INV-297-02 TC-NOM-02, TC-NEG-01 story_id + trace_source présents sur chaque entrée Auditabilité opposable.
INV-297-03 TC-NOM-05, TC-ERR-03 Replay identique, collision refusée Robustesse retry.
INV-297-04 TC-ERR-04 Passage obligatoire en ENRICHMENT_DEGRADED Dégradation contrôlée.
INV-297-05 TC-ERR-07, TC-ERR-08, TC-ERR-13 Erreur interne/outillage/timeout => FAIL Fail-closed.
INV-297-06 TC-NOM-04, TC-ERR-09 Scopes uniquement GO|FAIL Fermeture du trou SKIP.
INV-297-07 TC-NOM-03, TC-NEG-03 4 formalismes présents Couverture complète.
INV-297-08 TC-NOM-04, TC-NR-02 Non-régression post-enrichissement Contradictions détectables.
INV-297-09 TC-NEG-01, TC-ERR-11 États autorisés uniquement FSM fermée.
INV-297-10 TC-ERR-10, TC-NEG-05 Transitions non listées rejetées Zéro ambiguïté FSM.
INV-297-11 TC-NOM-01 Entrée unique PENDING -> EXTRACTING Démarrage déterministe.
INV-297-12 TC-NOM-03, TC-NEG-03 ENRICHED conditionné à 4 formalismes Intégrité du statut.
INV-297-13 TC-ERR-04 Timeout/erreur -> ENRICHMENT_DEGRADED Contrat de dégradation.
INV-297-14 TC-NOM-04 Non-régression GO + 3 scopes GO Validation complète.
INV-297-15 TC-ERR-06, TC-ERR-08, TC-ERR-09 FAIL/ERROR/SKIP => FAILED_BLOCKING Blocage non contournable.
INV-297-16 TC-ERR-04, TC-ERR-06 ENRICHMENT_DEGRADED -> FAILED_BLOCKING Cohérence fail-closed.
INV-297-17 TC-NOM-04 VERIFICATION_PASSED -> DONE uniquement Clôture contrôlée.
INV-297-18 TC-NOM-06, TC-NR-05 Retour unique + historique conservé Boucle de correction maîtrisée.
INV-297-19 TC-ERR-11 DONE -> * interdit Terminalité stricte.
INV-297-20 TC-ERR-02, TC-ERR-03, TC-NR-03, TC-NR-04, TC-NEG-09 Mécanismes distribués actifs Robustesse multi-runs.
INV-297-21 TC-NOM-07, TC-NEG-04 Guard clôture actif hors DONE Alignement inter-modules.
INV-297-22 Matrice §2 + §3..§9 Chaque règle couverte ou classée NON TESTABLE Contractualisation vérifiable.

6. Tests de non-régression

Test ID Objet Observable Commentaire
TC-NR-01 Conservation append-only après cycles erreur/retry Hash initial inchangé + ajouts uniquement Vérifie absence de mutation historique.
TC-NR-02 Contradiction détectée sur base étendue failure_code=NON_REGRESSION_CONTRADICTION, blocage de clôture Empêche régression logique silencieuse.
TC-NR-03 Réconciliation orpheline EXTRACTING au-delà orphan_threshold_sec => FAILED_BLOCKING Rattrapage déterministe des runs partiels.
TC-NR-04 Clearing conditionnel Levée dégradée uniquement après clearing_success_cycles_required cycles conformes Évite déblocage prématuré.
TC-NR-05 Retour correction sans perte d’historique Traces préexistantes conservées après FAILED_BLOCKING -> PENDING Non-régression d’auditabilité.

7. Tests négatifs et adversariaux

Test ID Entrée invalide / abus Résultat attendu Observable
TC-NEG-01 Campagne paramétrée D-297-01..D-297-21 invalides (regex, taille, enum, format) Rejet + FAILED_BLOCKING Rapport détaillé des champs refusés.
TC-NEG-02 Config hors bornes §5.2 (min-1 / max+1) Rejet config + FAILED_BLOCKING Journal de validation de configuration.
TC-NEG-03 Exécution avec 3 formalismes seulement ou max_formal_scopes_per_run != 3 Refus de validation enrichissement Pas de transition EXTRACTING -> ENRICHED.
TC-NEG-04 Tentative de clôture step 10 avec job_state=ENRICHED ou FAILED_BLOCKING Refus de clôture Guard cross-module tracé.
TC-NEG-05 Bypass FSM (FAILED_BLOCKING -> DONE) Rejet État inchangé + motif explicite.
TC-NEG-06 formal_scope hors enum (security) Rejet + blocage Validation D-297-05 échoue.
TC-NEG-07 job_state hors enum (RUNNING) Rejet + blocage Validation D-297-06 échoue.
TC-NEG-08 verdict hors enum (WARN) Rejet + blocage Validation D-297-07 échoue.
TC-NEG-09 Dépassement rate_limit_runs_per_min_per_story Rejet exécution (équivalent 429) Compteur de quota + refus horodaté.
TC-NEG-10 Chemins de persistance hors regex D-297-10 ou D-297-14 Rejet + blocage Contrôle chemin absolu et cible contractuelle.

8. Observabilité requise pour les tests

  • État système : job_state courant, historique transitions, état lock, compteurs rate-limit, statut réconciliation.
  • Réponse API : formal_result_json complet avec toutes clés D-297-21.
  • Journal d’audit : événements horodatés UTC, motif de décision, story_id, correlation_id, failure_code, trace_source.
  • Événement signé / horodaté : preuve d’intégrité de chaque verdict et transition.
  • Export probatoire : bundle corrélant entrées, artefacts enrichis, verdicts scopes, non-régression, transitions FSM, refus de clôture.

9. Règles non testables

Règle Raison Impact
NON TESTABLE — Routage canonique story_id -> norme (Q-297-02) La règle de dérivation métier de {norme} n’est pas formalisée (seule la regex de chemin l’est). Majeur
NON TESTABLE — Format canonique du champ details dans formal_result_json (Q-297-04) Présence obligatoire définie, structure sémantique non spécifiée. Majeur
NON TESTABLE — Versionnement inter-repo append-only en concurrence (Q-297-03) Stratégie de résolution de conflit/ordre d’écriture non contractuellement définie. Majeur
NON TESTABLE — Référence épique Jira exacte (Q-297-01) Identifiant d’épic absent des entrées spécifiées. Mineur
NON TESTABLE — Portée globale Jira Done vs ENRICHMENT_DEGRADED (Q-297-06) Guard local spécifié, politique globale Jira non détaillée dans le contrat. Majeur

10. Verdict QA

  • ✅ Testable intégralement : Non
  • ⚠️ Testable partiellement (avec réserves listées) : Oui
  • ❌ Non testable (refus contractuel) : Non