FAILURE MAP
← Case archive

FA-53796 / Accessibility interaction semantics / Open access

Coalesced attribute runs lose their final character · case 01

Coalesced attribute runs lose their final character.

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

ROOT CAUSE

The run extension decision in the text attribute runs adapter violates its declared contract.

VERIFIED REPAIR

Apply the exact contract at the run extension decision: result[-1][1] = pos+1

Unsuccessful approach: The local repair substitutes result[-1][1] += 0 but still mishandles the regression fixtures.

Case contract

Input [length,default_attributes,spans] where spans are [start,end,attributes,priority]. Clamp endpoints to [0,length], discard empty/reversed spans. At each character position merge active spans over defaults by increasing priority, preserving input tie order; None attribute removes that attribute. Build maximal equal adjacent runs [start,end,attributes]. Zero length returns empty. Offsets are codepoints. Dictionary values are strings or None.

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,defaults,spans = data
    points = []
    for pos in range(length):
        attrs = dict(defaults)
        active = [(p,i,a) for i,(s,e,a,p) in enumerate(spans) if max(0,s) <= pos < min(length,e)]
        for priority,idx,updates in sorted(active,key=lambda x:(x[0],x[1])):
            for key,value in updates.items():
                if value is None: attrs.pop(key,None)
                else: attrs[key] = value
        points.append(attrs)
    result = []
    for pos,attrs in enumerate(points):
        if result and result[-1][2] == attrs: result[-1][1] = pos
        else: result.append([pos,pos+1,attrs])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+2,{'lang':'en'},[[0,N,{'weight':'bold'},1],[1,N+1,{'lang':'fr'},2]]],), [[0,1,{'lang':'en','weight':'bold'}]]+([[1,N,{'lang':'fr','weight':'bold'}]] if N>1 else [])+[[N,N+1,{'lang':'fr'}],[N+1,N+2,{'lang':'en'}]])
check('contract fixture 2', solve([3,{'lang':'en','color':'red'},[[0,3,{'lang':None},1],[1,2,{'color':'blue'},2]]],), [[0,1,{'color':'red'}],[1,2,{'color':'blue'}],[2,3,{'color':'red'}]])
check('contract fixture 3', solve([3,{},[[0,3,{'x':'high'},5],[0,3,{'x':'low'},1]]],), [[0,3,{'x':'high'}]])
check('contract fixture 4', solve([3,{},[[0,3,{'x':'first'},1],[0,3,{'x':'last'},1]]],), [[0,3,{'x':'last'}]])
check('contract fixture 5', solve([3,{},[[-3,2,{'x':'a'},0],[2,8,{'x':'a'},0],[2,1,{'x':'bad'},9]]],), [[0,3,{'x':'a'}]])
check('contract fixture 6', solve([0,{'lang':'en'},[]],), [])
check('contract fixture 7', solve([2,{'lang':'en'},[[0,1,{},0]]],), [[0,2,{'lang':'en'}]])
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[[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]][[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]]Passed
contract fixture 2[[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]][[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]]Passed
contract fixture 3[[0, 2, {'x': 'high'}]][[0, 3, {'x': 'high'}]]Failed
contract fixture 4[[0, 2, {'x': 'last'}]][[0, 3, {'x': 'last'}]]Failed
contract fixture 5[[0, 2, {'x': 'a'}]][[0, 3, {'x': 'a'}]]Failed
contract fixture 6[][]Passed
contract fixture 7[[0, 1, {'lang': 'en'}]][[0, 2, {'lang': 'en'}]]Failed

SHA-256 / ce167dedffe747821e382b75e8d18ea64010c5af8909d241378439c13cb9b634

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(data):
    length,defaults,spans = data
    points = []
    for pos in range(length):
        attrs = dict(defaults)
        active = [(p,i,a) for i,(s,e,a,p) in enumerate(spans) if max(0,s) <= pos < min(length,e)]
        for priority,idx,updates in sorted(active,key=lambda x:(x[0],x[1])):
            for key,value in updates.items():
                if value is None: attrs.pop(key,None)
                else: attrs[key] = value
        points.append(attrs)
    result = []
    for pos,attrs in enumerate(points):
        if result and result[-1][2] == attrs: result[-1][1] += 0
        else: result.append([pos,pos+1,attrs])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+2,{'lang':'en'},[[0,N,{'weight':'bold'},1],[1,N+1,{'lang':'fr'},2]]],), [[0,1,{'lang':'en','weight':'bold'}]]+([[1,N,{'lang':'fr','weight':'bold'}]] if N>1 else [])+[[N,N+1,{'lang':'fr'}],[N+1,N+2,{'lang':'en'}]])
