FAILURE MAP
← Case archive

FA-93981 / Shift rostering labor rules / Open access

Long callback truncated at the minimum guarantee · case 01

A four-hour callback is paid only three hours.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The window end ignores callbacks longer than the guarantee.

VERIFIED REPAIR

Window end is the later of callback end and start plus guarantee.

Unsuccessful approach: Adding the guarantee after the callback end overpays every callback.

Case contract

Callback work intervals [start, end] and a minimum guarantee in minutes. Sorted by start, each callback that does not start inside the current guarantee window opens a new window from its start to max(end, start + guarantee); a callback starting before the window end extends the window to its own end if later. Return [paid minutes as the sum of window lengths, window count].

Why this case matters

Callback and show-up minimum-pay rules routinely double pay or underpay when callbacks cluster.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(callbacks, guarantee):
    paid = 0
    windows = 0
    win_start = win_end = None
    for s, e in sorted(callbacks):
        if win_end is not None and s < win_end:
            win_end = max(win_end, e)
        else:
            if win_end is not None:
                paid += win_end - win_start
            win_start, win_end = s, s + guarantee
            windows += 1
    if win_end is not None:
        paid += win_end - win_start
    return [paid, windows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: guarantee floor 1', [[[0, 240]], 180], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1819, 1939], [1640, 1760], [1400, 1640]], 180], [539, 2]),
  ('partial repair guard 3', [[[1550, 1580], [2180, 2210], [1580, 1780], [1400, 1520]], 120], [470, 3]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]),
  ('normal control 5', [[[100, 300], [400, 520], [579, 609], [758, 998]], 120], [680, 4]),
  ('normal control 6', [[[240, 300], [0, 30], [330, 390]], 120], [270, 2]),
  ('normal control 7', [[[0, 200], [361, 421], [180, 380]], 120], [421, 1]),
  ('normal control 8', [[[190, 430], [100, 340]], 180], [330, 1])],
 [('regression: guarantee floor 1', [[[0, 30], [481, 601], [181, 381], [661, 691]], 120], [560, 4]),
  ('regression variant: guarantee floor 2', [[[100, 130], [1120, 1150], [880, 1120], [700, 715]], 180],
   [780, 4]),
  ('partial repair guard 3', [[[1430, 1490], [1400, 1430]], 240], [240, 1]),
  ('boundary control 4', [[], 180], [0, 0]), ('boundary control 5', [[[0, 30], [60, 400]], 180], [400, 1]),
  ('normal control 6', [[[0, 120], [181, 301]], 120], [240, 2]),
  ('normal control 7', [[[1640, 1880], [1400, 1460]], 120], [360, 2]),
  ('normal control 8', [[[100, 300], [220, 250], [190, 220]], 180], [200, 1])],
 [('regression: guarantee floor 1', [[[1580, 1595], [1760, 1960], [1400, 1460]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[340, 370], [700, 820], [100, 130], [519, 719]], 120],
   [541, 3]),
  ('partial repair guard 3', [[[100, 340]], 120], [240, 1]),
  ('boundary control 4', [[[0, 30], [179, 200]], 180], [200, 1]),
  ('boundary control 5', [[[0, 30]], 180], [180, 1]),
  ('normal control 6', [[[1579, 1699], [1759, 1774], [1400, 1430]], 240], [539, 2]),
  ('normal control 7', [[[100, 300]], 120], [200, 1]),
  ('normal control 8', [[[0, 120], [211, 241], [392, 452], [30, 230]], 120], [361, 2])],
 [('regression: guarantee floor 1', [[[100, 130], [340, 460], [521, 721]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[1400, 1600], [2000, 2240]], 120], [440, 2]),
  ('partial repair guard 3', [[[160, 280], [760, 820], [130, 250], [100, 340]], 120], [360, 2]),
  ('boundary control 4', [[[300, 330], [0, 30]], 180], [360, 2]),
  ('boundary control 5', [[[0, 240]], 180], [240, 1]),
  ('normal control 6', [[[1400, 1520], [1550, 1580], [1640, 1670]], 240], [480, 2]),
  ('normal control 7', [[[1640, 1700], [1400, 1640], [1670, 1700]], 180], [420, 2]),
  ('normal control 8', [[[1400, 1600], [2271, 2286], [1581, 1596], [1671, 1791]], 120], [440, 3])],
 [('regression: guarantee floor 1', [[[100, 340]], 120], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1400, 1415], [1940, 2180], [1640, 1880], [2030, 2270]], 120],
   [690, 3]),
  ('partial repair guard 3', [[[280, 295], [880, 1120], [100, 340]], 120], [480, 2]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]), ('boundary control 5', [[], 180], [0, 0]),
  ('normal control 6', [[[100, 300], [281, 341], [762, 962], [581, 821]], 240], [622, 2]),
  ('normal control 7', [[[1400, 1460], [1640, 1670]], 180], [360, 2]),
  ('normal control 8', [[[310, 510], [130, 190], [491, 731], [100, 115]], 240], [631, 1])]]
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 fixtureActualExpectedOutcome
regression: guarantee floor 1[180, 1][240, 1]Failed
regression variant: guarantee floor 2[479, 2][539, 2]Failed
partial repair guard 3[470, 3][470, 3]Passed
boundary control 4[360, 2][360, 2]Passed
normal control 5[480, 4][680, 4]Failed
normal control 6[270, 2][270, 2]Passed
normal control 7[360, 3][421, 1]Failed
normal control 8[330, 1][330, 1]Passed

