FAILURE MAP
← Case archive

FA-94131 / Shift rostering labor rules / Open access

Accrual fraction discarded every period · case 01

Part-time workers systematically lose leave minutes over a year.

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

ROOT CAUSE

The sub-minute remainder is reset each period instead of carried.

VERIFIED REPAIR

Carry the full remainder of the running numerator.

Unsuccessful approach: Carrying only this period's remainder drops the previously carried fraction.

Case contract

Per pay period [worked minutes, leave minutes requested]. Accrual is worked * rate_bp / 10000 minutes with the fractional remainder (in 1/10000 minutes) carried to later periods. After accrual the balance is capped (excess forfeited), then the request is approved up to the balance; unapproved minutes accumulate. Return [balance, forfeited, unapproved].

Why this case matters

Leave accrual ledgers attached to rosters must carry fractions and apply caps in the right order.

1 / The failure

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

N = 1
observations = []
def solve(periods, rate_bp, cap):
    bal = carry = forfeit = unappr = 0
    for worked, used in periods:
        num = worked * rate_bp + carry
        bal += num // 10000
        carry = 0
        if bal > cap:
            forfeit += bal - cap
            bal = cap
        take = min(used, bal)
        unappr += used - take
        bal -= take
    return [bal, forfeit, unappr]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: fraction carry 1', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('regression variant: fraction carry 2',
   [[[0, 0], [1200, 2000], [2400, 2000], [2280, 0], [2700, 240], [1376, 480], [2700, 480]], 833, 11200],
   [0, 0, 4146]),
  ('partial repair guard 3', [[[0, 0], [1200, 240], [714, 0], [2280, 0], [2697, 2000]], 769, 1200],
   [0, 0, 1711]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 5', [[[2700, 0], [1200, 2000], [480, 0]], 1207, 600], [58, 0, 1530]),
  ('normal control 6', [[[2400, 900], [2280, 900], [2700, 2000], [2916, 0], [0, 0]], 1000, 600],
   [291, 0, 3062]),
  ('normal control 7', [[[0, 240], [2400, 240]], 833, 400], [0, 0, 281]),
  ('normal control 8', [[[1405, 900], [2621, 2000]], 1207, 400], [0, 0, 2415])],
 [('regression: fraction carry 1', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('regression variant: fraction carry 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200], [0, 0, 1871]),
  ('partial repair guard 3', [[[2700, 480], [2280, 900], [2400, 0], [0, 240]], 769, 11200], [0, 0, 1053]),
  ('boundary control 4', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('boundary control 5', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 6', [[[2280, 0], [2280, 2000]], 1207, 600], [0, 0, 1450]),
  ('normal control 7', [[[1417, 480], [2700, 900]], 1000, 400], [0, 0, 969]),
  ('normal control 8', [[[2446, 480], [1200, 900], [1200, 240], [1200, 2000], [1200, 2000]], 1000, 600],
   [0, 0, 4896])],
 [('regression: fraction carry 1', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('regression variant: fraction carry 2', [[[2700, 0], [0, 900], [24, 0], [2412, 0]], 1207, 1200],
   [294, 0, 575]),
  ('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
  ('boundary control 4', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('boundary control 5', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('normal control 6',
   [[[2400, 2000], [1200, 480], [2400, 0], [2922, 240], [2400, 480], [0, 2000]], 1207, 600], [0, 92, 3926]),
  ('normal control 7',
   [[[2400, 2000], [1936, 480], [2700, 480], [2280, 480], [2400, 0], [2700, 0]], 769, 1200], [392, 0, 2724]),
  ('normal control 8', [[[2700, 2000], [2400, 2000], [2700, 0]], 1000, 11200], [270, 0, 3490])],
 [('regression: fraction carry 1',
   [[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
   [540, 0, 1969]),
  ('regression variant: fraction carry 2',
   [[[1200, 0], [2280, 900], [2429, 2000], [2669, 2000], [2700, 240], [1917, 2000], [2400, 2000], [2700, 0]],
    1000, 600],
   [270, 0, 7581]),
  ('partial repair guard 3',
   [[[2400, 0], [2700, 0], [1200, 480], [1200, 0], [2400, 0], [2280, 0]], 769, 1200], [456, 0, 0]),
  ('boundary control 4', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('normal control 6', [[[0, 480], [1645, 0], [2298, 0], [1507, 480]], 833, 11200], [0, 0, 507]),
  ('normal control 7',
   [[[2280, 480], [1200, 2000], [2280, 480], [2280, 0], [2400, 480], [2700, 480], [635, 2000]], 769, 11200],
   [0, 0, 4861]),
  ('normal control 8', [[[2280, 0], [0, 240]], 1207, 400], [35, 0, 0])],
 [('regression: fraction carry 1', [[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400],
   [290, 188, 3600]),
  ('regression variant: fraction carry 2',
   [[[0, 480], [2280, 0], [0, 480], [2280, 240], [1200, 0], [1200, 0], [2700, 240]], 1207, 11200],
   [410, 0, 685]),
  ('partial repair guard 3',
   [[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
   [22, 0, 1261]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('normal control 6',
   [[[2700, 240], [2700, 0], [2700, 2000], [2400, 480], [2280, 240], [2280, 0], [0, 900]], 769, 600],
   [0, 0, 2702]),
  ('normal control 7', [[[2638, 480], [1838, 2000], [1200, 0]], 1207, 600], [145, 0, 1940]),
  ('normal control 8', [[[97, 0], [1572, 2000], [1847, 900], [0, 240], [0, 480], [0, 0]], 833, 1200],
   [0, 0, 3328])]]
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: fraction carry 1[867, 0, 0][869, 0, 0]Failed
regression variant: fraction carry 2[0, 0, 4151][0, 0, 4146]Failed
partial repair guard 3[0, 0, 1712][0, 0, 1711]Failed
boundary control 4[99, 0, 0][100, 0, 0]Failed
normal control 5[57, 0, 1531][58, 0, 1530]Failed
normal control 6[291, 0, 3062][291, 0, 3062]Passed
normal control 7[0, 0, 281][0, 0, 281]Passed
normal control 8[0, 0, 2415][0, 0, 2415]Passed

SHA-256 / a9c4aa9312cfe9da0d392f30864adf0a872bced1ccde17aa91f5e1f0659cf266

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(periods, rate_bp, cap):
    bal = carry = forfeit = unappr = 0
    for worked, used in periods:
        num = worked * rate_bp + carry
        bal += num // 10000
        carry = worked * rate_bp % 10000
        if bal > cap:
            forfeit += bal - cap
            bal = cap
        take = min(used, bal)
        unappr += used - take
        bal -= take
    return [bal, forfeit, unappr]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: fraction carry 1', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('regression variant: fraction carry 2',
   [[[0, 0], [1200, 2000], [2400, 2000], [2280, 0], [2700, 240], [1376, 480], [2700, 480]], 833, 11200],
   [0, 0, 4146]),
  ('partial repair guard 3', [[[0, 0], [1200, 240], [714, 0], [2280, 0], [2697, 2000]], 769, 1200],
   [0, 0, 1711]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 5', [[[2700, 0], [1200, 2000], [480, 0]], 1207, 600], [58, 0, 1530]),
  ('normal control 6', [[[2400, 900], [2280, 900], [2700, 2000], [2916, 0], [0, 0]], 1000, 600],
   [291, 0, 3062]),
  ('normal control 7', [[[0, 240], [2400, 240]], 833, 400], [0, 0, 281]),
  ('normal control 8', [[[1405, 900], [2621, 2000]], 1207, 400], [0, 0, 2415])],
 [('regression: fraction carry 1', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('regression variant: fraction carry 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200], [0, 0, 1871]),
  ('partial repair guard 3', [[[2700, 480], [2280, 900], [2400, 0], [0, 240]], 769, 11200], [0, 0, 1053]),
  ('boundary control 4', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('boundary control 5', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 6', [[[2280, 0], [2280, 2000]], 1207, 600], [0, 0, 1450]),
  ('normal control 7', [[[1417, 480], [2700, 900]], 1000, 400], [0, 0, 969]),
  ('normal control 8', [[[2446, 480], [1200, 900], [1200, 240], [1200, 2000], [1200, 2000]], 1000, 600],
   [0, 0, 4896])],
 [('regression: fraction carry 1', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('regression variant: fraction carry 2', [[[2700, 0], [0, 900], [24, 0], [2412, 0]], 1207, 1200],
   [294, 0, 575]),
  ('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
  ('boundary control 4', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('boundary control 5', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('normal control 6',
   [[[2400, 2000], [1200, 480], [2400, 0], [2922, 240], [2400, 480], [0, 2000]], 1207, 600], [0, 92, 3926]),
  ('normal control 7',
   [[[2400, 2000], [1936, 480], [2700, 480], [2280, 480], [2400, 0], [2700, 0]], 769, 1200], [392, 0, 2724]),
  ('normal control 8', [[[2700, 2000], [2400, 2000], [2700, 0]], 1000, 11200], [270, 0, 3490])],
 [('regression: fraction carry 1',
   [[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
   [540, 0, 1969]),
  ('regression variant: fraction carry 2',
   [[[1200, 0], [2280, 900], [2429, 2000], [2669, 2000], [2700, 240], [1917, 2000], [2400, 2000], [2700, 0]],
    1000, 600],
   [270, 0, 7581]),
  ('partial repair guard 3',
   [[[2400, 0], [2700, 0], [1200, 480], [1200, 0], [2400, 0], [2280, 0]], 769, 1200], [456, 0, 0]),
  ('boundary control 4', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('normal control 6', [[[0, 480], [1645, 0], [2298, 0], [1507, 480]], 833, 11200], [0, 0, 507]),
  ('normal control 7',
   [[[2280, 480], [1200, 2000], [2280, 480], [2280, 0], [2400, 480], [2700, 480], [635, 2000]], 769, 11200],
   [0, 0, 4861]),
  ('normal control 8', [[[2280, 0], [0, 240]], 1207, 400], [35, 0, 0])],
 [('regression: fraction carry 1', [[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400],
   [290, 188, 3600]),
  ('regression variant: fraction carry 2',
   [[[0, 480], [2280, 0], [0, 480], [2280, 240], [1200, 0], [1200, 0], [2700, 240]], 1207, 11200],
   [410, 0, 685]),
  ('partial repair guard 3',
   [[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
   [22, 0, 1261]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('normal control 6',
   [[[2700, 240], [2700, 0], [2700, 2000], [2400, 480], [2280, 240], [2280, 0], [0, 900]], 769, 600],
   [0, 0, 2702]),
  ('normal control 7', [[[2638, 480], [1838, 2000], [1200, 0]], 1207, 600], [145, 0, 1940]),
  ('normal control 8', [[[97, 0], [1572, 2000], [1847, 900], [0, 240], [0, 480], [0, 0]], 833, 1200],
   [0, 0, 3328])]]
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: fraction carry 1[869, 0, 0][869, 0, 0]Passed
regression variant: fraction carry 2[0, 0, 4146][0, 0, 4146]Passed
partial repair guard 3[0, 0, 1710][0, 0, 1711]Failed
boundary control 4[100, 0, 0][100, 0, 0]Passed
normal control 5[58, 0, 1530][58, 0, 1530]Passed
normal control 6[291, 0, 3062][291, 0, 3062]Passed
normal control 7[0, 0, 281][0, 0, 281]Passed
normal control 8[0, 0, 2415][0, 0, 2415]Passed

SHA-256 / aff77825a5d17f62d7346587e2c33ee7e12f553ae4a6fcf75b04f7bd8a0d7b79

3 / The verified repair

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

N = 1
observations = []
def solve(periods, rate_bp, cap):
    bal = carry = forfeit = unappr = 0
    for worked, used in periods:
        num = worked * rate_bp + carry
        bal += num // 10000
        carry = num % 10000
        if bal > cap:
            forfeit += bal - cap
            bal = cap
        take = min(used, bal)
        unappr += used - take
        bal -= take
    return [bal, forfeit, unappr]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: fraction carry 1', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('regression variant: fraction carry 2',
   [[[0, 0], [1200, 2000], [2400, 2000], [2280, 0], [2700, 240], [1376, 480], [2700, 480]], 833, 11200],
   [0, 0, 4146]),
  ('partial repair guard 3', [[[0, 0], [1200, 240], [714, 0], [2280, 0], [2697, 2000]], 769, 1200],
   [0, 0, 1711]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 5', [[[2700, 0], [1200, 2000], [480, 0]], 1207, 600], [58, 0, 1530]),
  ('normal control 6', [[[2400, 900], [2280, 900], [2700, 2000], [2916, 0], [0, 0]], 1000, 600],
   [291, 0, 3062]),
  ('normal control 7', [[[0, 240], [2400, 240]], 833, 400], [0, 0, 281]),
  ('normal control 8', [[[1405, 900], [2621, 2000]], 1207, 400], [0, 0, 2415])],
 [('regression: fraction carry 1', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('regression variant: fraction carry 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200], [0, 0, 1871]),
  ('partial repair guard 3', [[[2700, 480], [2280, 900], [2400, 0], [0, 240]], 769, 11200], [0, 0, 1053]),
  ('boundary control 4', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('boundary control 5', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('normal control 6', [[[2280, 0], [2280, 2000]], 1207, 600], [0, 0, 1450]),
  ('normal control 7', [[[1417, 480], [2700, 900]], 1000, 400], [0, 0, 969]),
  ('normal control 8', [[[2446, 480], [1200, 900], [1200, 240], [1200, 2000], [1200, 2000]], 1000, 600],
   [0, 0, 4896])],
 [('regression: fraction carry 1', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('regression variant: fraction carry 2', [[[2700, 0], [0, 900], [24, 0], [2412, 0]], 1207, 1200],
   [294, 0, 575]),
  ('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
  ('boundary control 4', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('boundary control 5', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
  ('normal control 6',
   [[[2400, 2000], [1200, 480], [2400, 0], [2922, 240], [2400, 480], [0, 2000]], 1207, 600], [0, 92, 3926]),
  ('normal control 7',
   [[[2400, 2000], [1936, 480], [2700, 480], [2280, 480], [2400, 0], [2700, 0]], 769, 1200], [392, 0, 2724]),
  ('normal control 8', [[[2700, 2000], [2400, 2000], [2700, 0]], 1000, 11200], [270, 0, 3490])],
 [('regression: fraction carry 1',
   [[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
   [540, 0, 1969]),
  ('regression variant: fraction carry 2',
   [[[1200, 0], [2280, 900], [2429, 2000], [2669, 2000], [2700, 240], [1917, 2000], [2400, 2000], [2700, 0]],
    1000, 600],
   [270, 0, 7581]),
  ('partial repair guard 3',
   [[[2400, 0], [2700, 0], [1200, 480], [1200, 0], [2400, 0], [2280, 0]], 769, 1200], [456, 0, 0]),
  ('boundary control 4', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 500]], 1207, 400], [0, 179, 100]),
  ('normal control 6', [[[0, 480], [1645, 0], [2298, 0], [1507, 480]], 833, 11200], [0, 0, 507]),
  ('normal control 7',
   [[[2280, 480], [1200, 2000], [2280, 480], [2280, 0], [2400, 480], [2700, 480], [635, 2000]], 769, 11200],
   [0, 0, 4861]),
  ('normal control 8', [[[2280, 0], [0, 240]], 1207, 400], [35, 0, 0])],
 [('regression: fraction carry 1', [[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400],
   [290, 188, 3600]),
  ('regression variant: fraction carry 2',
   [[[0, 480], [2280, 0], [0, 480], [2280, 240], [1200, 0], [1200, 0], [2700, 240]], 1207, 11200],
   [410, 0, 685]),
  ('partial repair guard 3',
   [[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
   [22, 0, 1261]),
  ('boundary control 4', [[[99, 0], [99, 0], [2, 0]], 5000, 100], [100, 0, 0]),
  ('boundary control 5', [[[2400, 0], [2400, 0], [2400, 0]], 1207, 11200], [869, 0, 0]),
  ('normal control 6',
   [[[2700, 240], [2700, 0], [2700, 2000], [2400, 480], [2280, 240], [2280, 0], [0, 900]], 769, 600],
   [0, 0, 2702]),
  ('normal control 7', [[[2638, 480], [1838, 2000], [1200, 0]], 1207, 600], [145, 0, 1940]),
  ('normal control 8', [[[97, 0], [1572, 2000], [1847, 900], [0, 240], [0, 480], [0, 0]], 833, 1200],
   [0, 0, 3328])]]
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: fraction carry 1[869, 0, 0][869, 0, 0]Passed
regression variant: fraction carry 2[0, 0, 4146][0, 0, 4146]Passed
partial repair guard 3[0, 0, 1711][0, 0, 1711]Passed
boundary control 4[100, 0, 0][100, 0, 0]Passed
normal control 5[58, 0, 1530][58, 0, 1530]Passed
normal control 6[291, 0, 3062][291, 0, 3062]Passed
normal control 7[0, 0, 281][0, 0, 281]Passed
normal control 8[0, 0, 2415][0, 0, 2415]Passed

SHA-256 / 62e66c6e92f6d53663c94eff65af15cd74473251054fec19dccdbb214cbe7835

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

Case digest / f4f968a78a1e6f0a07740649de73fd3000c52bd75ad63fdb2fab9d9f8bd96f72