diff --git a/05_activity_log/2026-07-31.md b/05_activity_log/2026-07-31.md index 7047331..aa1c534 100644 --- a/05_activity_log/2026-07-31.md +++ b/05_activity_log/2026-07-31.md @@ -1,5 +1,77 @@ # Activity Log · 2026-07-31 · Claude Code DTP +## Session `20260731_015954` · Buffer S8 · « Vert trompeur » : les 6 gates `ci/*.sh` passaient VERT hors d'un arbre git en ne contrôlant RIEN + +**Tâche** : **Sprint 8 · buffer L75 (« Regression tests exhaustifs » · DevOps +CI/CD)**. Roadmap fonctionnellement close (21/21 modules 100/100, 534 tests verts, +6 gates statiques). Poursuite de la série anti-dérive : recherche d'un **faux-vert +réel** (gate qui passe sans rien vérifier), même classe que les bugs +`regression_run.json` / `out/` RBAC des sessions précédentes. + +### Défaut trouvé — `cd "$(git rev-parse --show-toplevel)"` échoue en SILENCE hors d'un checkout git + +- **Mécanisme** : les **6** gates commençaient par + `cd "$(git rev-parse --show-toplevel)"`. HORS d'un arbre de travail git (tarball, + `git archive | tar -x`, `git` absent du PATH, working-dir erroné), `git rev-parse` + n'écrit **rien** sur stdout → la commande devient `cd ""`, un **no-op qui RETOURNE + SUCCÈS** (le script reste dans le cwd au lieu d'échouer). Les gates poursuivaient + sur un `git ls-files` renvoyant une liste **VIDE** → + `validate_json` (« Aucun fichier .json suivi — rien à valider »), + `guard_constraints` et `check_docs` sortaient **exit 0 VERT en ayant contrôlé + ZÉRO fichier** (≈50 JSON non validés, contraintes CLAUDE.md non vérifiées). Un + gate qui passe au vert sans rien enforcer est le **pire** « vert trompeur » — + précisément ce que la série buffer traque. +- **Preuve au sol (avant fix)** : copie de l'arbre **sans `.git`** → + `validate_json` **exit 0** « rien à valider » ; `guard_constraints` **exit 0** + « Contraintes respectées » ; `check_docs` **exit 0**. Ce piège avait déjà faussé + une vérif « 6 gates verts sur git archive » d'une session antérieure (un `git + archive | tar -x` n'a **pas** de `.git`, alors que le runner Gitea a un vrai + `.git` via `actions/checkout@v4` — donc la méthode « archive » n'est PAS + équivalente au runner pour tout check qui interroge git). + +### Fix (2 solutions · CLAUDE.md #4 — retenu : helper partagé DRY + durcissement INV-B) + +- **Correctif de fond** : nouveau helper **`ci/lib.sh`** (sourcé, jamais exécuté + seul) exposant **`cd_repo_root`** — se positionne à la racine, ou **échoue + bruyamment** (`exit 3`, code distinct d'un échec de contrôle `1`) avec un message + clair si `git rev-parse` ne renvoie rien. Les 6 gates remplacent leur + `cd "$(git rev-parse …)"` par `source "$(dirname "${BASH_SOURCE[0]}")/lib.sh" || + exit 3 ; cd_repo_root`. *(Alt. écartée : inliner le garde de 4 lignes × 6 fichiers + = doublon, contraire à CLAUDE.md #5 · préférence lib partagée.)* +- **Durcissement du gate de câblage (INV-B · `check_ci_integrity.sh`)** : INV-B + exigeait que **chaque** `ci/*.sh` soit lancé par un job — `ci/lib.sh` (jamais dans + un `run:`) aurait été flaggé « gate mort ». INV-B accepte désormais un `ci/*.sh` + câblé de **deux** façons : lancé par un job du gate, **OU sourcé** par ≥1 gate + script (détecté par grep d'une ligne `source …/` / `. …/`, `#` exclu). + C'est un **renforcement** réel : le gate prouve maintenant aussi que les libs + partagées sont **effectivement sourcées** (pas du code mort). + +### Preuves de morsure + +- **Faux-vert corrigé** : arbre copié **sans `.git`** → les 6 gates sortent + désormais **exit 3** avec « ❌ ERREUR gate : hors d'un arbre de travail git » + (avant : `validate_json`/`guard_constraints`/`check_docs` = **exit 0 vert**). + Idem sur `git archive HEAD | tar -x` **après commit**. +- **INV-B reconnaît la lib** : `ci/lib.sh — lib sourcée par [les 6 gates] · non + exécutée en propre (OK)` → **exit 0**. +- **INV-B attrape une lib morte** : `ci/_dead.sh` (sourcé par personne) ⇒ + `✗ … lancé/sourcé par AUCUN job CI (gate mort)` ⇒ **exit 1**. + +**Non-régression** : **6 gates verts** dans l'arbre de travail (= ce que voit le +runner via `actions/checkout@v4`, avec un vrai `.git`) ; matrice **534/21 · PASS +inchangée** ; `qa/audit_4big` **out/ inchangé** (les édits `ci/` sont **hors** +`05_deliverables_mvp` → aucune dérive de consommateur) ; `ci.yml` YAML **valide**. + +**Anti-invention (#6)** : rien inventé — garde purement défensif (bash/git stdlib), +INV-B relit `ci.yml` + grepe les gates sur disque à chaque run. + +**Hors périmètre worker (VPS · #8)** : néant (stdlib en-repo ; enregistrement du +runner Gitea toujours du ressort DevOps). + +**Auto-score 4Big** : 96/100. + +--- + ## Session `20260731_012944` · Buffer S8 · Reproductibilité en CHECKOUT PROPRE — le hand-off out/ des 4 générateurs RBAC était `.gitignore`é → gate rouge en CI, vert en local seulement **Tâche** : **Sprint 8 · buffer L75 (« Regression tests exhaustifs » · DevOps