Same fix as graphcast-benchmark c75e327 (same root cause). Our first
GFS smoke test on the benchmark Space diverged to 60°+ temperatures;
GraphCast's published normalization stats show it was trained on a
1-hour TOA accumulation (mean 1.07e6 J/m², stddev 1.44e6) even though
the model itself steps at 6h. Default changed to 1h; new test asserts
our analytical values land in the GraphCast stats band.
No CRE production behaviour change on the existing ERA5t path;
relevant only when NWP_INIT_SOURCE=gfs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
gfs: analytical TOA forcing + pipeline traceback logging
The first CRE GFS smoke fell back to observed_fallback for all 15 zones.
Root cause: GraphCast's task_config forces toa_incident_solar_radiation
on every forecast step, but GFS pgrb2.0p25 doesn't publish it — cfgrib
returns nothing, graphcast.data_utils.extract_inputs_targets_forcings
raises, and the pipeline catches the exception and falls back silently.
This commit:
- adds compute_toa_incident_solar_radiation() that integrates
S0 * max(0, cos zenith) over each 6h window. 12 substeps ≈ 30-min
quadrature, units J/m^2 to match ERA5.
- attaches TOA to full_ds after the per-timestep concat in
fetch_gfs_as_era5 so it's present at every input + forecast step.
- logs per-timestep a count of loaded surface + pressure-level vars
so the next live run will tell us which vars actually made it in.
- switches the pipeline's fallback warning to log.exception so the
traceback lands in container logs — next fall-back, we'll see why.
- 5 new unit tests pin shape, non-negativity, night=0, noo…
Fix GFS shortName regression: use ecCodes names, not cfgrib names
Mirror of the WA2 fix — same bug, same change, synced to stay in lockstep
until init_sources is extracted to a shared package.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add GFS init source as alternative to ERA5T (Phase 2 wiring)
Mirrors the same plumbing shipped in Weather AI 2. CRE's GraphCast
currently inits from ARCO ERA5T at today-5, which means its "5-day
forecast" actually covers today-5 through today-1 — the past week,
not the next week. Trigger decisions confirm past heat events instead
of warning before, which misaligns with the alert-SMS product intent.
GFS has ~3h lag instead of 5 days, enabling forward-looking forecasts
over today → today+5.
Behind a config toggle:
* NWP_INIT_SOURCE=gfs — GFS instead of ERA5T
* NWP_TARGET_DATE_OVERRIDE=YYYY-MM-DD — pin init date for
validation runs against the LMB insurance benchmark panel
Defaults leave existing ERA5T behavior unchanged. Only
src/init_sources/ + tests/test_init_sources/ + two one-line call-site
swaps in graphcast_inference/pipeline touch production code.
56 new unit tests, all pass. Opt-in live GFS test skipped unless
GFS_LIVE_TEST=1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>