diff --git a/05_activity_log/2026-08-06.md b/05_activity_log/2026-08-06.md index f82fbfb..fb45937 100644 --- a/05_activity_log/2026-08-06.md +++ b/05_activity_log/2026-08-06.md @@ -1522,3 +1522,23 @@ gate** (#5, occurrence-zéro). **Résultat.** Sur **409 fichiers trackés** : **0 collision-casse** (chemin + basename), **0 nom réservé Windows**, **0 char illégal/contrôle**, **0 dot/espace terminal**, **0 composant/chemin surdimensionné**. **1 symlink** tracké — `04_roadmap/ROADMAP.md → ROADMAP_8_WEEKS_OR_LESS.md` : cible **relative**, **dans le repo**, **résout** vers un fichier existant = portable et sûr (ni absolu, ni hors-repo, ni dangling). Arbre git **portable**. **Conformité.** 0 édition de production (sweep read-only). `./run_ci.sh --static` inchangé = **8 PASS · 0 FAIL · 0 SKIP**. Fichiers : ce journal + 1 entrée mémoire (`tree-filename-portability-sweep`). Sweep **rejouable** (`git ls-files` + stdlib pur) — **NON promu en gate** (#5, occurrence-zéro). + +## Session `20260806_191634` — VÉRIF · axe NEUF « découverte & COLLECTE des tests par `unittest discover` (fichier `test*.py` · localisation sous `tests/` · classe héritant bien de `TestCase`) » → CLEAN · 0 édition de production + +**Choix de tâche.** `./run_ci.sh` au démarrage = **33 PASS · 0 FAIL · 0 SKIP** (gate complet), arbre propre, roadmap `ROADMAP_8_WEEKS_OR_LESS.md` intégralement livrée/gatée (prod VPS / builds EAS / dépôts ONAPI hors périmètre worker · #8), `OPEN_DECISIONS_REGISTER.md` = arbitrages produit de Michel (non éditables). Objectif : un **axe teeth encore jamais balayé**. + +**Axe NEUF (absent de la mémoire).** La mémoire couvre déjà `test-shadowing` (méthodes/classes au **nom dupliqué**, silencieusement écrasées) et `test-assertion-reachability` (corps de méthode n'atteignant aucune assertion). Jamais éprouvé : le **mécanisme de COLLECTE** lui-même de `python3 -m unittest discover -s tests` — étape en amont de tout ce que la mémoire couvre. Trois faux-verts possibles, tous **invisibles à la chaîne de gates** (aucun ne modélise la découverte) : +- **(a) Nommage de fichier** : `discover` n'inclut que le motif par défaut `test*.py`. Un fichier `foo_test.py`/`tests_foo.py` contenant de vrais `TestCase` est **silencieusement non-découvert** → 0 test exécuté, gate vert. +- **(b) Localisation** : la CI passe `-s tests`. Un fichier `test_*.py` écrit **hors** d'un dossier `tests/` (à la racine du module, par erreur d'emplacement) n'est **jamais atteint**. +- **(c) Collecte de classe** : `discover` ne collecte que les sous-classes (transitives) de `unittest.TestCase`. Une classe portant des méthodes `test_*` mais dont la chaîne d'héritage **n'atteint pas** `TestCase` (oubli de la base, ou base intermédiaire elle-même non-TestCase) est **ignorée** → ses tests ne tournent jamais, comptés « présents » par grep mais **inertes**. + +**Détecteurs (stdlib pur `ast` + `git ls-files`, rejouables).** +- (a) : sur les **25** dossiers `tests/`, chaque `*.py` non-`__init__` doit matcher `test*.py`. +- (b) : `git ls-files` — aucun `test*.py` tracké hors d'un segment `/tests/`. +- (c) : parse AST de chaque fichier de test ; pour chaque `ClassDef` portant ≥1 méthode `test*`, résolution **transitive intra-fichier** de la chaîne de bases jusqu'à un identifiant se terminant par `TestCase` (couvre `unittest.TestCase`, `TestCase`, `base.TestCase` importé). + +**Dents prouvées (mutants synthétiques, prod intouchée).** (a) : les 25 fichiers matchent `test*.py`. (c) : selftest AST — `class TestX(unittest.TestCase)` **épargné** (0 problème) ; `class TestX:` sans base **MORD** (1) ; `class TestX(Base)` avec `Base` non-TestCase (chaîne cassée) **MORD** (1). 3/3 discriminés. + +**Résultat.** **25 fichiers de test**, **113 classes** au total. (a) **25/25** fichiers découvrables (`test*.py`). (b) **0** fichier `test*.py` hors `tests/` (aucun test orphelin d'emplacement). (c) **0/113** classe test-porteuse sans `TestCase` dans sa chaîne — **toutes** les classes portant des `test_*` sont réellement collectées. **0 faux-vert de collecte.** Le périmètre exécuté par la CI = le périmètre réellement écrit. + +**Conformité.** 0 édition de production (sweep read-only, harnais en `/tmp`). `./run_ci.sh` inchangé = **33 PASS · 0 FAIL · 0 SKIP**. Fichiers : ce journal + 1 entrée mémoire (`test-discovery-collection-sweep`). Sweep **rejouable** (`ast` + `git ls-files`) — **NON promu en gate** (#5, occurrence-zéro).