FAILURE MAP
← Case archive

FA-31061 / Keyboard interactions / Open access

Owned repeat deadline scheduler: Window blur leaves per-key repeat deadlines running · case 01

The event trace violates the blur cancel rule and produces incorrect keyboard state or command output.

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

ROOT CAUSE

Window blur leaves per-key repeat deadlines running.

VERIFIED REPAIR

Use the contract transition `next_due.clear()` at the blur cancel fault site; preserve the other state transitions.

Unsuccessful approach: The partial repair changes this transition to next_due.pop(key,None), which still violates the model contract on the explicit regression traces.

Case contract

Case [delay,period,events], events [kind,key,time]. First down per key emits immediately and schedules first repeat at time+delay. Tick drains every deadline at or before time, ordered by deadline then key. Up removes only that key, blur clears all. Return emissions [key,time] and sorted pending deadlines. Positive delay and period; times nondecreasing. Inputs are finite ordered event traces; return the stated deterministic state. Batch entries are independent. N varies the number of independent input transactions.

Why this case matters

Controlled keyboard event processing model for debugging application event logic.

1 / The failure

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

N = 1
observations = []
def solve(cases):
    def run(c):
        delay,period,events=c
        next_due={}; output=[]
        for kind,key,now in events:
            if kind=='down' and key not in next_due:
                output.append([key,now])
                next_due[key]=now+delay
            elif kind=='up':
                next_due.pop(key,None)
            elif kind=='blur':
                pass
            elif kind=='tick':
                ready=sorted((t,k) for k,t in next_due.items() if t<=now)
                while ready:
                    due,k=ready[0]
                    output.append([k,due])
                    next_due[k]=due+period
                    ready=sorted((t,k) for k,t in next_due.items() if t<=now)
        return [output,sorted([[k,v] for k,v in next_due.items()])]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('repeat-clock scenario 0', solve([[5, 2, []]] * N), [[[], []]] * N)
check('repeat-clock scenario 1', solve([[5, 2, [['down', 'A', 10], ['tick', '', 15]]]] * N), [[[['A', 10], ['A', 15]], [['A', 17]]]] * N)
check('repeat-clock scenario 2', solve([[5, 2, [['down', 'A', 10], ['down', 'A', 12], ['tick', '', 17]]]] * N), [[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]] * N)
check('repeat-clock scenario 3', solve([[5, 2, [['down', 'Z', 0], ['down', 'A', 1], ['tick', '', 10]]]] * N), [[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]] * N)
check('repeat-clock scenario 4', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['up', 'A', 2], ['tick', '', 9]]]] * N), [[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]] * N)
check('repeat-clock scenario 5', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['blur', '', 3], ['tick', '', 10]]]] * N), [[[['A', 0], ['B', 1]], []]] * N)
check('repeat-clock scenario 6', solve([[5, 2, [['down', 'A', 0], ['tick', '', 12]]]] * N), [[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]] * N)
check('repeat-clock scenario 7', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 0], ['tick', '', 5]]]] * N), [[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]] * N)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
repeat-clock scenario 0[[[], []]][[[], []]]Passed
repeat-clock scenario 1[[[['A', 10], ['A', 15]], [['A', 17]]]][[[['A', 10], ['A', 15]], [['A', 17]]]]Passed
repeat-clock scenario 2[[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]][[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]]Passed
repeat-clock scenario 3[[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]][[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]]Passed
repeat-clock scenario 4[[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]][[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]]Passed
repeat-clock scenario 5[[[['A', 0], ['B', 1], ['A', 5], ['B', 6], ['A', 7], ['B', 8], ['A', 9], ['B', 10]], [['A', 11], ['B', 12]]]][[[['A', 0], ['B', 1]], []]]Failed
repeat-clock scenario 6[[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]][[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]]Passed
repeat-clock scenario 7[[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]][[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]]Passed

SHA-256 / dc1a9d78dbd1ad99930ae39bf9fd9883a5f77c31a94922c7187e2d6de2a5a9b9

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(cases):
    def run(c):
        delay,period,events=c
        next_due={}; output=[]
        for kind,key,now in events:
            if kind=='down' and key not in next_due:
                output.append([key,now])
                next_due[key]=now+delay
            elif kind=='up':
                next_due.pop(key,None)
            elif kind=='blur':
                next_due.pop(key,None)
            elif kind=='tick':
                ready=sorted((t,k) for k,t in next_due.items() if t<=now)
                while ready:
                    due,k=ready[0]
                    output.append([k,due])
                    next_due[k]=due+period
                    ready=sorted((t,k) for k,t in next_due.items() if t<=now)
        return [output,sorted([[k,v] for k,v in next_due.items()])]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('repeat-clock scenario 0', solve([[5, 2, []]] * N), [[[], []]] * N)
