FA-70871 / Weather index computation / Open access
Wind chill from km/h anemometer: warm cutoff inclusivity · case 01
At exactly 50 degF the index returns the air temperature despite qualifying wind.
ROOT CAUSE
The validity limit excludes 50 degF although the formula is defined for T <= 50.
THE FAILURE
The validity limit excludes 50 degF although the formula is defined for T <= 50.
Unsuccessful approach: Lowering the cutoff to freezing suppresses wind chill for 33 to 50 degF.
Case contract
Input temperature in degF and wind in km/h. Convert wind to mph (divide by 1.609344). If T > 50 degF or wind below 3 mph, return T rounded to 0.1. Otherwise return 35.74 + 0.6215T - 35.75V^0.16 + 0.4275T*V^0.16 rounded to 0.1.
Why this case matters
Cold-weather advisories and frostbite timing use the wind chill index.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(t_f, wind_kmh):
mph = wind_kmh / 1.609344
if t_f >= 50 or mph < 3:
return round(t_f, 1)
v = mph ** 0.16
wc = 35.74 + 0.6215 * t_f - 35.75 * v + 0.4275 * t_f * v
return round(wc, 1)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['-40F with 0 km/h wind', [-40, 0], -40], ['-40F with 3 km/h wind', [-40, 3], -40], ['-40F with 4 km/h wind', [-40, 4], -40], ['-40F with 4.8 km/h wind', [-40, 4.8], -40], ['-40F with 5 km/h wind', [-40, 5], -52.5], ['-40F with 8 km/h wind', [-40, 8], -57.4], ['40F with 8 km/h wind', [40, 8], 36.5], ['50F with 5 km/h wind', [50, 5], 49.6]], [['-40F with 32 km/h wind', [-40, 32], -74.4], ['-40F with 64 km/h wind', [-40, 64], -84.4], ['-40F with 100 km/h wind', [-40, 100], -91.4], ['-20F with 0 km/h wind', [-20, 0], -20], ['-20F with 3 km/h wind', [-20, 3], -20], ['-20F with 4 km/h wind', [-20, 4], -20], ['49F with 5 km/h wind', [49, 5], 48.4], ['50F with 32 km/h wind', [50, 32], 43.6]], [['-20F with 5 km/h wind', [-20, 5], -29.8], ['-20F with 8 km/h wind', [-20, 8], -33.9], ['-20F with 16 km/h wind', [-20, 16], -40.7], ['-20F with 32 km/h wind', [-20, 32], -48.2], ['-20F with 64 km/h wind', [-20, 64], -56.5], ['-20F with 100 km/h wind', [-20, 100], -62.5], ['49F with 100 km/h wind', [49, 100], 37.5], ['50F with 5 km/h wind', [50, 5], 49.6]], [['-5F with 3 km/h wind', [-5, 3], -5], ['-5F with 4 km/h wind', [-5, 4], -5], ['-5F with 4.8 km/h wind', [-5, 4.8], -5], ['-5F with 5 km/h wind', [-5, 5], -12.8], ['-5F with 8 km/h wind', [-5, 8], -16.3], ['-5F with 16 km/h wind', [-5, 16], -22.1], ['50F with 32 km/h wind', [50, 32], 43.6], ['50F with 64 km/h wind', [50, 64], 40.9]], [['-5F with 64 km/h wind', [-5, 64], -35.7], ['-5F with 100 km/h wind', [-5, 100], -40.7], ['0F with 0 km/h wind', [0, 0], 0], ['0F with 3 km/h wind', [0, 3], 0], ['0F with 4 km/h wind', [0, 4], 0], ['0F with 4.8 km/h wind', [0, 4.8], 0], ['40F with 32 km/h wind', [40, 32], 30.5], ['50F with 5 km/h wind', [50, 5], 49.6]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| -40F with 0 km/h wind | -40 | -40 | Passed |
| -40F with 3 km/h wind | -40 | -40 | Passed |
| -40F with 4 km/h wind | -40 | -40 | Passed |
| -40F with 4.8 km/h wind | -40 | -40 | Passed |
| -40F with 5 km/h wind | -52.5 | -52.5 | Passed |
| -40F with 8 km/h wind | -57.4 | -57.4 | Passed |
| 40F with 8 km/h wind | 36.5 | 36.5 | Passed |
| 50F with 5 km/h wind | 50 | 49.6 | Failed |
SHA-256 / 9c5e8db14b297aaa0e1dc403dd4119615366f4ee5d10fa7a56f96e20684f7497
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(t_f, wind_kmh):
mph = wind_kmh / 1.609344
if t_f > 32 or mph < 3:
return round(t_f, 1)
v = mph ** 0.16
wc = 35.74 + 0.6215 * t_f - 35.75 * v + 0.4275 * t_f * v
return round(wc, 1)
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['-40F with 0 km/h wind', [-40, 0], -40], ['-40F with 3 km/h wind', [-40, 3], -40], ['-40F with 4 km/h wind', [-40, 4], -40], ['-40F with 4.8 km/h wind', [-40, 4.8], -40], ['-40F with 5 km/h wind', [-40, 5], -52.5], ['-40F with 8 km/h wind', [-40, 8], -57.4], ['40F with 8 km/h wind', [40, 8], 36.5], ['50F with 5 km/h wind', [50, 5], 49.6]], [['-40F with 32 km/h wind', [-40, 32], -74.4], ['-40F with 64 km/h wind', [-40, 64], -84.4], ['-40F with 100 km/h wind', [-40, 100], -91.4], ['-20F with 0 km/h wind', [-20, 0], -20], ['-20F with 3 km/h wind', [-20, 3], -20], ['-20F with 4 km/h wind', [-20, 4], -20], ['49F with 5 km/h wind', [49, 5], 48.4], ['50F with 32 km/h wind', [50, 32], 43.6]], [['-20F with 5 km/h wind', [-20, 5], -29.8], ['-20F with 8 km/h wind', [-20, 8], -33.9], ['-20F with 16 km/h wind', [-20, 16], -40.7], ['-20F with 32 km/h wind', [-20, 32], -48.2], ['-20F with 64 km/h wind', [-20, 64], -56.5], ['-20F with 100 km/h wind', [-20, 100], -62.5], ['49F with 100 km/h wind', [49, 100], 37.5], ['50F with 5 km/h wind', [50, 5], 49.6]], [['-5F with 3 km/h wind', [-5, 3], -5], ['-5F with 4 km/h wind', [-5, 4], -5], ['-5F with 4.8 km/h wind', [-5, 4.8], -5], ['-5F with 5 km/h wind', [-5, 5], -12.8], ['-5F with 8 km/h wind', [-5, 8], -16.3], ['-5F with 16 km/h wind', [-5, 16], -22.1], ['50F with 32 km/h wind', [50, 32], 43.6], ['50F with 64 km/h wind', [50, 64], 40.9]], [['-5F with 64 km/h wind', [-5, 64], -35.7], ['-5F with 100 km/h wind', [-5, 100], -40.7], ['0F with 0 km/h wind', [0, 0], 0], ['0F with 3 km/h wind', [0, 3], 0], ['0F with 4 km/h wind', [0, 4], 0], ['0F with 4.8 km/h wind', [0, 4.8], 0], ['40F with 32 km/h wind', [40, 32], 30.5], ['50F with 5 km/h wind', [50, 5], 49.6]]]
for label, args, expected in fixtures[N - 1]:
check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| -40F with 0 km/h wind | -40 | -40 | Passed |
| -40F with 3 km/h wind | -40 | -40 | Passed |
| -40F with 4 km/h wind | -40 | -40 | Passed |
| -40F with 4.8 km/h wind | -40 | -40 | Passed |
| -40F with 5 km/h wind | -52.5 | -52.5 | Passed |
| -40F with 8 km/h wind | -57.4 | -57.4 | Passed |
| 40F with 8 km/h wind | 40 | 36.5 | Failed |
| 50F with 5 km/h wind | 50 | 49.6 | Failed |
SHA-256 / a2b9ce0a2c6794b1f7e73606dc4e6fca1d3fd3c10d73c0f0448f719cd1c2d98a
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗Verification & scope
Stipulated deterministic teaching model of an operational weather index; coefficients and thresholds are fixed by the contract and no claim of standards conformance is made. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:48:24.697302+00:00.
Case digest / 340a3050b7f536ec389cbd8c7041edf7b3b1e30c7796e2ecf654ba0de622c3b5