diff --git a/AGENTS.md b/AGENTS.md index c8f0240..e6231f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -204,6 +204,26 @@ vers un gestionnaire d'énergie complet (EV, ECS, PAC SG-Ready, batterie). > (3 680 W au lieu de 6 000). Suites : simulation 29/29, charging 16/16, loadmodel 18/18, > spotmarket 7/7 — amd64 0 erreur / 0 avertissement. +**DÉPLOYÉ SUR `.75` — `1.15.2+etm26`, 2026-08-28.** Cross-build arm64 dans `build-cross-arm64` +(bundle git → `/root/build-etm26`), posé par `deploy.sh`, version relue sur la box, `nymead` +actif. `measuredW` a bien disparu de la charge utile ; `measurement {source, powerW}` est publié. + +> **Trois vérifications de banc restent MASQUÉES par la configuration de la box, et ce n'est pas +> un défaut** — c'est LM-1105 qui joue : +> - `chauffe-eau` et `pac-terrain` portent chacun un `meterThingId` vers un compteur RÉEL et +> distinct (`ECS-Meter` 1 500 W, `PAC-Meter` 800 W). Ils publient donc `source: "meter"`, et +> le chemin `device` n'est jamais atteint. **La `pac-terrain` ne publie donc PAS `none`** : le +> compteur explicite l'emporte, y compris sur un `sg-ready`. LM-1105-b décrit ce que la PAC +> publierait *sans* compteur dédié. +> - Les **deux bornes sont `pluggedIn: false`** (V2C Trydan en `ChargingModeEcoWithMinCurrent`, +> wallbox simulée en `ChargingModeEco`, aucune voiture assignée — donc plus exclues par ce +> motif depuis `+etm25`). Elles sont **absentes de `loads[]`**, pas en `none` : la V2C ne peut +> donc pas montrer son `source: "meter"` tant que rien n'y est branché. +> +> Pour observer `device` sur l'ECS et `none` sur la PAC, il faut **retirer temporairement leur +> `meterThingId`** — `SetLoadConfig`, champ SOUPLE, aucun rebuild d'adaptateur ni réarmement de +> verrou. Non fait : c'est la configuration du banc, elle appartient à l'installateur. + **À VÉRIFIER AU BANC, distinct et non tranché** : **le compteur racine lit ~1,5 kW de moins que la somme des charges mesurées** (3 250 W contre 3 980 W pour la seule V2C, plus 800 W de PAC). Même famille que l'aveuglement documenté aux résistances ECS. Ce n'est pas un problème diff --git a/INTERFACE.md b/INTERFACE.md index e9f80e9..6fc08eb 100644 --- a/INTERFACE.md +++ b/INTERFACE.md @@ -717,6 +717,24 @@ allocations irréconciliable avec `budget.allocatedW`. > pouvoir détecter un mensonge.** C'est ce qui justifie de laisser `meterThingId` **disponible** > sur une charge qui publie déjà sa puissance : masqué par défaut, jamais interdit. +> **Une charge ABSENTE de `loads[]` n'est pas `none`.** *(Distinction remontée par l'agent app, +> 2026-08-28, et confirmée sur le banc le jour même.)* `none` est **publié** : il AFFIRME « cette +> charge n'est pas mesurable ». L'absence n'affirme rien — elle dit seulement que la charge n'a +> **pas participé à l'arbitrage de ce cycle**, ce qui est une question sans rapport avec la +> mesure. Une borne en mode manuel ou sans véhicule branché sort de `loads[]` (voir +> `GetLoadTelemetry`, exclusions du waterfall) alors qu'elle publiera sa propre puissance dès le +> cycle où elle y rentrera. +> +> Sans cette distinction, un client afficherait « pas mesurable — le compteur dédié est la seule +> voie » sur une borne débranchée qui, une fois branchée, mesure très bien toute seule. +> **Constaté tel quel sur `.75` en `+etm26`** : deux bornes `pluggedIn: false`, absentes de +> `loads[]`, dont l'une porte `currentPower` et publiera `device`. +> +> La règle est simple parce que `measurement` n'est jamais omis d'une entrée présente : **la clé +> existe pour toute charge de `loads[]`, et pour elle seule.** Donc — charge dans `loads[]` : +> lire `measurement.source`. Charge absente : ne rien conclure sur sa mesurabilité, et ne rien +> afficher qui l'affirme. + > **Décidez sur `source`, jamais sur `adapter`.** « Masquer le compteur dédié sauf pour > `sg-ready` » paraît équivalent et ne l'est pas : un `relay-router` à topologie **mixte** > publie lui aussi `none`, et un client qui déciderait au mécanisme masquerait le champ sur un diff --git a/specs/spec_loadmodel.md b/specs/spec_loadmodel.md index 170ce07..baa2228 100644 --- a/specs/spec_loadmodel.md +++ b/specs/spec_loadmodel.md @@ -997,6 +997,18 @@ o:measurement { distinguer « pas mesurable » de « compteur en panne », et continue d'afficher un bloc de mesure vide sur un `sg-ready` qui n'en aura jamais. +> **Et `none` ne se confond pas avec l'ABSENCE de la charge.** *(Distinction remontée par +> l'agent app, 2026-08-28.)* `none` est **publié**, donc il AFFIRME. L'absence n'affirme rien : +> elle dit que la charge n'a pas participé à l'arbitrage du cycle — mode manuel, aucun véhicule +> branché — ce qui est sans rapport avec sa mesurabilité. Une borne débranchée est absente de +> `loads[]` et publiera `device` dès qu'on y branchera une voiture ; lui annoncer « le compteur +> dédié est la seule voie » serait faux. +> +> C'est la même famille que LM-1009 D — *un champ absent se voit ; un champ qui s'efface se lit +> comme un zéro* — appliquée un cran plus haut : ici c'est l'ENTRÉE entière qui s'efface, et la +> lire comme un `none` transformerait un silence en affirmation. La garantie qui rend la règle +> utilisable : **`measurement` est présent pour toute charge de `loads[]`, et pour elle seule.** + > **Sous `none`, aucune valeur n'est publiée sous ce nom.** La puissance *nominale* existe et > reste lisible — `mechanism.stageW`, `mechanism.state`, `mechanism.estimatedPowerW` la portent > déjà, et disent d'où elle vient. La faire passer pour une mesure produirait un écart