FA-94146 / Shift rostering labor rules / Open access
Unapproved leave total reset each period · case 01
Only the last period's unapproved minutes are reported.
ROOT CAUSE
The unapproved counter is assigned instead of accumulated.
VERIFIED REPAIR
Accumulate unapproved minutes across periods.
Unsuccessful approach: Skipping periods with zero approval loses fully denied requests.
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 = 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: unapproved accumulation 1', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [2280, 240]], 1000, 600], [0, 0, 24]),
('partial repair guard 3', [[[0, 0], [0, 900]], 833, 400], [0, 0, 900]),
('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',
[[[2400, 480], [0, 480], [525, 2000], [2400, 0], [2700, 480], [2763, 480], [2400, 0]], 769, 1200],
[185, 0, 3091]),
('normal control 7', [[[2094, 0], [2400, 2000]], 769, 1200], [0, 0, 1655]),
('normal control 8',
[[[2280, 0], [1200, 0], [1200, 240], [2700, 0], [652, 0], [2280, 0], [2280, 240], [2208, 0]], 1207, 600],
[600, 706, 0])],
[('regression: unapproved accumulation 1',
[[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
[540, 0, 1969]),
('regression variant: unapproved accumulation 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200],
[0, 0, 1871]),
('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
('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', [[[688, 240], [0, 0], [2280, 0], [0, 900], [2700, 240]], 1000, 600], [30, 0, 844]),
('normal control 7',
[[[2400, 0], [2400, 0], [2700, 240], [2400, 0], [2280, 900], [242, 0], [2280, 900]], 769, 400],
[0, 296, 1206]),
('normal control 8', [[[1200, 0], [0, 0]], 833, 400], [99, 0, 0])],
[('regression: unapproved accumulation 1',
[[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400], [290, 188, 3600]),
('regression variant: unapproved accumulation 2', [[[2400, 2000], [2280, 0]], 1000, 1200], [228, 0, 1760]),
('partial repair guard 3', [[[0, 900], [2280, 0], [1200, 2000]], 1207, 400], [0, 20, 2500]),
('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', [[[1200, 0], [2400, 480], [1200, 0], [2400, 0], [2700, 0]], 1207, 11200],
[760, 0, 46]),
('normal control 7',
[[[2700, 900], [2400, 0], [0, 240], [2400, 0], [2700, 2000], [2280, 0], [1265, 0], [0, 0]], 769, 600],
[272, 0, 2356]),
('normal control 8', [[[2400, 0], [2280, 480]], 769, 400], [0, 0, 121])],
[('regression: unapproved accumulation 1',
[[[0, 480], [2280, 240], [344, 0], [2700, 240], [2700, 2000]], 833, 1200], [0, 0, 2292]),
('regression variant: unapproved accumulation 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',
[[[1200, 480], [0, 240], [2089, 0], [2700, 2000], [2700, 0], [2700, 0]], 1000, 11200], [540, 0, 2122]),
('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',
[[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
[22, 0, 1261]),
('normal control 7', [[[1200, 2000], [2400, 900], [1200, 240], [2280, 480], [0, 2000]], 833, 600],
[0, 0, 5031]),
('normal control 8',
[[[2400, 0], [0, 2000], [1200, 900], [0, 240], [1200, 900], [2400, 480], [2700, 0]], 1000, 1200],
[270, 0, 3800])],
[('regression: unapproved accumulation 1',
[[[0, 0], [2400, 900], [2700, 0], [2280, 900], [2700, 2000], [1200, 0], [1200, 0], [2280, 0]], 1207, 600],
[565, 1, 2585]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [0, 0], [1200, 0]], 769, 400],
[92, 0, 65]),
('partial repair guard 3', [[[0, 480], [0, 2000]], 1207, 1200], [0, 0, 2480]),
('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', [[[0, 2000], [2700, 0], [653, 900], [0, 480], [2400, 900], [0, 2000]], 1207, 11200],
[0, 0, 5586]),
('normal control 7', [[[2280, 2000], [1070, 240], [1200, 0]], 833, 600], [100, 0, 1961]),
('normal control 8',
[[[2700, 2000], [2700, 480], [2239, 2000], [1907, 480], [1200, 2000], [2700, 0], [2700, 0], [1200, 900]],
833, 600],
[0, 0, 6416])]]
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: unapproved accumulation 1 | [0, 0, 400] | [0, 0, 511] | Failed |
| regression variant: unapproved accumulation 2 | [0, 0, 12] | [0, 0, 24] | Failed |
| partial repair guard 3 | [0, 0, 900] | [0, 0, 900] | Passed |
| boundary control 4 | [100, 0, 0] | [100, 0, 0] | Passed |
| boundary control 5 | [869, 0, 0] | [869, 0, 0] | Passed |
| normal control 6 | [185, 0, 0] | [185, 0, 3091] | Failed |
| normal control 7 | [0, 0, 1655] | [0, 0, 1655] | Passed |
| normal control 8 | [600, 706, 0] | [600, 706, 0] | Passed |
SHA-256 / d831acd96f6eb58cd818af9ccc3dbbee6fa7cbfadbd5b8819634fa49db41f20d
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 = num % 10000
if bal > cap:
forfeit += bal - cap
bal = cap
take = min(used, bal)
unappr += used - take if take else 0
bal -= take
return [bal, forfeit, unappr]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: unapproved accumulation 1', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [2280, 240]], 1000, 600], [0, 0, 24]),
('partial repair guard 3', [[[0, 0], [0, 900]], 833, 400], [0, 0, 900]),
('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',
[[[2400, 480], [0, 480], [525, 2000], [2400, 0], [2700, 480], [2763, 480], [2400, 0]], 769, 1200],
[185, 0, 3091]),
('normal control 7', [[[2094, 0], [2400, 2000]], 769, 1200], [0, 0, 1655]),
('normal control 8',
[[[2280, 0], [1200, 0], [1200, 240], [2700, 0], [652, 0], [2280, 0], [2280, 240], [2208, 0]], 1207, 600],
[600, 706, 0])],
[('regression: unapproved accumulation 1',
[[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
[540, 0, 1969]),
('regression variant: unapproved accumulation 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200],
[0, 0, 1871]),
('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
('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', [[[688, 240], [0, 0], [2280, 0], [0, 900], [2700, 240]], 1000, 600], [30, 0, 844]),
('normal control 7',
[[[2400, 0], [2400, 0], [2700, 240], [2400, 0], [2280, 900], [242, 0], [2280, 900]], 769, 400],
[0, 296, 1206]),
('normal control 8', [[[1200, 0], [0, 0]], 833, 400], [99, 0, 0])],
[('regression: unapproved accumulation 1',
[[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400], [290, 188, 3600]),
('regression variant: unapproved accumulation 2', [[[2400, 2000], [2280, 0]], 1000, 1200], [228, 0, 1760]),
('partial repair guard 3', [[[0, 900], [2280, 0], [1200, 2000]], 1207, 400], [0, 20, 2500]),
('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', [[[1200, 0], [2400, 480], [1200, 0], [2400, 0], [2700, 0]], 1207, 11200],
[760, 0, 46]),
('normal control 7',
[[[2700, 900], [2400, 0], [0, 240], [2400, 0], [2700, 2000], [2280, 0], [1265, 0], [0, 0]], 769, 600],
[272, 0, 2356]),
('normal control 8', [[[2400, 0], [2280, 480]], 769, 400], [0, 0, 121])],
[('regression: unapproved accumulation 1',
[[[0, 480], [2280, 240], [344, 0], [2700, 240], [2700, 2000]], 833, 1200], [0, 0, 2292]),
('regression variant: unapproved accumulation 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',
[[[1200, 480], [0, 240], [2089, 0], [2700, 2000], [2700, 0], [2700, 0]], 1000, 11200], [540, 0, 2122]),
('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',
[[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
[22, 0, 1261]),
('normal control 7', [[[1200, 2000], [2400, 900], [1200, 240], [2280, 480], [0, 2000]], 833, 600],
[0, 0, 5031]),
('normal control 8',
[[[2400, 0], [0, 2000], [1200, 900], [0, 240], [1200, 900], [2400, 480], [2700, 0]], 1000, 1200],
[270, 0, 3800])],
[('regression: unapproved accumulation 1',
[[[0, 0], [2400, 900], [2700, 0], [2280, 900], [2700, 2000], [1200, 0], [1200, 0], [2280, 0]], 1207, 600],
[565, 1, 2585]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [0, 0], [1200, 0]], 769, 400],
[92, 0, 65]),
('partial repair guard 3', [[[0, 480], [0, 2000]], 1207, 1200], [0, 0, 2480]),
('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', [[[0, 2000], [2700, 0], [653, 900], [0, 480], [2400, 900], [0, 2000]], 1207, 11200],
[0, 0, 5586]),
('normal control 7', [[[2280, 2000], [1070, 240], [1200, 0]], 833, 600], [100, 0, 1961]),
('normal control 8',
[[[2700, 2000], [2700, 480], [2239, 2000], [1907, 480], [1200, 2000], [2700, 0], [2700, 0], [1200, 900]],
833, 600],
[0, 0, 6416])]]
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: unapproved accumulation 1 | [0, 0, 111] | [0, 0, 511] | Failed |
| regression variant: unapproved accumulation 2 | [0, 0, 24] | [0, 0, 24] | Passed |
| partial repair guard 3 | [0, 0, 0] | [0, 0, 900] | Failed |
| boundary control 4 | [100, 0, 0] | [100, 0, 0] | Passed |
| boundary control 5 | [869, 0, 0] | [869, 0, 0] | Passed |
| normal control 6 | [185, 0, 2611] | [185, 0, 3091] | Failed |
| normal control 7 | [0, 0, 1655] | [0, 0, 1655] | Passed |
| normal control 8 | [600, 706, 0] | [600, 706, 0] | Passed |
SHA-256 / b8c27c4dde96ce577bd40438ed1e154d96d2cbb2c90d922ce8d9731c73e798ca
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: unapproved accumulation 1', [[[2400, 400], [0, 400]], 1207, 11200], [0, 0, 511]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [2280, 240]], 1000, 600], [0, 0, 24]),
('partial repair guard 3', [[[0, 0], [0, 900]], 833, 400], [0, 0, 900]),
('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',
[[[2400, 480], [0, 480], [525, 2000], [2400, 0], [2700, 480], [2763, 480], [2400, 0]], 769, 1200],
[185, 0, 3091]),
('normal control 7', [[[2094, 0], [2400, 2000]], 769, 1200], [0, 0, 1655]),
('normal control 8',
[[[2280, 0], [1200, 0], [1200, 240], [2700, 0], [652, 0], [2280, 0], [2280, 240], [2208, 0]], 1207, 600],
[600, 706, 0])],
[('regression: unapproved accumulation 1',
[[[2406, 240], [0, 0], [2700, 2000], [129, 0], [2280, 0], [0, 480], [2700, 0], [2700, 0]], 1000, 600],
[540, 0, 1969]),
('regression variant: unapproved accumulation 2', [[[2400, 0], [0, 240], [2400, 2000]], 769, 1200],
[0, 0, 1871]),
('partial repair guard 3', [[[2400, 2000], [0, 900], [2700, 480]], 769, 1200], [0, 0, 2988]),
('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', [[[688, 240], [0, 0], [2280, 0], [0, 900], [2700, 240]], 1000, 600], [30, 0, 844]),
('normal control 7',
[[[2400, 0], [2400, 0], [2700, 240], [2400, 0], [2280, 900], [242, 0], [2280, 900]], 769, 400],
[0, 296, 1206]),
('normal control 8', [[[1200, 0], [0, 0]], 833, 400], [99, 0, 0])],
[('regression: unapproved accumulation 1',
[[[0, 2000], [0, 0], [2597, 0], [2280, 2000], [2400, 0]], 1207, 400], [290, 188, 3600]),
('regression variant: unapproved accumulation 2', [[[2400, 2000], [2280, 0]], 1000, 1200], [228, 0, 1760]),
('partial repair guard 3', [[[0, 900], [2280, 0], [1200, 2000]], 1207, 400], [0, 20, 2500]),
('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', [[[1200, 0], [2400, 480], [1200, 0], [2400, 0], [2700, 0]], 1207, 11200],
[760, 0, 46]),
('normal control 7',
[[[2700, 900], [2400, 0], [0, 240], [2400, 0], [2700, 2000], [2280, 0], [1265, 0], [0, 0]], 769, 600],
[272, 0, 2356]),
('normal control 8', [[[2400, 0], [2280, 480]], 769, 400], [0, 0, 121])],
[('regression: unapproved accumulation 1',
[[[0, 480], [2280, 240], [344, 0], [2700, 240], [2700, 2000]], 833, 1200], [0, 0, 2292]),
('regression variant: unapproved accumulation 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',
[[[1200, 480], [0, 240], [2089, 0], [2700, 2000], [2700, 0], [2700, 0]], 1000, 11200], [540, 0, 2122]),
('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',
[[[2280, 0], [2400, 0], [2280, 0], [2400, 2000], [2400, 240], [69, 0], [197, 0]], 833, 1200],
[22, 0, 1261]),
('normal control 7', [[[1200, 2000], [2400, 900], [1200, 240], [2280, 480], [0, 2000]], 833, 600],
[0, 0, 5031]),
('normal control 8',
[[[2400, 0], [0, 2000], [1200, 900], [0, 240], [1200, 900], [2400, 480], [2700, 0]], 1000, 1200],
[270, 0, 3800])],
[('regression: unapproved accumulation 1',
[[[0, 0], [2400, 900], [2700, 0], [2280, 900], [2700, 2000], [1200, 0], [1200, 0], [2280, 0]], 1207, 600],
[565, 1, 2585]),
('regression variant: unapproved accumulation 2', [[[2280, 240], [0, 0], [1200, 0]], 769, 400],
[92, 0, 65]),
('partial repair guard 3', [[[0, 480], [0, 2000]], 1207, 1200], [0, 0, 2480]),
('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', [[[0, 2000], [2700, 0], [653, 900], [0, 480], [2400, 900], [0, 2000]], 1207, 11200],
[0, 0, 5586]),
('normal control 7', [[[2280, 2000], [1070, 240], [1200, 0]], 833, 600], [100, 0, 1961]),
('normal control 8',
[[[2700, 2000], [2700, 480], [2239, 2000], [1907, 480], [1200, 2000], [2700, 0], [2700, 0], [1200, 900]],
833, 600],
[0, 0, 6416])]]
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: unapproved accumulation 1 | [0, 0, 511] | [0, 0, 511] | Passed |
| regression variant: unapproved accumulation 2 | [0, 0, 24] | [0, 0, 24] | Passed |
| partial repair guard 3 | [0, 0, 900] | [0, 0, 900] | Passed |
| boundary control 4 | [100, 0, 0] | [100, 0, 0] | Passed |
| boundary control 5 | [869, 0, 0] | [869, 0, 0] | Passed |
| normal control 6 | [185, 0, 3091] | [185, 0, 3091] | Passed |
| normal control 7 | [0, 0, 1655] | [0, 0, 1655] | Passed |
| normal control 8 | [600, 706, 0] | [600, 706, 0] | Passed |
SHA-256 / 293ae2864318c6a09ea9bbdb4adbfb65dc10e24a0e478257ed435e15ab9c1dcc
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.583551+00:00.
Case digest / ab7fa554defaa4f769e676b5bf2fbea660afe011ead4179fbfe1d13639de86e3