FA-92371 / HVAC thermostat control / Open access
Stage-2 time upstage ignores how close the room is to setpoint · case 01
The second stage kicks in after ten minutes even when the room is within a few tenths of setpoint, overshooting.
ROOT CAUSE
The time-based upstage condition omits the temperature qualifier.
THE FAILURE
The time-based upstage condition omits the temperature qualifier.
Unsuccessful approach: Qualifying with temp < setpoint still upstages within the last half degree.
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 - 3 or not s1):
s2 = False
s2_off = minute
elif not s2 and s1 and (temp <= setpoint - 30 or (run1 > 10)):
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: scenario 27',
[700,
[678,
676,
674,
680,
681,
673,
681,
680,
680,
684,
689,
693,
699,
693,
695,
698,
690,
695,
688,
693,
698,
690,
698,
703]],
[[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],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[False, False]]],
['regression: scenario 36',
[700, [681, 681, 689, 682, 678, 685, 693, 687, 691, 695, 695, 694, 702, 707, 701, 707]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[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]]],
['control: 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: 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]]]],
[['regression: scenario 34',
[700, [690, 690, 690, 688, 693, 697, 698, 694, 696, 688, 695, 691, 687, 687, 684, 678, 674, 680, 680]],
[[True, 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]]],
['regression: scenario 39',
[700, [677, 677, 684, 690, 693, 687, 689, 689, 691, 694, 695, 701, 709, 710, 704, 709, 708, 706]],
[[True, False],
[True, False],
[True, False],
[True, False],
[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]]],
['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]]],
['control: 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: 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,
[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]]]],
[['regression: scenario 29',
[700, [694, 696, 695, 690, 689, 697, 697, 689, 687, 688, 692, 696, 694, 697, 703]],
[[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, False],
[False, False]]],
['regression: scenario 48',
[700,
[698,
693,
699,
698,
690,
698,
699,
695,
688,
689,
681,
681,
689,
688,
696,
702,
710,
710,
710,
710,
710,
710,
703,
705,
705,
702,
702,
710,
706,
698]],
[[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, 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]]],
['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]]],
['control: 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: 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 58',
[700,
[692,
687,
679,
674,
681,
675,
679,
687,
692,
694,
690,
696,
695,
700,
695,
692,
691,
687,
687,
682,
686,
680,
685,
692,
690]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, 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]]],
['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]]],
['control: 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: 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,
[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]]],
['control: scenario 2',
[700,
[665,
665,
663,
660,
657,
651,
650,
644,
639,
643,
637,
635,
628,
628,
636,
634,
634,
638,
645,
647,
654,
655,
659,
660,
657,
657]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[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 13',
[700,
[686,
678,
680,
680,
686,
686,
692,
695,
697,
696,
699,
697,
704,
710,
706,
709,
707,
709,
702,
707,
707,
709,
710,
710,
703,
702,
702]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[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],
[False, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 12',
[700,
[677,
675,
680,
674,
677,
682,
688,
683,
683,
691,
696,
700,
703,
696,
697,
696,
692,
690,
686,
678,
682,
686,
689,
685,
677,
672,
668,
671,
674]],
[[True, False],
[True, False],
[True, False],
[True, False],
[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],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[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]]],
['control: 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: 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: scenario 27 | [[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], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, True], [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, True], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, False], [True, False], [True, False], [False, False]] | Failed |
| regression: scenario 36 | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [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, False], [True, True], [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 |
| control: 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 |
| control: 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 |
SHA-256 / bcf04204496d598a0baaf1be56252150f9dd1ce469f573ed485efbd5213d2054
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)):
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: scenario 27',
[700,
[678,
676,
674,
680,
681,
673,
681,
680,
680,
684,
689,
693,
699,
693,
695,
698,
690,
695,
688,
693,
698,
690,
698,
703]],
[[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],
[True, False],
[True, False],
[True, False],
[True, True],
[True, True],
[True, True],
[True, True],
[True, False],
[True, False],
[True, False],
[False, False]]],
['regression: scenario 36',
[700, [681, 681, 689, 682, 678, 685, 693, 687, 691, 695, 695, 694, 702, 707, 701, 707]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, True],
[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]]],
['control: 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: 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]]]],
[['regression: scenario 34',
[700, [690, 690, 690, 688, 693, 697, 698, 694, 696, 688, 695, 691, 687, 687, 684, 678, 674, 680, 680]],
[[True, 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]]],
['regression: scenario 39',
[700, [677, 677, 684, 690, 693, 687, 689, 689, 691, 694, 695, 701, 709, 710, 704, 709, 708, 706]],
[[True, False],
[True, False],
[True, False],
[True, False],
[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]]],
['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]]],
['control: 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: 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,
[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]]]],
[['regression: scenario 29',
[700, [694, 696, 695, 690, 689, 697, 697, 689, 687, 688, 692, 696, 694, 697, 703]],
[[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, False],
[False, False]]],
['regression: scenario 48',
[700,
[698,
693,
699,
698,
690,
698,
699,
695,
688,
689,
681,
681,
689,
688,
696,
702,
710,
710,
710,
710,
710,
710,
703,
705,
705,
702,
702,
710,
706,
698]],
[[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, 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]]],
['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]]],
['control: 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: 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 58',
[700,
[692,
687,
679,
674,
681,
675,
679,
687,
692,
694,
690,
696,
695,
700,
695,
692,
691,
687,
687,
682,
686,
680,
685,
692,
690]],
[[False, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, 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]]],
['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]]],
['control: 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: 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,
[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]]],
['control: scenario 2',
[700,
[665,
665,
663,
660,
657,
651,
650,
644,
639,
643,
637,
635,
628,
628,
636,
634,
634,
638,
645,
647,
654,
655,
659,
660,
657,
657]],
[[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[True, True],
[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 13',
[700,
[686,
678,
680,
680,
686,
686,
692,
695,
697,
696,
699,
697,
704,
710,
706,
709,
707,
709,
702,
707,
707,
709,
710,
710,
703,
702,
702]],
[[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[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],
[False, False],
[False, False],
[False, False],
[False, False]]],
['regression: scenario 12',
[700,
[677,
675,
680,
674,
677,
682,
688,
683,
683,
691,
696,
700,
703,
696,
697,
696,
692,
690,
686,
678,
682,
686,
689,
685,
677,
672,
668,
671,
674]],
[[True, False],
[True, False],
[True, False],
[True, False],
[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],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[True, False],
[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]]],
['control: 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: 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: scenario 27 | [[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], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, True], [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, True], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [True, True], [True, True], [True, False], [True, False], [True, False], [False, False]] | Failed |
| regression: scenario 36 | [[True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, False], [True, True], [True, True], [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, False], [True, True], [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 |
| control: 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 |
| control: 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 |
SHA-256 / 36592134f90e6e4d4dc68f6b6e99c74bc80a718492f23fbed9480553a2f89a70
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.133380+00:00.
Case digest / 097398175b0c4839554e670e1b2e05aebbe437c18502353b092ca803bb93f6f4