FA-92301 / PLC ladder logic scan cycles / Open access
Horn silence is not cancelled by a new alarm · case 01
Once silenced, later alarms never sound the horn.
ROOT CAUSE
Nothing clears the silenced flag on a new activation.
VERIFIED REPAIR
Any new activation cancels silence.
Unsuccessful approach: Cancelling silence only for high alarms keeps new low alarms silent.
Case contract
Stack light and horn logic. alarms is a list of [name, high|low]; each scan gives the active alarm names plus optional ack and silence buttons. An alarm becomes unacknowledged on its inactive-to-active transition and stops being unacknowledged when it clears or ack is pressed. Any new activation cancels silence; silence (pressed after that) mutes the horn. The lamp is red if any high alarm is active, else amber if any alarm is active, else off; it flashes if an unacknowledged alarm of the displayed level exists. The horn sounds while any unacknowledged alarm exists and not silenced. Return [color, flashing, horn] per scan.
Why this case matters
Ladder programs are executed as repeated scans; each defect here changes what a rung, timer, counter or data-table instruction reports on a particular scan, which is how commissioning and field faults are actually observed.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(alarms, scans):
level = dict(alarms)
prev = set()
unacked = set()
silenced = False
out = []
for s in scans:
active = set(s.get('active', []))
new = active - prev
unacked = (unacked | new) & active
if s.get('ack'):
unacked = set()
if s.get('silence'):
silenced = True
if any(level[a] == 'high' for a in active):
shown = 'high'
elif active:
shown = 'low'
else:
shown = None
color = {'high': 'red', 'low': 'amber', None: 'off'}[shown]
flashing = any(level[a] == shown for a in unacked)
horn = bool(unacked) and not silenced
prev = active
out.append([color, flashing, horn])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'ack': True},
{'active': ['TT300']},
{'active': ['ZS400'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['ZS400'], 'silence': True},
{'active': ['TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400'], 'ack': True}]],
[['amber', False, False],
['amber', False, False],
['red', False, False],
['off', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'silence': True},
{'active': ['ZS400']},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True}]],
[['amber', True, False],
['red', True, True],
['amber', True, True],
['red', True, True],
['red', True, False],
['red', True, False]]],
['control: scenario 3',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'ack': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101'], 'ack': True}]],
[['off', False, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', False, False]]]],
[['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'ack': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': []}]],
[['off', False, False],
['amber', True, True],
['red', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['off', False, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['ZS400'], 'silence': True},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200']}]],
[['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', True, True]]],
['control: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['TT300']},
{'active': ['PT101', 'TT300']},
{'active': ['PT101']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', False, False],
['amber', False, False]]]],
[['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101'], 'silence': True},
{'active': ['LT200', 'PT101']},
{'active': []},
{'active': []},
{'active': []},
{'active': [], 'ack': True},
{'active': ['LT200']},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['amber', True, True],
['amber', True, True]]],
['regression: scenario 12',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['ZS400'], 'silence': True},
{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': [], 'silence': True},
{'active': ['LT200']},
{'active': ['LT200']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['off', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400'], 'silence': True},
{'active': ['ZS400']},
{'active': []},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101', 'TT300', 'ZS400']}]],
[['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, True]]]],
[['regression: scenario 4',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200'], 'silence': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['amber', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True]]],
['regression: scenario 21',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, True],
['red', False, False],
['amber', False, False]]]],
[['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['PT101'], 'silence': True},
{'active': ['TT300'], 'ack': True, 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': [], 'ack': True}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False],
['off', False, False],
['red', True, True],
['red', True, False],
['amber', False, False],
['off', False, False],
['off', False, False],
['off', False, False]]],
['regression: scenario 23',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['TT300']},
{'active': ['TT300'], 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['ZS400']},
{'active': ['LT200', 'ZS400'], 'silence': True},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']}]],
[['off', False, False],
['amber', True, True],
['amber', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['red', True, True],
['red', False, False],
['amber', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False]]]]]
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: escalation sequence | [['amber', True, True], ['amber', True, False], ['red', True, False], ['red', False, False], ['amber', False, False], ['off', False, False]] | [['amber', True, True], ['amber', True, False], ['red', True, True], ['red', False, False], ['amber', False, False], ['off', False, False]] | Failed |
| regression: silence then new low alarm | [['red', True, True], ['red', True, False], ['red', True, False]] | [['red', True, True], ['red', True, False], ['red', True, True]] | Failed |
| control: alarm clears unacknowledged | [['red', True, True], ['off', False, False], ['amber', True, True]] | [['red', True, True], ['off', False, False], ['amber', True, True]] | Passed |
| control: low alarm while high acked | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | Passed |
| control: alarm present at first scan | [['red', True, True], ['red', True, True]] | [['red', True, True], ['red', True, True]] | Passed |
| regression: scenario 1 | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, False], ['red', True, False], ['red', True, False], ['red', False, False]] | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, True], ['red', True, True], ['red', True, True], ['red', False, False]] | Failed |
| regression: scenario 2 | [['amber', True, False], ['red', True, False], ['amber', True, False], ['red', True, False], ['red', True, False], ['red', True, False]] | [['amber', True, False], ['red', True, True], ['amber', True, True], ['red', True, True], ['red', True, False], ['red', True, False]] | Failed |
| control: scenario 3 | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | Passed |
SHA-256 / 8165f35001fc9ff0f1075917e4957c57213eb80e9ecfb4f9867c49c69e57562f
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(alarms, scans):
level = dict(alarms)
prev = set()
unacked = set()
silenced = False
out = []
for s in scans:
active = set(s.get('active', []))
new = active - prev
if any(level[a] == 'high' for a in new):
silenced = False
unacked = (unacked | new) & active
if s.get('ack'):
unacked = set()
if s.get('silence'):
silenced = True
if any(level[a] == 'high' for a in active):
shown = 'high'
elif active:
shown = 'low'
else:
shown = None
color = {'high': 'red', 'low': 'amber', None: 'off'}[shown]
flashing = any(level[a] == shown for a in unacked)
horn = bool(unacked) and not silenced
prev = active
out.append([color, flashing, horn])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'ack': True},
{'active': ['TT300']},
{'active': ['ZS400'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['ZS400'], 'silence': True},
{'active': ['TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400'], 'ack': True}]],
[['amber', False, False],
['amber', False, False],
['red', False, False],
['off', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'silence': True},
{'active': ['ZS400']},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True}]],
[['amber', True, False],
['red', True, True],
['amber', True, True],
['red', True, True],
['red', True, False],
['red', True, False]]],
['control: scenario 3',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'ack': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101'], 'ack': True}]],
[['off', False, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', False, False]]]],
[['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'ack': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': []}]],
[['off', False, False],
['amber', True, True],
['red', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['off', False, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['ZS400'], 'silence': True},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200']}]],
[['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', True, True]]],
['control: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['TT300']},
{'active': ['PT101', 'TT300']},
{'active': ['PT101']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', False, False],
['amber', False, False]]]],
[['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101'], 'silence': True},
{'active': ['LT200', 'PT101']},
{'active': []},
{'active': []},
{'active': []},
{'active': [], 'ack': True},
{'active': ['LT200']},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['amber', True, True],
['amber', True, True]]],
['regression: scenario 12',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['ZS400'], 'silence': True},
{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': [], 'silence': True},
{'active': ['LT200']},
{'active': ['LT200']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['off', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400'], 'silence': True},
{'active': ['ZS400']},
{'active': []},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101', 'TT300', 'ZS400']}]],
[['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, True]]]],
[['regression: scenario 4',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200'], 'silence': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['amber', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True]]],
['regression: scenario 21',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, True],
['red', False, False],
['amber', False, False]]]],
[['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['PT101'], 'silence': True},
{'active': ['TT300'], 'ack': True, 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': [], 'ack': True}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False],
['off', False, False],
['red', True, True],
['red', True, False],
['amber', False, False],
['off', False, False],
['off', False, False],
['off', False, False]]],
['regression: scenario 23',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['TT300']},
{'active': ['TT300'], 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['ZS400']},
{'active': ['LT200', 'ZS400'], 'silence': True},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']}]],
[['off', False, False],
['amber', True, True],
['amber', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['red', True, True],
['red', False, False],
['amber', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False]]]]]
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: escalation sequence | [['amber', True, True], ['amber', True, False], ['red', True, True], ['red', False, False], ['amber', False, False], ['off', False, False]] | [['amber', True, True], ['amber', True, False], ['red', True, True], ['red', False, False], ['amber', False, False], ['off', False, False]] | Passed |
| regression: silence then new low alarm | [['red', True, True], ['red', True, False], ['red', True, False]] | [['red', True, True], ['red', True, False], ['red', True, True]] | Failed |
| control: alarm clears unacknowledged | [['red', True, True], ['off', False, False], ['amber', True, True]] | [['red', True, True], ['off', False, False], ['amber', True, True]] | Passed |
| control: low alarm while high acked | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | Passed |
| control: alarm present at first scan | [['red', True, True], ['red', True, True]] | [['red', True, True], ['red', True, True]] | Passed |
| regression: scenario 1 | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, False], ['red', True, False], ['red', True, False], ['red', False, False]] | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, True], ['red', True, True], ['red', True, True], ['red', False, False]] | Failed |
| regression: scenario 2 | [['amber', True, False], ['red', True, True], ['amber', True, True], ['red', True, True], ['red', True, False], ['red', True, False]] | [['amber', True, False], ['red', True, True], ['amber', True, True], ['red', True, True], ['red', True, False], ['red', True, False]] | Passed |
| control: scenario 3 | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | Passed |
SHA-256 / 5d2cb0f0a7d82a973eddc65b95f3332fedab7a8fe5bfbadcb6ca600ecfae3fe7
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(alarms, scans):
level = dict(alarms)
prev = set()
unacked = set()
silenced = False
out = []
for s in scans:
active = set(s.get('active', []))
new = active - prev
if new:
silenced = False
unacked = (unacked | new) & active
if s.get('ack'):
unacked = set()
if s.get('silence'):
silenced = True
if any(level[a] == 'high' for a in active):
shown = 'high'
elif active:
shown = 'low'
else:
shown = None
color = {'high': 'red', 'low': 'amber', None: 'off'}[shown]
flashing = any(level[a] == shown for a in unacked)
horn = bool(unacked) and not silenced
prev = active
out.append([color, flashing, horn])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'ack': True},
{'active': ['TT300']},
{'active': ['ZS400'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['ZS400'], 'silence': True},
{'active': ['TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400'], 'ack': True}]],
[['amber', False, False],
['amber', False, False],
['red', False, False],
['off', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300'], 'silence': True},
{'active': ['ZS400']},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True}]],
[['amber', True, False],
['red', True, True],
['amber', True, True],
['red', True, True],
['red', True, False],
['red', True, False]]],
['control: scenario 3',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'ack': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101'], 'ack': True}]],
[['off', False, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', False, False]]]],
[['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': ['LT200', 'TT300']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'ack': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': []}]],
[['off', False, False],
['amber', True, True],
['red', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['off', False, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['ZS400'], 'silence': True},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200']}]],
[['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', True, True]]],
['control: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['TT300']},
{'active': ['PT101', 'TT300']},
{'active': ['PT101']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['amber', False, False],
['amber', False, False]]]],
[['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101'], 'silence': True},
{'active': ['LT200', 'PT101']},
{'active': []},
{'active': []},
{'active': []},
{'active': [], 'ack': True},
{'active': ['LT200']},
{'active': ['LT200', 'TT300']}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['amber', True, True],
['amber', True, True]]],
['regression: scenario 12',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['ZS400'], 'silence': True},
{'active': ['PT101']},
{'active': ['LT200', 'PT101']},
{'active': [], 'silence': True},
{'active': ['LT200']},
{'active': ['LT200']},
{'active': ['LT200', 'PT101']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', False, False],
['red', True, False],
['red', True, True],
['red', True, True],
['off', False, False],
['amber', True, True],
['amber', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 2',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400'], 'silence': True},
{'active': ['ZS400']},
{'active': []},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']},
{'active': ['PT101', 'TT300', 'ZS400']}]],
[['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, True]]]],
[['regression: scenario 4',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['LT200'], 'silence': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['amber', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True]]],
['regression: scenario 21',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'ZS400']},
{'active': ['LT200', 'TT300', 'ZS400'], 'silence': True}]],
[['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True],
['red', True, True],
['red', True, False]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['control: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101'], 'ack': True},
{'active': ['PT101']},
{'active': ['PT101']},
{'active': ['LT200', 'PT101', 'TT300']},
{'active': ['LT200', 'PT101', 'TT300'], 'ack': True},
{'active': ['LT200', 'TT300']}]],
[['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, True],
['red', False, False],
['amber', False, False]]]],
[['regression: scenario 5',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': ['TT300', 'ZS400']},
{'active': ['ZS400']},
{'active': ['ZS400']},
{'active': ['LT200', 'PT101']},
{'active': ['PT101', 'TT300'], 'ack': True, 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['PT101'], 'silence': True},
{'active': ['TT300'], 'ack': True, 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': [], 'ack': True}]],
[['red', True, True],
['red', True, True],
['red', True, True],
['red', True, True],
['red', False, False],
['off', False, False],
['red', True, True],
['red', True, False],
['amber', False, False],
['off', False, False],
['off', False, False],
['off', False, False]]],
['regression: scenario 23',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': []},
{'active': ['TT300']},
{'active': ['TT300'], 'silence': True},
{'active': []},
{'active': ['PT101']},
{'active': ['ZS400']},
{'active': ['LT200', 'ZS400'], 'silence': True},
{'active': ['LT200', 'TT300', 'ZS400']},
{'active': ['LT200', 'PT101', 'ZS400']}]],
[['off', False, False],
['amber', True, True],
['amber', True, False],
['off', False, False],
['red', True, True],
['red', True, True],
['red', True, False],
['red', True, True],
['red', True, True]]],
['regression: escalation sequence',
[[['A', 'high'], ['B', 'low']],
[{'active': ['B']},
{'active': ['B'], 'silence': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'ack': True},
{'active': ['B']},
{}]],
[['amber', True, True],
['amber', True, False],
['red', True, True],
['red', False, False],
['amber', False, False],
['off', False, False]]],
['control: alarm clears unacknowledged',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {}, {'active': ['B']}]],
[['red', True, True], ['off', False, False], ['amber', True, True]]],
['control: low alarm while high acked',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A'], 'ack': True},
{'active': ['A', 'B']},
{'active': ['A', 'B'], 'silence': True},
{'active': ['A', 'B']}]],
[['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]]],
['control: alarm present at first scan',
[[['A', 'high'], ['B', 'low']], [{'active': ['A']}, {'active': ['A']}]],
[['red', True, True], ['red', True, True]]],
['regression: silence then new low alarm',
[[['A', 'high'], ['B', 'low']],
[{'active': ['A']}, {'active': ['A'], 'silence': True}, {'active': ['A', 'B']}]],
[['red', True, True], ['red', True, False], ['red', True, True]]],
['regression: scenario 1',
[[['PT101', 'high'], ['LT200', 'low'], ['TT300', 'low'], ['ZS400', 'high']],
[{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': [], 'silence': True},
{'active': []},
{'active': ['ZS400']},
{'active': ['ZS400'], 'ack': True},
{'active': ['TT300']},
{'active': ['PT101', 'TT300'], 'ack': True},
{'active': ['PT101', 'TT300']},
{'active': ['PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300'], 'silence': True},
{'active': ['LT200', 'PT101', 'TT300']}]],
[['off', False, False],
['off', False, False],
['off', False, False],
['off', False, False],
['red', True, True],
['red', False, False],
['amber', True, True],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False],
['red', False, False]]]]]
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: escalation sequence | [['amber', True, True], ['amber', True, False], ['red', True, True], ['red', False, False], ['amber', False, False], ['off', False, False]] | [['amber', True, True], ['amber', True, False], ['red', True, True], ['red', False, False], ['amber', False, False], ['off', False, False]] | Passed |
| regression: silence then new low alarm | [['red', True, True], ['red', True, False], ['red', True, True]] | [['red', True, True], ['red', True, False], ['red', True, True]] | Passed |
| control: alarm clears unacknowledged | [['red', True, True], ['off', False, False], ['amber', True, True]] | [['red', True, True], ['off', False, False], ['amber', True, True]] | Passed |
| control: low alarm while high acked | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | [['red', False, False], ['red', False, True], ['red', False, False], ['red', False, False]] | Passed |
| control: alarm present at first scan | [['red', True, True], ['red', True, True]] | [['red', True, True], ['red', True, True]] | Passed |
| regression: scenario 1 | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, True], ['red', True, True], ['red', True, True], ['red', False, False]] | [['amber', False, False], ['amber', False, False], ['red', False, False], ['off', False, False], ['red', True, False], ['red', True, True], ['red', True, True], ['red', True, True], ['red', False, False]] | Passed |
| regression: scenario 2 | [['amber', True, False], ['red', True, True], ['amber', True, True], ['red', True, True], ['red', True, False], ['red', True, False]] | [['amber', True, False], ['red', True, True], ['amber', True, True], ['red', True, True], ['red', True, False], ['red', True, False]] | Passed |
| control: scenario 3 | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | [['off', False, False], ['off', False, False], ['red', True, True], ['red', True, True], ['red', True, False], ['red', False, False]] | Passed |
SHA-256 / e71edd5d7a10473eaa36d4b737b23bc308216eec834cadb2e9ece83b061ad95c
Verification & scope
A deterministic bounded teaching model of one PLC instruction or rung pattern evaluated scan by scan. The stated contract is a stipulated toy convention, not a claim of conformance to any vendor controller or IEC 61131-3 runtime. 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:51:44.470158+00:00.
Case digest / 8df23a7084a59494442a775e671b63bbab58b32022defbd12e2f4d98c6326d1c