FA-54136 / Accessibility interaction semantics / Open access
Negative range indices replace the final selection · case 01
Negative range indices replace the final selection.
ROOT CAUSE
The replace index decision in the text selection api adapter violates its declared contract.
VERIFIED REPAIR
Apply the exact contract at the replace index decision: kind == 'replace' and 0 <= index < len(ranges)
Unsuccessful approach: The local repair substitutes kind == 'replace' and -1 <= index < len(ranges) but still mishandles the regression fixtures.
Case contract
Input [text_length,multi,readonly,selections,operation] selections ordered [anchor,focus]; operation [kind,index,anchor,focus]. API supports add,replace,remove,clear; readonly concerns text edits and does not prevent selecting. Validate endpoints inclusive0..length and index for replace/remove. add only when multi or no selection; remove preserves other ranges; clear ignores index. Return [ranges,success,active] where active is last range's focus or None. Preserve anchor direction and collapsed selections. Failure leaves input unchanged.
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):
length,multi,readonly,selections,operation = data
ranges = [list(x) for x in selections]
kind,index,anchor,focus = operation
ok = False
if kind == 'clear': ranges,ok = [],True
elif kind in ('add','replace') and 0 <= anchor <= length and 0 <= focus <= length:
if kind == 'add' and (multi or not ranges): ranges.append([anchor,focus]); ok = True
elif kind == 'replace' and -len(ranges) <= index < len(ranges): ranges[index] = [anchor,focus]; ok = True
elif kind == 'remove' and 0 <= index < len(ranges): ranges.pop(index); ok = True
return [ranges,ok,ranges[-1][1] if ranges else None]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,True,False,[[0,1]],['add',0,N+3,N]],), [[[0,1],[N+3,N]],True,N])
check('contract fixture 2', solve([5,False,True,[],['add',0,5,5]],), [[[5,5]],True,5])
check('contract fixture 3', solve([5,False,False,[[0,1]],['add',0,2,3]],), [[[0,1]],False,1])
check('contract fixture 4', solve([5,True,False,[[0,1],[2,3]],['replace',0,4,2]],), [[[4,2],[2,3]],True,3])
check('contract fixture 5', solve([5,True,False,[[0,1],[2,3]],['remove',0,0,0]],), [[[2,3]],True,3])
check('contract fixture 6', solve([5,False,False,[[0,1]],['clear',99,-1,99]],), [[],True,None])
check('contract fixture 7', solve([5,True,False,[[0,1]],['replace',-1,2,3]],), [[[0,1]],False,1])
check('contract fixture 8', solve([5,True,False,[],['add',0,-1,3]],), [[],False,None])
check('contract fixture 9', solve([5,True,False,[],['add',0,1,6]],), [[],False,None])
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 |
|---|---|---|---|
| contract fixture 1 | [[[0, 1], [4, 1]], True, 1] | [[[0, 1], [4, 1]], True, 1] | Passed |
| contract fixture 2 | [[[5, 5]], True, 5] | [[[5, 5]], True, 5] | Passed |
| contract fixture 3 | [[[0, 1]], False, 1] | [[[0, 1]], False, 1] | Passed |
| contract fixture 4 | [[[4, 2], [2, 3]], True, 3] | [[[4, 2], [2, 3]], True, 3] | Passed |
| contract fixture 5 | [[[2, 3]], True, 3] | [[[2, 3]], True, 3] | Passed |
| contract fixture 6 | [[], True, None] | [[], True, None] | Passed |
| contract fixture 7 | [[[2, 3]], True, 3] | [[[0, 1]], False, 1] | Failed |
| contract fixture 8 | [[], False, None] | [[], False, None] | Passed |
| contract fixture 9 | [[], False, None] | [[], False, None] | Passed |
SHA-256 / b4a76b79e598dbcfc035f6389c5d4ebb2d5e65ea1463dd3315dcc7765f4e0008
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
length,multi,readonly,selections,operation = data
ranges = [list(x) for x in selections]
kind,index,anchor,focus = operation
ok = False
if kind == 'clear': ranges,ok = [],True
elif kind in ('add','replace') and 0 <= anchor <= length and 0 <= focus <= length:
if kind == 'add' and (multi or not ranges): ranges.append([anchor,focus]); ok = True
elif kind == 'replace' and -1 <= index < len(ranges): ranges[index] = [anchor,focus]; ok = True
elif kind == 'remove' and 0 <= index < len(ranges): ranges.pop(index); ok = True
return [ranges,ok,ranges[-1][1] if ranges else None]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,True,False,[[0,1]],['add',0,N+3,N]],), [[[0,1],[N+3,N]],True,N])
check('contract fixture 2', solve([5,False,True,[],['add',0,5,5]],), [[[5,5]],True,5])
check('contract fixture 3', solve([5,False,False,[[0,1]],['add',0,2,3]],), [[[0,1]],False,1])
check('contract fixture 4', solve([5,True,False,[[0,1],[2,3]],['replace',0,4,2]],), [[[4,2],[2,3]],True,3])
check('contract fixture 5', solve([5,True,False,[[0,1],[2,3]],['remove',0,0,0]],), [[[2,3]],True,3])
check('contract fixture 6', solve([5,False,False,[[0,1]],['clear',99,-1,99]],), [[],True,None])
check('contract fixture 7', solve([5,True,False,[[0,1]],['replace',-1,2,3]],), [[[0,1]],False,1])
check('contract fixture 8', solve([5,True,False,[],['add',0,-1,3]],), [[],False,None])
check('contract fixture 9', solve([5,True,False,[],['add',0,1,6]],), [[],False,None])
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 |
|---|---|---|---|
| contract fixture 1 | [[[0, 1], [4, 1]], True, 1] | [[[0, 1], [4, 1]], True, 1] | Passed |
| contract fixture 2 | [[[5, 5]], True, 5] | [[[5, 5]], True, 5] | Passed |
| contract fixture 3 | [[[0, 1]], False, 1] | [[[0, 1]], False, 1] | Passed |
| contract fixture 4 | [[[4, 2], [2, 3]], True, 3] | [[[4, 2], [2, 3]], True, 3] | Passed |
| contract fixture 5 | [[[2, 3]], True, 3] | [[[2, 3]], True, 3] | Passed |
| contract fixture 6 | [[], True, None] | [[], True, None] | Passed |
| contract fixture 7 | [[[2, 3]], True, 3] | [[[0, 1]], False, 1] | Failed |
| contract fixture 8 | [[], False, None] | [[], False, None] | Passed |
| contract fixture 9 | [[], False, None] | [[], False, None] | Passed |
SHA-256 / 08938566921de0d95641bc4bc67a27637c102d79c7a75dea96729ba92b9d8a52
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
length,multi,readonly,selections,operation = data
ranges = [list(x) for x in selections]
kind,index,anchor,focus = operation
ok = False
if kind == 'clear': ranges,ok = [],True
elif kind in ('add','replace') and 0 <= anchor <= length and 0 <= focus <= length:
if kind == 'add' and (multi or not ranges): ranges.append([anchor,focus]); ok = True
elif kind == 'replace' and 0 <= index < len(ranges): ranges[index] = [anchor,focus]; ok = True
elif kind == 'remove' and 0 <= index < len(ranges): ranges.pop(index); ok = True
return [ranges,ok,ranges[-1][1] if ranges else None]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,True,False,[[0,1]],['add',0,N+3,N]],), [[[0,1],[N+3,N]],True,N])
check('contract fixture 2', solve([5,False,True,[],['add',0,5,5]],), [[[5,5]],True,5])
check('contract fixture 3', solve([5,False,False,[[0,1]],['add',0,2,3]],), [[[0,1]],False,1])
check('contract fixture 4', solve([5,True,False,[[0,1],[2,3]],['replace',0,4,2]],), [[[4,2],[2,3]],True,3])
check('contract fixture 5', solve([5,True,False,[[0,1],[2,3]],['remove',0,0,0]],), [[[2,3]],True,3])
check('contract fixture 6', solve([5,False,False,[[0,1]],['clear',99,-1,99]],), [[],True,None])
check('contract fixture 7', solve([5,True,False,[[0,1]],['replace',-1,2,3]],), [[[0,1]],False,1])
check('contract fixture 8', solve([5,True,False,[],['add',0,-1,3]],), [[],False,None])
check('contract fixture 9', solve([5,True,False,[],['add',0,1,6]],), [[],False,None])
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 |
|---|---|---|---|
| contract fixture 1 | [[[0, 1], [4, 1]], True, 1] | [[[0, 1], [4, 1]], True, 1] | Passed |
| contract fixture 2 | [[[5, 5]], True, 5] | [[[5, 5]], True, 5] | Passed |
| contract fixture 3 | [[[0, 1]], False, 1] | [[[0, 1]], False, 1] | Passed |
| contract fixture 4 | [[[4, 2], [2, 3]], True, 3] | [[[4, 2], [2, 3]], True, 3] | Passed |
| contract fixture 5 | [[[2, 3]], True, 3] | [[[2, 3]], True, 3] | Passed |
| contract fixture 6 | [[], True, None] | [[], True, None] | Passed |
| contract fixture 7 | [[[0, 1]], False, 1] | [[[0, 1]], False, 1] | Passed |
| contract fixture 8 | [[], False, None] | [[], False, None] | Passed |
| contract fixture 9 | [[], False, None] | [[], False, None] | Passed |
SHA-256 / 725d4c725ca86d34b902a3c9b4d163c4933039170364ca138cf49147fdc9964a
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:45.544981+00:00.
Case digest / f60feee5c93e45f9fe0658192619ad651d0368ed59b5b2b8168c42cc0490bcf4