FAILURE MAP
← Case archive

FA-54186 / Accessibility interaction semantics / Open access

Annotation ID collisions produce ambiguous descriptors · case 01

Annotation ID collisions produce ambiguous descriptors.

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

ROOT CAUSE

The annotation id decision in the annotation ranges adapter violates its declared contract.

VERIFIED REPAIR

Apply the exact contract at the annotation id decision: or ident in seen

Unsuccessful approach: The local repair substitutes or ident in seen and not detail but still mishandles the regression fixtures.

Case contract

Input [length,annotations,types] annotations [id,start,end,kind,detail,resolved]. Admit allowed types and unresolved annotations with nonempty detail. Clamp half-open ranges, discard empty or reversed. Preserve overlapping annotations; dedupe same ID by first eligible record. Output sorted by start,end,ID. Return [id,start,end,kind,detail]. Spelling, grammar, comment are the only recognized kinds even if types requests unknown types.

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,annotations,types = data
    seen = set()
    result = []
    for ident,start,end,kind,detail,resolved in annotations:
        if kind not in {'spelling','grammar','comment'} or kind not in types: continue
        if resolved or not detail: continue
        start,end = max(0,start),min(length,end)
        if start >= end : continue
        seen.add(ident)
        result.append([ident,start,end,kind,detail])
    return sorted(result,key=lambda row:(row[1],row[2],row[0]))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['b',N,N+3,'comment','B',False],['a',N,N+2,'spelling','A',False],['c',N,N+2,'grammar','C',False]],['comment','spelling','grammar']],), [['a',N,N+2,'spelling','A'],['c',N,N+2,'grammar','C'],['b',N,N+3,'comment','B']])
check('contract fixture 2', solve([4,[['a',-2,2,'comment','A',False],['b',2,8,'comment','B',False]],['comment']],), [['a',0,2,'comment','A'],['b',2,4,'comment','B']])
check('contract fixture 3', solve([4,[['a',0,2,'comment','A',True],['b',0,2,'spelling','B',False],['c',0,2,'unknown','C',False],['d',0,2,'comment','',False]],['comment','unknown']],), [])
check('contract fixture 4', solve([4,[['a',0,0,'comment','zero',False],['b',3,1,'comment','reverse',False]],['comment']],), [])
check('contract fixture 5', solve([4,[['a',2,3,'comment','first',False],['a',0,1,'comment','later',False]],['comment']],), [['a',2,3,'comment','first']])
check('contract fixture 6', solve([4,[['a',0,2,'comment','resolved',True],['a',1,3,'comment','live',False]],['comment']],), [['a',1,3,'comment','live']])
check('contract fixture 7', solve([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[['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']][['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']]Passed
contract fixture 2[['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']][['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']]Passed
contract fixture 3[][]Passed
contract fixture 4[][]Passed
contract fixture 5[['a', 0, 1, 'comment', 'later'], ['a', 2, 3, 'comment', 'first']][['a', 2, 3, 'comment', 'first']]Failed
contract fixture 6[['a', 1, 3, 'comment', 'live']][['a', 1, 3, 'comment', 'live']]Passed
contract fixture 7[][]Passed

SHA-256 / 3945b9bf4fa4e6c981819863aa0e2f899d29fb41c5953a46bc63e02a595a1ccb

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(data):
    length,annotations,types = data
    seen = set()
    result = []
    for ident,start,end,kind,detail,resolved in annotations:
        if kind not in {'spelling','grammar','comment'} or kind not in types: continue
        if resolved or not detail: continue
        start,end = max(0,start),min(length,end)
        if start >= end or ident in seen and not detail: continue
        seen.add(ident)
        result.append([ident,start,end,kind,detail])
    return sorted(result,key=lambda row:(row[1],row[2],row[0]))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['b',N,N+3,'comment','B',False],['a',N,N+2,'spelling','A',False],['c',N,N+2,'grammar','C',False]],['comment','spelling','grammar']],), [['a',N,N+2,'spelling','A'],['c',N,N+2,'grammar','C'],['b',N,N+3,'comment','B']])
