#!/bin/bash # SPDX-License-Identifier: GPL-3.0-or-later # Copyright (C) 2025 - 2026, Patrick Schurig / ETM PowerSync # # Contrôle de qualité documentaire — TROIS vérifications, un seul endroit. # # ./tools/ci-quality.sh # # Elles se posent au même endroit parce qu'elles partagent la même sortie # (`doc-generated/`) et la même commande de réparation. Les séparer ferait trois # jobs qui regénèrent trois fois la même chose. # # 1. L'INDEX DES RÈGLES est-il VRAI ? (tools/gen-rules.py, code de retour) # Casse sur : un identifiant cité et jamais défini ; un identifiant qui n'existe # qu'en ligne de tableau ; un domicile ambigu ; un numéro retiré réattribué. # 2. La DOC DOXYGEN est-elle complète ? (0 avertissement — DoD §5 d'AGENTS.md) # 3. Le tout est-il REPRODUCTIBLE ? (deux passes donnent le même index) # # ── CE QU'ON NE VÉRIFIE PAS, ET POURQUOI ──────────────────────────────────── # # « Régénérer et refuser si ça diffère de ce qui est commité » n'a rien à comparer : # `doc-generated/` est dans .gitignore, décision du 2026-08-29 — versionner une page # générée produirait un diff à chaque édition de spec et des conflits sur un fichier # que personne ne relit. Le risque qu'un tel diff attrape — un artefact commité qui # dérive de sa source — n'existe pas quand l'artefact n'est pas commité : il a été # SUPPRIMÉ, pas déplacé. Ce qui reste à garantir est que l'index soit VRAI, et c'est # la vérification 1. La 3 couvre le reste : un générateur non déterministe. # # ── ÉTAT : ÉCRIT, PAS EN SERVICE ──────────────────────────────────────────── # # Aucun déclencheur automatique n'est posé. `ci/gitea-workflow.yml.disabled` porte le # workflow prêt à l'emploi et la marche à suivre pour l'activer. La raison est datée : # au 2026-08-29 la forge ne répond pas et plus de trente commits attendent en local. # Un job activé à l'aveugle échouerait à son premier passage — au moment précis où # tout le monde pousse — et le premier réflexe serait de le désactiver. Un garde-fou # désactivé une fois ne se réactive jamais. # # Il PASSE sur l'état du dépôt au 2026-08-29 : index RC=0 (113 règles), doxygen 0 # avertissement. Vérifié avant d'être déclaré prêt, parce qu'un job qu'on n'a jamais # vu passer n'est pas un job, c'est une intention. set -u RACINE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$RACINE" || exit 1 ROUGE=""; VERT=""; GRAS=""; FIN="" if [ -t 1 ]; then ROUGE=$'\e[31m'; VERT=$'\e[32m'; GRAS=$'\e[1m'; FIN=$'\e[0m'; fi echec=0 titre() { printf '\n%s── %s %s\n' "$GRAS" "$1" "$FIN"; } ko() { printf '%s✗ %s%s\n' "$ROUGE" "$1" "$FIN"; echec=1; } ok() { printf '%s✓ %s%s\n' "$VERT" "$1" "$FIN"; } # Toute panne doit dire QUOI LANCER. Un job qui annonce « l'index est périmé » sans # donner la commande se contourne en le désactivant — c'est le chemin de moindre # effort, et il gagne toujours. reparer() { printf ' → réparer : %s\n' "$1"; } # --- 1. L'index des règles est-il vrai ? ------------------------------------ titre "1/4 · index des règles" if python3 tools/gen-rules.py; then ok "index complet — aucun orphelin, aucun domicile ambigu" else ko "l'index des règles est INCOMPLET (détail ci-dessus)" reparer "définir la règle manquante dans specs/, ou la déclarer dans tools/rules-retired.txt" reparer "puis : python3 tools/gen-rules.py" fi # --- 2. La doc est-elle complète ? ------------------------------------------ titre "2/4 · documentation Doxygen" if ! command -v doxygen >/dev/null 2>&1 || ! command -v dot >/dev/null 2>&1; then ko "doxygen ou graphviz absent — la vérification n'a PAS eu lieu" reparer "apt install doxygen graphviz" else ./tools/gen-doc.sh >/dev/null 2>&1 JOURNAL="$RACINE/doc-generated/warnings.txt" # `wc -l` et non `grep -c` : grep -c AFFICHE 0 puis SORT EN 1 quand il ne trouve rien, # si bien qu'un « || echo 0 » empile un second zéro et que le test entier échoue sur un # dépôt SAIN. Une commande de mesure dont l'échec produit une lecture fausse — le motif # de la semaine, appliqué à l'outil (AGENTS.md, « Lire le journal de la box »). N=0 [ -f "$JOURNAL" ] && N="$(grep -i "warning" "$JOURNAL" 2>/dev/null | wc -l)" if [ "$N" -eq 0 ]; then ok "0 avertissement" else ko "$N avertissement(s) Doxygen — DoD §5 : toute méthode publique d'etm/ se documente" printf '\n'; sed 's|^.*/energyplugin/| |' "$JOURNAL" | head -20 reparer "./tools/gen-doc.sh puis lire doc-generated/warnings.txt" fi fi # --- 3. Le générateur est-il déterministe ? --------------------------------- titre "3/4 · reproductibilité de l'index" A="$(mktemp)"; B="$(mktemp)" python3 tools/gen-rules.py >/dev/null 2>&1; cp doc-generated/RULES.md "$A" python3 tools/gen-rules.py >/dev/null 2>&1; cp doc-generated/RULES.md "$B" if diff -q "$A" "$B" >/dev/null; then ok "deux passes, un seul résultat" else ko "l'index n'est PAS reproductible — deux passes ont divergé" printf '\n'; diff "$A" "$B" | head -20 reparer "un ordre d'itération dépend d'un QHash ou du système de fichiers : trier" fi rm -f "$A" "$B" # --- 4. Un verdict de test peut-il dépendre de l'HEURE ? --------------------- titre "4/4 · horloge des déclencheurs" if sortie="$(python3 tools/check-simulation-clock.py 2>&1)"; then ok "${sortie#✓ }" else ko "un déclencheur d'arbitrage tourne à l'horloge murale sans garde" printf '\n'; printf '%s\n' "$sortie" | sed '1d;s/^/ /' reparer "entourer l'appel de #ifndef ENERGY_SIMULATION, comme ses voisins" fi printf '\n' if [ "$echec" -eq 0 ]; then printf '%s✓ qualité documentaire : tout passe.%s\n' "$VERT" "$FIN" else printf '%s✗ qualité documentaire : au moins une vérification a échoué.%s\n' "$ROUGE" "$FIN" printf ' Tout relancer d'"'"'un coup : ./tools/ci-quality.sh\n' fi exit "$echec"