Trois colonnes nullables : gtiObserved (W/m²), gtiObservedSource
(openmeteo-satellite-state), gtiObservedAt (observedGtiTime tel que publié).
Rattachées au pas [T − 1 h, T) : même convention que gti prévu (§14.3),
Open-Meteo horodatant une moyenne horaire à la fin de son heure.
L'observation arrive 1 à 4 h après l'écriture du pas : elle complète la ligne
existante par un UPDATE ciblé — ces trois colonnes seulement, seulement si
gtiObserved IS NULL. Seule exception à « une ligne n'est jamais réécrite » ;
elle ne crée jamais de ligne. Encore en tampon, elle entre par l'INSERT.
Une table de forme etm67 exacte est migrée par ALTER TABLE ADD COLUMN dans une
transaction : lignes conservées, nouvelles colonnes NULL. Le mécanisme « forme
inattendue → refaite » ne vaut plus que pour les autres formes.
Tests loadmodel : migration d'une base écrite par le code etm67 lui-même
(fixture data/energy-forecast-etm67.sqlite), rattachement, retard, nuit à 0,
valeur jamais remplacée, aucun autre champ touché.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brief 3 T2. Nouvelle table dans energy-forecast.sqlite, clé (targetAt, siteId,
planId) : le pas écoulé est un fait clos, jamais réécrit (ON CONFLICT DO NOTHING,
pas INSERT OR IGNORE qui avalerait un NOT NULL). Les révisions restent dans
forecastPv ; la table y renvoie par la clé de contenu du §20 (révision en vigueur
à J−1 18:00 locale et à H−1).
gti/tempC et paramètres v2 NULL en v1, jamais 0. Production moyenne depuis les
échantillons d'une minute du bilan, NULL sous 90 % de couverture ou sans
producteur. Écrêtage détecté seulement contre le plafond AC déclaré ; neige =
chute lue sur le site. Écriture sur un fil dédié ; rétention 400 jours ; table
abîmée refaite ou mise de côté, le service continue.
Tests loadmodel : 5 fonctions, 13 contre-épreuves vérifiées échouant.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>