docs(télémétrie): allocatedW publie le DÉCIDÉ, pas le commandé

La prémisse inverse était écrite dans CLAUDE.md et dans le modèle, et c'est elle
qui a produit l'erreur de la maquette §10 : un écran cherchant l'arrondi entre
`Σ targetW` et `allocatedW` compare deux valeurs égales par construction — il ne
montre jamais rien, et sans erreur.

Trois nombres nommés à leur place : décidé (`allocatedW`), appliqué
(`mechanism.*`), mesuré (`measurement.powerW`) — et ce que chaque écart prouve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GKM8FDNHZWogAsjjfB8pSw
This commit is contained in:
Patrick Schurig 2026-08-30 08:17:01 +02:00
parent 2792e07265
commit 5c06e65a0e
2 changed files with 29 additions and 4 deletions

View File

@ -276,7 +276,25 @@ de surplus est `decision.params.budgetW`, pas `targetW`. Elle le restera tant qu
pas livrée — **à lire comme l'exception documentée qu'elle est, jamais comme une divergence
à diagnostiquer**. Cf. `LoadTelemetry.surplusAllocatedW` et `LoadTelemetryEntry.surplusShareW`.
**2. `allocatedW` est ce qui a été COMMANDÉ — jamais ce que la charge tire.**
**2. `allocatedW` est ce qui a été DÉCIDÉ — ni le commandé, ni ce que la charge tire.**
Corrigé le 2026-08-29 par le moteur : `buildTelemetry()` publie le **plan**,
`applyActionsToAdapters()` reçoit le slot en `const`, et rien n'est réécrit après le
dispatch — un test attend `allocatedW == 3000` sur une borne dont le courant commandé donne
2 990 W. **Trois nombres, jamais le même sens** :
| Nombre | Champ | Ce qu'il dit |
|---|---|---|
| **Décidé** | `allocatedW` (et `Σ levels[].targetW`, identiques) | ce que l'arbitre a planifié — ce que les compteurs de budget comptent |
| **Appliqué** | `mechanism.*` (`stageW`, `setpointW`, `currentA`) | ce que l'adaptateur a su produire |
| **Mesuré** | `measurement.powerW` | ce que la charge tire, quand c'est mesurable |
**décidé ↔ appliqué** = l'arrondi du mécanisme, normal et permanent. **appliqué ↔ mesuré** =
la charge n'obéit pas, et ce que l'écart prouve dépend de `measurement.source`.
**décidé ↔ mesuré** = la somme des deux, à ne jamais lire seule.
> ⚠️ **Ne pas chercher l'arrondi entre `Σ targetW` et `allocatedW`** : ils sont égaux par
> construction. Un écran bâti là-dessus ne montrerait jamais rien, **et sans erreur**.
La mise en garde « pour une borne, ce n'est même pas une commande » est **levée** :
depuis `+etm23`, `adjustEvChargers()` ne commande plus, l'arbitre est seul (mesuré : 9
commandes à la borne, 9 par l'arbitre, 0 par le proxy). Mais ce qui devient vrai, c'est

View File

@ -583,10 +583,17 @@ class LoadTelemetryEntry {
return total;
}
/// **[allocatedW] est ce qui a été COMMANDÉ. Ce n'est pas ce que la charge tire.**
/// **[allocatedW] est ce qui a été DÉCIDÉ — ni le commandé, ni ce que la charge tire.**
///
/// La distinction a changé de nature avec le lot plugin 3g-2, et il faut la reprendre
/// exactement, sans l'élargir.
/// Corrigé le 2026-08-29 : `buildTelemetry()` publie le **plan**,
/// `applyActionsToAdapters()` reçoit le slot en `const`, et rien n'est réécrit après le
/// dispatch — un test du moteur attend `allocatedW == 3000` sur une borne dont le
/// courant commandé donne 2 990 W. D'où `Σ levels[].targetW == allocatedW`, une
/// **identité** et non un écart d'arrondi : l'arrondi vit après, dans l'adaptateur, et
/// se lit dans [mechanism].
///
/// La distinction avec ce que la charge TIRE a changé de nature avec le lot plugin
/// 3g-2, et il faut la reprendre exactement, sans l'élargir.
///
/// Jusqu'à `+etm22`, une borne avait **deux commandeurs** : l'arbitre décidait et
/// publiait, puis `adjustEvChargers()` re-décidait derrière lui et commandait autre