diff --git a/docs/BRIEF_plugin_depuis_maquettes.md b/docs/BRIEF_plugin_depuis_maquettes.md index 1414cc5..451754b 100644 --- a/docs/BRIEF_plugin_depuis_maquettes.md +++ b/docs/BRIEF_plugin_depuis_maquettes.md @@ -2,6 +2,98 @@ --- +## 2026-08-30 — R3 : `counts` est retenu, et `funding` sort de la réconciliation + +**Réponse à la question du moteur sur le niveau mixte.** La forme proposée est prise telle +quelle : `funding` reste, `counts` s'y ajoute, `Σ counts == targetW` toujours, et `counts` +est publié même à une seule destination. + +### Le code unique l'emporte — et l'argument contre l'omission est vérifiable, pas seulement juste + +L'omission n'est pas neutre **dans le code qui tourne aujourd'hui** : `resolvedFunding` rend +`null` quand rien n'est publié, et `isSurplusFunded` rend alors `true` +(`lib/models/load_telemetry.dart`). Un niveau mixte sans `funding` serait donc rangé **avec +les charges du soleil**, en silence. L'omission porterait déjà une affirmation — et la pire +des deux. + +### Mais « approximation » est le mauvais mot, et le garder coûterait le champ + +Tant que `funding` est décrit comme approximatif, quelqu'un finira par vouloir le rendre +exact : part dominante, seuil de majorité. Ce serait un libellé qui **bascule d'un cycle à +l'autre** sur 900/480, sans qu'aucune décision n'ait changé. + +**La règle que nous demandons d'écrire à sa place : `grid` l'emporte dès qu'un watt est +acheté.** Déterministe, indépendante des proportions, et alignée sur ce qu'un humain doit +savoir — l'achat est le fait actionnable, le surplus est l'ordinaire. Elle vaudra telle +quelle pour le plancher éco acheté au réseau (§10) sans nouvelle décision à prendre. + +### Ce qui rend l'ensemble soutenable : `funding` sort de la comptabilité + +Avec `counts` **toujours** publié, `funding` ne participe plus à aucun calcul de +réconciliation. Il ne dit plus que : *faut-il en parler ?* — et `counts` dit *combien, et +où*. Aucun des deux ne se dérive de l'autre, et l'approximation qui reste n'entre plus dans +un total. Côté écran, la carte d'un niveau mixte dira **« en partie achetée — 480 W sur +1 380 »** : `funding` déclenche la phrase, `counts` la chiffre. + +### Et `"mixed"` publié ? Non — et c'est notre propre code qui le dit + +C'est bien la troisième voie, elle mérite d'être posée, et nous la refusons. Trois raisons, +dans l'ordre de force : + +**1. Il reproduirait EXACTEMENT la panne de l'omission, sur le même chemin de code.** Tout +client qui teste `funding == 'grid'` a une branche par défaut, et cette branche est +« surplus » — la nôtre l'était encore ce matin (`isSurplusFunded => funding != 'grid'`). +Une troisième valeur y tombe **sans erreur**, et range au soleil un niveau dont une part est +achetée. C'est le défaut que l'omission produisait, avec un champ présent en plus pour faire +croire le contraire. + +**2. Il serait dérivable — donc il violerait votre propre règle.** `"mixed"` ⟺ `counts` a +plus d'une destination non nulle. Un champ publié qui se recalcule depuis un autre est +précisément celui que quelqu'un supprimera un jour comme redondant, et il aura raison. + +**3. Il ne répond pas à la question que `funding` pose.** `funding` dit *d'où viennent ces +watts* ; `"mixed"` dit *qu'il y a deux réponses* — une réponse sur la question, pas sur les +watts. Et l'information actionnable qu'elle promet (**combien** est acheté) est déjà dans +`counts`, en clair. + +**La ligne qui sépare nos deux `mixed`** : le nôtre est **dérivé, local, jamais transporté** +— `resolvedFunding` le fabrique pour une CHARGE dont les niveaux divergent, uniquement pour +empêcher une carte d'affirmer une origine unique là où il y en a deux. Il est légitime parce +qu'il est dérivable ; le vôtre serait illégitime pour la même raison. **On publie ce qui ne +se dérive pas, on dérive ce qui se dérive** — et cette règle range `funding`, `counts` et +`mixed` chacun à sa place sans qu'aucun ne soit redondant. + +### Trois choses en échange, et elles sont de notre champ + +**a. Une clé inconnue ne doit jamais disparaître.** Nous traiterons les clés de `counts` +comme des **identifiants opaques**, jamais comme des chemins à parser. Si `draw.committedW` +arrive sur une box plus récente que l'app, elle vérifiera quand même `Σ counts == targetW` +— la règle ne dépend pas du sens des clés — mais dira **« destination inconnue de cette +version »**, jamais zéro. Corollaire pour vous : **ne réutilisez jamais une clé existante +pour un sens nouveau**. C'est le seul cas qu'aucun client ne peut détecter. + +**b. Publiez `counts` même à zéro, avec sa destination.** Mesuré sur `.75` ce matin (cycle +06:14) : un niveau `targetW: 0` **est** publié, avec le motif qui dit pourquoi. Un +`counts: {}` y satisferait l'identité (0 == 0) tout en perdant la destination — un trou +exactement sur le cas le plus fréquent, et de la même famille que celui que `counts` vient +fermer. Une clé, valeur 0. + +**c. Dites qui fait foi entre `counts` et les params d'`EV_GRID_START`.** Les deux porteront +le même partage (`budgetW` / `gridW`). Notre lecture : **`counts` fait foi pour la +comptabilité**, les params restent pour la **phrase** du motif — catalogue fermé, testé sur +le texte. Si vous les gardez, dites-le ; s'ils divergent un jour, c'est `counts` que nous +croirons. + +### Ce que ça change pour nous, et quand + +R3 devient vérifiable **par niveau**, sans connaître le sens des compteurs — c'est plus fort +que ce que nous demandions. L'exception `EV_GRID_START` disparaîtra du contrat **le jour où +la sonde la verra disparaître de la box** : d'ici là elle reste écrite dans `CLAUDE.md` et +traitée dans `surplusShareW`, et nous ne touchons ni l'un ni l'autre. Contrat, pas feuille +de route — comme pour `levels[]`. + +--- + ## 2026-08-29 — RÉPONSE au §9 : les deux passes du §10, vues de l'écran **Maquette : `docs/mockups/deux_passes_eco_confort_mockup.html`** — trois écrans, un catalogue diff --git a/docs/mockups/deux_passes_eco_confort_mockup.html b/docs/mockups/deux_passes_eco_confort_mockup.html index c934f97..f92a057 100644 --- a/docs/mockups/deux_passes_eco_confort_mockup.html +++ b/docs/mockups/deux_passes_eco_confort_mockup.html @@ -611,6 +611,8 @@
Σ targetW et allocatedW : ils sont égaux par
construction. Cherché là, l'arrondi est invisible et l'écran se tait sans se tromper.counts, il n'y en a plus une seule.
+ Un écart qui subsiste est un défaut, et il se dit.Parti le 2026-08-29 — l'argument de coût a emporté la priorisation. C'est la première des huit à être écrite.
-Trois destinations coexisteront : budget.allocatedW (surplus), budget.evReservedW
- (réseau, proxy VE) et draw.committedW (réseau, plancher éco). Dites où va chaque
- (niveau, financement) — l'app ne doit pas le deviner, sinon deux clients afficheront deux bilans
- différents du même cycle. C'est la leçon d'EV_GRID_START, qui partage une allocation entre deux
- compteurs et qui aurait cassé notre réconciliation en silence. Tranché le 2026-08-29 : les compteurs
- comptent le décidé — reste à publier la destination de chaque couple (niveau, financement).
La forme du moteur est prise telle quelle (2026-08-30) : à côté de funding, un
+ counts qui nomme les registres, avec Σ counts == targetW toujours, publié
+ même à une seule destination. L'identité devient calculable sans exception et par niveau :
+ l'exception EV_GRID_START, qui partageait une allocation entre deux compteurs, disparaît —
+ remplacée par une règle vérifiable qui vaudra telle quelle quand draw.committedW arrivera.
Les deux champs ne se dérivent pas l'un de l'autre, et c'est ce qui empêchera qu'on en supprime un :
+ funding dit l'origine (« ces watts sont achetés » — voisin du motif), counts
+ dit le registre (« ils sont comptés ici » — une comptabilité).
Sur un niveau mixte, un code unique : "grid" — et la règle demandée n'est pas « une
+ approximation » mais « grid l'emporte dès qu'un watt est acheté ». Déterministe, indépendante des
+ proportions (un libellé qui bascule sur 900/480 serait pire que faux), et alignée sur ce qu'un humain doit
+ savoir : l'achat est le fait actionnable. Elle vaudra sans nouvelle décision pour le plancher éco du §10.
+ Ni omission (notre isSurplusFunded range alors le niveau au soleil, en silence)
+ ni "mixed" publié : une troisième valeur tomberait dans la branche par défaut de tout
+ client — « surplus » — donc reproduirait la panne de l'omission, et elle serait dérivable de
+ counts, donc supprimée un jour à juste titre.
Ce que l'app promet en échange : les clés de counts sont traitées comme des
+ identifiants opaques, jamais comme des chemins. Une clé inconnue d'une version ancienne n'est pas
+ perdue : l'identité Σ counts == targetW reste vérifiable sans connaître le sens des clés, et
+ l'écran dit « destination inconnue de cette version », jamais zéro. Corollaire pour le moteur : ne
+ jamais réutiliser une clé existante pour un sens nouveau — c'est le seul cas qu'aucun client ne peut
+ détecter.
Corrigé le 2026-08-29 : notre prémisse était fausse. allocatedW publie le