diff --git a/docs/BRIEF_plugin_depuis_maquettes.md b/docs/BRIEF_plugin_depuis_maquettes.md index f6a0c0c..18d3549 100644 --- a/docs/BRIEF_plugin_depuis_maquettes.md +++ b/docs/BRIEF_plugin_depuis_maquettes.md @@ -2,6 +2,67 @@ --- +## 2026-09-01 — §10 vu à la sonde : les six champs, et une trajectoire à trancher + +**Obligation déclarée sur le banc puis retirée** — `chauffe-eau`, `needs {dailyDeadline: "12:00", +minEnergyWhPerDay: 4000}`, sept cycles, `+etm43`. Capture sur disque avant la première écriture, +restauration **depuis le fichier**, comparaison clé par clé : *« 0 écart »*. + +### La forme est celle qui était annoncée, et elle porte plus que le motif + +```jsonc +{ "level": "eco", "funding": "grid", "targetW": 766.813994355397, + "counts": { "draw.committedW": 766.813994355397 }, + "progress": { "regime": "unmeasurable", "targetWh": 4000 }, + "decision": { "code": "ECO_FLOOR_GRID", "params": { + "gridW": 767, "remainingWh": 4000, "targetWh": 4000, + "remainingS": 18779, "regime": "unmeasurable", "atMaximum": false } } } +``` + +`decision` et `progress` **au niveau**, `deliveredWh` **absent** sous `unmeasurable`, `counts` qui +tombe sur `draw.committedW`, et le motif racine qui porte `"level": "comfort"`. R1, R5 et R7 sont +vérifiés sur le fil. Les deux identités tiennent à chaque cycle. + +### Le dernier cycle est le cas que la maquette visait, et il valide R7 durement + +À 05:47 le surplus passe à **−922 W** : le niveau `comfort` tombe à `targetW: 0` avec +`SURPLUS_INSUFFICIENT` et `counts {"budget.allocatedW": 0}` — destination publiée **à zéro**, comme +demandé — pendant que le niveau `eco` **achète 767 W au réseau**. + +Le motif racine de cette charge vaut alors `SURPLUS_INSUFFICIENT`. **Un client d'avant `levels[]` lit +donc « surplus insuffisant, rien fait » sur une charge en train d'acheter 767 W.** Ce n'est pas une +vue incomplète, c'est une vue **fausse** — et c'est l'argument le plus dur en faveur de +`decision.level` et des deux lignes à l'écran. + +### La trajectoire, mesurée — et la question qu'elle pose + +| cycle | `remainingWh` | `remainingS` | `gridW` | +|---|---|---|---| +| 05:42 | 4 000 | 19 079 | 755 | +| 05:45 | 4 000 | 18 899 | 762 | +| 05:47 | 4 000 | 18 779 | 767 | + +Sous `unmeasurable`, rien n'est soustrait : **le plancher ne peut jamais se refermer**, donc l'achat +s'accélère mécaniquement jusqu'à l'échéance et finit en `ECO_FLOOR_MISSED`. Ce n'est pas un cas +limite du régime, c'est sa trajectoire garantie. La maquette l'affiche désormais — *reste* et +*temps*, pas seulement les watts de l'instant. + +**Et le point qui mérite votre arbitrage** : cette charge **a un compteur**. `ECS-Meter` publie +`currentPower: 1500` **et `totalEnergyConsumed: 10`** — une énergie, la grandeur exacte qui manque. +Le régime sort quand même `unmeasurable`. Si c'est `LoadContextTelemetry::sessionWh` toujours +déclaré et jamais rempli hors borne, alors **aujourd'hui toute obligation éco achète à l'aveugle et +accélère, y compris sur une charge instrumentée**. Deux questions, et elles ne sont pas d'écran : +faut-il remplir `sessionWh` depuis le compteur de charge, et faut-il acheter du tout quand on ne +peut pas vérifier ? Notre écran montrera la trajectoire ; il ne la corrigera pas. + +### Un détail à confirmer + +`gridW: 767` (entier) et `targetW: 766.813994355397` (double) portent le même fait, et `counts` +s'accorde avec `targetW`. Nous prenons donc **`targetW`/`counts` pour l'arithmétique** et `gridW` +**pour la phrase**. Confirmez si c'est l'intention. + +--- + ## 2026-08-30 (soir, lien rétabli) — relevé frais : deux confirmations et une correction ### `chargingState` figé : confirmé sur lien VIVANT, ce n'est pas de la péremption diff --git a/docs/mockups/deux_passes_eco_confort_mockup.html b/docs/mockups/deux_passes_eco_confort_mockup.html index 27fb8bc..0471a85 100644 --- a/docs/mockups/deux_passes_eco_confort_mockup.html +++ b/docs/mockups/deux_passes_eco_confort_mockup.html @@ -338,10 +338,11 @@ ÉCO
setpointW, currentA), qui existe déjà aujourd'hui.
unmeasurable, le plancher ne peut pas se refermer — mesuré le
+ 2026-09-01 sur quatre cycles : remainingWh figé à 4 000, remainingS qui
+ descend, gridW qui monte 755 → 767. Ce n'est pas un cas limite, c'est la
+ trajectoire garantie du régime : l'écran doit montrer reste et temps, pas
+ seulement les watts de l'instant, sans quoi « 767 W achetés » ne laisse pas deviner le mur.budget.evReservedW est un terme de correction : la latence entre l'ordre et sa
lecture au compteur. Il est affiché parce que la box le publie, jamais sommé. Son ancien
@@ -654,16 +660,15 @@
// L'appliqué vit dans "mechanism" ; le mesuré dans "measurement".
"levels": [ // AJOUT — un élément par passe RÉELLEMENT parcourue
- { "level": "eco",
- "targetW": 1400, // la part de ce décidé qui revient à ce niveau
- "funding": "grid", // L'ORIGINE — « ces watts sont achetés ». Livré en +etm30.
- "counts": { "draw.committedW": 1400 }, // LE REGISTRE — « ils sont comptés ici ».
- // Σ counts == targetW, toujours. Publié même à une seule
- // destination, et même à zéro, avec sa destination.
- "decision": { "code": "ECO_FLOOR_GRID",
- "params": { "deliveredWh": 2100, "targetWh": 3000, "gridW": 1400 } },
- "progress": { "regime": "measured", // measured | estimated | unmeasurable
- "deliveredWh": 2100, "targetWh": 3000 } }, // deliveredWh ABSENT si unmeasurable
+ { "level": "eco", // RELEVÉ sur `.75` le 2026-09-01, +etm43
+ "targetW": 766.813994355397, // le décidé, NON arrondi
+ "funding": "grid",
+ "counts": { "draw.committedW": 766.813994355397 },
+ "progress": { "regime": "unmeasurable", "targetWh": 4000 },
+ // deliveredWh ABSENT sous unmeasurable — jamais 0
+ "decision": { "code": "ECO_FLOOR_GRID", "params": {
+ "gridW": 767, "remainingWh": 4000, "targetWh": 4000,
+ "remainingS": 18779, "regime": "unmeasurable", "atMaximum": false } } },
{ "level": "comfort",
"targetW": 0,
"decision": { "code": "SURPLUS_INSUFFICIENT", "params": { "requiredW": 900, "availableW": 0 } } }
@@ -751,7 +756,16 @@
pendant que l'installation en tire 1 000 — d'où le bloc « trois nombres » de l'écran 3, qui empêche de
lire cet écart comme une erreur de comptage.
- Vérifié à la sonde le 2026-09-01 : progress et decision descendent au
+ niveau, et deliveredWh est bien absent sous unmeasurable.
Et le motif publie remainingWh, pas deliveredWh — accepté. Ce n'est pas
+ « une source par fait » qui tranche (on aurait pu retirer deliveredWh de progress)
+ mais ceci : remainingWh n'est pas dérivable sous unmeasurable, et c'est
+ exactement le régime où l'on achète. Un champ qui n'existe que là où on peut le calculer ferait taire
+ l'écran dans le cas qui coûte de l'argent. Sous unmeasurable,
+ remainingWh == targetWh : « 4 000 sur 4 000 » se lit « rien de mesurable », jamais
+ « rien livré ».
progress.regime ∈ measured | estimated | unmeasurable, et deliveredWh
absent sous unmeasurable — jamais 0. C'est la même règle que
measurement.source = "none", qui nous a déjà servis : un régime publié sépare « pas mesurable »