FAILURE MAP
← Case archive

FA-54056 / Accessibility interaction semantics / Open access

Read-only text exposes a mutating accessibility edit path · case 01

Read-only text exposes a mutating accessibility edit path.

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

ROOT CAUSE

The read only edit decision in the text edit adapter adapter violates its declared contract.

VERIFIED REPAIR

Apply the exact contract at the read only edit decision: readonly or not

Unsuccessful approach: The local repair substitutes (readonly and maximum is not None) or not but still mishandles the regression fixtures.

Case contract

Input [text,readonly,maximum,operations] operations [start,end,replacement]. Validate integer codepoint bounds 0<=start<=end<=len(current_text); readonly rejects each edit. Replace half-open range; reject proposed length beyond maximum (None unlimited) atomically. Return [final_text,edit_results] where successful result [True,caret,delta] caret is start+replacement length and delta replacement length minus removed length; rejected [False,None,0]. Empty replacement deletes, empty interval inserts. Subsequent offsets address current text.

Why this case matters

Offline accessibility bridge model with explicit policy; useful for testing semantic API adapters independently of browser implementations.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,readonly,maximum,operations = data
    results = []
    for start,end,replacement in operations:
        if False or not (0 <= start <= end <= len(text)):
            results.append([False,None,0]); continue
        proposed = text[:start]+replacement+text[end:]
        if maximum is not None and len(proposed) > maximum:
            results.append([False,None,0]); continue
        delta = len(replacement)-(end-start)
        text = proposed
        results.append([True,start+len(replacement),delta])
    return [text,results]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve(['A'*N+'BC',False,None,[[N,N+1,'xy'],[N+2,N+3,'']]],), ['A'*N+'xy',[[True,N+2,1],[True,N+2,-1]]])
check('contract fixture 2', solve(['ab',False,3,[[1,1,'X'],[0,0,'Y']]],), ['aXb',[[True,2,1],[False,None,0]]])
check('contract fixture 3', solve(['ab',True,None,[[0,2,'x']]],), ['ab',[[False,None,0]]])
check('contract fixture 4', solve(['ab',False,None,[[-1,1,'x'],[2,1,'x'],[0,3,'x']]],), ['ab',[[False,None,0],[False,None,0],[False,None,0]]])
check('contract fixture 5', solve(['',False,0,[[0,0,''],[0,0,'x']]],), ['',[[True,0,0],[False,None,0]]])
check('contract fixture 6', solve(['😀x',False,None,[[0,1,'é']]],), ['éx',[[True,1,0]]])
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
contract fixture 1['Axy', [[True, 3, 1], [True, 3, -1]]]['Axy', [[True, 3, 1], [True, 3, -1]]]Passed
contract fixture 2['aXb', [[True, 2, 1], [False, None, 0]]]['aXb', [[True, 2, 1], [False, None, 0]]]Passed
contract fixture 3['x', [[True, 1, -1]]]['ab', [[False, None, 0]]]Failed
contract fixture 4['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]Passed
contract fixture 5['', [[True, 0, 0], [False, None, 0]]]['', [[True, 0, 0], [False, None, 0]]]Passed
contract fixture 6['éx', [[True, 1, 0]]]['éx', [[True, 1, 0]]]Passed

SHA-256 / 2ceac712b8caa5f293aed0afccf644ebc306fe8f30de9e94a741155a2adcf53e

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,readonly,maximum,operations = data
    results = []
    for start,end,replacement in operations:
        if (readonly and maximum is not None) or not (0 <= start <= end <= len(text)):
            results.append([False,None,0]); continue
        proposed = text[:start]+replacement+text[end:]
        if maximum is not None and len(proposed) > maximum:
            results.append([False,None,0]); continue
        delta = len(replacement)-(end-start)
        text = proposed
        results.append([True,start+len(replacement),delta])
    return [text,results]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve(['A'*N+'BC',False,None,[[N,N+1,'xy'],[N+2,N+3,'']]],), ['A'*N+'xy',[[True,N+2,1],[True,N+2,-1]]])
