17 Commits

Author SHA1 Message Date
Patrick Schurig
cd1a0c83a5 fix: ECS-410-b — l'issue de ClearLoadFault, et l'asymétrie refus/succès (règles 7-c, 7-d)
ClearLoadFault est le SEUL levier de reprise à distance : ECS-410 pose un verrou collant que
seuls ce RPC ou une reconstruction lèvent. L'arbitre journalisait la demande de l'opérateur,
jamais son issue — si bien qu'appelé depuis l'étranger, on ne distinguait pas « le défaut a
été levé » de « il n'y en avait pas » de « l'appel n'a pas atteint l'adaptateur ». L'opérateur
relance trois fois et conclut que le système est cassé.

L'issue est écrite dans l'ARBITRE, pas dans chaque adaptateur : une ligne là couvre les quatre
d'un coup et ne peut pas être oubliée par un adaptateur futur ; répétée dans chacun, elle
manquerait le cinquième. Les trois cas sont distincts à la lecture.

ILoadAdapter::clearFault() rend un bool au lieu de void. Le type de retour force chaque
implémentation, présente et future, à répondre à la question « un défaut a-t-il réellement été
levé ». EvAdapter, qui n'a pas de mécanisme de défaut, le dit désormais explicitement plutôt
que par un corps vide.

Règle 7-d — un refus doit être au moins aussi visible que l'application correspondante. Le
refus par verrou minStateHold de SgReadyAdapter était en qCDebug quand l'application, dix
lignes plus bas, était en qCInfo. L'asymétrie est le défaut, pas le niveau : un resserrement
de la journalisation — et on vient d'en faire un pour tenir deux semaines — aurait fait
disparaître le refus AVANT le succès, ne laissant au journal que les décisions abouties. Or un
refus est plus informatif qu'une application réussie : il dit qu'une décision a été prise et
n'a pas été exécutée. Vérification faite sur les autres adaptateurs : c'était le seul cas. Les
qCDebug restants sont symétriques, et le marqueur L2 par cycle reste en debug à dessein, son
entrée étant en qCWarning et sa sortie en qCInfo.

Le retour idempotent du routeur reste DIFFÉRÉ, et ira en qCDebug : c'est le cas le plus
fréquent — plusieurs milliers de lignes par jour sur un budget ramené à 6,5 Mo — et son
ambiguïté est partiellement couverte, le scheduler journalisant sa décision et l'armement à
froid s'exécutant avant ce retour. Faible gain, coût réel : l'inverse des deux cas corrigés.

Le test porte sur le TEXTE des trois issues et vérifie qu'elles sont deux à deux distinctes.
Suite complète : 112 tests, 0 échec.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 20:27:53 +02:00
Patrick Schurig
6acaee38f9 fix(relayrouter): ECS-411-b — la reprise s'annonce, et annonce ce qu'elle a lu
La correspondance exacte ne journalisait qu'au palier non nul (`if (i > 0)`). Au palier 0 —
le cas de l'armement minOff d'ECS-412, celui qu'on vient précisément observer — le journal
était muet, et « relais lus, tous ouverts » ne se distinguait pas de « reprise non
exécutée ». Constaté au banc le 2026-08-13 : ECS-411 fonctionnait, et son contrôle sur le
chemin réel était impossible depuis les traces.

Le relevé porte désormais l'état de CHAQUE relais — identifiant, puissance déclarée, et
fermé / ouvert / injoignable→supposé fermé — avec le palier retenu, la branche empruntée et
la somme lue. Sortie unique pour les trois branches. Un relais injoignable fait passer la
ligne en avertissement : le palier déduit est plausible, la lecture ne l'est pas, et
« palier repris : 0 » couvrait ces deux situations sans les distinguer.

Un défaut de fond a été trouvé PAR ce relevé, qui affichait « (0W) » pour le relais 1500 W.
La nominale par relais était redéduite des encodages solo, or la déduplication par puissance
peut en évincer un : avec 500/1000/1500, le palier 1500 est encodé {500,1000} (masque 3,
rencontré avant le masque 4) et le relais 1500 n'apparaît seul nulle part. Sa nominale valait
0, donc un démarrage sur ce seul relais donnait sumW = 0, aucune correspondance exacte, et un
palier 0 annoncé pendant que 1500 W circulaient — l'annonce en sous-estimation qu'ECS-411
existe pour interdire. Elle est prise à la déclaration (m_relayNominalW). Rendre la lecture
visible est ce qui a rendu le défaut trouvable : c'est le sens de la règle, pas un effet
secondaire.

Règle 7-c dans AGENTS.md : un silence ne doit jamais être ambigu. Journaliser l'issue, pas
seulement l'issue remarquable ; journaliser ce qui a été lu, pas seulement ce qui en est
déduit. Trois autres endroits signalés dans spec_ecs.md, non corrigés — le retour idempotent
du routeur, clearFault() sur charge saine, et le refus minStateHold en qCDebug quand
l'application est en qCInfo.

RELEVE_ECS306 §3.0, en tête du protocole : un état nymea n'émet changed() que si la valeur
bouge, donc une grandeur forcée constante déclenche le watchdog L2 en 90 s et fait mesurer le
watchdog au lieu de l'arbitrage. Constaté au banc en gelant le simulateur.

