PD-295 — Tests v3
1. Références
- Spécification :
PD-295-specification-v3.md - Epic :
tooling - JIRA :
PD-295
2. Matrice de couverture
| ID Invariant | ID Critère | ID Test | Couverture | Commentaire |
| INV-295-01 | CA-295-02 | TC-NOM-02, TC-NR-03 | Oui | Stack inchangée, dim 768. |
| INV-295-02 | — | TC-NR-01, TC-NR-02 | Oui | Non-régression skills + compounder. |
| INV-295-03 | CA-295-01, CA-295-03 | TC-NOM-01, TC-NOM-03 | Oui | Corpus veille + filtres. |
| INV-295-04 | CA-295-04, CA-295-05 | TC-NOM-04 | Oui | Persistance local + Ringbearer. |
| INV-295-05 | CA-295-04 | TC-NOM-05 | Oui | Verbatim + schéma clarifications. |
| INV-295-06 | CA-295-07 | TC-NOM-07 | Oui | Parallèle, source inchangée. |
| INV-295-07 | CA-295-08 | TC-NOM-07 | Oui | Formule tanh bornée. |
| INV-295-08 | CA-295-09 | TC-NOM-10 | Oui | scope présent partout. |
| INV-295-09 | CA-295-10 | TC-NOM-11, TC-NOM-11-bis | Oui | Promotions + blocage nb_domains=0. |
| INV-295-10 | CA-295-11 | TC-NOM-12 | Oui | Éviction contractuelle stricte. |
| INV-295-11 | CA-295-10 | TC-ERR-13, TC-NEG-08 | Oui | Transitions interdites rejetées. |
| INV-295-12 | CA-295-12, CA-295-13 | TC-NOM-13 | Oui | 3 sections + 5/3/3 + “aucun résultat”. |
| INV-295-13 | CA-295-14 | TC-NOM-14 | Oui | Traces par source/story/step/domain/project. |
| INV-295-14 | CA-295-06, CA-295-25 | TC-NOM-06, TC-NOM-13, TC-ERR-04 | Oui | Flags obligatoires + propagation B5. |
| INV-295-15 | CA-295-15 | TC-NOM-15, TC-NR-04 | Oui | Ordre reindex-all. |
| INV-295-16 | — | TC-ERR-08, TC-NOM-10-bis | Oui | Commit requis seulement si migration effective. |
| INV-295-17 | CA-295-20, CA-295-27 | TC-NOM-16, TC-NOM-24, TC-NOM-32 | Oui | Baseline + delta CS-1. |
| INV-295-18 | CA-295-16 | TC-NOM-17, TC-NOM-18, TC-NOM-19, TC-NOM-20, TC-ERR-09, TC-ERR-10, TC-ERR-11 | Oui | Double lock + arbitrage quota/idempotence. |
| INV-295-19 | CA-295-08 | TC-NOM-09, TC-NOM-25 | Oui | Jointure {story,gate,tag_hash} + fallback. |
| INV-295-20 | CA-295-22, CA-295-24 | TC-NOM-14, TC-NOM-26, TC-NOM-26-bis, TC-NOM-28, TC-ERR-14, TC-ERR-14-bis | Oui | Vault key + version active/archivée + fail-closed. |
| INV-295-21 | CA-295-23, CA-295-26 | TC-NOM-27, TC-NOM-27-bis, TC-ERR-14 | Oui | Purge 3 déclencheurs. |
| INV-295-22 | CA-295-21 | TC-NOM-08, TC-ERR-16 | Oui | Top3 obligatoire + observable d’échec. |
| INV-295-23 | — | TC-NEG-03 | Oui | count == len(result_ids). |
3. Scénarios de test – Flux nominaux
Préconditions communes : horloge UTC figée, fixtures versionnées, environnement isolé réinitialisé.
TEST-ID: TC-NOM-01
Référence spec: INV-295-03, CA-295-01, §5.1.2
GIVEN un lot veille valide
WHEN collecte B1 vers data/veille.jsonl
THEN nombre d’entrées identique et schéma conforme
AND aucun rejet journalisé
TEST-ID: TC-NOM-02
Référence spec: INV-295-01, CA-295-02, §5.2
GIVEN corpus veille valide
WHEN indexation B1
THEN index FAISS lisible en dim 768
AND toute autre dimension rejetée
TEST-ID: TC-NOM-03
Référence spec: INV-295-03, CA-295-03, §5.5
GIVEN index veille hétérogène
WHEN recherche --impact fort --verdict signal
THEN tous les résultats respectent les filtres
AND aucun hors filtre
TEST-ID: TC-NOM-04
Référence spec: INV-295-04, CA-295-04, CA-295-05, §5.6
GIVEN step 0 local et Ringbearer + 4 réponses PO
WHEN phase clarification se termine
THEN PD-XX-clarifications.md écrit dans les 2 modes
AND horodatage clarification <= début rédaction besoin
TEST-ID: TC-NOM-05
Référence spec: INV-295-05, §5.1.3, §5.3.1
GIVEN réponses PO UTF-8 multi-lignes
WHEN persistance + collecte JSONL clarifications
THEN Q1..Q4 conservées verbatim (égalité binaire)
AND data/clarifications.jsonl conforme au schéma canonique
TEST-ID: TC-NOM-06
Référence spec: INV-295-14, CA-295-06, §5.6
GIVEN corpus clarifications multi-domaines/projets
WHEN search-clarifications --domain D --project P
THEN exécution réussie avec résultats strictement (D,P)
AND trace source=clarification émise
TEST-ID: TC-NOM-07
Référence spec: INV-295-06, INV-295-07, CA-295-07, CA-295-08, §5.7
GIVEN hash H0 de learnings.jsonl et cas contrôlés
WHEN compute-learning-scores.py
THEN learnings-scores.jsonl écrit et hash final == H0
AND reuse_score respecte tanh(reuse_score_brut/10)
TEST-ID: TC-NOM-08
Référence spec: INV-295-22, CA-295-21, §5.7
GIVEN learnings-scores.jsonl peuplé
WHEN /morning exécuté
THEN sortie contient exactement 3 learnings top reuse_score
AND code retour = 0
TEST-ID: TC-NOM-09
Référence spec: INV-295-19, §5.1.4, §5.7
GIVEN 3 learnings et seulement 2 scores
WHEN search-learnings.py
THEN jointure par {story,gate,tag_hash}
AND learning sans score reçoit reuse_score=0.0 sans blocage
TEST-ID: TC-NOM-10
Référence spec: INV-295-08, CA-295-09, §5.8
GIVEN learnings historiques sans scope + commit préalable valide
WHEN migration B4
THEN toutes les lignes ont scope valide
AND aucune ligne sans scope
TEST-ID: TC-NOM-10-bis
Référence spec: INV-295-16, §5.8
GIVEN learnings déjà migrés (aucune ligne sans scope)
WHEN exécution B4 périodique sans nouveau commit
THEN pas de refus ERR-295-08
AND promotion/éviction continuent normalement
TEST-ID: TC-NOM-11
Référence spec: INV-295-09, CA-295-10, §5.4
GIVEN learnings aux seuils 0.29/0.30/0.59/0.60
WHEN promotion B4
THEN story->domain si score>=0.30 && nb_domains>=1
AND domain->global si score>=0.60 && nb_domains>=2
TEST-ID: TC-NOM-11-bis
Référence spec: INV-295-09, §3, §5.4
GIVEN learning avec reuse_score>=0.30 mais nb_domains=0
WHEN promotion B4
THEN aucune promotion story->domain
AND scope reste story
TEST-ID: TC-NOM-12
Référence spec: INV-295-10, CA-295-11, §5.8
GIVEN (a)57j/0inj, (b)56j/0inj, (c)57j/1inj
WHEN archivage B4
THEN seule (a) est archivée
AND (b)/(c) restent actives
TEST-ID: TC-NOM-13
Référence spec: INV-295-12, INV-295-14, CA-295-12, CA-295-13, CA-295-25, §5.9
GIVEN 3 sources disponibles, une source à count=0
WHEN injection B5 step 0
THEN bloc markdown 3 sections
AND cardinalités strictes: learnings=5, veille=3, clarifications=3
AND commande clarification observée avec --domain --project --top-k 3
AND section à count=0 affiche "aucun résultat"
TEST-ID: TC-NOM-14
Référence spec: INV-295-13, INV-295-20, CA-295-14, CA-295-22, §5.1.6
GIVEN exécution B5 avec --trace
WHEN lecture learnings-injections.jsonl
THEN 1 trace par source (learning/veille/clarification)
AND champs event,timestamp,story_id,step,source,domain,project,operation,key_version,signature présents
AND vérification HMAC valide
TEST-ID: TC-NOM-15
Référence spec: INV-295-15, CA-295-15, §5.5, §5.6
GIVEN reindex-all instrumenté
WHEN réindexation globale
THEN contracts/specs/plans avant veille/clarifications
AND ordre vérifiable en logs
TEST-ID: TC-NOM-16
Référence spec: INV-295-17, §5.7
GIVEN dataset injections + Gate 8 GO v1
WHEN analyze-compounding.py
THEN rapport ventilé par source
AND export probatoire disponible
TEST-ID: TC-NOM-17
Référence spec: INV-295-18, CA-295-16, §5.12
GIVEN B4 (EX+EX), B3 (SH+EX), B5 (SH+SH) en concurrence
WHEN exécutions parallèles
THEN ordre d’acquisition learnings->scores respecté
AND absence d’artefacts partiels
AND timeout 30s => ERR-295-09 fail-closed
TEST-ID: TC-NOM-18
Référence spec: INV-295-18, §5.9, §5.12
GIVEN 3 requêtes valides déjà acceptées dans 5 min glissantes
WHEN 4e requête step 0 soumise avec query différente
THEN rejet en premier par rate-limit (ERR-295-11)
AND idempotence n’est évaluée qu’après quota valide
TEST-ID: TC-NOM-19
Référence spec: INV-295-18, §5.12
GIVEN rejet quota pour story A
WHEN requête story B dans même fenêtre
THEN story B non impactée (isolation quota)
AND si quota OK, idempotence fonctionne normalement
TEST-ID: TC-NOM-20
Référence spec: INV-295-18, §5.12
GIVEN orphelins > orphan_threshold
WHEN job réconciliation
THEN MEMORY_DEGRADED + rattrapage
AND retour MEMORY_HEALTHY après 2 cycles conformes
TEST-ID: TC-NOM-21
Référence spec: CA-295-17, §7 bis
GIVEN fenêtre T+90j post-B5
WHEN measure-cs2.sh --window 90d
THEN CS-2 calculé selon formule contractuelle
AND valeur >= 30%
TEST-ID: TC-NOM-22
Référence spec: CA-295-18, §7 bis
GIVEN fenêtre mensuelle glissante
WHEN measure-cs3.sh
THEN occurrences clarification réutilisée calculées
AND valeur >= 1/mois
TEST-ID: TC-NOM-23
Référence spec: CA-295-19, §7 bis
GIVEN 5 premières stories post-B5
WHEN measure-cs4.sh
THEN nb stories avec veille impact fort|modere injectée calculé
AND valeur >= 5/5
TEST-ID: TC-NOM-24
Référence spec: CA-295-20, INV-295-17
GIVEN date merge B5 + 10 stories pré + 10 post (fixture)
WHEN measure-cs1-baseline.py + calcul CS-1
THEN baseline gelée pré-B5
AND delta CS-1 calculé reproductiblement
TEST-ID: TC-NOM-25
Référence spec: INV-295-19, §3, §5.1.5
GIVEN tags réordonnés équivalents
WHEN calcul tag_hash + jointure scores
THEN tag_hash identique et learning_id stable
AND tri secondaire par reuse_score déterministe
TEST-ID: TC-NOM-26
Référence spec: INV-295-20, CA-295-22
GIVEN événements B1..B5 signés
WHEN vérification avec clé Vault active
THEN toutes signatures valides
AND key_version active cohérente
TEST-ID: TC-NOM-26-bis
Référence spec: INV-295-20, §5.1.6
GIVEN événement historique signé avec key_version archivée
WHEN vérification audit
THEN vérificateur charge la clé depuis kv/pd-295/memory-audit-hmac/archive/{date}
AND signature valide
TEST-ID: TC-NOM-27
Référence spec: INV-295-21, CA-295-23
GIVEN clarifications à 17/18/19 mois
WHEN purge-clarifications.py via step 10
THEN 19 mois purgé
AND 17/18 mois conservés (règle >18)
TEST-ID: TC-NOM-27-bis
Référence spec: INV-295-21, CA-295-26
GIVEN stories REJECTED et DONE_WITH_ANOMALY + cron actif
WHEN hook on_story_close puis cron quotidien
THEN purge déclenchée dans les deux cas
AND traces distinctes des 3 déclencheurs (step10/hook/cron)
TEST-ID: TC-NOM-28
Référence spec: §5.4, CA-295-24, INV-295-20
GIVEN learning en archive
WHEN restore-learning.py --id <learning_id>
THEN learning restauré scope=story
AND événement audit signé avec key_version Vault
TEST-ID: TC-NOM-29
Référence spec: CA-295-17, §7 bis
GIVEN datasets learnings pré-B5 + injections fenêtre 90j
WHEN measure-cs2.sh
THEN formule CS-2 appliquée strictement
AND résultat reproductible
TEST-ID: TC-NOM-30
Référence spec: CA-295-18, §7 bis
GIVEN événements clarifications sur 30j glissants
WHEN measure-cs3.sh
THEN formule CS-3 appliquée strictement
AND stories contributrices listées
TEST-ID: TC-NOM-31
Référence spec: CA-295-19, §7 bis
GIVEN 5 premières stories post-B5 identifiées
WHEN measure-cs4.sh
THEN formule CS-4 appliquée strictement
AND résultat >=5/5 requis
TEST-ID: TC-NOM-32
Référence spec: CA-295-27, INV-295-17
GIVEN baseline CS-1 gelée + 10 stories post-B5 réelles
WHEN calcul production CS-1
THEN CS-1 > 0
AND méthode identique à TC-NOM-24
4. Scénarios de test – Cas d’erreur
TEST-ID: TC-ERR-01
Référence spec: ERR-295-01
GIVEN story/domain/project invalide
WHEN exécution commande
THEN rejet explicite + zéro écriture
TEST-ID: TC-ERR-02
Référence spec: ERR-295-02, §5.1.3
GIVEN clarification frontmatter invalide
WHEN collecte/indexation
THEN fichier ignoré + log explicite
TEST-ID: TC-ERR-03
Référence spec: ERR-295-03
GIVEN enum invalide
WHEN ingestion/recherche
THEN rejet/exclusion selon contexte
TEST-ID: TC-ERR-04
Référence spec: ERR-295-04, INV-295-14
GIVEN search-clarifications sans --domain ou --project
WHEN exécution
THEN rejet non exécutable
TEST-ID: TC-ERR-05
Référence spec: ERR-295-05
GIVEN 1 source indisponible, 2 disponibles
WHEN B5 step 0
THEN injection partielle maintenue + trace dégradée
TEST-ID: TC-ERR-06
Référence spec: ERR-295-06
GIVEN 3 sources indisponibles
WHEN B5 step 0
THEN blocage explicite
TEST-ID: TC-ERR-07
Référence spec: ERR-295-07
GIVEN learnings-scores.jsonl absent
WHEN promotion B4
THEN promotion désactivée + scopes inchangés
TEST-ID: TC-ERR-08
Référence spec: ERR-295-08, INV-295-16
GIVEN migration scope requise sans commit préalable
WHEN B4
THEN refus migration + aucun fichier modifié
TEST-ID: TC-ERR-09
Référence spec: ERR-295-09, INV-295-18
GIVEN lock requis non obtenable en 30s
WHEN opération critique
THEN fail-closed explicite + aucun effet de bord
TEST-ID: TC-ERR-10
Référence spec: ERR-295-10
GIVEN même clé idempotence + query_hash différent
WHEN rejeu dans fenêtre idempotence
THEN rejet conflit + pas de doublon
TEST-ID: TC-ERR-11
Référence spec: ERR-295-11
GIVEN quota 3/5min glissantes déjà atteint
WHEN nouvelle requête step 0
THEN rejet quota explicite
TEST-ID: TC-ERR-11-bis
Référence spec: ERR-295-18
GIVEN réponses PO incomplètes
WHEN po_question_timeout atteint
THEN step 0 interrompu
TEST-ID: TC-ERR-12
Référence spec: ERR-295-12
GIVEN échec écriture trace
WHEN injection B5
THEN injection maintenue + observabilité dégradée
TEST-ID: TC-ERR-13
Référence spec: INV-295-11, §5.4
GIVEN transition interdite demandée
WHEN exécution
THEN rejet explicite + état inchangé
TEST-ID: TC-ERR-14
Référence spec: ERR-295-13, INV-295-20
GIVEN signature absente/invalide ou key_version incohérente
WHEN vérification audit
THEN événement rejeté + alerte audit
TEST-ID: TC-ERR-14-bis
Référence spec: ERR-295-16, INV-295-20
GIVEN Vault indisponible au démarrage
WHEN commande /gov nécessitant audit est lancée
THEN fail-closed ERR-295-16
AND aucun événement audit n’est émis
TEST-ID: TC-ERR-15
Référence spec: ERR-295-15
GIVEN restore-learning.py --id absent/invalide
WHEN exécution
THEN rejet explicite + aucun mouvement archive/actif
TEST-ID: TC-ERR-16
Référence spec: ERR-295-19, INV-295-22
GIVEN /morning ne peut produire 3 entrées (fichier vide/incomplet)
WHEN exécution
THEN échec explicite (code retour !=0) avec ERR-295-19
5. Tests d’invariants (non négociables)
| Invariant | Test(s) dédiés | Observable |
| INV-295-01 | TC-NOM-02, TC-NR-03 | Dim 768 + stack |
| INV-295-02 | TC-NR-01, TC-NR-02 | Non-régression |
| INV-295-03 | TC-NOM-01, TC-NOM-03 | Corpus + filtres |
| INV-295-04 | TC-NOM-04 | Persistance tous modes |
| INV-295-05 | TC-NOM-05 | Verbatim |
| INV-295-06 | TC-NOM-07 | Fichier parallèle |
| INV-295-07 | TC-NOM-07 | Formule tanh |
| INV-295-08 | TC-NOM-10 | Scope partout |
| INV-295-09 | TC-NOM-11, TC-NOM-11-bis | Promotion non vacuous |
| INV-295-10 | TC-NOM-12 | Éviction story |
| INV-295-11 | TC-ERR-13, TC-NEG-08 | Rejet transitions interdites |
| INV-295-12 | TC-NOM-13 | 3 sections + 5/3/3 |
| INV-295-13 | TC-NOM-14 | Traces complètes |
| INV-295-14 | TC-NOM-06, TC-NOM-13, TC-ERR-04 | Flags obligatoires + propagation |
| INV-295-15 | TC-NOM-15 | Ordre reindex |
| INV-295-16 | TC-ERR-08, TC-NOM-10-bis | Commit requis si migration effective |
| INV-295-17 | TC-NOM-16, TC-NOM-24, TC-NOM-32 | CS-1 + ventilation |
| INV-295-18 | TC-NOM-17, TC-NOM-18, TC-NOM-19, TC-NOM-20, TC-ERR-09, TC-ERR-10, TC-ERR-11 | Locks + quota + idempotence |
| INV-295-19 | TC-NOM-09, TC-NOM-25 | Jointure canonique + fallback |
| INV-295-20 | TC-NOM-14, TC-NOM-26, TC-NOM-26-bis, TC-NOM-28, TC-ERR-14, TC-ERR-14-bis | Vault/HMAC/version |
| INV-295-21 | TC-NOM-27, TC-NOM-27-bis, TC-ERR-14 | Rétention multi-déclencheurs |
| INV-295-22 | TC-NOM-08, TC-ERR-16 | /morning top3 observable |
| INV-295-23 | TC-NEG-03 | count/result_ids cohérents |
6. Tests de non-régression
| Test ID | Objet | Observable |
| TC-NR-01 | 4 skills recherche existants | Contrat E/S inchangé |
| TC-NR-02 | gov-compounder compatible ascendant | Exécution historique sans erreur |
| TC-NR-03 | Stack non migrée | Aucun artefact hors stack |
| TC-NR-04 | reindex-all conserve phases historiques | contracts/specs/plans avant nouvelles phases |
7. Tests négatifs et adversariaux
| Test ID | Entrée invalide / abus | Résultat attendu | Observable |
| TC-NEG-01 | source_path veille traversal (../../x.md) | Ligne exclue + log | Index propre |
| TC-NEG-02 | Casse invalide (pd-295, Tooling) | Rejet ERR-295-01 | Zéro écriture |
| TC-NEG-03 | count>0 avec result_ids[] vide | Événement ignoré | audit_inconsistent_trace |
| TC-NEG-04 | query > 500 chars | Rejet ERR-295-17 | Erreur explicite |
| TC-NEG-05 | scope=team | Rejet migration/promotion | Scope inchangé |
| TC-NEG-06 | Âge exactement 56 jours, 0 injection | Pas d’archivage | Entrée active |
| TC-NEG-07 | reuse_score=0.299 puis 0.300 | Pas de promotion puis promotion | Seuil binaire |
| TC-NEG-08 | Tentative DOMAIN_ACTIVE -> STORY_ACTIVE auto | Rejet | État inchangé |
| TC-NEG-09 | Saturation quota story A | Story B non impactée | Isolation |
| TC-NEG-10 | Rejeu après fenêtre idempotence | Accepté comme nouvelle tentative | Nouvelle trace |
| TC-NEG-11 | Lockfile orphelin mtime>60s | Nettoyage puis acquisition | Séquence cohérente |
| TC-NEG-12 | Coefficients B3 différents de 0.40/0.40/0.20 | Rejet config | Erreur explicite |
| TC-NEG-13 | Même clé idempotence, payload altéré | ERR-295-10 | Conflit détecté |
| TC-NEG-14 | Signature HMAC altérée | Rejet audit | ERR-295-13 |
| TC-NEG-15 | restore-learning.py sans --id | Rejet argument | Aucun mouvement d’état |
| TC-NEG-16 | Modification tags historique (dérive learning_id) | Exclusion scoring | learning_id_drift |
8. Observabilité requise pour les tests
- État système : hash avant/après
learnings.jsonl, learnings-scores.jsonl, learnings-archive.jsonl, état mémoire (MEMORY_DEGRADED/HEALTHY), état locks. - Réponse CLI : code retour,
ERR-295-xx, message explicite, timestamp UTC. - Journal audit : événements RFC3339 UTC avec
story_id, step, source, operation, key_version. - Signature :
signature_hmac_sha256 valide ; clé Vault lue via kv/pd-295/memory-audit-hmac, archive vérifiée pour versions historiques. - Export probatoire : fixtures hashées, sorties, logs, rapport compounding, baseline CS-1, résultats CS-⅔/4.
9. Règles non testables
| Règle | Raison | Impact |
| CA-295-17 | Horizon T+90j réel | Vérification continue |
| CA-295-18 | Fenêtre mensuelle réelle | Vérification continue |
| CA-295-19 | Dépend des 5 premières stories réelles post-B5 | Vérification continue |
| CA-295-27 | Dépend de 10 stories post-B5 réelles | Vérification continue |
10. Verdict QA
- Gate 8 : testable sur invariants techniques, sécurité audit Vault, et contrat d’orchestration.
- Post-merge : CS-⅔/4 suivis en continu, CS-1 recalculé sur fenêtre glissante.
Changelog v2→v3
- G3v2-B1 : ajout TC-NOM-26-bis et TC-ERR-14-bis ; TC-NOM-26/TC-ERR-14 alignés sur Vault + key_version.
- G3v2-M1 : ajout TC-NOM-11-bis (blocage promotion si
nb_domains==0). - G3v2-M2 : TC-NOM-13 durci avec cardinalité clarifications = 3.
- G3v2-M3 : ajout TC-NOM-29/30/31 pour formules CS-2/CS-3/CS-4.
- G3v2-M4 : TC-NOM-17 étendu aux locks B3 sur deux lockfiles.
- G3v2-M5 : TC-NOM-13 vérifie propagation
--domain --project --top-k 3. - G3v2-M6 : ajout TC-NOM-27-bis (purge via hook
on_story_close + cron). - G3v2-M7 : TC-NOM-18 + TC-ERR-11 valident arbitrage rate-limit avant idempotence.
- G3v2-M8 : TC-NOM-05 vérifie le schéma
data/clarifications.jsonl. - G3v2-M9 : TC-NOM-28 vérifie que restore utilise la même politique clé Vault.
- G3v2-M10 : TC-NEG-04 aligné sur
ERR-295-17 QUERY_TOO_LONG. - G3v2-M11 : TC-NEG-03 aligné sur
count == len(result_ids) avec log audit_inconsistent_trace. - Corrections mineures intégrées : TC-NOM-10-bis (migration one-shot), TC-ERR-16 (
/morning observable), TC-NEG-12 rendu atteignable, TC-NEG-16 (dérive learning_id).