Fix Ridge wind direction no longer snapped to 45° sectors
Kaider and Tavo flew Paldiski on the morning of 22 April (09:30–11:30 local), even though the Opportunities page had reported NO-GO for the day with the reason “wrong direction: NW (315°)”. They reported the flights afterwards — which is how the bug was caught. Aitäh!
Every forecast model on Windguru for that morning (HARM-FI 2.5 km, MET Nordic, HARM-DK, Zephyr-HD, HARMONIE) showed 286°–298°, well inside Paldiski’s 259°–310° acceptable window. The forecast itself was fine.
Root cause: the window-level direction aggregate bucketed the four passing morning hours (305°, 293°, 301°, 292°) into one of eight 45° sectors and returned the sector midpoint — here, NW 315°. The direction gate then compared that snapped 315° against Paldiski’s acceptable window and hard-failed. The true circular mean of those hours is 297.7°.
Fix: modal_wind_dir now returns a circular vector mean instead of the sector midpoint. The same snap affected Türisalu, Tabasalu, Toila, and Alajõe too — Alajõe was quietly passing some directions just outside its 135°–225° window because 140° rounded to 135°. Regression tests added for both flavours.
Code: modal_wind_dir in archive/cron/lib/assessors.php. Investigation and fix implemented by Claude Code.
19 April 2026
Fix Morning flyable windows no longer masked by afternoon gusts
Pilots flew Tabasalu on the morning of 18 April, but the Opportunities page reported NO-GO for the whole day. Investigation: the forecast was correct — Vanasadam observed gusts up to 10.6 m/s in the afternoon, which tripped the 9 m/s ridge gust hard gate. But the gate was applied to the day’s maximum gust, so a single gusty afternoon hour killed the calm morning window too.
Fix: the gust gate is now also applied per hour. Gusty hours drop out of the flyable window, so a calm sub-window (09–12 UTC in this case) can still be assessed on its own. Simulated against the observed data, 18 April Tabasalu would now have shown a morning GOOD verdict.
While at it, Toila and Alajõe were extended with the same 9 m/s gust gate — previously they did not track gusts at all. All five ridge sites (Paldiski, Türisalu, Tabasalu, Toila, Alajõe) now apply the same gust rule, both per-hour and per-window.
Code: hour_passes_ridge, hour_passes_toila, hour_passes_alajoe, assess_toila, assess_alajoe, aggregate_coastal. Regression tests added. Changes implemented by Claude Code.
17 April 2026
New Contrails card in the morning briefing
The briefing now includes a contrail forecast for Tallinn-Harku and Kuusiku at 300 and 250 hPa (~9–10 km cruise altitude). Per location the card shows:
Whether contrails will form at all (Schmidt-Appleman threshold, T < −40 °C).
Whether they will persist and spread into cirrus (ice-supersaturation, RHi ≥ 100 %) — relevant because widespread cirrus under the sun weakens thermals.
The peak hour with temperature, RHi, and wind aloft — so a pilot on the field can look up and verify the forecast by eye.
Huge thanks to Mitja Vishnjakov — this one was entirely his idea. It is the kind of sideways thought that makes the whole site better: most of us look down at wind and BLH, Mitja looked up at the sky and asked what the jet trails could tell us. Aitäh, Mitja!
Improved Rapla FP/FN confidence indicator — now live
The historical miss-rate indicator described below is now active on the Opportunities page. The daily calibration script ran for the first time today: 19 ERA5 dates evaluated, 99 (verdict, lead) pairs aggregated. All NO-GO forecasts in the post-v4 window had FN 0% at every lead time.
Buckets for MARGINAL/POSSIBLE/GOOD show “·” (fewer than 10 samples) — will fill in over the coming weeks.
13 April 2026
New Rapla cells now show historical miss rate
Each Rapla cell on the Opportunities page now carries a small FP or FN number showing how the same verdict has performed historically at that lead time:
FP X% (on GOOD / EXCELLENT cells) — share of past forecasts with the same verdict at the same lead time where ERA5 reanalysis turned out to be below GOOD. The risk of committing a drive for a day that did not materialise.
FN X% (on NO-GO / MARGINAL / POSSIBLE cells) — share of past forecasts where ERA5 reanalysis actually met GOOD. The risk of skipping a day that would have been flyable.
A dim “·” means fewer than 10 past samples in that (verdict, lead) bucket — insufficient history.
Computed daily from assessment_log (stored forecasts since the current Rapla rules took effect on 22 March) vs Open-Meteo ERA5 reanalysis. Only “is the day flyable?” is measured — tier shifts within flyable or within non-flyable don’t count.
12 April 2026
Improved Morning briefing: maps and sounding
Three usability improvements to the daily morning briefing page:
Skew-T Log-P diagram — the Tallinn-Harku 00Z sounding now includes the full Skew-T diagram from University of Wyoming, with a legend explaining temperature, dewpoint, dry/moist adiabats, mixing ratio lines, and how to read them for thermal forecasting.
SIGWX fallback link — when the SIGWX SFC–10000ft chart is unavailable, a direct link to lennuilm.ee is shown so you can check manually.
5 April 2026
Improved Dashboard accuracy overhaul
Major dashboard update driven by the first user feedback from Kaia Kala — thank you! The core insight: Pakri ridge-top station shows a systematic −27° to −30° wind direction bias in the ridge-relevant WSW–NW sector, making it misleading for soaring decisions.
Pakri hidden from Wind Overview for Paldiski and Türisalu. Port stations (Põhjasadam, Lõunasadam) are more accurate for ridge wind assessment. Pakri data remains visible in Wind History and Conditions for reference.
Wind direction arrows on the history chart now use the calibrated reference station (Põhjasadam for Paldiski, Vanasadam for Tabasalu/Türisalu).
Sea Thermal Activity card — new tile showing ΔT (water − air temperature). When sea surface is warmer than air, the marine boundary layer becomes unstable, producing sea thermals that can supplement ridge lift. Thresholds: < 0°C stable, 0–2°C neutral, 2–4°C moderate, > 4°C strong. Available for Paldiski, Tabasalu, Türisalu, and Toila.
Square root wind scale on the Forecast tile gives better visual resolution in the flyable 1–5 m/s range while compressing strong winds.
Cloud & Temperature legend added (solid line = cloud cover, dashed = temperature).
Toila-Oru station added to observation collection — was configured but never collected.
Pakri bias documented from 100,681 matched hourly pairs (2013–2024) against Põhjasadam.
2 April 2026
Improved Multi-model BLH verification fixed
The system compares boundary layer height (BLH) forecasts from two models — GFS and MET Norway Nordic — against ERA5 reanalysis to find which predicts thermal ceiling more accurately.
Investigation revealed that the “KNMI” model label was misleading: KNMI HARMONIE does not provide BLH at all. The Open-Meteo seamless wrapper silently substitutes MET Norway Nordic for forecast dates and ERA5 reanalysis for past dates. This made the old comparison circular — ERA5 vs ERA5.
Renamed blh_knmi → blh_metno across the pipeline to reflect the actual data source.
Verification now only uses forecasts with lead ≥1 day, ensuring genuinely independent predictions.
Early results (N=6): MET Norway Nordic MAE 78 m, GFS MAE 183 m. More data needed.
31 March 2026
Improved Ridge forecasts now use the best model for each lead day
A 30-day benchmark of 12 weather models against Estonian station observations revealed that no single model is best at all forecast horizons. Ridge soaring sites (Paldiski, Türisalu, Tabasalu, Toila, Alajõe) now automatically select the most accurate wind model based on how far ahead the forecast is:
D+0–2 — FMI HARMONIE-AROME 2.5 km (wind MAE 1.15–1.30 m/s). Already in use since March 8.
D+3 — DWD ICON 7 km (MAE 1.35 m/s). New — replaces the generic Open-Meteo “best match”.
D+4–5 — ECMWF IFS-HRES 9 km (MAE 1.5–1.7 m/s). New — the most gracefully degrading global model.
D+6+ — no model beats 2.0 m/s MAE. Shown as trend only.
Each assessment now records which model provided the wind data. Falls back gracefully to the default model if the preferred one is unavailable.
31 March 2026
Data Forecast model benchmark published
The Forecast Accuracy Benchmark page now updates weekly with verification statistics for all 12 Windguru models against Estonian weather station observations. Metrics include wind speed MAE, direction MAE, and temperature bias, sorted by accuracy.
A separate lead-time analysis showed that high-resolution models (1–2.5 km) are barely better than global models (13–15 km) at D+0, but diverge sharply by D+3. Wind direction degrades faster than speed — by D+5, direction errors exceed the width of a typical ridge site’s optimal wind window.
22 March 2026
Improved Wind and gust safety gates for Rapla and ridge sites
The assessors now check gusts, not just mean wind. Key changes:
Rapla gust gate — gusts >9 m/s are a hard NO-GO. Gusts >7 m/s with crosswind (>20° off runway 15/33) are also NO-GO; along the runway they produce a warning only.
Rapla wind scoring — mean wind >4.2 m/s now penalises the score (−1). South wind (S/SSW/SSE) also penalises (−1) due to restricted airspace limiting XC distance.
Ridge gust gate — gusts >9 m/s are NO-GO for Paldiski, Türisalu, and Tabasalu.
Ridge sweet spot narrowed — the ideal wind range is now 4.7–6.0 m/s (was 4.7–10.0). Wind above 6 m/s is “strong” and scores lower.
22 March 2026
Improved Forecast accuracy tracking — how far ahead can you trust the verdict?
The system now stores every assessment verdict it produces (with all the weather inputs that went into it) and compares them against ERA5 reanalysis — what the weather actually was. This builds a track record over time showing:
Lead-time reliability — how many days ahead is the Rapla thermal forecast trustworthy? (T-1? T-2? T-3?)
BLH convergence — how the boundary layer height prediction for a given date evolves from T-5 to T-0, and when it settles near the actual value
Multi-model BLH comparison — GFS vs KNMI vs Open-Meteo best_match, checked against ERA5 reanalysis to find which model predicts BLH most reliably for Rapla
New signals — dewpoint spread (T−Td) as a dry-air/thermal quality indicator, station visibility as an aerosol proxy, and previous-day precipitation effect on BLH bias
Parameter bias — which inputs (BLH, temperature, wind, cloud cover) are causing the most verdict errors and by how much
The accuracy pipeline runs locally. Results will feed back into model selection and threshold calibration as data accumulates over the coming weeks.
20 March 2026
New Vatsla ground handling site added
The Opportunities page now includes Vatsla — a ground handling spot that works in NE through SSE winds (45°–170°). Complements the existing sites which favour west and south directions.
20 March 2026
Improved Harku GH renamed to Lennuplats Kollane
The generic “Harku GH” ground handling site is now called Lennuplats Kollane — its actual name. Same location, same any-direction filter.
20 March 2026
Improved Fewer API calls, faster Opportunities page
Ground handling sites that share the same forecast coordinates now reuse a single Open-Meteo response instead of making duplicate API calls. Reduces total requests from 9 to 7 per run, saving 2–4 seconds of runtime.
19 March 2026
Improved Tap cells for details on mobile
The Flying Opportunities table now works on phones. Tapping any cell opens a bottom sheet with the full forecast details — gate reasons, window times, wind, BLH, temperature, soil moisture. Previously this information was only accessible via mouse hover on desktop.
19 March 2026
Fix Opportunities page no longer crashes when Open-Meteo is slow
The Flying Opportunities page failed intermittently when Open-Meteo responses were slow. With a 30-second per-request timeout and a built-in retry, a single sluggish fetch could hold the script for 62 seconds — long enough for the server to kill the process mid-run. The page would silently stop updating.
Fixed by reducing the Open-Meteo fetch timeout to 15 seconds (worst-case retry cycle: 32 s) and adding set_time_limit(0) to prevent the server’s default 30-second execution cap from applying to long-running cron scripts.
17 March 2026
Improved Scenario tests catch logic bugs before deployment
Assessment logic (hourly gates, wind direction windows, verdicts) is now covered by 34 automated scenario tests that run in CI on every commit. This catches inconsistencies like the gust fallback bug — where changing the verdict function without updating the upstream hourly filter caused gusty-but-flyable conditions to be silently rejected.
Pure assessment functions were extracted into a separate library (lib/assessors.php) for testability. The opportunities page shrank from 2200 to 1200 lines.
17 March 2026
Fix Opportunities page survives FMI outages
The Flying Opportunities page crashed twice today when the FMI HARMONIE-AROME API went down. The script makes 24 HTTP requests to FMI (4 ridge sites × 6 days); with the API unresponsive, timeouts accumulated to ~480 seconds and exceeded the server’s execution limit.
Fixed with a circuit breaker: if the first HARMONIE request fails, all remaining FMI requests are skipped. Ridge sites gracefully fall back to Open-Meteo data. Also reduced per-request timeout from 20 s to 8 s.
17 March 2026
New Soil moisture now in forecasts
Rapla airfield director Kristjan Plamus asked pilots to stay away for ~2 weeks because the grass field is too wet after snowmelt. That got us thinking: does ground moisture affect thermals too, not just the runway?
Turns out, yes. Dry ground heats the air more efficiently — wet ground wastes solar energy on evaporation instead (the Bowen ratio effect). Analysis of 114 Rapla flight dates (438 flights, 2014–2025) against ERA5-Land soil moisture data shows that pilots fly 2.6× farther on dry soil days (median 41.7 km vs 15.8 km on wet days). The effect is strongest on cool, marginal days — exactly when you need the extra signal most.
What changed:
Morning Briefing — new “Ground conditions” card shows soil moisture for Kuusiku (flying site) and Tallinn (reference point you can verify outside your window). Color-coded: DRY = good for thermals, WET = thermals weakened.
Flying Opportunities — Rapla thermal cells now show 🟤 (dry soil, +1 bonus point) or 🔵 (wet soil, warning). Hover for the numeric value.
Rapla XC assessor (rapla_xc.py) — +1 score bonus when soil is dry and temperature is below 23°C. This helps marginal spring days score closer to reality.
Thresholds (DRY < 0.22, WET > 0.32 m³/m³) are calibrated on ERA5-Land 0–7 cm layer. Forecast API uses 0–1 cm — values are preliminary. Full analysis on the blog.
17 March 2026
Improved Ridge sites work in gusty light wind
Ridge soaring sites (Paldiski, Türisalu, Tabasalu) no longer show NO-GO when sustained wind is below 4.0 m/s but gusts are strong enough to fly. Previously, mean wind < 4.0 m/s was an automatic NO-GO — now the system checks gusts and shows MARGINAL instead.
Calibrated from Kaider’s Paldiski flight today: mean wind only 2.8 m/s, but gusts 4.9 m/s — enough for 30 minutes of ridge soaring in fog. The old algorithm said NO-GO; Kaider proved it wrong.
14 March 2026
New System status page
A status page now monitors all 11 data sources and shows their freshness. Automated alerts trigger if any source goes stale for more than an hour.
14 March 2026
Improved Dashboard reads from database
The main dashboard now reads observations from the database instead of scraping live XML/HTML on every page load. Response time dropped from ~2 seconds to ~5 ms.
9 March 2026
New Trip Planner with live flight prices
The Trip Planner combines XC weather forecasts with live flight prices from Tallinn for Ager (Catalonia), Bassano (Italy), and other destinations. Auto-discovers new spots from config files.
8 March 2026
Improved Wind direction with HARMONIE-AROME 2.5 km
Ridge sites (Paldiski, Türisalu, Tabasalu) now use the FMI HARMONIE-AROME 2.5 km model for wind direction when available. This high-resolution model outperforms GFS by 50% for direction accuracy near the complex Estonian coastline.
8 March 2026
Fix Wind speed unit bug
Fixed a bug where Open-Meteo wind speed was interpreted as m/s but was actually km/h (the API default). All wind thresholds are now correctly calibrated. This fix affected both the opportunities dashboard and the main dashboard.