`phasePowerLimit` devient un `DrawCap{Breaker, perPhaseW}` et
`evPhaseAllowanceW()` traverse `resolveDrawMargin()` — la mécanique du
délestage est branchée, et rien ne bouge. C'est le but : à comportement
constant, tout écart observé ensuite est un défaut, pas une évolution.
L'égalité est obtenue par CONSTRUCTION. `phaseDrawW()` inverse
`calculateAllowanceAmpere()` phase par phase plutôt que de relire les états
du compteur : les lectures amont ne sont pas symétriques entre phases, et
les recopier ici en aurait fait deux versions vouées à diverger.
Deux déplacements sans changement de valeur : l'écrêtage `qMax(0, …)`
descend chez le consommateur (la résolution rend une marge SIGNÉE, dont
l'étape 4 a besoin pour dire de combien délester), et le facteur 230 remonte
dans le plafond, qui s'exprime en watts comme les autres.
Vérification : quatre suites diffées ligne à ligne contre une référence
capturée avant l'édition — charging 48/48 et simulation 50/50 identiques,
loadmodel 21/21, spotmarket 32/32. Contre-épreuve : à 1 V près la suite ne
discrimine pas (consignes en ampères entiers), donc cet essai ne prouve
rien ; à un facteur dix, 7 échecs. Le chemin est vivant.
Au passage, une `\note` du .h affirmait qu'on rend à la borne ce qu'elle
tire déjà. Le code ne l'a jamais fait, et c'est délibérément de sécurité :
sur une phase en dépassement la marge est négative, et c'est ce signe qui
ramène la borne à son minimum.
Décisions 6.1 à 6.3 gravées dans le design, et défaut amont consigné dans
SAFETY.md — non corrigé sciemment, il appartient à un [upstream-fix] isolé.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015F7G5VeaPVSMeVNjiGj36p