check('contract fixture 2', solve(['ab',False,3,[[1,1,'X'],[0,0,'Y']]],), ['aXb',[[True,2,1],[False,None,0]]])
check('contract fixture 3', solve(['ab',True,None,[[0,2,'x']]],), ['ab',[[False,None,0]]])
check('contract fixture 4', solve(['ab',False,None,[[-1,1,'x'],[2,1,'x'],[0,3,'x']]],), ['ab',[[False,None,0],[False,None,0],[False,None,0]]])
check('contract fixture 5', solve(['',False,0,[[0,0,''],[0,0,'x']]],), ['',[[True,0,0],[False,None,0]]])
check('contract fixture 6', solve(['😀x',False,None,[[0,1,'é']]],), ['éx',[[True,1,0]]])
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
contract fixture 1['Axy', [[True, 3, 1], [True, 3, -1]]]['Axy', [[True, 3, 1], [True, 3, -1]]]Passed
contract fixture 2['aXb', [[True, 2, 1], [False, None, 0]]]['aXb', [[True, 2, 1], [False, None, 0]]]Passed
contract fixture 3['x', [[True, 1, -1]]]['ab', [[False, None, 0]]]Failed
contract fixture 4['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]Passed
contract fixture 5['', [[True, 0, 0], [False, None, 0]]]['', [[True, 0, 0], [False, None, 0]]]Passed
contract fixture 6['éx', [[True, 1, 0]]]['éx', [[True, 1, 0]]]Passed

SHA-256 / a4feb1a71ddb22c2e9d6217b55520b34f04adb9b0c84c7a783e9adcfec2d4c83

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(data):
    text,readonly,maximum,operations = data
    results = []
    for start,end,replacement in operations:
        if readonly or not (0 <= start <= end <= len(text)):
            results.append([False,None,0]); continue
        proposed = text[:start]+replacement+text[end:]
        if maximum is not None and len(proposed) > maximum:
            results.append([False,None,0]); continue
        delta = len(replacement)-(end-start)
        text = proposed
        results.append([True,start+len(replacement),delta])
    return [text,results]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve(['A'*N+'BC',False,None,[[N,N+1,'xy'],[N+2,N+3,'']]],), ['A'*N+'xy',[[True,N+2,1],[True,N+2,-1]]])
check('contract fixture 2', solve(['ab',False,3,[[1,1,'X'],[0,0,'Y']]],), ['aXb',[[True,2,1],[False,None,0]]])
check('contract fixture 3', solve(['ab',True,None,[[0,2,'x']]],), ['ab',[[False,None,0]]])
check('contract fixture 4', solve(['ab',False,None,[[-1,1,'x'],[2,1,'x'],[0,3,'x']]],), ['ab',[[False,None,0],[False,None,0],[False,None,0]]])
check('contract fixture 5', solve(['',False,0,[[0,0,''],[0,0,'x']]],), ['',[[True,0,0],[False,None,0]]])
check('contract fixture 6', solve(['😀x',False,None,[[0,1,'é']]],), ['éx',[[True,1,0]]])
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
contract fixture 1['Axy', [[True, 3, 1], [True, 3, -1]]]['Axy', [[True, 3, 1], [True, 3, -1]]]Passed
contract fixture 2['aXb', [[True, 2, 1], [False, None, 0]]]['aXb', [[True, 2, 1], [False, None, 0]]]Passed
contract fixture 3['ab', [[False, None, 0]]]['ab', [[False, None, 0]]]Passed
contract fixture 4['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]['ab', [[False, None, 0], [False, None, 0], [False, None, 0]]]Passed
contract fixture 5['', [[True, 0, 0], [False, None, 0]]]['', [[True, 0, 0], [False, None, 0]]]Passed
contract fixture 6['éx', [[True, 1, 0]]]['éx', [[True, 1, 0]]]Passed

SHA-256 / d2b022cd03d2c9f2e58d77330e5ce6a30ccd9b07835dd789bcb527ef39755a45

Verification & scope

Stipulated finite adapter contract, not a claim of platform accessibility or ARIA conformance. 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:45:44.687869+00:00.

Case digest / 149b90f665ce7cf7b1a21b65314749939e9b31563ae6613fc566ef382dab41d9