FA-71301 / Weather index computation / Open access
Excess heat factor heatwave days: significance window · case 01
Heatwaves are flagged a day before the hot three-day window starts.
ROOT CAUSE
The three-day window is centred on the previous day instead of starting at day i.
VERIFIED REPAIR
Average days i, i+1 and i+2.
Unsuccessful approach: Slicing only two days while dividing by three understates the window mean.
Case contract
temps are daily mean degC. For each day i with 6 prior days and 2 following days: m3 = mean of days i..i+2, prior = mean of days i-6..i-1, EHIsig = m3 - t95, EHIaccl = m3 - prior, EHF = EHIsig * max(1, EHIaccl). Return [[i, EHF rounded 0.01]] for days with EHF > 0.
Why this case matters
Heat-health warning systems trigger on positive excess heat factor.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(temps, t95):
res = []
for i in range(6, len(temps) - 2):
m3 = sum(temps[i - 1:i + 2]) / 3.0
prior = sum(temps[i - 6:i]) / 6.0
sig = m3 - t95
accl = m3 - prior
ehf = sig * max(1.0, accl)
if ehf > 0:
res.append([i, round(ehf, 2)])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['city 0', [[22, 27, 20, 22, 21, 30, 25, 25, 32, 23, 32, 18], 26], [[6, 4.89], [7, 1.67], [8, 15.5]]], ['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 2', [[17, 29, 19, 30, 23, 20, 30, 26, 21, 18, 24, 18], 24], [[6, 4.44]]], ['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 4', [[22, 31, 30, 27, 29, 35, 31, 21, 24, 25, 32, 35], 24], [[6, 1.33], [8, 3.0], [9, 18.89]]], ['city 5', [[24, 24, 28, 33, 23, 27, 27, 28, 27, 28, 34, 25], 28], [[8, 3.33], [9, 1.5]]], ['city 6', [[19, 21, 29, 18, 27, 22, 19, 19, 28, 27, 23, 16], 28], []], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []]], [['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []], ['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 9', [[15, 26, 16, 15, 23, 19, 19, 28, 28, 27, 26, 26], 26], [[7, 13.33], [8, 7.0], [9, 1.44]]], ['city 10', [[19, 26, 22, 22, 17, 20, 16, 17, 28, 25, 25, 24], 28], []], ['city 11', [[27, 28, 31, 19, 23, 21, 32, 31, 22, 23, 20, 22], 26], [[6, 8.17]]], ['city 12', [[27, 24, 26, 17, 20, 26, 23, 24, 20, 19, 26, 26], 26], []], ['city 13', [[19, 26, 25, 27, 20, 25, 22, 27, 19, 25, 24, 26], 26], []]], [['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 15', [[30, 27, 28, 21, 32, 33, 29, 31, 34, 31, 35, 28], 24], [[6, 20.78], [7, 29.33], [8, 40.44], [9, 9.78]]], ['city 16', [[26, 25, 22, 33, 23, 19, 25, 32, 22, 23, 23, 31], 26], [[6, 0.56]]], ['city 17', [[23, 21, 21, 21, 31, 19, 22, 25, 26, 27, 21, 20], 28], []], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 19', [[23, 21, 25, 18, 19, 19, 27, 27, 23, 18, 17, 21], 28], []], ['city 20', [[24, 26, 32, 29, 31, 24, 23, 23, 26, 24, 23, 18], 28], []]], [['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 21', [[35, 29, 27, 30, 30, 28, 29, 35, 22, 24, 24, 29], 24], [[6, 4.67], [7, 3.0], [9, 1.67]]], ['city 22', [[28, 23, 24, 20, 29, 28, 18, 28, 18, 26, 20, 18], 24], []], ['city 23', [[34, 34, 28, 22, 23, 27, 21, 21, 31, 24, 24, 23], 26], [[8, 0.89]]], ['city 24', [[32, 30, 18, 25, 18, 26, 28, 23, 31, 21, 25, 25], 28], []], ['city 25', [[28, 26, 30, 18, 22, 31, 20, 20, 24, 29, 29, 30], 26], [[8, 5.11], [9, 22.78]]], ['city 26', [[22, 27, 19, 25, 14, 26, 15, 25, 22, 25, 24, 18], 28], []], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]]], [['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]], ['city 29', [[27, 24, 26, 19, 17, 20, 28, 16, 17, 28, 21, 20], 28], []], ['cool acclimatised spell', [[30, 30, 30, 30, 30, 30, 27, 27, 27, 20], 26], [[6, 1.0]]], ['exact threshold', [[20, 20, 20, 20, 20, 20, 26, 26, 26, 22], 26], []], ['short record', [[25, 26, 27, 28, 29, 30, 31, 32], 25], []], ['record ends in extreme heat', [[22, 23, 22, 24, 23, 22, 25, 26, 38, 40], 26], [[6, 25.67], [7, 99.67]]]]]
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 |
|---|---|---|---|
| city 0 | [[6, 2.0], [7, 4.22], [8, 1.89], [9, 9.5]] | [[6, 4.89], [7, 1.67], [8, 15.5]] | Failed |
| city 1 | [[6, 1.67], [7, 4.0], [8, 13.72], [9, 4.67]] | [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]] | Failed |
| city 2 | [[6, 3.11], [7, 1.67]] | [[6, 4.44]] | Failed |
| city 3 | [[6, 3.0], [7, 2.67], [8, 3.0], [9, 3.0]] | [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]] | Failed |
| city 4 | [[6, 5.0], [7, 1.33], [9, 3.0]] | [[6, 1.33], [8, 3.0], [9, 18.89]] | Failed |
| city 5 | [[9, 3.61]] | [[8, 3.33], [9, 1.5]] | Failed |
| city 6 | [] | [] | Passed |
| city 7 | [] | [] | Passed |
SHA-256 / f759dcbbf81896bfdd27080285f58639a53437d4471241e6771ad1188717b4f3
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(temps, t95):
res = []
for i in range(6, len(temps) - 2):
m3 = sum(temps[i:i + 2]) / 3.0
prior = sum(temps[i - 6:i]) / 6.0
sig = m3 - t95
accl = m3 - prior
ehf = sig * max(1.0, accl)
if ehf > 0:
res.append([i, round(ehf, 2)])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['city 0', [[22, 27, 20, 22, 21, 30, 25, 25, 32, 23, 32, 18], 26], [[6, 4.89], [7, 1.67], [8, 15.5]]], ['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 2', [[17, 29, 19, 30, 23, 20, 30, 26, 21, 18, 24, 18], 24], [[6, 4.44]]], ['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 4', [[22, 31, 30, 27, 29, 35, 31, 21, 24, 25, 32, 35], 24], [[6, 1.33], [8, 3.0], [9, 18.89]]], ['city 5', [[24, 24, 28, 33, 23, 27, 27, 28, 27, 28, 34, 25], 28], [[8, 3.33], [9, 1.5]]], ['city 6', [[19, 21, 29, 18, 27, 22, 19, 19, 28, 27, 23, 16], 28], []], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []]], [['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []], ['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 9', [[15, 26, 16, 15, 23, 19, 19, 28, 28, 27, 26, 26], 26], [[7, 13.33], [8, 7.0], [9, 1.44]]], ['city 10', [[19, 26, 22, 22, 17, 20, 16, 17, 28, 25, 25, 24], 28], []], ['city 11', [[27, 28, 31, 19, 23, 21, 32, 31, 22, 23, 20, 22], 26], [[6, 8.17]]], ['city 12', [[27, 24, 26, 17, 20, 26, 23, 24, 20, 19, 26, 26], 26], []], ['city 13', [[19, 26, 25, 27, 20, 25, 22, 27, 19, 25, 24, 26], 26], []]], [['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 15', [[30, 27, 28, 21, 32, 33, 29, 31, 34, 31, 35, 28], 24], [[6, 20.78], [7, 29.33], [8, 40.44], [9, 9.78]]], ['city 16', [[26, 25, 22, 33, 23, 19, 25, 32, 22, 23, 23, 31], 26], [[6, 0.56]]], ['city 17', [[23, 21, 21, 21, 31, 19, 22, 25, 26, 27, 21, 20], 28], []], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 19', [[23, 21, 25, 18, 19, 19, 27, 27, 23, 18, 17, 21], 28], []], ['city 20', [[24, 26, 32, 29, 31, 24, 23, 23, 26, 24, 23, 18], 28], []]], [['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 21', [[35, 29, 27, 30, 30, 28, 29, 35, 22, 24, 24, 29], 24], [[6, 4.67], [7, 3.0], [9, 1.67]]], ['city 22', [[28, 23, 24, 20, 29, 28, 18, 28, 18, 26, 20, 18], 24], []], ['city 23', [[34, 34, 28, 22, 23, 27, 21, 21, 31, 24, 24, 23], 26], [[8, 0.89]]], ['city 24', [[32, 30, 18, 25, 18, 26, 28, 23, 31, 21, 25, 25], 28], []], ['city 25', [[28, 26, 30, 18, 22, 31, 20, 20, 24, 29, 29, 30], 26], [[8, 5.11], [9, 22.78]]], ['city 26', [[22, 27, 19, 25, 14, 26, 15, 25, 22, 25, 24, 18], 28], []], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]]], [['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]], ['city 29', [[27, 24, 26, 19, 17, 20, 28, 16, 17, 28, 21, 20], 28], []], ['cool acclimatised spell', [[30, 30, 30, 30, 30, 30, 27, 27, 27, 20], 26], [[6, 1.0]]], ['exact threshold', [[20, 20, 20, 20, 20, 20, 26, 26, 26, 22], 26], []], ['short record', [[25, 26, 27, 28, 29, 30, 31, 32], 25], []], ['record ends in extreme heat', [[22, 23, 22, 24, 23, 22, 25, 26, 38, 40], 26], [[6, 25.67], [7, 99.67]]]]]
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 |
|---|---|---|---|
| city 0 | [] | [[6, 4.89], [7, 1.67], [8, 15.5]] | Failed |
| city 1 | [] | [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]] | Failed |
| city 2 | [] | [[6, 4.44]] | Failed |
| city 3 | [] | [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]] | Failed |
| city 4 | [] | [[6, 1.33], [8, 3.0], [9, 18.89]] | Failed |
| city 5 | [] | [[8, 3.33], [9, 1.5]] | Failed |
| city 6 | [] | [] | Passed |
| city 7 | [] | [] | Passed |
SHA-256 / c47484d068ed7671e03ff7a223880925d76d8fe59940f051ff45e8146c91312e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(temps, t95):
res = []
for i in range(6, len(temps) - 2):
m3 = sum(temps[i:i + 3]) / 3.0
prior = sum(temps[i - 6:i]) / 6.0
sig = m3 - t95
accl = m3 - prior
ehf = sig * max(1.0, accl)
if ehf > 0:
res.append([i, round(ehf, 2)])
return res
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['city 0', [[22, 27, 20, 22, 21, 30, 25, 25, 32, 23, 32, 18], 26], [[6, 4.89], [7, 1.67], [8, 15.5]]], ['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 2', [[17, 29, 19, 30, 23, 20, 30, 26, 21, 18, 24, 18], 24], [[6, 4.44]]], ['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 4', [[22, 31, 30, 27, 29, 35, 31, 21, 24, 25, 32, 35], 24], [[6, 1.33], [8, 3.0], [9, 18.89]]], ['city 5', [[24, 24, 28, 33, 23, 27, 27, 28, 27, 28, 34, 25], 28], [[8, 3.33], [9, 1.5]]], ['city 6', [[19, 21, 29, 18, 27, 22, 19, 19, 28, 27, 23, 16], 28], []], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []]], [['city 3', [[28, 25, 35, 35, 25, 28, 31, 22, 27, 32, 22, 22], 24], [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]]], ['city 7', [[16, 27, 21, 22, 21, 19, 24, 21, 22, 24, 19, 29], 26], []], ['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 9', [[15, 26, 16, 15, 23, 19, 19, 28, 28, 27, 26, 26], 26], [[7, 13.33], [8, 7.0], [9, 1.44]]], ['city 10', [[19, 26, 22, 22, 17, 20, 16, 17, 28, 25, 25, 24], 28], []], ['city 11', [[27, 28, 31, 19, 23, 21, 32, 31, 22, 23, 20, 22], 26], [[6, 8.17]]], ['city 12', [[27, 24, 26, 17, 20, 26, 23, 24, 20, 19, 26, 26], 26], []], ['city 13', [[19, 26, 25, 27, 20, 25, 22, 27, 19, 25, 24, 26], 26], []]], [['city 8', [[32, 32, 34, 35, 29, 22, 30, 30, 24, 27, 28, 25], 24], [[6, 4.0], [7, 3.0], [8, 2.33], [9, 2.67]]], ['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 15', [[30, 27, 28, 21, 32, 33, 29, 31, 34, 31, 35, 28], 24], [[6, 20.78], [7, 29.33], [8, 40.44], [9, 9.78]]], ['city 16', [[26, 25, 22, 33, 23, 19, 25, 32, 22, 23, 23, 31], 26], [[6, 0.56]]], ['city 17', [[23, 21, 21, 21, 31, 19, 22, 25, 26, 27, 21, 20], 28], []], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 19', [[23, 21, 25, 18, 19, 19, 27, 27, 23, 18, 17, 21], 28], []], ['city 20', [[24, 26, 32, 29, 31, 24, 23, 23, 26, 24, 23, 18], 28], []]], [['city 14', [[35, 23, 27, 23, 34, 26, 24, 36, 35, 36, 25, 27], 24], [[6, 28.11], [7, 110.83], [8, 29.33], [9, 5.33]]], ['city 21', [[35, 29, 27, 30, 30, 28, 29, 35, 22, 24, 24, 29], 24], [[6, 4.67], [7, 3.0], [9, 1.67]]], ['city 22', [[28, 23, 24, 20, 29, 28, 18, 28, 18, 26, 20, 18], 24], []], ['city 23', [[34, 34, 28, 22, 23, 27, 21, 21, 31, 24, 24, 23], 26], [[8, 0.89]]], ['city 24', [[32, 30, 18, 25, 18, 26, 28, 23, 31, 21, 25, 25], 28], []], ['city 25', [[28, 26, 30, 18, 22, 31, 20, 20, 24, 29, 29, 30], 26], [[8, 5.11], [9, 22.78]]], ['city 26', [[22, 27, 19, 25, 14, 26, 15, 25, 22, 25, 24, 18], 28], []], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]]], [['city 1', [[23, 29, 24, 33, 35, 26, 25, 26, 33, 32, 21, 28], 24], [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]]], ['city 18', [[18, 21, 31, 27, 28, 30, 21, 28, 23, 31, 17, 27], 24], [[7, 3.33], [9, 1.0]]], ['city 28', [[23, 25, 34, 22, 30, 20, 28, 32, 31, 20, 33, 25], 24], [[6, 29.56], [7, 4.28], [8, 4.0], [9, 2.0]]], ['city 29', [[27, 24, 26, 19, 17, 20, 28, 16, 17, 28, 21, 20], 28], []], ['cool acclimatised spell', [[30, 30, 30, 30, 30, 30, 27, 27, 27, 20], 26], [[6, 1.0]]], ['exact threshold', [[20, 20, 20, 20, 20, 20, 26, 26, 26, 22], 26], []], ['short record', [[25, 26, 27, 28, 29, 30, 31, 32], 25], []], ['record ends in extreme heat', [[22, 23, 22, 24, 23, 22, 25, 26, 38, 40], 26], [[6, 25.67], [7, 99.67]]]]]
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 |
|---|---|---|---|
| city 0 | [[6, 4.89], [7, 1.67], [8, 15.5]] | [[6, 4.89], [7, 1.67], [8, 15.5]] | Passed |
| city 1 | [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]] | [[6, 4.0], [7, 10.56], [8, 4.67], [9, 3.0]] | Passed |
| city 2 | [[6, 4.44]] | [[6, 4.44]] | Passed |
| city 3 | [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]] | [[6, 2.67], [7, 3.0], [8, 3.0], [9, 1.33]] | Passed |
| city 4 | [[6, 1.33], [8, 3.0], [9, 18.89]] | [[6, 1.33], [8, 3.0], [9, 18.89]] | Passed |
| city 5 | [[8, 3.33], [9, 1.5]] | [[8, 3.33], [9, 1.5]] | Passed |
| city 6 | [] | [] | Passed |
| city 7 | [] | [] | Passed |
SHA-256 / 96add033b64dee092a4c8ab4bf71902bcafe90bac393cc355fd80f3c7c47eae6
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:28.501654+00:00.
Case digest / 561ff4459ab38e9be008b36a8a560e76242bf49ab8f37b8ba8b508b8c98a8fd8