FA-67021 / Railway interlocking logic / Open access
Overlap timed release: timer expiry boundary · case 01
The overlap stays locked at the exact moment the timer expires.
ROOT CAUSE
The elapsed time must strictly exceed the timer.
THE FAILURE
The elapsed time must strictly exceed the timer.
Unsuccessful approach: Comparing whole minutes releases up to a minute early.
Case contract
The overlap beyond a signal is locked. The release timer starts at the first berth occupation; the overlap is released when an event time reaches start + timer_s while the train has not overrun into the overlap. A berth clear before release cancels the timer (a later occupation restarts it); after release it has no effect. Entering the overlap before release marks an overrun and blocks release. query appends locked or released.
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):
T = x['timer_s']
start = None
overran = False
released = False
out = []
for t, ev in x['events']:
if start is not None and not released and not overran and t - start > T:
released = True
if ev == 'berth_occ':
if start is None:
start = t
elif ev == 'berth_clr':
if not released:
start = None
elif ev == 'overlap_occ':
if not released:
overran = True
elif ev == 'query':
out.append('released' if released else 'locked')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: expiry exactly on time', {'timer_s': 60, 'events': [[10, 'berth_occ'], [70, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('control 1', {'timer_s': 45, 'events': [[5, 'overlap_occ'], [35, 'query'], [65, 'berth_clr'], [125, 'query'], [170, 'query'], [170, 'berth_clr'], [230, 'berth_occ'], [350, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 4', {'timer_s': 90, 'events': [[60, 'berth_clr'], [150, 'berth_occ'], [155, 'berth_occ'], [155, 'query']]}, ['locked']), ('control 7', {'timer_s': 45, 'events': [[5, 'query'], [65, 'overlap_occ'], [110, 'overlap_occ'], [170, 'query']]}, ['locked', 'locked'])], [('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('sampled regression 33', {'timer_s': 60, 'events': [[60, 'berth_occ'], [60, 'query'], [120, 'query'], [150, 'berth_occ'], [240, 'berth_clr'], [360, 'query']]}, ['locked', 'released', 'released']), ('control 62', {'timer_s': 90, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [75, 'query'], [120, 'query'], [150, 'overlap_occ'], [240, 'query'], [245, 'query'], [365, 'query']]}, ['locked', 'released', 'released', 'released', 'released']), ('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('control 12', {'timer_s': 120, 'events': [[60, 'berth_occ'], [65, 'query'], [70, 'query'], [70, 'query'], [75, 'berth_occ'], [80, 'berth_occ'], [125, 'berth_clr'], [125, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 15', {'timer_s': 120, 'events': [[60, 'berth_clr'], [105, 'berth_clr'], [110, 'berth_clr'], [115, 'berth_clr'], [175, 'query'], [175, 'berth_clr'], [235, 'query'], [265, 'overlap_occ'], [270, 'berth_clr'], [390, 'query']]}, ['locked', 'locked', 'locked']), ('sampled regression 18', {'timer_s': 90, 'events': [[0, 'query'], [0, 'query'], [30, 'berth_occ'], [120, 'overlap_occ'], [210, 'berth_clr'], [215, 'query'], [245, 'berth_occ'], [365, 'query']]}, ['locked', 'locked', 'released', 'released'])], [('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('boundary: overrun into the overlap', {'timer_s': 60, 'events': [[0, 'berth_occ'], [20, 'overlap_occ'], [120, 'query']]}, ['locked']), ('control 23', {'timer_s': 45, 'events': [[0, 'query'], [5, 'berth_occ'], [95, 'berth_occ'], [185, 'berth_occ'], [245, 'query']]}, ['locked', 'released']), ('control 26', {'timer_s': 60, 'events': [[30, 'query'], [60, 'query'], [150, 'overlap_occ'], [150, 'query']]}, ['locked', 'locked', 'locked']), ('control 29', {'timer_s': 90, 'events': [[90, 'overlap_occ'], [95, 'query'], [95, 'berth_occ'], [185, 'query'], [230, 'query'], [260, 'query'], [350, 'berth_occ'], [410, 'query']]}, ['locked', 'locked', 'locked', 'locked', 'locked'])], [('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('sampled regression 32', {'timer_s': 90, 'events': [[60, 'berth_occ'], [105, 'berth_clr'], [105, 'berth_occ'], [105, 'query'], [135, 'query'], [195, 'berth_clr'], [255, 'query']]}, ['locked', 'locked', 'released']), ('control 62', {'timer_s': 90, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [75, 'query'], [120, 'query'], [150, 'overlap_occ'], [240, 'query'], [245, 'query'], [365, 'query']]}, ['locked', 'released', 'released', 'released', 'released']), ('regression: expiry after a minute boundary', {'timer_s': 120, 'events': [[30, 'berth_occ'], [140, 'query'], [150, 'query']]}, ['locked', 'released']), ('control 34', {'timer_s': 60, 'events': [[5, 'query'], [35, 'query'], [80, 'berth_occ'], [170, 'berth_occ'], [260, 'berth_occ'], [320, 'berth_occ'], [350, 'overlap_occ'], [395, 'overlap_occ'], [440, 'query'], [500, 'query'], [560, 'query']]}, ['locked', 'locked', 'released', 'released', 'released']), ('control 37', {'timer_s': 120, 'events': [[30, 'query'], [60, 'overlap_occ'], [120, 'berth_occ'], [180, 'overlap_occ'], [185, 'overlap_occ'], [185, 'overlap_occ'], [245, 'query'], [275, 'query'], [280, 'overlap_occ'], [280, 'berth_occ'], [280, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 40', {'timer_s': 90, 'events': [[60, 'overlap_occ'], [90, 'query'], [135, 'berth_occ'], [195, 'overlap_occ'], [225, 'berth_occ'], [230, 'berth_clr'], [230, 'query']]}, ['locked', 'locked'])], [('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: expiry exactly on time', {'timer_s': 60, 'events': [[10, 'berth_occ'], [70, 'query']]}, ['released']), ('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('control 45', {'timer_s': 60, 'events': [[60, 'query'], [120, 'query'], [150, 'overlap_occ'], [155, 'berth_occ'], [245, 'overlap_occ'], [290, 'berth_occ'], [380, 'berth_clr'], [470, 'overlap_occ'], [470, 'query'], [475, 'berth_occ'], [595, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 48', {'timer_s': 45, 'events': [[60, 'overlap_occ'], [150, 'berth_occ'], [180, 'overlap_occ'], [180, 'berth_occ'], [270, 'berth_clr'], [275, 'berth_clr'], [275, 'overlap_occ'], [275, 'query']]}, ['locked']), ('control 51', {'timer_s': 90, 'events': [[90, 'berth_occ'], [150, 'berth_clr'], [195, 'query'], [255, 'berth_occ'], [315, 'query'], [320, 'query'], [320, 'overlap_occ'], [440, 'query']]}, ['locked', 'locked', 'locked', 'locked'])]]
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: expiry exactly on time | ['locked'] | ['released'] | Failed |
| regression: ninety second timer at one minute | ['locked', 'locked', 'locked'] | ['locked', 'locked', 'released'] | Failed |
| regression: berth clears after release | ['locked', 'released'] | ['released', 'released'] | Failed |
| control 24 | ['locked', 'locked', 'locked', 'locked'] | ['locked', 'locked', 'locked', 'locked'] | Passed |
| regression: track circuit bob restarts nothing | ['locked'] | ['released'] | Failed |
| control 1 | ['locked', 'locked', 'locked', 'locked'] | ['locked', 'locked', 'locked', 'locked'] | Passed |
| control 4 | ['locked'] | ['locked'] | Passed |
| control 7 | ['locked', 'locked'] | ['locked', 'locked'] | Passed |
SHA-256 / 124dd7ecb1605fe89cc022c47b211dbe3fb4dd2dfc1baa85ea997ec7e197efa8
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
T = x['timer_s']
start = None
overran = False
released = False
out = []
for t, ev in x['events']:
if start is not None and not released and not overran and (t - start) // 60 >= T // 60:
released = True
if ev == 'berth_occ':
if start is None:
start = t
elif ev == 'berth_clr':
if not released:
start = None
elif ev == 'overlap_occ':
if not released:
overran = True
elif ev == 'query':
out.append('released' if released else 'locked')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: expiry exactly on time', {'timer_s': 60, 'events': [[10, 'berth_occ'], [70, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('control 1', {'timer_s': 45, 'events': [[5, 'overlap_occ'], [35, 'query'], [65, 'berth_clr'], [125, 'query'], [170, 'query'], [170, 'berth_clr'], [230, 'berth_occ'], [350, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 4', {'timer_s': 90, 'events': [[60, 'berth_clr'], [150, 'berth_occ'], [155, 'berth_occ'], [155, 'query']]}, ['locked']), ('control 7', {'timer_s': 45, 'events': [[5, 'query'], [65, 'overlap_occ'], [110, 'overlap_occ'], [170, 'query']]}, ['locked', 'locked'])], [('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('sampled regression 33', {'timer_s': 60, 'events': [[60, 'berth_occ'], [60, 'query'], [120, 'query'], [150, 'berth_occ'], [240, 'berth_clr'], [360, 'query']]}, ['locked', 'released', 'released']), ('control 62', {'timer_s': 90, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [75, 'query'], [120, 'query'], [150, 'overlap_occ'], [240, 'query'], [245, 'query'], [365, 'query']]}, ['locked', 'released', 'released', 'released', 'released']), ('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('control 12', {'timer_s': 120, 'events': [[60, 'berth_occ'], [65, 'query'], [70, 'query'], [70, 'query'], [75, 'berth_occ'], [80, 'berth_occ'], [125, 'berth_clr'], [125, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 15', {'timer_s': 120, 'events': [[60, 'berth_clr'], [105, 'berth_clr'], [110, 'berth_clr'], [115, 'berth_clr'], [175, 'query'], [175, 'berth_clr'], [235, 'query'], [265, 'overlap_occ'], [270, 'berth_clr'], [390, 'query']]}, ['locked', 'locked', 'locked']), ('sampled regression 18', {'timer_s': 90, 'events': [[0, 'query'], [0, 'query'], [30, 'berth_occ'], [120, 'overlap_occ'], [210, 'berth_clr'], [215, 'query'], [245, 'berth_occ'], [365, 'query']]}, ['locked', 'locked', 'released', 'released'])], [('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('boundary: overrun into the overlap', {'timer_s': 60, 'events': [[0, 'berth_occ'], [20, 'overlap_occ'], [120, 'query']]}, ['locked']), ('control 23', {'timer_s': 45, 'events': [[0, 'query'], [5, 'berth_occ'], [95, 'berth_occ'], [185, 'berth_occ'], [245, 'query']]}, ['locked', 'released']), ('control 26', {'timer_s': 60, 'events': [[30, 'query'], [60, 'query'], [150, 'overlap_occ'], [150, 'query']]}, ['locked', 'locked', 'locked']), ('control 29', {'timer_s': 90, 'events': [[90, 'overlap_occ'], [95, 'query'], [95, 'berth_occ'], [185, 'query'], [230, 'query'], [260, 'query'], [350, 'berth_occ'], [410, 'query']]}, ['locked', 'locked', 'locked', 'locked', 'locked'])], [('regression: berth clears after release', {'timer_s': 60, 'events': [[0, 'berth_occ'], [60, 'query'], [65, 'berth_clr'], [70, 'query']]}, ['released', 'released']), ('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('sampled regression 32', {'timer_s': 90, 'events': [[60, 'berth_occ'], [105, 'berth_clr'], [105, 'berth_occ'], [105, 'query'], [135, 'query'], [195, 'berth_clr'], [255, 'query']]}, ['locked', 'locked', 'released']), ('control 62', {'timer_s': 90, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [75, 'query'], [120, 'query'], [150, 'overlap_occ'], [240, 'query'], [245, 'query'], [365, 'query']]}, ['locked', 'released', 'released', 'released', 'released']), ('regression: expiry after a minute boundary', {'timer_s': 120, 'events': [[30, 'berth_occ'], [140, 'query'], [150, 'query']]}, ['locked', 'released']), ('control 34', {'timer_s': 60, 'events': [[5, 'query'], [35, 'query'], [80, 'berth_occ'], [170, 'berth_occ'], [260, 'berth_occ'], [320, 'berth_occ'], [350, 'overlap_occ'], [395, 'overlap_occ'], [440, 'query'], [500, 'query'], [560, 'query']]}, ['locked', 'locked', 'released', 'released', 'released']), ('control 37', {'timer_s': 120, 'events': [[30, 'query'], [60, 'overlap_occ'], [120, 'berth_occ'], [180, 'overlap_occ'], [185, 'overlap_occ'], [185, 'overlap_occ'], [245, 'query'], [275, 'query'], [280, 'overlap_occ'], [280, 'berth_occ'], [280, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 40', {'timer_s': 90, 'events': [[60, 'overlap_occ'], [90, 'query'], [135, 'berth_occ'], [195, 'overlap_occ'], [225, 'berth_occ'], [230, 'berth_clr'], [230, 'query']]}, ['locked', 'locked'])], [('regression: ninety second timer at one minute', {'timer_s': 90, 'events': [[0, 'berth_occ'], [60, 'query'], [89, 'query'], [90, 'query']]}, ['locked', 'locked', 'released']), ('regression: track circuit bob restarts nothing', {'timer_s': 60, 'events': [[0, 'berth_occ'], [40, 'berth_occ'], [60, 'query']]}, ['released']), ('control 24', {'timer_s': 90, 'events': [[30, 'query'], [60, 'berth_occ'], [120, 'overlap_occ'], [210, 'query'], [240, 'berth_clr'], [245, 'berth_occ'], [245, 'query'], [245, 'berth_clr'], [305, 'berth_occ'], [335, 'overlap_occ'], [395, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('regression: expiry exactly on time', {'timer_s': 60, 'events': [[10, 'berth_occ'], [70, 'query']]}, ['released']), ('regression: train stops at time zero', {'timer_s': 60, 'events': [[0, 'berth_occ'], [30, 'berth_occ'], [60, 'query']]}, ['released']), ('control 45', {'timer_s': 60, 'events': [[60, 'query'], [120, 'query'], [150, 'overlap_occ'], [155, 'berth_occ'], [245, 'overlap_occ'], [290, 'berth_occ'], [380, 'berth_clr'], [470, 'overlap_occ'], [470, 'query'], [475, 'berth_occ'], [595, 'query']]}, ['locked', 'locked', 'locked', 'locked']), ('control 48', {'timer_s': 45, 'events': [[60, 'overlap_occ'], [150, 'berth_occ'], [180, 'overlap_occ'], [180, 'berth_occ'], [270, 'berth_clr'], [275, 'berth_clr'], [275, 'overlap_occ'], [275, 'query']]}, ['locked']), ('control 51', {'timer_s': 90, 'events': [[90, 'berth_occ'], [150, 'berth_clr'], [195, 'query'], [255, 'berth_occ'], [315, 'query'], [320, 'query'], [320, 'overlap_occ'], [440, 'query']]}, ['locked', 'locked', 'locked', 'locked'])]]
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: expiry exactly on time | ['released'] | ['released'] | Passed |
| regression: ninety second timer at one minute | ['released', 'released', 'released'] | ['locked', 'locked', 'released'] | Failed |
| regression: berth clears after release | ['released', 'released'] | ['released', 'released'] | Passed |
| control 24 | ['locked', 'released', 'released', 'released'] | ['locked', 'locked', 'locked', 'locked'] | Failed |
| regression: track circuit bob restarts nothing | ['released'] | ['released'] | Passed |
| control 1 | ['locked', 'locked', 'locked', 'locked'] | ['locked', 'locked', 'locked', 'locked'] | Passed |
| control 4 | ['locked'] | ['locked'] | Passed |
| control 7 | ['locked', 'locked'] | ['locked', 'locked'] | Passed |
SHA-256 / 2fe27c678942d12fecb436d1aac26274e9de6712a1ea1ca8239f7792bf222431
HELD IN THE MEMBER ARCHIVE
The verified repair and its recorded checks are member-only.
This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.
Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.
Member access is invitation-based. Sign in with your invited account to inspect the repair.
Sign in to the archive ↗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:49.066140+00:00.
Case digest / ac8e3dd21325ea8804daa7a7dc081891e3bdc6d47442a5f4d9cb026d4d15b392