{"abstract":"Each arrow press in C mode jumps 1 C (1.8 F) instead of 0.5 C.","category":"HVAC thermostat control","checks":8,"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.","evaluation_group":"w2-hvac-thermostat-control-setpoint-keypad-units","failed_approach":"Adding 9 tenths to the raw stored value keeps off-grid values off the 0.5 C grid.","family":"w2-hvac-thermostat-control-setpoint-keypad-units-half-degree-increment","id":"FA-92511","implementations":{"attempt":{"sha256":"a06f25df3b7162cb65189ce604a5d77b959821a2275b6e8ed511a0d0c15f92cf","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(unit, presses, start_f10):\n    f10 = start_f10\n    out = []\n    for p in presses:\n        step = 1 if p == 'up' else -1\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            f10 = f10 + step * 9\n        else:\n            f_whole = (f10 + 5) // 10\n            f10 = (f_whole + step) * 10\n        f10 = max(450, min(900, f10))\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])\n        else:\n            out.append([str((f10 + 5) // 10), f10])\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],\n   [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],\n  ['regression: scenario 2',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],\n   [['21.5', 707],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['20.0', 680],\n    ['20.5', 689]]]],\n [['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],\n   [['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],\n  ['control: scenario 2',\n   ['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],\n   [['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],\n [['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: scenario 7',\n   ['C', ['up', 'down', 'up', 'up'], 905],\n   [['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 1',\n   ['C', ['up', 'up', 'down', 'up', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],\n [['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 6',\n   ['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],\n   [['32.0', 900],\n    ['32.0', 900],\n    ['31.5', 887],\n    ['31.0', 878],\n    ['30.5', 869],\n    ['30.0', 860],\n    ['29.5', 851],\n    ['29.0', 842]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: scenario 1',\n   ['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],\n   [['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],\n [['regression: scenario 3',\n   ['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],\n  ['regression: scenario 10',\n   ['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],\n   [['15.0', 590],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['13.5', 563],\n    ['13.0', 554]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"4ac10f6f38bdb3bf542b028e94081be48378900aaaaaa928f954ca1b399d9e2b","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(unit, presses, start_f10):\n    f10 = start_f10\n    out = []\n    for p in presses:\n        step = 1 if p == 'up' else -1\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            f10 = 320 + (c_half + step) * 18\n        else:\n            f_whole = (f10 + 5) // 10\n            f10 = (f_whole + step) * 10\n        f10 = max(450, min(900, f10))\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])\n        else:\n            out.append([str((f10 + 5) // 10), f10])\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],\n   [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],\n  ['regression: scenario 2',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],\n   [['21.5', 707],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['20.0', 680],\n    ['20.5', 689]]]],\n [['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],\n   [['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],\n  ['control: scenario 2',\n   ['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],\n   [['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],\n [['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: scenario 7',\n   ['C', ['up', 'down', 'up', 'up'], 905],\n   [['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 1',\n   ['C', ['up', 'up', 'down', 'up', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],\n [['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 6',\n   ['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],\n   [['32.0', 900],\n    ['32.0', 900],\n    ['31.5', 887],\n    ['31.0', 878],\n    ['30.5', 869],\n    ['30.0', 860],\n    ['29.5', 851],\n    ['29.0', 842]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: scenario 1',\n   ['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],\n   [['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],\n [['regression: scenario 3',\n   ['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],\n  ['regression: scenario 10',\n   ['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],\n   [['15.0', 590],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['13.5', 563],\n    ['13.0', 554]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"fixed":{"sha256":"502c9ca86a044c6e2f0611442f1fedcd24747d9864d7033126236ef4a585d679","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(unit, presses, start_f10):\n    f10 = start_f10\n    out = []\n    for p in presses:\n        step = 1 if p == 'up' else -1\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            f10 = 320 + (c_half + step) * 9\n        else:\n            f_whole = (f10 + 5) // 10\n            f10 = (f_whole + step) * 10\n        f10 = max(450, min(900, f10))\n        if unit == 'C':\n            c_half = (2 * (f10 - 320) + 9) // 18\n            out.append(['%d.%d' % (c_half // 2, 5 * (c_half % 2)), f10])\n        else:\n            out.append([str((f10 + 5) // 10), f10])\n    return out\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'up', 'down', 'down', 'up'], 716],\n   [['71', 710], ['70', 700], ['71', 710], ['72', 720], ['73', 730], ['72', 720], ['71', 710], ['72', 720]]],\n  ['regression: scenario 2',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down', 'up'], 716],\n   [['21.5', 707],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['21.0', 698],\n    ['20.5', 689],\n    ['20.0', 680],\n    ['20.5', 689]]]],\n [['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['control: scenario 1',\n   ['F', ['down', 'down', 'up', 'up', 'down', 'down', 'down', 'up'], 652],\n   [['64', 640], ['63', 630], ['64', 640], ['65', 650], ['64', 640], ['63', 630], ['62', 620], ['63', 630]]],\n  ['control: scenario 2',\n   ['F', ['down', 'down', 'up', 'down', 'up', 'down', 'up', 'up'], 725],\n   [['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['71', 710], ['72', 720], ['73', 730]]]],\n [['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: scenario 7',\n   ['C', ['up', 'down', 'up', 'up'], 905],\n   [['32.0', 900], ['31.5', 887], ['32.0', 896], ['32.0', 900]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 1',\n   ['C', ['up', 'up', 'down', 'up', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['22.5', 725], ['22.0', 716]]]],\n [['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\n  ['regression: scenario 6',\n   ['C', ['up', 'up', 'down', 'down', 'down', 'down', 'down', 'down'], 905],\n   [['32.0', 900],\n    ['32.0', 900],\n    ['31.5', 887],\n    ['31.0', 878],\n    ['30.5', 869],\n    ['30.0', 860],\n    ['29.5', 851],\n    ['29.0', 842]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['control: scenario 1',\n   ['F', ['down', 'up', 'up', 'down', 'up', 'up', 'down', 'down'], 716],\n   [['71', 710], ['72', 720], ['73', 730], ['72', 720], ['73', 730], ['74', 740], ['73', 730], ['72', 720]]]],\n [['regression: scenario 3',\n   ['C', ['up', 'up', 'down', 'down', 'up', 'down', 'down'], 707],\n   [['22.0', 716], ['22.5', 725], ['22.0', 716], ['21.5', 707], ['22.0', 716], ['21.5', 707], ['21.0', 698]]],\n  ['regression: scenario 10',\n   ['C', ['up', 'down', 'down', 'up', 'down', 'up', 'down', 'down', 'down'], 577],\n   [['15.0', 590],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['14.5', 581],\n    ['14.0', 572],\n    ['13.5', 563],\n    ['13.0', 554]]],\n  ['regression: celsius steps',\n   ['C', ['up', 'up', 'down'], 720],\n   [['22.5', 725], ['23.0', 734], ['22.5', 725]]],\n  ['control: fahrenheit half value',\n   ['F', ['up', 'down', 'down'], 725],\n   [['74', 740], ['73', 730], ['72', 720]]],\n  ['control: upper clamp', ['F', ['up'], 895], [['90', 900]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\n  ['regression: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]]]]\nfor label, args, expected in fixtures[N-1]:\n    check(label, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-hvac-thermostat-control-setpoint-keypad-units-half-degree-increment","generated_at":"2026-09-29T14:51:46.455042+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"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.","repair":"One half-degree C is exactly 9 tenths F.","root_cause":"The stored value is rebuilt with 18 tenths F per half-degree step.","sha256":"519a6169ee57ded5cb5c71c497363215d2cf18e8833c7b44e83d8abe880947ac","title":"Celsius press moves a whole degree Celsius · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":41.773,"exit_code":1,"observations":[{"actual":[["22.5",729],["23.0",738],["22.5",729]],"check":"regression: celsius steps","expected":[["22.5",725],["23.0",734],["22.5",725]],"passed":false},{"actual":[["7.0",450],["7.0",450],["7.5",459]],"check":"regression: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"passed":false},{"actual":[["74",740],["73",730],["72",720]],"check":"control: fahrenheit half value","expected":[["74",740],["73",730],["72",720]],"passed":true},{"actual":[["90",900]],"check":"control: upper clamp","expected":[["90",900]],"passed":true},{"actual":[["21.5",707],["22.0",716]],"check":"regression: celsius off-grid start","expected":[["21.5",707],["22.0",716]],"passed":true},{"actual":[["22.0",716]],"check":"regression: celsius half-step display","expected":[["22.0",716]],"passed":true},{"actual":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"check":"control: scenario 1","expected":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"passed":true},{"actual":[["21.5",707],["21.0",698],["20.5",689],["21.0",698],["20.5",689],["20.0",680],["20.5",689]],"check":"regression: scenario 2","expected":[["21.5",707],["21.0",698],["20.5",689],["21.0",698],["20.5",689],["20.0",680],["20.5",689]],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: celsius steps\", \"actual\": [[\"22.5\", 729], [\"23.0\", 738], [\"22.5\", 729]], \"expected\": [[\"22.5\", 725], [\"23.0\", 734], [\"22.5\", 725]], \"passed\": false}, {\"check\": \"regression: celsius lower clamp\", \"actual\": [[\"7.0\", 450], [\"7.0\", 450], [\"7.5\", 459]], \"expected\": [[\"7.0\", 450], [\"7.0\", 450], [\"7.5\", 455]], \"passed\": false}, {\"check\": \"control: fahrenheit half value\", \"actual\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"expected\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"passed\": true}, {\"check\": \"control: upper clamp\", \"actual\": [[\"90\", 900]], \"expected\": [[\"90\", 900]], \"passed\": true}, {\"check\": \"regression: celsius off-grid start\", \"actual\": [[\"21.5\", 707], [\"22.0\", 716]], \"expected\": [[\"21.5\", 707], [\"22.0\", 716]], \"passed\": true}, {\"check\": \"regression: celsius half-step display\", \"actual\": [[\"22.0\", 716]], \"expected\": [[\"22.0\", 716]], \"passed\": true}, {\"check\": \"control: scenario 1\", \"actual\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"expected\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"passed\": true}, {\"check\": \"regression: scenario 2\", \"actual\": [[\"21.5\", 707], [\"21.0\", 698], [\"20.5\", 689], [\"21.0\", 698], [\"20.5\", 689], [\"20.0\", 680], [\"20.5\", 689]], \"expected\": [[\"21.5\", 707], [\"21.0\", 698], [\"20.5\", 689], [\"21.0\", 698], [\"20.5\", 689], [\"20.0\", 680], [\"20.5\", 689]], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":42.394,"exit_code":1,"observations":[{"actual":[["32.0",900],["32.0",900],["32.0",900]],"check":"regression: celsius steps","expected":[["22.5",725],["23.0",734],["22.5",725]],"passed":false},{"actual":[["14.0",572],["27.0",806],["32.0",900]],"check":"regression: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"passed":false},{"actual":[["74",740],["73",730],["72",720]],"check":"control: fahrenheit half value","expected":[["74",740],["73",730],["72",720]],"passed":true},{"actual":[["90",900]],"check":"control: upper clamp","expected":[["90",900]],"passed":true},{"actual":[["32.0",900],["32.0",900]],"check":"regression: celsius off-grid start","expected":[["21.5",707],["22.0",716]],"passed":false},{"actual":[["32.0",900]],"check":"regression: celsius half-step display","expected":[["22.0",716]],"passed":false},{"actual":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"check":"control: scenario 1","expected":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"passed":true},{"actual":[["32.0",900],["32.0",900],["32.0",900],["32.0",900],["32.0",900],["32.0",900],["32.0",900]],"check":"regression: scenario 2","expected":[["21.5",707],["21.0",698],["20.5",689],["21.0",698],["20.5",689],["20.0",680],["20.5",689]],"passed":false}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: celsius steps\", \"actual\": [[\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900]], \"expected\": [[\"22.5\", 725], [\"23.0\", 734], [\"22.5\", 725]], \"passed\": false}, {\"check\": \"regression: celsius lower clamp\", \"actual\": [[\"14.0\", 572], [\"27.0\", 806], [\"32.0\", 900]], \"expected\": [[\"7.0\", 450], [\"7.0\", 450], [\"7.5\", 455]], \"passed\": false}, {\"check\": \"control: fahrenheit half value\", \"actual\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"expected\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"passed\": true}, {\"check\": \"control: upper clamp\", \"actual\": [[\"90\", 900]], \"expected\": [[\"90\", 900]], \"passed\": true}, {\"check\": \"regression: celsius off-grid start\", \"actual\": [[\"32.0\", 900], [\"32.0\", 900]], \"expected\": [[\"21.5\", 707], [\"22.0\", 716]], \"passed\": false}, {\"check\": \"regression: celsius half-step display\", \"actual\": [[\"32.0\", 900]], \"expected\": [[\"22.0\", 716]], \"passed\": false}, {\"check\": \"control: scenario 1\", \"actual\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"expected\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"passed\": true}, {\"check\": \"regression: scenario 2\", \"actual\": [[\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900], [\"32.0\", 900]], \"expected\": [[\"21.5\", 707], [\"21.0\", 698], [\"20.5\", 689], [\"21.0\", 698], [\"20.5\", 689], [\"20.0\", 680], [\"20.5\", 689]], \"passed\": false}], \"passed\": false}\n"},"fixed":{"elapsed_ms":39.788,"exit_code":0,"observations":[{"actual":[["22.5",725],["23.0",734],["22.5",725]],"check":"regression: celsius steps","expected":[["22.5",725],["23.0",734],["22.5",725]],"passed":true},{"actual":[["7.0",450],["7.0",450],["7.5",455]],"check":"regression: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"passed":true},{"actual":[["74",740],["73",730],["72",720]],"check":"control: fahrenheit half value","expected":[["74",740],["73",730],["72",720]],"passed":true},{"actual":[["90",900]],"check":"control: upper clamp","expected":[["90",900]],"passed":true},{"actual":[["21.5",707],["22.0",716]],"check":"regression: celsius off-grid start","expected":[["21.5",707],["22.0",716]],"passed":true},{"actual":[["22.0",716]],"check":"regression: celsius half-step display","expected":[["22.0",716]],"passed":true},{"actual":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"check":"control: scenario 1","expected":[["71",710],["70",700],["71",710],["72",720],["73",730],["72",720],["71",710],["72",720]],"passed":true},{"actual":[["21.5",707],["21.0",698],["20.5",689],["21.0",698],["20.5",689],["20.0",680],["20.5",689]],"check":"regression: scenario 2","expected":[["21.5",707],["21.0",698],["20.5",689],["21.0",698],["20.5",689],["20.0",680],["20.5",689]],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: celsius steps\", \"actual\": [[\"22.5\", 725], [\"23.0\", 734], [\"22.5\", 725]], \"expected\": [[\"22.5\", 725], [\"23.0\", 734], [\"22.5\", 725]], \"passed\": true}, {\"check\": \"regression: celsius lower clamp\", \"actual\": [[\"7.0\", 450], [\"7.0\", 450], [\"7.5\", 455]], \"expected\": [[\"7.0\", 450], [\"7.0\", 450], [\"7.5\", 455]], \"passed\": true}, {\"check\": \"control: fahrenheit half value\", \"actual\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"expected\": [[\"74\", 740], [\"73\", 730], [\"72\", 720]], \"passed\": true}, {\"check\": \"control: upper clamp\", \"actual\": [[\"90\", 900]], \"expected\": [[\"90\", 900]], \"passed\": true}, {\"check\": \"regression: celsius off-grid start\", \"actual\": [[\"21.5\", 707], [\"22.0\", 716]], \"expected\": [[\"21.5\", 707], [\"22.0\", 716]], \"passed\": true}, {\"check\": \"regression: celsius half-step display\", \"actual\": [[\"22.0\", 716]], \"expected\": [[\"22.0\", 716]], \"passed\": true}, {\"check\": \"control: scenario 1\", \"actual\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"expected\": [[\"71\", 710], [\"70\", 700], [\"71\", 710], [\"72\", 720], [\"73\", 730], [\"72\", 720], [\"71\", 710], [\"72\", 720]], \"passed\": true}, {\"check\": \"regression: scenario 2\", \"actual\": [[\"21.5\", 707], [\"21.0\", 698], [\"20.5\", 689], [\"21.0\", 698], [\"20.5\", 689], [\"20.0\", 680], [\"20.5\", 689]], \"expected\": [[\"21.5\", 707], [\"21.0\", 698], [\"20.5\", 689], [\"21.0\", 698], [\"20.5\", 689], [\"20.0\", 680], [\"20.5\", 689]], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}