SHA-256 / 05368f49c9e09c48ad725e6c9c031bc97f388c6902777c99d1f7028142a069ae

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(callbacks, guarantee):
    paid = 0
    windows = 0
    win_start = win_end = None
    for s, e in sorted(callbacks):
        if win_end is not None and s < win_end:
            win_end = max(win_end, e)
        else:
            if win_end is not None:
                paid += win_end - win_start
            win_start, win_end = s, e + guarantee
            windows += 1
    if win_end is not None:
        paid += win_end - win_start
    return [paid, windows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: guarantee floor 1', [[[0, 240]], 180], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1819, 1939], [1640, 1760], [1400, 1640]], 180], [539, 2]),
  ('partial repair guard 3', [[[1550, 1580], [2180, 2210], [1580, 1780], [1400, 1520]], 120], [470, 3]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]),
  ('normal control 5', [[[100, 300], [400, 520], [579, 609], [758, 998]], 120], [680, 4]),
  ('normal control 6', [[[240, 300], [0, 30], [330, 390]], 120], [270, 2]),
  ('normal control 7', [[[0, 200], [361, 421], [180, 380]], 120], [421, 1]),
  ('normal control 8', [[[190, 430], [100, 340]], 180], [330, 1])],
 [('regression: guarantee floor 1', [[[0, 30], [481, 601], [181, 381], [661, 691]], 120], [560, 4]),
  ('regression variant: guarantee floor 2', [[[100, 130], [1120, 1150], [880, 1120], [700, 715]], 180],
   [780, 4]),
  ('partial repair guard 3', [[[1430, 1490], [1400, 1430]], 240], [240, 1]),
  ('boundary control 4', [[], 180], [0, 0]), ('boundary control 5', [[[0, 30], [60, 400]], 180], [400, 1]),
  ('normal control 6', [[[0, 120], [181, 301]], 120], [240, 2]),
  ('normal control 7', [[[1640, 1880], [1400, 1460]], 120], [360, 2]),
  ('normal control 8', [[[100, 300], [220, 250], [190, 220]], 180], [200, 1])],
 [('regression: guarantee floor 1', [[[1580, 1595], [1760, 1960], [1400, 1460]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[340, 370], [700, 820], [100, 130], [519, 719]], 120],
   [541, 3]),
  ('partial repair guard 3', [[[100, 340]], 120], [240, 1]),
  ('boundary control 4', [[[0, 30], [179, 200]], 180], [200, 1]),
  ('boundary control 5', [[[0, 30]], 180], [180, 1]),
  ('normal control 6', [[[1579, 1699], [1759, 1774], [1400, 1430]], 240], [539, 2]),
  ('normal control 7', [[[100, 300]], 120], [200, 1]),
  ('normal control 8', [[[0, 120], [211, 241], [392, 452], [30, 230]], 120], [361, 2])],
 [('regression: guarantee floor 1', [[[100, 130], [340, 460], [521, 721]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[1400, 1600], [2000, 2240]], 120], [440, 2]),
  ('partial repair guard 3', [[[160, 280], [760, 820], [130, 250], [100, 340]], 120], [360, 2]),
  ('boundary control 4', [[[300, 330], [0, 30]], 180], [360, 2]),
  ('boundary control 5', [[[0, 240]], 180], [240, 1]),
  ('normal control 6', [[[1400, 1520], [1550, 1580], [1640, 1670]], 240], [480, 2]),
  ('normal control 7', [[[1640, 1700], [1400, 1640], [1670, 1700]], 180], [420, 2]),
  ('normal control 8', [[[1400, 1600], [2271, 2286], [1581, 1596], [1671, 1791]], 120], [440, 3])],
 [('regression: guarantee floor 1', [[[100, 340]], 120], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1400, 1415], [1940, 2180], [1640, 1880], [2030, 2270]], 120],
   [690, 3]),
  ('partial repair guard 3', [[[280, 295], [880, 1120], [100, 340]], 120], [480, 2]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]), ('boundary control 5', [[], 180], [0, 0]),
  ('normal control 6', [[[100, 300], [281, 341], [762, 962], [581, 821]], 240], [622, 2]),
  ('normal control 7', [[[1400, 1460], [1640, 1670]], 180], [360, 2]),
  ('normal control 8', [[[310, 510], [130, 190], [491, 731], [100, 115]], 240], [631, 1])]]
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 fixtureActualExpectedOutcome
regression: guarantee floor 1[420, 1][240, 1]Failed
regression variant: guarantee floor 2[539, 1][539, 2]Failed
partial repair guard 3[530, 2][470, 3]Failed
boundary control 4[210, 1][360, 2]Failed
normal control 5[930, 3][680, 4]Failed
normal control 6[330, 2][270, 2]Failed
normal control 7[421, 1][421, 1]Passed
normal control 8[420, 1][330, 1]Failed

