FA-31966 / Keyboard interactions / Open access
Multi-tap keyboard character commit timing: A newly selected keypad key starts on its last character or an absolute deadline · case 01
The event trace violates the new character rule and produces incorrect keyboard state or command output.
ROOT CAUSE
A newly selected keypad key starts on its last character or an absolute deadline.
VERIFIED REPAIR
Use the contract transition `pending=[value,0,now+window]` at the new character fault site; preserve the other state transitions.
Unsuccessful approach: The partial repair changes this transition to pending=[value,0,window], which still violates the model contract on the explicit regression traces.
Case contract
Case [map,window,events]. Map maps keys to nonempty character strings. Events [kind,value,time]. Valid press cycles the pending same-key character before deadline, otherwise commits previous and starts new. Tick at or past deadline commits. Backspace cancels pending character before deleting committed text. Space commits pending then adds space; cancel drops pending only. Unknown press is ignored. Return committed text and pending [key,index,deadline] or None. 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):
mapping,window,events=c
text=''; pending=None
for kind,value,now in events:
if kind=='press' and value in mapping:
if pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
if pending is not None and pending[0]==value:
pending[1]=(pending[1]+1)%len(mapping[value])
pending[2]=now+window
else:
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=[value,len(mapping[value])-1,now+window]
elif kind=='tick' and pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
elif kind=='backspace':
if pending is not None: pending=None
else: text=text[:-1]
elif kind=='space':
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=None; text+=' '
elif kind=='cancel': pending=None
return [text,pending]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('multi-tap-keypad scenario 0', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11]]]] * N), [['', ['2', 1, 16]]] * N)
check('multi-tap-keypad scenario 1', solve([[{'2': 'abc', '3': 'de'}, 5, []]] * N), [['', None]] * N)
check('multi-tap-keypad scenario 2', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11], ['press', '2', 12], ['press', '2', 13], ['tick', '', 18]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 3', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 15]]]] * N), [['a', ['2', 0, 20]]] * N)
check('multi-tap-keypad scenario 4', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 12], ['tick', '', 17]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 5', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 12]]]] * N), [['', ['2', 0, 15]]] * N)
check('multi-tap-keypad scenario 6', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 15], ['press', '3', 16], ['backspace', '', 17]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 7', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 11], ['space', '', 12], ['backspace', '', 13]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 8', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['space', '', 12]]]] * N), [['a ', None]] * N)
check('multi-tap-keypad scenario 9', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '?', 10], ['backspace', '', 11]]]] * N), [['', 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 |
|---|---|---|---|
| multi-tap-keypad scenario 0 | [['', ['2', 0, 16]]] | [['', ['2', 1, 16]]] | Failed |
| multi-tap-keypad scenario 1 | [['', None]] | [['', None]] | Passed |
| multi-tap-keypad scenario 2 | [['c', None]] | [['a', None]] | Failed |
| multi-tap-keypad scenario 3 | [['c', ['2', 2, 20]]] | [['a', ['2', 0, 20]]] | Failed |
| multi-tap-keypad scenario 4 | [['ce', None]] | [['ad', None]] | Failed |
| multi-tap-keypad scenario 5 | [['', ['2', 2, 15]]] | [['', ['2', 0, 15]]] | Failed |
| multi-tap-keypad scenario 6 | [['c', None]] | [['a', None]] | Failed |
| multi-tap-keypad scenario 7 | [['ce', None]] | [['ad', None]] | Failed |
| multi-tap-keypad scenario 8 | [['c ', None]] | [['a ', None]] | Failed |
| multi-tap-keypad scenario 9 | [['', None]] | [['', None]] | Passed |
SHA-256 / 1b5188044f9aaeb32883d688a638b1735dd8a93d2ab86fdaf68da73b92ce844f
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):
mapping,window,events=c
text=''; pending=None
for kind,value,now in events:
if kind=='press' and value in mapping:
if pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
if pending is not None and pending[0]==value:
pending[1]=(pending[1]+1)%len(mapping[value])
pending[2]=now+window
else:
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=[value,0,window]
elif kind=='tick' and pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
elif kind=='backspace':
if pending is not None: pending=None
else: text=text[:-1]
elif kind=='space':
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=None; text+=' '
elif kind=='cancel': pending=None
return [text,pending]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('multi-tap-keypad scenario 0', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11]]]] * N), [['', ['2', 1, 16]]] * N)
check('multi-tap-keypad scenario 1', solve([[{'2': 'abc', '3': 'de'}, 5, []]] * N), [['', None]] * N)
check('multi-tap-keypad scenario 2', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11], ['press', '2', 12], ['press', '2', 13], ['tick', '', 18]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 3', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 15]]]] * N), [['a', ['2', 0, 20]]] * N)
check('multi-tap-keypad scenario 4', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 12], ['tick', '', 17]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 5', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 12]]]] * N), [['', ['2', 0, 15]]] * N)
check('multi-tap-keypad scenario 6', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 15], ['press', '3', 16], ['backspace', '', 17]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 7', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 11], ['space', '', 12], ['backspace', '', 13]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 8', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['space', '', 12]]]] * N), [['a ', None]] * N)
check('multi-tap-keypad scenario 9', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '?', 10], ['backspace', '', 11]]]] * N), [['', 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 |
|---|---|---|---|
| multi-tap-keypad scenario 0 | [['a', ['2', 0, 5]]] | [['', ['2', 1, 16]]] | Failed |
| multi-tap-keypad scenario 1 | [['', None]] | [['', None]] | Passed |
| multi-tap-keypad scenario 2 | [['aaaa', None]] | [['a', None]] | Failed |
| multi-tap-keypad scenario 3 | [['a', ['2', 0, 5]]] | [['a', ['2', 0, 20]]] | Failed |
| multi-tap-keypad scenario 4 | [['ad', None]] | [['ad', None]] | Passed |
| multi-tap-keypad scenario 5 | [['a', None]] | [['', ['2', 0, 15]]] | Failed |
| multi-tap-keypad scenario 6 | [['a', None]] | [['a', None]] | Passed |
| multi-tap-keypad scenario 7 | [['ad', None]] | [['ad', None]] | Passed |
| multi-tap-keypad scenario 8 | [['a ', None]] | [['a ', None]] | Passed |
| multi-tap-keypad scenario 9 | [['', None]] | [['', None]] | Passed |
SHA-256 / 94adee5be97cdaa7b088aafc0006e0f5bac48658a8407c5393971364dbb9ecdf
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):
mapping,window,events=c
text=''; pending=None
for kind,value,now in events:
if kind=='press' and value in mapping:
if pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
if pending is not None and pending[0]==value:
pending[1]=(pending[1]+1)%len(mapping[value])
pending[2]=now+window
else:
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=[value,0,now+window]
elif kind=='tick' and pending is not None and now>=pending[2]:
text+=mapping[pending[0]][pending[1]]; pending=None
elif kind=='backspace':
if pending is not None: pending=None
else: text=text[:-1]
elif kind=='space':
if pending is not None: text+=mapping[pending[0]][pending[1]]
pending=None; text+=' '
elif kind=='cancel': pending=None
return [text,pending]
return [run(c) for c in cases]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('multi-tap-keypad scenario 0', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11]]]] * N), [['', ['2', 1, 16]]] * N)
check('multi-tap-keypad scenario 1', solve([[{'2': 'abc', '3': 'de'}, 5, []]] * N), [['', None]] * N)
check('multi-tap-keypad scenario 2', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 11], ['press', '2', 12], ['press', '2', 13], ['tick', '', 18]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 3', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '2', 15]]]] * N), [['a', ['2', 0, 20]]] * N)
check('multi-tap-keypad scenario 4', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 12], ['tick', '', 17]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 5', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 12]]]] * N), [['', ['2', 0, 15]]] * N)
check('multi-tap-keypad scenario 6', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['tick', '', 15], ['press', '3', 16], ['backspace', '', 17]]]] * N), [['a', None]] * N)
check('multi-tap-keypad scenario 7', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['press', '3', 11], ['space', '', 12], ['backspace', '', 13]]]] * N), [['ad', None]] * N)
check('multi-tap-keypad scenario 8', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '2', 10], ['space', '', 12]]]] * N), [['a ', None]] * N)
check('multi-tap-keypad scenario 9', solve([[{'2': 'abc', '3': 'de'}, 5, [['press', '?', 10], ['backspace', '', 11]]]] * N), [['', 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 |
|---|---|---|---|
| multi-tap-keypad scenario 0 | [['', ['2', 1, 16]]] | [['', ['2', 1, 16]]] | Passed |
| multi-tap-keypad scenario 1 | [['', None]] | [['', None]] | Passed |
| multi-tap-keypad scenario 2 | [['a', None]] | [['a', None]] | Passed |
| multi-tap-keypad scenario 3 | [['a', ['2', 0, 20]]] | [['a', ['2', 0, 20]]] | Passed |
| multi-tap-keypad scenario 4 | [['ad', None]] | [['ad', None]] | Passed |
| multi-tap-keypad scenario 5 | [['', ['2', 0, 15]]] | [['', ['2', 0, 15]]] | Passed |
| multi-tap-keypad scenario 6 | [['a', None]] | [['a', None]] | Passed |
| multi-tap-keypad scenario 7 | [['ad', None]] | [['ad', None]] | Passed |
| multi-tap-keypad scenario 8 | [['a ', None]] | [['a ', None]] | Passed |
| multi-tap-keypad scenario 9 | [['', None]] | [['', None]] | Passed |
SHA-256 / c49828b5f5b1fdde51b61f28e886a77027aacc96eaa33b82489764363e23d433
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:07.383201+00:00.
Case digest / 9419f93c458954e4c6cef11fb3a050ee740c81fee67bea4f5b2da5b2ac876ce0