FA-92511 / HVAC thermostat control / Open access
Celsius press moves a whole degree Celsius · case 01
Each arrow press in C mode jumps 1 C (1.8 F) instead of 0.5 C.
ROOT CAUSE
The stored value is rebuilt with 18 tenths F per half-degree step.
VERIFIED REPAIR
One half-degree C is exactly 9 tenths F.
Unsuccessful approach: Adding 9 tenths to the raw stored value keeps off-grid values off the 0.5 C grid.
Case contract
Thermostat setpoint keypad. The setpoint is stored in tenths F. In C mode the display shows the stored value converted to C and rounded half up to 0.5 C; a press moves the displayed value by 0.5 C and stores exactly 320 + half_degrees*9 tenths F. In F mode the display rounds half up to whole F and a press moves the whole-degree value by 1 F. After each press the stored value is clamped to 45.0-90.0 F. Return [display, stored_tenths_F] per press.
Why this case matters
Residential and light-commercial thermostats make these decisions sample by sample; each defect changes equipment calls in a way that shows up as short cycling, comfort complaints or equipment stress.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(unit, presses, start_f10):
f10 = start_f10
out = []
for p in presses:
step = 1 if p == 'up' else -1
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
f10 = 320 + (c_half + step) * 18
else:
f_whole = (f10 + 5) // 10
f10 = (f_whole + step) * 10
f10 = max(450, min(900, f10))
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])
else:
out.append([str((f10 + 5) // 10), f10])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],
[['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],
['regression: scenario 2',
['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],
[['21.5', 707],
['21.0', 698],
['20.5', 689],
['21.0', 698],
['20.5', 689],
['20.0', 680],
['20.5', 689]]]],
[['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],
[['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],
['control: scenario 2',
['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],
[['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],
[['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: scenario 7',
['C', ['up', 'down', 'up', 'up'], 905],
[['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 1',
['C', ['up', 'up', 'down', 'up', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],
[['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 6',
['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],
[['32.0', 900],
['32.0', 900],
['31.5', 887],
['31.0', 878],
['30.5', 869],
['30.0', 860],
['29.5', 851],
['29.0', 842]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: scenario 1',
['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],
[['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],
[['regression: scenario 3',
['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],
['regression: scenario 10',
['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],
[['15.0', 590],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['13.5', 563],
['13.0', 554]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]
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 |
|---|---|---|---|
| regression: celsius steps | [['32.0', 900], ['32.0', 900], ['32.0', 900]] | [['22.5', 725], ['23.0', 734], ['22.5', 725]] | Failed |
| regression: celsius lower clamp | [['14.0', 572], ['27.0', 806], ['32.0', 900]] | [['7.0', 450], ['7.0', 450], ['7.5', 455]] | Failed |
| control: fahrenheit half value | [['74', 740], ['73', 730], ['72', 720]] | [['74', 740], ['73', 730], ['72', 720]] | Passed |
| control: upper clamp | [['90', 900]] | [['90', 900]] | Passed |
| regression: celsius off-grid start | [['32.0', 900], ['32.0', 900]] | [['21.5', 707], ['22.0', 716]] | Failed |
| regression: celsius half-step display | [['32.0', 900]] | [['22.0', 716]] | Failed |
| control: scenario 1 | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | Passed |
| regression: scenario 2 | [['32.0', 900], ['32.0', 900], ['32.0', 900], ['32.0', 900], ['32.0', 900], ['32.0', 900], ['32.0', 900]] | [['21.5', 707], ['21.0', 698], ['20.5', 689], ['21.0', 698], ['20.5', 689], ['20.0', 680], ['20.5', 689]] | Failed |
SHA-256 / 4ac10f6f38bdb3bf542b028e94081be48378900aaaaaa928f954ca1b399d9e2b
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(unit, presses, start_f10):
f10 = start_f10
out = []
for p in presses:
step = 1 if p == 'up' else -1
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
f10 = f10 + step * 9
else:
f_whole = (f10 + 5) // 10
f10 = (f_whole + step) * 10
f10 = max(450, min(900, f10))
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])
else:
out.append([str((f10 + 5) // 10), f10])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],
[['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],
['regression: scenario 2',
['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],
[['21.5', 707],
['21.0', 698],
['20.5', 689],
['21.0', 698],
['20.5', 689],
['20.0', 680],
['20.5', 689]]]],
[['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],
[['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],
['control: scenario 2',
['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],
[['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],
[['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: scenario 7',
['C', ['up', 'down', 'up', 'up'], 905],
[['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 1',
['C', ['up', 'up', 'down', 'up', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],
[['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 6',
['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],
[['32.0', 900],
['32.0', 900],
['31.5', 887],
['31.0', 878],
['30.5', 869],
['30.0', 860],
['29.5', 851],
['29.0', 842]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: scenario 1',
['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],
[['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],
[['regression: scenario 3',
['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],
['regression: scenario 10',
['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],
[['15.0', 590],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['13.5', 563],
['13.0', 554]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]
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 |
|---|---|---|---|
| regression: celsius steps | [['22.5', 729], ['23.0', 738], ['22.5', 729]] | [['22.5', 725], ['23.0', 734], ['22.5', 725]] | Failed |
| regression: celsius lower clamp | [['7.0', 450], ['7.0', 450], ['7.5', 459]] | [['7.0', 450], ['7.0', 450], ['7.5', 455]] | Failed |
| control: fahrenheit half value | [['74', 740], ['73', 730], ['72', 720]] | [['74', 740], ['73', 730], ['72', 720]] | Passed |
| control: upper clamp | [['90', 900]] | [['90', 900]] | Passed |
| regression: celsius off-grid start | [['21.5', 707], ['22.0', 716]] | [['21.5', 707], ['22.0', 716]] | Passed |
| regression: celsius half-step display | [['22.0', 716]] | [['22.0', 716]] | Passed |
| control: scenario 1 | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | Passed |
| regression: scenario 2 | [['21.5', 707], ['21.0', 698], ['20.5', 689], ['21.0', 698], ['20.5', 689], ['20.0', 680], ['20.5', 689]] | [['21.5', 707], ['21.0', 698], ['20.5', 689], ['21.0', 698], ['20.5', 689], ['20.0', 680], ['20.5', 689]] | Passed |
SHA-256 / a06f25df3b7162cb65189ce604a5d77b959821a2275b6e8ed511a0d0c15f92cf
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(unit, presses, start_f10):
f10 = start_f10
out = []
for p in presses:
step = 1 if p == 'up' else -1
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
f10 = 320 + (c_half + step) * 9
else:
f_whole = (f10 + 5) // 10
f10 = (f_whole + step) * 10
f10 = max(450, min(900, f10))
if unit == 'C':
c_half = (2 * (f10 - 320) + 9) // 18
out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])
else:
out.append([str((f10 + 5) // 10), f10])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],
[['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],
['regression: scenario 2',
['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],
[['21.5', 707],
['21.0', 698],
['20.5', 689],
['21.0', 698],
['20.5', 689],
['20.0', 680],
['20.5', 689]]]],
[['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['control: scenario 1',
['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],
[['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],
['control: scenario 2',
['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],
[['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],
[['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: scenario 7',
['C', ['up', 'down', 'up', 'up'], 905],
[['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 1',
['C', ['up', 'up', 'down', 'up', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],
[['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],
['regression: scenario 6',
['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],
[['32.0', 900],
['32.0', 900],
['31.5', 887],
['31.0', 878],
['30.5', 869],
['30.0', 860],
['29.5', 851],
['29.0', 842]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['control: scenario 1',
['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],
[['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],
[['regression: scenario 3',
['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],
[['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],
['regression: scenario 10',
['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],
[['15.0', 590],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['14.5', 581],
['14.0', 572],
['13.5', 563],
['13.0', 554]]],
['regression: celsius steps',
['C', ['up', 'up', 'down'], 720],
[['22.5', 725], ['23.0', 734], ['22.5', 725]]],
['control: fahrenheit half value',
['F', ['up', 'down', 'down'], 725],
[['74', 740], ['73', 730], ['72', 720]]],
['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],
['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],
['regression: celsius lower clamp',
['C', ['down', 'down', 'up'], 452],
[['7.0', 450], ['7.0', 450], ['7.5', 455]]],
['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]
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 |
|---|---|---|---|
| regression: celsius steps | [['22.5', 725], ['23.0', 734], ['22.5', 725]] | [['22.5', 725], ['23.0', 734], ['22.5', 725]] | Passed |
| regression: celsius lower clamp | [['7.0', 450], ['7.0', 450], ['7.5', 455]] | [['7.0', 450], ['7.0', 450], ['7.5', 455]] | Passed |
| control: fahrenheit half value | [['74', 740], ['73', 730], ['72', 720]] | [['74', 740], ['73', 730], ['72', 720]] | Passed |
| control: upper clamp | [['90', 900]] | [['90', 900]] | Passed |
| regression: celsius off-grid start | [['21.5', 707], ['22.0', 716]] | [['21.5', 707], ['22.0', 716]] | Passed |
| regression: celsius half-step display | [['22.0', 716]] | [['22.0', 716]] | Passed |
| control: scenario 1 | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]] | Passed |
| regression: scenario 2 | [['21.5', 707], ['21.0', 698], ['20.5', 689], ['21.0', 698], ['20.5', 689], ['20.0', 680], ['20.5', 689]] | [['21.5', 707], ['21.0', 698], ['20.5', 689], ['21.0', 698], ['20.5', 689], ['20.0', 680], ['20.5', 689]] | Passed |
SHA-256 / 502c9ca86a044c6e2f0611442f1fedcd24747d9864d7033126236ef4a585d679
Verification & scope
A deterministic bounded teaching model of one thermostat or HVAC controller decision evaluated per sample. Temperatures are integer tenths of a degree Fahrenheit unless stated otherwise. The contract is a stipulated toy convention, not a claim of conformance to any manufacturer, ASHRAE guideline or code. 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:51:46.455042+00:00.
Case digest / 519a6169ee57ded5cb5c71c497363215d2cf18e8833c7b44e83d8abe880947ac