Bilan : reserve d orage, en mode ombre

Une coupure reseau n arrete pas l installation : le solaire et la batterie
continuent, seul le filet de secours disparait. La reserve a tenir est donc la
couverture prudente p80 que le bilan calcule deja — aucune constante nouvelle.
En deficit c est la fenetre traversee, en surplus la prochaine, car a 15 h la
reponse « rien a couvrir » est exacte et inutile.

Le seuil d activation est la vigilance orange, echelle officielle de
Meteo-France et non un nombre choisi ici. Le snapshot lit l alerte sans
connaitre la commune, donc le code marche des l installation de l integration
et publie « indisponible » en attendant.

Tests 38 -> 42. Le fixture du test de perimetre ombre ne contenait pas storm :
les nouvelles ecritures n etaient pas couvertes. Corrige, assertion explicite,
preuve par mutation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KKzkkVTG6KXnGXFFC7X9XJ
This commit is contained in:
Tallagrand Thierry
2026-08-27 12:05:15 +02:00
parent 99aba9da0d
commit cf7eb47356
9 changed files with 294 additions and 5 deletions

View File

@@ -145,4 +145,113 @@ export const balanceScenarios = [
missing: 'usable_capacity_kwh',
},
},
// ================= RÉSERVE D'ORAGE (27/08/2026) =================
// Une coupure réseau n'arrête PAS l'installation : le solaire et la batterie
// continuent, seul le filet de secours disparaît. La réserve à tenir est donc
// la couverture PRUDENTE (p80) de la fenêtre de déficit qui compte — pas une
// nouvelle constante.
{
node: 'BALANCE',
id: 'orage-vigilance-absente',
label: 'Intégration Météo-France non installée : niveau indisponible, aucune activation, mais la réserve reste chiffrée',
snapshot: {
nowMs: Date.parse('2026-08-24T06:43:00+02:00'),
consumption_p50: P50,
consumption_p80: P80,
horizon: horizonFrom('2026-08-24T06:43:00+02:00', 18, PROD_24_08),
soc_percent: 21,
usable_capacity_kwh: 15,
soc_floor_percent: 22,
storm_alert_level: 'indisponible',
},
expect: {
usable: true,
stormLevel: 'indisponible',
stormActive: false,
// La réserve se calcule quand même : 2,42 kWh pour la matinée du 24/08
// sur le profil prudent, soit SOC 38,1 %.
stormReserveKwh: 2.42,
stormReserveSocPct: 38.1,
},
},
{
node: 'BALANCE',
id: 'orage-vigilance-jaune-pas-active',
label: 'Vigilance jaune : en dessous du seuil de Météo-France, la réserve est publiée mais pas déclarée d\'actualité',
snapshot: {
nowMs: Date.parse('2026-08-24T06:43:00+02:00'),
consumption_p50: P50,
consumption_p80: P80,
horizon: horizonFrom('2026-08-24T06:43:00+02:00', 18, PROD_24_08),
soc_percent: 21,
usable_capacity_kwh: 15,
soc_floor_percent: 22,
storm_alert_level: 'Jaune',
},
expect: {
usable: true,
stormLevel: 'jaune',
stormActive: false,
stormReserveKwh: 2.42,
},
},
{
node: 'BALANCE',
id: 'orage-vigilance-orange-deficit-decouvert',
label: 'Vigilance orange à 06:43 avec SOC 21 % : la matinée ne passe pas sans réseau, le manque est chiffré',
snapshot: {
nowMs: Date.parse('2026-08-24T06:43:00+02:00'),
consumption_p50: P50,
consumption_p80: P80,
horizon: horizonFrom('2026-08-24T06:43:00+02:00', 18, PROD_24_08),
soc_percent: 21,
usable_capacity_kwh: 15,
soc_floor_percent: 22,
storm_alert_level: 'Orange',
storm_alert_detail: { 'Orages': 'Orange', 'Vent violent': 'Jaune' },
},
expect: {
usable: true,
stormLevel: 'orange',
stormActive: true,
stormReserveKwh: 2.42,
stormReserveSocPct: 38.1,
stormCovered: false,
// SOC 21 contre 38,1 requis : il manque 2,57 kWh pour tenir la matinée
// sans réseau.
stormShortfallKwh: 2.57,
},
},
{
node: 'BALANCE',
id: 'orage-vigilance-rouge-surplus-nuit-a-venir',
label: 'Vigilance rouge à 15:30, batterie à 95 % : la fenêtre qui compte est la nuit qui vient, pas celle en cours',
snapshot: {
nowMs: Date.parse('2026-08-24T15:30:00+02:00'),
consumption_p50: P50,
consumption_p80: P80,
horizon: horizonFrom('2026-08-24T15:30:00+02:00', 24, {
...PROD_24_08,
15: 3.00, 16: 2.80, 17: 2.60, 18: 2.40, 19: 1.20, 20: 0.20,
7: 1.50, 8: 3.00, 9: 5.00,
}),
soc_percent: 95,
usable_capacity_kwh: 15,
soc_floor_percent: 22,
storm_alert_level: 'Rouge',
},
expect: {
usable: true,
stormLevel: 'rouge',
stormActive: true,
// Bascule sur la fenêtre de 19 h : 12,77 kWh, soit un SOC requis de
// 107,1 % — même pleine, la batterie actuelle ne passe pas la nuit sans
// réseau. C'est le signal de dimensionnement, il ne doit pas être écrêté.
stormReserveKwh: 12.77,
stormReserveSocPct: 107.1,
stormCovered: false,
stormShortfallKwh: 1.82,
},
},
];