FA-94226 / Shift rostering labor rules / Open access
Exactly sixteen hours in 24 flagged as fatigue breach · case 01
Double shifts totalling 16 hours are rejected.
ROOT CAUSE
The 24-hour limit comparison is inclusive.
VERIFIED REPAIR
Flag only totals above 960 minutes.
Unsuccessful approach: Comparing whole hours ignores 1 to 59 excess minutes.
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 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: daily limit units 1', [[[0, 480], [480, 960]]], [960, 960, []]),
('regression variant: daily limit units 2',
[[[1740, 2340], [540, 1020], [2820, 3420], [4140, 4620], [5100, 5700], [7140, 7740], [0, 480]]],
[960, 3840, ['7d']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 5', [[[1260, 1980], [780, 1260], [2700, 3300], [0, 720], [3540, 4140]]],
[1380, 3120, ['24h']]),
('normal control 6', [[[300, 780], [3600, 4080], [4140, 4620], [1680, 2160]]], [960, 1920, []]),
('normal control 7', [[[3060, 3660], [2400, 3000], [3900, 4260], [0, 480], [960, 1680]]],
[1200, 2760, ['24h']]),
('normal control 8', [[[2460, 3060], [300, 780], [3540, 4140], [1020, 1740]]], [1200, 2400, ['24h']])],
[('regression: daily limit units 1', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2',
[[[4020, 4740], [300, 660], [6600, 7080], [2820, 3300], [5640, 6120], [1560, 1920]]], [960, 2880, []]),
('partial repair guard 3', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[0, 360], [1800, 2280]]], [480, 840, []]),
('normal control 7', [[[300, 1020], [4260, 4740], [3480, 4200], [1260, 1620], [3060, 3420]]],
[1320, 2640, ['24h']]),
('normal control 8', [[[0, 600], [1080, 1800], [2040, 2640], [3120, 3720]]], [1200, 2520, ['24h']])],
[('regression: daily limit units 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: daily limit units 2', [[[660, 1260], [300, 660]]], [960, 960, []]),
('partial repair guard 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[3720, 4200], [2220, 2820], [300, 780]]], [600, 1560, []]),
('normal control 6', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']]),
('normal control 7', [[[300, 900], [1380, 1860]]], [960, 1080, []]),
('normal control 8',
[[[960, 1680], [6480, 6840], [3360, 3720], [7740, 8340], [5160, 5760], [0, 480], [1920, 2640]]],
[1200, 3840, ['24h', '7d']])],
[('regression: daily limit units 1', [[[2520, 3120], [2100, 2460], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2', [[[300, 660], [2580, 2940], [1140, 1860]]], [960, 1440, []]),
('partial repair guard 3', [[[0, 500], [500, 1000]]], [1000, 1000, ['24h']]),
('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', [[[3120, 3720], [1200, 1800], [1860, 2220], [0, 720]]], [960, 2280, []]),
('normal control 7',
[[[4380, 4740], [6180, 6540], [300, 1020], [4980, 5460], [3540, 4140], [2460, 3060], [7440, 7800]]],
[960, 3480, []]),
('normal control 8',
[[[2520, 2880], [7080, 7680], [0, 600], [4800, 5280], [6000, 6360], [600, 1080], [3600, 4320]]],
[1080, 3600, ['24h']])],
[('regression: daily limit units 1',
[[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]], [960, 3000, []]),
('regression variant: daily limit units 2', [[[300, 660], [900, 1500]]], [960, 960, []]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['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',
[[[1200, 1800], [480, 1200], [0, 480], [4500, 5220], [7140, 7620], [2880, 3600], [5940, 6420],
[2280, 2880]]],
[1440, 4800, ['24h', '7d']]),
('normal control 7', [[[4140, 4620], [1800, 2520], [0, 360], [2760, 3240]]], [1200, 2040, ['24h']]),
('normal control 8', [[[300, 780], [840, 1560]]], [1200, 1200, ['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: daily limit units 1 | [960, 960, ['24h']] | [960, 960, []] | Failed |
| regression variant: daily limit units 2 | [960, 3840, ['24h', '7d']] | [960, 3840, ['7d']] | Failed |
| partial repair guard 3 | [1000, 1000, ['24h']] | [1000, 1000, ['24h']] | Passed |
| boundary control 4 | [920, 980, []] | [920, 980, []] | Passed |
| normal control 5 | [1380, 3120, ['24h']] | [1380, 3120, ['24h']] | Passed |
| normal control 6 | [960, 1920, ['24h']] | [960, 1920, []] | Failed |
| normal control 7 | [1200, 2760, ['24h']] | [1200, 2760, ['24h']] | Passed |
| normal control 8 | [1200, 2400, ['24h']] | [1200, 2400, ['24h']] | Passed |
SHA-256 / 0debfdb3522fc7ede3755a39b83de5b11627ac7f45e0eb30c05264bd58c88a2a
2 / The unsuccessful fix
Exit 1"""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 // 60 > 16:
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: daily limit units 1', [[[0, 480], [480, 960]]], [960, 960, []]),
('regression variant: daily limit units 2',
[[[1740, 2340], [540, 1020], [2820, 3420], [4140, 4620], [5100, 5700], [7140, 7740], [0, 480]]],
[960, 3840, ['7d']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 5', [[[1260, 1980], [780, 1260], [2700, 3300], [0, 720], [3540, 4140]]],
[1380, 3120, ['24h']]),
('normal control 6', [[[300, 780], [3600, 4080], [4140, 4620], [1680, 2160]]], [960, 1920, []]),
('normal control 7', [[[3060, 3660], [2400, 3000], [3900, 4260], [0, 480], [960, 1680]]],
[1200, 2760, ['24h']]),
('normal control 8', [[[2460, 3060], [300, 780], [3540, 4140], [1020, 1740]]], [1200, 2400, ['24h']])],
[('regression: daily limit units 1', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2',
[[[4020, 4740], [300, 660], [6600, 7080], [2820, 3300], [5640, 6120], [1560, 1920]]], [960, 2880, []]),
('partial repair guard 3', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[0, 360], [1800, 2280]]], [480, 840, []]),
('normal control 7', [[[300, 1020], [4260, 4740], [3480, 4200], [1260, 1620], [3060, 3420]]],
[1320, 2640, ['24h']]),
('normal control 8', [[[0, 600], [1080, 1800], [2040, 2640], [3120, 3720]]], [1200, 2520, ['24h']])],
[('regression: daily limit units 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: daily limit units 2', [[[660, 1260], [300, 660]]], [960, 960, []]),
('partial repair guard 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[3720, 4200], [2220, 2820], [300, 780]]], [600, 1560, []]),
('normal control 6', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']]),
('normal control 7', [[[300, 900], [1380, 1860]]], [960, 1080, []]),
('normal control 8',
[[[960, 1680], [6480, 6840], [3360, 3720], [7740, 8340], [5160, 5760], [0, 480], [1920, 2640]]],
[1200, 3840, ['24h', '7d']])],
[('regression: daily limit units 1', [[[2520, 3120], [2100, 2460], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2', [[[300, 660], [2580, 2940], [1140, 1860]]], [960, 1440, []]),
('partial repair guard 3', [[[0, 500], [500, 1000]]], [1000, 1000, ['24h']]),
('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', [[[3120, 3720], [1200, 1800], [1860, 2220], [0, 720]]], [960, 2280, []]),
('normal control 7',
[[[4380, 4740], [6180, 6540], [300, 1020], [4980, 5460], [3540, 4140], [2460, 3060], [7440, 7800]]],
[960, 3480, []]),
('normal control 8',
[[[2520, 2880], [7080, 7680], [0, 600], [4800, 5280], [6000, 6360], [600, 1080], [3600, 4320]]],
[1080, 3600, ['24h']])],
[('regression: daily limit units 1',
[[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]], [960, 3000, []]),
('regression variant: daily limit units 2', [[[300, 660], [900, 1500]]], [960, 960, []]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['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',
[[[1200, 1800], [480, 1200], [0, 480], [4500, 5220], [7140, 7620], [2880, 3600], [5940, 6420],
[2280, 2880]]],
[1440, 4800, ['24h', '7d']]),
('normal control 7', [[[4140, 4620], [1800, 2520], [0, 360], [2760, 3240]]], [1200, 2040, ['24h']]),
('normal control 8', [[[300, 780], [840, 1560]]], [1200, 1200, ['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: daily limit units 1 | [960, 960, []] | [960, 960, []] | Passed |
| regression variant: daily limit units 2 | [960, 3840, ['7d']] | [960, 3840, ['7d']] | Passed |
| partial repair guard 3 | [1000, 1000, []] | [1000, 1000, ['24h']] | Failed |
| boundary control 4 | [920, 980, []] | [920, 980, []] | Passed |
| normal control 5 | [1380, 3120, ['24h']] | [1380, 3120, ['24h']] | Passed |
| normal control 6 | [960, 1920, []] | [960, 1920, []] | Passed |
| normal control 7 | [1200, 2760, ['24h']] | [1200, 2760, ['24h']] | Passed |
| normal control 8 | [1200, 2400, ['24h']] | [1200, 2400, ['24h']] | Passed |
SHA-256 / 808ed4c1b0a4f212b30a5a2d1a39385b049eb5c2f4016be03e2f4e02fa3611c3
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: daily limit units 1', [[[0, 480], [480, 960]]], [960, 960, []]),
('regression variant: daily limit units 2',
[[[1740, 2340], [540, 1020], [2820, 3420], [4140, 4620], [5100, 5700], [7140, 7740], [0, 480]]],
[960, 3840, ['7d']]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 4', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 5', [[[1260, 1980], [780, 1260], [2700, 3300], [0, 720], [3540, 4140]]],
[1380, 3120, ['24h']]),
('normal control 6', [[[300, 780], [3600, 4080], [4140, 4620], [1680, 2160]]], [960, 1920, []]),
('normal control 7', [[[3060, 3660], [2400, 3000], [3900, 4260], [0, 480], [960, 1680]]],
[1200, 2760, ['24h']]),
('normal control 8', [[[2460, 3060], [300, 780], [3540, 4140], [1020, 1740]]], [1200, 2400, ['24h']])],
[('regression: daily limit units 1', [[[2220, 2580], [1560, 2160], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2',
[[[4020, 4740], [300, 660], [6600, 7080], [2820, 3300], [5640, 6120], [1560, 1920]]], [960, 2880, []]),
('partial repair guard 3', [[[0, 1010]]], [1010, 1010, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('boundary control 5', [[[1000, 1500], [0, 480]]], [920, 980, []]),
('normal control 6', [[[0, 360], [1800, 2280]]], [480, 840, []]),
('normal control 7', [[[300, 1020], [4260, 4740], [3480, 4200], [1260, 1620], [3060, 3420]]],
[1320, 2640, ['24h']]),
('normal control 8', [[[0, 600], [1080, 1800], [2040, 2640], [3120, 3720]]], [1200, 2520, ['24h']])],
[('regression: daily limit units 1', [[[300, 900], [1380, 1740]]], [960, 960, []]),
('regression variant: daily limit units 2', [[[660, 1260], [300, 660]]], [960, 960, []]),
('partial repair guard 3', [[[0, 480], [480, 961]]], [961, 961, ['24h']]),
('boundary control 4', [[[100, 700], [900, 1300]]], [1000, 1000, ['24h']]),
('normal control 5', [[[3720, 4200], [2220, 2820], [300, 780]]], [600, 1560, []]),
('normal control 6', [[[4680, 5280], [3960, 4440], [2640, 3240], [1440, 1920], [0, 720], [5520, 6240]]],
[1200, 3600, ['24h']]),
('normal control 7', [[[300, 900], [1380, 1860]]], [960, 1080, []]),
('normal control 8',
[[[960, 1680], [6480, 6840], [3360, 3720], [7740, 8340], [5160, 5760], [0, 480], [1920, 2640]]],
[1200, 3840, ['24h', '7d']])],
[('regression: daily limit units 1', [[[2520, 3120], [2100, 2460], [300, 660]]], [960, 1320, []]),
('regression variant: daily limit units 2', [[[300, 660], [2580, 2940], [1140, 1860]]], [960, 1440, []]),
('partial repair guard 3', [[[0, 500], [500, 1000]]], [1000, 1000, ['24h']]),
('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', [[[3120, 3720], [1200, 1800], [1860, 2220], [0, 720]]], [960, 2280, []]),
('normal control 7',
[[[4380, 4740], [6180, 6540], [300, 1020], [4980, 5460], [3540, 4140], [2460, 3060], [7440, 7800]]],
[960, 3480, []]),
('normal control 8',
[[[2520, 2880], [7080, 7680], [0, 600], [4800, 5280], [6000, 6360], [600, 1080], [3600, 4320]]],
[1080, 3600, ['24h']])],
[('regression: daily limit units 1',
[[[5700, 6180], [3960, 4320], [4380, 4980], [0, 480], [1920, 2400], [2880, 3480]]], [960, 3000, []]),
('regression variant: daily limit units 2', [[[300, 660], [900, 1500]]], [960, 960, []]),
('partial repair guard 3', [[[100, 700], [900, 1300]]], [1000, 1000, ['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',
[[[1200, 1800], [480, 1200], [0, 480], [4500, 5220], [7140, 7620], [2880, 3600], [5940, 6420],
[2280, 2880]]],
[1440, 4800, ['24h', '7d']]),
('normal control 7', [[[4140, 4620], [1800, 2520], [0, 360], [2760, 3240]]], [1200, 2040, ['24h']]),
('normal control 8', [[[300, 780], [840, 1560]]], [1200, 1200, ['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: daily limit units 1 | [960, 960, []] | [960, 960, []] | Passed |
| regression variant: daily limit units 2 | [960, 3840, ['7d']] | [960, 3840, ['7d']] | Passed |
| partial repair guard 3 | [1000, 1000, ['24h']] | [1000, 1000, ['24h']] | Passed |
| boundary control 4 | [920, 980, []] | [920, 980, []] | Passed |
| normal control 5 | [1380, 3120, ['24h']] | [1380, 3120, ['24h']] | Passed |
| normal control 6 | [960, 1920, []] | [960, 1920, []] | Passed |
| normal control 7 | [1200, 2760, ['24h']] | [1200, 2760, ['24h']] | Passed |
| normal control 8 | [1200, 2400, ['24h']] | [1200, 2400, ['24h']] | Passed |
SHA-256 / a0b548183ead4a487c3ea5725a0edde3a002d32135b5a1c9a5eb9973eb352fb6
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.366511+00:00.
Case digest / 330ae337335a1af2802d360ebeaacf915d43284232a61c459336ddc9d0190b96