SHA-256 / 3d1ec8d0b774f95280c5252f4947c0153013a3ceeed854c6f0f3ac2086a3131d

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(callbacks, guarantee):
    paid = 0
    windows = 0
    win_start = win_end = None
    for s, e in sorted(callbacks):
        if win_end is not None and s < win_end:
            win_end = max(win_end, e)
        else:
            if win_end is not None:
                paid += win_end - win_start
            win_start, win_end = s, max(e, s + guarantee)
            windows += 1
    if win_end is not None:
        paid += win_end - win_start
    return [paid, windows]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: guarantee floor 1', [[[0, 240]], 180], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1819, 1939], [1640, 1760], [1400, 1640]], 180], [539, 2]),
  ('partial repair guard 3', [[[1550, 1580], [2180, 2210], [1580, 1780], [1400, 1520]], 120], [470, 3]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]),
  ('normal control 5', [[[100, 300], [400, 520], [579, 609], [758, 998]], 120], [680, 4]),
  ('normal control 6', [[[240, 300], [0, 30], [330, 390]], 120], [270, 2]),
  ('normal control 7', [[[0, 200], [361, 421], [180, 380]], 120], [421, 1]),
  ('normal control 8', [[[190, 430], [100, 340]], 180], [330, 1])],
 [('regression: guarantee floor 1', [[[0, 30], [481, 601], [181, 381], [661, 691]], 120], [560, 4]),
  ('regression variant: guarantee floor 2', [[[100, 130], [1120, 1150], [880, 1120], [700, 715]], 180],
   [780, 4]),
  ('partial repair guard 3', [[[1430, 1490], [1400, 1430]], 240], [240, 1]),
  ('boundary control 4', [[], 180], [0, 0]), ('boundary control 5', [[[0, 30], [60, 400]], 180], [400, 1]),
  ('normal control 6', [[[0, 120], [181, 301]], 120], [240, 2]),
  ('normal control 7', [[[1640, 1880], [1400, 1460]], 120], [360, 2]),
  ('normal control 8', [[[100, 300], [220, 250], [190, 220]], 180], [200, 1])],
 [('regression: guarantee floor 1', [[[1580, 1595], [1760, 1960], [1400, 1460]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[340, 370], [700, 820], [100, 130], [519, 719]], 120],
   [541, 3]),
  ('partial repair guard 3', [[[100, 340]], 120], [240, 1]),
  ('boundary control 4', [[[0, 30], [179, 200]], 180], [200, 1]),
  ('boundary control 5', [[[0, 30]], 180], [180, 1]),
  ('normal control 6', [[[1579, 1699], [1759, 1774], [1400, 1430]], 240], [539, 2]),
  ('normal control 7', [[[100, 300]], 120], [200, 1]),
  ('normal control 8', [[[0, 120], [211, 241], [392, 452], [30, 230]], 120], [361, 2])],
 [('regression: guarantee floor 1', [[[100, 130], [340, 460], [521, 721]], 120], [440, 3]),
  ('regression variant: guarantee floor 2', [[[1400, 1600], [2000, 2240]], 120], [440, 2]),
  ('partial repair guard 3', [[[160, 280], [760, 820], [130, 250], [100, 340]], 120], [360, 2]),
  ('boundary control 4', [[[300, 330], [0, 30]], 180], [360, 2]),
  ('boundary control 5', [[[0, 240]], 180], [240, 1]),
  ('normal control 6', [[[1400, 1520], [1550, 1580], [1640, 1670]], 240], [480, 2]),
  ('normal control 7', [[[1640, 1700], [1400, 1640], [1670, 1700]], 180], [420, 2]),
  ('normal control 8', [[[1400, 1600], [2271, 2286], [1581, 1596], [1671, 1791]], 120], [440, 3])],
 [('regression: guarantee floor 1', [[[100, 340]], 120], [240, 1]),
  ('regression variant: guarantee floor 2', [[[1400, 1415], [1940, 2180], [1640, 1880], [2030, 2270]], 120],
   [690, 3]),
  ('partial repair guard 3', [[[280, 295], [880, 1120], [100, 340]], 120], [480, 2]),
  ('boundary control 4', [[[0, 30], [180, 200]], 180], [360, 2]), ('boundary control 5', [[], 180], [0, 0]),
  ('normal control 6', [[[100, 300], [281, 341], [762, 962], [581, 821]], 240], [622, 2]),
  ('normal control 7', [[[1400, 1460], [1640, 1670]], 180], [360, 2]),
  ('normal control 8', [[[310, 510], [130, 190], [491, 731], [100, 115]], 240], [631, 1])]]
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 fixtureActualExpectedOutcome
regression: guarantee floor 1[240, 1][240, 1]Passed
regression variant: guarantee floor 2[539, 2][539, 2]Passed
partial repair guard 3[470, 3][470, 3]Passed
boundary control 4[360, 2][360, 2]Passed
normal control 5[680, 4][680, 4]Passed
normal control 6[270, 2][270, 2]Passed
normal control 7[421, 1][421, 1]Passed
normal control 8[330, 1][330, 1]Passed

SHA-256 / 37f834897d46d19d5309ca2fb90933e763eae312c4c9f087fccea80d3a8f4a2a

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:00.074650+00:00.

Case digest / 4f605554a259e95be036f3eabe4bc0cb7c05e5b0cac908e6467d744f6d946015