Add a feature roadmap and implementation plan for a consensus-based algorithm for the condition code in the current conditions endpoint
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful

This commit is contained in:
2026-06-28 16:44:34 -05:00
parent 5a1134b955
commit cfe6748330
2 changed files with 166 additions and 0 deletions

56
docs/roadmap/current.md Normal file
View File

@@ -0,0 +1,56 @@
# Current Conditions Condition-Code Selection
## Summary
Improve `/conditions/current` so numeric conditions continue to aggregate from recent observations, but `conditionCode` is selected by source-balanced WMO family consensus instead of numeric maximum. The goal is to prevent a single bad high WMO code, such as an erroneous thunderstorm code, from dominating current conditions while still returning a useful code when providers report semantically similar conditions.
## Target Behavior
Current conditions continue to use the application observation window, currently `app.ObservationWindowMinutesDefault`.
Numeric and directional fields remain aggregate values over recent `observations` rows:
- temperature, apparent temperature, dewpoint, relative humidity, and wind speed use averages;
- wind direction uses circular averaging;
- `isDay` comes from the latest row in the window.
`conditionCode` uses source-balanced consensus:
1. Select the latest observation per `event_source` within the current window.
2. Each source contributes at most one WMO condition-code vote.
3. Map each voted WMO code to a semantic family.
4. Select the family with the highest source vote count.
5. If the family vote is tied, return `model.WMOUnknown`.
6. Within the winning family, select the most frequent exact WMO code.
7. If exact-code vote is tied within the winning family, select the first code by family-specific representative ranking.
8. If there are no recognized condition-code votes, return `model.WMOUnknown`.
Family mapping and tie ranking:
| Family | Codes / tie ranking |
| --- | --- |
| `clear_or_cloud` | `0`, `1`, `2`, `3` |
| `fog` | `45`, `48` |
| `drizzle` | `51`, `53`, `55`, `56`, `57` |
| `rain` | `61`, `63`, `65`, `80`, `81`, `82`, `66`, `67` |
| `snow` | `71`, `73`, `75`, `85`, `86`, `77` |
| `thunderstorm` | `95`, `96`, `99` |
Examples:
| Source votes | Result |
| --- | --- |
| `0`, `1`, `2` | `0` |
| `1`, `2`, `95` | `1` |
| `0`, `95` | `model.WMOUnknown` |
| `61`, `63`, `80` | `61` |
| `61`, `95`, `0` | `model.WMOUnknown` |
| only `95` | `95` |
## Policy Decisions
- No public response schema change is required.
- No weatherfeeder change or database migration is required because `observations.event_source`, `condition_code`, `observed_at`, and `event_emitted_at` already exist.
- Provider-specific blacklists, trust weights, and source priorities are intentionally out of scope for this change.
- `WMOUnknown` is preferable to falsely choosing between tied precipitation, thunderstorm, and clear/cloud families.
- Current conditions remain a latest-window read model, not a durable derived table.