FAILURE MAP
← Case archive

FA-30991 / Keyboard interactions / Open access

Release activated command binding: A repeat transfers release ownership to a different receiver · case 01

The event trace violates the repeat owner rule and produces incorrect keyboard state or command output.

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

ROOT CAUSE

A repeat transfers release ownership to a different receiver.

VERIFIED REPAIR

Use the contract transition `if key not in pending: pending[key]=owner` at the repeat owner fault site; preserve the other state transitions.

Unsuccessful approach: The partial repair changes this transition to if key in pending: pending[key]=owner, which still violates the model contract on the explicit regression traces.

Case contract

Events [kind,key,owner]. Down arms a key for its owner; repeated down preserves the original owner. Up emits key only for matching key and owner then always disarms that physical key. Cancel clears all pending keys; owner-left clears that owner. Return emitted key-owner pairs and sorted pending pairs. 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):
        pending={}; emitted=[]; cancelled=0; unmatched=0
        for kind,key,owner in c:
            if kind=='down':
                pending[key]=owner
            elif kind=='up':
                if key in pending and pending[key]==owner:
                    emitted.append([key,owner])
                else: unmatched+=1
                pending.pop(key,None)
            elif kind=='cancel':
                cancelled+=len(pending)
                pending.clear()
            elif kind=='owner-left':
                dropped=[k for k,v in pending.items() if v==owner]
                cancelled+=len(dropped)
                for k in dropped: pending.pop(k)
        return [emitted,sorted([[k,v] for k,v in pending.items()]),cancelled,unmatched]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('release-binding scenario 0', solve([[]] * N), [[[], [], 0, 0]] * N)