check('repeat-clock scenario 1', solve([[5, 2, [['down', 'A', 10], ['tick', '', 15]]]] * N), [[[['A', 10], ['A', 15]], [['A', 17]]]] * N)
check('repeat-clock scenario 2', solve([[5, 2, [['down', 'A', 10], ['down', 'A', 12], ['tick', '', 17]]]] * N), [[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]] * N)
check('repeat-clock scenario 3', solve([[5, 2, [['down', 'Z', 0], ['down', 'A', 1], ['tick', '', 10]]]] * N), [[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]] * N)
check('repeat-clock scenario 4', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['up', 'A', 2], ['tick', '', 9]]]] * N), [[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]] * N)
check('repeat-clock scenario 5', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['blur', '', 3], ['tick', '', 10]]]] * N), [[[['A', 0], ['B', 1]], []]] * N)
check('repeat-clock scenario 6', solve([[5, 2, [['down', 'A', 0], ['tick', '', 12]]]] * N), [[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]] * N)
check('repeat-clock scenario 7', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 0], ['tick', '', 5]]]] * N), [[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]] * N)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
repeat-clock scenario 0[[[], []]][[[], []]]Passed
repeat-clock scenario 1[[[['A', 10], ['A', 15]], [['A', 17]]]][[[['A', 10], ['A', 15]], [['A', 17]]]]Passed
repeat-clock scenario 2[[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]][[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]]Passed
repeat-clock scenario 3[[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]][[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]]Passed
repeat-clock scenario 4[[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]][[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]]Passed
repeat-clock scenario 5[[[['A', 0], ['B', 1], ['A', 5], ['B', 6], ['A', 7], ['B', 8], ['A', 9], ['B', 10]], [['A', 11], ['B', 12]]]][[[['A', 0], ['B', 1]], []]]Failed
repeat-clock scenario 6[[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]][[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]]Passed
repeat-clock scenario 7[[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]][[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]]Passed

SHA-256 / db5dffaaa08c3e183e264b2541fb7d75da7adfe156707e0eb769f0cc026162e4

3 / The verified repair

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

N = 1
observations = []
def solve(cases):
    def run(c):
        delay,period,events=c
        next_due={}; output=[]
        for kind,key,now in events:
            if kind=='down' and key not in next_due:
                output.append([key,now])
                next_due[key]=now+delay
            elif kind=='up':
                next_due.pop(key,None)
            elif kind=='blur':
                next_due.clear()
            elif kind=='tick':
                ready=sorted((t,k) for k,t in next_due.items() if t<=now)
                while ready:
                    due,k=ready[0]
                    output.append([k,due])
                    next_due[k]=due+period
                    ready=sorted((t,k) for k,t in next_due.items() if t<=now)
        return [output,sorted([[k,v] for k,v in next_due.items()])]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('repeat-clock scenario 0', solve([[5, 2, []]] * N), [[[], []]] * N)
check('repeat-clock scenario 1', solve([[5, 2, [['down', 'A', 10], ['tick', '', 15]]]] * N), [[[['A', 10], ['A', 15]], [['A', 17]]]] * N)
check('repeat-clock scenario 2', solve([[5, 2, [['down', 'A', 10], ['down', 'A', 12], ['tick', '', 17]]]] * N), [[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]] * N)
check('repeat-clock scenario 3', solve([[5, 2, [['down', 'Z', 0], ['down', 'A', 1], ['tick', '', 10]]]] * N), [[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]] * N)
check('repeat-clock scenario 4', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['up', 'A', 2], ['tick', '', 9]]]] * N), [[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]] * N)
check('repeat-clock scenario 5', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 1], ['blur', '', 3], ['tick', '', 10]]]] * N), [[[['A', 0], ['B', 1]], []]] * N)
check('repeat-clock scenario 6', solve([[5, 2, [['down', 'A', 0], ['tick', '', 12]]]] * N), [[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]] * N)
check('repeat-clock scenario 7', solve([[5, 2, [['down', 'A', 0], ['down', 'B', 0], ['tick', '', 5]]]] * N), [[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]] * N)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
repeat-clock scenario 0[[[], []]][[[], []]]Passed
repeat-clock scenario 1[[[['A', 10], ['A', 15]], [['A', 17]]]][[[['A', 10], ['A', 15]], [['A', 17]]]]Passed
repeat-clock scenario 2[[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]][[[['A', 10], ['A', 15], ['A', 17]], [['A', 19]]]]Passed
repeat-clock scenario 3[[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]][[[['Z', 0], ['A', 1], ['Z', 5], ['A', 6], ['Z', 7], ['A', 8], ['Z', 9], ['A', 10]], [['A', 12], ['Z', 11]]]]Passed
repeat-clock scenario 4[[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]][[[['A', 0], ['B', 1], ['B', 6], ['B', 8]], [['B', 10]]]]Passed
repeat-clock scenario 5[[[['A', 0], ['B', 1]], []]][[[['A', 0], ['B', 1]], []]]Passed
repeat-clock scenario 6[[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]][[[['A', 0], ['A', 5], ['A', 7], ['A', 9], ['A', 11]], [['A', 13]]]]Passed
repeat-clock scenario 7[[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]][[[['A', 0], ['B', 0], ['A', 5], ['B', 5]], [['A', 7], ['B', 7]]]]Passed

SHA-256 / 918e78dde2188835289176e5100f5ef0368da2c6990bf43874e92fc713ff776c

Verification & scope

Offline stipulated event model, not a browser implementation or web standard conformance claim. 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:41:58.588349+00:00.

Case digest / 1aae535ffd6f152203d3ebcfd3394c92685e21677601fbca3cec6405a247a96f