Ce qui est en cours, ce qui s'en vient, ce qui est reporté, et ce qui a été mis en ligne.
globals.css pilotent déjà les 338 lignes suivantes ; les isoler dans un fichier de thème importé après, avec un emplacement de logo, pour qu'une identité visuelle se change sans toucher à un composant. (2) Seuils de pression dérivés de l'altitude — tempest.ts classe « basse / normale / haute » sur 960 et 975 mb, calibrés pour 377 m ; à calculer depuis location.elevation_m (pression normale ≈ 1013,25 × (1 − 2,25577e−5·h)^5,25588, soit 968,9 mb ici). Attention : la bande dérivée donne 961,4 / 976,4, un écart de ~1,4 mb avec les seuils actuels — quelques jours limites changeront de catégorie, à trancher avant d'appliquer. (3) _scope sur data/breeding.json — les semaines de ponte et d'élevage valent pour une région bioclimatique, pas pour un point ; déclarer la région de calibration et la source, comme le fait déjà quotes.json avec son _about. (4) USER_AGENT configurable — inat.ts annonce almanach-val-des-loups et l'URL du dépôt en dur. (5) npm run doctor — vérifie que almanach.config.json est complet et bien formé (position, altitude, fuseau, identifiants de station, chemins de prompts) et refuse de builder sinon. Il valide la forme, jamais la véracité : une position erronée reste la responsabilité de qui l'a saisie.data/lieu.json) — tarir le décor inventérain_days_since : donner le fait au lieu d'espérer l'inférence. Un data/lieu.json rédigé par Michael — essences réellement présentes, éléments du paysage, orientation du terrain, ce qui entoure le pont couvert — transmis dans le payload, avec interdiction de nommer quoi que ce soit hors de cette liste. L'invention devient du rappel. Le fichier doit venir de Michael : le faire rédiger par le modèle reproduirait exactement l'erreur. Une fois l'inventaire en main, trier et corriger les 44 éditions concernées.data/ebird-species-codes.json statique, refresh annuel manuel) : obtenir une clé API eBird gratuite, l'ajouter aux secrets GitHub, et récupérer la taxonomy à jour automatiquement. Permettrait aussi d'autres features eBird (« Rare au secteur », abondance régionale, etc.).body_md et summary pour confronter aux sources les affirmations vérifiables — durées de temps sec (contre rain_days_since), durées depuis un orage (contre last_storm.days_ago), noms d'espèces (contre top_species + other_species), chiffres cités. En cas de contradiction, lever une FactCheckError : la machinerie de reprise existe déjà, withRetry relance la génération sur SyntaxError dans synthesize.ts — il suffit d'ajouter la famille d'erreurs. C'est ce qui attrape la classe d'erreur plutôt qu'un cas isolé : les 8 fausses sécheresses du 25 juillet ont tenu des semaines en ligne faute de cette vérification. Attention aux faux positifs : « plus d'une semaine » pour 9 jours secs est exact, un contrôle trop littéral le signalerait à tort.npm run lint:editions — vérification de l'archive en CIalmanach.config.json) 19 août 2026 util/date.ts, birdweather.ts, tempest.ts, deux pages du site) et dans l'URL Open-Meteo, a maintenant une source unique. Vérifié : le ciel du 18 août recalculé est identique au committé (crépuscules et Lune au champ près), et le HTML rendu est inchangé.prompts/editorial-voice.md mélangeait deux choses de nature différente : ce que le billet a le droit d'affirmer, et la façon de le dire. Les contraintes de véracité (règle d'or d'exactitude, aucun décor inventé, aucune espèce hors liste, aucune durée sans champ, aucune citation dans le billet) sont désormais dans prompts/editorial-rules.md, fichier invariant qui ne décrit aucun style et ne dépend d'aucun lieu. Le ton, les principes, la forme, les interdits stylistiques, les inspirations et les exemples validés restent dans le fichier de voix, propre à l'instance. La synthèse charge les deux, règles d'abord, avec le point de cache posé sur le second pour couvrir les deux. Aucune ligne perdue à la scission (vérifié ligne à ligne contre la version committée).other_species) 25 juillet 2026 aggregate() ne conservait que les 10 espèces les plus fréquentes alors que le payload continuait d'annoncer unique_species (20 le 24 juillet) : la synthèse voyait dix noms manquants et comblait le trou en inventant. C'est ce qui a produit « la grive des bois » et « le pic-bois » dans l'édition du 24 juillet — deux grives étaient bien présentes ce jour-là (solitaire ×6, à dos olive ×1), mais parmi les espèces jetées. Nouveau champ other_species (nom + compte) portant toute la queue ; top_species reste à 10 pour ne rien changer au rendu du site ni à la résolution des photos iNat. Vérifié sur un fetch réel : 10 + 10 = 20, plus aucune espèce manquante.rain_days_since — jours depuis la dernière pluie 25 juillet 2026 rain_day_final_mm=0. Huit éditions annonçaient une sécheresse pluri-jours au lendemain d'une pluie. Preuve du mécanisme : les 20 affirmations sur les éclairs étaient toutes exactes, parce que lightning.last_storm.days_ago existe. Nouveau module src/util/weather-history.ts partagé par daily.ts et scripts/refresh-weather.ts ; seuil de pluie mesurable à 0,2 mm ; retourne null sur un trou d'historique plutôt que de compter les jours manquants comme secs.derived en tête du payload de synthèse 25 juillet 2026 prompts/editorial-voice.md et au contrat de schéma de synthesize.ts : (1) aucune durée sans champ — toute affirmation dépassant la journée décrite doit venir de derived, et une durée vraie pour un phénomène n'est pas transposable à un autre ; (2) aucun décor inventé — pas d'élément de terrain précis et défini absent des données (« le bouleau mort près du pont »), rester indéfini si un support est nécessaire, tout en autorisant l'extrapolation sur les mœurs connues d'une espèce attestée ; (3) aucune espèce hors liste — ne pas combler l'écart entre unique_species et les espèces effectivement nommées.SyntaxError: Bad control character in string literal : Claude avait inclus un retour à la ligne brut dans une string JSON au lieu de la séquence \n. Le withRetry précédent ne couvrait que les erreurs HTTP (429/529/5xx). Correctifs ajoutés à synthesize.ts : (1) un sanitizeJsonControlChars ré-échappe les caractères de contrôle bruts dans les string literals avant JSON.parse (mini état in-string, attrape la grande majorité des cas en local) ; (2) withRetry couvre désormais aussi les SyntaxError avec un backoff court (5 → 30 s) — un nouvel appel produit une autre génération probabiliste. Filet à deux niveaux : sanitisation locale gratuite, retry pour le résidu.astronomy-engine (offline). Glyphe de phase de lune dessiné sur sa ligne dédiée. Sur mobile : agrandie, centrée, défilement horizontal (même stratégie que le graphique 30 jours).529 « Overloaded » transitoire d'Anthropic à l'étape synthèse — un seul appel raté plantait tout le run, donc l'édition du 1er juin n'a pas été publiée. Correctif : l'appel à Claude est enveloppé dans un withRetry (réessais sur 429/529/5xx, backoff 30 s → 5 min, 5 tentatives), si bien qu'une surcharge passagère se résorbe d'elle-même au lieu de faire sauter l'édition. À noter : les runs planifiés GitHub Actions sont « best-effort » et démarrent souvent 3-5 h après l'heure prévue, donc le job croise des fenêtres variables — la tolérance aux pannes compte plus que l'horaire./teach-impeccable (contexte design persistant dans .impeccable.md — voix « calme · contemplatif · lettré », référence Aldo Leopold), /critique (score Nielsen 34/40 → 38/40 après corrections), puis les correctifs : lecteur audio en charte (remplace le lecteur natif), accessibilité tactile/clavier des interactions au survol (Pointer Events + :focus-within), état « aucune édition » repensé, et passe /polish (respect de prefers-reduced-motion, zone de seek audio agrandie).set:html (XSS stocké de défense en profondeur) ; inputs du workflow passés par env: (plus d'interpolation shell — script injection) ; validation du format --date (traversée de chemin) ; montée d'Astro 5 → 6.4.2 (XSS define:vars). Points informatifs documentés et acceptés (token Tempest en URL imposé par l'API et côté serveur seulement ; vuln dev-only de @astrojs/check non livrée ; SHA-pin des actions = durcissement optionnel).GainNode) et normalise le pic de chaque extrait à ~−3 dB, comme le fait BirdWeather. Dégradation gracieuse si Web Audio indisponible.scripts/backfill-birds.ts, idempotent) ; le cron quotidien fait avancer la fenêtre. Sur mobile, ~10 jours s'affichent à la fois avec défilement horizontal jusqu'à j-30 (départ sur le jour le plus récent). Bonus : l'historique enrichi affine aussi « Premières de la saison ».ebirdUrl(taxon_scientific) : photo de « Observation du jour » et vignettes de « Visiteurs les plus fréquents ». Lien posé uniquement quand un code eBird existe pour le binôme latin. Demande de MCB.stormAgeLabel décalé de +1 : days_ago=0 (orage le jour de l'édition) devient « hier » au lieu de « aujourd'hui », days_ago=1 devient « avant-hier », etc. Cohérence rétablie entre le titre de la page et les cartes Météo.pic 95 000 lux à 14 h + 6 h plein soleil · 3 h voilé · 2 h couvert. Sur mobile (≤560 px) : sparkline pleine largeur en haut, texte en dessous. Stockage : nouveau champ hourly_lux_avg[24] dans WeatherDaily (moyenne horaire). Fallback gracieux (—) pour les éditions sans le nouveau champ.24 éclairs / hier, à 35 km ou 8 éclairs / il y a 17 jours, à 23 km. Au-delà de 90 jours, simplifié en +3 mois sans distance. Calcul dans daily.ts par scan rétrograde de data/weather/*.json (cap 365 jours). Fallback gracieux pour les éditions sans le nouveau champ.data/editions/{date}.json existe déjà, daily.ts skip avec un message clair. Flag --force en CLI et input booléen force dans le workflow_dispatch pour réécrire intentionnellement. Le cron automatique n'est jamais affecté (il tourne toujours sur une date neuve).data/weather/ sans le nouveau champ : fallback gracieux sur l'ancien format.lang: 'fr' | 'en' à toutes les citations, prompt Claude ajusté pour ne pas traduire si la source est déjà en français. Total : 22 citations (13 anglophones + 9 francophones).https://ebird.org/species/{code}?lang=fr). Mapping taxon_scientifique → species_code stocké dans data/ebird-species-codes.json (11 167 espèces, ~350 KB), généré par scripts/build-ebird-codes.ts depuis l'API publique eBird (sans clé). À re-générer ~1×/an (nouvelle taxonomy en octobre).daily.ts filtre les citations utilisées dans les 7 derniers jours avant d'envoyer la liste à Claude — la rotation est garantie côté code, sans dépendre de la mémoire du modèle.taxon_scientific du jour (0 faux positif), appliquée au summary, au billet et à la narration du ciel. Robuste même quand l'IA oublie les marqueurs.<title> et <meta description> 25 mai 2026