check('contract fixture 2', solve([4,[['a',-2,2,'comment','A',False],['b',2,8,'comment','B',False]],['comment']],), [['a',0,2,'comment','A'],['b',2,4,'comment','B']])
check('contract fixture 3', solve([4,[['a',0,2,'comment','A',True],['b',0,2,'spelling','B',False],['c',0,2,'unknown','C',False],['d',0,2,'comment','',False]],['comment','unknown']],), [])
check('contract fixture 4', solve([4,[['a',0,0,'comment','zero',False],['b',3,1,'comment','reverse',False]],['comment']],), [])
check('contract fixture 5', solve([4,[['a',2,3,'comment','first',False],['a',0,1,'comment','later',False]],['comment']],), [['a',2,3,'comment','first']])
check('contract fixture 6', solve([4,[['a',0,2,'comment','resolved',True],['a',1,3,'comment','live',False]],['comment']],), [['a',1,3,'comment','live']])
check('contract fixture 7', solve([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[['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']][['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']]Passed
contract fixture 2[['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']][['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']]Passed
contract fixture 3[][]Passed
contract fixture 4[][]Passed
contract fixture 5[['a', 0, 1, 'comment', 'later'], ['a', 2, 3, 'comment', 'first']][['a', 2, 3, 'comment', 'first']]Failed
contract fixture 6[['a', 1, 3, 'comment', 'live']][['a', 1, 3, 'comment', 'live']]Passed
contract fixture 7[][]Passed

SHA-256 / 5380939167cbb6236ac593a0ee567aee2bef192ebc8fb7cb30647692b3d4ba78

3 / The verified repair

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

N = 1
observations = []
def solve(data):
    length,annotations,types = data
    seen = set()
    result = []
    for ident,start,end,kind,detail,resolved in annotations:
        if kind not in {'spelling','grammar','comment'} or kind not in types: continue
        if resolved or not detail: continue
        start,end = max(0,start),min(length,end)
        if start >= end or ident in seen: continue
        seen.add(ident)
        result.append([ident,start,end,kind,detail])
    return sorted(result,key=lambda row:(row[1],row[2],row[0]))
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+5,[['b',N,N+3,'comment','B',False],['a',N,N+2,'spelling','A',False],['c',N,N+2,'grammar','C',False]],['comment','spelling','grammar']],), [['a',N,N+2,'spelling','A'],['c',N,N+2,'grammar','C'],['b',N,N+3,'comment','B']])
check('contract fixture 2', solve([4,[['a',-2,2,'comment','A',False],['b',2,8,'comment','B',False]],['comment']],), [['a',0,2,'comment','A'],['b',2,4,'comment','B']])
check('contract fixture 3', solve([4,[['a',0,2,'comment','A',True],['b',0,2,'spelling','B',False],['c',0,2,'unknown','C',False],['d',0,2,'comment','',False]],['comment','unknown']],), [])
check('contract fixture 4', solve([4,[['a',0,0,'comment','zero',False],['b',3,1,'comment','reverse',False]],['comment']],), [])
check('contract fixture 5', solve([4,[['a',2,3,'comment','first',False],['a',0,1,'comment','later',False]],['comment']],), [['a',2,3,'comment','first']])
check('contract fixture 6', solve([4,[['a',0,2,'comment','resolved',True],['a',1,3,'comment','live',False]],['comment']],), [['a',1,3,'comment','live']])
check('contract fixture 7', solve([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[['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']][['a', 1, 3, 'spelling', 'A'], ['c', 1, 3, 'grammar', 'C'], ['b', 1, 4, 'comment', 'B']]Passed
contract fixture 2[['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']][['a', 0, 2, 'comment', 'A'], ['b', 2, 4, 'comment', 'B']]Passed
contract fixture 3[][]Passed
contract fixture 4[][]Passed
contract fixture 5[['a', 2, 3, 'comment', 'first']][['a', 2, 3, 'comment', 'first']]Passed
contract fixture 6[['a', 1, 3, 'comment', 'live']][['a', 1, 3, 'comment', 'live']]Passed
contract fixture 7[][]Passed

SHA-256 / 39109e157ea14e2f5b0807fb3b8e6c50af9a6caf8a6cb9f64f2daa8f2be3f1f0

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

Case digest / da42c82524f8c56d8073c91aca9074496eeff6bf452bd1423c5d119748411a72