etm-powersync-energy-plugin.../docs/BALAYAGE_CONTROLES_20260903.md
Patrick Schurig 08558540ed audit: la question passée à toute la suite — ce qu'on croyait vérifié
« 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
2026-09-03 06:58:42 +02:00

4.6 KiB
Raw Blame History

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 en cadrage, 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.