PD-295 — Scénarios de tests contractuels
1. Références
- Spécification : PD-295-specification.md
- Epic : EPIC-XX (non communiqué dans la spécification au 2026-04-12)
2. Matrice de couverture
| ID Invariant | ID Critère | ID Test | Couverture | Commentaire |
| INV-295-01 | CA-295-01 | TC-NOM-01 | Oui | Scan contractuel + robustesse non bloquante |
| INV-295-02 | CA-295-02 | TC-NOM-02 | Oui | Conformité modèle de données veille |
| INV-295-03 | CA-295-03 | TC-NOM-03 | Oui | Verbatim brut des 4 réponses PO |
| INV-295-04 | CA-295-04 | TC-NOM-04 | Oui | Indexation clarifications JSONL + FAISS |
| INV-295-05 | CA-295-05 | TC-NOM-05 | Oui | Formule reuse_score exacte 0.4/0.4/0.2 |
| INV-295-06 | CA-295-06 | TC-NOM-06 | Oui | Jointure {story,gate,tags_hash} univoque |
| INV-295-07 | CA-295-07 | TC-NOM-07 | Oui | Tri secondaire reuse_score |
| INV-295-08 | CA-295-08 | TC-NOM-08 | Oui | Migration initiale scope: story |
| INV-295-09 | CA-295-09 | TC-NOM-09, TC-NOM-16 | Oui | Seuil promotion story→domain |
| INV-295-10 | CA-295-09 | TC-NOM-09, TC-NOM-16 | Oui | Seuil promotion domain→global |
| INV-295-11 | CA-295-10 | TC-NOM-10, TC-NOM-16 | Oui | Règle stale >56j + nb_injections==0 |
| INV-295-12 | CA-295-11 | TC-NOM-11 | Oui | Archive absente de l’index actif |
| INV-295-13 | CA-295-12 | TC-NOM-12 | Oui | Bloc 3 sections, cardinalités max 5/3/3 |
| INV-295-14 | CA-295-13 | TC-NOM-13, TC-ERR-06 | Oui | aucun résultat sans blocage |
| INV-295-15 | CA-295-14 | TC-NOM-14, TC-ERR-04, TC-ERR-05, TC-ERR-09 | Oui | Erreur source non bloquante |
| INV-295-16 | CA-295-17 | TC-NOM-15, TC-NR-03, TC-NR-04 | Oui | Stack contractuelle + exclusions hors périmètre |
| INV-295-TR-01 | CA-295-09 | TC-NOM-16 | Oui | STORY_ACTIVE → DOMAIN_ACTIVE autorisée |
| INV-295-TR-02 | CA-295-15 | TC-ERR-07 | Oui | STORY_ACTIVE → GLOBAL_ACTIVE interdite |
| INV-295-TR-03 | CA-295-10 | TC-NOM-16 | Oui | STORY_ACTIVE → ARCHIVED autorisée si stale |
| INV-295-TR-04 | CA-295-15 | TC-ERR-07 | Oui | DOMAIN_ACTIVE → STORY_ACTIVE interdite |
| INV-295-TR-05 | CA-295-09 | TC-NOM-16 | Oui | DOMAIN_ACTIVE → GLOBAL_ACTIVE autorisée |
| INV-295-TR-06 | CA-295-10 | TC-NOM-16 | Oui | DOMAIN_ACTIVE → ARCHIVED autorisée si stale |
| INV-295-TR-07 | CA-295-15 | TC-ERR-07 | Oui | GLOBAL_ACTIVE → DOMAIN_ACTIVE interdite |
| INV-295-TR-08 | CA-295-15 | TC-ERR-07 | Oui | GLOBAL_ACTIVE → STORY_ACTIVE interdite |
| INV-295-TR-09 | CA-295-10 | TC-NOM-16 | Oui | GLOBAL_ACTIVE → ARCHIVED autorisée si stale |
| INV-295-TR-10 | CA-295-16 | TC-ERR-11 | Oui | ARCHIVED → STORY_ACTIVE interdite |
| INV-295-TR-11 | CA-295-16 | TC-ERR-11 | Oui | ARCHIVED → DOMAIN_ACTIVE interdite |
| INV-295-TR-12 | CA-295-16 | TC-ERR-11 | Oui | ARCHIVED → GLOBAL_ACTIVE interdite |
| INV-295-TR-13 | CA-295-16 | TC-ERR-11 | Oui | ARCHIVED terminal (→ * interdit) |
3. Scénarios de test – Flux nominaux
TEST-ID: TC-NOM-01
Référence spec: INV-295-01, CA-295-01
GIVEN
- Corpus de test fixe dans `ProbatioVault-doc/docs/veille/` avec 3 fiches valides et 2 invalides
WHEN
- Le flux B1 d’indexation veille est exécuté
THEN
- Le scan couvre le motif `ProbatioVault-doc/docs/veille/**/*.md`
- `data/veille.jsonl` contient exactement 3 lignes
AND
- Les 2 fiches invalides sont ignorées, journalisées sur stderr, sans arrêt global
TEST-ID: TC-NOM-02
Référence spec: INV-295-02, CA-295-02
GIVEN
- `data/veille.jsonl` produit depuis un corpus valide
WHEN
- Validation contractuelle des champs §5.1 (regex/enums/tailles)
THEN
- 100% des lignes passent les contraintes D-295 applicables à la veille
AND
- Aucune ligne invalide n’est acceptée silencieusement
TEST-ID: TC-NOM-03
Référence spec: INV-295-03, CA-295-03
GIVEN
- Step 0 avec exactement 4 réponses PO verbatim (chaînes sentinelles connues)
WHEN
- B2 persistance clarifications est exécuté
THEN
- Le fichier `PD-XX-clarifications.md` est créé dans le dossier epic de la story
- Les 4 réponses y sont présentes en verbatim brut, sans résumé ni filtrage
AND
- L’ordre des réponses est conservé
TEST-ID: TC-NOM-04
Référence spec: INV-295-04, CA-295-04
GIVEN
- Un fichier `PD-XX-clarifications.md` valide déjà persisté
WHEN
- L’indexation clarifications est exécutée
THEN
- `data/clarifications.jsonl` est présent
- L’index FAISS clarifications est présent
AND
- Une recherche `/clarifications --domain --project` retrouve la clarification persistée
TEST-ID: TC-NOM-05
Référence spec: INV-295-05, CA-295-05
GIVEN
- Dataset déterministe:
L1: `nb_injections=2`, `nb_stories_gate8_go_apres_injection=1`, `nb_domains_distincts=3`
L2: `nb_injections=0`, `nb_stories_gate8_go_apres_injection=2`, `nb_domains_distincts=1`
WHEN
- B3 calcule les scores
THEN
- `reuse_score(L1)=1.8` et `reuse_score(L2)=1.0`
AND
- Les coefficients appliqués sont exactement 0.4/0.4/0.2
TEST-ID: TC-NOM-06
Référence spec: INV-295-06, CA-295-06
GIVEN
- `learnings.jsonl` et `data/learnings-scores.jsonl` avec clés de jointure contrôlées
WHEN
- Jointure `{story,gate,tags_hash}` est évaluée
THEN
- Chaque ligne score référence exactement 1 learning
AND
- Aucune correspondance 0 ou multiple n’est tolérée
TEST-ID: TC-NOM-07
Référence spec: INV-295-07, CA-295-07
GIVEN
- Deux learnings avec similarité identique et `reuse_score` différents (0.8 vs 0.6)
WHEN
- Recherche learnings est exécutée
THEN
- Le learning `reuse_score=0.8` est classé avant `0.6`
AND
- La différence d’ordre est observable dans la liste retournée
TEST-ID: TC-NOM-08
Référence spec: INV-295-08, CA-295-08
GIVEN
- Corpus historique avec entrées mixtes: avec et sans champ `scope`
WHEN
- Migration initiale B4 est exécutée
THEN
- 100% des entrées sans `scope` deviennent `scope: story`
AND
- Les entrées déjà typées conservent leur scope initial
TEST-ID: TC-NOM-09
Référence spec: INV-295-09, INV-295-10, CA-295-09
GIVEN
- 4 learnings:
S1 `scope=story`, `reuse_score=0.29`
S2 `scope=story`, `reuse_score=0.30`
D1 `scope=domain`, `reuse_score=0.59`
D2 `scope=domain`, `reuse_score=0.60`
WHEN
- Promotion B4 est exécutée
THEN
- S2 passe `story→domain`, S1 reste `story`
- D2 passe `domain→global`, D1 reste `domain`
AND
- Les seuils sont appliqués strictement à 0.3 et 0.6
TEST-ID: TC-NOM-10
Référence spec: INV-295-11, CA-295-10
GIVEN
- 4 learnings:
A `age=57j`, `nb_injections=0`
B `age=56j`, `nb_injections=0`
C `age=57j`, `nb_injections=1`
D `age=10j`, `nb_injections=0`
WHEN
- Éviction B4 est exécutée
THEN
- Seul A est déplacé vers `learnings-archive.jsonl`
AND
- B, C, D ne sont pas archivés
TEST-ID: TC-NOM-11
Référence spec: INV-295-12, CA-295-11
GIVEN
- Un learning archivé fortement pertinent + un learning actif faiblement pertinent
WHEN
- Injection step 0 interroge l’index actif
THEN
- Le learning archivé n’apparaît jamais dans les résultats
AND
- Le learning actif peut apparaître
TEST-ID: TC-NOM-12
Référence spec: INV-295-13, CA-295-12
GIVEN
- Corpus où chaque source retourne plus que la limite (>=7 résultats)
WHEN
- Injection unifiée B5 est exécutée
THEN
- Le bloc Markdown contient exactement 3 sections (learnings, veille, clarifications)
- Les cardinalités effectives sont limitées à 5/3/3
AND
- Aucune 4e section n’est produite
TEST-ID: TC-NOM-13
Référence spec: INV-295-14, CA-295-13
GIVEN
- Source clarifications valide mais sans hit
WHEN
- Injection B5 est exécutée
THEN
- La section clarifications affiche exactement `aucun résultat`
AND
- Le step 0 se termine sans blocage
TEST-ID: TC-NOM-14
Référence spec: INV-295-15, CA-295-14
GIVEN
- Source veille en erreur technique (ex: dépendance indisponible)
WHEN
- Injection B5 est exécutée
THEN
- La section veille est vide
- Une erreur est tracée sur stderr
AND
- Le step 0 continue et rend le bloc Markdown
TEST-ID: TC-NOM-15
Référence spec: CA-295-17
GIVEN
- La spécification canonique PD-295
WHEN
- Contrôle documentaire de la section 10 est effectué
THEN
- Les mentions Python, FAISS, Ollama, Markdown, YAML sont présentes
AND
- Les technologies Swift et Spring sont absentes
TEST-ID: TC-NOM-16
Référence spec: INV-295-TR-01, INV-295-TR-03, INV-295-TR-05, INV-295-TR-06, INV-295-TR-09, CA-295-09, CA-295-10
GIVEN
- Matrice de 5 learnings:
T1 `story`, `reuse_score=0.30`
T2 `story`, `age=57j`, `nb_injections=0`
T3 `domain`, `reuse_score=0.60`
T4 `domain`, `age=57j`, `nb_injections=0`
T5 `global`, `age=57j`, `nb_injections=0`
WHEN
- Moteur de transitions B4 est exécuté
THEN
- T1: `story→domain` autorisée
- T2: `story→archived` autorisée
- T3: `domain→global` autorisée
- T4: `domain→archived` autorisée
- T5: `global→archived` autorisée
AND
- Chaque transition autorisée modifie le scope attendu
4. Scénarios de test – Cas d’erreur
TEST-ID: TC-ERR-01
Référence spec: ERR-295-01
GIVEN
- Un lot mixte de lignes valides + 1 ligne invalide au format §5.1
WHEN
- Le traitement de la source est exécuté
THEN
- La ligne invalide est rejetée
- Un message est tracé sur stderr
AND
- Les lignes valides continuent d’être traitées
TEST-ID: TC-ERR-02
Référence spec: ERR-295-02
GIVEN
- Une fiche veille avec frontmatter incomplet dans le corpus
WHEN
- B1 indexation veille est exécuté
THEN
- La fiche invalide est ignorée
AND
- L’indexation des autres fiches continue
TEST-ID: TC-ERR-03
Référence spec: ERR-295-03
GIVEN
- `learnings-injections.jsonl` absent ou inaccessible
WHEN
- B3 scoring est exécuté
THEN
- Le scoring est calculé avec le corpus disponible
- Un log stderr est produit
AND
- Les learnings sans historique exploitable sont traités avec score absent équivalent à 0 en usage aval
TEST-ID: TC-ERR-04
Référence spec: ERR-295-04
GIVEN
- Échec Ollama (timeout 30000 ms ou indisponibilité) sur une source
WHEN
- Injection B5 est exécutée
THEN
- La section de la source en échec est vide
- Erreur consignée sur stderr
AND
- Step 0 reste non bloqué
TEST-ID: TC-ERR-05
Référence spec: ERR-295-05
GIVEN
- Index FAISS d’une source absent ou corrompu
WHEN
- Injection B5 est exécutée
THEN
- La section de la source concernée est vide
- Erreur consignée sur stderr
AND
- Step 0 reste non bloqué
TEST-ID: TC-ERR-06
Référence spec: ERR-295-06
GIVEN
- Source valide retournant 0 résultat
WHEN
- Injection B5 est exécutée
THEN
- La section correspondante affiche exactement `aucun résultat`
AND
- Aucun échec de workflow n’est déclenché
TEST-ID: TC-ERR-07
Référence spec: ERR-295-07, INV-295-TR-02, INV-295-TR-04, INV-295-TR-07, INV-295-TR-08, CA-295-15
GIVEN
- Tentatives de transitions interdites:
`story→global`, `domain→story`, `global→domain`, `global→story`
WHEN
- Le moteur de transitions est sollicité
THEN
- Chaque transition est refusée
- Le scope reste inchangé
AND
- Un refus explicite est journalisé sur stderr
TEST-ID: TC-ERR-08
Référence spec: ERR-295-08
GIVEN
- Paramètres hors bornes contractuelles §5.2 (ex: `top_k_learnings_step0=4`, `embedding_dimension=769`)
WHEN
- Validation de conformité contractuelle est exécutée
THEN
- Verdict de conformité = KO
AND
- Aucune tolérance implicite n’est appliquée
TEST-ID: TC-ERR-09
Référence spec: ERR-295-09
GIVEN
- Écriture `PD-XX-clarifications.md` impossible (droits/path)
WHEN
- B2 persistance est exécuté
THEN
- Erreur consignée sur stderr
- Aucune clarification n’est persistée
AND
- Step 0 continue sans blocage
TEST-ID: TC-ERR-10
Référence spec: ERR-295-10
GIVEN
- Une ligne score dont `{story,gate,tags_hash}` ne correspond à aucun learning
WHEN
- Scoring/promotion est exécuté
THEN
- Le learning non jointable est exclu du calcul et de la promotion
AND
- Un log explicite est émis sur stderr
TEST-ID: TC-ERR-11
Référence spec: INV-295-TR-10, INV-295-TR-11, INV-295-TR-12, INV-295-TR-13, CA-295-16
GIVEN
- Learning en état `ARCHIVED`
WHEN
- Tentatives de sortie: `archived→story`, `archived→domain`, `archived→global`
THEN
- Toutes les transitions sortantes sont refusées
- Le scope reste `archived`
AND
- Le caractère terminal est explicitement observable dans les traces
5. Tests d’invariants (non négociables)
| Invariant | Test(s) dédiés | Observable | Commentaire |
| INV-295-01 | TC-NOM-01, TC-ERR-02 | Scan du chemin contractuel + ignore invalides sans arrêt | Non-bloquant validé |
| INV-295-02 | TC-NOM-02 | 1 fiche valide -> 1 ligne JSONL conforme | Conformité §5.1 |
| INV-295-03 | TC-NOM-03 | 4 verbatims bruts persistés | Sans résumé/filtrage |
| INV-295-04 | TC-NOM-04 | clarifications.jsonl + index FAISS présents | Réutilisation possible |
| INV-295-05 | TC-NOM-05 | Scores exacts calculés | Coefficients stricts |
| INV-295-06 | TC-NOM-06, TC-ERR-10 | Jointure univoque par clé | Exclusion si impossible |
| INV-295-07 | TC-NOM-07 | Ordre secondaire par score | Similarité égale contrôlée |
| INV-295-08 | TC-NOM-08 | Entrées sans scope migrées en story | 100% attendu |
| INV-295-09 | TC-NOM-09, TC-NOM-16 | Promotion story→domain au seuil | Refus sous seuil |
| INV-295-10 | TC-NOM-09, TC-NOM-16 | Promotion domain→global au seuil | Refus sous seuil |
| INV-295-11 | TC-NOM-10, TC-NOM-16 | Archivage seulement stale + inj=0 | Condition conjonctive stricte |
| INV-295-12 | TC-NOM-11 | Archive absente de l’index actif | Éviction effective |
| INV-295-13 | TC-NOM-12 | Bloc 3 sections, cardinalités 5/3/3 max | Contrat B5 |
| INV-295-14 | TC-NOM-13, TC-ERR-06 | aucun résultat affiché | Step 0 non bloqué |
| INV-295-15 | TC-NOM-14, TC-ERR-04, TC-ERR-05, TC-ERR-09 | Section vide + stderr | Step 0 non bloqué |
| INV-295-16 | TC-NR-04 | Mécanismes exclus absents du périmètre PD-295 | Anti-régression |
| INV-295-TR-01 | TC-NOM-16 | story→domain acceptée à >=0.3 | Transition autorisée |
| INV-295-TR-02 | TC-ERR-07 | story→global refusée | Transition interdite |
| INV-295-TR-03 | TC-NOM-16 | story→archived acceptée si stale | Transition autorisée |
| INV-295-TR-04 | TC-ERR-07 | domain→story refusée | Transition interdite |
| INV-295-TR-05 | TC-NOM-16 | domain→global acceptée à >=0.6 | Transition autorisée |
| INV-295-TR-06 | TC-NOM-16 | domain→archived acceptée si stale | Transition autorisée |
| INV-295-TR-07 | TC-ERR-07 | global→domain refusée | Transition interdite |
| INV-295-TR-08 | TC-ERR-07 | global→story refusée | Transition interdite |
| INV-295-TR-09 | TC-NOM-16 | global→archived acceptée si stale | Transition autorisée |
| INV-295-TR-10 | TC-ERR-11 | archived→story refusée | Terminal |
| INV-295-TR-11 | TC-ERR-11 | archived→domain refusée | Terminal |
| INV-295-TR-12 | TC-ERR-11 | archived→global refusée | Terminal |
| INV-295-TR-13 | TC-ERR-11 | archived→* interdit | Terminal absolu |
6. Tests de non-régression
| Test ID | Objet | Observable | Commentaire |
| TC-NR-01 | Absence de migration moteur de stockage | Aucun artefact de migration moteur requis pour PD-295 | Conforme hors périmètre |
| TC-NR-02 | Aucune refonte pipeline hors B1..B5 | Les flux historiques hors B1..B5 restent inchangés au smoke test | Non-régression fonctionnelle |
| TC-NR-03 | Stack cible section 10 respectée | Présence Python/FAISS/Ollama/Markdown/YAML, absence Swift/Spring | Couvre CA-295-17 |
| TC-NR-04 | Mécanismes explicitement exclus restent hors périmètre | Aucun comportement PD-295 n’introduit HMAC/Vault/JCS/PII filter/RGPD purge/etc. listés en exclusion | Couvre INV-295-16 |
| TC-NR-05 | Archive reste exclue après réindexation complète | Un learning archivé ne revient pas dans les résultats actifs | Renforce INV-295-12 |
7. Tests négatifs et adversariaux
| Test ID | Entrée invalide / abus | Résultat attendu | Observable |
| TC-NEG-01 | Batterie d’entrées invalides D-295-01..D-295-17 (regex, enum, tailles, types) | Rejet/exclusion stricts selon colonne “Invalide” §5.1 | Logs stderr + absence des entrées invalides dans artefacts |
| TC-NEG-02 | Valeurs hors bornes sur chaque paramètre figé §5.2 | Erreur de conformité contractuelle (KO) | Verdict de test KO, aucune tolérance implicite |
| TC-NEG-03 | Frontières stale: age=56, age=57, nb_injections=0/1 | Seul age>56 ET nb_injections==0 archive | Diff scope avant/après exécution |
| TC-NEG-04 | clarification_filename invalide ou clarification_verbatim taille 0/>20000 | Persistance refusée | Absence de fichier/ligne + stderr |
| TC-NEG-05 | Dimension embedding != 768 | Indexation rejetée | Erreur explicite + index non publié |
8. Observabilité requise pour les tests
- État système : présence/absence et contenu de
data/veille.jsonl, data/clarifications.jsonl, data/learnings-scores.jsonl, learnings-archive.jsonl, index FAISS actifs. - Réponse API : sortie step 0 observable avec bloc Markdown à 3 sections, statut de continuation en cas d’erreur source.
- Journal d’audit : traces stderr horodatées avec identifiant de cas d’erreur et motif de rejet/exclusion.
- Événement signé / horodaté : horodatage requis; signature d’événement NON APPLICABLE dans le contrat PD-295 actuel.
- Export probatoire : archive de campagne contenant fixtures, sorties JSONL/Markdown, logs stderr, et verdicts de conformité.
9. Règles non testables
| Règle | Raison | Impact |
Politique de tie-break final si similarité et reuse_score sont strictement égaux | Non spécifiée en §10.2 (Q-295-03), donc ordre total non contractualisé | Majeur |
Enum exacte des valeurs autorisées pour project (D-295-04) | Type “Enum” déclaré sans liste explicite des valeurs | Majeur |
| Reproductibilité CS-1 post-merge | Fenêtre baseline non définie (Q-295-02) | Majeur |
Procédure de “résolution manuelle” depuis ARCHIVED | Mentionnée mais non spécifiée opérationnellement; seule l’interdiction automatique est testable | Mineur |
10. Verdict QA