FA-92256 / PLC ladder logic scan cycles / Open access
Free-running clock timer loses done after the elapsed value wraps · case 01
A timer that finished long ago drops its done bit when the clock has gone all the way round.
ROOT CAUSE
Done is recomputed from the wrapped elapsed value each scan instead of latched.
VERIFIED REPAIR
Latch done once reached and clear it only when the timer is disabled.
Unsuccessful approach: Holding done while elapsed is nonzero still drops it when the clock returns to the start tick.
Case contract
Delay timer built on a 16-bit free-running clock register (ticks wrap from 65535 to 0). samples is a list of [enable, clock] read each scan. The first enabled scan captures the start tick; elapsed is (clock - start) modulo 65536. Done latches once elapsed >= preset and stays set while enabled even if the elapsed value later wraps. A disabled scan clears start and done. Return [done, elapsed capped at preset once done] per scan, [False, 0] when disabled.
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(preset, samples):
start = None
done = False
out = []
for enable, clock in samples:
if not enable:
start = None
done = False
out.append([False, 0])
continue
if start is None:
start = clock
elapsed = (clock - start) & 0xFFFF
done = elapsed >= preset
out.append([done, preset if done else elapsed])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[True, 53593],
[True, 53635],
[True, 10212],
[False, 10250],
[True, 24553],
[True, 35364],
[True, 35501],
[True, 35591],
[True, 65279],
[True, 65379],
[True, 65509]]],
[[False, 0],
[False, 42],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 2',
[100,
[[True, 17304],
[True, 20531],
[True, 27559],
[False, 57396],
[True, 19489],
[True, 46000],
[True, 46035],
[True, 46209],
[True, 5526]]],
[[False, 0],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 3',
[40000,
[[True, 42783],
[False, 4625],
[True, 4670],
[True, 8857],
[False, 15422],
[False, 15500],
[True, 15560],
[True, 27335],
[True, 27471]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 4187],
[False, 0],
[False, 0],
[False, 0],
[False, 11775],
[False, 11911]]],
['control: scenario 4',
[100,
[[True, 2607],
[True, 18576],
[True, 18609],
[True, 18619],
[True, 45272],
[True, 45282],
[True, 55824],
[False, 61503]]],
[[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]]]],
[['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[1000,
[[False, 39404],
[False, 39599],
[True, 39752],
[True, 39914],
[False, 49270],
[True, 53547],
[True, 53700],
[True, 4426]]],
[[False, 0], [False, 0], [False, 0], [False, 162], [False, 0], [False, 0], [False, 153], [True, 1000]]],
['control: scenario 2',
[5,
[[True, 40525],
[True, 40666],
[True, 40725],
[True, 58227],
[True, 18319],
[False, 25775],
[True, 25797],
[True, 25799]]],
[[False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [False, 0], [False, 0], [False, 2]]],
['control: scenario 3',
[5,
[[False, 30258],
[True, 30296],
[True, 45510],
[True, 2343],
[True, 12538],
[True, 12596],
[False, 12635],
[True, 37410],
[True, 53676],
[True, 10497],
[True, 10628],
[False, 10824],
[True, 27527],
[True, 55148]]],
[[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5]]],
['control: scenario 4',
[65535,
[[True, 43066],
[True, 60153],
[False, 2292],
[True, 2392],
[True, 12076],
[False, 28626],
[False, 28693],
[False, 45850],
[True, 5636]]],
[[False, 0],
[False, 17087],
[False, 0],
[False, 0],
[False, 9684],
[False, 0],
[False, 0],
[False, 0],
[False, 0]]]],
[['regression: scenario 2',
[40000,
[[True, 54821],
[True, 18035],
[True, 32212],
[True, 38340],
[True, 38521],
[True, 38565],
[True, 38691],
[True, 52834],
[True, 6573],
[False, 6717],
[True, 13602]]],
[[False, 0],
[False, 28750],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[False, 0],
[False, 0]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[False, 22859],
[True, 23009],
[True, 46893],
[True, 47082],
[True, 47173],
[True, 47274],
[False, 47358],
[True, 47448],
[True, 54303],
[True, 54477],
[False, 54574]]],
[[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[False, 0]]],
['control: scenario 3',
[5,
[[False, 23870],
[True, 46782],
[True, 46917],
[True, 46976],
[True, 56255],
[True, 61627],
[True, 1767],
[True, 1874]]],
[[False, 0], [False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5]]],
['control: scenario 4',
[5,
[[True, 25219],
[True, 25303],
[True, 25491],
[True, 33180],
[True, 33370],
[True, 34085],
[True, 35832],
[True, 46392],
[True, 48652],
[True, 48709],
[True, 6073],
[True, 6100]]],
[[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[65535,
[[False, 3784],
[False, 8211],
[False, 33966],
[True, 50163],
[True, 63009],
[False, 63184],
[True, 63243],
[True, 63325]]],
[[False, 0], [False, 0], [False, 0], [False, 0], [False, 12846], [False, 0], [False, 0], [False, 82]]],
['control: scenario 2',
[1000,
[[False, 46148],
[True, 57365],
[False, 57416],
[True, 57439],
[True, 57613],
[True, 57776],
[True, 61872],
[True, 62038],
[True, 9532],
[True, 32841],
[True, 32973]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 174],
[False, 337],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 3',
[65535,
[[False, 15447],
[True, 18837],
[False, 18898],
[True, 19006],
[False, 33164],
[True, 33164],
[True, 41175],
[True, 53503],
[True, 53600],
[True, 6331],
[True, 35575],
[True, 35594],
[True, 35643]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 8011],
[False, 20339],
[False, 20436],
[False, 38703],
[False, 2411],
[False, 2430],
[False, 2479]]],
['control: scenario 4',
[40000,
[[False, 63428],
[False, 10454],
[True, 36085],
[False, 36231],
[True, 36344],
[True, 36357],
[True, 36437],
[True, 36476],
[True, 59214],
[False, 59324],
[True, 23687],
[True, 45223],
[False, 61971]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 13],
[False, 93],
[False, 132],
[False, 22870],
[False, 0],
[False, 0],
[False, 21536],
[False, 0]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[40000,
[[True, 14860],
[True, 43167],
[True, 43310],
[True, 43470],
[False, 65246],
[False, 2333],
[True, 20092],
[True, 45967],
[False, 64834],
[True, 20225],
[False, 20250],
[True, 21773],
[True, 26780]]],
[[False, 0],
[False, 28307],
[False, 28450],
[False, 28610],
[False, 0],
[False, 0],
[False, 0],
[False, 25875],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 5007]]],
['control: scenario 2',
[1000,
[[True, 51184],
[True, 56535],
[True, 13279],
[True, 24517],
[True, 24685],
[True, 32146],
[True, 59255],
[False, 21739],
[True, 21822],
[True, 43196]]],
[[False, 0],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[True, 1000]]],
['control: scenario 3',
[1000,
[[True, 22897],
[True, 22914],
[True, 28312],
[True, 28374],
[True, 35057],
[True, 50246],
[True, 63704],
[True, 65227],
[True, 26677],
[True, 39163]]],
[[False, 0],
[False, 17],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 4',
[1000,
[[True, 38985],
[True, 39119],
[True, 46977],
[True, 47168],
[False, 6446],
[True, 33057],
[True, 33083],
[True, 33130],
[True, 49169],
[True, 49195],
[True, 49212],
[True, 12968],
[True, 13081]]],
[[False, 0],
[False, 134],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[False, 26],
[False, 73],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]]]]
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: long enable past a full wrap | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [False, 600]] | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]] | Failed |
| regression: elapsed returns to zero | [[False, 0], [True, 5], [False, 0], [False, 2]] | [[False, 0], [True, 5], [True, 5], [True, 5]] | Failed |
| control: clock wrap | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | Passed |
| control: enable after idle | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | Passed |
| control: scenario 1 | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 2 | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 3 | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | Passed |
| control: scenario 4 | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | Passed |
SHA-256 / 887ae4ee94084425048ba06d0f11652611fd3f70525e7cee5158c8bb376af852
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(preset, samples):
start = None
done = False
out = []
for enable, clock in samples:
if not enable:
start = None
done = False
out.append([False, 0])
continue
if start is None:
start = clock
elapsed = (clock - start) & 0xFFFF
done = elapsed >= preset or (done and elapsed > 0)
out.append([done, preset if done else elapsed])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[True, 53593],
[True, 53635],
[True, 10212],
[False, 10250],
[True, 24553],
[True, 35364],
[True, 35501],
[True, 35591],
[True, 65279],
[True, 65379],
[True, 65509]]],
[[False, 0],
[False, 42],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 2',
[100,
[[True, 17304],
[True, 20531],
[True, 27559],
[False, 57396],
[True, 19489],
[True, 46000],
[True, 46035],
[True, 46209],
[True, 5526]]],
[[False, 0],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 3',
[40000,
[[True, 42783],
[False, 4625],
[True, 4670],
[True, 8857],
[False, 15422],
[False, 15500],
[True, 15560],
[True, 27335],
[True, 27471]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 4187],
[False, 0],
[False, 0],
[False, 0],
[False, 11775],
[False, 11911]]],
['control: scenario 4',
[100,
[[True, 2607],
[True, 18576],
[True, 18609],
[True, 18619],
[True, 45272],
[True, 45282],
[True, 55824],
[False, 61503]]],
[[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]]]],
[['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[1000,
[[False, 39404],
[False, 39599],
[True, 39752],
[True, 39914],
[False, 49270],
[True, 53547],
[True, 53700],
[True, 4426]]],
[[False, 0], [False, 0], [False, 0], [False, 162], [False, 0], [False, 0], [False, 153], [True, 1000]]],
['control: scenario 2',
[5,
[[True, 40525],
[True, 40666],
[True, 40725],
[True, 58227],
[True, 18319],
[False, 25775],
[True, 25797],
[True, 25799]]],
[[False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [False, 0], [False, 0], [False, 2]]],
['control: scenario 3',
[5,
[[False, 30258],
[True, 30296],
[True, 45510],
[True, 2343],
[True, 12538],
[True, 12596],
[False, 12635],
[True, 37410],
[True, 53676],
[True, 10497],
[True, 10628],
[False, 10824],
[True, 27527],
[True, 55148]]],
[[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5]]],
['control: scenario 4',
[65535,
[[True, 43066],
[True, 60153],
[False, 2292],
[True, 2392],
[True, 12076],
[False, 28626],
[False, 28693],
[False, 45850],
[True, 5636]]],
[[False, 0],
[False, 17087],
[False, 0],
[False, 0],
[False, 9684],
[False, 0],
[False, 0],
[False, 0],
[False, 0]]]],
[['regression: scenario 2',
[40000,
[[True, 54821],
[True, 18035],
[True, 32212],
[True, 38340],
[True, 38521],
[True, 38565],
[True, 38691],
[True, 52834],
[True, 6573],
[False, 6717],
[True, 13602]]],
[[False, 0],
[False, 28750],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[False, 0],
[False, 0]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[False, 22859],
[True, 23009],
[True, 46893],
[True, 47082],
[True, 47173],
[True, 47274],
[False, 47358],
[True, 47448],
[True, 54303],
[True, 54477],
[False, 54574]]],
[[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[False, 0]]],
['control: scenario 3',
[5,
[[False, 23870],
[True, 46782],
[True, 46917],
[True, 46976],
[True, 56255],
[True, 61627],
[True, 1767],
[True, 1874]]],
[[False, 0], [False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5]]],
['control: scenario 4',
[5,
[[True, 25219],
[True, 25303],
[True, 25491],
[True, 33180],
[True, 33370],
[True, 34085],
[True, 35832],
[True, 46392],
[True, 48652],
[True, 48709],
[True, 6073],
[True, 6100]]],
[[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[65535,
[[False, 3784],
[False, 8211],
[False, 33966],
[True, 50163],
[True, 63009],
[False, 63184],
[True, 63243],
[True, 63325]]],
[[False, 0], [False, 0], [False, 0], [False, 0], [False, 12846], [False, 0], [False, 0], [False, 82]]],
['control: scenario 2',
[1000,
[[False, 46148],
[True, 57365],
[False, 57416],
[True, 57439],
[True, 57613],
[True, 57776],
[True, 61872],
[True, 62038],
[True, 9532],
[True, 32841],
[True, 32973]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 174],
[False, 337],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 3',
[65535,
[[False, 15447],
[True, 18837],
[False, 18898],
[True, 19006],
[False, 33164],
[True, 33164],
[True, 41175],
[True, 53503],
[True, 53600],
[True, 6331],
[True, 35575],
[True, 35594],
[True, 35643]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 8011],
[False, 20339],
[False, 20436],
[False, 38703],
[False, 2411],
[False, 2430],
[False, 2479]]],
['control: scenario 4',
[40000,
[[False, 63428],
[False, 10454],
[True, 36085],
[False, 36231],
[True, 36344],
[True, 36357],
[True, 36437],
[True, 36476],
[True, 59214],
[False, 59324],
[True, 23687],
[True, 45223],
[False, 61971]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 13],
[False, 93],
[False, 132],
[False, 22870],
[False, 0],
[False, 0],
[False, 21536],
[False, 0]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[40000,
[[True, 14860],
[True, 43167],
[True, 43310],
[True, 43470],
[False, 65246],
[False, 2333],
[True, 20092],
[True, 45967],
[False, 64834],
[True, 20225],
[False, 20250],
[True, 21773],
[True, 26780]]],
[[False, 0],
[False, 28307],
[False, 28450],
[False, 28610],
[False, 0],
[False, 0],
[False, 0],
[False, 25875],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 5007]]],
['control: scenario 2',
[1000,
[[True, 51184],
[True, 56535],
[True, 13279],
[True, 24517],
[True, 24685],
[True, 32146],
[True, 59255],
[False, 21739],
[True, 21822],
[True, 43196]]],
[[False, 0],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[True, 1000]]],
['control: scenario 3',
[1000,
[[True, 22897],
[True, 22914],
[True, 28312],
[True, 28374],
[True, 35057],
[True, 50246],
[True, 63704],
[True, 65227],
[True, 26677],
[True, 39163]]],
[[False, 0],
[False, 17],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 4',
[1000,
[[True, 38985],
[True, 39119],
[True, 46977],
[True, 47168],
[False, 6446],
[True, 33057],
[True, 33083],
[True, 33130],
[True, 49169],
[True, 49195],
[True, 49212],
[True, 12968],
[True, 13081]]],
[[False, 0],
[False, 134],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[False, 26],
[False, 73],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]]]]
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: long enable past a full wrap | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]] | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]] | Passed |
| regression: elapsed returns to zero | [[False, 0], [True, 5], [False, 0], [False, 2]] | [[False, 0], [True, 5], [True, 5], [True, 5]] | Failed |
| control: clock wrap | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | Passed |
| control: enable after idle | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | Passed |
| control: scenario 1 | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 2 | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 3 | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | Passed |
| control: scenario 4 | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | Passed |
SHA-256 / b4a79b55c7841d47cf32e57b10fe9eff9715179f86dc91f2a1e873e460c9cd8f
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(preset, samples):
start = None
done = False
out = []
for enable, clock in samples:
if not enable:
start = None
done = False
out.append([False, 0])
continue
if start is None:
start = clock
elapsed = (clock - start) & 0xFFFF
if elapsed >= preset:
done = True
out.append([done, preset if done else elapsed])
return out
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[True, 53593],
[True, 53635],
[True, 10212],
[False, 10250],
[True, 24553],
[True, 35364],
[True, 35501],
[True, 35591],
[True, 65279],
[True, 65379],
[True, 65509]]],
[[False, 0],
[False, 42],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 2',
[100,
[[True, 17304],
[True, 20531],
[True, 27559],
[False, 57396],
[True, 19489],
[True, 46000],
[True, 46035],
[True, 46209],
[True, 5526]]],
[[False, 0],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100]]],
['control: scenario 3',
[40000,
[[True, 42783],
[False, 4625],
[True, 4670],
[True, 8857],
[False, 15422],
[False, 15500],
[True, 15560],
[True, 27335],
[True, 27471]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 4187],
[False, 0],
[False, 0],
[False, 0],
[False, 11775],
[False, 11911]]],
['control: scenario 4',
[100,
[[True, 2607],
[True, 18576],
[True, 18609],
[True, 18619],
[True, 45272],
[True, 45282],
[True, 55824],
[False, 61503]]],
[[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]]]],
[['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[1000,
[[False, 39404],
[False, 39599],
[True, 39752],
[True, 39914],
[False, 49270],
[True, 53547],
[True, 53700],
[True, 4426]]],
[[False, 0], [False, 0], [False, 0], [False, 162], [False, 0], [False, 0], [False, 153], [True, 1000]]],
['control: scenario 2',
[5,
[[True, 40525],
[True, 40666],
[True, 40725],
[True, 58227],
[True, 18319],
[False, 25775],
[True, 25797],
[True, 25799]]],
[[False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [False, 0], [False, 0], [False, 2]]],
['control: scenario 3',
[5,
[[False, 30258],
[True, 30296],
[True, 45510],
[True, 2343],
[True, 12538],
[True, 12596],
[False, 12635],
[True, 37410],
[True, 53676],
[True, 10497],
[True, 10628],
[False, 10824],
[True, 27527],
[True, 55148]]],
[[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5],
[True, 5],
[True, 5],
[False, 0],
[False, 0],
[True, 5]]],
['control: scenario 4',
[65535,
[[True, 43066],
[True, 60153],
[False, 2292],
[True, 2392],
[True, 12076],
[False, 28626],
[False, 28693],
[False, 45850],
[True, 5636]]],
[[False, 0],
[False, 17087],
[False, 0],
[False, 0],
[False, 9684],
[False, 0],
[False, 0],
[False, 0],
[False, 0]]]],
[['regression: scenario 2',
[40000,
[[True, 54821],
[True, 18035],
[True, 32212],
[True, 38340],
[True, 38521],
[True, 38565],
[True, 38691],
[True, 52834],
[True, 6573],
[False, 6717],
[True, 13602]]],
[[False, 0],
[False, 28750],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[True, 40000],
[False, 0],
[False, 0]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[100,
[[False, 22859],
[True, 23009],
[True, 46893],
[True, 47082],
[True, 47173],
[True, 47274],
[False, 47358],
[True, 47448],
[True, 54303],
[True, 54477],
[False, 54574]]],
[[False, 0],
[False, 0],
[True, 100],
[True, 100],
[True, 100],
[True, 100],
[False, 0],
[False, 0],
[True, 100],
[True, 100],
[False, 0]]],
['control: scenario 3',
[5,
[[False, 23870],
[True, 46782],
[True, 46917],
[True, 46976],
[True, 56255],
[True, 61627],
[True, 1767],
[True, 1874]]],
[[False, 0], [False, 0], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5], [True, 5]]],
['control: scenario 4',
[5,
[[True, 25219],
[True, 25303],
[True, 25491],
[True, 33180],
[True, 33370],
[True, 34085],
[True, 35832],
[True, 46392],
[True, 48652],
[True, 48709],
[True, 6073],
[True, 6100]]],
[[False, 0],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5],
[True, 5]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[65535,
[[False, 3784],
[False, 8211],
[False, 33966],
[True, 50163],
[True, 63009],
[False, 63184],
[True, 63243],
[True, 63325]]],
[[False, 0], [False, 0], [False, 0], [False, 0], [False, 12846], [False, 0], [False, 0], [False, 82]]],
['control: scenario 2',
[1000,
[[False, 46148],
[True, 57365],
[False, 57416],
[True, 57439],
[True, 57613],
[True, 57776],
[True, 61872],
[True, 62038],
[True, 9532],
[True, 32841],
[True, 32973]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 174],
[False, 337],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 3',
[65535,
[[False, 15447],
[True, 18837],
[False, 18898],
[True, 19006],
[False, 33164],
[True, 33164],
[True, 41175],
[True, 53503],
[True, 53600],
[True, 6331],
[True, 35575],
[True, 35594],
[True, 35643]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 8011],
[False, 20339],
[False, 20436],
[False, 38703],
[False, 2411],
[False, 2430],
[False, 2479]]],
['control: scenario 4',
[40000,
[[False, 63428],
[False, 10454],
[True, 36085],
[False, 36231],
[True, 36344],
[True, 36357],
[True, 36437],
[True, 36476],
[True, 59214],
[False, 59324],
[True, 23687],
[True, 45223],
[False, 61971]]],
[[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 13],
[False, 93],
[False, 132],
[False, 22870],
[False, 0],
[False, 0],
[False, 21536],
[False, 0]]]],
[['regression: long enable past a full wrap',
[1000, [[True, 100], [True, 30100], [True, 60100], [True, 24564], [True, 700]]],
[[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]]],
['regression: elapsed returns to zero',
[5, [[True, 10], [True, 20], [True, 10], [True, 12]]],
[[False, 0], [True, 5], [True, 5], [True, 5]]],
['control: clock wrap',
[100, [[True, 65500], [True, 65530], [True, 40], [True, 64], [False, 70]]],
[[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]]],
['control: enable after idle',
[50, [[False, 0], [False, 400], [True, 900], [True, 930], [True, 960]]],
[[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]]],
['control: scenario 1',
[40000,
[[True, 14860],
[True, 43167],
[True, 43310],
[True, 43470],
[False, 65246],
[False, 2333],
[True, 20092],
[True, 45967],
[False, 64834],
[True, 20225],
[False, 20250],
[True, 21773],
[True, 26780]]],
[[False, 0],
[False, 28307],
[False, 28450],
[False, 28610],
[False, 0],
[False, 0],
[False, 0],
[False, 25875],
[False, 0],
[False, 0],
[False, 0],
[False, 0],
[False, 5007]]],
['control: scenario 2',
[1000,
[[True, 51184],
[True, 56535],
[True, 13279],
[True, 24517],
[True, 24685],
[True, 32146],
[True, 59255],
[False, 21739],
[True, 21822],
[True, 43196]]],
[[False, 0],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[True, 1000]]],
['control: scenario 3',
[1000,
[[True, 22897],
[True, 22914],
[True, 28312],
[True, 28374],
[True, 35057],
[True, 50246],
[True, 63704],
[True, 65227],
[True, 26677],
[True, 39163]]],
[[False, 0],
[False, 17],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]],
['control: scenario 4',
[1000,
[[True, 38985],
[True, 39119],
[True, 46977],
[True, 47168],
[False, 6446],
[True, 33057],
[True, 33083],
[True, 33130],
[True, 49169],
[True, 49195],
[True, 49212],
[True, 12968],
[True, 13081]]],
[[False, 0],
[False, 134],
[True, 1000],
[True, 1000],
[False, 0],
[False, 0],
[False, 26],
[False, 73],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000],
[True, 1000]]]]]
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: long enable past a full wrap | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]] | [[False, 0], [True, 1000], [True, 1000], [True, 1000], [True, 1000]] | Passed |
| regression: elapsed returns to zero | [[False, 0], [True, 5], [True, 5], [True, 5]] | [[False, 0], [True, 5], [True, 5], [True, 5]] | Passed |
| control: clock wrap | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | [[False, 0], [False, 30], [False, 76], [True, 100], [False, 0]] | Passed |
| control: enable after idle | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | [[False, 0], [False, 0], [False, 0], [False, 30], [True, 50]] | Passed |
| control: scenario 1 | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [False, 42], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 2 | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | [[False, 0], [True, 100], [True, 100], [False, 0], [False, 0], [True, 100], [True, 100], [True, 100], [True, 100]] | Passed |
| control: scenario 3 | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | [[False, 0], [False, 0], [False, 0], [False, 4187], [False, 0], [False, 0], [False, 0], [False, 11775], [False, 11911]] | Passed |
| control: scenario 4 | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | [[False, 0], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [True, 100], [False, 0]] | Passed |
SHA-256 / 958c195110ccd533ba70c9c2e10d7734682abec4bc12bd4722e711c1266e757b
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:43.912003+00:00.
Case digest / 6fc9b4f2082256cc8f8171253f0026793fbbf61f4dde8d20e13bc06ea6190104