{"abstract":"The first press after switching to C sometimes leaves the displayed value unchanged or jumps the wrong way.","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":"Rounding to the nearest whole degree C before doubling loses the half-degree position.","family":"w2-hvac-thermostat-control-setpoint-keypad-units-celsius-step-base","id":"FA-92501","implementations":{"attempt":{"sha256":"2487354ca993cce26b301b3189334c8ddbc5929681efeaeebb3b7eb856094794","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: scenario 19',\n   ['C', ['up', 'up', 'up', 'up', 'up', 'up'], 659],\n   [['19.5', 671], ['20.0', 680], ['20.5', 689], ['21.0', 698], ['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 46',\n   ['C', ['up', 'down', 'up', 'up', 'up', 'up', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473], ['9.0', 482], ['9.5', 491]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 [['regression: scenario 56',\n   ['C', ['up', 'down', 'up', 'down', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\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  ['control: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\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: scenario 35',\n   ['C', ['up', 'down', 'up', 'down', 'down', 'up', 'up', 'down'], 776],\n   [['26.0', 788],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779],\n    ['25.0', 770],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779]]],\n  ['regression: scenario 5',\n   ['C', ['down', 'down', 'up', 'up', 'up'], 445],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473]]],\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  ['control: 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]]]],\n [['regression: scenario 32',\n   ['C', ['down', 'down', 'up', 'down', 'down'], 652],\n   [['18.0', 644], ['17.5', 635], ['18.0', 644], ['17.5', 635], ['17.0', 626]]],\n  ['regression: scenario 6',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down'], 725],\n   [['22.0', 716], ['21.5', 707], ['21.0', 698], ['21.5', 707], ['21.0', 698], ['20.5', 689]]],\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  ['control: 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":"2fcd500e73cb6783aaa593f16d0a274532fb547a161b587090b9b842d858c5ba","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 = (f10 - 320) // 9\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: scenario 19',\n   ['C', ['up', 'up', 'up', 'up', 'up', 'up'], 659],\n   [['19.5', 671], ['20.0', 680], ['20.5', 689], ['21.0', 698], ['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 46',\n   ['C', ['up', 'down', 'up', 'up', 'up', 'up', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473], ['9.0', 482], ['9.5', 491]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 [['regression: scenario 56',\n   ['C', ['up', 'down', 'up', 'down', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\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  ['control: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\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: scenario 35',\n   ['C', ['up', 'down', 'up', 'down', 'down', 'up', 'up', 'down'], 776],\n   [['26.0', 788],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779],\n    ['25.0', 770],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779]]],\n  ['regression: scenario 5',\n   ['C', ['down', 'down', 'up', 'up', 'up'], 445],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473]]],\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  ['control: 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]]]],\n [['regression: scenario 32',\n   ['C', ['down', 'down', 'up', 'down', 'down'], 652],\n   [['18.0', 644], ['17.5', 635], ['18.0', 644], ['17.5', 635], ['17.0', 626]]],\n  ['regression: scenario 6',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down'], 725],\n   [['22.0', 716], ['21.5', 707], ['21.0', 698], ['21.5', 707], ['21.0', 698], ['20.5', 689]]],\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  ['control: 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":"39cbf77bf1a56e152aafe53f74935b37ba7ac6279fb5fc998d83f3f82e6ae5cd","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: scenario 19',\n   ['C', ['up', 'up', 'up', 'up', 'up', 'up'], 659],\n   [['19.5', 671], ['20.0', 680], ['20.5', 689], ['21.0', 698], ['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 46',\n   ['C', ['up', 'down', 'up', 'up', 'up', 'up', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473], ['9.0', 482], ['9.5', 491]]],\n  ['regression: celsius off-grid start', ['C', ['down', 'up'], 716], [['21.5', 707], ['22.0', 716]]],\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  ['control: 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]]],\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 [['regression: scenario 56',\n   ['C', ['up', 'down', 'up', 'down', 'up'], 445],\n   [['7.5', 455], ['7.0', 450], ['7.5', 455], ['7.0', 450], ['7.5', 455]]],\n  ['regression: celsius half-step display', ['C', ['up'], 707], [['22.0', 716]]],\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  ['control: celsius lower clamp',\n   ['C', ['down', 'down', 'up'], 452],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455]]],\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: scenario 35',\n   ['C', ['up', 'down', 'up', 'down', 'down', 'up', 'up', 'down'], 776],\n   [['26.0', 788],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779],\n    ['25.0', 770],\n    ['25.5', 779],\n    ['26.0', 788],\n    ['25.5', 779]]],\n  ['regression: scenario 5',\n   ['C', ['down', 'down', 'up', 'up', 'up'], 445],\n   [['7.0', 450], ['7.0', 450], ['7.5', 455], ['8.0', 464], ['8.5', 473]]],\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  ['control: 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]]]],\n [['regression: scenario 32',\n   ['C', ['down', 'down', 'up', 'down', 'down'], 652],\n   [['18.0', 644], ['17.5', 635], ['18.0', 644], ['17.5', 635], ['17.0', 626]]],\n  ['regression: scenario 6',\n   ['C', ['down', 'down', 'down', 'up', 'down', 'down'], 725],\n   [['22.0', 716], ['21.5', 707], ['21.0', 698], ['21.5', 707], ['21.0', 698], ['20.5', 689]]],\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  ['control: 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-celsius-step-base","generated_at":"2026-09-29T14:51:46.315757+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":"Round the stored value half up to 0.5 C before stepping.","root_cause":"The starting half-degree for a C step truncates the stored value instead of rounding half up.","sha256":"66a3f755805e4edb38bc84961757572a49e966f81c4cf5eb4be1cb3cf7f76146","title":"Celsius arrow press steps from a truncated half degree · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":42.392,"exit_code":1,"observations":[{"actual":[["19.5",671],["20.5",689],["21.5",707],["22.5",725],["23.5",743],["24.5",761]],"check":"regression: scenario 19","expected":[["19.5",671],["20.0",680],["20.5",689],["21.0",698],["21.5",707],["22.0",716]],"passed":false},{"actual":[["22.5",725],["23.5",743],["23.5",743]],"check":"regression: celsius steps","expected":[["22.5",725],["23.0",734],["22.5",725]],"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.5",725]],"check":"regression: celsius off-grid start","expected":[["21.5",707],["22.0",716]],"passed":false},{"actual":[["7.0",450],["7.0",450],["7.5",455]],"check":"control: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"passed":true},{"actual":[["22.5",725]],"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}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: scenario 19\", \"actual\": [[\"19.5\", 671], [\"20.5\", 689], [\"21.5\", 707], [\"22.5\", 725], [\"23.5\", 743], [\"24.5\", 761]], \"expected\": [[\"19.5\", 671], [\"20.0\", 680], [\"20.5\", 689], [\"21.0\", 698], [\"21.5\", 707], [\"22.0\", 716]], \"passed\": false}, {\"check\": \"regression: celsius steps\", \"actual\": [[\"22.5\", 725], [\"23.5\", 743], [\"23.5\", 743]], \"expected\": [[\"22.5\", 725], [\"23.0\", 734], [\"22.5\", 725]], \"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.5\", 725]], \"expected\": [[\"21.5\", 707], [\"22.0\", 716]], \"passed\": false}, {\"check\": \"control: 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\": \"regression: celsius half-step display\", \"actual\": [[\"22.5\", 725]], \"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}], \"passed\": false}\n"},"broken":{"elapsed_ms":40.908,"exit_code":1,"observations":[{"actual":[["19.0",662],["19.5",671],["20.0",680],["20.5",689],["21.0",698],["21.5",707]],"check":"regression: scenario 19","expected":[["19.5",671],["20.0",680],["20.5",689],["21.0",698],["21.5",707],["22.0",716]],"passed":false},{"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":[["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":[["7.0",450],["7.0",450],["7.5",455]],"check":"control: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"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}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: scenario 19\", \"actual\": [[\"19.0\", 662], [\"19.5\", 671], [\"20.0\", 680], [\"20.5\", 689], [\"21.0\", 698], [\"21.5\", 707]], \"expected\": [[\"19.5\", 671], [\"20.0\", 680], [\"20.5\", 689], [\"21.0\", 698], [\"21.5\", 707], [\"22.0\", 716]], \"passed\": false}, {\"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\": \"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\": \"control: 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\": \"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}], \"passed\": false}\n"},"fixed":{"elapsed_ms":46.247,"exit_code":0,"observations":[{"actual":[["19.5",671],["20.0",680],["20.5",689],["21.0",698],["21.5",707],["22.0",716]],"check":"regression: scenario 19","expected":[["19.5",671],["20.0",680],["20.5",689],["21.0",698],["21.5",707],["22.0",716]],"passed":true},{"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":[["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":[["7.0",450],["7.0",450],["7.5",455]],"check":"control: celsius lower clamp","expected":[["7.0",450],["7.0",450],["7.5",455]],"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}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"regression: scenario 19\", \"actual\": [[\"19.5\", 671], [\"20.0\", 680], [\"20.5\", 689], [\"21.0\", 698], [\"21.5\", 707], [\"22.0\", 716]], \"expected\": [[\"19.5\", 671], [\"20.0\", 680], [\"20.5\", 689], [\"21.0\", 698], [\"21.5\", 707], [\"22.0\", 716]], \"passed\": true}, {\"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\": \"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\": \"control: 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\": \"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}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}