1. Objectif
La User Story PD-296 DOIT imposer une vérification formelle systématique aux points critiques du workflow /gov, avec un effet bloquant non contournable en cas d’échec, afin de garantir que les artefacts produits restent conformes aux invariants formels (Prolog, Alloy, TLA+, Z) sur toutes les stories et tous les projets ProbatioVault.
2. Périmètre / Hors périmètre
Inclus
- Intégration obligatoire des contrôles formels aux checkpoints suivants :
STEP1_SPEC_COHERENCE (après step 1), STEP4_CONTRACTS_FORMAL (après step 4), GATE5_PLAN_FORMAL (pré-Gate 5), STEP6_CODE_FORMAL (après step 6c), GATE8_FINAL_FORMAL (pré-Gate 8). - Effet bloquant sur la transition de step/gate en cas d’échec.
- Règle constitutionnelle Article VIII (obligatoire, non skippable).
- Application sans filtre de domaine ou de type de story.
- Contrats de format des données de vérification formelle.
- Contrats de concurrence et idempotence pour exécutions simultanées
/gov.
Exclu
- Création d’un nouveau modèle formel.
- Refonte de
ProbatioVault-formal. - Optimisation de performance des moteurs formels.
- Changement du job CI GitLab
tla-verify. - Toute règle non testable : hors périmètre.
3. Définitions
| Terme | Définition |
| Checkpoint formel | Point du workflow où un contrôle formel est obligatoire. |
| FAIL_CLOSED | Échec bloquant par défaut si outil indisponible, timeout ou erreur technique. |
| Gate bloquée | Impossibilité de passer au step/gate suivant tant que le checkpoint n’est pas PASSED. |
| Checkpoint ID | Identifiant canonique d’un contrôle (STEP1_SPEC_COHERENCE, etc.). |
Vérification coherence | Contrôle inter-EB via Prolog sur la cohérence des besoins/specs. |
Vérification formal-verify | Pipeline formel multi-modèles (Prolog, Alloy, TLA+, Z selon scope). |
| Transition retour | Retour explicite d’un état de blocage vers un état relançable. |
| État terminal | État sans sortie autorisée ; toute sortie doit être explicitement interdite. |
| Idempotence | Même clé + même payload => même résultat sans effet secondaire. |
| Réconciliation | Détection/rattrapage des exécutions orphelines en cas de crash/interruption. |
4. Invariants (non négociables)
| ID | Règle | Justification |
| INV-296-01 | Chaque story DOIT exécuter exactement 5 checkpoints formels (cf. §5.2). | Couverture complète demandée. |
| INV-296-02 | Après sauvegarde de PD-XX-specification.md, STEP1_SPEC_COHERENCE est obligatoire avant step 2. | Contradictions détectées au niveau spec. |
| INV-296-03 | Après sauvegarde de PD-XX-plan.md + code-contracts.yaml, STEP4_CONTRACTS_FORMAL est obligatoire avant Gate 5. | Alignement plan/contracts/invariants. |
| INV-296-04 | /gov-check-plan DOIT inclure GATE5_PLAN_FORMAL (phase formelle) avant soumission Gate 5. | Vérification pré-verdict. |
| INV-296-05 | Après step 6c, STEP6_CODE_FORMAL est obligatoire avant step 7. | Conformité du code aux invariants formels. |
| INV-296-06 | Dans /gov-accept, après Phase 2 (reviews LLM), GATE8_FINAL_FORMAL est obligatoire avant Gate 8. | Dernier filet de sécurité. |
| INV-296-07 | Si verdict d’un checkpoint = FAIL, transition aval = BLOQUÉE. | Échec bloquant exigé. |
| INV-296-08 | Outil formel indisponible, erreur runtime ou timeout => FAIL (fail-closed). | Non-contournement de la garantie. |
| INV-296-09 | Aucune transition Jira vers Done n’est autorisée si un FAIL formel reste non corrigé. | Contrainte constitutionnelle. |
| INV-296-10 | L’obligation s’applique à tous les projets (backend, app, site, infra, doc, formal, pixel-governance, ia-governance). | Arbitrage PO “sans exception”. |
| INV-296-11 | Article VIII “Vérification formelle” DOIT être présent dans CONSTITUTIONAL.md et référencé dans CLAUDE.md. | Constitutionnalisation explicite. |
| INV-296-12 | États de checkpoint autorisés: PENDING, RUNNING, PASSED, FAILED_BLOCKING uniquement. | FSM testable et fermée. |
| INV-296-13 | Toute transition non listée en §5.4 est INTERDITE. | Élimination des ambiguïtés de transition. |
| INV-296-14 | Le payload de résultat DOIT respecter le contrat D-296-14. | Traçabilité machine-readable. |
| INV-296-15 | Les protections distribuées §5.6 sont obligatoires en exécution concurrente. | Robustesse multi-runs /gov. |
| INV-296-16 | Toute donnée invalide selon §5.1 entraîne rejet du checkpoint et blocage de progression. | Intégrité des entrées. |
| INV-296-17 | Aucun mode “warning only”, “informative only” ou “skip” n’est autorisé pour les checkpoints formels. | Échec = bloquant non négociable. |
| INV-296-18 | Toutes les règles ci-dessus sont testables via critères §7 et scénarios §8. | Exigence contractuelle de testabilité. |
5. Flux nominaux
| ID | Donnée | Format / encodage | Taille | Jeu de caractères | Case | Regex / contrainte | Si invalide |
| D-296-01 | story_id | String UTF-8 | 4..11 | [A-Z0-9-] | Sensitive | ^PD-[0-9]{1,4}$ | Rejet + FAILED_BLOCKING |
| D-296-02 | project_code | Enum string UTF-8 | 3..16 | [a-z-] | Sensitive | ^(backend|app|site|infra|doc|formal|pixel-governance|ia-governance)$ | Rejet + FAILED_BLOCKING |
| D-296-03 | checkpoint_id | Enum string ASCII | 20..28 | [A-Z0-9_] | Sensitive | ^(STEP1_SPEC_COHERENCE|STEP4_CONTRACTS_FORMAL|GATE5_PLAN_FORMAL|STEP6_CODE_FORMAL|GATE8_FINAL_FORMAL)$ | Rejet + FAILED_BLOCKING |
| D-296-04 | trigger_event | Enum string ASCII | 9..24 | [A-Z0-9_] | Sensitive | ^(SPEC_SAVED|PLAN_AND_CONTRACTS_SAVED|CHECK_PLAN_PHASE4_START|STEP6C_DONE|GOV_ACCEPT_PHASE2_DONE)$ | Rejet + FAILED_BLOCKING |
| D-296-05 | check_scope | Enum string ASCII | 13..16 | [a-z_] | Sensitive | ^(coherence_spec|formal_contracts|formal_plan|formal_code|formal_full)$ | Rejet + FAILED_BLOCKING |
| D-296-06 | checkpoint_state | Enum string ASCII | 7..15 | [A-Z_] | Sensitive | ^(PENDING|RUNNING|PASSED|FAILED_BLOCKING)$ | Rejet + FAILED_BLOCKING |
| D-296-07 | verdict | Enum string ASCII | 2..4 | [A-Z] | Sensitive | ^(GO|FAIL)$ | Rejet + FAILED_BLOCKING |
| D-296-08 | blocking | Bool JSON | n/a | true|false | n/a | FAIL => blocking=true (obligatoire) | Rejet + FAILED_BLOCKING |
| D-296-09 | failure_code | Enum string ASCII | 11..21 | [A-Z_] | Sensitive | ^(NONE|CONTRADICTION_DETECTED|MODEL_VIOLATION|TOOL_UNAVAILABLE|TIMEOUT|INPUT_INVALID|CONCURRENT_RUN|INTERNAL_ERROR)$ | Rejet + FAILED_BLOCKING |
| D-296-10 | artifact_path | Path POSIX absolu UTF-8 | 1..512 | UTF-8 printable sans contrôle | Sensitive | ^/Users/loic/Developpement/ProbatioVault/ProbatioVault-[a-z-]+/.+$ | Rejet + FAILED_BLOCKING |
| D-296-11 | idempotency_key | Hex SHA-256 lowercase | 64 chars | [a-f0-9] | Sensitive | ^[a-f0-9]{64}$ | Rejet + FAILED_BLOCKING |
| D-296-12 | correlation_id | UUID v4 | 36 chars | [a-f0-9-] | Sensitive | ^[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89ab][a-f0-9]{3}-[a-f0-9]{12}$ | Rejet + FAILED_BLOCKING |
| D-296-13 | timestamp_utc | RFC3339 UTC | 20..30 chars | ASCII | Sensitive | horodatage parseable UTC (Z ou offset) | Rejet + FAILED_BLOCKING |
| D-296-14 | formal_check_result_json | Objet JSON UTF-8 | 120..10000 bytes | Clés ASCII, valeurs UTF-8 | Clés sensitive | Clés requises: story_id, project_code, checkpoint_id, check_scope, checkpoint_state, verdict, blocking, failure_code, idempotency_key, correlation_id, timestamp_utc, details | Rejet + FAILED_BLOCKING |
| D-296-15 | details[] | Array JSON de strings UTF-8 | 0..200 éléments | UTF-8 printable | Sensitive | item 1..500 chars | Rejet + FAILED_BLOCKING |
Référencement unique : toutes les sections suivantes réutilisent ces IDs (D-296-*) sans redéfinir les formats.
5.2 Bornes numériques contractuelles
| Paramètre | Défaut | Min | Max | Unité | Contexte de référence | Percentile | Hors bornes |
mandatory_checkpoints_per_story | 5 | 5 | 5 | checkpoints | Workflow /gov | n/a | Erreur de conformité, workflow bloqué |
mandatory_gates_formal | 3 | 3 | 3 | gates | Gates ⅗/8 | n/a | Erreur de conformité, workflow bloqué |
formal_timeout_sec | 180 | 30 | 180 | secondes | Exécution locale /gov (poste dev, hors CI) | P95 | FAIL + blocage checkpoint |
formal_retry_on_failure | 0 | 0 | 0 | tentatives auto | Tous checkpoints | n/a | Toute valeur ≠0 rejetée, fail-closed |
distributed_lock_ttl_sec | 600 | 60 | 1800 | secondes | Exécution concurrente multi-runs | n/a | Rejet config + blocage |
idempotency_window_h | 24 | 1 | 168 | heures | Déduplication checkpoints | n/a | Rejet config + blocage |
reconciliation_interval_sec | 300 | 60 | 900 | secondes | Scanner d’orphelins | n/a | Rejet config + blocage |
orphan_threshold_sec | 900 | 180 | 3600 | secondes | Détection exécution bloquée | n/a | Rejet config + blocage |
rate_limit_checks_per_min_per_story | 3 | 1 | 10 | checks/min/story | Protection moteur formel | n/a | Rejet de requête (équivalent 429) |
clearing_success_cycles_required | 2 | 1 | 10 | cycles conformes | Levée état dégradé | n/a | Rejet config + blocage |
5.3 SLA temporels (transitions)
| SLA | Défaut | Min | Max | Configurabilité | Comportement à expiration |
sla_step1_spec_coherence_timeout | 180s | 30s | 180s | Oui | RUNNING -> FAILED_BLOCKING, step 2 interdit |
sla_step4_contracts_formal_timeout | 180s | 30s | 180s | Oui | RUNNING -> FAILED_BLOCKING, Gate 5 interdite |
sla_gate5_plan_formal_timeout | 180s | 30s | 180s | Oui | RUNNING -> FAILED_BLOCKING, verdict Gate 5 interdit |
sla_step6_code_formal_timeout | 180s | 30s | 180s | Oui | RUNNING -> FAILED_BLOCKING, step 7 interdit |
sla_gate8_final_formal_timeout | 180s | 30s | 180s | Oui | RUNNING -> FAILED_BLOCKING, Gate 8 interdite |
Aucune autre transition temporelle identifiée.
5.4 Machine d’états des checkpoints (transitions retour explicites)
États officiels : PENDING, RUNNING, PASSED, FAILED_BLOCKING.
État PENDING
| Transition sortante | Statut | Raison / condition | Comportement |
PENDING -> RUNNING | AUTORISÉE | trigger_event valide (D-296-04) | Démarre le contrôle |
PENDING -> PASSED | INTERDITE | Verdict absent | Rejet |
PENDING -> FAILED_BLOCKING | INTERDITE | Échec sans exécution | Rejet |
État RUNNING
| Transition sortante | Statut | Raison / condition | Comportement |
RUNNING -> PASSED | AUTORISÉE | verdict=GO (D-296-07) | Déverrouille transition aval |
RUNNING -> FAILED_BLOCKING | AUTORISÉE | verdict=FAIL ou timeout ou indisponibilité | Bloque gate/step aval |
RUNNING -> PENDING | INTERDITE | Retour sans verdict interdit | Rejet |
État PASSED (terminal)
| Transition sortante | Statut | Raison / condition | Comportement |
PASSED -> * | INTERDITE | État terminal | état terminal, résolution manuelle uniquement |
État FAILED_BLOCKING
| Transition sortante | Statut | Raison / condition | Comportement |
FAILED_BLOCKING -> PENDING | AUTORISÉE | Artefact corrigé puis nouvel événement déclencheur | Données conservées, relance obligatoire |
FAILED_BLOCKING -> RUNNING | INTERDITE | Bypass du déclencheur | Rejet |
FAILED_BLOCKING -> PASSED | INTERDITE | Preuve formelle manquante | Rejet |
Comportement au retour/downgrade FAILED_BLOCKING -> PENDING : - Les détails d’échec (D-296-15) sont conservés. - Les verrouillages aval restent actifs jusqu’à passage PASSED. - Le rate-limit et l’idempotence sont réappliqués immédiatement. - Aucune suppression de données historiques.
Checklist machine à états : - [x] Chaque état liste ses transitions sortantes autorisées/interdites. - [x] État terminal explicite : PASSED -> * : INTERDITE. - [x] Modèle couvert par invariants dédiés (INV-296-12, INV-296-13).
5.5 Flux nominaux par checkpoint
- Flux F-296-01 — Step 1 (spec)
- Déclencheur :
SPEC_SAVED (D-296-04) sur PD-XX-specification.md (D-296-10). - Checkpoint :
STEP1_SPEC_COHERENCE (D-296-03), scope coherence_spec (D-296-05). - Résultat :
GO => step 2 autorisé. -
FAIL => step 2 bloqué, contradictions affichées (D-296-15).
-
Flux F-296-02 — Step 4 (plan + contracts)
- Déclencheur :
PLAN_AND_CONTRACTS_SAVED. - Checkpoint :
STEP4_CONTRACTS_FORMAL, scope formal_contracts. - Résultat :
GO => éligible pré-Gate 5. -
FAIL => Gate 5 bloquée.
-
Flux F-296-03 — Pré-Gate 5 (/gov-check-plan Phase 4)
- Déclencheur :
CHECK_PLAN_PHASE4_START. - Checkpoint :
GATE5_PLAN_FORMAL, scope formal_plan. - Résultat :
GO => soumission Gate 5 autorisée. -
FAIL => verdict Gate 5 interdit.
-
Flux F-296-04 — Step 6 (code)
- Déclencheur :
STEP6C_DONE. - Checkpoint :
STEP6_CODE_FORMAL, scope formal_code. - Résultat :
GO => step 7 autorisé. -
FAIL => step 7 bloqué, boucle correction step 6.
-
Flux F-296-05 — Pré-Gate 8 (/gov-accept)
- Déclencheur :
GOV_ACCEPT_PHASE2_DONE. - Checkpoint :
GATE8_FINAL_FORMAL, scope formal_full. - Résultat :
GO => soumission Gate 8 autorisée. FAIL => Gate 8 bloquée, clôture interdite.
5.6 Mécanismes de protection distribuée (obligatoire)
| Mécanisme | Contrat |
| Lock distribué | Scope story_id + checkpoint_id; TTL=distributed_lock_ttl_sec; si lock non acquis => failure_code=CONCURRENT_RUN, FAIL bloquant |
| Idempotence | Clé idempotency_key (D-296-11) par payload; fenêtre=idempotency_window_h; replay identique => même résultat; replay clé identique + payload différent => rejet |
| Réconciliation | Scan toutes reconciliation_interval_sec; run RUNNING > orphan_threshold_sec => FAILED_BLOCKING (failure_code=INTERNAL_ERROR) |
| Rate-limiting | rate_limit_checks_per_min_per_story; dépassement => rejet de contrôle (pas de progression) |
| Clearing conditionnel | État dégradé levé après clearing_success_cycles_required cycles PASSED consécutifs |
Checklist protection distribuée : - [x] Lock : scope + TTL + comportement lock non acquis définis. - [x] Idempotence : clé + durée de déduplication définies. - [x] Réconciliation : intervalle + seuil orphelin + rattrapage définis. - [x] Rate-limit : granularité story + quota + rejet définis. - [x] Clearing : nombre de cycles conformes + comptage définis.
5.7 Contraintes inter-modules
| Élément | Contrat |
| Modules/commandes à protéger | /gov-step (steps 1,4,6), /gov-check-plan (phase 4), /gov-accept (post phase 2), /gov-gate (G3/G5/G8) |
| Mécanisme de protection | Guard formel bloquant avant transition aval |
| Données nécessaires cross-module | story_id (D-296-01), checkpoint_id (D-296-03), état courant Jira/FSM, artefact(s) source (D-296-10) |
| Résolution de liaison cross-module | Mapping déterministe step/gate -> checkpoint_id (F-296-01..05) |
| Scope d’enregistrement du guard | Enregistrement local aux commandes listées ; pas de guard global hors workflow /gov |
| Exceptions d’accès | Aucune exception de rôle ; aucun bypass humain autorisé sur échec formel |
5.8 Clauses obligatoires “non applicables”
- Stratégie de migration DDL : non applicable (aucune modification de colonne SQL).
- Atomicité multi-composant DB + queue/append-only : non applicable (pas de flux DB+queue dans PD-296).
- Invariant envelope encryption crypto : non applicable (domaine
tooling/governance, pas crypto/crypto-proof).
5bis. Diagrammes (si applicable)
Diagramme d’état (>= 3 états)
stateDiagram-v2
[*] --> PENDING
PENDING --> RUNNING: trigger_event valide
PENDING --> PASSED: INTERDITE
PENDING --> FAILED_BLOCKING: INTERDITE
RUNNING --> PASSED: verdict=GO
RUNNING --> FAILED_BLOCKING: verdict=FAIL|timeout|tool_unavailable
RUNNING --> PENDING: INTERDITE
FAILED_BLOCKING --> PENDING: correction artefact + relance
FAILED_BLOCKING --> RUNNING: INTERDITE (retrigger requis)
FAILED_BLOCKING --> PASSED: INTERDITE (preuve manquante)
PASSED --> PENDING: INTERDITE (etat terminal)
PASSED --> RUNNING: INTERDITE (etat terminal)
PASSED --> FAILED_BLOCKING: INTERDITE (etat terminal)
PASSED --> [*]
Diagramme de séquence (flow multi-services)
sequenceDiagram
participant GS as /gov-step
participant CO as /coherence
participant FV as /formal-verify
participant GCP as /gov-check-plan
participant GA as /gov-accept
participant GG as /gov-gate
participant FSM as FSM/Jira
GS->>GS: save(PD-XX-specification.md)
GS->>CO: check(predicates(spec_markdown))
CO-->>GS: formal_check_result_json{checkpoint=STEP1_SPEC_COHERENCE, verdict}
alt verdict=FAIL
GS->>FSM: block step1->step2
else verdict=GO
GS->>FSM: allow step1->step2
end
GS->>GS: save(PD-XX-plan.md + code-contracts.yaml)
GS->>FV: verify(invariants(spec) + contracts_yaml + plan_constraints_graph)
FV-->>GS: formal_check_result_json{checkpoint=STEP4_CONTRACTS_FORMAL, verdict}
alt verdict=FAIL
GS->>FSM: block Gate 5
else verdict=GO
GCP->>FV: verify(plan_constraints_graph)
FV-->>GCP: formal_check_result_json{checkpoint=GATE5_PLAN_FORMAL, verdict}
GCP->>FSM: allow_or_block Gate 5
end
GS->>FV: verify(extract_facts(code_ast) + model_checks)
FV-->>GS: formal_check_result_json{checkpoint=STEP6_CODE_FORMAL, verdict}
GS->>FSM: allow_or_block step6->step7
GA->>FV: verify_full(extract_facts(code_ast) + TLA+ + Prolog + Alloy + Z)
FV-->>GA: formal_check_result_json{checkpoint=GATE8_FINAL_FORMAL, verdict}
alt verdict=FAIL
GA->>FSM: block Gate 8
else verdict=GO
GA->>GG: submit Gate 8
GG->>FSM: continue verdict process
end
6. Cas d’erreur
| ID | Cas | Réponse attendue |
| ERR-296-01 | story_id invalide (D-296-01) | Rejet immédiat, FAILED_BLOCKING, progression interdite |
| ERR-296-02 | checkpoint_id invalide (D-296-03) | Rejet immédiat, FAILED_BLOCKING |
| ERR-296-03 | Payload résultat non conforme D-296-14 | Rejet, failure_code=INTERNAL_ERROR, blocage |
| ERR-296-04 | Contradiction détectée par checkpoint spec | verdict=FAIL, blocage step 2 |
| ERR-296-05 | Échec formel contracts/plan | verdict=FAIL, blocage Gate 5 |
| ERR-296-06 | Échec formel code | verdict=FAIL, blocage step 7 |
| ERR-296-07 | Échec formel final | verdict=FAIL, blocage Gate 8 |
| ERR-296-08 | Outil formel indisponible | verdict=FAIL, failure_code=TOOL_UNAVAILABLE, fail-closed |
| ERR-296-09 | Timeout checkpoint | verdict=FAIL, failure_code=TIMEOUT, fail-closed |
| ERR-296-10 | Lock non acquis (concurrence) | verdict=FAIL, failure_code=CONCURRENT_RUN, blocage checkpoint |
| ERR-296-11 | Collision idempotence (même clé, payload différent) | Rejet de la relance, blocage |
| ERR-296-12 | Tentative de bypass/force passage | Rejet explicite, maintien blocage, traçabilité obligatoire |
| ERR-296-13 | Tentative Jira Done avec échec formel ouvert | Transition interdite, statut inchangé |
7. Critères d’acceptation (testables)
| ID | Critère | Observable |
| CA-296-01 | coherence est exécuté après step 0 ET step 1 | Logs/session montrent deux exécutions distinctes |
| CA-296-02 | formal-verify est exécuté après step 4, pré-Gate 5, après step 6, pré-Gate 8 | 4 checkpoints formal_* présents dans traces |
| CA-296-03 | Échec formel bloque la gate/le step concerné | Transition aval absente tant que verdict=FAIL |
| CA-296-04 | Mode fail-closed effectif si outil indisponible | TOOL_UNAVAILABLE entraîne blocage |
| CA-296-05 | Article VIII présent dans CONSTITUTIONAL.md | Texte article détectable et exact |
| CA-296-06 | CLAUDE.md référence Article VIII | Table constitutionnelle mise à jour |
| CA-296-07 | Une story de chaque projet cible déclenche les checkpoints formels | Exécution observée sur backend/app/site/infra au minimum |
| CA-296-08 | Aucune clôture Jira Done avec échec formel ouvert | Transition Done refusée dans ce cas |
| CA-296-09 | Concurrence contrôlée par lock + idempotence | Double déclenchement simultané ne crée pas double run |
| CA-296-10 | Timeouts appliqués selon §5.3 | Dépassement => FAILED_BLOCKING systématique |
| CA-296-11 | Résultat checkpoint respecte D-296-14 | Validation schéma réussie sur chaque run |
| CA-296-12 | /gov-check-plan inclut phase formelle pré-Gate 5 | Phase dédiée visible avant verdict Gate 5 |
8. Scénarios de test (Given / When / Then)
- Given une spec sauvegardée, When checkpoint
STEP1_SPEC_COHERENCE retourne GO, Then step 2 est autorisé. - Given une spec sauvegardée, When checkpoint
STEP1_SPEC_COHERENCE retourne FAIL, Then step 2 est bloqué et la liste des contradictions est visible. - Given plan + code-contracts sauvegardés, When
STEP4_CONTRACTS_FORMAL retourne FAIL, Then Gate 5 est bloquée. - Given
/gov-check-plan en phase 4, When GATE5_PLAN_FORMAL retourne FAIL, Then aucun verdict Gate 5 n’est soumis. - Given step 6c terminé, When
STEP6_CODE_FORMAL retourne FAIL, Then step 7 est interdit jusqu’à correction et relance. - Given
/gov-accept phase 2 terminée, When GATE8_FINAL_FORMAL retourne FAIL, Then Gate 8 est bloquée. - Given moteur formel indisponible, When un checkpoint est déclenché, Then résultat
FAIL avec TOOL_UNAVAILABLE et blocage immédiat. - Given deux déclenchements concurrents sur même
story_id + checkpoint_id, When le second démarre, Then il est rejeté (CONCURRENT_RUN). - Given une relance avec même
idempotency_key et même payload, When elle est rejouée, Then le résultat est identique sans double exécution. - Given une story avec échec formel non résolu, When transition Jira vers
Done est tentée, Then la transition est refusée. - Given une story projet
app ou site, When workflow /gov atteint les checkpoints, Then les mêmes contrôles formels s’exécutent (pas d’exception projet). - Given timeout dépassé sur un checkpoint, When la fenêtre SLA expire, Then état
RUNNING -> FAILED_BLOCKING et progression aval interdite.
9. Hypothèses explicites
| ID | Hypothèse | Impact si faux |
| H-296-01 | Les sorties /coherence et /formal-verify sont mappables sans ambiguïté vers verdict=GO|FAIL. | Contrat D-296-14 non tenable sans adaptateur explicite. |
| H-296-02 | Le workflow conserve data/fsm.yaml comme source de vérité des transitions. | Les points de blocage doivent être redéfinis. |
| H-296-03 | Le nommage des artefacts suit PD-XX-* comme en workflow actuel. | Déclencheurs automatiques non déterministes. |
| H-296-04 | L’environnement d’exécution dispose des dépendances formelles nécessaires. | Multiplication des TOOL_UNAVAILABLE et blocage systématique. |
10. Points à clarifier
10.1 Contraintes techniques (stack projet cible)
- Projet cible de la story :
ProbatioVault-ia-governance. - Stack réelle du projet cible :
- Scripts
Shell (bash/zsh) pour orchestration workflow, Python 3 pour scripts d’indexation/traitement gouvernance, - Artefacts
Markdown, YAML, JSON, - Composant
Node.js (mcp-signal) pour intégration MCP Signal. - Dépendance externe de vérification formelle (repo
ProbatioVault-formal) : Python, SWI-Prolog, TLA+, Alloy, Z. - Contrainte explicite : aucune substitution de stack (pas de Swift/SwiftUI, pas de Spring Boot) n’est autorisée pour ce projet.
10.2 Questions ouvertes
| ID | Question | Impact |
| Q-296-01 | Référence épique exacte non fournie (nom Jira parent). | Traçabilité référence incomplète. |
| Q-296-02 | La sortie canonique commune GO|FAIL est-elle imposée nativement ou via mapping (STOP -> FAIL) ? | Validation D-296-14 à verrouiller. |
| Q-296-03 | Le mode “force” existant en escalade gate est-il explicitement interdit pour les échecs formels ? | Risque de contournement de l’Article VIII. |
| Q-296-04 | Quelle clé de configuration porte les timeouts §5.3 (nommage exact) ? | Test d’administration/config non finalisable. |
| Q-296-05 | Matériel de référence exact pour mesure P95 des timeouts non fourni. | Comparabilité des métriques perf limitée. |
| Q-296-06 | Le wrapper scripts/formal-check.sh est-il obligatoire ou optionnel contractuellement ? | Variantes d’intégration possibles à harmoniser. |
| Q-296-07 | Le workflow doit-il créer un statut Jira dédié aux échecs formels ou réutiliser les statuts existants ? | Consistance FSM/Jira à confirmer. |
Références
- Epic : non fournie dans l’entrée (donnée manquante).
- JIRA :
PD-296. - Repos concernés :
ProbatioVault-ia-governance, ProbatioVault-formal, et stories cibles backend/app/site/infra/doc/formal. - Documents associés :
docs/epics/tooling/PD-296-formal-verification-integration/PD-296-besoin.md governance/CONSTITUTIONAL.md CLAUDE.md .claude/commands/gov.md .claude/commands/gov-step.md .claude/commands/gov-gate.md .claude/commands/gov-check-plan.md .claude/commands/gov-accept.md .claude/commands/coherence.md .claude/commands/formal-verify.md