FA-94161 / Shift rostering labor rules / Open access
Seventh grace minute after the scheduled end not forgiven · case 01
A punch out exactly seven minutes late is rounded instead of snapping to the schedule.
ROOT CAUSE
The clock-out grace window is strict at seven minutes.
VERIFIED REPAIR
Snap punch outs up to and including seven minutes after the end.
Unsuccessful approach: Widening the grace to 15 minutes hides genuine overtime.
Case contract
Scheduled [start, end] and raw punches in minutes. A punch in at most 7 minutes before the scheduled start is treated as the start; a punch out at most 7 minutes after the scheduled end is treated as the end. Then each time is rounded to the quarter hour: remainder 0-7 down, 8-14 up. Return [in, out, max(out - in, 0)].
Why this case matters
Punch rounding and grace periods must be neutral; asymmetric boundaries systematically underpay.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(sched, punch_in, punch_out):
start, end = sched
def q(t):
r = t % 15
return t - r if r <= 7 else t + 15 - r
i = start if 0 < start - punch_in <= 7 else punch_in
o = end if 0 < punch_out - end < 7 else punch_out
i, o = q(i), q(o)
return [i, o, max(o - i, 0)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: late out grace window 1', [[487, 727], 495, 734], [495, 720, 225]),
('regression variant: late out grace window 2', [[487, 967], 486, 974], [480, 960, 480]),
('partial repair guard 3', [[487, 997], 490, 1006], [495, 1005, 510]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[487, 727], 496, 739], [495, 735, 240]),
('normal control 7', [[600, 1110], 595, 1122], [600, 1125, 525]),
('normal control 8', [[540, 1050], 532, 1051], [525, 1050, 525])],
[('regression: late out grace window 1', [[487, 727], 467, 734], [465, 720, 255]),
('regression variant: late out grace window 2', [[487, 727], 480, 734], [480, 720, 240]),
('partial repair guard 3', [[600, 1080], 595, 1092], [600, 1095, 495]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[600, 1080], 607, 1088], [600, 1095, 495]),
('normal control 7', [[540, 1020], 532, 1032], [525, 1035, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 479, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 727], 495, 734], [495, 720, 225]),
('partial repair guard 3', [[487, 727], 496, 739], [495, 735, 240]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[420, 930], 400, 931], [405, 930, 525]),
('normal control 7', [[540, 1050], 539, 1049], [540, 1050, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 467, 974], [465, 960, 495]),
('regression variant: late out grace window 2', [[487, 727], 467, 734], [465, 720, 255]),
('partial repair guard 3', [[487, 997], 479, 1005], [480, 1005, 525]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[487, 967], 480, 979], [480, 975, 495]),
('normal control 7', [[540, 1050], 532, 1072], [525, 1065, 540]),
('normal control 8', [[600, 840], 614, 862], [615, 855, 240])],
[('regression: late out grace window 1', [[487, 967], 486, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 967], 479, 974], [480, 960, 480]),
('partial repair guard 3', [[420, 660], 413, 672], [420, 675, 255]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[600, 840], 607, 840], [600, 840, 240]),
('normal control 7', [[480, 990], 479, 980], [480, 975, 495]),
('normal control 8', [[487, 727], 467, 734], [465, 720, 255])]]
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: late out grace window 1 | [495, 735, 240] | [495, 720, 225] | Failed |
| regression variant: late out grace window 2 | [480, 975, 495] | [480, 960, 480] | Failed |
| partial repair guard 3 | [495, 1005, 510] | [495, 1005, 510] | Passed |
| boundary control 4 | [495, 945, 450] | [495, 945, 450] | Passed |
| boundary control 5 | [480, 960, 480] | [480, 960, 480] | Passed |
| normal control 6 | [495, 735, 240] | [495, 735, 240] | Passed |
| normal control 7 | [600, 1125, 525] | [600, 1125, 525] | Passed |
| normal control 8 | [525, 1050, 525] | [525, 1050, 525] | Passed |
SHA-256 / 91b87e1cc020405a03a5705e1db52b21ec72856db9f150d85d6ed30c9dcb4d9a
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(sched, punch_in, punch_out):
start, end = sched
def q(t):
r = t % 15
return t - r if r <= 7 else t + 15 - r
i = start if 0 < start - punch_in <= 7 else punch_in
o = end if 0 < punch_out - end <= 15 else punch_out
i, o = q(i), q(o)
return [i, o, max(o - i, 0)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: late out grace window 1', [[487, 727], 495, 734], [495, 720, 225]),
('regression variant: late out grace window 2', [[487, 967], 486, 974], [480, 960, 480]),
('partial repair guard 3', [[487, 997], 490, 1006], [495, 1005, 510]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[487, 727], 496, 739], [495, 735, 240]),
('normal control 7', [[600, 1110], 595, 1122], [600, 1125, 525]),
('normal control 8', [[540, 1050], 532, 1051], [525, 1050, 525])],
[('regression: late out grace window 1', [[487, 727], 467, 734], [465, 720, 255]),
('regression variant: late out grace window 2', [[487, 727], 480, 734], [480, 720, 240]),
('partial repair guard 3', [[600, 1080], 595, 1092], [600, 1095, 495]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[600, 1080], 607, 1088], [600, 1095, 495]),
('normal control 7', [[540, 1020], 532, 1032], [525, 1035, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 479, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 727], 495, 734], [495, 720, 225]),
('partial repair guard 3', [[487, 727], 496, 739], [495, 735, 240]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[420, 930], 400, 931], [405, 930, 525]),
('normal control 7', [[540, 1050], 539, 1049], [540, 1050, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 467, 974], [465, 960, 495]),
('regression variant: late out grace window 2', [[487, 727], 467, 734], [465, 720, 255]),
('partial repair guard 3', [[487, 997], 479, 1005], [480, 1005, 525]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[487, 967], 480, 979], [480, 975, 495]),
('normal control 7', [[540, 1050], 532, 1072], [525, 1065, 540]),
('normal control 8', [[600, 840], 614, 862], [615, 855, 240])],
[('regression: late out grace window 1', [[487, 967], 486, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 967], 479, 974], [480, 960, 480]),
('partial repair guard 3', [[420, 660], 413, 672], [420, 675, 255]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[600, 840], 607, 840], [600, 840, 240]),
('normal control 7', [[480, 990], 479, 980], [480, 975, 495]),
('normal control 8', [[487, 727], 467, 734], [465, 720, 255])]]
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: late out grace window 1 | [495, 720, 225] | [495, 720, 225] | Passed |
| regression variant: late out grace window 2 | [480, 960, 480] | [480, 960, 480] | Passed |
| partial repair guard 3 | [495, 990, 495] | [495, 1005, 510] | Failed |
| boundary control 4 | [495, 945, 450] | [495, 945, 450] | Passed |
| boundary control 5 | [480, 960, 480] | [480, 960, 480] | Passed |
| normal control 6 | [495, 720, 225] | [495, 735, 240] | Failed |
| normal control 7 | [600, 1110, 510] | [600, 1125, 525] | Failed |
| normal control 8 | [525, 1050, 525] | [525, 1050, 525] | Passed |
SHA-256 / 22170296dd311099289f0f9bbd80fbc5c6829227eb1e6c92941900562908d437
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(sched, punch_in, punch_out):
start, end = sched
def q(t):
r = t % 15
return t - r if r <= 7 else t + 15 - r
i = start if 0 < start - punch_in <= 7 else punch_in
o = end if 0 < punch_out - end <= 7 else punch_out
i, o = q(i), q(o)
return [i, o, max(o - i, 0)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: late out grace window 1', [[487, 727], 495, 734], [495, 720, 225]),
('regression variant: late out grace window 2', [[487, 967], 486, 974], [480, 960, 480]),
('partial repair guard 3', [[487, 997], 490, 1006], [495, 1005, 510]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[487, 727], 496, 739], [495, 735, 240]),
('normal control 7', [[600, 1110], 595, 1122], [600, 1125, 525]),
('normal control 8', [[540, 1050], 532, 1051], [525, 1050, 525])],
[('regression: late out grace window 1', [[487, 727], 467, 734], [465, 720, 255]),
('regression variant: late out grace window 2', [[487, 727], 480, 734], [480, 720, 240]),
('partial repair guard 3', [[600, 1080], 595, 1092], [600, 1095, 495]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[600, 1080], 607, 1088], [600, 1095, 495]),
('normal control 7', [[540, 1020], 532, 1032], [525, 1035, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 479, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 727], 495, 734], [495, 720, 225]),
('partial repair guard 3', [[487, 727], 496, 739], [495, 735, 240]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[420, 930], 400, 931], [405, 930, 525]),
('normal control 7', [[540, 1050], 539, 1049], [540, 1050, 510]),
('normal control 8', [[420, 660], 413, 672], [420, 675, 255])],
[('regression: late out grace window 1', [[487, 967], 467, 974], [465, 960, 495]),
('regression variant: late out grace window 2', [[487, 727], 467, 734], [465, 720, 255]),
('partial repair guard 3', [[487, 997], 479, 1005], [480, 1005, 525]),
('boundary control 4', [[480, 960], 473, 967], [480, 960, 480]),
('boundary control 5', [[480, 960], 500, 490], [495, 495, 0]),
('normal control 6', [[487, 967], 480, 979], [480, 975, 495]),
('normal control 7', [[540, 1050], 532, 1072], [525, 1065, 540]),
('normal control 8', [[600, 840], 614, 862], [615, 855, 240])],
[('regression: late out grace window 1', [[487, 967], 486, 974], [480, 960, 480]),
('regression variant: late out grace window 2', [[487, 967], 479, 974], [480, 960, 480]),
('partial repair guard 3', [[420, 660], 413, 672], [420, 675, 255]),
('boundary control 4', [[480, 960], 488, 952], [495, 945, 450]),
('boundary control 5', [[480, 960], 487, 953], [480, 960, 480]),
('normal control 6', [[600, 840], 607, 840], [600, 840, 240]),
('normal control 7', [[480, 990], 479, 980], [480, 975, 495]),
('normal control 8', [[487, 727], 467, 734], [465, 720, 255])]]
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: late out grace window 1 | [495, 720, 225] | [495, 720, 225] | Passed |
| regression variant: late out grace window 2 | [480, 960, 480] | [480, 960, 480] | Passed |
| partial repair guard 3 | [495, 1005, 510] | [495, 1005, 510] | Passed |
| boundary control 4 | [495, 945, 450] | [495, 945, 450] | Passed |
| boundary control 5 | [480, 960, 480] | [480, 960, 480] | Passed |
| normal control 6 | [495, 735, 240] | [495, 735, 240] | Passed |
| normal control 7 | [600, 1125, 525] | [600, 1125, 525] | Passed |
| normal control 8 | [525, 1050, 525] | [525, 1050, 525] | Passed |
SHA-256 / 10cc4fb7a422b239d8e1fafe6c131d076ddfd9f75f91c2b29902b8598d5c4520
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:01.918609+00:00.
Case digest / 1218ad3e7680286d2e31e04d894ae027a56223b6cc369501a7637d07aabeae35