Les tests portent sur le TEXTE publié, via un collecteur de messages : un test « journal non
vide » n'aurait rien vu. Trois cas, tous vérifiés échouant sans les correctifs. Suite
complète : 112 tests, 0 échec.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 20:13:18 +02:00
Patrick Schurig
1ccea65ecd fix(scheduler): ECS-309-b — le motif ne nomme un verrou que s'il a déplacé la consigne
Le critère était « consigne > budget ». Il est vrai dès que le budget passe sous zéro à
palier nul — 0 > -389 — et le motif annonçait alors « Verrou minOn — chauffe-eau maintenue
à 0 W (puissance engagée, budget -389 W) » : un verrou qui ne mordait pas, sur une
puissance engagée nulle, quand le soutirage était la seule cause.

Constaté au banc le 2026-08-13 sur +etm10, sept fois en quatre heures, toujours au cycle
suivant un palier 0. Le défaut est antérieur à ECS-309 : celui-ci a ajouté la branche
minOff après la branche minOn sans voir que la première capturait déjà un cas étranger.
Corriger une branche ne dit rien de ses voisines.

Le critère compare désormais la consigne appliquée à la consigne VOULUE avant écrêtage —
la mémoire qu'ECS-309 avait justement introduite. Relevée par le verrou → minOn ; rabaissée
→ minOff ; inchangée → le budget. Les deux branches se lisent sur le même axe, et le motif
nomme un mécanisme parce qu'il a agi, non parce qu'il aurait pu.

Ce n'était pas qu'un défaut de lisibilité. La branche minOn étant évaluée en premier, elle
masquait le motif d'armement à froid d'ECS-412 chaque fois que le budget était négatif au
redémarrage — c'est-à-dire au fond du creux, précisément l'instant où il faut redémarrer
pour observer minOff. La campagne du volet 2 aurait mesuré le mauvais verrou.

Le test reproduit le cas du banc : palier 0, budget négatif, aucun verrou actif. Sans le
correctif il produit le texte exact relevé sur la machine. Suite complète : 112 tests
(34 simulation + 46 charging + 32 spotmarket), 0 échec.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 07:32:42 +02:00
Patrick Schurig
2305a6b825 docs+deb: ECS-309, renvoi ECS-306, ECS-412 cold-start, LM-302 réécrit — 1.15.2+etm10
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 07:05:57 +02:00
Patrick Schurig
d9c16d34ea docs+deb: 1.15.2+etm9 — frontière RPC, clés internes optionnelles
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 06:32:32 +02:00
Patrick Schurig
a1e6b0ce56 deb: bump 1.15.2+etm8 (ECS-110-b)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 16:29:28 +02:00
Patrick Schurig
69a7e8c19e deb: bump 1.15.2+etm7 (SG-Ready configurable — LM-300)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 12:35:37 +02:00
Patrick Schurig
9b4945bb58 deb: bump 1.15.2+etm6 (ECS-414)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 12:07:59 +02:00
Patrick Schurig
195a399bcd deb: bump 1.15.2+etm5 (ECS-410 + ECS-413)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 11:36:59 +02:00
Patrick Schurig
8c868dfd4a deb: bump 1.15.2+etm4 (ECS-412 — blocage circulaire du verrou à froid)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09 08:28:45 +02:00
Patrick Schurig
791d272311 deb: bump 1.15.2+etm3 (étape 1 — ECS-306, ECS-411, ECS-412)
Version alignée sur la box cible : nymea 1.15.2, plugin installé 1.15.2+etm2.
Numérotation contiguë — aucun +etm3 n'a jamais été distribué.

Le fichier réel est debian-qt5/changelog : debian -> debian-qt6, et
debian-qt6/changelog -> ../debian-qt5/changelog. Un seul changelog pour les deux
arbres de packaging, écrit via debian/changelog.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08 14:36:38 +02:00
Patrick Schurig
ad385ca8fc deb: bump 1.15.2+etm2 (rév. 3 — frontière optimiseur↔routeur, RelayRouter)
Build contre nymea 1.15.2. Paquet rév. 3 pour test live RelayRouter sur hems (testing).
(changelog réel = debian-qt5/changelog ; debian → debian-qt6 → ../debian-qt5/changelog.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28 13:39:51 +02:00
Patrick Schurig
dd3503ab52 deb: bump vers 1.15.2+etm1 (build contre nymea 1.15.2)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 16:17:39 +02:00
Patrick Schurig
3afef0436d [packaging] renommage powersync-* + version 1.15.0+etm1 + invariants AGENTS
- debian/control : Source+Package → powersync-energy-plugin-nymea ;
  Provides/Conflicts/Replaces: nymea-energy-plugin-nymea (remplace l'amont) ;
  description + homepage ETM.
- debian/changelog : nouvelle entrée tête powersync-energy-plugin-nymea
  (1.15.0+etm1) trixie — plus de 1.13.0/jammy comme version courante.
- debian/nymea-energy-plugin-nymea.install.in → powersync-energy-plugin-nymea.install.in
  (déjà commité via git mv).
- AGENTS.md : section "INVARIANTS BUILD / PACKAGING" (nom powersync-*,
  version +etmN, cross arm64, tests hors deb, vérification post-build).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 14:50:40 +02:00
Patrick Schurig
f7cb1ba8af [build] exclure nymea-energy-tests du build deb
debian/rules : DH_OPTIONS=-N nymea-energy-tests — les binaires de test
n'existent pas dans le build deb (ils nécessitent CONFIG+=build_tests).
L'exclusion est globale sur tous les outils dh, pas de paquet vide produit.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 14:26:50 +02:00
Patrick Schurig
f4d5b20297 [phase1] renommage .pro + métadonnées debian ETM (fork 1.13.0+etm1, TARGET et paquets inchangés)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 21:39:49 +02:00
b343650f9b initial commit 2026-01-11 11:09:23 +01:00