FAILURE MAP
← Case archive

FA-66976 / Railway interlocking logic / Open access

Axle counter section supervision: state precedence · case 01

A section under preparatory reset is shown as ordinarily occupied while the sweep train passes.

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

ROOT CAUSE

Occupied is reported ahead of the preparatory state.

VERIFIED REPAIR

Report prep ahead of occupied until the sweep completes.

Unsuccessful approach: Reporting prep only at a zero count still hides the preparatory state during the sweep.

Case contract

An axle-counter section counts axles in and out. Counting out below zero latches disturbed (count forced to 0). A reset is accepted only when the section is disturbed or the count is non-zero; it zeroes the count and enters preparatory state, which ends only when a sweep train has counted in and the count returns to zero on an out-count. query reports disturbed, prep, occupied (count>0) or clear, in that precedence.

Why this case matters

Interlocking logic decides whether trains may be given authority; a wrong decision at this point either grants unsafe movements or strands traffic.

1 / The failure

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

N = 1
observations = []
def solve(x):
    count = 0
    disturbed = False
    prep = False
    swept = False
    out = []
    for ev in x['events']:
        if ev == 'in':
            count += 1
            if prep:
                swept = True
        elif ev == 'out':
            count -= 1
            if count < 0:
                disturbed = True
                count = 0
            if prep and swept and count == 0:
                prep = False
        elif ev == 'reset':
            if disturbed or count != 0:
                count = 0
                disturbed = False
                prep = True
                swept = False
        elif ev == 'query':
            if disturbed:
                out.append('disturbed')
            elif count > 0:
                out.append('occupied')
            elif prep:
                out.append('prep')
            else:
                out.append('clear')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 9', {'events': ['in', 'query', 'query', 'reset', 'in', 'in', 'in', 'in', 'query', 'reset', 'in', 'query']}, ['occupied', 'occupied', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('control 1', {'events': ['out', 'in', 'out', 'query', 'out', 'query', 'in', 'out', 'in', 'out', 'query', 'query', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']), ('control 4', {'events': ['in', 'out', 'query', 'query', 'query']}, ['clear', 'clear', 'clear']), ('control 7', {'events': ['query', 'out', 'in', 'query', 'out', 'query', 'reset', 'reset', 'in', 'reset', 'query', 'reset', 'query']}, ['clear', 'disturbed', 'disturbed', 'prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('control 12', {'events': ['query', 'out', 'reset', 'out', 'query']}, ['clear', 'disturbed']), ('control 15', {'events': ['out', 'out', 'in', 'reset', 'query', 'query', 'query']}, ['prep', 'prep', 'prep']), ('sampled regression 18', {'events': ['out', 'query', 'query', 'reset', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'prep', 'prep'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 2', {'events': ['in', 'in', 'reset', 'reset', 'query', 'in', 'query']}, ['prep', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count during preparation', {'events': ['in', 'reset', 'out', 'query']}, ['disturbed']), ('control 23', {'events': ['query', 'out', 'query', 'out', 'in', 'in', 'in', 'query', 'out', 'in', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 26', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 29', {'events': ['out', 'in', 'in', 'out', 'out', 'in', 'reset', 'out', 'reset', 'in', 'query', 'in', 'query']}, ['prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 39', {'events': ['query', 'query', 'query', 'query', 'query', 'reset', 'out', 'out', 'out', 'reset', 'in', 'in', 'out', 'query']}, ['clear', 'clear', 'clear', 'clear', 'clear', 'prep']), ('boundary: normal passage', {'events': ['in', 'in', 'query', 'out', 'out', 'query']}, ['occupied', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('control 34', {'events': ['in', 'out', 'in', 'out', 'in', 'in', 'query']}, ['occupied']), ('control 37', {'events': ['reset', 'query', 'out', 'query', 'query', 'out', 'in', 'out', 'in', 'out', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 40', {'events': ['in', 'in', 'query', 'out', 'query']}, ['occupied', 'occupied'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('control 51', {'events': ['reset', 'query', 'in', 'out', 'query', 'in', 'in', 'query', 'query', 'query', 'query']}, ['clear', 'clear', 'occupied', 'occupied', 'occupied', 'occupied'])]]
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: reset of a miscounted section['prep', 'occupied', 'clear']['prep', 'prep', 'clear']Failed
sampled regression 9['occupied', 'occupied', 'occupied', 'occupied']['occupied', 'occupied', 'prep', 'prep']Failed
regression: sweep train partly through['occupied', 'clear']['prep', 'clear']Failed
boundary: under-count latches disturbance['disturbed', 'disturbed']['disturbed', 'disturbed']Passed
boundary: reset of a disturbed section['prep', 'clear']['prep', 'clear']Passed
control 1['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']Passed
control 4['clear', 'clear', 'clear']['clear', 'clear', 'clear']Passed
control 7['clear', 'disturbed', 'disturbed', 'prep', 'prep']['clear', 'disturbed', 'disturbed', 'prep', 'prep']Passed

SHA-256 / cb64f85a4919baaed70eda7edb64996b598ca7212cf2e0f88efb1660b859e473

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(x):
    count = 0
    disturbed = False
    prep = False
    swept = False
    out = []
    for ev in x['events']:
        if ev == 'in':
            count += 1
            if prep:
                swept = True
        elif ev == 'out':
            count -= 1
            if count < 0:
                disturbed = True
                count = 0
            if prep and swept and count == 0:
                prep = False
        elif ev == 'reset':
            if disturbed or count != 0:
                count = 0
                disturbed = False
                prep = True
                swept = False
        elif ev == 'query':
            if disturbed:
                out.append('disturbed')
            elif prep and count == 0:
                out.append('prep')
            elif count > 0:
                out.append('occupied')
            else:
                out.append('clear')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 9', {'events': ['in', 'query', 'query', 'reset', 'in', 'in', 'in', 'in', 'query', 'reset', 'in', 'query']}, ['occupied', 'occupied', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('control 1', {'events': ['out', 'in', 'out', 'query', 'out', 'query', 'in', 'out', 'in', 'out', 'query', 'query', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']), ('control 4', {'events': ['in', 'out', 'query', 'query', 'query']}, ['clear', 'clear', 'clear']), ('control 7', {'events': ['query', 'out', 'in', 'query', 'out', 'query', 'reset', 'reset', 'in', 'reset', 'query', 'reset', 'query']}, ['clear', 'disturbed', 'disturbed', 'prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('control 12', {'events': ['query', 'out', 'reset', 'out', 'query']}, ['clear', 'disturbed']), ('control 15', {'events': ['out', 'out', 'in', 'reset', 'query', 'query', 'query']}, ['prep', 'prep', 'prep']), ('sampled regression 18', {'events': ['out', 'query', 'query', 'reset', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'prep', 'prep'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 2', {'events': ['in', 'in', 'reset', 'reset', 'query', 'in', 'query']}, ['prep', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count during preparation', {'events': ['in', 'reset', 'out', 'query']}, ['disturbed']), ('control 23', {'events': ['query', 'out', 'query', 'out', 'in', 'in', 'in', 'query', 'out', 'in', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 26', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 29', {'events': ['out', 'in', 'in', 'out', 'out', 'in', 'reset', 'out', 'reset', 'in', 'query', 'in', 'query']}, ['prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 39', {'events': ['query', 'query', 'query', 'query', 'query', 'reset', 'out', 'out', 'out', 'reset', 'in', 'in', 'out', 'query']}, ['clear', 'clear', 'clear', 'clear', 'clear', 'prep']), ('boundary: normal passage', {'events': ['in', 'in', 'query', 'out', 'out', 'query']}, ['occupied', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('control 34', {'events': ['in', 'out', 'in', 'out', 'in', 'in', 'query']}, ['occupied']), ('control 37', {'events': ['reset', 'query', 'out', 'query', 'query', 'out', 'in', 'out', 'in', 'out', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 40', {'events': ['in', 'in', 'query', 'out', 'query']}, ['occupied', 'occupied'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('control 51', {'events': ['reset', 'query', 'in', 'out', 'query', 'in', 'in', 'query', 'query', 'query', 'query']}, ['clear', 'clear', 'occupied', 'occupied', 'occupied', 'occupied'])]]
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: reset of a miscounted section['prep', 'occupied', 'clear']['prep', 'prep', 'clear']Failed
sampled regression 9['occupied', 'occupied', 'occupied', 'occupied']['occupied', 'occupied', 'prep', 'prep']Failed
regression: sweep train partly through['occupied', 'clear']['prep', 'clear']Failed
boundary: under-count latches disturbance['disturbed', 'disturbed']['disturbed', 'disturbed']Passed
boundary: reset of a disturbed section['prep', 'clear']['prep', 'clear']Passed
control 1['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']Passed
control 4['clear', 'clear', 'clear']['clear', 'clear', 'clear']Passed
control 7['clear', 'disturbed', 'disturbed', 'prep', 'prep']['clear', 'disturbed', 'disturbed', 'prep', 'prep']Passed

SHA-256 / 2260564d14570c3372d3ea15d997912e22c6c310548626dd3815b8bcff47ae5f

3 / The verified repair

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

N = 1
observations = []
def solve(x):
    count = 0
    disturbed = False
    prep = False
    swept = False
    out = []
    for ev in x['events']:
        if ev == 'in':
            count += 1
            if prep:
                swept = True
        elif ev == 'out':
            count -= 1
            if count < 0:
                disturbed = True
                count = 0
            if prep and swept and count == 0:
                prep = False
        elif ev == 'reset':
            if disturbed or count != 0:
                count = 0
                disturbed = False
                prep = True
                swept = False
        elif ev == 'query':
            if disturbed:
                out.append('disturbed')
            elif prep:
                out.append('prep')
            elif count > 0:
                out.append('occupied')
            else:
                out.append('clear')
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 9', {'events': ['in', 'query', 'query', 'reset', 'in', 'in', 'in', 'in', 'query', 'reset', 'in', 'query']}, ['occupied', 'occupied', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('control 1', {'events': ['out', 'in', 'out', 'query', 'out', 'query', 'in', 'out', 'in', 'out', 'query', 'query', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']), ('control 4', {'events': ['in', 'out', 'query', 'query', 'query']}, ['clear', 'clear', 'clear']), ('control 7', {'events': ['query', 'out', 'in', 'query', 'out', 'query', 'reset', 'reset', 'in', 'reset', 'query', 'reset', 'query']}, ['clear', 'disturbed', 'disturbed', 'prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('control 12', {'events': ['query', 'out', 'reset', 'out', 'query']}, ['clear', 'disturbed']), ('control 15', {'events': ['out', 'out', 'in', 'reset', 'query', 'query', 'query']}, ['prep', 'prep', 'prep']), ('sampled regression 18', {'events': ['out', 'query', 'query', 'reset', 'in', 'query', 'query']}, ['disturbed', 'disturbed', 'prep', 'prep'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('sampled regression 2', {'events': ['in', 'in', 'reset', 'reset', 'query', 'in', 'query']}, ['prep', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('boundary: under-count during preparation', {'events': ['in', 'reset', 'out', 'query']}, ['disturbed']), ('control 23', {'events': ['query', 'out', 'query', 'out', 'in', 'in', 'in', 'query', 'out', 'in', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 26', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 29', {'events': ['out', 'in', 'in', 'out', 'out', 'in', 'reset', 'out', 'reset', 'in', 'query', 'in', 'query']}, ['prep', 'prep'])], [('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 39', {'events': ['query', 'query', 'query', 'query', 'query', 'reset', 'out', 'out', 'out', 'reset', 'in', 'in', 'out', 'query']}, ['clear', 'clear', 'clear', 'clear', 'clear', 'prep']), ('boundary: normal passage', {'events': ['in', 'in', 'query', 'out', 'out', 'query']}, ['occupied', 'clear']), ('boundary: under-count latches disturbance', {'events': ['out', 'query', 'in', 'query']}, ['disturbed', 'disturbed']), ('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('control 34', {'events': ['in', 'out', 'in', 'out', 'in', 'in', 'query']}, ['occupied']), ('control 37', {'events': ['reset', 'query', 'out', 'query', 'query', 'out', 'in', 'out', 'in', 'out', 'in', 'query']}, ['clear', 'disturbed', 'disturbed', 'disturbed']), ('control 40', {'events': ['in', 'in', 'query', 'out', 'query']}, ['occupied', 'occupied'])], [('regression: reset of a miscounted section', {'events': ['in', 'in', 'out', 'reset', 'query', 'in', 'in', 'query', 'out', 'out', 'query']}, ['prep', 'prep', 'clear']), ('regression: sweep train partly through', {'events': ['out', 'reset', 'in', 'in', 'out', 'query', 'out', 'query']}, ['prep', 'clear']), ('sampled regression 14', {'events': ['in', 'in', 'reset', 'in', 'query', 'out', 'out', 'reset', 'in', 'in', 'in', 'out', 'in', 'query']}, ['prep', 'prep']), ('boundary: reset of a disturbed section', {'events': ['out', 'reset', 'query', 'in', 'out', 'query']}, ['prep', 'clear']), ('boundary: reset refused on a clear section', {'events': ['reset', 'query', 'in', 'query']}, ['clear', 'occupied']), ('sampled regression 45', {'events': ['out', 'query', 'out', 'in', 'query', 'in', 'in', 'in', 'reset', 'in', 'query']}, ['disturbed', 'disturbed', 'prep']), ('sampled regression 48', {'events': ['out', 'query', 'in', 'out', 'reset', 'in', 'query', 'query', 'query', 'query']}, ['disturbed', 'prep', 'prep', 'prep', 'prep']), ('control 51', {'events': ['reset', 'query', 'in', 'out', 'query', 'in', 'in', 'query', 'query', 'query', 'query']}, ['clear', 'clear', 'occupied', 'occupied', 'occupied', 'occupied'])]]
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: reset of a miscounted section['prep', 'prep', 'clear']['prep', 'prep', 'clear']Passed
sampled regression 9['occupied', 'occupied', 'prep', 'prep']['occupied', 'occupied', 'prep', 'prep']Passed
regression: sweep train partly through['prep', 'clear']['prep', 'clear']Passed
boundary: under-count latches disturbance['disturbed', 'disturbed']['disturbed', 'disturbed']Passed
boundary: reset of a disturbed section['prep', 'clear']['prep', 'clear']Passed
control 1['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']['disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed', 'disturbed']Passed
control 4['clear', 'clear', 'clear']['clear', 'clear', 'clear']Passed
control 7['clear', 'disturbed', 'disturbed', 'prep', 'prep']['clear', 'disturbed', 'disturbed', 'prep', 'prep']Passed

SHA-256 / 738ffeda02eb6f8c98f28304895622fb43616f4076d74e78c6787206ad2e8bc7

Verification & scope

Stipulated toy interlocking contract for a bounded teaching model; it makes no claim of conformance to any railway signalling standard and omits real safety cases. 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:48.643293+00:00.

Case digest / 36613d88f333b9c3e1eecea1c2ae41ad50b5f22f8293eb5c8001dcdb45e3dda3