FA-67641 / Elevator dispatch scheduling / Open access
Door obstruction reopen and nudging: reopen limit · case 01
The doors reopen a third time instead of nudging, or safety-edge contacts bring nudging forward.
ROOT CAUSE
Nudging starts only on the fourth obstruction.
VERIFIED REPAIR
Start nudging on the third curtain obstruction.
Unsuccessful approach: Counting safety-edge contacts towards the limit nudges after edge reopenings.
Case contract
During a door cycle each light-curtain obstruction reopens the doors and counts; the third obstruction, or an obstruction while the curtain has been blocked continuously for 20 s or more since the first unbroken obstruction, starts nudging (slow close, curtain ignored). While nudging, curtain obstructions are ignored. The mechanical safety edge always reopens and does not affect counting. unblock ends a continuous blockage. closed ends the cycle and resets everything.
Why this case matters
Lift group controllers make these decisions many times per minute; a wrong answer strands passengers, wastes trips or overrides a safety rule.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
count = 0
nudge = False
block_start = None
out = []
for t, ev in x['events']:
if ev == 'obstruct':
if block_start is None:
block_start = t
if nudge:
out.append('ignored')
else:
count += 1
if count > 3 or t - block_start >= 20:
nudge = True
out.append('nudge')
else:
out.append('reopen')
elif ev == 'unblock':
block_start = None
elif ev == 'edge':
out.append('reopen')
elif ev == 'closed':
count = 0
nudge = False
block_start = None
out.append('done')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 4', {'events': [[5, 'edge'], [10, 'unblock'], [11, 'obstruct'], [19, 'closed']]}, ['reopen', 'reopen', 'done']), ('control 7', {'events': [[2, 'unblock'], [10, 'edge'], [18, 'obstruct'], [23, 'unblock'], [28, 'edge'], [33, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 10', {'events': [[8, 'edge'], [13, 'obstruct'], [18, 'edge'], [30, 'unblock'], [35, 'obstruct'], [40, 'obstruct'], [42, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'])], [('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 17', {'events': [[5, 'unblock'], [13, 'unblock'], [14, 'closed'], [26, 'obstruct'], [34, 'edge'], [36, 'obstruct'], [48, 'unblock'], [60, 'obstruct'], [72, 'unblock']]}, ['done', 'reopen', 'reopen', 'reopen', 'nudge']), ('sampled regression 13', {'events': [[5, 'unblock'], [13, 'obstruct'], [21, 'closed'], [29, 'edge'], [34, 'obstruct'], [46, 'obstruct'], [47, 'unblock'], [55, 'obstruct'], [63, 'closed'], [64, 'unblock']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'done']), ('boundary: new cycle after closing', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct'], [5, 'unblock']]}, ['reopen', 'reopen', 'done', 'reopen']), ('control 12', {'events': [[5, 'obstruct'], [13, 'edge'], [15, 'unblock'], [16, 'obstruct'], [21, 'unblock'], [22, 'edge'], [30, 'closed'], [32, 'obstruct'], [44, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen']), ('sampled regression 15', {'events': [[8, 'obstruct'], [9, 'obstruct'], [10, 'obstruct'], [11, 'unblock'], [16, 'obstruct'], [24, 'obstruct'], [29, 'edge']]}, ['reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'reopen']), ('sampled regression 18', {'events': [[12, 'obstruct'], [20, 'obstruct'], [22, 'obstruct']]}, ['reopen', 'reopen', 'nudge'])], [('regression: curtain broken then blocked again', {'events': [[0, 'obstruct'], [5, 'unblock'], [15, 'obstruct'], [26, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 28', {'events': [[12, 'unblock'], [20, 'edge'], [32, 'edge'], [33, 'obstruct'], [35, 'obstruct'], [40, 'obstruct'], [41, 'obstruct'], [53, 'obstruct'], [58, 'closed']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'done']), ('control 29', {'events': [[8, 'edge'], [10, 'obstruct'], [12, 'obstruct'], [20, 'closed']]}, ['reopen', 'reopen', 'reopen', 'done']), ('boundary: curtain held for twenty seconds', {'events': [[0, 'obstruct'], [20, 'obstruct']]}, ['reopen', 'nudge']), ('control 23', {'events': [[1, 'unblock'], [6, 'unblock'], [18, 'obstruct'], [30, 'closed']]}, ['reopen', 'done']), ('sampled regression 26', {'events': [[12, 'closed'], [13, 'closed'], [15, 'obstruct'], [17, 'obstruct'], [19, 'obstruct']]}, ['done', 'done', 'reopen', 'reopen', 'nudge']), ('sampled regression 32', {'events': [[8, 'closed'], [13, 'unblock'], [15, 'obstruct'], [16, 'obstruct'], [17, 'obstruct'], [19, 'unblock'], [31, 'obstruct'], [36, 'obstruct']]}, ['done', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored'])], [('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 64', {'events': [[8, 'obstruct'], [13, 'edge'], [18, 'unblock'], [26, 'unblock'], [34, 'obstruct'], [36, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'nudge']), ('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('sampled regression 34', {'events': [[8, 'edge'], [16, 'obstruct'], [24, 'obstruct'], [36, 'closed'], [48, 'obstruct'], [60, 'obstruct'], [62, 'obstruct'], [64, 'unblock'], [72, 'obstruct'], [80, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen', 'nudge', 'ignored']), ('control 37', {'events': [[2, 'closed'], [4, 'closed'], [9, 'obstruct'], [21, 'edge']]}, ['done', 'done', 'reopen', 'reopen']), ('control 40', {'events': [[2, 'closed'], [7, 'obstruct'], [15, 'edge'], [16, 'obstruct'], [18, 'closed']]}, ['done', 'reopen', 'reopen', 'reopen', 'done'])], [('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 72', {'events': [[12, 'obstruct'], [14, 'obstruct'], [15, 'unblock'], [20, 'obstruct'], [32, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 45', {'events': [[5, 'edge'], [17, 'closed'], [22, 'obstruct'], [24, 'closed']]}, ['reopen', 'done', 'reopen', 'done']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('control 51', {'events': [[8, 'closed'], [9, 'closed'], [14, 'obstruct'], [26, 'closed'], [38, 'obstruct']]}, ['done', 'done', 'reopen', 'done', 'reopen'])]]
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: third obstruction | ['reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'nudge'] | Failed |
| boundary: edge contacts do not count | ['reopen', 'reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Passed |
| regression: closing clears nudging | ['reopen', 'reopen', 'reopen', 'done', 'reopen'] | ['reopen', 'reopen', 'nudge', 'done', 'reopen'] | Failed |
| sampled regression 1 | ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'done'] | ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done'] | Failed |
| regression: safety edge while nudging | ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'] | ['reopen', 'reopen', 'nudge', 'reopen', 'ignored'] | Failed |
| control 4 | ['reopen', 'reopen', 'done'] | ['reopen', 'reopen', 'done'] | Passed |
| control 7 | ['reopen', 'reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Passed |
| sampled regression 10 | ['reopen', 'reopen', 'reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'] | Failed |
SHA-256 / d0fa54837017071f0c150e408d233bcbccdebb96d13ba23b5d35fca0e23bef59
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
count = 0
nudge = False
block_start = None
out = []
for t, ev in x['events']:
if ev == 'obstruct':
if block_start is None:
block_start = t
if nudge:
out.append('ignored')
else:
count += 1
if count >= 3 or t - block_start >= 20:
nudge = True
out.append('nudge')
else:
out.append('reopen')
elif ev == 'unblock':
block_start = None
elif ev == 'edge':
count += 1
out.append('reopen')
elif ev == 'closed':
count = 0
nudge = False
block_start = None
out.append('done')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 4', {'events': [[5, 'edge'], [10, 'unblock'], [11, 'obstruct'], [19, 'closed']]}, ['reopen', 'reopen', 'done']), ('control 7', {'events': [[2, 'unblock'], [10, 'edge'], [18, 'obstruct'], [23, 'unblock'], [28, 'edge'], [33, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 10', {'events': [[8, 'edge'], [13, 'obstruct'], [18, 'edge'], [30, 'unblock'], [35, 'obstruct'], [40, 'obstruct'], [42, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'])], [('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 17', {'events': [[5, 'unblock'], [13, 'unblock'], [14, 'closed'], [26, 'obstruct'], [34, 'edge'], [36, 'obstruct'], [48, 'unblock'], [60, 'obstruct'], [72, 'unblock']]}, ['done', 'reopen', 'reopen', 'reopen', 'nudge']), ('sampled regression 13', {'events': [[5, 'unblock'], [13, 'obstruct'], [21, 'closed'], [29, 'edge'], [34, 'obstruct'], [46, 'obstruct'], [47, 'unblock'], [55, 'obstruct'], [63, 'closed'], [64, 'unblock']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'done']), ('boundary: new cycle after closing', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct'], [5, 'unblock']]}, ['reopen', 'reopen', 'done', 'reopen']), ('control 12', {'events': [[5, 'obstruct'], [13, 'edge'], [15, 'unblock'], [16, 'obstruct'], [21, 'unblock'], [22, 'edge'], [30, 'closed'], [32, 'obstruct'], [44, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen']), ('sampled regression 15', {'events': [[8, 'obstruct'], [9, 'obstruct'], [10, 'obstruct'], [11, 'unblock'], [16, 'obstruct'], [24, 'obstruct'], [29, 'edge']]}, ['reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'reopen']), ('sampled regression 18', {'events': [[12, 'obstruct'], [20, 'obstruct'], [22, 'obstruct']]}, ['reopen', 'reopen', 'nudge'])], [('regression: curtain broken then blocked again', {'events': [[0, 'obstruct'], [5, 'unblock'], [15, 'obstruct'], [26, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 28', {'events': [[12, 'unblock'], [20, 'edge'], [32, 'edge'], [33, 'obstruct'], [35, 'obstruct'], [40, 'obstruct'], [41, 'obstruct'], [53, 'obstruct'], [58, 'closed']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'done']), ('control 29', {'events': [[8, 'edge'], [10, 'obstruct'], [12, 'obstruct'], [20, 'closed']]}, ['reopen', 'reopen', 'reopen', 'done']), ('boundary: curtain held for twenty seconds', {'events': [[0, 'obstruct'], [20, 'obstruct']]}, ['reopen', 'nudge']), ('control 23', {'events': [[1, 'unblock'], [6, 'unblock'], [18, 'obstruct'], [30, 'closed']]}, ['reopen', 'done']), ('sampled regression 26', {'events': [[12, 'closed'], [13, 'closed'], [15, 'obstruct'], [17, 'obstruct'], [19, 'obstruct']]}, ['done', 'done', 'reopen', 'reopen', 'nudge']), ('sampled regression 32', {'events': [[8, 'closed'], [13, 'unblock'], [15, 'obstruct'], [16, 'obstruct'], [17, 'obstruct'], [19, 'unblock'], [31, 'obstruct'], [36, 'obstruct']]}, ['done', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored'])], [('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 64', {'events': [[8, 'obstruct'], [13, 'edge'], [18, 'unblock'], [26, 'unblock'], [34, 'obstruct'], [36, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'nudge']), ('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('sampled regression 34', {'events': [[8, 'edge'], [16, 'obstruct'], [24, 'obstruct'], [36, 'closed'], [48, 'obstruct'], [60, 'obstruct'], [62, 'obstruct'], [64, 'unblock'], [72, 'obstruct'], [80, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen', 'nudge', 'ignored']), ('control 37', {'events': [[2, 'closed'], [4, 'closed'], [9, 'obstruct'], [21, 'edge']]}, ['done', 'done', 'reopen', 'reopen']), ('control 40', {'events': [[2, 'closed'], [7, 'obstruct'], [15, 'edge'], [16, 'obstruct'], [18, 'closed']]}, ['done', 'reopen', 'reopen', 'reopen', 'done'])], [('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 72', {'events': [[12, 'obstruct'], [14, 'obstruct'], [15, 'unblock'], [20, 'obstruct'], [32, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 45', {'events': [[5, 'edge'], [17, 'closed'], [22, 'obstruct'], [24, 'closed']]}, ['reopen', 'done', 'reopen', 'done']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('control 51', {'events': [[8, 'closed'], [9, 'closed'], [14, 'obstruct'], [26, 'closed'], [38, 'obstruct']]}, ['done', 'done', 'reopen', 'done', 'reopen'])]]
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: third obstruction | ['reopen', 'reopen', 'nudge'] | ['reopen', 'reopen', 'nudge'] | Passed |
| boundary: edge contacts do not count | ['reopen', 'reopen', 'nudge', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Failed |
| regression: closing clears nudging | ['reopen', 'reopen', 'nudge', 'done', 'reopen'] | ['reopen', 'reopen', 'nudge', 'done', 'reopen'] | Passed |
| sampled regression 1 | ['reopen', 'done', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'ignored', 'done'] | ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done'] | Failed |
| regression: safety edge while nudging | ['reopen', 'reopen', 'nudge', 'reopen', 'ignored'] | ['reopen', 'reopen', 'nudge', 'reopen', 'ignored'] | Passed |
| control 4 | ['reopen', 'reopen', 'done'] | ['reopen', 'reopen', 'done'] | Passed |
| control 7 | ['reopen', 'reopen', 'reopen', 'nudge'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Failed |
| sampled regression 10 | ['reopen', 'reopen', 'reopen', 'nudge', 'ignored'] | ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'] | Failed |
SHA-256 / f09cdddb3d219ff33811879b9731bbad9a86cb98adc12835bf8f6b96d966b43a
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(x):
count = 0
nudge = False
block_start = None
out = []
for t, ev in x['events']:
if ev == 'obstruct':
if block_start is None:
block_start = t
if nudge:
out.append('ignored')
else:
count += 1
if count >= 3 or t - block_start >= 20:
nudge = True
out.append('nudge')
else:
out.append('reopen')
elif ev == 'unblock':
block_start = None
elif ev == 'edge':
out.append('reopen')
elif ev == 'closed':
count = 0
nudge = False
block_start = None
out.append('done')
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 4', {'events': [[5, 'edge'], [10, 'unblock'], [11, 'obstruct'], [19, 'closed']]}, ['reopen', 'reopen', 'done']), ('control 7', {'events': [[2, 'unblock'], [10, 'edge'], [18, 'obstruct'], [23, 'unblock'], [28, 'edge'], [33, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 10', {'events': [[8, 'edge'], [13, 'obstruct'], [18, 'edge'], [30, 'unblock'], [35, 'obstruct'], [40, 'obstruct'], [42, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'])], [('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 17', {'events': [[5, 'unblock'], [13, 'unblock'], [14, 'closed'], [26, 'obstruct'], [34, 'edge'], [36, 'obstruct'], [48, 'unblock'], [60, 'obstruct'], [72, 'unblock']]}, ['done', 'reopen', 'reopen', 'reopen', 'nudge']), ('sampled regression 13', {'events': [[5, 'unblock'], [13, 'obstruct'], [21, 'closed'], [29, 'edge'], [34, 'obstruct'], [46, 'obstruct'], [47, 'unblock'], [55, 'obstruct'], [63, 'closed'], [64, 'unblock']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'done']), ('boundary: new cycle after closing', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct'], [5, 'unblock']]}, ['reopen', 'reopen', 'done', 'reopen']), ('control 12', {'events': [[5, 'obstruct'], [13, 'edge'], [15, 'unblock'], [16, 'obstruct'], [21, 'unblock'], [22, 'edge'], [30, 'closed'], [32, 'obstruct'], [44, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen']), ('sampled regression 15', {'events': [[8, 'obstruct'], [9, 'obstruct'], [10, 'obstruct'], [11, 'unblock'], [16, 'obstruct'], [24, 'obstruct'], [29, 'edge']]}, ['reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'reopen']), ('sampled regression 18', {'events': [[12, 'obstruct'], [20, 'obstruct'], [22, 'obstruct']]}, ['reopen', 'reopen', 'nudge'])], [('regression: curtain broken then blocked again', {'events': [[0, 'obstruct'], [5, 'unblock'], [15, 'obstruct'], [26, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 28', {'events': [[12, 'unblock'], [20, 'edge'], [32, 'edge'], [33, 'obstruct'], [35, 'obstruct'], [40, 'obstruct'], [41, 'obstruct'], [53, 'obstruct'], [58, 'closed']]}, ['reopen', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'done']), ('control 29', {'events': [[8, 'edge'], [10, 'obstruct'], [12, 'obstruct'], [20, 'closed']]}, ['reopen', 'reopen', 'reopen', 'done']), ('boundary: curtain held for twenty seconds', {'events': [[0, 'obstruct'], [20, 'obstruct']]}, ['reopen', 'nudge']), ('control 23', {'events': [[1, 'unblock'], [6, 'unblock'], [18, 'obstruct'], [30, 'closed']]}, ['reopen', 'done']), ('sampled regression 26', {'events': [[12, 'closed'], [13, 'closed'], [15, 'obstruct'], [17, 'obstruct'], [19, 'obstruct']]}, ['done', 'done', 'reopen', 'reopen', 'nudge']), ('sampled regression 32', {'events': [[8, 'closed'], [13, 'unblock'], [15, 'obstruct'], [16, 'obstruct'], [17, 'obstruct'], [19, 'unblock'], [31, 'obstruct'], [36, 'obstruct']]}, ['done', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored'])], [('regression: closing clears nudging', {'events': [[0, 'obstruct'], [1, 'obstruct'], [2, 'obstruct'], [3, 'closed'], [4, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'done', 'reopen']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 64', {'events': [[8, 'obstruct'], [13, 'edge'], [18, 'unblock'], [26, 'unblock'], [34, 'obstruct'], [36, 'obstruct']]}, ['reopen', 'reopen', 'reopen', 'nudge']), ('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('sampled regression 34', {'events': [[8, 'edge'], [16, 'obstruct'], [24, 'obstruct'], [36, 'closed'], [48, 'obstruct'], [60, 'obstruct'], [62, 'obstruct'], [64, 'unblock'], [72, 'obstruct'], [80, 'unblock']]}, ['reopen', 'reopen', 'reopen', 'done', 'reopen', 'reopen', 'nudge', 'ignored']), ('control 37', {'events': [[2, 'closed'], [4, 'closed'], [9, 'obstruct'], [21, 'edge']]}, ['done', 'done', 'reopen', 'reopen']), ('control 40', {'events': [[2, 'closed'], [7, 'obstruct'], [15, 'edge'], [16, 'obstruct'], [18, 'closed']]}, ['done', 'reopen', 'reopen', 'reopen', 'done'])], [('regression: third obstruction', {'events': [[1, 'obstruct'], [2, 'unblock'], [3, 'obstruct'], [4, 'unblock'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge']), ('boundary: edge contacts do not count', {'events': [[1, 'obstruct'], [2, 'edge'], [3, 'unblock'], [4, 'obstruct'], [5, 'edge']]}, ['reopen', 'reopen', 'reopen', 'reopen']), ('sampled regression 72', {'events': [[12, 'obstruct'], [14, 'obstruct'], [15, 'unblock'], [20, 'obstruct'], [32, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('sampled regression 1', {'events': [[8, 'obstruct'], [13, 'closed'], [18, 'obstruct'], [26, 'edge'], [28, 'obstruct'], [29, 'obstruct'], [41, 'obstruct'], [42, 'obstruct'], [54, 'obstruct'], [66, 'closed']]}, ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done']), ('regression: safety edge while nudging', {'events': [[1, 'obstruct'], [2, 'obstruct'], [3, 'obstruct'], [4, 'edge'], [5, 'obstruct']]}, ['reopen', 'reopen', 'nudge', 'reopen', 'ignored']), ('control 45', {'events': [[5, 'edge'], [17, 'closed'], [22, 'obstruct'], [24, 'closed']]}, ['reopen', 'done', 'reopen', 'done']), ('sampled regression 48', {'events': [[2, 'obstruct'], [7, 'obstruct'], [15, 'obstruct'], [27, 'obstruct'], [35, 'unblock']]}, ['reopen', 'reopen', 'nudge', 'ignored']), ('control 51', {'events': [[8, 'closed'], [9, 'closed'], [14, 'obstruct'], [26, 'closed'], [38, 'obstruct']]}, ['done', 'done', 'reopen', 'done', 'reopen'])]]
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: third obstruction | ['reopen', 'reopen', 'nudge'] | ['reopen', 'reopen', 'nudge'] | Passed |
| boundary: edge contacts do not count | ['reopen', 'reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Passed |
| regression: closing clears nudging | ['reopen', 'reopen', 'nudge', 'done', 'reopen'] | ['reopen', 'reopen', 'nudge', 'done', 'reopen'] | Passed |
| sampled regression 1 | ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done'] | ['reopen', 'done', 'reopen', 'reopen', 'reopen', 'nudge', 'ignored', 'ignored', 'ignored', 'done'] | Passed |
| regression: safety edge while nudging | ['reopen', 'reopen', 'nudge', 'reopen', 'ignored'] | ['reopen', 'reopen', 'nudge', 'reopen', 'ignored'] | Passed |
| control 4 | ['reopen', 'reopen', 'done'] | ['reopen', 'reopen', 'done'] | Passed |
| control 7 | ['reopen', 'reopen', 'reopen', 'reopen'] | ['reopen', 'reopen', 'reopen', 'reopen'] | Passed |
| sampled regression 10 | ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'] | ['reopen', 'reopen', 'reopen', 'reopen', 'nudge'] | Passed |
SHA-256 / 50ef08450272a33d524f062f94f8e6b05a4ce7b3f17e787d89a161763993adc4
Verification & scope
Stipulated toy lift-control contract for a bounded teaching model; it makes no claim of conformance to any lift code or vendor dispatcher 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:54.670933+00:00.
Case digest / f4554cba986d6d2e74cb03a369ba8d32b87bdf242f310bd3da90f7012dcea56a