Correction de mon explication du volet 2. Le chauffe-eau n'était pas à 3500 W par
reliquat mais par EMBALLEMENT, et le mécanisme change la conclusion.
Deux conditions se composent sur .75 : les Things sont des relais GPIO, dont la
ThingClass n'expose pas currentPower — le recrédit anti-clignotement crédite donc
le nominal commandé ; et le rootmeter est la vue SunSpec du simulateur, aveugle
aux résistances câblées sur ces broches — la conso ECS ne fait jamais baisser
l'export mesuré. budget_charge = surplus + palier double-compte, le palier monte
d'un cran par cycle tant que le surplus dépasse 500 W, jusqu'au plafond. C'est ce
qui explique les quatorze plateaux sans commutation, pas un point de départ
malheureux.
GARDE-FOU ajouté sous « Correction B » dans AGENTS.md et dans le relevé : c'est un
ARTEFACT DE BANC, pas un défaut du moteur. Sur une installation réelle l'ECS est
derrière le compteur réseau, sa consommation fait réellement chuter l'export, et
le recrédit compense exactement ce qu'elle vient de retirer. Le supprimer casserait
l'anti-oscillation qu'il protège (ECS-404) sans rien régler. Sans cette note,
quelqu'un « corrigerait » la correction B sur la foi de cette mesure.
ECS-303 n'est donc PAS affaibli : ma remarque valait pour ce banc, où aucune montée
pas à pas n'est possible. Avec de la physique réelle, la rampe matinale traverse la
bande 1500-2000 W lentement et la frontière est franchie normalement. Le volet 2
n'est pas à refaire depuis le palier 0 sur le simulateur — il est à faire après le
câblage, sur la vraie installation.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Documente ce qui a effectivement tourné, pas ce qui était supposé. Build
1.15.2+etm3 du 2026-08-08, cross arm64, réussi.
- L'exclusion DH_OPTIONS=-N nymea-energy-tests était citée pour debian-qt5/rules
alors que c'est qt6 qui construit (debian -> debian-qt6, dh --buildsystem=qmake6).
Vérifié avant le build : l'exclusion EST présente dans debian-qt6/rules:6, donc
seule la citation était périmée. Aucun paquet nymea-energy-tests produit.
- Les dépendances étaient annoncées « toutes en 1.15.0 » avec Qt5
(libqt5websockets5-dev, qtbase5-dev, qttools5-dev-tools). Le build réel utilise
nymea 1.15.2+202606191336~trixie1 et Qt 6.8.2 — chaîne Qt6 de bout en bout,
cohérente avec la box (aucun libqt5 installé sur .75, ldd du .so ne renvoie que
du Qt6).
- Ajouté : debian-qt6/changelog est un lien symbolique VERSIONNÉ vers
../debian-qt5/changelog, comme copyright et nymea-energy-tests.install.in. Il
n'y a qu'un changelog réel. Sans cette note, lire les deux fichiers donne
l'illusion d'une divergence — c'est l'erreur que j'ai commise et rapportée.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Couverture des fichiers non visés par la restructuration à venir : l'extraction
du noyau de calcul (étape 2) et celle de m_relayMapping (étape 3) ne les
touchent pas. relayrouter.h et energyarbitrator.h sont volontairement DIFFÉRÉS —
documenter ce qui va changer produirait du bruit d'historique.
Mesure sur la config du Doxyfile : 113 → 31 avertissements.
loadconfig.h 41→0 · surpluscontext.h 30→0 · sgreadyadapter.h 4→1 (le \return
restant relève du lot suivant) · etmvariableloadadapter.h 2→0 · evadapter.h 1→0
Ce sont des contrats, pas des étiquettes : enabled dit qu'une charge déclarée
mais exclue n'est JAMAIS pilotée ; priority qu'il s'agit d'un rang ascendant et
non d'un poids ; timestamp qu'il est la source unique du temps, dont dérivent
verrous et fenêtres ; setPowerLevels qu'il trie et déduplique ; fromMap qu'il
retourne une config NON validée ; internalRootMeter() qu'il peut être nul.
Ajouts « // [ETM] » hors etm/ (smartchargingmanager.h) : ils échappent au
périmètre du Doxyfile, la frontière étant un répertoire. Un inventaire explicite
est posé au marqueur [ETM] BEGIN, distinguant les trois cas — degradedMode() et
les trois accesseurs internal* sont des ajouts ETM et sont documentés ; les huit
changements de visibilité seule gardent la documentation de l'amont. La
définition de fait d'AGENTS.md renvoie à cet inventaire et l'étend explicitement
aux ajouts hors etm/.
Build amd64 0 erreur. Simulation : 7/7.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Purge des affirmations devenues fausses depuis la rév. 3. Chaque correction est
vérifiée contre le code ; rien n'est repris du texte existant par défaut.
Zones : ÉTAT (tableau + Détail 3c) · « ce que le moteur sait faire » · DÉFÉRÉ
(2 entrées) · PLAN 3C · ARCHITECTURE CIBLE · WORKFLOW phase 3 · 3b révisé ·
Verrous minOn/minOff (2 endroits) · MODÈLE DE SÉCURITÉ (L2) · ROADMAP ·
RÉFÉRENCES.
Principales remises au fait :
- EcsRelayAdapter et le kind Stage, supprimés en 5100674, disparaissent du
schéma « non négociable » au profit de RelayRouter + EtmVariableLoadAdapter ;
SocketScheduler et BatteryAdapter, qui n'existent pas, sont marqués [3d]/[3f].
- EvAdapter::applyAction() n'est pas « inactif » : il est implémenté
(evadapter.cpp:62-94) mais jamais appelé (energyarbitrator.cpp:288).
3g est un travail de câblage, pas d'écriture.
- minStage/maxStage ont été retirés du contexte ; minState/maxState et
minStateHold subsistent et sont conservés tels quels.
- La configuration des charges est persistée et rechargée à chaud depuis
7184fe4 — le point (b) de la ROADMAP est fait côté moteur, seule l'UI
Flutter reste ouverte.
- Le watchdog L2 est en place, plus « à coder en 3c ».
- PLAN 3C n'est plus reproduit (pseudocode nommant une classe supprimée et un
identifiant « relay-stages » jamais livré) ; les corrections A et B, toujours
en vigueur, sont conservées avec leurs références actuelles.
- PRÉCONDITION ajoutée au basculement de SgReadyAdapter sur la config :
retirer d'abord Q_ASSERT(m_stateRelays.contains(2)) au profit d'un refus
explicite — l'assertion garde l'état 2, repli sûr du mode dégradé L2, et
disparaît en release.
Aucune règle absolue 1 à 10 modifiée (vérifié identique à HEAD).
INVARIANTS BUILD / PACKAGING intact. Aucun code touché.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Décision Patrick : délestage strict au budget, MAIS minOn/minOff (protection
compresseur, anti court-cycling) bornent le palier via l'adaptateur, pas le budget.
Paramètres par charge (config installateur, jamais hardcodé) + défauts indicatifs
par type (résistif / thermodynamique-PAC / SG-Ready). Note seam de temps unifié.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
QTimer 30s indépendant des signaux ; m_lastMeterUpdate picoté sur powerBalanceChanged.
Silence >90s → mode dégradé (appliqué à la TRANSITION uniquement) :
- ECS palier 0 force=true ;
- EV : clamp courant minimum SEULEMENT si déjà en charge (pas d'activation forcée ;
"jamais 0 A si branché" relève du failsafe L1, pas du repli logiciel).
update() suspend la planification + le dispatch tant que m_degradedMode (sécurité L4
en position 3 reste active) → pas de rallumage sur le cache d'un compteur mort, pas
d'oscillation. Reprise au retour du compteur.
SAFETY.md §L2 : nuance maintenu/démarré + suspension planification. AGENTS.md morceau 7 :
exiger ECS reste à 0 sur plusieurs cycles. SG-Ready/Batterie déférés 3e/3f ;
flag degradedMode exposé en 3c-6. Build 0 erreur / 0 warning.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Corrections A (déduction EV unique) et B (anti-clignotement) intégrées.
Tri priorité ascendant (rang 1 = premier servi, OPTIMIZER_PROTOCOL §5/annexe C) —
corrige l'inversion du PLAN 3C et 3 doc-comments (plan.h, loaddescriptor.h,
ecsrelayadapter.h). Build 0 erreur / 0 warning.
telemetry() ECS : currentPowerW MESURÉE si au moins un relais expose "currentPower"
(thermostat coupé → 0, pas de fantôme), DÉCLARÉE en repli seulement sans comptage.
Dette evadapter.cpp priority=100 (ancienne convention) inscrite en 3g.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>