// Scénarios de BUILD_HA_CALLS — garantie du mode ombre. // La suite doit ÉCHOUER si une écriture sort du périmètre `evcs_balance_*`. // C'est la seule protection structurelle contre un câblage réel accidentel. const SNAPSHOT = { balance_enabled: 'on', grid_soc_off: '30.0', soc_percent: '21', usable_capacity_kwh: '15', }; const CENSORSHIP_CENSURE = { censorship: { pvCensored: true, reasons: ['batterie_pleine_sans_puits'] }, }; const CENSORSHIP_LIBRE = { censorship: { pvCensored: false, reasons: [] }, }; const BALANCE_OK = { usable: true, crossing: { found: true, hour: 8 }, coverage: { energyToCoverKwh: 0.82, requiredSocPct: 27.5, currentSocPct: 21, socMarginPct: -6.5, gridNeeded: true, gridEnergyNeededKwh: 0.97, prudent: { requiredSocPct: 38.1 }, }, vehicle: { surplusAvailableKwh: 20.17 }, }; export const shadowScenarios = [ { node: 'BUILD_HA_CALLS', id: 'ombre-perimetre-respecte', label: 'Bilan complet : toutes les écritures restent dans evcs_balance_*', snapshot: { ...BALANCE_OK, __nodes: { 'HA Snapshot Balance': SNAPSHOT, CENSORSHIP: CENSORSHIP_CENSURE }, }, expect: { outOfScope: '', wroteRequiredSoc: true, wroteGridNeeded: true, hasLogbook: true, }, }, { node: 'BUILD_HA_CALLS', id: 'ombre-bilan-indisponible', label: 'Bilan inutilisable : statut publié, aucune valeur inventée', snapshot: { usable: false, missing: ['usable_capacity_kwh'], __nodes: { 'HA Snapshot Balance': SNAPSHOT, CENSORSHIP: CENSORSHIP_LIBRE }, }, expect: { outOfScope: '', wroteRequiredSoc: false, hasLogbook: false, }, }, { node: 'BUILD_HA_CALLS', id: 'ombre-kill-switch', label: 'Kill-switch à OFF : absolument aucune écriture', snapshot: { ...BALANCE_OK, __nodes: { 'HA Snapshot Balance': { ...SNAPSHOT, balance_enabled: 'off' }, CENSORSHIP: CENSORSHIP_CENSURE, }, }, expect: { callCount: 0, outOfScope: '', }, }, ]; // --- BUILD_HA_CALLS_PROFILES (workflow quotidien) ------------------------ const PROFILES_OK = { complete: true, days: 28, csv: { p50: '1,'.repeat(23) + '1', p80: '2,'.repeat(23) + '2', envelope: '3,'.repeat(23) + '3', censorshipRate: '0,'.repeat(23) + '0' }, totals: { typicalDailyKwh: 31.9, prudentDailyKwh: 42.8 }, production: { demonstratedDailyKwh: 74.4, censoredDayHours: 8 }, quality: { hoursUsed: 639, pvHoursUsed: 620, countersReset: 0, unreliableHours: [] }, }; export const profilesShadowScenarios = [ { node: 'BUILD_HA_CALLS_PROFILES', id: 'profils-perimetre-respecte', label: 'Publication des profils : périmètre evcs_balance_* respecté', snapshot: PROFILES_OK, expect: { outOfScope: '', callCount: 6, hasLogbook: true }, }, { node: 'BUILD_HA_CALLS_PROFILES', id: 'profils-historique-insuffisant', label: 'Historique trop court : les profils en place ne sont PAS écrasés', snapshot: { ...PROFILES_OK, complete: false, days: 2, quality: { ...PROFILES_OK.quality, unreliableHours: [3, 4, 5] } }, expect: { outOfScope: '', wroteProfiles: false }, }, ];