check('release-binding scenario 1', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 2', solve([[['up', 'A', 'one'], ['up', 'B', 'one']]] * N), [[[], [], 0, 2]] * N)
check('release-binding scenario 3', solve([[['down', 'A', 'one'], ['down', 'A', 'two'], ['up', 'A', 'two']]] * N), [[[], [], 0, 1]] * N)
check('release-binding scenario 4', solve([[['down', 'A', 'one'], ['up', 'A', 'one'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [], 0, 1]] * N)
check('release-binding scenario 5', solve([[['down', 'A', 'one'], ['down', 'B', 'two'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [['B', 'two']], 0, 0]] * N)
check('release-binding scenario 6', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', ''], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 7', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['down', 'C', 'two'], ['owner-left', '', 'one']]] * N), [[[], [['C', 'two']], 2, 0]] * N)
check('release-binding scenario 8', solve([[['down', 'A', 'one'], ['owner-left', '', 'two']]] * N), [[[], [['A', 'one']], 0, 0]] * N)
check('release-binding scenario 9', solve([[['down', 'A', 'one'], ['cancel', '', ''], ['down', 'B', 'two'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * 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
release-binding scenario 0[[[], [], 0, 0]][[[], [], 0, 0]]Passed
release-binding scenario 1[[[], [], 2, 0]][[[], [], 2, 0]]Passed
release-binding scenario 2[[[], [], 0, 2]][[[], [], 0, 2]]Passed
release-binding scenario 3[[[['A', 'two']], [], 0, 0]][[[], [], 0, 1]]Failed
release-binding scenario 4[[[['A', 'one']], [], 0, 1]][[[['A', 'one']], [], 0, 1]]Passed
release-binding scenario 5[[[['A', 'one']], [['B', 'two']], 0, 0]][[[['A', 'one']], [['B', 'two']], 0, 0]]Passed
release-binding scenario 6[[[], [], 2, 0]][[[], [], 2, 0]]Passed
release-binding scenario 7[[[], [['C', 'two']], 2, 0]][[[], [['C', 'two']], 2, 0]]Passed
release-binding scenario 8[[[], [['A', 'one']], 0, 0]][[[], [['A', 'one']], 0, 0]]Passed
release-binding scenario 9[[[], [], 2, 0]][[[], [], 2, 0]]Passed

SHA-256 / 1959d2d74a8ddb84ab508f471ff94fd3db2878e96e27c4aa0270ba45bd0fbbe4

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):
        pending={}; emitted=[]; cancelled=0; unmatched=0
        for kind,key,owner in c:
            if kind=='down':
                if key in pending: pending[key]=owner
            elif kind=='up':
                if key in pending and pending[key]==owner:
                    emitted.append([key,owner])
                else: unmatched+=1
                pending.pop(key,None)
            elif kind=='cancel':
                cancelled+=len(pending)
                pending.clear()
            elif kind=='owner-left':
                dropped=[k for k,v in pending.items() if v==owner]
                cancelled+=len(dropped)
                for k in dropped: pending.pop(k)
        return [emitted,sorted([[k,v] for k,v in pending.items()]),cancelled,unmatched]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('release-binding scenario 0', solve([[]] * N), [[[], [], 0, 0]] * N)
check('release-binding scenario 1', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 2', solve([[['up', 'A', 'one'], ['up', 'B', 'one']]] * N), [[[], [], 0, 2]] * N)
check('release-binding scenario 3', solve([[['down', 'A', 'one'], ['down', 'A', 'two'], ['up', 'A', 'two']]] * N), [[[], [], 0, 1]] * N)
check('release-binding scenario 4', solve([[['down', 'A', 'one'], ['up', 'A', 'one'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [], 0, 1]] * N)
check('release-binding scenario 5', solve([[['down', 'A', 'one'], ['down', 'B', 'two'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [['B', 'two']], 0, 0]] * N)
check('release-binding scenario 6', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', ''], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 7', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['down', 'C', 'two'], ['owner-left', '', 'one']]] * N), [[[], [['C', 'two']], 2, 0]] * N)
check('release-binding scenario 8', solve([[['down', 'A', 'one'], ['owner-left', '', 'two']]] * N), [[[], [['A', 'one']], 0, 0]] * N)
check('release-binding scenario 9', solve([[['down', 'A', 'one'], ['cancel', '', ''], ['down', 'B', 'two'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * 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
release-binding scenario 0[[[], [], 0, 0]][[[], [], 0, 0]]Passed
release-binding scenario 1[[[], [], 0, 0]][[[], [], 2, 0]]Failed
release-binding scenario 2[[[], [], 0, 2]][[[], [], 0, 2]]Passed
release-binding scenario 3[[[], [], 0, 1]][[[], [], 0, 1]]Passed
release-binding scenario 4[[[], [], 0, 2]][[[['A', 'one']], [], 0, 1]]Failed
release-binding scenario 5[[[], [], 0, 1]][[[['A', 'one']], [['B', 'two']], 0, 0]]Failed
release-binding scenario 6[[[], [], 0, 0]][[[], [], 2, 0]]Failed
release-binding scenario 7[[[], [], 0, 0]][[[], [['C', 'two']], 2, 0]]Failed
release-binding scenario 8[[[], [], 0, 0]][[[], [['A', 'one']], 0, 0]]Failed
release-binding scenario 9[[[], [], 0, 0]][[[], [], 2, 0]]Failed

SHA-256 / c9ab1a9a9b3475e215f69f0728a0dde111b5bc84d17321552237123e3b170311

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):
        pending={}; emitted=[]; cancelled=0; unmatched=0
        for kind,key,owner in c:
            if kind=='down':
                if key not in pending: pending[key]=owner
            elif kind=='up':
                if key in pending and pending[key]==owner:
                    emitted.append([key,owner])
                else: unmatched+=1
                pending.pop(key,None)
            elif kind=='cancel':
                cancelled+=len(pending)
                pending.clear()
            elif kind=='owner-left':
                dropped=[k for k,v in pending.items() if v==owner]
                cancelled+=len(dropped)
                for k in dropped: pending.pop(k)
        return [emitted,sorted([[k,v] for k,v in pending.items()]),cancelled,unmatched]
    return [run(c) for c in cases]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('release-binding scenario 0', solve([[]] * N), [[[], [], 0, 0]] * N)
check('release-binding scenario 1', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 2', solve([[['up', 'A', 'one'], ['up', 'B', 'one']]] * N), [[[], [], 0, 2]] * N)
check('release-binding scenario 3', solve([[['down', 'A', 'one'], ['down', 'A', 'two'], ['up', 'A', 'two']]] * N), [[[], [], 0, 1]] * N)
check('release-binding scenario 4', solve([[['down', 'A', 'one'], ['up', 'A', 'one'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [], 0, 1]] * N)
check('release-binding scenario 5', solve([[['down', 'A', 'one'], ['down', 'B', 'two'], ['up', 'A', 'one']]] * N), [[[['A', 'one']], [['B', 'two']], 0, 0]] * N)
check('release-binding scenario 6', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['cancel', '', ''], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * N)
check('release-binding scenario 7', solve([[['down', 'A', 'one'], ['down', 'B', 'one'], ['down', 'C', 'two'], ['owner-left', '', 'one']]] * N), [[[], [['C', 'two']], 2, 0]] * N)
check('release-binding scenario 8', solve([[['down', 'A', 'one'], ['owner-left', '', 'two']]] * N), [[[], [['A', 'one']], 0, 0]] * N)
check('release-binding scenario 9', solve([[['down', 'A', 'one'], ['cancel', '', ''], ['down', 'B', 'two'], ['cancel', '', '']]] * N), [[[], [], 2, 0]] * 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
release-binding scenario 0[[[], [], 0, 0]][[[], [], 0, 0]]Passed
release-binding scenario 1[[[], [], 2, 0]][[[], [], 2, 0]]Passed
release-binding scenario 2[[[], [], 0, 2]][[[], [], 0, 2]]Passed
release-binding scenario 3[[[], [], 0, 1]][[[], [], 0, 1]]Passed
release-binding scenario 4[[[['A', 'one']], [], 0, 1]][[[['A', 'one']], [], 0, 1]]Passed
release-binding scenario 5[[[['A', 'one']], [['B', 'two']], 0, 0]][[[['A', 'one']], [['B', 'two']], 0, 0]]Passed
release-binding scenario 6[[[], [], 2, 0]][[[], [], 2, 0]]Passed
release-binding scenario 7[[[], [['C', 'two']], 2, 0]][[[], [['C', 'two']], 2, 0]]Passed
release-binding scenario 8[[[], [['A', 'one']], 0, 0]][[[], [['A', 'one']], 0, 0]]Passed
release-binding scenario 9[[[], [], 2, 0]][[[], [], 2, 0]]Passed

SHA-256 / e21d0e53af3f7e82145e8398182479d83ec93a586f50b2fb877e540de2c6a875

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

Case digest / d206d4e4e89b54de1d4546abd015ca0146f282781eb491335ff061281fdadd92