diff --git a/docs/BRIEF_plugin_depuis_maquettes.md b/docs/BRIEF_plugin_depuis_maquettes.md index 6015191..137acfa 100644 --- a/docs/BRIEF_plugin_depuis_maquettes.md +++ b/docs/BRIEF_plugin_depuis_maquettes.md @@ -54,6 +54,13 @@ sortie unique (`NymeaService.setLoadConfig`). L'écriture passe, mais la marque la box » disparaîtra donc d'une borne que personne n'a classée, au premier renommage d'une autre charge. +> ✅ **Répondu le 2026-08-29 : l'exception existe déjà.** `reconcileRankOrigin()` accepte +> `"auto"` quand le persisté le porte déjà. Le refus mesuré côté app portait un écho +> **périmé** — la marque avait été consommée entre la lecture et l'écriture — ce qui est le +> bon comportement, et un symptôme identique pour deux causes distinctes. La mesure sur +> marque fraîche est en cours côté moteur ; à son résultat, `sansRankOriginAuto()` disparaît +> côté app. **Tout ce qui suit reste comme trace de la demande, et de son argument.** + **La demande** : tolérer l'écho **inchangé** — même id, même rang, même valeur. Le refus vise à empêcher un client de **fabriquer une affirmation** sur un geste du moteur. diff --git a/docs/UI_data_contract.md b/docs/UI_data_contract.md index 9bcf868..87a537d 100644 --- a/docs/UI_data_contract.md +++ b/docs/UI_data_contract.md @@ -453,14 +453,27 @@ Une seconde wallbox simulée appairée après `+etm27` a produit les trois cas d | Écriture | Réponse de la box | État après | |---|---|---| -| renommage d'une AUTRE charge, `"auto"` renvoyé verbatim | `status: "success"` + `energyError: "EnergyErrorInvalidParameter"` | **inchangé** | +| renommage, `"auto"` renvoyé **alors que le persisté ne le portait plus** | `status: "success"` + `energyError: "EnergyErrorInvalidParameter"` | **inchangé** | | même renommage, `"auto"` → `""` (ce que fait l'app) | `EnergyErrorNoError` | **la marque est effacée** | | `"user"` sur la seule borne visée | `EnergyErrorNoError` | rang inchangé, seul ce champ change | | deux renommages voisins ensuite | `EnergyErrorNoError` | **`"user"` survit** | -Le coût annoncé est donc réel et vérifié : le badge « rang posé par la box » a disparu d'une -borne que personne n'avait classée, au renommage d'une autre charge. La fragilité ne touche -que `"auto"` — `"user"`, lui, traverse les gestes voisins. +> ⚠️ **La première ligne ne dit PAS ce que j'ai d'abord conclu.** J'y avais lu « l'écho +> verbatim est refusé ». C'est faux : le moteur porte une exception écrite exprès +> (`reconcileRankOrigin()`) qui **accepte `"auto"` quand le persisté le porte déjà** — +> précisément pour ne pas rompre la neutralité `Get` → `Set`. Entre ma lecture et mon +> écriture, la marque avait été consommée par une manipulation concurrente : mon écho était +> donc **périmé**, et son refus est le bon comportement. Deux cas distincts, un seul +> symptôme — et c'est exactement pourquoi une mesure sans relecture immédiate ne prouve +> rien (cf. le contrôle de la suppression, qui relit avant de conclure). +> +> **Ce qui reste à mesurer** : un écho *inchangé* sur une marque *fraîche*. Tant que ce +> n'est pas fait, `sansRankOriginAuto()` reste — et le jour où l'écho passe, elle part et la +> marque survit aux gestes qui ne la concernent pas. + +Le reste tient : `"user"` s'écrit, ne déplace pas le rang, et **survit** aux gestes voisins. +L'effacement observé de `"auto"` est, lui, **le fait de l'app** — de son nettoyage, pas d'un +refus de la box. > ⚠️ **Un refus arrive en `status: "success"`.** Le verdict est dans `params.energyError`, > et un contrôle sur `status` seul le prend pour un succès. Le service de l'app teste bien diff --git a/lib/services/load_priority.dart b/lib/services/load_priority.dart index 7345d01..f260a74 100644 --- a/lib/services/load_priority.dart +++ b/lib/services/load_priority.dart @@ -155,11 +155,15 @@ List tiedByPriority(List entries) { /// installation avec une borne neuve deviendrait non modifiable), renvoyer `"auto"` (refus /// systématique), ou effacer une marque informative. /// -/// **Contournement, pas solution.** La demande est portée au moteur : tolérer l'écho -/// *inchangé*, la règle devant porter sur le **changement** et non sur la **présence** — -/// même distinction que l'effacement de `rankOrigin`, qui porte sur « rang différent pour -/// cet id » et non sur « écriture reçue ». Le jour où l'écho passe, cette fonction disparaît -/// et la marque survit aux gestes qui ne la concernent pas. +/// **Contournement EN SURSIS.** Le moteur porte déjà l'exception demandée — +/// `reconcileRankOrigin()` accepte `"auto"` quand le persisté le porte déjà, pour ne pas +/// rompre la neutralité `Get` → `Set`. Le refus mesuré le 2026-08-29 côté app portait un +/// écho **périmé** : la marque avait été consommée entre la lecture et l'écriture, et +/// refuser un écho périmé est le bon comportement. +/// +/// Dès que l'écho *inchangé* sur une marque *fraîche* sera vérifié, **cette fonction +/// disparaît** — et la marque survivra alors aux gestes qui ne la concernent pas, ce qui +/// est le comportement voulu. Elle ne reste que le temps de cette vérification. /// /// Le motif général — *un interdit d'écriture doit se prononcer sur l'écho inchangé* — est /// écrit en `docs/UI_data_contract.md` §10, avec le contrôle à faire une fois par règle. diff --git a/tools/rpc/README.md b/tools/rpc/README.md index 030ff78..dabf00c 100644 --- a/tools/rpc/README.md +++ b/tools/rpc/README.md @@ -28,6 +28,33 @@ dart tools/rpc/