docs(sondes): défaire son action n'est pas restaurer l'état

Payé le 2026-08-30 en cherchant à provoquer EV_GRID_START. Trois erreurs, aucune
n'a produit de code d'erreur :

- `connect` bascule `connected` (la liaison du Thing), pas `pluggedIn` — lecture
  seule, qu'aucune action n'écrit. La borne n'est jamais entrée dans `loads[]` ;
- le `finally` défaisait le GESTE, pas l'ÉTAT : `connected` valait déjà `true`
  avant, donc la « restauration » a laissé la borne déconnectée dix minutes ;
- `ThingErrorNoError` est un VRAI succès, et c'est ce qui rend le cas plus
  vicieux que `status: "success"` : l'action a réussi, elle ne faisait pas ce
  qu'on croyait. Aucun code ne dira « tu t'es trompé d'action » — le seul verdict
  est l'état relu.

La règle que `fault_probe.dart` tenait déjà pour la configuration est généralisée
à `ExecuteAction` : capturer avant, restaurer VERS la capture, comparer état par
état.

Et le fait mesuré, pour qui réessaiera : EV_GRID_START n'est pas provocable
depuis la frontière RPC (pas de prise véhicule exposée, pas d'`assignedCarId`).
La fenêtre, elle, s'ouvre seule — 07:46, surplus 905 W, sous le minimum de la
borne. La preuve du partage viendra donc de la suite de simulation du moteur ;
le critère ne bouge pas, et la branche reste jusqu'à sa trace.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
This commit is contained in:
Patrick Schurig 2026-08-30 10:18:36 +02:00
parent 820e58c13e
commit 47866ddee3
2 changed files with 41 additions and 0 deletions

View File

@ -583,6 +583,13 @@ class LoadTelemetryEntry {
/// **Cette branche tient jusqu'à l'observation d'un `EV_GRID_START` réel.** Retirer sur
/// la foi de l'annonce ferait exactement ce que la mesure a déjà démenti une fois cette
/// semaine.
///
/// **Et la trace ne viendra pas du banc** : mesuré le 2026-08-30, le motif n'y est pas
/// provocable — aucune action n'expose la prise véhicule, et sans `assignedCarId` la borne
/// reste hors `loads[]` même branchée (`tools/rpc/README.md`). La preuve viendra de la
/// suite de simulation du moteur, qui assère le partage depuis `+etm31` ; le critère, lui,
/// ne bouge pas : `params.budgetW` dans `budget.allocatedW` **et** `params.gridW` dans
/// `draw.committedW`.
double get surplusShareW {
// L'exception passe avant tout : elle vaut pour les deux formes.
if (decision.code == 'EV_GRID_START' && !isSurplusFunded) {

View File

@ -62,6 +62,40 @@ dart tools/rpc/<script>.dart [host] [args…] # host par défaut : 192.168.1
> `docs/UI_data_contract.md` §9. C'est ici, la sonde en main, qu'il se voit le plus vite :
> comparer les charges utiles **brutes** des deux appels, jamais les modèles Dart.
> ⚠️ **Défaire son action n'est pas restaurer l'état.** *(Payé le 2026-08-30, en cherchant à
> provoquer `EV_GRID_START` sur la wallbox simulée.)*
>
> La sonde branchait la borne par `Integrations.ExecuteAction`, surveillait, et appelait
> `disconnect` dans un `finally`. Trois choses fausses là-dedans, et **aucune n'a produit
> d'erreur** :
>
> 1. **`connect` ne fait pas ce que son nom promet.** Il bascule `connected` — la liaison du
> Thing — et **pas `pluggedIn`**, qui est en lecture seule et qu'**aucune action n'écrit**.
> La borne n'est donc jamais entrée dans `loads[]`, et le motif cherché était inatteignable
> par ce chemin. 18 cycles pour l'apprendre.
> 2. **Le `finally` défaisait le GESTE, pas l'ÉTAT.** `connected` valait **déjà `true`** avant
> la sonde : le `disconnect` « de restauration » a laissé la borne déconnectée dix minutes.
> Un `finally` symétrique de l'action n'est juste que si l'action est un interrupteur dont
> on connaît la position de départ — c'est-à-dire jamais, sauf à l'avoir relevée.
> 3. **`ThingErrorNoError` est un VRAI succès**, et c'est ce qui rend ce cas plus vicieux que
> le `status: "success"` du bloc précédent : l'action **a** réussi, elle ne faisait pas ce
> qu'on croyait. Aucun code d'erreur ne dira jamais « tu t'es trompé d'action ». **Le seul
> verdict est l'état relu.**
>
> **Règle, et `fault_probe.dart` la tenait déjà pour la configuration** : capturer l'état
> **avant** la première écriture, restaurer **vers la capture** et non vers l'inverse du
> geste, puis **comparer état par état** — le script de retour lit le fichier de capture,
> jamais la mémoire de ce qu'on a tapé. Ce qui valait pour `SetLoadConfig` vaut identiquement
> pour un `ExecuteAction`.
>
> **Et ce que le passage a mesuré, pour qui réessaiera** : `EV_GRID_START` n'est pas
> provocable depuis la frontière RPC. Il faudrait une prise véhicule (aucune action ne
> l'expose) **et** une voiture assignée — les `ChargingInfos` du banc n'ont aucun
> `assignedCarId`, et sans elle la borne reste hors `loads[]` même branchée (`+etm24`). En
> revanche la **fenêtre** s'ouvre bien toute seule : le 2026-08-30 à 07:46, surplus à 905 W,
> entre zéro et le minimum de la borne (~1 380 W à 6 A monophasé). Ce n'est pas la fenêtre qui
> manque, c'est la borne dans l'arbitrage.
### `probe.dart`
```bash