check('contract fixture 2', solve([3,{'lang':'en','color':'red'},[[0,3,{'lang':None},1],[1,2,{'color':'blue'},2]]],), [[0,1,{'color':'red'}],[1,2,{'color':'blue'}],[2,3,{'color':'red'}]])
check('contract fixture 3', solve([3,{},[[0,3,{'x':'high'},5],[0,3,{'x':'low'},1]]],), [[0,3,{'x':'high'}]])
check('contract fixture 4', solve([3,{},[[0,3,{'x':'first'},1],[0,3,{'x':'last'},1]]],), [[0,3,{'x':'last'}]])
check('contract fixture 5', solve([3,{},[[-3,2,{'x':'a'},0],[2,8,{'x':'a'},0],[2,1,{'x':'bad'},9]]],), [[0,3,{'x':'a'}]])
check('contract fixture 6', solve([0,{'lang':'en'},[]],), [])
check('contract fixture 7', solve([2,{'lang':'en'},[[0,1,{},0]]],), [[0,2,{'lang':'en'}]])
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[[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]][[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]]Passed
contract fixture 2[[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]][[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]]Passed
contract fixture 3[[0, 1, {'x': 'high'}]][[0, 3, {'x': 'high'}]]Failed
contract fixture 4[[0, 1, {'x': 'last'}]][[0, 3, {'x': 'last'}]]Failed
contract fixture 5[[0, 1, {'x': 'a'}]][[0, 3, {'x': 'a'}]]Failed
contract fixture 6[][]Passed
contract fixture 7[[0, 1, {'lang': 'en'}]][[0, 2, {'lang': 'en'}]]Failed

SHA-256 / b2d6246afb720915d423751675c59a739e993a87b8c186184e0a1f611260cc66

3 / The verified repair

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

N = 1
observations = []
def solve(data):
    length,defaults,spans = data
    points = []
    for pos in range(length):
        attrs = dict(defaults)
        active = [(p,i,a) for i,(s,e,a,p) in enumerate(spans) if max(0,s) <= pos < min(length,e)]
        for priority,idx,updates in sorted(active,key=lambda x:(x[0],x[1])):
            for key,value in updates.items():
                if value is None: attrs.pop(key,None)
                else: attrs[key] = value
        points.append(attrs)
    result = []
    for pos,attrs in enumerate(points):
        if result and result[-1][2] == attrs: result[-1][1] = pos+1
        else: result.append([pos,pos+1,attrs])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([N+2,{'lang':'en'},[[0,N,{'weight':'bold'},1],[1,N+1,{'lang':'fr'},2]]],), [[0,1,{'lang':'en','weight':'bold'}]]+([[1,N,{'lang':'fr','weight':'bold'}]] if N>1 else [])+[[N,N+1,{'lang':'fr'}],[N+1,N+2,{'lang':'en'}]])
check('contract fixture 2', solve([3,{'lang':'en','color':'red'},[[0,3,{'lang':None},1],[1,2,{'color':'blue'},2]]],), [[0,1,{'color':'red'}],[1,2,{'color':'blue'}],[2,3,{'color':'red'}]])
check('contract fixture 3', solve([3,{},[[0,3,{'x':'high'},5],[0,3,{'x':'low'},1]]],), [[0,3,{'x':'high'}]])
check('contract fixture 4', solve([3,{},[[0,3,{'x':'first'},1],[0,3,{'x':'last'},1]]],), [[0,3,{'x':'last'}]])
check('contract fixture 5', solve([3,{},[[-3,2,{'x':'a'},0],[2,8,{'x':'a'},0],[2,1,{'x':'bad'},9]]],), [[0,3,{'x':'a'}]])
check('contract fixture 6', solve([0,{'lang':'en'},[]],), [])
check('contract fixture 7', solve([2,{'lang':'en'},[[0,1,{},0]]],), [[0,2,{'lang':'en'}]])
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[[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]][[0, 1, {'lang': 'en', 'weight': 'bold'}], [1, 2, {'lang': 'fr'}], [2, 3, {'lang': 'en'}]]Passed
contract fixture 2[[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]][[0, 1, {'color': 'red'}], [1, 2, {'color': 'blue'}], [2, 3, {'color': 'red'}]]Passed
contract fixture 3[[0, 3, {'x': 'high'}]][[0, 3, {'x': 'high'}]]Passed
contract fixture 4[[0, 3, {'x': 'last'}]][[0, 3, {'x': 'last'}]]Passed
contract fixture 5[[0, 3, {'x': 'a'}]][[0, 3, {'x': 'a'}]]Passed
contract fixture 6[][]Passed
contract fixture 7[[0, 2, {'lang': 'en'}]][[0, 2, {'lang': 'en'}]]Passed

SHA-256 / 32ebd0cffac1988cd1602c91ab559cbf8a7e675b59a345a2c31984585f7ebbf5

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

Case digest / b522efd707775b7daccb3938711eb50c206ac13b636497f4d0f6a85f55f485d0