# Activity Log · 2026-07-31 · Claude Code DTP ## Session `20260731_002924` · Buffer S8 · Intégrité de la matrice de régression (bug CI réel + invariant disque→CI) **Tâche** : **Sprint 8 · buffer L75 (« Regression tests exhaustifs » · DevOps CI/CD)** — roadmap fonctionnellement close (21/21 modules gated à 100/100, 534 tests verts, 5 gates statiques). Recherche d'une **incohérence de reproductibilité réelle** plutôt qu'un correctif doc cosmétique. **Deux** défauts réels trouvés et corrigés, tous deux dans `qa/regression`. ### Défaut #1 (PRIORITAIRE · bug CI réel) — le gate `check-regression` était cassé en checkout propre - **Symptôme** : `ci/check_regression.sh` (l.52-53) **exige** que `qa/regression/out/regression_run.json` **existe dans le dépôt**, puis compare un `run` frais à ce fichier commité (baseline byte-identique). - **Contradiction** : ce même fichier était **`.gitignore`é** (« non déterministe (temps machine) → jamais commitée ») → **jamais présent dans un checkout propre**. Le job Gitea `check-regression` ne fait que `checkout` + `bash check_regression.sh`, **aucune étape ne génère** le fichier. **Conséquence** : le gate **échouait sur CHAQUE run CI propre** (`artefact absent du dépôt`). Il ne « passait » qu'en local, par la présence d'un `regression_run.json` **non suivi** laissé par un `run` manuel. Le commentaire de `ci.yml` disait déjà « le regression_run.json **commité** » — intention claire du commit précédent, jamais concrétisée (fichier resté ignoré). - **Vérif de faisabilité (#1 analyser)** : l'artefact `run` est **byte-déterministe** — clés `{ran,passed,failures,...}` + `path` **relatif**, **aucun** horodatage/hôte/ durée. Deux `run` successifs **byte-identiques** (vérifié). Le committer est donc **licite** et complète l'intention du gate. - **Fix** : `run` est désormais **commité** (baseline du gate) → - `.gitignore` : retrait de `out/regression_run.json` + note expliquant qu'il est commité *parce que* déterministe ; - `README.md` : section `run` réécrite (byte-déterministe · commité · baseline `check_regression` · distinction d'avec `check_artifacts` qui ne rejoue que `build`) ; - `out/regression_run.json` : **ajouté au suivi** (21 suites · 534 tests · PASS). - **Preuve de morsure** : fichier retiré (simule checkout propre) ⇒ gate **exit 1** (`artefact absent`) — l'état exact en CI ; restauré ⇒ **exit 0** (`run == commité`). ### Défaut #2 (invariant manquant) — dérive silencieuse disque→CI non gardée - **Gap** : `discovery.coverage_report` prouvait le sens **CI→disque** (tout module gated a un `tests/`) mais **pas l'inverse** : un module gagnant un `tests/` sur disque **sans job CI** n'entrait jamais dans la matrice, ses tests **ne tournaient jamais**, et la couverture ne le voyait pas (elle n'itère que les suites dérivées du CI) — la matrice restait « PASS » en **sous-comptant** en silence. Même classe de dérive que « demo 18→21 », direction opposée. - **Fix** : nouvel invariant **INV4** — - `discovery.disk_test_modules()` : marche disque pure listant tout module portant un `tests/` (POSIX, trié, déterministe) ; - `coverage_report` : champ `orphan_tests_dirs = disk − ci_paths` ; `ok` exige désormais `not orphan_tests_dirs` ; - `regression.schema.json` : `orphan_tests_dirs` ajouté (required · strict) ; - `regression_gen.py` : message INV4 surface les orphelins ; - `tests/test_regression.py` : +2 tests (sous-ensemble disque⊆CI sur le dépôt réel ; preuve de morsure monkeypatch d'un orphelin ⇒ `ok=False`). - **Preuve de morsure end-to-end** : `mkdir zz_orphan/tests` + `build` ⇒ **build refusé** `INV4 … orphan_tests_dirs=['zz_orphan']` ; répertoire retiré ⇒ build OK. **Anti-invention (#6)** : rien inventé — les deux gates **régénèrent** la vérité (run frais / couverture recomputée) au lieu de figer un compteur. **Régénération des consommateurs (mémoire projet)** : l'édition des tests + du README de `qa/regression` a fait dériver `qa/audit_4big/out/quality_report.json` (evidence « README.md 3710→4236 octets » et « 24→26 méthodes test_* ») — **régénéré**, verdict **PASS · 21/21 · min 100**. Totaux matrice **534/21** **inchangés** : le harnais `qa/regression` est **self-exclu** (INV3) → +2 méthodes test_* n'affectent pas la matrice. **Vérifs** : **5 gates** locaux verts (`guard_constraints`/`validate_json`/`check_docs`/ `check_artifacts`/`check_regression`) ; `ci.yml` **YAML valide** ; tests harnais **26/26 OK** (régression) + **34/34 OK** (audit_4big) ; matrice **534/534 · 21/21 · PASS** ; artefacts `out/` reproductibles à l'identique. **Hors périmètre worker (VPS · #8)** : néant (stdlib pur en-repo ; enregistrement du runner Gitea toujours du ressort DevOps). **Auto-score 4Big** : 96/100.