# INVENTAIRE À FROID DU MOCK — ce qu'il rend structurellement introuvable *(Fait le 2026-09-01, après trois occurrences en trois jours d'un cas réel impossible à reproduire. Ce n'est plus un incident, c'est une propriété du banc d'essai.)* ## Pourquoi cet inventaire Trois fois cette semaine, un défaut réel s'est révélé **inatteignable par la suite** : | Occurrence | Ce qui était introuvable | Comment on l'a su | |---|---|---| | Correctif amont `calculateAllowanceAmpere` | un compteur publiant les courants **sans** les puissances par phase | le mock pose `currentPhaseB = currentPowerPhaseB / 230`, cohérent **par construction** | | Test `command` sous `source: none` | une charge dont rien ne mesure la puissance | **toutes** les classes pilotables portent `currentPower` | | Test `ECO_FLOOR_*` en régime `unmeasurable` | une borne sans `sessionEnergy` | il a fallu **ajouter** l'état à une seule classe pour avoir les deux cas | Le point commun : **le mock est plus homogène que la réalité.** Il a été construit pour faire marcher des scénarios, pas pour représenter la diversité du parc — et une suite verte ne dit alors rien sur les cas qu'il ne sait pas produire. ## Les classes, et ce qu'elles portent | Classe | `currentPower` | `totalEnergyConsumed` | `sessionEnergy` | |---|---|---|---| | `meter` | ✅ | ✅ | — | | `charger` | ✅ | ✅ | ❌ | | `chargerPhaseSwitching` | ✅ | ✅ | ✅ *(ajouté le 2026-08-31)* | | `simpleCharger` | ❌ | ❌ | ❌ | | `powerSwitch` | ✅ | ❌ | — | | `etmVariableLoad` | ✅ *(`currentPowerW`)* | ❌ | — | | `energyStorage` | ✅ | ❌ | — | | `car`, `notification` | ❌ | ❌ | — | **Ce que la table donne, et c'est la bonne nouvelle** : `sessionEnergy` et `totalEnergyConsumed` sont désormais **discriminants** — il existe des classes avec et sans. Les régimes `measured` / `unmeasurable` et les causes `noSessionEnergy` / `meterWithoutEnergy` sont donc exerçables. ## Ce qui reste STRUCTURELLEMENT introuvable **1. ~~`measurement.source: none` pour une charge saine.~~ — OUVERT le 2026-09-02.** La classe `dryRelay` a été ajoutée : elle commute, elle ne mesure pas. Une charge **saine et non mesurée** est désormais fabricable, et `testHealthyButUnmeasuredDiffersFromFaulty` vérifie ce que rien ne pouvait vérifier avant — que le moteur **distingue** « rien ne mesure cette charge » de « cette charge est en panne », deux affirmations que le seul chemin disponible (un Thing manquant) mélangeait. > **Ce que l'ajout a révélé au passage** : `executeAction()` déréférençait le contrôleur HTTP de > **chaque** Thing sans vérifier — le mock supposait que toute classe en possède un. Un relais sec > n'en a pas besoin, n'ayant rien à mesurer. Le plantage était immédiat et net ; l'hypothèse, elle, > était invisible tant qu'aucune classe ne la contredisait. **Le mock avait sa propre prémisse > fausse**, protégée par son homogénéité. **2. Un compteur par phase incohérent.** `currentPhaseX` et `currentPowerPhaseX` sont posés ensemble par le mock, dans un rapport fixe de 230. Aucun scénario ne peut produire une tension réelle ≠ 230 V, ni un compteur qui ne publierait qu'une des deux familles. **3. `temperature`.** Le code teste `hasState("temperature")` et **aucune classe du mock ne le porte** : la branche « sonde présente » n'a jamais été exécutée. Elle est écrite, elle n'est pas testée. **4. Une borne triphasée à phases déséquilibrées.** Les états existent, mais aucun helper de test ne les pose indépendamment — d'où le pessimisme de `LM-1210-a` qui n'a jamais été exercé sur un vrai déséquilibre. ## La règle qui en sort > **Avant d'écrire un test qui exerce une ABSENCE, vérifier que le mock peut la produire.** > Une assertion sur un cas inatteignable ne passe pas : elle **ne s'exécute pas**, ce qui est > pire — elle compte comme verte. > > Le symptôme se reconnaît : **la contre-épreuve ne mord pas**. C'est le corollaire fin > d'`AGENTS.md` appliqué au banc d'essai plutôt qu'au code. **Et la parade tient en une ligne de test** : quand on itère pour trouver des cas, **compter combien on en a examinés**, et échouer si le compte est nul. C'est ce qui a rattrapé le test de `command`, et ce qui garde celui de la mesurabilité. ## Ce qu'il faudrait ajouter, par ordre d'utilité 1. **Une classe pilotable SANS aucune puissance** — un relais sec. Débloque `source: none` sur une charge saine, et sépare enfin « non mesurée » de « en panne ». 2. **Un compteur sans `totalEnergyConsumed`** en tant que classe déclarée, plutôt qu'un `powerSwitch` détourné comme aujourd'hui. 3. **Une tension par phase réglable** indépendamment des puissances — pour exercer le correctif amont ailleurs qu'en inversant la fonction. > Aucune de ces trois n'est urgente. Ce qui l'est, c'est de **savoir qu'elles manquent** : sans > cette liste, chaque lot repaiera le même temps à découvrir qu'un cas est introuvable.