« Qu'est-ce que ce contrôle aurait attrapé s'il avait échoué ? » passée à la suite existante. Le résultat n'est pas une liste de tests à supprimer. Contrôles qui ne contrôlent rien : les assertions conditionnelles dans une boucle sont à zéro — la seule qui existait a été corrigée avant-hier. Sur dix identités auto-référentielles relevées, UNE SEULE est vaine : authorisedW − committedW == remainingW relisait une affectation d'une ligne. Elle est retirée AVEC SA RAISON à sa place, et avec la distinction d'avec l'identité du budget — qui croise remainingSurplusW filé le long de la cascade et allocatedW accumulé en trois sites distincts, donc attrape un site qui décrémenterait sans accumuler. Supprimer sans dire pourquoi aurait invité quelqu'un à la remettre. La moitié qui compte : l'index annonçait 47 règles sans porteur. Il mesurait la CITATION, pas la couverture — douze étaient couvertes par un test qui ne les nommait pas. Citées par un test : 22 → 40. Les liens sont maintenant vérifiables par la machine au lieu de reposer sur la mémoire de qui a écrit quoi ; c'est la doctrine du dépôt appliquée à elle-même. Sur les 31 restantes, 23 relèvent de familles non implantées — écrire leur test poserait un invariant sur du code que rien n'émet. Six sont du cadrage mal classé. Et UNE manque vraiment : LM-1210-a, la pire phase faute de masque, qu'aucun test n'exerce parce que le mock ne sait pas produire une triphasée déséquilibrée. Même angle mort que l'inventaire, nommé deux fois. tools/audit-controles.py pérennise les deux motifs. Il ne remplace pas la question, il la pose là où elle se pose souvent — et il ne juge pas : la lecture tranche, l'écart entre les dix relevées et la seule vaine le montre. Le résultat le plus utile n'est pas le défaut trouvé, c'est le chiffre corrigé. On croyait 47 règles non couvertes ; il y en avait 31, dont 23 légitimes et une seule qui manque. Savoir lesquelles change ce qu'on surveille. Suite : simulation 62/62, loadmodel 22/22, charging 48/48 identique à la référence, spotmarket 32/32, doxygen 0 avertissement. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p
4.6 KiB
BALAYAGE — « qu'est-ce que ce contrôle aurait attrapé s'il avait échoué ? »
(2026-09-03. La question passée à toute la suite existante. Ce qui suit n'est pas une liste de tests à supprimer : c'est la liste de ce qu'on croyait vérifié et qui ne l'était pas.)
Pourquoi ce balayage
Trois défauts de cette classe ont été rencontrés sans les chercher, sous trois formes :
| Forme | Cas réel |
|---|---|
| La contre-épreuve inerte | perturber deliveredWh sous unmeasurable, où il vaut 0 — la perturbation ne pouvait rien changer |
| L'identité qui se referme sur elle-même | Σ levels[].targetW == estimatedPowerW : deux termes de la même source |
| Le test qui échoue à côté | l'horodatage « après échéance » visait la MÊME échéance — rien ne basculait |
Trois formes, un seul défaut : le voyant est vert et n'a rien mesuré.
Résultat 1 — les contrôles qui ne contrôlent rien
Assertions conditionnelles dans une boucle : 0. La seule qui existait — « sans mesure, pas de
command » — a été corrigée le 2026-09-01. L'outil (tools/audit-controles.py) le confirme et
le surveillera.
Identités auto-référentielles : 10 relevées, 1 vaine. Le motif signale, il ne juge pas — la lecture tranche, et le résultat est très inégal :
| Assertion | Verdict |
|---|---|
surplus + recrédit − alloué == restant |
contrôle — croise remainingSurplusW filé le long de la cascade avec allocatedW accumulé en trois sites distincts. Attraperait un site qui décrémente sans accumuler |
lockMin == lockMax, minState == maxState |
contrôlent — champs différents, ils épinglent le gel d'une charge |
mapping.size() == levels.size() |
contrôle — une dérivation qui produirait un compte différent |
authorisedW − committedW == remainingW |
NE CONTRÔLE RIEN — le moteur l'établit sur une ligne ; l'assertion relisait l'affectation |
remainingWh == targetWh sous unmeasurable |
faible, et documenté — corollaire de delivered == false, pas une garde indépendante |
expectedW == observedW sous device |
faible, et délibéré — le mock renvoie sa consigne ; l'assertion documente le piège plutôt qu'elle ne contrôle |
Action : l'assertion vaine est retirée, avec sa raison écrite à sa place — et la distinction d'avec l'identité du budget, qui, elle, mérite d'être assertée. Supprimer sans dire pourquoi aurait invité quelqu'un à la remettre.
Résultat 2 — les invariants que personne ne couvrait (la moitié qui compte)
L'index des règles annonçait 47 règles « spécifiées seules » — ni code, ni test. Le balayage montre que l'index mesure la CITATION, pas la couverture : douze de ces règles étaient couvertes par un test qui ne les nommait pas.
| avant | après | |
|---|---|---|
| citée par un test | 22 | 40 |
| spécifiée seule | 47 | 31 |
Les liens sont désormais vérifiables par la machine au lieu de reposer sur la mémoire de qui a écrit quoi. C'est la doctrine du dépôt appliquée à elle-même : quelle machine rejouera cette décision ?
Sur les 31 restantes, 23 appartiennent à des familles NON IMPLANTÉES — sonde thermique
(ECS-5xx/6xx), transport réseau du §14 (LM-14xx), optimiseur externe (LM-4xx/5xx),
ancien lot ECS. Elles sont légitimement sans porteur : écrire leur test aujourd'hui poserait un
invariant sur un code que rien n'émet.
Restent huit règles du lot courant sans porteur, et elles se répartissent en deux tas :
- Cadrage mal classé —
LM-1000,LM-1001,LM-1005,LM-1006,LM-1010,LM-1014: des règles de forme et de doctrine, dont le porteur naturel est la spec elle-même. À reclasser encadrage, ce qui est une correction d'index, pas un manque de test. - Un vrai manque, assumé —
LM-1210-a(la marge retenue est celle de la pire phase, faute de masque de phases). Aucun test ne l'exerce parce que le mock ne sait pas produire une triphasée déséquilibrée (cf.INVENTAIRE_MOCK.md, manque n°4). C'est le même angle mort, et il est maintenant nommé deux fois.
Ce que le balayage a coûté et rapporté
Coût : une heure. Rapport : une assertion vaine retirée, dix-huit invariants dont la
couverture est passée de crue à démontrée, et un outil qui repose la question à chaque
passage de ci-quality.
Le résultat le plus utile n'est pas le défaut trouvé, c'est le chiffre corrigé. On croyait 47 règles non couvertes ; il y en avait 31, dont 23 légitimes et une seule qui manque vraiment. Savoir lesquelles change ce qu'on surveille.