FAILURE MAP
← Case archive

FA-31241 / Keyboard interactions / Open access

Keyboard layout mapping generations: Layout switch keeps the previous generation or reverses generation ownership · case 01

The event trace violates the generation replace rule and produces incorrect keyboard state or command output.

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

ROOT CAUSE

Layout switch keeps the previous generation or reverses generation ownership.

VERIFIED REPAIR

Use the contract transition `generations[device]=a` at the generation replace fault site; preserve the other state transitions.

Unsuccessful approach: The partial repair changes this transition to generations[a]=device, which still violates the model contract on the explicit regression traces.

Case contract

Events [kind,device,a,b]. layout replaces device generation a and clears cached labels; map caches physical code a to label b in current generation; lookup emits cached label or code a as fallback. Disconnect removes generation and cache. Maps and lookups before layout are ignored. Return emitted labels, generations and cached [device,code,label] rows. 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):
        generations={}; cache={}; out=[]
        for kind,device,a,b in c:
            if kind=='layout':
                generations.setdefault(device,a)
                cache={k:v for k,v in cache.items() if k[0]!=device}
            elif kind=='map' and device in generations:
                cache[(device,a)]=b
            elif kind=='lookup' and device in generations:
                out.append(cache.get((device,a),a))
            elif kind=='disconnect':
                generations.pop(device,None)
                cache={k:v for k,v in cache.items() if k[0]!=device}
        return [out,sorted([[k,v] for k,v in generations.items()]),sorted([[d,k,v] for (d,k),v in cache.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('layout-cache scenario 0', solve([[]] * N), [[[], [], []]] * N)
check('layout-cache scenario 1', solve([[['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[[], [], []]] * N)
check('layout-cache scenario 2', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]] * N)
check('layout-cache scenario 3', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'a', 'KeyA', 'y'], ['lookup', 'a', 'KeyA', '']]] * N), [[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]] * N)
check('layout-cache scenario 4', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['layout', 'a', 2, ''], ['lookup', 'a', 'KeyA', '']]] * N), [[['KeyA'], [['a', 2]], []]] * N)
check('layout-cache scenario 5', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['layout', 'a', 3, '']]] * N), [[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]] * N)
check('layout-cache scenario 6', solve([[['layout', 'a', 1, ''], ['lookup', 'b', 'KeyA', '']]] * N), [[[], [['a', 1]], []]] * N)
check('layout-cache scenario 7', solve([[['layout', 'a', 1, ''], ['lookup', 'a', 'Unknown', 'fallback']]] * N), [[['Unknown'], [['a', 1]], []]] * N)
check('layout-cache scenario 8', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['disconnect', 'a', '', '']]] * N), [[[], [['b', 2]], [['b', 'KeyB', 'y']]]] * 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
layout-cache scenario 0[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 1[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 2[[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]][[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]]Passed
layout-cache scenario 3[[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]][[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]]Passed
layout-cache scenario 4[[['KeyA'], [['a', 1]], []]][[['KeyA'], [['a', 2]], []]]Failed
layout-cache scenario 5[[[], [['a', 1], ['b', 2]], [['b', 'KeyB', 'y']]]][[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]]Failed
layout-cache scenario 6[[[], [['a', 1]], []]][[[], [['a', 1]], []]]Passed
layout-cache scenario 7[[['Unknown'], [['a', 1]], []]][[['Unknown'], [['a', 1]], []]]Passed
layout-cache scenario 8[[[], [['b', 2]], [['b', 'KeyB', 'y']]]][[[], [['b', 2]], [['b', 'KeyB', 'y']]]]Passed

SHA-256 / 3e3676d0050ccc93446c633f109930ce38b647508f5390f106af7470b70ac5ab

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):
        generations={}; cache={}; out=[]
        for kind,device,a,b in c:
            if kind=='layout':
                generations[a]=device
                cache={k:v for k,v in cache.items() if k[0]!=device}
            elif kind=='map' and device in generations:
                cache[(device,a)]=b
            elif kind=='lookup' and device in generations:
                out.append(cache.get((device,a),a))
            elif kind=='disconnect':
                generations.pop(device,None)
                cache={k:v for k,v in cache.items() if k[0]!=device}
        return [out,sorted([[k,v] for k,v in generations.items()]),sorted([[d,k,v] for (d,k),v in cache.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('layout-cache scenario 0', solve([[]] * N), [[[], [], []]] * N)
check('layout-cache scenario 1', solve([[['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[[], [], []]] * N)
check('layout-cache scenario 2', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]] * N)
check('layout-cache scenario 3', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'a', 'KeyA', 'y'], ['lookup', 'a', 'KeyA', '']]] * N), [[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]] * N)
check('layout-cache scenario 4', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['layout', 'a', 2, ''], ['lookup', 'a', 'KeyA', '']]] * N), [[['KeyA'], [['a', 2]], []]] * N)
check('layout-cache scenario 5', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['layout', 'a', 3, '']]] * N), [[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]] * N)
check('layout-cache scenario 6', solve([[['layout', 'a', 1, ''], ['lookup', 'b', 'KeyA', '']]] * N), [[[], [['a', 1]], []]] * N)
check('layout-cache scenario 7', solve([[['layout', 'a', 1, ''], ['lookup', 'a', 'Unknown', 'fallback']]] * N), [[['Unknown'], [['a', 1]], []]] * N)
check('layout-cache scenario 8', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['disconnect', 'a', '', '']]] * N), [[[], [['b', 2]], [['b', 'KeyB', 'y']]]] * 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
layout-cache scenario 0[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 1[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 2[[[], [[1, 'a']], []]][[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]]Failed
layout-cache scenario 3[[[], [[1, 'a']], []]][[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]]Failed
layout-cache scenario 4[[[], [[1, 'a'], [2, 'a']], []]][[['KeyA'], [['a', 2]], []]]Failed
layout-cache scenario 5[[[], [[1, 'a'], [2, 'b'], [3, 'a']], []]][[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]]Failed
layout-cache scenario 6[[[], [[1, 'a']], []]][[[], [['a', 1]], []]]Failed
layout-cache scenario 7[[[], [[1, 'a']], []]][[['Unknown'], [['a', 1]], []]]Failed
layout-cache scenario 8[[[], [[1, 'a'], [2, 'b']], []]][[[], [['b', 2]], [['b', 'KeyB', 'y']]]]Failed

SHA-256 / 30e0903901b386c3c2026e1e2bda17922f5e1a843baf596dbb3b131fbf915a47

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):
        generations={}; cache={}; out=[]
        for kind,device,a,b in c:
            if kind=='layout':
                generations[device]=a
                cache={k:v for k,v in cache.items() if k[0]!=device}
            elif kind=='map' and device in generations:
                cache[(device,a)]=b
            elif kind=='lookup' and device in generations:
                out.append(cache.get((device,a),a))
            elif kind=='disconnect':
                generations.pop(device,None)
                cache={k:v for k,v in cache.items() if k[0]!=device}
        return [out,sorted([[k,v] for k,v in generations.items()]),sorted([[d,k,v] for (d,k),v in cache.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('layout-cache scenario 0', solve([[]] * N), [[[], [], []]] * N)
check('layout-cache scenario 1', solve([[['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[[], [], []]] * N)
check('layout-cache scenario 2', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['lookup', 'a', 'KeyA', '']]] * N), [[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]] * N)
check('layout-cache scenario 3', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'a', 'KeyA', 'y'], ['lookup', 'a', 'KeyA', '']]] * N), [[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]] * N)
check('layout-cache scenario 4', solve([[['layout', 'a', 1, ''], ['map', 'a', 'KeyA', 'x'], ['layout', 'a', 2, ''], ['lookup', 'a', 'KeyA', '']]] * N), [[['KeyA'], [['a', 2]], []]] * N)
check('layout-cache scenario 5', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['layout', 'a', 3, '']]] * N), [[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]] * N)
check('layout-cache scenario 6', solve([[['layout', 'a', 1, ''], ['lookup', 'b', 'KeyA', '']]] * N), [[[], [['a', 1]], []]] * N)
check('layout-cache scenario 7', solve([[['layout', 'a', 1, ''], ['lookup', 'a', 'Unknown', 'fallback']]] * N), [[['Unknown'], [['a', 1]], []]] * N)
check('layout-cache scenario 8', solve([[['layout', 'a', 1, ''], ['layout', 'b', 2, ''], ['map', 'a', 'KeyA', 'x'], ['map', 'b', 'KeyB', 'y'], ['disconnect', 'a', '', '']]] * N), [[[], [['b', 2]], [['b', 'KeyB', 'y']]]] * 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
layout-cache scenario 0[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 1[[[], [], []]][[[], [], []]]Passed
layout-cache scenario 2[[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]][[['x'], [['a', 1]], [['a', 'KeyA', 'x']]]]Passed
layout-cache scenario 3[[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]][[['y'], [['a', 1]], [['a', 'KeyA', 'y']]]]Passed
layout-cache scenario 4[[['KeyA'], [['a', 2]], []]][[['KeyA'], [['a', 2]], []]]Passed
layout-cache scenario 5[[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]][[[], [['a', 3], ['b', 2]], [['b', 'KeyB', 'y']]]]Passed
layout-cache scenario 6[[[], [['a', 1]], []]][[[], [['a', 1]], []]]Passed
layout-cache scenario 7[[['Unknown'], [['a', 1]], []]][[['Unknown'], [['a', 1]], []]]Passed
layout-cache scenario 8[[[], [['b', 2]], [['b', 'KeyB', 'y']]]][[[], [['b', 2]], [['b', 'KeyB', 'y']]]]Passed

SHA-256 / 81957e9e152d851f1942bafe5f3b7fdc8d346d726d7b19d2110c209673b8efed

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

Case digest / 5e8f41445ad98ea948bde7310cbfdbe8e166639a66263043c05d58f3942c149c