Défaut #1 (bug CI réel) : ci/check_regression.sh exigeait regression_run.json commité comme baseline, mais le fichier était .gitignore → absent en checkout propre → le job Gitea check-regression échouait sur CHAQUE run CI (ne passait qu'en local via un fichier non suivi). L'artefact run est byte-déterministe (aucun horodatage/hôte/durée · path relatif) → committer est licite. Fix : run désormais commité (baseline), .gitignore + README réécrits. Défaut #2 (invariant manquant) : coverage_report prouvait CI→disque mais pas l'inverse. Nouveau disk_test_modules() + orphan_tests_dirs dans INV4 : un module gagnant un tests/ sans job CI fait chuter la couverture (fini la sous-comptée silencieuse de la matrice). Schéma + 2 tests de morsure. Consommateur régénéré : qa/audit_4big/quality_report.json (README 3710→4236 o, 24→26 méthodes). Matrice 534/21/PASS inchangée (harnais self-exclu, INV3). 5 gates verts · 26+34 tests OK · YAML valide.
4.9 KiB
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 queqa/regression/out/regression_run.jsonexiste dans le dépôt, puis compare unrunfrais à 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 Giteacheck-regressionne fait quecheckout+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'unregression_run.jsonnon suivi laissé par unrunmanuel. Le commentaire deci.ymldisait 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
runest byte-déterministe — clés{ran,passed,failures,...}+pathrelatif, aucun horodatage/hôte/ durée. Deuxrunsuccessifs byte-identiques (vérifié). Le committer est donc licite et complète l'intention du gate. - Fix :
runest désormais commité (baseline du gate) →.gitignore: retrait deout/regression_run.json+ note expliquant qu'il est commité parce que déterministe ;README.md: sectionrunréécrite (byte-déterministe · commité · baselinecheck_regression· distinction d'aveccheck_artifactsqui ne rejoue quebuild) ;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_reportprouvait le sens CI→disque (tout module gated a untests/) mais pas l'inverse : un module gagnant untests/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 untests/(POSIX, trié, déterministe) ;coverage_report: champorphan_tests_dirs = disk − ci_paths;okexige désormaisnot orphan_tests_dirs;regression.schema.json:orphan_tests_dirsajouté (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.