FA-94221 / Shift rostering labor rules / Open access
Rolling 24-hour limit evaluated on calendar days · case 01
Two long shifts straddling midnight never exceed a calendar-day total.
ROOT CAUSE
Windows are anchored at midnight instead of at shift starts.
VERIFIED REPAIR
Anchor candidate windows at each shift start.
Unsuccessful approach: Anchoring at shift ends misses windows that begin at a shift start.
Case contract
Shifts [start, end] in minutes. For window W, evaluate windows [t, t + W) anchored at each shift start and sum the minutes of all shifts clipped to the window; report the maximum. Return [max in any 24h window, max in any 168h window, violations] where more than 960 minutes in 24h or more than 3600 minutes in 168h is a violation.
Why this case matters
Rolling-window fatigue limits catch hours concentrated across calendar-day boundaries.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(shifts):
starts = sorted(s // 1440 * 1440 for s, e in shifts)
def worst(W):
best = 0
for t in starts:
tot = sum(max(0, min(e, t + W) - max(s, t)) for s, e in shifts)
best = max(best, tot)
return best
m24, m168 = worst(1440), worst(10080)
v = []
if m24 > 960:
v.append('24h')
if m168 > 3600:
v.append('7d')
return [m24, m168, v]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: calendar day anchor 1',
[[[0, 600], [3480, 3960], [5400, 5880], [840, 1200], [4200, 4920], [1680, 2040]]], [1200, 3000, ['24h']]),
('regression variant: calendar day anchor 2', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]],
[1200, 1680, ['24h']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('boundary control 5', [[[0, 480], [480, 960]]], [960, 960, []]),
('normal control 6', [[[300, 780], [1260, 1980]]], [960, 1200, []]),
('normal control 7', [[[0, 720], [720, 1440], [2340, 2700]]], [1440, 1800, ['24h']]),
('normal control 8', [[[1320, 1920], [2820, 3180], [0, 600]]], [720, 1560, []])],
[('regression: calendar day anchor 1',
[[[0, 720], [2160, 2520], [8580, 8940], [9660, 10260], [5160, 5640], [8040, 8520], [7080, 7800],
[3240, 3720]]],
[1200, 4020, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[0, 720], [5400, 6000], [9180, 9900], [7980, 8460], [10140, 10620], [1620, 2340], [3240, 3960],
[7440, 7920]]],
[1200, 4440, ['24h', '7d']]),
('partial repair guard 3', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7', [[[0, 480], [540, 1020], [1680, 2160], [1080, 1680]]], [1380, 2040, ['24h']]),
('normal control 8',
[[[6180, 6660], [7140, 7500], [4260, 4740], [0, 360], [5640, 6120], [840, 1200], [2640, 3360]]],
[960, 3240, []])],
[('regression: calendar day anchor 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: calendar day anchor 2', [[[1680, 2160], [300, 780]]], [540, 960, []]),
('boundary control 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]],
[960, 3000, []]),
('normal control 6', [[[300, 780], [2220, 2580]]], [480, 840, []]),
('normal control 7', [[[1740, 2100], [3540, 4140], [0, 600], [660, 1260]]], [1200, 2160, ['24h']]),
('normal control 8', [[[3000, 3360], [300, 1020], [2460, 2940], [4800, 5520]]], [840, 2280, []])],
[('regression: calendar day anchor 1',
[[[3360, 3720], [0, 600], [6480, 6960], [4620, 4980], [2760, 3360], [5220, 5580], [2040, 2520],
[6960, 7680]]],
[1200, 3960, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[5640, 6360], [1260, 1620], [2820, 3300], [300, 780], [5280, 5640], [7260, 7740], [4200, 4560],
[2100, 2820]]],
[1200, 3960, ['24h', '7d']]),
('partial repair guard 3',
[[[5220, 5940], [1500, 2100], [0, 600], [2340, 2700], [4620, 5220], [3420, 3900], [660, 1260]]],
[1320, 3960, ['24h', '7d']]),
('boundary control 4', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('boundary control 5', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('normal control 6', [[[3720, 4440], [300, 780], [2220, 2820], [1500, 1980]]], [1080, 2280, ['24h']]),
('normal control 7', [[[2280, 3000], [300, 1020], [3720, 4080], [4140, 4620], [1080, 1800]]],
[1380, 3000, ['24h']]),
('normal control 8', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']])],
[('regression: calendar day anchor 1',
[[[4680, 5160], [4080, 4440], [1920, 2640], [1200, 1680], [6120, 6600], [0, 720], [5400, 5880],
[3540, 4020]]],
[1200, 4200, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[6240, 6840], [5520, 6240], [3780, 4140], [1140, 1740], [300, 660], [1740, 2340], [5040, 5520]]],
[1440, 3720, ['24h', '7d']]),
('partial repair guard 3', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]], [1200, 1680, ['24h']]),
('boundary control 4', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 5', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7',
[[[4320, 4920], [5640, 6000], [2460, 2940], [3720, 4080], [3000, 3720], [1380, 1740], [300, 900]]],
[1380, 3480, ['24h']]),
('normal control 8', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']])]]
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: calendar day anchor 1 | [960, 3000, []] | [1200, 3000, ['24h']] | Failed |
| regression variant: calendar day anchor 2 | [1140, 1680, ['24h']] | [1200, 1680, ['24h']] | Failed |
| partial repair guard 3 | [1000, 1000, ['24h']] | [1000, 1000, ['24h']] | Passed |
| boundary control 4 | [920, 980, []] | [920, 980, []] | Passed |
| boundary control 5 | [960, 960, []] | [960, 960, []] | Passed |
| normal control 6 | [660, 1200, []] | [960, 1200, []] | Failed |
| normal control 7 | [1440, 1800, ['24h']] | [1440, 1800, ['24h']] | Passed |
| normal control 8 | [720, 1560, []] | [720, 1560, []] | Passed |
SHA-256 / f7746ccce2ed6f96f7c0c784f70110453474de8481d040ae59d5a8a28467138c
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(shifts):
starts = sorted(e for s, e in shifts)
def worst(W):
best = 0
for t in starts:
tot = sum(max(0, min(e, t + W) - max(s, t)) for s, e in shifts)
best = max(best, tot)
return best
m24, m168 = worst(1440), worst(10080)
v = []
if m24 > 960:
v.append('24h')
if m168 > 3600:
v.append('7d')
return [m24, m168, v]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: calendar day anchor 1',
[[[0, 600], [3480, 3960], [5400, 5880], [840, 1200], [4200, 4920], [1680, 2040]]], [1200, 3000, ['24h']]),
('regression variant: calendar day anchor 2', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]],
[1200, 1680, ['24h']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('boundary control 5', [[[0, 480], [480, 960]]], [960, 960, []]),
('normal control 6', [[[300, 780], [1260, 1980]]], [960, 1200, []]),
('normal control 7', [[[0, 720], [720, 1440], [2340, 2700]]], [1440, 1800, ['24h']]),
('normal control 8', [[[1320, 1920], [2820, 3180], [0, 600]]], [720, 1560, []])],
[('regression: calendar day anchor 1',
[[[0, 720], [2160, 2520], [8580, 8940], [9660, 10260], [5160, 5640], [8040, 8520], [7080, 7800],
[3240, 3720]]],
[1200, 4020, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[0, 720], [5400, 6000], [9180, 9900], [7980, 8460], [10140, 10620], [1620, 2340], [3240, 3960],
[7440, 7920]]],
[1200, 4440, ['24h', '7d']]),
('partial repair guard 3', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7', [[[0, 480], [540, 1020], [1680, 2160], [1080, 1680]]], [1380, 2040, ['24h']]),
('normal control 8',
[[[6180, 6660], [7140, 7500], [4260, 4740], [0, 360], [5640, 6120], [840, 1200], [2640, 3360]]],
[960, 3240, []])],
[('regression: calendar day anchor 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: calendar day anchor 2', [[[1680, 2160], [300, 780]]], [540, 960, []]),
('boundary control 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]],
[960, 3000, []]),
('normal control 6', [[[300, 780], [2220, 2580]]], [480, 840, []]),
('normal control 7', [[[1740, 2100], [3540, 4140], [0, 600], [660, 1260]]], [1200, 2160, ['24h']]),
('normal control 8', [[[3000, 3360], [300, 1020], [2460, 2940], [4800, 5520]]], [840, 2280, []])],
[('regression: calendar day anchor 1',
[[[3360, 3720], [0, 600], [6480, 6960], [4620, 4980], [2760, 3360], [5220, 5580], [2040, 2520],
[6960, 7680]]],
[1200, 3960, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[5640, 6360], [1260, 1620], [2820, 3300], [300, 780], [5280, 5640], [7260, 7740], [4200, 4560],
[2100, 2820]]],
[1200, 3960, ['24h', '7d']]),
('partial repair guard 3',
[[[5220, 5940], [1500, 2100], [0, 600], [2340, 2700], [4620, 5220], [3420, 3900], [660, 1260]]],
[1320, 3960, ['24h', '7d']]),
('boundary control 4', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('boundary control 5', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('normal control 6', [[[3720, 4440], [300, 780], [2220, 2820], [1500, 1980]]], [1080, 2280, ['24h']]),
('normal control 7', [[[2280, 3000], [300, 1020], [3720, 4080], [4140, 4620], [1080, 1800]]],
[1380, 3000, ['24h']]),
('normal control 8', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']])],
[('regression: calendar day anchor 1',
[[[4680, 5160], [4080, 4440], [1920, 2640], [1200, 1680], [6120, 6600], [0, 720], [5400, 5880],
[3540, 4020]]],
[1200, 4200, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[6240, 6840], [5520, 6240], [3780, 4140], [1140, 1740], [300, 660], [1740, 2340], [5040, 5520]]],
[1440, 3720, ['24h', '7d']]),
('partial repair guard 3', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]], [1200, 1680, ['24h']]),
('boundary control 4', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 5', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7',
[[[4320, 4920], [5640, 6000], [2460, 2940], [3720, 4080], [3000, 3720], [1380, 1740], [300, 900]]],
[1380, 3480, ['24h']]),
('normal control 8', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']])]]
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: calendar day anchor 1 | [720, 2400, []] | [1200, 3000, ['24h']] | Failed |
| regression variant: calendar day anchor 2 | [840, 1200, []] | [1200, 1680, ['24h']] | Failed |
| partial repair guard 3 | [400, 400, []] | [1000, 1000, ['24h']] | Failed |
| boundary control 4 | [500, 500, []] | [920, 980, []] | Failed |
| boundary control 5 | [480, 480, []] | [960, 960, []] | Failed |
| normal control 6 | [720, 720, []] | [960, 1200, []] | Failed |
| normal control 7 | [720, 1080, []] | [1440, 1800, ['24h']] | Failed |
| normal control 8 | [600, 960, []] | [720, 1560, []] | Failed |
SHA-256 / ccb192157efabbeb55d22d00c2acdf28a0a532f379c0a9ce7e08aa3d21f79e53
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(shifts):
starts = sorted(s for s, e in shifts)
def worst(W):
best = 0
for t in starts:
tot = sum(max(0, min(e, t + W) - max(s, t)) for s, e in shifts)
best = max(best, tot)
return best
m24, m168 = worst(1440), worst(10080)
v = []
if m24 > 960:
v.append('24h')
if m168 > 3600:
v.append('7d')
return [m24, m168, v]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: calendar day anchor 1',
[[[0, 600], [3480, 3960], [5400, 5880], [840, 1200], [4200, 4920], [1680, 2040]]], [1200, 3000, ['24h']]),
('regression variant: calendar day anchor 2', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]],
[1200, 1680, ['24h']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('boundary control 5', [[[0, 480], [480, 960]]], [960, 960, []]),
('normal control 6', [[[300, 780], [1260, 1980]]], [960, 1200, []]),
('normal control 7', [[[0, 720], [720, 1440], [2340, 2700]]], [1440, 1800, ['24h']]),
('normal control 8', [[[1320, 1920], [2820, 3180], [0, 600]]], [720, 1560, []])],
[('regression: calendar day anchor 1',
[[[0, 720], [2160, 2520], [8580, 8940], [9660, 10260], [5160, 5640], [8040, 8520], [7080, 7800],
[3240, 3720]]],
[1200, 4020, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[0, 720], [5400, 6000], [9180, 9900], [7980, 8460], [10140, 10620], [1620, 2340], [3240, 3960],
[7440, 7920]]],
[1200, 4440, ['24h', '7d']]),
('partial repair guard 3', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7', [[[0, 480], [540, 1020], [1680, 2160], [1080, 1680]]], [1380, 2040, ['24h']]),
('normal control 8',
[[[6180, 6660], [7140, 7500], [4260, 4740], [0, 360], [5640, 6120], [840, 1200], [2640, 3360]]],
[960, 3240, []])],
[('regression: calendar day anchor 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: calendar day anchor 2', [[[1680, 2160], [300, 780]]], [540, 960, []]),
('boundary control 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]],
[960, 3000, []]),
('normal control 6', [[[300, 780], [2220, 2580]]], [480, 840, []]),
('normal control 7', [[[1740, 2100], [3540, 4140], [0, 600], [660, 1260]]], [1200, 2160, ['24h']]),
('normal control 8', [[[3000, 3360], [300, 1020], [2460, 2940], [4800, 5520]]], [840, 2280, []])],
[('regression: calendar day anchor 1',
[[[3360, 3720], [0, 600], [6480, 6960], [4620, 4980], [2760, 3360], [5220, 5580], [2040, 2520],
[6960, 7680]]],
[1200, 3960, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[5640, 6360], [1260, 1620], [2820, 3300], [300, 780], [5280, 5640], [7260, 7740], [4200, 4560],
[2100, 2820]]],
[1200, 3960, ['24h', '7d']]),
('partial repair guard 3',
[[[5220, 5940], [1500, 2100], [0, 600], [2340, 2700], [4620, 5220], [3420, 3900], [660, 1260]]],
[1320, 3960, ['24h', '7d']]),
('boundary control 4', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('boundary control 5', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('normal control 6', [[[3720, 4440], [300, 780], [2220, 2820], [1500, 1980]]], [1080, 2280, ['24h']]),
('normal control 7', [[[2280, 3000], [300, 1020], [3720, 4080], [4140, 4620], [1080, 1800]]],
[1380, 3000, ['24h']]),
('normal control 8', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']])],
[('regression: calendar day anchor 1',
[[[4680, 5160], [4080, 4440], [1920, 2640], [1200, 1680], [6120, 6600], [0, 720], [5400, 5880],
[3540, 4020]]],
[1200, 4200, ['24h', '7d']]),
('regression variant: calendar day anchor 2',
[[[6240, 6840], [5520, 6240], [3780, 4140], [1140, 1740], [300, 660], [1740, 2340], [5040, 5520]]],
[1440, 3720, ['24h', '7d']]),
('partial repair guard 3', [[[2460, 2940], [300, 780], [1680, 2040], [2040, 2400]]], [1200, 1680, ['24h']]),
('boundary control 4', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 5', [[[0, 720], [1440, 2160], [2880, 3600], [4320, 5040], [5760, 6480]]],
[720, 3600, []]),
('normal control 6', [[[1920, 2520], [0, 480], [720, 1200], [2760, 3480]]], [1200, 2280, ['24h']]),
('normal control 7',
[[[4320, 4920], [5640, 6000], [2460, 2940], [3720, 4080], [3000, 3720], [1380, 1740], [300, 900]]],
[1380, 3480, ['24h']]),
('normal control 8', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']])]]
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: calendar day anchor 1 | [1200, 3000, ['24h']] | [1200, 3000, ['24h']] | Passed |
| regression variant: calendar day anchor 2 | [1200, 1680, ['24h']] | [1200, 1680, ['24h']] | Passed |
| partial repair guard 3 | [1000, 1000, ['24h']] | [1000, 1000, ['24h']] | Passed |
| boundary control 4 | [920, 980, []] | [920, 980, []] | Passed |
| boundary control 5 | [960, 960, []] | [960, 960, []] | Passed |
| normal control 6 | [960, 1200, []] | [960, 1200, []] | Passed |
| normal control 7 | [1440, 1800, ['24h']] | [1440, 1800, ['24h']] | Passed |
| normal control 8 | [720, 1560, []] | [720, 1560, []] | Passed |
SHA-256 / bf1cd2063c0c40f9456dd6010f2621f056db7e439522f8019315e646ba3c72b8
Verification & scope
Stipulated toy labor rule for a bounded roster model; it is not legal advice and does not claim conformance with any jurisdiction, award, or collective agreement. 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:52:02.310391+00:00.
Case digest / eab1f391ca0ac1a3c1cd3a239227303a3db7843b44f63572c7c0c45ab9d08661