FAILURE MAP
← Case archive

FA-31986 / Keyboard interactions / Open access

Multi-tap keyboard character commit timing: Space fails to close pending character state or erases previous text · case 01

The event trace violates the space close rule and produces incorrect keyboard state or command output.

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

ROOT CAUSE

Space fails to close pending character state or erases previous text.

VERIFIED REPAIR

Use the contract transition `pending=None; text+=' '` at the space close fault site; preserve the other state transitions.

Unsuccessful approach: The partial repair changes this transition to pending=None; text='', 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,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]]
                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 fixtureActualExpectedOutcome
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]]Failed
multi-tap-keypad scenario 8[['a ', ['2', 0, 15]]][['a ', None]]Failed
multi-tap-keypad scenario 9[['', None]][['', None]]Passed

SHA-256 / 7a086e74aa925261862d3145e492434cf3b40907575e3382269fe4b530be994f

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,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 fixtureActualExpectedOutcome
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[['', None]][['ad', None]]Failed
multi-tap-keypad scenario 8[['', None]][['a ', None]]Failed
multi-tap-keypad scenario 9[['', None]][['', None]]Passed

SHA-256 / f9806c1682e30ee7507c838d6683d330cb1e6b524da1689fdb3197c03a3f3af6

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 fixtureActualExpectedOutcome
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.521250+00:00.

Case digest / 3693362ed32e8221c80476bae9226ec7d7d8bb1d5292838632e83499ec742937