FA-92376 / HVAC thermostat control / Open access
Stage 2 stays on until the heating setpoint is reached · case 01
High fire runs all the way to setpoint and the room overshoots on every recovery.
ROOT CAUSE
The stage-2 end test uses setpoint instead of setpoint - 0.3 F.
THE FAILURE
The stage-2 end test uses setpoint instead of setpoint - 0.3 F.
Unsuccessful approach: Using a strict comparison keeps stage 2 on for one extra sample at the threshold.
Case contract
Two-stage furnace thermostat sampled per minute. Stage 1 starts at temp <= setpoint - 1.0 F and ends at temp >= setpoint. Stage 2 requires stage 1 and starts either on droop (temp <= setpoint - 3.0 F) or after stage 1 has been on for more than 10 samples of the current cycle while still below setpoint - 0.5 F; it ends at temp >= setpoint - 0.3 F or when stage 1 ends, and cannot restart within 3 minutes of ending. Return [stage1, stage2] per minute.
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(setpoint, temps):
s1 = False
s2 = False
run1 = 0
s2_off = None
out = []
for minute, temp in enumerate(temps):
if s1 and temp >= setpoint:
s1 = False
elif not s1 and temp <= setpoint - 10:
s1 = True
run1 = 0
if s1:
run1 += 1
if s2 and (temp >= setpoint or not s1):
s2 = False
s2_off = minute
elif not s2 and s1 and (temp <= setpoint - 30 or (run1 > 10 and temp < setpoint - 5)):
if s2_off is None or minute - s2_off >= 3:
s2 = True
out.append([s1, s2])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: scenario 7',
[700,
[680,
679,
676,
682,
683,
680,
688,
686,
692,
688,
692,
697,
696,
688,
693,
697,
702,
696,
703,
699,
706,
703,
703,
696]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700,
[668,
676,
684,
689,
688,
685,
691,
686,
690,
688,
696,
688,
691,
693,
690,
693,
693,
686,
679,
685,
678,
682,
677,
685,
679,
675,
682,
688,
696]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: scenario 2',
[700, [650, 652, 648, 644, 640, 637, 645, 650, 657, 654, 651, 644, 643, 651, 645, 643, 635]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]]],
[['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['regression: scenario 36',
[700,
[661,
668,
666,
671,
674,
671,
678,
679,
687,
691,
697,
692,
693,
692,
687,
684,
688,
688,
689,
697,
694,
689,
681,
686,
678,
683,
685,
686,
689]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['control: scenario 1',
[700,
[664,
664,
656,
661,
657,
652,
647,
647,
642,
647,
646,
644,
642,
634,
634,
637,
640,
644,
650,
643,
640,
640]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: scenario 2',
[700, [678, 683, 689, 697, 705, 705, 710, 705, 704, 709, 701, 709, 710, 710, 704, 696, 702, 705, 709]],
[[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]],
[['regression: scenario 5',
[700,
[686,
687,
692,
699,
698,
690,
685,
690,
684,
690,
689,
686,
692,
696,
695,
693,
699,
703,
705,
710,
708]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 18',
[700,
[665,
658,
660,
666,
672,
679,
685,
679,
687,
689,
695,
693,
685,
690,
698,
694,
697,
690,
691,
690,
697,
701,
702,
700]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700,
[697,
690,
685,
682,
687,
690,
693,
687,
689,
697,
689,
685,
680,
679,
671,
675,
680,
675,
676,
678,
673,
668,
663,
662,
665,
662,
661,
669,
666,
665]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]]],
[['regression: scenario 9',
[700,
[685,
682,
690,
695,
703,
708,
700,
692,
693,
689,
684,
677,
671,
677,
684,
677,
676,
684,
683,
682,
679,
683,
687,
691,
692,
699,
704,
702,
708]],
[[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 39',
[700,
[691,
692,
691,
685,
683,
676,
671,
679,
684,
677,
685,
693,
689,
693,
694,
697,
705,
697,
693,
688,
690,
686,
681,
686,
684,
683]],
[[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['regression: scenario 1',
[700,
[682,
679,
685,
683,
680,
678,
684,
682,
681,
688,
693,
698,
702,
710,
710,
710,
708,
701,
694,
696,
693]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]],
[['regression: scenario 53',
[700,
[679,
683,
681,
682,
687,
684,
677,
674,
681,
673,
666,
670,
671,
670,
665,
657,
665,
671,
677,
683,
690,
691,
697]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False]]],
['regression: scenario 46',
[700,
[674,
678,
684,
683,
687,
691,
685,
683,
683,
676,
672,
677,
676,
682,
690,
697,
689,
693,
696,
703,
698,
698,
698,
703,
697,
697,
691,
688,
691]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700, [690, 685, 681, 689, 689, 687, 693, 701, 709, 709, 706, 703, 698, 694, 697, 699, 700, 702]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]]]
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: stage two cycling | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [False, False]] | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [False, False]] | Failed |
| regression: scenario 7 | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, False], [True, False], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False]] | Failed |
| control: slow recovery upstages on time | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [False, False]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [False, False]] | Passed |
| control: second cycle after short first | [[True, False], [True, False], [True, False], [True, False], [True, False], [False, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [False, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True]] | Passed |
| control: droop recovery above upstage exit | [[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]] | Passed |
| regression: stage two cycling late | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]] | Failed |
| control: scenario 1 | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | Passed |
| control: scenario 2 | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | Passed |
SHA-256 / cb5795736a49b156d4ce9b1e35bc140fc5c90242d17c642a19befcdb6d1bd2f7
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(setpoint, temps):
s1 = False
s2 = False
run1 = 0
s2_off = None
out = []
for minute, temp in enumerate(temps):
if s1 and temp >= setpoint:
s1 = False
elif not s1 and temp <= setpoint - 10:
s1 = True
run1 = 0
if s1:
run1 += 1
if s2 and (temp > setpoint - 3 or not s1):
s2 = False
s2_off = minute
elif not s2 and s1 and (temp <= setpoint - 30 or (run1 > 10 and temp < setpoint - 5)):
if s2_off is None or minute - s2_off >= 3:
s2 = True
out.append([s1, s2])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: scenario 7',
[700,
[680,
679,
676,
682,
683,
680,
688,
686,
692,
688,
692,
697,
696,
688,
693,
697,
702,
696,
703,
699,
706,
703,
703,
696]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700,
[668,
676,
684,
689,
688,
685,
691,
686,
690,
688,
696,
688,
691,
693,
690,
693,
693,
686,
679,
685,
678,
682,
677,
685,
679,
675,
682,
688,
696]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: scenario 2',
[700, [650, 652, 648, 644, 640, 637, 645, 650, 657, 654, 651, 644, 643, 651, 645, 643, 635]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]]],
[['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['regression: scenario 36',
[700,
[661,
668,
666,
671,
674,
671,
678,
679,
687,
691,
697,
692,
693,
692,
687,
684,
688,
688,
689,
697,
694,
689,
681,
686,
678,
683,
685,
686,
689]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['control: scenario 1',
[700,
[664,
664,
656,
661,
657,
652,
647,
647,
642,
647,
646,
644,
642,
634,
634,
637,
640,
644,
650,
643,
640,
640]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]],
['control: scenario 2',
[700, [678, 683, 689, 697, 705, 705, 710, 705, 704, 709, 701, 709, 710, 710, 704, 696, 702, 705, 709]],
[[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]],
[['regression: scenario 5',
[700,
[686,
687,
692,
699,
698,
690,
685,
690,
684,
690,
689,
686,
692,
696,
695,
693,
699,
703,
705,
710,
708]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 18',
[700,
[665,
658,
660,
666,
672,
679,
685,
679,
687,
689,
695,
693,
685,
690,
698,
694,
697,
690,
691,
690,
697,
701,
702,
700]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700,
[697,
690,
685,
682,
687,
690,
693,
687,
689,
697,
689,
685,
680,
679,
671,
675,
680,
675,
676,
678,
673,
668,
663,
662,
665,
662,
661,
669,
666,
665]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True]]]],
[['regression: scenario 9',
[700,
[685,
682,
690,
695,
703,
708,
700,
692,
693,
689,
684,
677,
671,
677,
684,
677,
676,
684,
683,
682,
679,
683,
687,
691,
692,
699,
704,
702,
708]],
[[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 39',
[700,
[691,
692,
691,
685,
683,
676,
671,
679,
684,
677,
685,
693,
689,
693,
694,
697,
705,
697,
693,
688,
690,
686,
681,
686,
684,
683]],
[[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['regression: scenario 1',
[700,
[682,
679,
685,
683,
680,
678,
684,
682,
681,
688,
693,
698,
702,
710,
710,
710,
708,
701,
694,
696,
693]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]],
[['regression: scenario 53',
[700,
[679,
683,
681,
682,
687,
684,
677,
674,
681,
673,
666,
670,
671,
670,
665,
657,
665,
671,
677,
683,
690,
691,
697]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False]]],
['regression: scenario 46',
[700,
[674,
678,
684,
683,
687,
691,
685,
683,
683,
676,
672,
677,
676,
682,
690,
697,
689,
693,
696,
703,
698,
698,
698,
703,
697,
697,
691,
688,
691]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[True, False],
[True, False]]],
['control: slow recovery upstages on time',
[700, [690, 691, 692, 692, 693, 693, 694, 694, 694, 694, 694, 694, 695, 696, 700]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[False, False]]],
['control: second cycle after short first',
[700, [690, 692, 694, 696, 698, 700, 690, 692, 694, 694, 694, 694, 694, 694, 694, 694, 694]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True]]],
['control: droop recovery above upstage exit',
[700, [665, 675, 685, 693, 696, 700]],
[[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]]],
['regression: stage two cycling',
[700, [665, 698, 668, 668, 668, 668, 699, 700]],
[[True, True],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, False],
[False, False]]],
['regression: stage two cycling late',
[700, [669, 698, 669, 669, 666, 669, 669]],
[[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]]],
['control: scenario 1',
[700, [690, 685, 681, 689, 689, 687, 693, 701, 709, 709, 706, 703, 698, 694, 697, 699, 700, 702]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False],
[False, False]]]]]
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: stage two cycling | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [False, False]] | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, False], [False, False]] | Passed |
| regression: scenario 7 | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, False], [True, False], [True, False], [True, True], [True, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False], [False, False]] | Failed |
| control: slow recovery upstages on time | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [False, False]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [False, False]] | Passed |
| control: second cycle after short first | [[True, False], [True, False], [True, False], [True, False], [True, False], [False, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True]] | [[True, False], [True, False], [True, False], [True, False], [True, False], [False, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True]] | Passed |
| control: droop recovery above upstage exit | [[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [False, False]] | Passed |
| regression: stage two cycling late | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]] | [[True, True], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True]] | Passed |
| control: scenario 1 | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | Passed |
| control: scenario 2 | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | [[True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True], [True, True]] | Passed |
SHA-256 / ad3297915f3b900717926cd175c39e61c909923db018cbadc6e41756d2fd422e
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
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:45.136394+00:00.
Case digest / dd002d99ae12a95976381bf2d6d2da90558c0ddbea7e7eb490ac8478dea60da1