FAILURE MAP
← Case archive

FA-68046 / Traffic signal timing plans / Open access

Coordinated local cycle timer: the full yellow is reported regardless of elapsed yellow · case 01

Coordinated local cycle timer returns a wrong result when the full yellow is reported regardless of elapsed yellow.

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

ROOT CAUSE

The remaining-time field repeats the configured yellow instead of the time left in it.

VERIFIED REPAIR

Restore the yellow time remaining rule so that the step reads `[ph, 'yellow', ge + y - lc]`.

Unsuccessful approach: Subtracting one more second reports zero remaining in the last yellow second, which the contract never does.

Case contract

Input {cycle, offset, master, splits: [[phase, split s]] in sequence starting with the coordinated phase, yellow, red, ref}. Splits must sum to the cycle, else 'bad-splits'. Local time = (master - offset) mod cycle, where the offset marks the start of coordinated green (ref 'begin') or the end of coordinated green (ref 'end'). Each split is green then yellow then all-red. Return [phase, interval, seconds remaining].

Why this case matters

Signal timing arithmetic is exact and integer or rational; a wrong rule silently produces unsafe or inefficient timing plans.

1 / The failure

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

N = 1
observations = []
def solve(x):
    C = x['cycle']
    sp = x['splits']
    y, r = x['yellow'], x['red']
    if sum(s for _, s in sp) != C:
        return 'bad-splits'
    lc = (x['master'] - x['offset']) % C
    if x['ref'] == 'end':
        lc = (lc + sp[0][1] - y - r) % C
    start = 0
    for ph, s in sp:
        ge = start + s - y - r
        if lc < ge:
            return [ph, 'green', ge - lc]
        if lc < ge + y:
            return [ph, 'yellow', y]
        if lc < start + s:
            return [ph, 'red', start + s - lc]
        start += s
    return ['free', 'dark', 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 22, 'master': 276, 'splits': [[2, 30], [4, 12]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 67, 'offset': 15, 'master': 313, 'splits': [[2, 40], [4, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [4, 'yellow', 1]), ({'cycle': 90, 'offset': 55, 'master': 1000, 'splits': [[2, 18], [4, 18], [6, 24], [8, 30]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 118, 'offset': 26, 'master': 74, 'splits': [[2, 40], [4, 22], [6, 21], [8, 35]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 9]), ({'cycle': 30, 'offset': 8, 'master': 32, 'splits': [[2, 14], [4, 16]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25])], [({'cycle': 88, 'offset': 76, 'master': 606, 'splits': [[2, 19], [4, 33], [6, 23], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 52, 'offset': 51, 'master': 207, 'splits': [[2, 22], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [2, 'yellow', 3]), ({'cycle': 64, 'offset': 4, 'master': 173, 'splits': [[2, 28], [4, 16], [6, 20]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [4, 'yellow', 2]), ({'cycle': 98, 'offset': 74, 'master': 280, 'splits': [[2, 30], [4, 21], [6, 14], [8, 33]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 15]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 32, 'master': 833, 'splits': [[2, 27], [4, 15]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 1])], [({'cycle': 57, 'offset': 37, 'master': 74, 'splits': [[2, 22], [4, 16], [6, 19]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 54, 'offset': 4, 'master': 576, 'splits': [[2, 35], [4, 19]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 76, 'offset': 48, 'master': 580, 'splits': [[2, 36], [4, 40]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 4]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 64, 'offset': 4, 'master': 283, 'splits': [[2, 25], [4, 39]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 86, 'offset': 58, 'master': 977, 'splits': [[2, 31], [4, 19], [6, 36]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [2, 'green', 27])], [({'cycle': 51, 'offset': 44, 'master': 5, 'splits': [[2, 16], [4, 35]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 2]), ({'cycle': 116, 'offset': 89, 'master': 203, 'splits': [[2, 19], [4, 29], [6, 36], [8, 32]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 88, 'offset': 39, 'master': 770, 'splits': [[2, 29], [4, 25], [6, 34]], 'yellow': 3, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 37, 'offset': 13, 'master': 804, 'splits': [[2, 19], [4, 18]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 3]), ({'cycle': 86, 'offset': 61, 'master': 865, 'splits': [[2, 31], [4, 35], [6, 20]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [4, 'green', 5]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits')], [({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 47, 'offset': 23, 'master': 37, 'splits': [[2, 25], [4, 22]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 6]), ({'cycle': 86, 'offset': 78, 'master': 997, 'splits': [[2, 29], [4, 32], [6, 25]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 78, 'offset': 64, 'master': 139, 'splits': [[2, 14], [4, 15], [6, 36], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 82, 'offset': 44, 'master': 456, 'splits': [[2, 32], [4, 23], [6, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 69, 'offset': 12, 'master': 586, 'splits': [[2, 18], [4, 33], [6, 23]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, 'bad-splits')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0bad-splitsbad-splitsPassed
timing oracle 1[2, 'yellow', 4][2, 'yellow', 2]Failed
timing oracle 2[4, 'green', 10][4, 'green', 10]Passed
timing oracle 3[4, 'yellow', 4][4, 'yellow', 1]Failed
timing oracle 4[6, 'yellow', 4][6, 'yellow', 1]Failed
timing oracle 5[4, 'green', 9][4, 'green', 9]Passed
timing oracle 6[4, 'green', 1][4, 'green', 1]Passed
timing oracle 7[2, 'green', 25][2, 'green', 25]Passed

SHA-256 / 0bc6a02bb53d4d1b33524dc09f203e794ccc2d7f87a813c5a440f58655ed3d91

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    C = x['cycle']
    sp = x['splits']
    y, r = x['yellow'], x['red']
    if sum(s for _, s in sp) != C:
        return 'bad-splits'
    lc = (x['master'] - x['offset']) % C
    if x['ref'] == 'end':
        lc = (lc + sp[0][1] - y - r) % C
    start = 0
    for ph, s in sp:
        ge = start + s - y - r
        if lc < ge:
            return [ph, 'green', ge - lc]
        if lc < ge + y:
            return [ph, 'yellow', ge + y - lc - 1]
        if lc < start + s:
            return [ph, 'red', start + s - lc]
        start += s
    return ['free', 'dark', 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 22, 'master': 276, 'splits': [[2, 30], [4, 12]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 67, 'offset': 15, 'master': 313, 'splits': [[2, 40], [4, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [4, 'yellow', 1]), ({'cycle': 90, 'offset': 55, 'master': 1000, 'splits': [[2, 18], [4, 18], [6, 24], [8, 30]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 118, 'offset': 26, 'master': 74, 'splits': [[2, 40], [4, 22], [6, 21], [8, 35]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 9]), ({'cycle': 30, 'offset': 8, 'master': 32, 'splits': [[2, 14], [4, 16]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25])], [({'cycle': 88, 'offset': 76, 'master': 606, 'splits': [[2, 19], [4, 33], [6, 23], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 52, 'offset': 51, 'master': 207, 'splits': [[2, 22], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [2, 'yellow', 3]), ({'cycle': 64, 'offset': 4, 'master': 173, 'splits': [[2, 28], [4, 16], [6, 20]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [4, 'yellow', 2]), ({'cycle': 98, 'offset': 74, 'master': 280, 'splits': [[2, 30], [4, 21], [6, 14], [8, 33]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 15]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 32, 'master': 833, 'splits': [[2, 27], [4, 15]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 1])], [({'cycle': 57, 'offset': 37, 'master': 74, 'splits': [[2, 22], [4, 16], [6, 19]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 54, 'offset': 4, 'master': 576, 'splits': [[2, 35], [4, 19]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 76, 'offset': 48, 'master': 580, 'splits': [[2, 36], [4, 40]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 4]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 64, 'offset': 4, 'master': 283, 'splits': [[2, 25], [4, 39]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 86, 'offset': 58, 'master': 977, 'splits': [[2, 31], [4, 19], [6, 36]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [2, 'green', 27])], [({'cycle': 51, 'offset': 44, 'master': 5, 'splits': [[2, 16], [4, 35]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 2]), ({'cycle': 116, 'offset': 89, 'master': 203, 'splits': [[2, 19], [4, 29], [6, 36], [8, 32]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 88, 'offset': 39, 'master': 770, 'splits': [[2, 29], [4, 25], [6, 34]], 'yellow': 3, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 37, 'offset': 13, 'master': 804, 'splits': [[2, 19], [4, 18]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 3]), ({'cycle': 86, 'offset': 61, 'master': 865, 'splits': [[2, 31], [4, 35], [6, 20]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [4, 'green', 5]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits')], [({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 47, 'offset': 23, 'master': 37, 'splits': [[2, 25], [4, 22]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 6]), ({'cycle': 86, 'offset': 78, 'master': 997, 'splits': [[2, 29], [4, 32], [6, 25]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 78, 'offset': 64, 'master': 139, 'splits': [[2, 14], [4, 15], [6, 36], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 82, 'offset': 44, 'master': 456, 'splits': [[2, 32], [4, 23], [6, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 69, 'offset': 12, 'master': 586, 'splits': [[2, 18], [4, 33], [6, 23]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, 'bad-splits')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0bad-splitsbad-splitsPassed
timing oracle 1[2, 'yellow', 1][2, 'yellow', 2]Failed
timing oracle 2[4, 'green', 10][4, 'green', 10]Passed
timing oracle 3[4, 'yellow', 0][4, 'yellow', 1]Failed
timing oracle 4[6, 'yellow', 0][6, 'yellow', 1]Failed
timing oracle 5[4, 'green', 9][4, 'green', 9]Passed
timing oracle 6[4, 'green', 1][4, 'green', 1]Passed
timing oracle 7[2, 'green', 25][2, 'green', 25]Passed

SHA-256 / b643d0f7c36470b6f53be06ac1cf6418321701f961e78d796d98f0cb03d70147

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    C = x['cycle']
    sp = x['splits']
    y, r = x['yellow'], x['red']
    if sum(s for _, s in sp) != C:
        return 'bad-splits'
    lc = (x['master'] - x['offset']) % C
    if x['ref'] == 'end':
        lc = (lc + sp[0][1] - y - r) % C
    start = 0
    for ph, s in sp:
        ge = start + s - y - r
        if lc < ge:
            return [ph, 'green', ge - lc]
        if lc < ge + y:
            return [ph, 'yellow', ge + y - lc]
        if lc < start + s:
            return [ph, 'red', start + s - lc]
        start += s
    return ['free', 'dark', 0]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 22, 'master': 276, 'splits': [[2, 30], [4, 12]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 67, 'offset': 15, 'master': 313, 'splits': [[2, 40], [4, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [4, 'yellow', 1]), ({'cycle': 90, 'offset': 55, 'master': 1000, 'splits': [[2, 18], [4, 18], [6, 24], [8, 30]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 118, 'offset': 26, 'master': 74, 'splits': [[2, 40], [4, 22], [6, 21], [8, 35]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 9]), ({'cycle': 30, 'offset': 8, 'master': 32, 'splits': [[2, 14], [4, 16]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [4, 'green', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25])], [({'cycle': 88, 'offset': 76, 'master': 606, 'splits': [[2, 19], [4, 33], [6, 23], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 52, 'offset': 51, 'master': 207, 'splits': [[2, 22], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [2, 'yellow', 3]), ({'cycle': 64, 'offset': 4, 'master': 173, 'splits': [[2, 28], [4, 16], [6, 20]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [4, 'yellow', 2]), ({'cycle': 98, 'offset': 74, 'master': 280, 'splits': [[2, 30], [4, 21], [6, 14], [8, 33]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 15]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 42, 'offset': 32, 'master': 833, 'splits': [[2, 27], [4, 15]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 1])], [({'cycle': 57, 'offset': 37, 'master': 74, 'splits': [[2, 22], [4, 16], [6, 19]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 54, 'offset': 4, 'master': 576, 'splits': [[2, 35], [4, 19]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 76, 'offset': 48, 'master': 580, 'splits': [[2, 36], [4, 40]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 4]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 64, 'offset': 4, 'master': 283, 'splits': [[2, 25], [4, 39]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 86, 'offset': 58, 'master': 977, 'splits': [[2, 31], [4, 19], [6, 36]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [2, 'green', 27])], [({'cycle': 51, 'offset': 44, 'master': 5, 'splits': [[2, 16], [4, 35]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 2]), ({'cycle': 116, 'offset': 89, 'master': 203, 'splits': [[2, 19], [4, 29], [6, 36], [8, 32]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 88, 'offset': 39, 'master': 770, 'splits': [[2, 29], [4, 25], [6, 34]], 'yellow': 3, 'red': 1, 'ref': 'begin'}, [2, 'yellow', 1]), ({'cycle': 37, 'offset': 13, 'master': 804, 'splits': [[2, 19], [4, 18]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'yellow', 3]), ({'cycle': 86, 'offset': 61, 'master': 865, 'splits': [[2, 31], [4, 35], [6, 20]], 'yellow': 3, 'red': 2, 'ref': 'end'}, [4, 'green', 5]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits')], [({'cycle': 80, 'offset': 70, 'master': 10, 'splits': [[2, 50], [4, 30]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 25]), ({'cycle': 47, 'offset': 23, 'master': 37, 'splits': [[2, 25], [4, 22]], 'yellow': 3, 'red': 2, 'ref': 'begin'}, [2, 'green', 6]), ({'cycle': 86, 'offset': 78, 'master': 997, 'splits': [[2, 29], [4, 32], [6, 25]], 'yellow': 3, 'red': 1, 'ref': 'end'}, [6, 'yellow', 1]), ({'cycle': 78, 'offset': 64, 'master': 139, 'splits': [[2, 14], [4, 15], [6, 36], [8, 13]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, [8, 'yellow', 1]), ({'cycle': 82, 'offset': 44, 'master': 456, 'splits': [[2, 32], [4, 23], [6, 27]], 'yellow': 4, 'red': 2, 'ref': 'end'}, [2, 'yellow', 2]), ({'cycle': 90, 'offset': 30, 'master': 45, 'splits': [[2, 40], [4, 25], [6, 25]], 'yellow': 4, 'red': 1, 'ref': 'end'}, [4, 'green', 10]), ({'cycle': 100, 'offset': 5, 'master': 3, 'splits': [[2, 50], [4, 30], [8, 25]], 'yellow': 4, 'red': 2, 'ref': 'begin'}, 'bad-splits'), ({'cycle': 69, 'offset': 12, 'master': 586, 'splits': [[2, 18], [4, 33], [6, 23]], 'yellow': 4, 'red': 1, 'ref': 'begin'}, 'bad-splits')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check('timing oracle' + ' %d' % i, 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
timing oracle 0bad-splitsbad-splitsPassed
timing oracle 1[2, 'yellow', 2][2, 'yellow', 2]Passed
timing oracle 2[4, 'green', 10][4, 'green', 10]Passed
timing oracle 3[4, 'yellow', 1][4, 'yellow', 1]Passed
timing oracle 4[6, 'yellow', 1][6, 'yellow', 1]Passed
timing oracle 5[4, 'green', 9][4, 'green', 9]Passed
timing oracle 6[4, 'green', 1][4, 'green', 1]Passed
timing oracle 7[2, 'green', 25][2, 'green', 25]Passed

SHA-256 / 9b0c1fd4fc285e1fbbcece62a71fcd09eaeba4f05d014a51a589cca15d417afd

Verification & scope

A deterministic, bounded toy model with a stipulated contract; it makes no claim of conformance to any agency manual or standard. 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:47:58.544834+00:00.

Case digest / 49ca4051d8fc383319931938388abb56237bfe3d2cc66333c801783c800044e7