Rebranche pendant que le conteneur tenait ttyUSB0, le cable est revenu en
ttyUSB1 : la garde cree un lien d'apres le numero de serie et recree le
conteneur quand le port change de numero.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Incident 25/09 11:49 : l'agent sans source avait invente 0,56 kWh / zero
reseau / 35 % pour une nuit a 7,9 kWh dont 2,2 reseau. donneesNuit() extrait
de rapport-nuit.mjs (texte identique sur 5 nuits), publie pour l'agent.
Tests 37/37.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
sensor.evcs_production_jour_kwh (somme des 3 yield_today, remises a zero
decalees gerees) et sensor.evcs_charge_solaire (relais de la decision du
controleur, pas un second arbitre). Tests 26/26 + mutations.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
La fiche OpenClaw basculait G5 de 7/7 a 1/7 sur un ajout sans rapport :
les deux jugements sortent du modele. sensor.evcs_pv_diagnostic (import
teste avant bridage) et sensor.evcs_cellules (perime => aucune valeur
visible), publies meme quand le cycle echoue. Tests 15/15 + mutations.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Les trames BMS cellule de HA sont mortes depuis le 15/09 ; le relevé série est la
source vivante. Le service publie evcs_cell_spread_max_mv, evcs_cell_weakest_module
et evcs_cell_releve_age_min à chaque cycle (publierCellulesHelpers). L'âge donne à
l'agent la discipline anti-valeur-figée (comme le gel GX). Vérifié en réel :
21 mV, âge 1 min, K220803C30160323. Package evcs_cellules.yaml (hors dépôt, HA).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le HANDOFF chargé à chaque session pesait 7566 lignes. Split vérifié par md5 :
§1→§72 (09/07→17/09) déplacés SANS PERTE dans HANDOFF_ARCHIVE_2026.md (non chargé
par CLAUDE.md, grep/lecture à la demande). HANDOFF.md ne garde vivantes que les
sessions récentes §73→§77 + un index des sections archivées. Aucune info perdue,
aucun changement d'@-import nécessaire (l'archive n'est pas référencée).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
9 gammes (snapshots reels figes + attendus), 9/9 sur 3 passages. Coordination
avec SPARK : moi la verite-terrain (PostgreSQL/InfluxDB/historique HA), SPARK le
harnais et la fiche OpenClaw. G5 a echoue 0/3 au premier tour et a fait corriger
la fiche (import reseau force en controle nº1 avant de conclure bridage) ->
verrouille la distinction bridage normal / substitution. Source de verite de la
production PV dans MANUEL §0.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Somme des 3 rendements par chargeur Victron (airtria_mppt1 + mppt_450_200 + v1)
= production reelle du jour. Verifie 24/09 (45,1 kWh) et recoupe par l'integrale
de pv_power_system (44,0). Documente les 3 pieges qui donnent un faux chiffre :
energy_production_today = prevision, gx_device_pv_energy = partiel/gelable,
v1_production_d_hier = la veille. Pour les rapports, le bilan et l'agent vocal.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Envoi decale 06:47 -> 07:30 : apres la fermeture de la fenetre HC (07:24)
l'import de la nuit est termine, donc le total est complet. A 06:47 le rapport
ratait l'import 06:47->07:24 meme apres le fix d'extrapolation (ec5f43e).
Proposition du proprietaire. HANDOFF §76 consigne le bug (extrapolation de la
derniere puissance sur la fenetre future), le fix et ce decalage.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Signale par la session SPARK via les compteurs d'energie Victron : le rapport du
24/09 annoncait 4,2 kWh importes contre ~1,6 mesure. Cause reelle (verifiee en
base) : le rapport tourne a 06:47 mais sa fenetre va jusqu'a 10:00 ; l'ancienne
methode (grille generate_series 1 min + derniere valeur connue + sum/60000)
reportait la derniere puissance connue sur les ~3 h futures -> import fantome.
Ce n'est PAS la cadence d'echantillonnage (donnees eparses, 130 pts/961 min) et
les compteurs d'energie ne sont pas dans la table mesure (seul grid_power_l1).
Fix : integration ponderee par l'intervalle reel entre points (cap 300 s, jamais
d'extrapolation apres le dernier echantillon) et fenetre plafonnee a now().
Applique aux 4 grandeurs integrees (importe/injecte/voiture/batterie_chargee).
Verifie : 1,60 kWh sur fenetre complete (= compteurs), 1,19 en simulation 06:47.
Tous les rapports depuis le 08/09 surestimaient ces kWh ; le reste (SOC,
fermetures, vehicule, injection) etait juste.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le releve serie tournait sur le portable et est mort 4 jours au reboot du 20/09.
Migre sur le .17 (conteneur node + tache de boot root/sh chargeant les pilotes).
Survie prouvee de bout en bout sur reboot + saut majeur DSM 7.3.2 -> 7.4.1, qui a
revele et fait corriger deux pieges (NFS noexec, sudo passwordless efface par
l'update). @reboot du portable retire.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Deux defauts vus au retour de l'update 7.4.1 :
- le montage NFS du depot est noexec, donc la tache DSM qui appelait le chemin nu
du script donnait « Permission denied » et ne chargeait rien. Commande corrigee
en `sh <chemin>` (lit le script au lieu de l'executer).
- la boucle faisait confiance au code retour de modprobe (0 sans charger sur DSM).
Elle verifie maintenant l'etat reel via lsmod apres chaque tentative.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Constate au reboot + update DSM 7.3.2 -> 7.4.1 : le sudo passwordless de TMZF5455
a ete supprime, donc l'auto-elevation du script ne marche plus et la tache de
boot (owner 1026) n'a pas charge les pilotes -> device absent, conteneur Exited.
Les .ko existent toujours en 7.4.1. Le fix durable est une tache Planificateur
en utilisateur root, qui ne depend d'aucun sudo. Note aussi que les updates
majeurs peuvent desactiver les taches declenchees.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le .17 passe en DSM 7.4.1 (saut majeur, noyau potentiellement different). Les .ko
etaient charges par chemin fixe /lib/modules/ ; si 7.4.1 les deplace, insmod
echouait. Desormais : modprobe si dispo (gere les dependances), sinon find du .ko
dans /lib/modules et /usr/lib/modules. usbserial reste charge avant ftdi_sio.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
La tache DSM « Au demarrage » CHARGE_PILOTES a ete creee en owner 1026 (TMZF5455),
pas root (verifie en base esynoscheduler). insmod aurait echoue en silence au
boot -> pas de /dev/ttyUSB0 -> conteneur bloque. Le script se re-exec via sudo -n
(passwordless pour cet utilisateur sur le .17) quand il n'est pas root. Teste en
lançant le script sans prefixe sudo : il s'eleve et charge les pilotes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le releve tournait sur le PC portable (deploy/releve-cellules/lancer.sh) : ferme,
il ne releve plus, et le 20/09 son @reboot a refuse de relancer sur un faux
positif du garde anti-doublon -> 4 jours de trou dans la table cellule, Grafana
"No data". Le portable n'a pas vocation a rester allume.
Deplacement vers le Synology .17 (ARCHIVE3, DS920+), toujours allume :
- compose.yaml : conteneur node:20 en uid 1026:100 (le montage NFS peut ecraser
root ; le dossier CSV est g+w pour users), device /dev/ttyUSB0 mappe, depot
monte en /depot. Ecrit les CSV comme avant ; le service d'historisation du .22
les ingere sans changement. restart:unless-stopped remplace la boucle lancer.sh.
- charger-pilotes.sh : DSM embarque usbserial.ko + ftdi_sio.ko mais ne les charge
pas d'office. Script root (Planificateur DSM au boot) qui insmod les deux et
ouvre les droits de /dev/ttyUSB0.
- README.md : deploiement, bascule depuis le portable, verification.
Garde anti-blocage dans pylontech-console.mjs (--suivi) : lireJusqua resout au
timeout au lieu de rejeter, donc un port fige renvoie du vide en boucle sans
jamais crasher -- exactement le hang du 20/09. Un controle du mtime du CSV force
process.exit(1) apres 3x le pas sans ecriture, pour que le superviseur (conteneur
ou lancer.sh) rouvre le port.
Menage : modified/*.bak-* (rollbacks locaux) ignores comme prepush-* ; ajout des
relevés de mesure batterie des sessions 16-20/09.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le 180 A venait de nous (monte 130->150->180 le 13/09, §64), pas du BMS qui
autorise 250. Il bridait reellement : PV 10,6 kW, excedent ~187 A que la
batterie prendrait, plafonnee a 180. Parc sain (cellules pack 2 a 3-6 mV) : on
prend toute la marge, direct a 250 sur decision du proprietaire.
golden-acm 20/20 (2 attendus 180->250), mutation : retour 180 -> 2 echecs.
patch rejouable tools/patch-20260920b-boost-250a.mjs.
⚠️ Surveillance pack 2, surtout module rang 5 (K220803C30160323, le plus ancien).
Pack 1 (US5000) hors surveillance continue (2e cable en commande).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le 52,4 V avait ete pose le 06/09 pour menager la cellule 12 faible du pack
ANCIEN (§57). Ce pack est sorti. Cellules du pack 2 a 3-6 mV, la plus haute a
3356 mV, loin des 3550 mV ou le BMS reduit le courant. On releve le top-off
pour atteindre une charge plus pleine et RECALIBRER la jauge SOC Pylontech (qui
derive tant qu'on n'atteint jamais 100 %). 52,8 V = 3,52 V/cellule, sous les
53,2 V autorises par le BMS.
⚠️ Cellules du pack 1 (US5000) pas encore sous surveillance continue (2e cable
en commande). Proprietaire a autorise explicitement malgre le caveat.
patch rejouable tools/patch-20260920-topoff-52v8.mjs. golden-acm 20/20, attendu
acm-jour-topoff mis a jour (52,4->52,8), mutation : retour a 52,4 -> 1 echec.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Re-mesure du 20/09 sur le parc a 13 modules assaini (cellules 3-6 mV) :
tools/mesure-courbe-batterie.mjs donne 0,30 kWh/point PLAT de 25 a 97 %, PLUS DE
GENOU. Le genou a 33 % etait la signature de la cellule 12 morte du pack ancien
(§50), il a disparu avec elle — exactement ce que predisait la note de prudence
du 03/09. La reserve utile a quasiment double (12,4 -> ~23 kWh de 100 a 22 %).
Le scaling modules/7 rattrapait par chance la partie HAUTE (0,169x13/7=0,31 ~
mesure) mais SOUS 33 % le bilan croyait 0,18 kWh/point contre 0,30 reels ->
required_soc surestime en bas d'echelle. Corrige :
- BALANCE.js : kneePct 33->0, pentes 0,169/0,097 -> 0,1615 plat (x13/7 = 0,30).
- INPUT_PARSE : batteryUsableCapacityKwh 2,414 -> 2,308 kWh/module (0,30/13x100).
- helper evcs_balance_usable_capacity_kwh 15 -> 23 (inerte mais coherent).
Tests : bilan 50/50 apres re-figeage des 10 attendus (verifies a la main : ex
rejeu 24/08, 0,82 kWh -> 22 + 0,82/0,1615 = 27,1 % contre 30,5 avant). Mutation
deux sens : ancien genou -> 10 echecs, pente fausse -> 11. Golden controleur
116/116 inchange (capacite -4 %, aucun basculement discret).
⚠️ Courbe a REMESURER apres toute evolution du parc. 2e cable console en
commande pour surveiller aussi les cellules du pack 1 (US5000), aujourd'hui hors
surveillance continue (trames etendues Cerbo mortes, §69).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Grief du proprietaire du 19/09 : JEEP branchee, du soleil, borne figee apres un
swap rapide -> rien qui charge, et il ne l'a su qu'en regardant. Le service
d'historisation detecte desormais l'episode et le SIGNALE dans un helper ;
la session OpenClaw lira ce helper et enverra l'alerte WhatsApp (son cote).
Critere, robuste par la censure sans injection : batterie pleine => MPPT bride
=> PV ~ conso => excedent ~ 0 => PAS d'alerte. Un excedent POSITIF qui persiste
(> 500 W) avec vehicule branche + borne < 300 W + etat controleur bloquant,
tenu > 10 min => il manque un preneur a de l'energie gratuite => signalement.
Un seul par episode (dedup sur son debut), helper efface a la resolution.
- helper input_text.evcs_alerte_charge (max 255, sans initial:), reload fait.
- detecterAnomalieCharge() + ecrireHelperTexte(), appele dans cycle().
- etat d'episode en processus (repart de null au redemarrage, se re-arme en 10
min sur une anomalie reelle).
⚠️ SEUILS A CALIBRER sur l'historique avant d'etre figes. Le helper reste
INERTE tant que SPARK n'a pas cable l'envoi : deployer maintenant ne fait rien
partir.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Filet MANUEL complementaire a P11-bis : quand meme le second signal echoue
(borne physiquement coincee), l'appui sur input_boolean.evcs_reset_borne force
une session fraiche pour un cycle -> nettoie le collant -> retest du vehicule.
Momentane : le controleur (HA_SERVICE_CALLS) le rebascule off apres avoir agi,
il ne peut donc pas forcer un retest en boucle.
- gabarit + INPUT_PARSE (params.resetBorneRequested) + sessionFresh (OU bouton)
- helper_reset_borne_ack : turn_off si le bouton etait ON
- paquet evcs_reset_borne.yaml (SANS initial:, lecon du 06/09), reload fait
- golden 115 -> 116 : reset-borne-force-retest (session etablie + bouton ON ->
retest + ack off). Mutation : bouton neutralise -> le scenario tombe.
Gabarit rendu contre HA : 203 champs, aucun null.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Incident du 19/09 : VW debranchee ~14:50, JEEP branchee, mais le swap n'a dure
que 14 s. La borne a GELE son etat (charging_time reste a 1h25, jamais
reinitialise) → P11 (base uniquement sur charging_time <= 90s) restait aveugle
→ le collant 'vehicule plein' de la VW bloquait la JEEP, qui n'a pas charge de
l'apres-midi. Un debranchement FRANC de 30s a tout debloque (borne reset).
Le last_changed du capteur de connexion, lui, a bien bouge sur le swap de 14 s
(14:54:17). C'etait l'info qui manquait : personne ne la lisait. sessionFresh
gagne donc un SECOND terme, l'age du dernier (re)branchement, meme fenetre 90s,
independant de la borne :
- gabarit : evcs_vehicle_connected_ts (as_timestamp du last_changed, patron
acin1_last_changed_ts §29) ;
- INPUT_PARSE : evcsVehicleConnectedAgeSec (Infinity si absent => repli sur) ;
- WINDOWS : sessionFresh = charging_time bas OU reconnexion recente.
Golden 113 -> 115 : p11bis-swap-rapide-borne-figee (charging_time fige 1h25 +
reconnexion 30s -> retest) et son contrefactuel reconnexion-vieille (2h -> reste
collant). Gabarit rendu contre HA : 202 champs, aucun null. Mutation deux sens :
retrait du signal -> le swap tombe ; fenetre infinie -> l'etablie tombe.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Six leviers epuises. Le GX cree les topics etendus en value:null (decodeur qui
attend et ne recoit pas). Mort datee au redemarrage HA du 15/09 (§69), donc
cause logicielle Venus, pas materielle. Ne plus toucher au materiel batterie.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Consigne les trois configs testees (lues en MQTT direct + console), les trois
conclusions dures (detail deja mort le 15/09 ; inverser le maitre n'agit pas ;
coupable = hub/agregation), la resolution du mystere des 3 bips (chainage
inter-groupes seulement en sens US5000-tete), et la config a garder.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Incident du 18/09 13:08-13:14 : clic BOOST 28 A, le controleur demande le
reseau, l'hysteresis met ~1 min a fermer le contacteur, et pendant ce trou il
MAINTIENT 13 A sur la batterie (hold_min_run_wait_grid_takeover). Le garde
batterie mord a -32,4 A, 23 secondes AVANT l'arrivee d'EDF, et pose 20 min de
verrou — que rien ne leve quand le reseau arrive. Resultat : contacteur ferme,
import qui tourne, voiture a l'arret.
Trois volets :
1. hold_min_run_wait_grid_takeover retombe au courant MINI — miroir de la
sequence d'ouverture (§30) : on ne tient pas la puissance sur la source
qu'on quitte. A 6 A le garde n'aurait jamais mordu.
2. Le stop encode si le reseau etait present : absent => blockReason
'grid_battery_guard_no_grid'. Present => verrou plein inchange (incident du
01/09, consigne insuffisante) — c'est ce qui interdit l'oscillateur
stop/retry a reseau present.
3. BCL leve le verrou '_no_grid' des que le reseau arrive. Reseau toujours
absent : la branche anterieure wait_grid_source protege deja (epingle).
Golden 108 -> 113. Mutations en trois directions, chacune tombant sur un
scenario different. Piege du fixture note en commentaire : ses seuils ne sont
pas a l'echelle du parc reel (fenetre garde reseau / hard general etroite).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le remplacement du commit precedent avait atterri sur l'en-tete de
--historique-distant au lieu de celui de --suivi : le nouveau fichier de suivi
sortait sans la colonne, et le rang restait NULL en base. Corrige, et retire de
la branche historique ou il n'avait rien a faire.
Trouve aussi en relancant : le releve est SUPERVISE par
deploy/releve-cellules/lancer.sh (@reboot, boucle de relance a 60 s, garde
anti-doublon). Ne jamais le relancer a la main — tuer le processus node suffit,
le superviseur repart seul avec le code a jour ; un lancement manuel cree un
doublon sur le port serie et entrelace les lectures.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le proprietaire demandait si le rang dans le pack etait accessible ou si seul
le code-barres l'etait. Il l'etait depuis le debut : l'outil de releve resout
adresse <-> code-barres au demarrage mais ne l'ecrivait pas. Desormais :
- pylontech-console.mjs --suivi ecrit une colonne 'adresse' (vide en mono-module,
jamais devinee) ;
- historise-evcs.mjs l'ingere par son NOM dans cellule.rang, enregistre PAR
RELEVE et non dans une table figee — un recablage du LVHUB renumerote, et
l'historique de chaque ligne doit garder le rang vrai a son instant ;
- Grafana : colonne 'Rang' dans le tableau de sante, et la liste deroulante
des modules affiche 'rang - code-barres' quand le rang est connu.
75/75 requetes valides.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Signale par le proprietaire avant le PUT : « il faut ajouter la periode HC
12h24 jusqu a 14h24 ». Il avait raison, et le trou etait plus profond qu une
borne manquante — l engagement de session etait gate sur `night_hc` SEUL,
parce que §40 ne traitait que la nuit.
Consequence : la charge HC manuelle qu on venait d ecrire ne pouvait RIEN faire
a midi. Le plancher relevait bien la cible du bilan, mais aucune session ne
s engageait, donc pas de takeover, pas de contacteur, pas de consigne. Le
reglage aurait releve le plancher de demarrage du soir — donc bloque la charge
du vehicule — sans jamais charger la batterie. Le pire des deux mondes.
⚠️ ET LE CRITERE N EST PAS LE MEME AUX DEUX FENETRES. La nuit, on compare le SOC
a `batteryMorningTargetPct`, qui contient le palier de prevision (35/55/85). A
midi ce palier n a aucun sens : il vaut 35 par beau temps, donc un SOC de 30 %
EN PLEIN SOLEIL engagerait une session reseau — la substitution du solaire par
le reseau qu on a mis des semaines a eteindre.
A midi le critere honnete est le SOC requis du bilan lui-meme, qui s auto-regule :
le croisement PV etant passe, l energie a couvrir vaut zero et le requis retombe
au plancher dur. Releve du 17/09 a 13:51, plein soleil : required_soc = 22,0 pour
energy_to_cover = 0,0. Il ne remonte qu un jour sombre — ou quand le proprietaire
pose un plancher manuel, ce qui est exactement le cas d usage.
Golden 106 -> 108. Les deux scenarios sont une paire : meme heure, meme profil,
seul le ciel change. Sombre avec un bilan qui reclame 85 % -> la session
s engage ; ensoleille avec un bilan a 22 % et un SOC de 30 % SOUS le palier du
matin -> aucun engagement.
Mutations : retour au gate night_hc seul -> le scenario sombre ; critere de la
nuit applique a midi -> le contrefactuel ensoleille. Chacune tombe sur un jeu
different. Hysteresis 24, ACM 20, bilan 50 inchanges.
⚠️ AUCUN PUT. Il en faut desormais DEUX — le bilan et le controleur — et ils
attendent tous les deux sa validation.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Decision du proprietaire, dans ses termes : « contraindre le bilan, un seul
arbitre ». Ce projet a deja paye cher les automates concurrents — charges
programmees de l ESS, consigne a 4200 W, plancher SOC du GX — et un bouton qui
ecrirait sa propre cible en aurait cree un quatrieme.
⚠️ LE FORCAGE EST EN AMONT, DANS coverage(), ET NULLE PART AILLEURS. Mesure sur
banc : ecrire directement dans balance_required_soc engage bien la session —
contacteur ferme, takeover ON — mais laisse la consigne reseau a 700 W, donc la
batterie recoit une centaine de watts. C est le defaut du 01/09 a l identique,
et le seul des trois resultats INDIAGNOSTICABLE depuis le tableau de bord : il a
l air de marcher. La raison est que required_soc ENGAGE la session et
grid_energy_needed_kwh la FINANCE. Pose dans coverage(), le plancher fait bouger
les deux ensemble par construction.
Sens unique, comme les cablages de §38, §39 et §40 : le plancher ne peut que
RELEVER l exigence. Un reglage trop bas est sans effet, il ne desarme rien.
DEUX NOMBRES ET PAS UN, et c est architectural. `..._target` est le reglage du
proprietaire ; `..._floor` est sa valeur EFFECTIVE, mise a zero hors des fenetres
d heures creuses par une automatisation Home Assistant, et c est elle que le
bilan lit. Le bilan repond a « de combien la batterie a besoin », pas a « quand
est-ce bon marche » : il ne contient aucune notion d heure creuse (zero
occurrence de hc_night ou hc_midday dans tout src/energy-balance/) et doit le
rester. Home Assistant detient le calendrier tarifaire, le bilan detient
l energie.
Sans ce filtrage le plancher fuit dans la journee et mord sur
BATTERY_CLOUD_LOCKS — eveningSocStartFloorPct = max(eveningSocStartMin,
balanceRequiredSocPct) — au point de bloquer le demarrage de la charge du
vehicule le soir. Ce n est pas theorique, c est une ligne qui s applique tous les
soirs.
Le bouton se desarme a la sortie de la fenetre ou il a servi : une demande de
charge est un geste ponctuel, pas un reglage permanent oublie.
⚠️ EFFET STRUCTUREL CONSIGNE, qu aucune echeance ne corrige : coverage() est
appelee pour le profil typique ET le profil prudent, donc le plancher releve
aussi required_soc_prudent, qui est le plancher de P12. Pendant une charge
manuelle, la voiture cesse de descendre la batterie. Coherent, mais une nuit ou
l on veut les deux on n aura que l un.
Bilan 48 -> 50. Mutations : plancher ignore -> le scenario qui le releve ;
plancher qui remplace au lieu de relever -> le contrefactuel a 25 %. Chacune
tombe sur un jeu different. gridEnergyNeededKwh ajoute au resume de test : il
manquait alors qu il est desormais consomme en aval par la consigne reseau.
Gabarit du bilan rendu contre Home Assistant : 42 champs, JSON valide, helper
absent lu « unknown » donc plancher nul — le repli est sur avant meme que les
helpers existent.
⚠️ AUCUN PUT VERS n8n. Le workflow du bilan tourne toujours sans ce changement.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le proprietaire ferme la question de force_grid_now — « pour moi c est pour
recharger la voiture » — et en tire le chantier : dissocier la recharge de la
batterie solaire de la fonction EVCS.
Trois pistes mesurees sur banc. La piste d un chemin separe est morte et de la
maniere la plus nette : elle ne se fait pas ecraser par accident, elle
s auto-detruit, puisqu il faudrait que le controleur la connaisse pour qu elle
tienne. La piste du forcage de la cible du bilan est retenue, mais l ENDROIT du
forcage decide de tout : force en aval, le contacteur se ferme, la session
s engage et la consigne reste a 700 W — le defaut du 01/09 a l identique, et le
seul des trois resultats indiagnosticable depuis le tableau de bord parce qu il
A L AIR de marcher.
Point d insertion identifie a une ligne pres dans coverage() : tout en derive,
donc la cible et le manque bougent ensemble par construction au lieu de
dependre d une discipline.
Trois effets consignes, dont deux qui demandent une decision : le plancher monte
aussi la cible prudente, donc la voiture cesse de descendre la batterie pendant
une charge manuelle — structurel, aucune echeance n y change rien ; et le bilan
ignore totalement les fenetres creuses, donc une cible manuelle fuit dans la
journee et bloque la charge du soir. Echeance retenue plutot que bornes : le
bilan repond a « de combien la batterie a besoin », pas a « quand est-ce bon
marche ».
Fait au passage : le courant du module entre dans le releve par cellule, ce qui
rend enfin lisible « le detail de chaque cellule PENDANT la charge ».
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le proprietaire veut « dans Grafana le detail de chaque cellule pendant la
charge ». Le detail existait deja ; ce qui manquait etait le « pendant la
charge » — rien ne disait QUAND le module chargeait, et un ecart entre cellules
ne veut rien dire hors de son courant : le 05/09 la cellule meneuse etait a
3555 mV sous 50 A et a 3496 mV sous 30 A, meme module, meme tension de parc.
Le releve console porte le courant depuis le 17/09, mais l ingestion ecrivait
`null` : elle ne lisait que les quinze tensions. Elle repere maintenant la
colonne `courant_mA` PAR SON NOM — les US5000 et les US2000C n emettent pas les
memes colonnes, et une position ferait lire la mauvaise grandeur des qu on
deplace le cable d un pack a l autre. Absente des anciens fichiers, donc les
lignes deja versees gardent leur courant inconnu.
Deux panneaux au tableau « Les batteries ».
« Sante des modules — tous, d un coup d oeil » : le resume qu on lit en premier,
tous modules ensemble, la ou les autres panneaux demandent de choisir un module
d avance. Ecart maintenant, ecart maximum sur la periode, cellule la plus haute
et la plus basse, courant au moment du releve, date du dernier releve. Releve au
deploiement : cinq modules vivants, ecarts de 1 a 3 mV — le parc restant est
sain, les trois modules atteints sont sortis le 12/09.
« Le module chargeait-il ? » : le courant du MODULE, lu dans la table des
cellules et non dans celle du parc, ce qui permet de voir qu un module se
charge moins que ses voisins.
Verifie contre la base et pas seulement execute : 75/75 requetes valides ne
prouve que l execution, donc les deux nouvelles ont ete rejouees avec la vraie
fenetre et rendent bien les grandeurs voulues.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Ecrit par la session voisine docker22-b2, verifie et commite ici : `git` echoue
chez elle sur ce depot (dubious ownership) et elle ne touche pas a
`safe.directory` sans consigne du proprietaire. Laisser ce travail non suivi
dans un arbre partage en NFS, c est l etat qui se fait ecraser au premier
`n8n-extract`.
Quand la garde du bilan tombait — statut degrade, mesure perimee, champ
illisible — la consigne revenait a `maison + plafond de borne`, y compris sans
voiture. Le defaut d origine survivait donc exactement la ou le systeme est
deja degrade. Mesure sur le chemin concerne (midi, fenetre HC autorisee, aucun
vehicule, bilan indisponible) : 5725 W autorises pour une maison a 900 W.
Deux changements, aucune variable ajoutee. La branche de repli du plafond
emploie `evcsSetpointShareW` au lieu du plafond brut ; et `gridSetpointLoadW`
n a plus qu une branche, la distinction n ayant de sens que tant que le repli
gardait l emprunt. L invariant du 01/09 et du 04/09 reste tenu PAR LA FORME :
le plafond vaut maison plus un terme positif ou nul.
⚠️ Le commentaire conserve la trace d un disjoint
`nightGridSessionCommitted || forceGridRequested` sur la part voiture, ecrit
puis MESURE puis retire : il ecrase le terme batterie du bilan, puisque
max(4825 emprunte, 1538 mesure) retient l emprunt. Cout mesure, trois attendus
figes d un coup — 2380 -> 5437, 2380 -> 5437, 4219 -> 6301. Il avait un sens
tant que la consigne n avait aucun terme batterie ; depuis qu elle en a un, ce
n est plus une protection mais un court-circuit. Sans cette trace quelqu un le
reintroduira en croyant combler un trou, comme le plafond de borne lui-meme,
qui etait une bonne idee le jour ou il a ete ecrit.
Golden 105 -> 106. Mutation verifiee ici : plafond de borne remis dans le repli
-> 1 seul echec sur 106, le nouveau scenario, 1130 attendu contre 5725 obtenu.
Il est donc le seul a couvrir ce chemin. Les autres suites intactes
(hysteresis 24, ACM 20, advisor, bilan 48).
⚠️ AUCUN PUT VERS n8n. La production tourne toujours la version poussee a
00:24, sans ce correctif. Le PUT attend la validation du proprietaire.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
J avais declare le quatrieme mutant incouvrable : remettre le terme batterie
dans le plancher nuage ne faisait echouer aucun test, et je pensais qu aucun
scenario ne pouvait le distinguer, parce qu il faudrait faire coexister une
descente de credit solaire (donc du soleil) avec un manque batterie en fenetre
creuse (donc la nuit).
L erreur etait dans le « donc la nuit ». Il y a DEUX fenetres creuses, et celle
de midi (12:24-14:24) admet simultanement le soleil fort, les chargeurs brides
et le manque batterie. Rien ne s exclut.
Et le vrai discriminant n est pas l heure, c est un DVCC HAUT. A 30 A le terme
batterie plafonne sous le budget de surtension et les deux variantes rendent la
meme chose ; a 180 A — le profil de boost de journee de l ACM — il vaut 6639 W
et le plancher pollue bloque la descente.
Scenario ajoute, forme reelle de l episode du 17/09 (force_grid pose a midi,
soleil, aucune voiture) avec en plus un manque batterie :
formule correcte : 4219 W
mutant M4 : 7309 W
3090 W d ecart. Avec le terme batterie dans le plancher, la consigne reste trop
haute et evince le solaire : c est le defaut du 11/09 reintroduit par la porte
de derriere. Le scenario ne teste donc pas une bizarrerie de forme, il protege
contre le retour d un incident connu.
Les deux valeurs ont ete obtenues independamment sur deux implementations
distinctes et concordent au watt.
Golden 104 -> 105.
⚠️ RIEN N EST POUSSE VERS n8n.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Elle empruntait le plafond de la borne — `maison + physicalCapA x V` — qui n a
aucune relation physique avec ce dont la batterie a besoin. Qu il tombe juste
etait un accident : le 17/09 a 13:51, voiture partie depuis cinq minutes,
consigne a 7032 W pour une maison a 933 W.
Elle additionne desormais des besoins NOMMES : la maison toujours, la voiture
seulement si un vehicule est branche, la batterie seulement dans une fenetre
d heures creuses — recharger la batterie sur le reseau n a de sens economique
que la. Hors fenetre le terme vaut zero, donc la division par un temps qui tend
vers zero disparait par construction et non par garde.
MAX ET NON ADDITION. La consigne est une AUTORISATION, pas une prediction : le
fichier le dit deja — « la consigne dit ce que le reseau a le DROIT de servir,
DVCC dit ce que la batterie a le droit de prendre ». Additionner deux
autorisations independantes n est pas plus honnete, seulement plus permissif.
Mesure : avec l addition, `consigne-session-engagee-couvre-la-maison` passe de
5595 a 6341 W — une autorisation en plus sur le chemin dominant (85 nuits sur
88 ont un vehicule) pour corriger un chemin emprunte zero fois en treize jours.
LE TERME BATTERIE EST BORNE PAR DVCC, PAS PAR LE BMS NI PAR LE TEMPS. Le BMS
declare 250 A, soit 12,2 kW : au-dessus de GRID_SETPOINT_MAX_W, il ne bornerait
rien. Et un plancher d horizon ne borne que le diviseur : en fin de fenetre
(14 min, manque 5,672 kWh) la division rend 17 kW, ecretes a 10 000, soit PIRE
que les 5437 empruntes qu on remplace. Avec DVCC le terme vaut 1538 W et la
consigne 2380 W. Corollaire : le plancher d horizon devient sans objet, il ne
reste qu une garde d une minute contre la division par zero.
Le manque vient de `evcs_balance_grid_energy_needed_kwh` et non de
`energy_to_cover_kwh` : la premiere est le MANQUE, nulle des que la batterie
couvre et convertie par la courbe mesuree par morceaux ; la seconde est
l energie que la batterie devra FOURNIR et ne tombe jamais a zero tant qu il
reste de la nuit — 11,96 kWh annonces le 17/09 a 20:00 avec un SOC de 91 %.
Le plancher nuage suit la voiture et PAS la batterie : il couvre l exposition
creee par le courant du vehicule ; une recharge batterie qui ralentit quand le
solaire s effondre ne coupe personne.
INVARIANT TENU PAR LA FORME : `maison + max(...)` ne peut jamais descendre sous
la maison, quel que soit DVCC. La regle du 01/09 et du 04/09 est donc garantie
par construction. Toute lecture manquante retombe sur la formule d avant.
Golden 102 -> 104. `nuit-sans-vehicule-session-engage` passe de 5437 a 2380 et
recoit le manque explicitement, sans quoi il heritait du zero de la fixture et
decrivait un etat impossible (SOC 20 pour un requis de 59,1 avec batterie
couverte). Deux scenarios ajoutes : la fin de fenetre bornee par DVCC — celui
qui protege contre la regression de 10 kW — et le contrefactuel a vehicule
branche qui epingle le choix du max.
Mutations : plafond DVCC retire -> 2 echecs dont la fin de fenetre ; max
remplace par une addition -> le contrefactuel seul ; bilan ignore -> les deux
scenarios pilotes par le bilan. Les autres suites sont intactes
(hysteresis 24, ACM 20, advisor, bilan 48).
⚠️ RIEN N EST POUSSE VERS n8n : la regle du depot impose la validation du
proprietaire avant tout PUT.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le mecanisme demande par le proprietaire — « ca va pas corriger le probleme si
nous ne sommes pas devant » — est deploye et a fonctionne seul a 14:24 :
strategie rendue a auto_solar_plus, consigne ramenee de 5641 a 700 W au cycle
suivant, contacteur ouvert par l hysteresis 33 s plus tard. La demande retombe
avant que le reseau parte, sans coordination.
Ce qui manquait a force_grid_now n etait pas une interdiction mais une
echeance : la condition porte sur l instant d ENGAGEMENT, pour qu un forcage
pose un soir de cuisson afin de proteger le parc ne soit pas annule a la minute
suivante.
Et la section consigne ce que la session voisine m a fait corriger sur la
surconsigne « voiture fantome ». Trois de mes chiffres etaient faux, tous
defavorables a la correction que je defendais : l episode de midi n etait pas
un defaut (heures creuses, demande, aucune eviction — sept chargeurs en
mppt_active) ; l occurrence de six minutes du 06/09 n existe pas (source_mode
valait Solaire de bout en bout, j avais verifie les ingredients sans demander
au controleur sa decision) ; et l import de 5,87 kWh se repartit en 2,52 pour
la voiture encore branchee, 2,43 pour la batterie et 0,92 pour la maison.
La mesure sur treize jours est conservee parce qu elle sera redemandee : 88
decisions « Reseau HC autorise », toutes avec vehicule, toutes entre 1 h et
6 h, zero a midi, et session_engagee faux 85 fois sur 88 — donc
nightGridSessionCommitted ne couvre pas les nuits ordinaires.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj