# Dérogations — le boost n'est pas un mode > Ouvert le 2026-09-07. **Design avant code, rien d'implémenté.** > Cadrage donné par Patrick, et il vaut au-delà du VE. ## 1. La distinction qui structure tout le lot | | mode | **dérogation** | |---|---|---| | se choisit | **une fois** | pour un **besoin ponctuel** | | vaut | jusqu'au prochain choix | **jusqu'à ce que le besoin cesse** | | se termine | jamais tout seul | **toujours tout seul** | > **Un boost encore actif après la fin est un mode qu'on a oublié de quitter. Un boost qui rend > la main est une dérogation terminée.** C'est le même geste que forcer un chauffe-eau parce qu'on veut plus d'eau chaude : on ne reconfigure pas l'installation, on demande quelque chose **maintenant**. **Conséquence de conception** : ce n'est ni un `ChargingMode` de plus, ni une demande dans `needs`. Une dérogation se **superpose** au mode courant et s'efface. Elle n'a ni cible d'énergie, ni échéance, ni cadence — les trois supposent un besoin qui dure. ## 2. Ce qui la borne : la sûreté, et rien d'autre Les trois comportements se distinguent par **ce qui les borne** : | | borné par | |---|---| | PV | le **surplus** | | Min+PV | un **plancher** + le surplus | | **Boost** | la **sûreté seule** — `DRAW_CAP` et le délestage | Et c'est cette dernière ligne qui le rend sûr : les plafonds deviennent la seule limite, **donc une limite obligatoire**. Un boost sur un branchement 3×30 A sans `phasePowerLimit` ferait disjoncter — ce n'est plus une hypothèse depuis le 2026-09-07, où l'on a découvert des semaines de fonctionnement à `0`. **Le boost prend la tête de la passe éco ; il ne surplombe pas la sûreté.** Si `DRAW_CAP` mord, il est servi le premier **dans ce qui reste**, pas au-delà. Sans cette précision on retomberait sur le second chemin d'achat refusé pour le minimum (`DESIGN_MIN_RESEAU.md` §3). ### Le rang Le boost passe **devant**, y compris devant une charge mieux rangée. `LM-1002` dit que le rang est ce que l'**installateur** décide ; elle ne dit rien d'une **action ponctuelle de l'utilisateur**. Prendre la tête ne contredit donc pas la règle : cela passe par une porte qu'elle ne ferme pas. Un boost servi après une autre charge contredirait « tout de suite », qui est sa définition. ## 3. Précaution 1 — le mode précédent se MÉMORISE, il ne se déduit pas À la fin de la dérogation, la charge revient **au mode qu'elle avait**, relu depuis ce qui a été stocké au déclenchement. Min+PV redevient Min+PV, PV redevient PV. **Revenir à un défaut serait un défaut.** Retomber sur `Normal` sortirait la borne de l'arbitrage — l'inverse exact du but, et une dérogation qui laisse l'installation moins pilotée qu'avant. C'est la même famille que le repli d'échéance qui réécrivait `EcoWithMinCurrent` en `Eco` : un état détruit en silence par un mécanisme qui croyait bien faire. ## 4. Précaution 2 — « terminé » se définit PAR MÉCANISME Le moteur ne peut pas deviner ce qui met fin à une dérogation : cela dépend de ce qu'on déroge. | charge | fins possibles | |---|---| | borne VE | **débranchement**, **cible en ÉNERGIE** (`sessionEnergy`), durée | | chauffe-eau | **température** atteinte (si sonde), durée | | batterie | cible en énergie, durée | ### La cible se dit en ÉNERGIE, jamais en SOC — et ce n'est pas un pis-aller **Il n'y a pas de communication véhicule**, et il n'y en aura pas : aucun plugin constructeur n'est prévu, et une intégration cloud Skoda/VW serait contraire au **100 % local**, fragile, et rafraîchie à la minute au mieux. Mais surtout, l'énergie est la **bonne** grandeur, indépendamment de cette contrainte : | | ce qu'il faut savoir pour l'affirmer | |---|---| | « 20 kWh puis tu t'arrêtes » | `sessionEnergy`, que le plugin V2C construit depuis le 2026-08-29 | | « jusqu'à 80 % » | la **capacité**, l'**état de santé** et le **rendement** de charge | C'est exactement ce que `LM-1009` a établi pour l'obligation éco : **on mesure de l'énergie parce que c'est ce qu'on sait mesurer.** Un SoC demanderait trois inconnues pour dire la même chose en moins sûr. > **La fin par SOC ne figure donc pas dans ce design**, et son absence n'est pas un manque à > combler plus tard : c'est une décision. L'écrire comme un manque aurait laissé quelqu'un > l'ouvrir comme un lot. ### Et `sessionEnergy` a un silence connu, qui justifie le filet `LM-1012-d`, mesuré sur la V2C le 2026-08-30 : à la **perte du lien**, `currentPower` tombe à 0 et les booléens à `false`, mais **`sessionEnergy` reste à sa dernière valeur**. Une dérogation « 20 kWh puis stop » dont le compteur se fige à 12 kWh **n'atteindra jamais sa cible**. Elle achèterait au maximum jusqu'à ce que quelqu'un s'en aperçoive — sauf que la durée est là. Ce n'est pas un cas d'école : c'est le comportement documenté de la borne installée. **Chaque mécanisme déclare ce qui termine sa dérogation.** C'est un ajout à `ILoadAdapter`, au même titre que `commandSettleS()` : une propriété du mécanisme, pas une constante du moteur. ## 5. LA RÈGLE — une dérogation qui ne sait pas dire quand elle finit ne devrait pas exister C'est la règle centrale du lot, et elle se teste. Sur un chauffe-eau **sans sonde**, « jusqu'à ce que ce soit chaud » n'est **pas mesurable**. La fin doit alors être une **durée**, explicitement — et **l'app doit le dire à la saisie**, au moment où l'utilisateur croit demander une température. C'est exactement le raisonnement de `progressMeasurable` : une capacité absente se **dit** à la saisie, parce que l'écran de résultat parle trop tard. Une dérogation dont la fin n'est pas observable est une dérogation qui ne finira pas. ### La question qui manquait : que fait-elle ENTRE le figement et l'échéance ? La durée arrêtera la dérogation — **au bout**. Entre-temps, elle achète au maximum sur une mesure morte. Sur un lien qui perd 40 % de ses trames, « au bout » peut vouloir dire des heures. **Position retenue : une dérogation dont la cible cesse d'être MESURABLE cesse.** Elle n'attend pas sa durée. C'est `R6` transposée. Là-bas : *servie oui, tenue jamais* — on ne conclut pas « tenue » sur un avancement qu'on ne mesure pas. Ici : **active oui, vérifiable non, donc on s'arrête.** Une dérogation est une commande qui **achète** ; la maintenir sans pouvoir dire où elle en est, c'est acheter à l'aveugle. **Et l'instrument existe déjà** : `measurement.source` et le régime de `LM-1009`. Quand le régime d'une charge en dérogation cesse d'être mesuré, la condition de fin est perdue — et cela se sait au cycle même, pas au bout de la durée. ### QUATRE fins, et le motif dit laquelle a mordu | fin | ce qu'elle dit à l'utilisateur | geste | |---|---|---| | `targetReached` | la cible en énergie est atteinte | aucun — c'est le succès | | `unplugged` | le véhicule est parti | aucun | | **`measurementLost`** | on ne sait plus où en est la charge | **regarder le lien / le compteur** | | `durationElapsed` | le temps imparti est écoulé | relancer si besoin | Les quatre appellent des gestes différents, et une dérogation qui se terminerait sans dire laquelle a mordu laisserait l'utilisateur relancer un boost que le lien empêchera encore. ### L'asymétrie, et la règle qu'elle donne Le débranchement peut **clignoter** sur cette borne. Le plugin V2C a déjà la parade — `k_absencesPourClore` polls consécutifs avant de clore une session — et elle porte une propriété qu'il faut reprendre : **seuls les polls RÉUSSIS font avancer le compteur.** Une coupure réseau le **gèle**, elle ne le fait pas progresser. Un lien mort ne peut donc pas fabriquer un faux débranchement. Cette confirmation vaut pour la dérogation aussi. Mais les deux erreurs ne coûtent pas la même chose : > **Terminer à tort** rend la main : la charge repasse à son mode mémorisé, et l'utilisateur > relance s'il veut. > **Continuer à tort** achète au maximum sur une mesure morte. D'où la règle : **dans le doute, une dérogation s'arrête.** Les seuils de confirmation sont donc asymétriques par conception — prompts à conclure la fin, lents à conclure la poursuite. C'est l'inverse du réglage qu'on choisirait pour un mode, et c'est parce qu'une dérogation achète. ### Corollaire — la DURÉE est un filet, pas une option Toute dérogation porte une durée maximale, **même quand elle a une meilleure condition de fin**. Raison : la condition de fin repose sur un **instrument**, et un instrument peut se taire. Une cible de charge qui ne remonte plus, une sonde qui tombe, un compteur qui se fige — et la dérogation ne se termine jamais, en tirant le maximum. C'est « l'instrument dont le silence ressemble à un résultat », appliqué à une commande qui achète. **Donc : jamais « jusqu'à annulation ».** Quatre fins, et la durée est toujours l'une d'elles. La durée est désormais **le filet du filet** : la perte de mesure attrape le cas où l'instrument se tait ET se signale ; la durée attrape le cas où **même le régime ne se signale pas**. Deux filets parce que le premier repose lui-même sur un instrument. Cela rejoint ce que la maquette batterie demande pour son propre boost. ## 6. Ce que ça publie Une dérogation active **se voit**, et sa fin **se lit** : - un motif dédié, qui dit que la charge est en dérogation et **ce qui y mettra fin** ; - l'instant de fin prévu, pour que l'écran affiche un compte à rebours plutôt qu'un état sans horizon ; - l'instant est **absolu, ancré à la capture** (`toUTC()`), jamais une heure murale — cf. la dérive mesurée le 2026-09-06. **Et la fin est un ÉVÉNEMENT**, publié le cycle où elle survient. Sans lui, l'écran ne peut pas distinguer « la dérogation s'est terminée normalement » de « quelqu'un l'a annulée ». ## 7. Étapes, à comportement constant d'abord **A** — le type et sa publication, sans qu'aucune dérogation ne puisse être posée. Le champ existe, il ne décide de rien. **B** — la déclaration des fins par mécanisme (`ILoadAdapter`), avec la durée obligatoire. **C** — la pose, la mémorisation du mode précédent, et le retour automatique. **D** — le service en tête de passe éco, borné par `DRAW_CAP` et le délestage. Le pas **D** est le seul qui change ce qui est commandé, et il arrive quand tout le reste est déjà vérifiable. ## 8. Ce que le banc ne prouvera pas **Les trois fins du VE sont exerçables sans véhicule communicant** : débranchement, cible en énergie via `sessionEnergy`, et durée. C'est ce qui rend ce lot éprouvable sur le banc réel, là où une fin par SoC ne l'aurait jamais été. Reste hors de portée : la fin par **température**, qui demande la sonde du §12 — elle n'existe qu'en mock, et c'est le sixième manque de `INVENTAIRE_MOCK.md` sous un autre angle. **La durée, elle, s'éprouve partout** — une raison de plus d'en faire le filet plutôt qu'un recours. --- ## 9. Implémenté — `+etm59`, 2026-09-08 Le design ci-dessus est posé **d'un bloc** et non par les quatre pas du §7 : la fenêtre de peu de production du matin était le bon moment pour éprouver un mécanisme qui **achète**, et découper l'implémentation aurait fait passer cette fenêtre. ### Où vit quoi | | fichier | |---|---| | le type, les quatre fins, les seuils | `etm/types/derogation.h` | | pose, levée, évaluation des fins, restitution du mode | `etm/energyarbitrator.cpp` | | service en **tête de passe éco** | `etm/scheduler/rulebasedscheduler.cpp` | | `SetLoadDerogation` / `ClearLoadDerogation`, `derogationEnded` | `nymeaenergyjsonhandler.cpp` | ### Trois décisions prises en écrivant, qui ne sont pas dans le design **a. Les fins se lisent dans le CONTEXTE DU CYCLE, pas dans les adaptateurs.** `evaluerDerogations()` tourne **entre** `buildContext()` et `getPlan()`, sur les `LoadContext` que le scheduler va lire. Une seconde lecture donnerait une seconde vérité, et une dérogation pourrait se terminer sur une mesure que le plan ne voit pas. C'est aussi ce qui rend le débranchement gratuit : une borne débranchée est déjà filtrée du contexte par `evParticipatesInWaterfall()`, son absence **est** le signal. **b. `measurementLost` ne mord QUE s'il y a une cible.** Le design disait « une dérogation dont la cible cesse d'être mesurable doit cesser ». Sans cible, rien ne dépend de la mesure : le filet de durée suffit, et couper là punirait la charge du silence d'un instrument dont elle n'a pas besoin. La garde porte donc sur `targetWh > 0`. C'est aussi pourquoi le critère est `telemetry.sessionMeasurable` et **non** `progress.regime` : `progress` est absent sur une charge sans obligation en énergie — c'est-à-dire exactement le cas du boost, où le critère aurait été inerte. **c. La base de la cible se capture au PREMIER CYCLE, pas à la pose.** Au moment où l'utilisateur appuie, aucun cycle n'a construit de contexte et le cumul de session n'est lisible nulle part. Prendre `0` compterait depuis le début de la **session de charge** : une dérogation « 5 kWh » posée sur une session déjà à 6 kWh serait atteinte avant d'avoir commencé. Mécanisme de `LM-1012-b`, même raison — une base se prend sur ce qu'on mesure. ### Le seul endroit où le mode est ÉCRIT Une borne en `Normal` (manuel) est **hors waterfall** : le moteur ne la commande pas, donc une dérogation n'y produirait rien du tout. La pose la bascule alors en éco pour la durée, et `modeForce` retient qu'elle l'a fait. C'est le seul cas — et c'est lui qui donne sa raison d'être à `previousMode` : sans mémorisation, on rendrait une borne manuelle en éco, c'est-à-dire qu'on lui prendrait un réglage en silence. ### La passe confort est SAUTÉE sous dérogation La fusion des niveaux est une **addition** (`la.powerW += eco.targetW`). La dérogation demande déjà le maximum de la charge : y ajouter du surplus dépasserait son plafond matériel. Le surplus non dépensé reste au budget et passe aux charges suivantes. **Conséquence comptable à connaître** : la dérogation est comptée **entièrement en achat** alors que le surplus présent la finance en partie, physiquement — `gridW` la surestime dès qu'il y a du soleil. Ce n'est pas une approximation neuve : le §10 la porte déjà pour le plancher éco, et elle sera reprise avec lui. C'est aussi pourquoi la première vérification au banc se fait le matin. ### Ce que le test prouve, et par quelle contre-épreuve `Simulation::testDerogationTakesTheHeadButNotTheSafety` — deux charges, la borne au **rang 9** (la queue) et l'ECS au **rang 1**, sans aucun surplus : 1. **contre-épreuve** — la même borne **sans** dérogation reçoit `0 W`, l'ECS ses 1 000 W de cadence. Sans elle, on ne saurait pas d'où viennent les 7 000 W du cas suivant ; 2. avec dérogation : 7 000 W, `funding = Grid`, motif `DEROGATION_ACTIVE`, `endsAt` publié, et **pas** de `targetWh` puisqu'il n'y en a pas ; 3. **la tête de passe prouvée par la rareté** — 7 500 W d'autorisation pour 8 000 demandés : la borne de rang 9 est servie **entièrement**, l'ECS de rang 1 prend les 500 restants. L'inverse exact de l'ordre des rangs, donc la preuve que c'est bien la tête de passe qui agit ; 4. 1 000 W d'autorisation : servie à 1 000, `boundBy: drawCap` — elle ne surplombe pas la sûreté ; 5. autorisation nulle : **aucun niveau**, pas un niveau à zéro. ### Ce qui reste ouvert - La **fin par cible** n'est pas éprouvée au banc : elle demande une session assez longue pour franchir un seuil, et la V2C a un `sessionEnergy` qui **se fige** à la perte du lien (`LM-1012-d`) — c'est précisément ce que le filet de durée couvre. - `ClearLoadDerogation` publie la cause `cancelled`, qui n'est pas une des quatre fins par mécanisme : c'est une fin **par décision**, et la distinguer est le but. ### Deux effets de `setChargingInfo()` trouvés en préparant l'essai — `+etm60` `SmartChargingManager::setChargingInfo()` **déclenche lui-même un `update()`**. Écrire le mode n'est donc pas un geste neutre, et le lot le touche aux deux bouts. **À la pose, l'ordre décide d'une minute.** L'écriture du mode vient **en dernier**, après l'insertion dans `m_derogations` : le cycle qu'elle déclenche trouve alors la dérogation déjà posée et la sert immédiatement. L'ordre inverse la lui faisait manquer d'un cycle — soixante secondes d'attente sur un mécanisme dont la définition est « tout de suite ». **À la fin, la restitution est DIFFÉRÉE d'un tour de boucle.** Les fins sont évaluées *depuis* `update()` ; y appeler `setChargingInfo()` imbriquerait un `update()` dans un `update()` — deux plans construits et deux dispatchs pour le même instant, sur des charges qu'un seul des deux croirait avoir commandées. `update()` n'a aucun verrou de ré-entrance, donc rien ne l'aurait signalé. Le décalage ne se voit nulle part : l'événement de fin part dans la trame du cycle courant, et le mode est rendu avant le suivant. **Effet heureux du retour à `Normal`** : l'amont restaure alors les valeurs manuelles (`manualChargingEnabled`, `manualMaxChargingCurrent`, `manualDesiredPhaseCount`). La borne retrouve donc *ses* réglages, et pas seulement son mode. --- ## 10. Premier essai au banc — 2026-09-08, 11:05:54 → 11:15:54 (`+etm60`) V2C Trydan, voiture branchée, **mode manuel** avant la pose. Durée 600 s, sans cible. Authentification désactivée sur `.75` pour l'essai ; appel par WebSocket `4444`. ### Les quatre refus mordent sur la vraie machine | appel | réponse | |---|---| | `durationS: 30` (sous le plancher de 60) | `EnergyErrorInvalidParameter` | | `durationS: 25200` (au-delà des 6 h) | `EnergyErrorInvalidParameter` | | `loadId` inconnu | `EnergyErrorInvalidParameter` | | `ClearLoadDerogation` sans dérogation en cours | `EnergyErrorInvalidParameter` | Journal : `[Dérogation] durée hors bornes : 25200 s (attendu 60 .. 21600)`, `[Dérogation] charge inconnue`. ### La pose est servie DANS LA MÊME SECONDE ``` 11:05:54 [Dérogation] POSÉE {4d1adafd…} — durée 600 s, sans cible, mode mémorisé 0 (forcé en éco pour la durée) 11:05:54 Charging mode changed for "V2C Trydan" ChargingModeEco 11:05:54 Executing action V2C Trydan to power: ON, Charging current: 9A ``` **C'est la correction `+etm60` qui se voit ici**, et rien d'autre : le cycle déclenché par `setChargingInfo()` trouve la dérogation déjà posée et la sert. Dans l'ordre inverse il l'aurait manquée, et la borne serait partie en éco ordinaire jusqu'au cycle suivant. ### Ce qui la borne, et rien d'autre `boundBy: "drawCap"` à **tous** les cycles, et `maxW: 13800` (20 A × 3 × 230 V) **jamais atteint** : ``` draw : { authorisedW: 5984, committedW: 5984, remainingW: 0, binding: "connection", bindingPhase: "A", perPhaseBound: true } ``` La dérogation prend la tête, **consomme toute l'autorisation de soutirage — et s'arrête là**. `remainingW` tombe à `0`, jamais en négatif. Les charges suivantes ne reçoivent plus que du surplus : le chauffe-eau passe `BELOW_MIN_POWER` (241 W restants), la PAC tient sur son recrédit. > **« Pleine puissance » ne veut pas dire 13 800 W.** La phase A du branchement 3×30 A n'en > autorisait que ~6 000 avec la maison dessus. La borne est allée au maximum que la **sûreté** > permettait, et le motif l'a dit à chaque cycle. C'est `LM-1500-e` observée, pas contournée. ### Une étiquette de journal à ne pas mal lire L'amont journalise `Issuer: Surplus` sur une action pourtant financée au **réseau**. `ChargingActionIssuerSurplusCharging` nomme le **canal** par lequel l'arbitre commande la borne, pas l'origine des watts — `EV_GRID_START` porte déjà la même étiquette depuis 3g-2. Rien à corriger, mais un lecteur du journal peut y voir une contradiction avec `funding: grid`. ### Ce que le premier essai a trouvé, et que le code seul ne disait pas — `+etm61` **a. La collision de commandeurs (`LM-1500-g`).** À 11:09:51 le bouton « boost » de l'app a écrit `ChargingModeNormal` pendant la dérogation. L'amont a alors restitué les valeurs manuelles — `chargingEnabled` à **faux** — et armé un verrou de 300 s, pendant que la dérogation continuait de commander 9 A. Six minutes de dérogation servie **sur le papier** dans une borne éteinte, que seul `[Divergence] DÉBUT — attendu 6210 W, mesuré 0 W` a signalées, sans pouvoir en dire la cause. Corrigé : une écriture de mode **termine** la dérogation (cause `modeChanged`), et **sans** restituer le mode mémorisé — il écraserait celui que l'utilisateur vient de choisir. **b. Le double écrêtage des bornes (`LM-1500-h`).** La tête de passe éco appliquait `margeRestante` — la marge d'**une** phase — au plafond **triphasé** d'une borne. 6 210 W au lieu de 13 800 : **9 A par phase au lieu de 27**, 4 kW au lieu des 11 que la voiture pouvait prendre. La passe confort ne fait pas cette faute, et son commentaire dit pourquoi depuis 3g-2 : *« leur plafond de cycle est déjà écrêté par `evPhaseAllowanceW()`, qui connaît les phases qu'elles occupent »*. Je l'ai réécrite quinze lignes plus haut sans la relire. > **Une règle notée à un seul endroit du code n'est pas une règle.** Et une erreur qui va dans le > sens prudent ne se signale nulle part : ni le disjoncteur, ni le délestage, ni un test qui > vérifie qu'on ne dépasse pas. Elle ne se voit qu'en **regardant la voiture**. **c. Le motif n'était pas rendu au journal.** `[Arbitre] … (motif inconnu DEROGATION_ACTIVE …)` : le catalogue français de `decisionreason.cpp` ignorait les deux codes neufs. Le repli 7-c a fonctionné — le code brut et ses paramètres, jamais une chaîne vide — mais la ligne que l'utilisateur lit était illisible. **d. La pose lisait l'horloge murale, le cycle l'horloge injectée.** Sans conséquence en production, où les deux sont la même ; en test, la fin par durée n'arrivait jamais. Trouvé par le test, pas par la lecture — `poseDerogation()` prend maintenant l'instant en paramètre. --- ## 11. Second essai — 2026-09-08, 11:52:34 → 11:58:00 (`+etm61`) Même borne, durée 300 s, sans cible. La voiture a été rebranchée pendant la pose. ### Le double écrêtage est bien la cause : de 9 A à 20 A ``` 11:52:34 [Dérogation] POSÉE — durée 300 s, mode mémorisé 0 (forcé en éco pour la durée) 11:53:00 Dérogation sur V2C Trydan — 13800 W achetés sur 13800 W possibles 11:53:00 Executing action V2C Trydan to power: ON, Charging current: 20A 11:54:00 … 9006 W … 13A 11:56:00 … 11248 W … 16A 11:57:00 … 9245 W … 13A 11:58:00 [Dérogation] FIN — cause durationElapsed, livré 716 Wh, mode rendu 0 11:58:00 changed to normal mode. Restoring manual values of false 6 A 3 phases ``` | | avant (`+etm60`) | après (`+etm61`) | |---|---|---| | commandé | **9 A** par phase | **13 à 20 A** | | mesuré | 4,4 kW | **8,4 kW** (`[Divergence] FIN — attendu 8970 W, mesuré 8396 W`) | | livré | 276 Wh en 10 min | **716 Wh en 5 min** | | motif | `boundBy: drawCap` (faux) | `boundBy: loadCeiling` | Le plafond suit le soutirage de la maison d'un cycle à l'autre — 13 800, 9 006, 11 248, 9 245 W — parce que `evPhaseAllowanceW()` le recalcule à chaque cycle. **C'est la sûreté qui module, et elle module sur la bonne grandeur.** Le motif est enfin rendu en clair : *« Dérogation sur V2C Trydan — 13800 W achetés sur 13800 W possibles »*. ### Trois observations à garder **a. La divergence d'OUVERTURE est une latence, pas une commande perdue.** `11:53:00 [Divergence] DÉBUT — attendu 13800 W, mesuré 3930 W` puis `11:57:00 FIN après 300 s — attendu 8970 W, mesuré 8396 W`. La voiture négocie sa montée (~30 s mesurés sur la V2C, et davantage depuis l'arrêt). C'est le même profil que l'épisode Min+PV du 2026-09-05, et il confirme le critère de tri de `DESIGN_COMMANDE_PERDUE.md` §6. **b. La FERMETURE en produit une aussi**, et elle est plus trompeuse : `11:58:00 [Divergence] DÉBUT — attendu 0 W, mesuré 8367 W`. La dérogation vient de rendre la main, la borne n'a pas encore décru. **Une divergence qui ouvre dans le même cycle qu'un `DEROGATION_ENDED` est une descente en cours**, jamais une commande perdue — à écrire dans le critère de tri de l'étape 4, sous peine de compter chaque boost comme un incident. **c. La fin par DÉBRANCHEMENT n'est toujours pas éprouvée.** L'essai avait été lancé sur une borne débranchée pour l'exercer ; la voiture est revenue avant les deux confirmations. On a en revanche vu le mécanisme faire ce qu'on lui demande : une absence isolée (09:55) **n'a pas** terminé la dérogation, parce que le compteur se remet à zéro dès que la charge reparaît (`LM-1500-c`). Un clignotement ne conclut rien.