FA-53876 / Accessibility interaction semantics / Open access
Zero-length hyperlink spans pollute indexed link counts · case 01
Zero-length hyperlink spans pollute indexed link counts.
ROOT CAUSE
The empty span decision in the hyperlink spans adapter violates its declared contract.
VERIFIED REPAIR
Apply the exact contract at the empty span decision: if start >= end: continue
Unsuccessful approach: The local repair substitutes if start == end and start == 0: continue but still mishandles the regression fixtures.
Case contract
Input [text_length,links,offset] where links [id,start,end,url,enabled]. Admit only nonempty URL, enabled and nonempty interval after clamping. Sort by start then shorter interval then input order; dedupe IDs after sorting. Query offset resolves the first matching half-open span, or None. Return [ordered descriptors,hit_id]. URLs remain exact including fragments; IDs are retained even when URL is shared.
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,links,offset = data
valid = []
for i,(ident,start,end,url,enabled) in enumerate(links):
if not enabled or not url: continue
start,end = max(0,start),min(length,end)
if start > end: continue
valid.append((start,end-start,i,ident,end,url))
valid.sort(key=lambda x:(x[0],x[1],x[2]))
seen = set()
rows = []
for start,width,i,ident,end,url in valid:
if ident in seen: continue
seen.add(ident)
rows.append([ident,start,end,url])
hit = next((ident for ident,start,end,url in rows if start <= offset < end),None)
return [rows,hit]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['wide',N,N+4,'/a#x',True],['small',N,N+2,'/a#y',True]],N+1],), [[['small',N,N+2,'/a#y'],['wide',N,N+4,'/a#x']],'small'])
check('contract fixture 2', solve([5,[['a',-3,2,'/a',True],['b',2,8,'/b',True]],2],), [[['a',0,2,'/a'],['b',2,5,'/b']],'b'])
check('contract fixture 3', solve([5,[['a',1,1,'/a',True],['b',4,2,'/b',True],['c',0,3,'',True],['d',0,3,'/d',False]],0],), [[],None])
check('contract fixture 4', solve([6,[['a',3,6,'later',True],['a',0,2,'early',True]],1],), [[['a',0,2,'early']],'a'])
check('contract fixture 5', solve([3,[['a',0,3,'/same',True],['b',0,3,'/same',True]],3],), [[['a',0,3,'/same'],['b',0,3,'/same']],None])
check('contract fixture 6', solve([0,[],0],), [[],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 | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | Passed |
| contract fixture 2 | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | Passed |
| contract fixture 3 | [[['a', 1, 1, '/a']], None] | [[], None] | Failed |
| contract fixture 4 | [[['a', 0, 2, 'early']], 'a'] | [[['a', 0, 2, 'early']], 'a'] | Passed |
| contract fixture 5 | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | Passed |
| contract fixture 6 | [[], None] | [[], None] | Passed |
SHA-256 / f9b9cc14b4c0bbc2b2768f7d13bb64781bab50e61fe4cf47631aa25705484590
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
length,links,offset = data
valid = []
for i,(ident,start,end,url,enabled) in enumerate(links):
if not enabled or not url: continue
start,end = max(0,start),min(length,end)
if start == end and start == 0: continue
valid.append((start,end-start,i,ident,end,url))
valid.sort(key=lambda x:(x[0],x[1],x[2]))
seen = set()
rows = []
for start,width,i,ident,end,url in valid:
if ident in seen: continue
seen.add(ident)
rows.append([ident,start,end,url])
hit = next((ident for ident,start,end,url in rows if start <= offset < end),None)
return [rows,hit]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['wide',N,N+4,'/a#x',True],['small',N,N+2,'/a#y',True]],N+1],), [[['small',N,N+2,'/a#y'],['wide',N,N+4,'/a#x']],'small'])
check('contract fixture 2', solve([5,[['a',-3,2,'/a',True],['b',2,8,'/b',True]],2],), [[['a',0,2,'/a'],['b',2,5,'/b']],'b'])
check('contract fixture 3', solve([5,[['a',1,1,'/a',True],['b',4,2,'/b',True],['c',0,3,'',True],['d',0,3,'/d',False]],0],), [[],None])
check('contract fixture 4', solve([6,[['a',3,6,'later',True],['a',0,2,'early',True]],1],), [[['a',0,2,'early']],'a'])
check('contract fixture 5', solve([3,[['a',0,3,'/same',True],['b',0,3,'/same',True]],3],), [[['a',0,3,'/same'],['b',0,3,'/same']],None])
check('contract fixture 6', solve([0,[],0],), [[],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 | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | Passed |
| contract fixture 2 | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | Passed |
| contract fixture 3 | [[['a', 1, 1, '/a'], ['b', 4, 2, '/b']], None] | [[], None] | Failed |
| contract fixture 4 | [[['a', 0, 2, 'early']], 'a'] | [[['a', 0, 2, 'early']], 'a'] | Passed |
| contract fixture 5 | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | Passed |
| contract fixture 6 | [[], None] | [[], None] | Passed |
SHA-256 / bc4b74a2d8b9c362e55a1464d8487703d78347047c261548bc38b329b0d711d8
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
length,links,offset = data
valid = []
for i,(ident,start,end,url,enabled) in enumerate(links):
if not enabled or not url: continue
start,end = max(0,start),min(length,end)
if start >= end: continue
valid.append((start,end-start,i,ident,end,url))
valid.sort(key=lambda x:(x[0],x[1],x[2]))
seen = set()
rows = []
for start,width,i,ident,end,url in valid:
if ident in seen: continue
seen.add(ident)
rows.append([ident,start,end,url])
hit = next((ident for ident,start,end,url in rows if start <= offset < end),None)
return [rows,hit]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['wide',N,N+4,'/a#x',True],['small',N,N+2,'/a#y',True]],N+1],), [[['small',N,N+2,'/a#y'],['wide',N,N+4,'/a#x']],'small'])
check('contract fixture 2', solve([5,[['a',-3,2,'/a',True],['b',2,8,'/b',True]],2],), [[['a',0,2,'/a'],['b',2,5,'/b']],'b'])
check('contract fixture 3', solve([5,[['a',1,1,'/a',True],['b',4,2,'/b',True],['c',0,3,'',True],['d',0,3,'/d',False]],0],), [[],None])
check('contract fixture 4', solve([6,[['a',3,6,'later',True],['a',0,2,'early',True]],1],), [[['a',0,2,'early']],'a'])
check('contract fixture 5', solve([3,[['a',0,3,'/same',True],['b',0,3,'/same',True]],3],), [[['a',0,3,'/same'],['b',0,3,'/same']],None])
check('contract fixture 6', solve([0,[],0],), [[],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 | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | [[['small', 1, 3, '/a#y'], ['wide', 1, 5, '/a#x']], 'small'] | Passed |
| contract fixture 2 | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | [[['a', 0, 2, '/a'], ['b', 2, 5, '/b']], 'b'] | Passed |
| contract fixture 3 | [[], None] | [[], None] | Passed |
| contract fixture 4 | [[['a', 0, 2, 'early']], 'a'] | [[['a', 0, 2, 'early']], 'a'] | Passed |
| contract fixture 5 | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | [[['a', 0, 3, '/same'], ['b', 0, 3, '/same']], None] | Passed |
| contract fixture 6 | [[], None] | [[], None] | Passed |
SHA-256 / f4654d835f55847af12997f87b94c7f2e1def26a29178e6b84b9e32d343f7cde
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:43.167458+00:00.
Case digest / 2fde335bd271d210c60bae738b814a983ca6da6e36e448dc6f0532af424d97ea