Trois verdicts au lieu de deux ; « la batterie suffit » exige le requis PRUDENT.
Attribut soc_requis_maintenant_pct (l'ancien nom se lisait comme un SOC du matin).
Tests 73/73, mutation qui mord.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Decision du proprietaire (28/09) : Forecast.Solar renvoie des totaux quasi
constants (~26 kWh) pour 40-47 reels ; VRM suivait mieux le reel sur 10 jours
(erreur 21 % contre 32 %, 14 % contre 36 % sur les 5 derniers). Le bilan
lit VRM des maintenant ; les deux previsions sont enregistrees (colonne
source, cle etendue) pour les comparer dans une semaine.
- input_select.evcs_balance_forecast_source (vrm | forecast_solar) = retour
arriere en un geste ; helpers evcs_balance_vrm_* au format du bilan
- historisation : lecture VRM (jeton dans .env, jamais dans HA) toutes les
15 min, vrmVersCourbes (jour et heure de Paris), tests 69/69
- modele du bilan conditionnel ; bilan 50/50, deploye
- evcs_prevision_contre_reel porte sur la source active
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Incident 27-28/09 : l'agent presentait le surplus solaire de demain comme
de l'energie batterie et lisait une projection de jour du controleur la
nuit. Ce capteur ne relaie que le bilan (meme arbitre que la decision de
nuit) ; bilan > 30 min -> indisponible. Tests 65/65.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Incident 27/09 : l'agent annoncait « vers 90 % » de sa tete. La prevision
Forecast.Solar sous-estime d'environ 50-60 % : on publie des faits (SOC,
ecart de prevision), jamais un SOC projete. Tests 61/61.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Delta depuis minuit de ac_in_1->ac_out + inverter->ac_out : 25,2 kWh a
17:11 le 26/09 pour ~25 dans VRM. Remise a zero -> indisponible, compteur
muet -> partiel. Tests 59/59, mutation qui mord.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011uJ47NxgfpGnuuMr3f2n7Z
Premier releve live (26/09 12:19) : compteur EDF 0,8 = VRM, delta des
compteurs AC-in du MultiPlus 0,7 (0,6 + 0,1, pas apparent de 0,1 kWh).
Repli sur le MultiPlus si le compteur EDF est muet ou remis a zero.
Tests diagnostics 55/55, deux mutations qui mordent.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xd7aRDEChdShwsECohnDN
Le proprietaire veut que l'agent vocal lui evite d'ouvrir VRM. « Combien ai-je
importe » est une quantite : delta des compteurs cumules AC-in du MultiPlus
(vers ac_out + vers inverter) depuis leur valeur a minuit, lue une fois par
jour dans l'historique HA. Compteur EDF publie en recoupement. Remise a zero ->
indetermine, jamais d'import negatif. Les trois compteurs entrent aussi dans la
table mesure (manque note au HANDOFF §76).
Tests diagnostics 48 -> 54, deux mutations qui mordent.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xd7aRDEChdShwsECohnDN
Incident du 26/09 : l'agent vocal a annonce le capteur reseau bloque a 07:24,
alors que le contacteur s'etait ouvert a la fin des heures creuses. Le verdict
ne juge l'age de la mesure que contacteur ferme ; ouvert, c'est non_raccorde.
Tests diagnostics 37 -> 48, trois mutations qui mordent.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011xd7aRDEChdShwsECohnDN
Le cable du pack 1 est a puce Prolific, sans pilote sur DSM : lu par un
portable a noyau recent. --suffixe pack1 separe les CSV des deux lecteurs ;
evcs_cellules regarde 15 min (deux lecteurs non synchronises) et publie
modules_lus (9 attendus).
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
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 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
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
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
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
Suite du correctif de l onglet Home Assistant. « La journee » avait le meme
angle mort : cadre sur le jour civil, il s arretait a l heure en cours.
Fenetre portee a la journee ENTIERE (dashboard() gagne un parametre `jusqu`),
serie « Encore attendu » en gris translucide a la suite des barres mesurees,
et colonne « Reste attendu » dans le bandeau du haut, a cote de « Solaire
produit ».
Sur le telephone, aucun panneau ajoute — un panneau de plus y est un ecran de
plus a faire defiler. « Soleil restant » rejoint le bandeau Maintenant, a cote
de Excedent ; « Soleil demain » rejoint La nuit qui vient, puisque c est lui
qui decide jusqu ou la batterie peut descendre.
Trois pieges, tous dans la meme direction. La mesure ne doit pas suivre la
fenetre dans le futur : ENERGIE_SQL construisait son axe entre les deux macros
puis reportait la derniere valeur connue, ce qui aurait rempli les heures a
venir avec la puissance de l instant et gonfle l energie du jour — sa borne
haute est desormais least($__timeTo(), now()). FULL OUTER JOIN et non LEFT :
une periode a venir n a aucune ligne de mesure. Et borne haute stricte, sans
quoi une barre « 18/09 00 h » apparaissait dans La journee.
L heure EN COURS n a volontairement pas de barre de prevision : elle est deja
mesuree pour ses minutes ecoulees.
73/73 requetes valides — mais ce controle prouve l execution, pas la grandeur.
Les deux requetes de La journee ont donc ete rejouees a la main avec la vraie
fenetre : 24 lignes, mesures jusqu a 02 h, prevision de 03 h a 23 h, somme des
barres 36,95 kWh contre 37,0 annonces par le bandeau. C est ce recoupement qui
a fait apparaitre le troisieme piege.
Corrige au passage la note du 08/09 sur l acces a l API Grafana : les
apostrophes du .env sont SIMPLES et non doubles, verifie a l octet.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Nuit du 16 au 17/09 : neuf arrets de la charge nuit de la VW, de 30 s a 3 min,
sans que le controleur EVCS ait bouge — sa table de decision ne porte que deux
lignes sur toute la periode. Le journal de bord de Home Assistant montre le
switch de charge passant a off SANS contexte de service, donc commande depuis
le GX, puis le controleur qui reessaie au cycle suivant.
Correlation un pour un avec les actions du chien de garde, trois secondes
avant chacune, et aucune coupure sans action. Son message porte la signature :
« CONTROLEUR MUET — derniere execution il y a NaNs ».
Cause : n8n inscrit une execution AVANT de la demarrer, avec status "new" et
startedAt null. Date.parse(null) vaut NaN, et le test !(ageSec <= 600) — forme
choisie pour echouer du cote sur — declare alors mort le controleur qui vient
precisement de demarrer un cycle. Le signal de vie retourne contre lui-meme.
La fenetre dure moins d une seconde : 3 sondages sur 968 y tombent, 0,3 %. Ce
qui a change le 16/09 n est pas le code mais la PHASE du chien de garde, qui
derive d environ vingt secondes par jour et est venue se poser exactement sur
les instants de declenchement du controleur (:00 et :30) — 34 evenements ce
jour-la contre 1 a 2 les jours precedents. Le defaut dormait depuis le 01/09.
Correction a la session precedente : la nuit du 15 au 16, presentee comme
irreprochable, portait deja trois coupures dont une de trois minutes. Ce que
j avais verifie — consigne a 6 A inchangee pendant 153 min — restait exact et
ne prouvait rien : la consigne ne bouge pas quand la borne s arrete, seule la
puissance tombe.
Second defaut, latent et plus grave : CFG.idleSetpointW valait 50 W quand le
controleur est passe a 700 W le 06/09, donc dangerousSetpoint etait vrai en
permanence et chaque fausse alerte ecrasait aussi la consigne reseau a 50 W.
Sans consequence cette nuit — EDF etait ouvert — mais pendant une nuit ou le
reseau porte la maison, c est le defaut du 04/09 reintroduit.
Trois correctifs : un horodatage manquant n est plus une panne (on prend le
plus recent startedAt exploitable, repli cote sur si aucun) ; valeur de repos
portee a 700 W avec le commentaire qui dit ou vit l autre exemplaire ; et une
panne doit DURER — deux lectures consecutives avant d agir, meme doctrine que
la tolerance batterie et le relachement du contacteur.
Verification par REJEU et non par absence de symptome : le redemarrage a remis
la phase a :07, donc une nuit calme ne prouverait rien. Un serveur local
rejouant la charge JSON exacte capturee a 02:07:01 donne, code d avant,
« MUET — il y a NaNs » et les deux ecritures ; code corrige, « controleur
vivant (execution il y a 36s) » et aucune ecriture. Le filet mord toujours sur
une panne soutenue : 1/2 puis alerte et StartStop = 0 au second cycle.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le graphe « production prevue et realisee heure par heure » du troisieme
onglet du bilan energetique ne montrait que du passe : sa courbe « prevue »
etait la prevision publiee le matin de chaque jour ECOULE, et la fenetre
s arretait a l heure en cours. C est un instrument de mesure du biais, pas
une prevision.
Deux courbes desormais, et elles n ont ni la meme provenance ni le meme
usage. Pour un jour ecoule, ce qui avait ete annonce LE MATIN MEME reste la
seule reference honnete : une prevision revisee a 18 h connait deja la
journee, la comparer au reel ne mesure plus rien. Pour les heures a venir,
c est la DERNIERE publication qui fait foi — aujourd hui jusqu au soir,
demain en entier. Les deux se touchent sur l heure en cours au lieu de
laisser un trou, et la seconde est tracee en pointilles.
Au-dela de l heure en cours, « reel » et « bridage » valent NULL et non
zero : un zero dessinerait une chute de production qui n a pas eu lieu.
Defaut trouve en chemin : l ecart moyen comptait l heure EN COURS, mesuree
sur ses seules minutes ecoulees. A 14h05 son reel vaut cinq minutes de
production contre une prevision d heure pleine, soit -92 % qui n existent
pas. La colonne `clos` l exclut. Et la serie mesuree s arrete desormais a
la minute courante et non au debut de l heure, si bien que l heure en cours
est reellement tracee au lieu de valoir zero.
Le partage aujourd hui / demain se fait en SQL, dans le fuseau deja utilise
par le reste de la requete : le conteneur repond en UTC a `date`, il ne
doit pas servir d arbitre.
Fenetre de la carte portee a hier / aujourd hui / demain (graph_span 3d,
span end day offset +1d) : sans cela la prevision, qui est justement ce
qu on veut voir, tombe hors du cadre. Verifie dans le paquet installe :
`span.offset` exige bien un signe, et l offset decale les deux bornes.
Verification en production : 47 points de prevision publies, du 17/09 01 h
au 18/09 23 h, 33,3 kWh encore attendus aujourd hui et 34,5 annonces pour
demain.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
La colonne courant_mA etait vide depuis la mise en service : le mode --modules
interroge chaque adresse avec soh <n>, qui donne les quinze tensions mais AUCUN
courant. La source juste est pwr, qui rend courant, tension et SOC pour TOUS les
modules en un seul appel — une commande serie par cycle au lieu d'une par
module.
⚠️ LE TABLEAU pwr N'A PAS LES MEMES COLONNES SELON LA FAMILLE DE MODULES.
Mesure du 16/09 : les US5000 (firmware B69.26) intercalent Tlow.Id, Thigh.Id,
Vlow.Id et Vhigh.Id que les US2000C (B69.13) n'ont pas. Un parseur a index figes
lit donc n'importe quoi des qu'on change de pack — c'est la meme famille de
piege que le trou de 44 h. Les colonnes sont resolues PAR LEUR NOM dans
l'en-tete. Les trois utiles (Volt, Curr, Coulomb) precedent Time, dont la valeur
contient une espace, donc le decoupage positionnel reste valable.
Echec de pwr non bloquant : on ecrit la ligne sans courant plutot que de perdre
les tensions, qui sont l'essentiel du releve.
Verifie sur cinq modules, trois cycles : courant et SOC par module dans le
journal et dans le CSV. Pack 2 a 13:18 — 9,5 + 9,4 + 9,0 + 9,2 + 9,1 = 46,2 A,
SOC 82/79/83/81/87 %.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Valide separement par le proprietaire le 16/09, comme la session OpenClaw et moi
l'avions demande : c'est la premiere fois qu'une reponse WhatsApp touche au
PILOTAGE et non a une etiquette consultative.
⚠️ LA LISTE BLANCHE EST DANS LE SERVICE, JAMAIS CHEZ L'AGENT — moindre
privilege : il demande, il ne decide pas de ce qui est demandable. Six ordres
admis : p12, p9, hc_nuit, strategie, vehicule, plafond_edf (borne 6-28).
Les options d'un input_select sont lues EN DIRECT sur l'entite, jamais codees en
dur : ZERO sera consomme sans modification quand la moto reviendra.
⚠️ HORS LISTE DEFINITIVEMENT : le contacteur EDF, les limites DVCC, la consigne
de puissance reseau, les planchers SOC de securite — exactement ceux qui peuvent
vider la batterie sous son plancher, la gaver sur le reseau, ou evincer le
solaire une journee entiere.
Garde supplementaire : un ordre de pilotage exige un canal HUMAIN. Une regle qui
deduit « il faudrait activer P12 » n'a rien a faire ici — c'est une decision,
pas une observation.
Interrupteur DISTINCT de celui du concierge (input_boolean.airtria_ordres_enabled,
a OFF), pour que couper le pilotage ne coupe pas l'etiquetage des vehicules.
Il gate l'ECRITURE, pas la lecture : a OFF le service journalise ce qu'il aurait
fait, ce qui permet d'eprouver la chaine avant qu'elle ne compte.
NEUF ESSAIS, tous verifies. Refuses : ordre edf, dvcc, consigne_reseau,
soc_stop_min (hors liste) · source regle-puissance (canal non humain) ·
plafond 45 A (hors bornes) · strategie « turbo » et vehicule « MEGANE » (absents
des options, listees en direct). Applique : plafond_edf 28 -> 20, journalise avec
l'etat anterieur ; rejeu du MEME confirmed_at -> ordre=0, rien ; nouveau
confirmed_at -> restauration a 28. P12 intact tout du long.
⚠️ DEFAUT TROUVE EN EPROUVANT CECI : le mode --once n'appelait pas
assurerConnexion(). Une base absente au demarrage lui donnait client = null,
donc un TypeError au lieu d'un message clair. Trouve sur un simple mauvais
numero de port. Corrige.
Carte « Agents & surveillance » completee : le guichet et son dernier ordre, a
cote du concierge et de l'etat du service.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Valide par le proprietaire le 16/09. Le service publie desormais
sensor.evcs_historisation_heartbeat a chaque cycle : etat = horodatage ISO 8601
UTC, attributs statut (ok|degrade), base_joignable, cycles_en_echec,
dernier_echec. Forme figee avec la session OpenClaw pour que les deux battements
du systeme soient identiques.
POURQUOI UN CAPTEUR DEDIE. Mesure du 16/09 : Home Assistant ne materialise pas
une ecriture identique, et last_reported — le champ introduit en 2024 pour
marquer chaque remontee d'etat — est rigoureusement EGAL a last_changed. Aucun
champ de l'API ne distingue donc un ecrivain mort d'un ecrivain qui republie la
meme valeur. Sur une installation saine, trois entites sur cinq paraissaient
figees. La vivacite se lit donc sur ce capteur seul, dont l'etat est un
horodatage : il change forcement a chaque ecriture.
L'appel est HORS du try/catch du cycle, dans les deux branches. C'est tout le
correctif : base morte, le battement part quand meme en portant degrade et la
cause. Avant, un cycle en echec n'ecrivait que sur console.error, et l'incident
n'etait journalise qu'au RETOUR a la normale — dans PostgreSQL, donc jamais
quand c'est PostgreSQL qui est tombe.
⚠️ CE QUE LE TEST A TROUVE, ET QUI RENDAIT LE BATTEMENT INUTILE. Eprouve sur une
base JETABLE derriere un relais TCP coupable a volonte (pas sur la production :
deux instances sur la meme base double-compteraient l'energie des sessions, le
UPDATE energie_kwh = energie_kwh + ... n'est pas idempotent). Premier essai : le
service a CRASHE a la coupure. Le client pg emet un evenement 'error' sur le
socket ; sans ecouteur, c'est une exception non capturee qui ne passe PAS par le
try/catch du cycle — il n'attend qu'une promesse — et qui tue le processus. Le
service mourait donc exactement dans la panne que le battement existe pour
signaler.
Trois correctifs qui en decoulent : un ecouteur 'error' qui marque la connexion
morte au lieu de faire tomber le processus ; une reconnexion, un client pg
n'etant pas reutilisable apres erreur (sans elle le service resterait vivant mais
definitivement muet) ; et une connexion initiale non fatale, pour qu'une base
absente au demarrage ne tue pas le service — un service mort ne signale rien.
Sequence complete verifiee : base vivante -> ok ; coupure -> service VIVANT,
degrade, base_joignable false, cycles_en_echec 2, cause « connect ECONNREFUSED » ;
retour -> reconnexion automatique, ok, et l'episode journalise avec sa duree.
Le message de reprise disait « Home Assistant injoignable » quelle que soit la
cause ; il nomme desormais ce qui a reellement echoue.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Corriger le selecteur a la main ne corrige rien : « demain si je dis JEEP il va
rester sur VW, donc la solution c'est de le piloter quand je reponds ».
Le selecteur n'est pas qu'une etiquette. Le CONTROLEUR n8n le lit pour en
deduire l'heure de depart (VW 08:50, JEEP 06:30), donc minutesUntilDeparture,
donc batteryRecoveryUrgent — qui coupe P12 et ferme EDF trente minutes avant le
depart suppose. Mesure de cette nuit : selecteur reste sur JEEP alors que la VW
etait branchee et confirmee par WhatsApp a 19:56 => EDF se serait ferme a 06:00
pour rien, la voiture etant pleine depuis 05:30 et la batterie a 51 %.
Deux correctifs, indissociables.
1. piloterSelecteurVehicule() : une reponse du proprietaire ecrit
input_select.victron_evcs_vehicle. UNE SEULE FOIS par reponse — la fonction
appelante est idempotente par confirmed_at — donc le dernier mot reste a
l'humain quel que soit le canal. Seulement pour les labels qui SONT des
options du selecteur : MEGANE, INVITE et ZERO n'y figurent pas, et l'heure de
depart n'a aucun sens pour un vehicule de passage.
2. ecrireSession() n'ecrase plus une session confirmee. Cette ligne reecrivait
le vehicule depuis le selecteur a CHAQUE CYCLE d'une session ouverte, pendant
que appliquerEtiquettesEnAttente remettait l'etiquette juste apres : deux
ecrivains sur la meme colonne toutes les 60 s, et une ligne de journal a
chaque passe — une soixantaine le 15/09. Le drapeau vehicule_sur dit « un
humain a confirme » : quand il est vrai, le selecteur n'a plus voix au
chapitre.
Preuve du diagnostic, par l'experience : le dernier « Etiquette VW posee » est a
01:40:58, le selecteur passe a VW a 01:41:59, et plus une seule ligne ensuite.
La bagarre s'arrete a la seconde ou les deux ecrivains s'accordent.
Preuve du correctif 2, en lecture seule sur les lignes reelles : sur les deux
sessions VW, l'expression d'avant ecrirait JEEP, la nouvelle garde VW ; sur les
sessions JEEP les deux concordent. Et sur un cas synthetique non confirme, la
nouvelle expression suit bien le selecteur — la garde est ciblee.
DEFAUT TROUVE EN RELISANT LA SORTIE DU PREMIER ESSAI A BLANC : sans garde, un
--dry-run aurait pilote le selecteur pour de vrai. Seule l'egalite fortuite
actuel === label avait evite l'ecriture. Garde posee, puis eprouvee en mettant
le selecteur sur JEEP : la sortie annonce « [blanc] piloterait JEEP -> VW » et
le selecteur est reste JEEP.
MANUEL : capacite des vehicules. La VW annonce 10 kWh de plaque pour 42 km ;
la reference MESUREE au compteur de la borne est 7,70 kWh pour une charge menee
a son terme (15/09 01:25-03:41). C'est ce chiffre qui dimensionne une nuit, pas
la plaque. La JEEP n'est pas mesuree de la meme facon : ne pas lui appliquer
les 7,70 kWh.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le proprietaire veut comparer prevision et production heure par heure sur une
semaine, dans son tableau de bilan. Les courbes de prevision vivent dans des
input_text ECRASES a chaque publication : HA n en garde aucun historique. La
base, elle, a treize jours de previsions horaires et la production mesuree.
Le service pousse donc la serie dans un capteur cree par l API HA, dont les
attributs portent les tableaux — un input_text plafonne a 255 caracteres ne
tiendrait pas 168 points.
⚠️ Premiere ecriture de ce service vers Home Assistant, qui a toujours ete
lecteur. Perimetre minuscule et delibere : un capteur, son propre espace de
noms, aucun actionneur.
⚠️ Et la troisieme serie n est pas decorative. Une heure BRIDEE n est pas
comparable : production sous la prevision peut vouloir dire mauvaise prevision
OU batterie pleine. Les mesures le montrent — le 13/09 a 15 h, prevu 5,32 et
realise 1,82 avec 100 % de bridage, l ecart n est pas meteorologique ; le 15/09
a 13 h, prevu 3,92 et realise 7,12 sans aucun bridage, la prevision SOUS-estime
de 82 %. Sans la bande, la courbe ferait accuser la meteo a tort.
L etat du capteur porte l ecart moyen sur les seules heures comparables — non
bridees — qui est le seul chiffre qui juge vraiment la prevision.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Il vient de me dire directement quel vehicule est branche. C est une
confirmation humaine au meme titre qu une reponse WhatsApp, mais le code ne
reconnaissait que ce canal-la et aurait marque sa parole « non confirmee ».
Les canaux humains sont desormais enumeres explicitement — whatsapp et
proprietaire — plutot que teste contre une seule valeur. Enumeres, et non
inverses : un canal inconnu ne doit pas valoir confirmation par defaut.
`regle-puissance` n y est pas et n y sera jamais, c est une deduction.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le bloc qui inverse la semantique de vehicule_sur n etait pas garde : a chaque
redemarrage il remettait les lignes anterieures a faux puis les six arbitrees a
vrai. Le resultat restait juste — l operation est idempotente en sortie — mais
elle ecrivait une ligne de journal trompeuse a chaque fois. Quatre en une
journee, qui seraient apparues en annotation sur tous les tableaux Grafana comme
autant de faux evenements.
Garde sur la trace elle-meme : si la ligne de journal existe, c est fait.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Il demandait « quel vehicule ? » a l ouverture d une session de charge. Trop
tard, et ca s est vu ce soir : a 19:55 la voiture est branchee, le selecteur
perime depuis six jours, et aucune question ne peut partir parce qu aucune
session n existe — la borne ne tire rien, il fait nuit. La premiere session de
la nuit serait nee etiquetee VW sans que personne ne soit consulte.
On etiquette desormais le BRANCHEMENT. C est d ailleurs l invariant du projet —
un cable, un vehicule — et ca rend la question possible des l instant ou on sait
qu il y a une voiture.
Deux temps. Le lecteur accepte une clef `branchement` en plus des `sessions`, et
memorise l etiquette dans une table dediee ; une passe differee, a chaque cycle,
la pose sur les sessions du branchement AU FUR ET A MESURE qu elles s ouvrent,
sans nouvelle question. Bornee par le debranchement suivant, avec les deux
secondes de tolerance du 09/09 — une session s ouvre jusqu a 62 ms avant que sa
transition de branchement soit journalisee.
L ancien contrat reste accepte : une etiquette portant des sessions fonctionne
comme avant.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le hub reconnait les deux groupes — LED verte et trois bips, son accuse de
reception — mais le Cerbo n en enumere qu un : 4 modules et 400 Ah la ou le parc
en compte 9 et 650.
Le releve de reference apporte le fait qui manquait : a 20:14 les quatre US5000
debitent 24 A au total pendant que le Cerbo annonce 41 A au parc. Les 17 A
d ecart sont le pack 2, qui porte donc bien du courant sans etre enumere. Le
courant mesure au shunt n est pas un indicateur d enumeration — seuls
nombre_de_modules_en_ligne et capacite_installee le sont.
Quatre etapes par risque croissant, la premiere ne touchant a aucun cable : un
redemarrage du Cerbo, l inventaire ayant deja change une fois le 13/09 a 21:35,
evenement isole verifie comme n etant pas un redemarrage de Home Assistant.
Regle de securite tiree de l incident d aujourd hui : fermer EDF AVANT toute
manoeuvre. Couper la communication du BMS arrete la gestion batterie, donc l
onduleur, donc la maison — 72 secondes dans le noir a 16:24. EDF deja ferme, la
maison passe en direct et ne voit rien.
L etape 4 renvoie a la documentation constructeur et n avance aucune theorie de
cablage : sur du materiel batterie je ne raisonne pas de memoire.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
L oscillation rapide se calibre sans ambiguite : sur le contacteur reseau, le
plus grand ecart pathologique vaut 193 s et le plus petit ecart normal 857 s,
facteur 4,4 sans aucune valeur entre les deux. Quatre bascules en dix minutes
isole exactement la salve du 12/09 et reste muet sur dix entites pendant dix
jours.
Piege trouve en calibrant : les plus petits ecarts normaux de plusieurs entites
valent 242 a 320 s, c est-a-dire la cadence des workflows. Ce ne sont pas des
oscillations mais deux executions consecutives qui changent d avis — toute
regle a deux bascules en cinq minutes se declenche sur le fonctionnement normal.
En revanche la regle des sessions reseau repetees NE SE CALIBRE PAS : les ecarts
entre fermetures forment un continuum de 4 minutes a 24 heures, sans
discontinuite. Or c est la pathologie la plus couteuse des deux. Je ne pose pas
de seuil dessus : elle demande une formulation metier et plus d historique, et
la bacler serait refaire l erreur que ce projet a payee six fois.
La regle de la mesure figee, elle, se valide sur un incident reel : le 05/09 la
tension et le courant batterie se sont tus 27 minutes pendant que le SOC, issu
du meme flux, publiait toutes les deux minutes. Le discriminant est relatif, pas
absolu — un silence long est normal pour une grandeur intermittente.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
auteurDeLaTransition filtrait sur x.context_name. Ce champ n existe pas dans le
journal de bord de Home Assistant : la fonction rendait null a tous les coups et
les 416 transitions journalisees portaient un auteur vide. Personne ne s en
etait apercu parce qu un auteur absent ressemble a un auteur inconnaissable.
Le contexte etait la, sous d autres noms, avec trois signatures distinctes
relevees sur des transitions dont je connaissais l auteur : une ligne voisine
script/automation qui se nomme ; un service exterieur dont la rafale se CLOT par
une ligne de narration portant le nom du workflow ET sa raison ; ou une simple
derivation depuis un autre capteur — qui n est pas un auteur et ne doit pas etre
annoncee comme tel.
On balaie vers l AVANT pour trouver la narration : un workflow ecrit ses helpers
puis se journalise, donc vers l arriere on ramasserait celle du precedent.
Verifie sur la seconde ou l Auto Charge Manager et le Water Heater Advisor
ecrivent ensemble — chaque helper revient a son propre workflow, 3 sur 3.
Benefice non cherche : le declencheur porte desormais la raison que le workflow
a lui-meme publiee. C est ce que « expliquer les decisions » reclamait, et
c etait deja dans le journal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Airtria envoie la clef telle que PostgreSQL l affiche — 2026-09-12
11:55:54.493+02 — et la base me la rend en ISO. Meme instant, caracteres
differents : mon Set les comptait deux fois, et le journal annoncait « 2
sessions, dont 1 ajoutee par le branchement » la ou le branchement n en
contient qu une.
L UPDATE resistait, les deux formes se transtypant en timestamptz. Ce qui ne
resistait pas, c est le tableau sessions du detail, qui portait le doublon —
et c est precisement lui que le controle de contradiction interroge sur les
etiquettes suivantes.
Trouve par le journal du service en essai a blanc, trois minutes avant la
bascule du kill-switch. Mon harnais de verification ne pouvait pas le voir :
il comptait les lignes SQL, pas les elements du Set.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Les trois pieces soudees, parce qu aucune ne tient seule. Le defaut de la
colonne passe a faux ; plus rien dans le chemin d ecriture ordinaire ne peut le
mettre a vrai ; le libelle Grafana « selecteur change » devient « a confirmer »,
et le compteur « Etiquette douteuse » devient « A confirmer ».
L ancienne semantique — « le selecteur n a pas bouge pendant la session » — ne
prouvait rien : le selecteur est reste sur VW du 07/09 au 13/09 et les onze
sessions fausses portaient toutes true. La mesure d hier a acheve de la
disqualifier : sur douze branchements, le selecteur n a ete regle au bon moment
qu une seule fois.
Rattrapage des lignes anterieures a faux, sauf les six que le proprietaire a
arbitrees lui-meme le 13/09 — une vraie confirmation humaine, seulement donnee
de vive voix, qu il serait absurde de jeter. Une ligne de journal l explique.
Rien n est deploye : le service tourne encore l ancien code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le kill-switch gate l ecriture, pas la lecture : tant qu il est a OFF, le
lecteur resout le branchement, applique ses refus et journalise ce qu il aurait
ecrit. L essai grandeur nature d Airtria eprouve donc aussi ma moitie, pas
seulement la leur.
Et il a servi immediatement. La resolution du branchement rendait deux sessions
sur trois : une session s ouvre AVANT que sa transition de branchement soit
journalisee, les deux etant ecrites dans le meme cycle — 62 ms d ecart le
09/09 — donc la session qui OUVRE un branchement etait exclue de son propre
groupe. Tolerance de deux secondes sur la borne basse ; les trois remontent.
Le meme controle, passe sur tout l historique, signale deux branchements
anterieurs a etiquettes contradictoires. Rien n est repare : un groupe mixte
peut aussi etre un echange de vehicule que le capteur a manque, et c est au
proprietaire de trancher.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
`energie_compteur_kwh` vaut la difference de deux releves du compteur
cumulatif de la borne, proches de 3 800 kWh : en double precision la
soustraction rend « 0.8000000000001819 » pour une mesure dont la resolution
est de 0,1 kWh. Arrondi a l ecriture, au millieme, plutot que de laisser
chaque lecteur s en charger.
Signale par la session OpenClaw en calibrant son module de detection sur la
table. Cosmetique pour la logique, mais ce projet a deja paye le prix de la
fausse precision affichee comme une mesure.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Correction de ma propre correction. J'avais mis 09/09 15:55 en JEEP et
laisse les deux sessions suivantes en VW — physiquement impossible, il n'y
a qu'un point de charge et le journal `evenement` montre aucun
debranchement entre mercredi 15:55 et jeudi 09:05.
L'explication du proprietaire est exactement ce qu'aucune regle ne
produira : sa femme a branche la JEEP l'apres-midi, et le soir son fils
n'a PAS debranche pour mettre la VW a la place — il a roule a l'essence le
jeudi. Trois sessions, un seul cable, un seul vehicule, et une decision
humaine que ni l'heure, ni la puissance, ni l'historique ne laissent
deviner.
La reparation passe de quatre a six lignes. Etiquettes finales sur la
semaine : 5 VW, 6 JEEP, 1 MEGANE.
Lecon inscrite dans le commentaire : la frontiere d'un branchement est un
FAIT lu dans `evenement`, jamais un ecart de temps — les creux entre la
session du soir et celle des heures creuses font 5 h 20 et ne se
distinguent pas d'une nuit entiere.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj
Le selecteur de vehicule est reste sur VW du 07/09 20:49 au 13/09 : onze
sessions consecutives ont herite de cette etiquette, toutes marquees
« sur » — le drapeau `vehicule_sur` ne passe a faux que si le selecteur
bouge PENDANT une session, donc un selecteur perime reste fiable a ses
propres yeux.
Quatre lignes corrigees, apres arbitrage du proprietaire :
mer 09/09 15:55 6,61 kWh -> JEEP
ven 11/09 16:54 7,45 kWh -> MEGANE
sam 12/09 11:42 0,09 kWh -> JEEP
sam 12/09 11:55 5,94 kWh -> JEEP
La session du 11/09 n'est ni la VW ni la JEEP : 6 360 W a 28 A quand les
deux vehicules du foyer plafonnent vers 3 680 W. C'est une Megane de
service. Ce cas n'etait documente nulle part, et il corrige la doctrine
« vehicules indiscernables » : elle ne vaut que pour la VW et la JEEP l'une
par rapport a l'autre, un vehicule invite se lit dans `p_max_w`.
Les sept autres lignes etaient justes — par chance, la VW etant celle qui
charge le plus souvent.
L'arbitrage a repose sur un contexte qu'aucun capteur ne produit : sa femme
(JEEP) en conges, son fils (VW) en stage sans retour le midi. C'est
l'argument central pour l'agent conversationnel — il dit lui-meme qu'il lui
est plus facile de donner cela par WhatsApp que de venir sur un PC.
Reparation idempotente, fenetre d'une minute, verifiee en lecture avant
ecriture : chaque predicat vise exactement une ligne, energies concordantes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GwpFpy2aQ2rJok6tNQSbVj