docs(§10): trois champs pour que l'écran tienne la nuance « non vérifiable »

Les deux règles du moteur sont prises. Il leur manque trois choses pour être
affichables :

1. `ECO_FLOOR_MISSED` sous `unmeasurable` — la cause porte la nuance et
   `missingWh` absent est juste, mais le COÛT manque. Sous le taux constant le
   moteur aura acheté exactement la cible et il le sait exactement : il l'a
   commandé. `draw.committedW` est une puissance par cycle, pas un cumul.
   `purchasedWh` est légitime là où `deliveredWh` ne l'est pas — l'un est une
   comptabilité, l'autre une mesure absente. Sans lui, la règle « ce que ça coûte
   par jour » ne peut être qu'une estimation de l'app.
2. Le signal de déclaration doit vivre dans `GetLoadConfig` en lecture seule, pas
   dans la télémétrie : `measurement` n'existe que pour les charges de `loads[]`,
   et une charge qu'on déclare est justement celle qui n'y est pas. Avec sa
   raison — aucun compteur / compteur sans énergie / borne sans `sessionEnergy` —
   parce que le geste de l'installateur en dépend. `meterThingId` ne suffit pas :
   un compteur peut publier la puissance sans l'énergie.
3. Après une bascule `unmeasurable → measured`, `deliveredWh` compte depuis la
   nouvelle base pendant que `targetWh` reste la cible entière : la paire cesse
   d'être une fraction, et une barre afficherait « 0,5 sur 4,0 » après une
   bascule où 3 kWh ont pu être achetés. Soit `targetWh` est rebasée, soit un
   champ dit depuis quand on mesure. Aucune barre avant que ce soit tranché.

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-09-01 07:55:47 +02:00
parent ff18dfee48
commit 5597c530fc

View File

@ -2,6 +2,73 @@
---
## 2026-09-01 (soir) — trois champs pour que l'écran puisse tenir la nuance
Vos deux règles sont prises. Il leur manque trois choses pour être **affichables**, et chacune
bloque une phrase précise.
### 1. `ECO_FLOOR_MISSED` sous `unmeasurable` : ajoutez `purchasedWh`
La cause `unmeasurable` porte bien la nuance — l'écran peut dire « non vérifiable » plutôt que
« non tenue », et `missingWh` absent est juste : on ne chiffre pas un manque qu'on ne connaît pas.
**Mais il manque le coût.** Sous le taux constant, le moteur aura acheté *exactement la cible*, et
il le sait **exactement** : il l'a commandé. Aucun écran ne peut le reconstituer —
`draw.committedW` est une puissance instantanée par cycle, pas un cumul d'obligation.
> **Et la distinction est celle de toute la semaine, appliquée à l'envers.** Ce qui est
> **acheté** est un fait que le moteur connaît sans mesure — c'est sa propre commande. Ce qui est
> **livré** est ce qu'il ne peut pas vérifier. Donc `purchasedWh` est légitime sous `unmeasurable`
> **là où `deliveredWh` ne l'est pas**, et les deux ne se confondent pas : l'un est une
> comptabilité, l'autre une mesure absente.
Sans lui, votre propre règle de saisie — « ce que ça coûte par jour » — ne peut être qu'une
**estimation de l'app**, faite à partir du taux. Nous préférerions ne pas l'inventer.
### 2. Le signal de déclaration doit vivre avec la CONFIGURATION, pas avec la télémétrie
Vous proposez que le moteur dise à la déclaration qu'une charge n'a pas de mesure d'énergie.
Oui — mais **pas dans `GetLoadTelemetry`** : `measurement` n'existe que pour les charges présentes
dans `loads[]`, et une charge qu'on est en train de déclarer est justement celle qui n'y est pas
encore — pas arbitrée, ou créée à l'instant. L'écran serait muet exactement au moment où il doit
parler.
Il le faut donc **dans `GetLoadConfig`**, en lecture seule (`r:`), présent pour **toute** entrée
configurée. Et avec sa **raison**, parce que le geste de l'installateur en dépend :
| raison | ce que l'écran propose |
|---|---|
| aucun compteur rattaché | « rattachez un compteur » — c'est réparable en une manipulation |
| compteur sans énergie (puissance seule) | « ce compteur ne compte pas l'énergie » — il faut le remplacer |
| borne sans `sessionEnergy` | rien à faire — c'est le matériel |
> `meterThingId` ne suffit pas à le déduire : un compteur peut publier `currentPower` sans
> `totalEnergyConsumed`, et l'app croirait la charge mesurable.
### 3. Changement de régime en cours d'obligation : `deliveredWh` cesse d'être une fraction
Votre précision sur la bascule est la bonne, et elle crée un piège d'affichage que LM-1014-b
décrit côté moteur mais que l'écran subit aussi.
Après un passage `unmeasurable → measured` en cours de fenêtre, la base est capturée **à cet
instant** : `deliveredWh` ne compte donc que depuis la bascule, pendant que `targetWh` reste la
cible entière. **La paire cesse d'être une fraction** — une barre d'avancement afficherait
« 0,5 sur 4,0 » après une bascule où 3 kWh ont pu être achetés. Crédible, et faux.
Deux sorties, et c'est à vous : soit `targetWh` est **rebasée** à la bascule (ce qui reste à
livrer devient la nouvelle cible), soit un champ dit **depuis quand on mesure** et l'écran affiche
« mesuré depuis 09:14 » au lieu d'une fraction. Nous n'afficherons pas de barre tant que ce n'est
pas tranché — une fraction fausse est pire qu'un chiffre absent.
### Ce qui est acté chez nous
Taux constant, `atMaximum` jamais vrai, total = la cible. `targetW`/`counts` pour l'arithmétique,
`gridW` pour la phrase. L'écran dira **« non vérifiable »**, jamais « non tenue ». Et la saisie
d'une obligation sur une charge sans mesure d'énergie portera l'avertissement — dès que le champ
du point 2 existe.
---
## 2026-09-01 (suite) — acheter sans vérifier : ce que nous proposons, et pourquoi
**Notre position : oui, mais à taux CONSTANT — l'escalade n'a pas de justification sous