+etm55 vérifié (posé le 04/09 18:21:08). Le taux constant est en ligne : la
maquette porte le bon chiffrage — ×4,75 sur une fenêtre quotidienne, facteur
ln(T·P/E) + 1 — et les deux interdits du régime `unmeasurable` : ni annoncer que
l'achat va s'intensifier, ni lire `atMaximum: false` comme « tout va bien », qui
signifie qu'il n'y a aucun étalement, donc rien qui puisse cesser.
La troisième nature d'heure murale touche du code livré : `fetchDailyBalance()`
et la baseline des ratios prennent minuit du TÉLÉPHONE, alors qu'une journée de
reporting suit l'installation. Sur `.75` en Europe/London vue d'un téléphone
français, entre minuit et 1 h l'app compte une journée que la box compte encore
dans la précédente.
L'app ne peut pas le corriger seule : `System.GetTime` publie un nom IANA, et un
décalage ne s'en déduit pas sans base de fuseaux — qu'il faudrait embarquer pour
recalculer une frontière que la box connaît, et qui resterait fausse les jours de
changement d'heure. Demandé au moteur : publier le DÉBUT de la journée de
reporting en cours, en epoch, à côté du fuseau. La divergence est écrite aux deux
endroits du code en attendant.
Noté sans conclure : le banc n'a aucune charge `unmeasurable`, donc la loi est
déployée mais pas exerçable de bout en bout.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Sonde en LECTURE SEULE — l'obligation est celle du moteur, rien n'a été écrit.
Le critère positif est atteint : `deliveredWh` +25 Wh/min (1 500 W, ce que le
compteur ECS annonce), `remainingWh` qui descend d'autant, `gridW` 466 → 463.
Décroissance, pas absence de mur.
Deux invariants tiennent, et l'écran les vérifiera à chaque trame :
- `deliveredWh + remainingWh == targetWh` — et c'est sous `measured` qu'elle
mord, là où elle n'est plus le corollaire trivial d'`unmeasurable` ;
- `gridW == remainingWh / remainingS` — 466 == 466 puis 463 == 463, donc la loi
d'étalement est vérifiable de l'extérieur, sans lire le code.
Fuseau : `remainingS` le confirme de notre côté (18 719 s à 06:48 heure box
mènent à 12:00 heure box), et `System.GetTime` publie `timeZone` — l'app peut
donc être honnête sans attendre l'arbitrage. Règle écrite dans CLAUDE.md et dans
la maquette : dire l'horloge au lieu de la choisir, fuseau de la box affiché à
côté du champ et divergence signalée. Ce que le lot moteur doit trancher reste
entier : d'où vient le fuseau, et ce qu'il fait quand il diverge.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Obligation déclarée sur le banc puis retirée (`chauffe-eau`, 4 000 Wh avant
12:00, +etm43, sept cycles). Capture sur disque avant la première écriture,
restauration DEPUIS le fichier, comparaison clé par clé : 0 écart.
La forme est celle annoncée, et elle porte plus que le motif : `decision` et
`progress` descendent au niveau, `deliveredWh` est absent sous `unmeasurable`,
`counts` tombe sur `draw.committedW`, et le motif racine porte `level`.
R1, R5 et R7 vérifiés sur le fil ; les deux identités tiennent à chaque cycle.
Deux choses que la mesure apprend, et qu'aucune lecture de code n'aurait données :
- au cycle 05:47 le surplus passe à −922 W : `comfort` tombe à 0 avec
`SURPLUS_INSUFFICIENT` pendant que `eco` achète 767 W au réseau. Le motif
RACINE vaut alors `SURPLUS_INSUFFICIENT` — un client d'avant `levels[]` lit
donc « rien fait » sur une charge qui achète. Vue fausse, pas incomplète ;
- sous `unmeasurable`, `remainingWh` ne bouge pas et `remainingS` descend, donc
`gridW` monte (755 → 767 en quatre cycles). Le plancher ne peut jamais se
refermer : l'accélération jusqu'au mur est la trajectoire GARANTIE du régime,
pas son cas limite. La maquette affiche désormais reste + temps, et pas
seulement les watts de l'instant.
Question posée au moteur : la charge a un compteur (`totalEnergyConsumed: 10`)
et le régime sort quand même `unmeasurable`. Faut-il remplir `sessionWh` depuis
le compteur, et faut-il acheter quand on ne peut pas vérifier ?
`remainingWh` plutôt que `deliveredWh` est accepté, et R5 porte l'argument :
`remainingWh` n'est pas dérivable sous `unmeasurable`, qui est justement le
régime où l'on achète.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Lien Modbus rétabli, Skoda en charge, valeurs en mouvement.
- `sessionEnergy` : notre doc était EN RETARD, pas contredite. La V2C la publie
depuis le plugin +etm13 et elle bouge (15,8015 → 15,8405 kWh). L'écart avec
`chargeEnergy` vaut 7,2044 kWh aux deux échantillons pris à deux heures
d'écart — constant au dix-millième : c'est l'accumulateur du plugin, et il
prouve l'accumulation que le code seul ne montrait pas. LM-1009 C1 reste vraie
pour les bornes sans cet état ; la V2C n'en fait plus partie. La maquette ne la
nomme donc plus dans l'exemple « non mesurable ».
- `chargingState` reste `Idle` sur un lien VIVANT, pendant que la borne tire
4 372 W : ce n'est pas de la péremption, personne ne maintient le champ.
Et un constat qui n'est pas dû au WiFi : la box a journalisé « Restoring manual
values of false 6 A » trois secondes après la coupure ; la borne est restée à
`power: true`, 7 A, et le lien est revenu sans que rien ne réapplique. En mode
manuel personne ne commande, donc l'écart est permanent — 4,4 kW tirés,
`draw.committedW` à 0. Question posée au moteur.
Aucun avancement n'est affiché pour autant : c'est une décision (D1), pas une
mesure qui manquerait.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Le moteur a livré la définition d'`evReservedW`, et il ne pouvait pas l'écrire
avant d'en avoir sorti la part réseau d'`EV_GRID_START` : un champ à deux natures
ne se documente pas. Le libellé tranché est le sien, parce qu'il dit la chose —
la latence entre l'ordre et sa lecture au compteur.
« Réservé au véhicule » affirmait deux faussetés : que c'est réservé, et que ça
regarde le véhicule plutôt que la latence de sa mesure.
La clé ARB garde le nom du champ de la box (`budgetEvReserved`), pas celui de
l'ancienne affirmation. Et la consigne qui compte reste écrite à côté : ce n'est
pas un registre, on ne réconcilie rien dessus — la nature du champ l'interdit,
pas son état de livraison.
`draw.committedW` : annoncé livré en +etm31, NON vérifié à la sonde. La box porte
`powersync-energy-plugin-nymea 1.15.2+etm30` au 2026-08-30 et ne publie aucune
clé `draw`. L'exception `EV_GRID_START` reste donc dans `surplusShareW` : c'est
la sonde qui autorise le retrait, pas l'annonce.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Le moteur l'a trouvé en câblant `counts` : `budget.evReservedW` est un terme de
CORRECTION du budget, pas un registre d'allocation. Il mêle la correction
« commandé non encore mesuré » à la part réseau d'`EV_GRID_START`, et une borne
servie au réseau qui tire déjà ce qu'on lui a commandé y contribue 0 pour un
`targetW` de 7 000 W. `Σ counts == targetW` y serait vraie au premier cycle après
un changement et fausse ensuite : une identité dépendante du temps, qui passe
tous les tests et certifie un total faux. Ne pas livrer était le bon appel.
Réponse : `draw.committedW` en préalable, oui, sans réserve — et trois demandes :
par cycle, en watts, dans la même trame que `budget` ; publié SEUL, les quatre
autres champs de `draw` absents et jamais à 0 (un `authorisedW` forgé afficherait
un plafond de soutirage qui n'existe pas) ; et une définition d'`evReservedW`,
que nous affichons sous « Réservé au véhicule » — un libellé qui affirme une
réservation là où il y a une correction, et que nous ne renommerons pas au jugé.
Nous portions la fausse affirmation en cinq endroits (`CLAUDE.md` ×2, le modèle
×3, la description ARB) : retirée ici, sans changement de comportement. Elle ne
relève pas de la discipline « attendre la sonde » — celle-ci arbitre ce que fait
la box, pas ce que nous en avions cru, et la phrase est fausse aujourd'hui.
Il n'existe donc qu'UNE identité vérifiable, et elle ne couvre qu'un côté :
Σ targetW(surplus) == budget.allocatedW. Côté réseau, rien — pas « à vérifier
plus tard », rien, jusqu'à `draw.committedW`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
Arbitrage rendu au moteur avant qu'il n'écrive R3. La forme proposée est prise
telle quelle : `funding` reste, `counts` s'ajoute, `Σ counts == targetW`
toujours, publié même à une seule destination. L'exception `EV_GRID_START`
disparaît du contrat, remplacée par une règle vérifiable par niveau.
Trois apports de notre côté :
- « approximation » est le mauvais mot et coûterait le champ : quelqu'un
voudrait le rendre exact, et un libellé par part dominante basculerait d'un
cycle à l'autre sur 900/480. Règle demandée : **`grid` l'emporte dès qu'un
watt est acheté** — déterministe, et vraie sans nouvelle décision pour le
plancher éco du §10 ;
- `"mixed"` publié est refusé, et c'est notre propre code qui le dit : une
troisième valeur tombe dans la branche par défaut de tout client — « surplus »
— donc reproduit la panne de l'omission, avec un champ présent en plus pour
faire croire le contraire. Et il serait dérivable de `counts`, donc supprimé
un jour à juste titre. Notre `mixed` reste dérivé, local, jamais transporté ;
- ce que l'app promet : clés de `counts` traitées comme identifiants opaques,
une clé inconnue dit « destination inconnue de cette version », jamais zéro.
Contrat, pas feuille de route : `CLAUDE.md` et `surplusShareW` gardent
l'exception écrite tant que la sonde ne l'a pas vue disparaître de la box.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
La maquette `docs/mockups/deux_passes_eco_confort_mockup.html` répond aux trois
questions du brief plugin §9 (= DESIGN_10 8.5), et sert de contrat au moteur.
- la liste reste ordonnée par RANG : l'ordre de service n'est pas une propriété
de la configuration — il change d'un cycle à l'autre selon les planchers déjà
atteints, donc une liste triée par lui bougerait sous le doigt ;
- une entrée par charge, deux lignes dans la carte : on dédouble là où l'objet
affiché est la SÉQUENCE, jamais là où c'est la CHARGE — d'où un second écran,
« ordre de service du cycle », en lecture seule ;
- « éco servi / confort non » s'affiche en deux états NOMMÉS : en fraction, le
régime nominal se lirait comme une dégradation permanente.
Huit exigences pour `GetLoadTelemetry`, dont R2 (`funding` descend au niveau) et
R4, dont la prémisse a été corrigée par le moteur : `allocatedW` publie le
DÉCIDÉ, donc `Σ targetW == allocatedW` est une identité, et l'écart à afficher
vit entre le décidé et `mechanism.*` (appliqué). D'où le bloc « trois nombres ».
Contrat, pas feuille de route : aucun écran ne se construit avant `levels[]`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw