{"abstract":"Charging is planned to finish after the driver leaves.","category":"EV charging session scheduling","checks":7,"contract":"Minutes. The battery must receive need_wh; the charger draws rate_w at eff_pct percent efficiency, so duration = ceil(need_wh*6000/(rate_w*eff_pct)) minutes. Latest start = depart - buffer_min - duration, rounded down to a 15-minute boundary. If that is before now, start now with status 'late'. need_wh <= 0 returns [None, now, 'done']; rate_w or eff_pct <= 0 returns [None, None, 'no-power']. Return [start, finish, status].","evaluation_group":"w2-ev_charging_session_scheduling-ready-by-latest-start","failed_approach":"Dropping the buffer finishes exactly at departure with no margin.","family":"w2-ev_charging_session_scheduling-ready-by-latest-start-buffer-direction","id":"FA-93046","implementations":{"attempt":{"sha256":"9a6e7fe6b3e2f03fb0826b33525d7703f5c9e3c70c92bdac493f80220388d649","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(now, depart, need_wh, rate_w, eff_pct, buffer_min):\n    if need_wh <= 0:\n        return [None, now, 'done']\n    if rate_w <= 0 or eff_pct <= 0:\n        return [None, None, 'no-power']\n    dur = -(-need_wh * 6000 // (rate_w * eff_pct))\n    latest = depart - dur\n    latest -= latest % 15\n    if latest < now:\n        return [now, now + dur, 'late']\n    return [latest, latest + dur, 'ok']\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [153, 434, 2000, 11000, 85, 30], [390, 403, 'ok']],\n  ['regression: buffer direction (partial repair)', [387, 1026, 30000, 11000, 95, 30],\n   [810, 983, 'ok']],\n  ['control 1', [117, 637, 11000, 11000, 95, 10], [555, 619, 'ok']],\n  ['control 2', [448, 1142, 0, 3700, 85, 0], [None, 448, 'done']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [351, 1109, 18000, 3700, 95, 15], [780, 1088, 'ok']],\n  ['regression: buffer direction (partial repair)', [20, 911, 30000, 7400, 100, 15],\n   [645, 889, 'ok']],\n  ['control 1', [416, 1003, 5000, 0, 85, 15], [None, None, 'no-power']],\n  ['control 2', [221, 503, 5000, 0, 85, 30], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [159, 777, 11000, 3700, 100, 30], [555, 734, 'ok']],\n  ['regression: buffer direction (partial repair)', [12, 862, 30000, 11000, 95, 15],\n   [660, 833, 'ok']],\n  ['control 1', [381, 632, 18000, 3700, 95, 30], [381, 689, 'late']],\n  ['control 2', [19, 584, 30000, 11000, 90, 15], [375, 557, 'ok']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [496, 868, 11000, 3700, 95, 30], [645, 833, 'ok']],\n  ['regression: buffer direction (partial repair)', [577, 1400, 11000, 7400, 85, 15],\n   [1275, 1380, 'ok']],\n  ['control 1', [66, 229, 11000, 0, 90, 15], [None, None, 'no-power']],\n  ['control 2', [44, 377, 2000, 0, 100, 0], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [522, 1168, 30000, 3700, 85, 30], [555, 1128, 'ok']],\n  ['regression: buffer direction (partial repair)', [546, 1243, 11000, 7400, 85, 30],\n   [1095, 1200, 'ok']],\n  ['control 1', [342, 397, 18000, 11000, 95, 10], [342, 446, 'late']],\n  ['control 2', [577, 1400, 11000, 7400, 85, 15], [1275, 1380, 'ok']]]]\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":"d0c189d21951202be1a79c6a1c5b8beac7aba1f5073e58a7b49ca050079c0bd1","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(now, depart, need_wh, rate_w, eff_pct, buffer_min):\n    if need_wh <= 0:\n        return [None, now, 'done']\n    if rate_w <= 0 or eff_pct <= 0:\n        return [None, None, 'no-power']\n    dur = -(-need_wh * 6000 // (rate_w * eff_pct))\n    latest = depart + buffer_min - dur\n    latest -= latest % 15\n    if latest < now:\n        return [now, now + dur, 'late']\n    return [latest, latest + dur, 'ok']\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [153, 434, 2000, 11000, 85, 30], [390, 403, 'ok']],\n  ['regression: buffer direction (partial repair)', [387, 1026, 30000, 11000, 95, 30],\n   [810, 983, 'ok']],\n  ['control 1', [117, 637, 11000, 11000, 95, 10], [555, 619, 'ok']],\n  ['control 2', [448, 1142, 0, 3700, 85, 0], [None, 448, 'done']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [351, 1109, 18000, 3700, 95, 15], [780, 1088, 'ok']],\n  ['regression: buffer direction (partial repair)', [20, 911, 30000, 7400, 100, 15],\n   [645, 889, 'ok']],\n  ['control 1', [416, 1003, 5000, 0, 85, 15], [None, None, 'no-power']],\n  ['control 2', [221, 503, 5000, 0, 85, 30], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [159, 777, 11000, 3700, 100, 30], [555, 734, 'ok']],\n  ['regression: buffer direction (partial repair)', [12, 862, 30000, 11000, 95, 15],\n   [660, 833, 'ok']],\n  ['control 1', [381, 632, 18000, 3700, 95, 30], [381, 689, 'late']],\n  ['control 2', [19, 584, 30000, 11000, 90, 15], [375, 557, 'ok']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [496, 868, 11000, 3700, 95, 30], [645, 833, 'ok']],\n  ['regression: buffer direction (partial repair)', [577, 1400, 11000, 7400, 85, 15],\n   [1275, 1380, 'ok']],\n  ['control 1', [66, 229, 11000, 0, 90, 15], [None, None, 'no-power']],\n  ['control 2', [44, 377, 2000, 0, 100, 0], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [522, 1168, 30000, 3700, 85, 30], [555, 1128, 'ok']],\n  ['regression: buffer direction (partial repair)', [546, 1243, 11000, 7400, 85, 30],\n   [1095, 1200, 'ok']],\n  ['control 1', [342, 397, 18000, 11000, 95, 10], [342, 446, 'late']],\n  ['control 2', [577, 1400, 11000, 7400, 85, 15], [1275, 1380, 'ok']]]]\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":"6f802d5b0650a7ae40045848e9e4b2b67c62a279ef0fbd26469352de0108c9a5","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\n\nN = 1\nobservations = []\ndef solve(now, depart, need_wh, rate_w, eff_pct, buffer_min):\n    if need_wh <= 0:\n        return [None, now, 'done']\n    if rate_w <= 0 or eff_pct <= 0:\n        return [None, None, 'no-power']\n    dur = -(-need_wh * 6000 // (rate_w * eff_pct))\n    latest = depart - buffer_min - dur\n    latest -= latest % 15\n    if latest < now:\n        return [now, now + dur, 'late']\n    return [latest, latest + dur, 'ok']\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [153, 434, 2000, 11000, 85, 30], [390, 403, 'ok']],\n  ['regression: buffer direction (partial repair)', [387, 1026, 30000, 11000, 95, 30],\n   [810, 983, 'ok']],\n  ['control 1', [117, 637, 11000, 11000, 95, 10], [555, 619, 'ok']],\n  ['control 2', [448, 1142, 0, 3700, 85, 0], [None, 448, 'done']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [351, 1109, 18000, 3700, 95, 15], [780, 1088, 'ok']],\n  ['regression: buffer direction (partial repair)', [20, 911, 30000, 7400, 100, 15],\n   [645, 889, 'ok']],\n  ['control 1', [416, 1003, 5000, 0, 85, 15], [None, None, 'no-power']],\n  ['control 2', [221, 503, 5000, 0, 85, 30], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [159, 777, 11000, 3700, 100, 30], [555, 734, 'ok']],\n  ['regression: buffer direction (partial repair)', [12, 862, 30000, 11000, 95, 15],\n   [660, 833, 'ok']],\n  ['control 1', [381, 632, 18000, 3700, 95, 30], [381, 689, 'late']],\n  ['control 2', [19, 584, 30000, 11000, 90, 15], [375, 557, 'ok']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [496, 868, 11000, 3700, 95, 30], [645, 833, 'ok']],\n  ['regression: buffer direction (partial repair)', [577, 1400, 11000, 7400, 85, 15],\n   [1275, 1380, 'ok']],\n  ['control 1', [66, 229, 11000, 0, 90, 15], [None, None, 'no-power']],\n  ['control 2', [44, 377, 2000, 0, 100, 0], [None, None, 'no-power']]],\n [['boundary: nothing to charge', [100, 400, 0, 0, 90, 10], [None, 100, 'done']],\n  ['boundary: latest start exactly now', [300, 390, 7400, 7400, 100, 0], [330, 390, 'ok']],\n  ['boundary: no charger power', [100, 400, 5000, 0, 90, 10], [None, None, 'no-power']],\n  ['regression: buffer direction', [522, 1168, 30000, 3700, 85, 30], [555, 1128, 'ok']],\n  ['regression: buffer direction (partial repair)', [546, 1243, 11000, 7400, 85, 30],\n   [1095, 1200, 'ok']],\n  ['control 1', [342, 397, 18000, 11000, 95, 10], [342, 446, 'late']],\n  ['control 2', [577, 1400, 11000, 7400, 85, 15], [1275, 1380, 'ok']]]]\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":"Deterministic stipulated toy contract for teaching; no claim of conformance with any standard, vendor protocol or production controller. 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-ev_charging_session_scheduling-ready-by-latest-start-buffer-direction","generated_at":"2026-09-29T14:51:51.664953+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"Depot, workplace and public EV chargers schedule sessions against prices, circuit limits and departure deadlines; a wrong decision silently strands a driver or overloads a feeder.","repair":"Subtract the buffer from the departure time.","root_cause":"The pre-departure buffer is added to the departure time instead of subtracted.","sha256":"ceff30c581aa487824c0d2d457201dcc44347cb7a0267c0fb33703e540dd9663","title":"Ready-by departure latest start: buffer direction · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verification":{"attempt":{"elapsed_ms":37.92,"exit_code":1,"observations":[{"actual":[null,100,"done"],"check":"boundary: nothing to charge","expected":[null,100,"done"],"passed":true},{"actual":[330,390,"ok"],"check":"boundary: latest start exactly now","expected":[330,390,"ok"],"passed":true},{"actual":[null,null,"no-power"],"check":"boundary: no charger power","expected":[null,null,"no-power"],"passed":true},{"actual":[420,433,"ok"],"check":"regression: buffer direction","expected":[390,403,"ok"],"passed":false},{"actual":[840,1013,"ok"],"check":"regression: buffer direction (partial repair)","expected":[810,983,"ok"],"passed":false},{"actual":[570,634,"ok"],"check":"control 1","expected":[555,619,"ok"],"passed":false},{"actual":[null,448,"done"],"check":"control 2","expected":[null,448,"done"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: nothing to charge\", \"actual\": [null, 100, \"done\"], \"expected\": [null, 100, \"done\"], \"passed\": true}, {\"check\": \"boundary: latest start exactly now\", \"actual\": [330, 390, \"ok\"], \"expected\": [330, 390, \"ok\"], \"passed\": true}, {\"check\": \"boundary: no charger power\", \"actual\": [null, null, \"no-power\"], \"expected\": [null, null, \"no-power\"], \"passed\": true}, {\"check\": \"regression: buffer direction\", \"actual\": [420, 433, \"ok\"], \"expected\": [390, 403, \"ok\"], \"passed\": false}, {\"check\": \"regression: buffer direction (partial repair)\", \"actual\": [840, 1013, \"ok\"], \"expected\": [810, 983, \"ok\"], \"passed\": false}, {\"check\": \"control 1\", \"actual\": [570, 634, \"ok\"], \"expected\": [555, 619, \"ok\"], \"passed\": false}, {\"check\": \"control 2\", \"actual\": [null, 448, \"done\"], \"expected\": [null, 448, \"done\"], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":38.521,"exit_code":1,"observations":[{"actual":[null,100,"done"],"check":"boundary: nothing to charge","expected":[null,100,"done"],"passed":true},{"actual":[330,390,"ok"],"check":"boundary: latest start exactly now","expected":[330,390,"ok"],"passed":true},{"actual":[null,null,"no-power"],"check":"boundary: no charger power","expected":[null,null,"no-power"],"passed":true},{"actual":[450,463,"ok"],"check":"regression: buffer direction","expected":[390,403,"ok"],"passed":false},{"actual":[870,1043,"ok"],"check":"regression: buffer direction (partial repair)","expected":[810,983,"ok"],"passed":false},{"actual":[570,634,"ok"],"check":"control 1","expected":[555,619,"ok"],"passed":false},{"actual":[null,448,"done"],"check":"control 2","expected":[null,448,"done"],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: nothing to charge\", \"actual\": [null, 100, \"done\"], \"expected\": [null, 100, \"done\"], \"passed\": true}, {\"check\": \"boundary: latest start exactly now\", \"actual\": [330, 390, \"ok\"], \"expected\": [330, 390, \"ok\"], \"passed\": true}, {\"check\": \"boundary: no charger power\", \"actual\": [null, null, \"no-power\"], \"expected\": [null, null, \"no-power\"], \"passed\": true}, {\"check\": \"regression: buffer direction\", \"actual\": [450, 463, \"ok\"], \"expected\": [390, 403, \"ok\"], \"passed\": false}, {\"check\": \"regression: buffer direction (partial repair)\", \"actual\": [870, 1043, \"ok\"], \"expected\": [810, 983, \"ok\"], \"passed\": false}, {\"check\": \"control 1\", \"actual\": [570, 634, \"ok\"], \"expected\": [555, 619, \"ok\"], \"passed\": false}, {\"check\": \"control 2\", \"actual\": [null, 448, \"done\"], \"expected\": [null, 448, \"done\"], \"passed\": true}], \"passed\": false}\n"},"fixed":{"elapsed_ms":44.286,"exit_code":0,"observations":[{"actual":[null,100,"done"],"check":"boundary: nothing to charge","expected":[null,100,"done"],"passed":true},{"actual":[330,390,"ok"],"check":"boundary: latest start exactly now","expected":[330,390,"ok"],"passed":true},{"actual":[null,null,"no-power"],"check":"boundary: no charger power","expected":[null,null,"no-power"],"passed":true},{"actual":[390,403,"ok"],"check":"regression: buffer direction","expected":[390,403,"ok"],"passed":true},{"actual":[810,983,"ok"],"check":"regression: buffer direction (partial repair)","expected":[810,983,"ok"],"passed":true},{"actual":[555,619,"ok"],"check":"control 1","expected":[555,619,"ok"],"passed":true},{"actual":[null,448,"done"],"check":"control 2","expected":[null,448,"done"],"passed":true}],"passed":true,"stderr":"","stdout":"{\"observations\": [{\"check\": \"boundary: nothing to charge\", \"actual\": [null, 100, \"done\"], \"expected\": [null, 100, \"done\"], \"passed\": true}, {\"check\": \"boundary: latest start exactly now\", \"actual\": [330, 390, \"ok\"], \"expected\": [330, 390, \"ok\"], \"passed\": true}, {\"check\": \"boundary: no charger power\", \"actual\": [null, null, \"no-power\"], \"expected\": [null, null, \"no-power\"], \"passed\": true}, {\"check\": \"regression: buffer direction\", \"actual\": [390, 403, \"ok\"], \"expected\": [390, 403, \"ok\"], \"passed\": true}, {\"check\": \"regression: buffer direction (partial repair)\", \"actual\": [810, 983, \"ok\"], \"expected\": [810, 983, \"ok\"], \"passed\": true}, {\"check\": \"control 1\", \"actual\": [555, 619, \"ok\"], \"expected\": [555, 619, \"ok\"], \"passed\": true}, {\"check\": \"control 2\", \"actual\": [null, 448, \"done\"], \"expected\": [null, 448, \"done\"], \"passed\": true}], \"passed\": true}\n"}},"verified":true,"visibility":"public"}