FA-32131 / Keyboard interactions / Open access
Asynchronous keyboard capture grant lifecycle: Blur revokes only active capture or pending requests, leaving the other live · case 01
The event trace violates the blur clear rule and produces incorrect keyboard state or command output.
ROOT CAUSE
Blur revokes only active capture or pending requests, leaving the other live.
VERIFIED REPAIR
Use the contract transition `focused=False; pending=None; active=[]` at the blur clear fault site; preserve the other state transitions.
Unsuccessful approach: The partial repair changes this transition to focused=False; pending=None, which still violates the model contract on the explicit regression traces.
Case contract
Events [kind,id,keys]. Initial window is focused. Request replaces pending id and deduplicated requested keys while focused. Grant applies only to current pending id while focused, filters Escape from captured keys, replaces active grant and clears pending. Deny clears only matching pending. Blur clears pending and active; focus restores eligibility; release clears both. Return focused flag, pending [id,keys] or None and active keys. 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):
focused=True; pending=None; active=[]
for kind,ident,keys in c:
if kind=='request' and focused:
pending=[ident,sorted(set(keys))]
elif kind=='grant' and focused and pending is not None and ident==pending[0]:
active=[k for k in pending[1] if k!='Escape']
pending=None
elif kind=='deny' and pending is not None and ident==pending[0]:
pending=None
elif kind=='blur':
focused=False; active=[]
elif kind=='focus': focused=True
elif kind=='release': pending=None; active=[]
return [focused,pending,active]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('keyboard-lock scenario 0', solve([[]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 1', solve([[['request', 1, ['B', 'A', 'A']]]] * N), [[True, [1, ['A', 'B']], []]] * N)
check('keyboard-lock scenario 2', solve([[['request', 1, ['A', 'Escape']], ['grant', 1, []]]] * N), [[True, None, ['A']]] * N)
check('keyboard-lock scenario 3', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['grant', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 4', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['deny', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 5', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['grant', 2, []]]] * N), [[True, None, ['B']]] * N)
check('keyboard-lock scenario 6', solve([[['blur', 0, []], ['request', 1, ['A']]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 7', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['blur', 0, []]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 8', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['release', 0, []]]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 9', solve([[['request', 1, ['A']], ['deny', 1, []]]] * N), [[True, None, []]] * 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| keyboard-lock scenario 0 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 1 | [[True, [1, ['A', 'B']], []]] | [[True, [1, ['A', 'B']], []]] | Passed |
| keyboard-lock scenario 2 | [[True, None, ['A']]] | [[True, None, ['A']]] | Passed |
| keyboard-lock scenario 3 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 4 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 5 | [[True, None, ['B']]] | [[True, None, ['B']]] | Passed |
| keyboard-lock scenario 6 | [[False, None, []]] | [[False, None, []]] | Passed |
| keyboard-lock scenario 7 | [[False, [2, ['B']], []]] | [[False, None, []]] | Failed |
| keyboard-lock scenario 8 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 9 | [[True, None, []]] | [[True, None, []]] | Passed |
SHA-256 / bd42bcce8547d36aec8bfa971aca8e1eb95f2aa821aff32d976360eb3b3a0e34
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):
focused=True; pending=None; active=[]
for kind,ident,keys in c:
if kind=='request' and focused:
pending=[ident,sorted(set(keys))]
elif kind=='grant' and focused and pending is not None and ident==pending[0]:
active=[k for k in pending[1] if k!='Escape']
pending=None
elif kind=='deny' and pending is not None and ident==pending[0]:
pending=None
elif kind=='blur':
focused=False; pending=None
elif kind=='focus': focused=True
elif kind=='release': pending=None; active=[]
return [focused,pending,active]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('keyboard-lock scenario 0', solve([[]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 1', solve([[['request', 1, ['B', 'A', 'A']]]] * N), [[True, [1, ['A', 'B']], []]] * N)
check('keyboard-lock scenario 2', solve([[['request', 1, ['A', 'Escape']], ['grant', 1, []]]] * N), [[True, None, ['A']]] * N)
check('keyboard-lock scenario 3', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['grant', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 4', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['deny', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 5', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['grant', 2, []]]] * N), [[True, None, ['B']]] * N)
check('keyboard-lock scenario 6', solve([[['blur', 0, []], ['request', 1, ['A']]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 7', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['blur', 0, []]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 8', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['release', 0, []]]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 9', solve([[['request', 1, ['A']], ['deny', 1, []]]] * N), [[True, None, []]] * 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| keyboard-lock scenario 0 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 1 | [[True, [1, ['A', 'B']], []]] | [[True, [1, ['A', 'B']], []]] | Passed |
| keyboard-lock scenario 2 | [[True, None, ['A']]] | [[True, None, ['A']]] | Passed |
| keyboard-lock scenario 3 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 4 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 5 | [[True, None, ['B']]] | [[True, None, ['B']]] | Passed |
| keyboard-lock scenario 6 | [[False, None, []]] | [[False, None, []]] | Passed |
| keyboard-lock scenario 7 | [[False, None, ['A']]] | [[False, None, []]] | Failed |
| keyboard-lock scenario 8 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 9 | [[True, None, []]] | [[True, None, []]] | Passed |
SHA-256 / 5a5f526e8d5df5efc70f8c6fca4bd4aed62b82c2750e218574c9e6a026ce9e25
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):
focused=True; pending=None; active=[]
for kind,ident,keys in c:
if kind=='request' and focused:
pending=[ident,sorted(set(keys))]
elif kind=='grant' and focused and pending is not None and ident==pending[0]:
active=[k for k in pending[1] if k!='Escape']
pending=None
elif kind=='deny' and pending is not None and ident==pending[0]:
pending=None
elif kind=='blur':
focused=False; pending=None; active=[]
elif kind=='focus': focused=True
elif kind=='release': pending=None; active=[]
return [focused,pending,active]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('keyboard-lock scenario 0', solve([[]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 1', solve([[['request', 1, ['B', 'A', 'A']]]] * N), [[True, [1, ['A', 'B']], []]] * N)
check('keyboard-lock scenario 2', solve([[['request', 1, ['A', 'Escape']], ['grant', 1, []]]] * N), [[True, None, ['A']]] * N)
check('keyboard-lock scenario 3', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['grant', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 4', solve([[['request', 1, ['A']], ['request', 2, ['B']], ['deny', 1, []]]] * N), [[True, [2, ['B']], []]] * N)
check('keyboard-lock scenario 5', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['grant', 2, []]]] * N), [[True, None, ['B']]] * N)
check('keyboard-lock scenario 6', solve([[['blur', 0, []], ['request', 1, ['A']]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 7', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['blur', 0, []]]] * N), [[False, None, []]] * N)
check('keyboard-lock scenario 8', solve([[['request', 1, ['A']], ['grant', 1, []], ['request', 2, ['B']], ['release', 0, []]]] * N), [[True, None, []]] * N)
check('keyboard-lock scenario 9', solve([[['request', 1, ['A']], ['deny', 1, []]]] * N), [[True, None, []]] * 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| keyboard-lock scenario 0 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 1 | [[True, [1, ['A', 'B']], []]] | [[True, [1, ['A', 'B']], []]] | Passed |
| keyboard-lock scenario 2 | [[True, None, ['A']]] | [[True, None, ['A']]] | Passed |
| keyboard-lock scenario 3 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 4 | [[True, [2, ['B']], []]] | [[True, [2, ['B']], []]] | Passed |
| keyboard-lock scenario 5 | [[True, None, ['B']]] | [[True, None, ['B']]] | Passed |
| keyboard-lock scenario 6 | [[False, None, []]] | [[False, None, []]] | Passed |
| keyboard-lock scenario 7 | [[False, None, []]] | [[False, None, []]] | Passed |
| keyboard-lock scenario 8 | [[True, None, []]] | [[True, None, []]] | Passed |
| keyboard-lock scenario 9 | [[True, None, []]] | [[True, None, []]] | Passed |
SHA-256 / b38b6aba0b4224b4568c292bb3ec2a021b546e0cd6bcec32ed9896b9e1a892fa
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:42:09.055194+00:00.
Case digest / 6649f32d50ccad40c567d116e2ace93cd9f72745f9a995327fe36ce8685a3130