FAILURE MAP
← Case archive

FA-54306 / Accessibility interaction semantics / Open access

Added objects ignore declared semantic sibling order · case 01

Added objects ignore declared semantic sibling order.

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

ROOT CAUSE

The add order decision in the snapshot delta adapter violates its declared contract.

VERIFIED REPAIR

Apply the exact contract at the add order decision: key=lambda x:(after[x]['order'],x)

Unsuccessful approach: The local repair substitutes key=lambda x:(-after[x]['order'],x) but still mishandles the regression fixtures.

Case contract

Input [before,after] maps stable object ID to {role,name,parent,order}. Return delta operations in phases: removed IDs sorted lexical; added IDs sorted by after order then ID; common IDs sorted lexical get role-replace if role differs, otherwise name-set if name differs; parent/order changes append move even after role-replace. Removed values use old role, added records preserve complete new record, name-set preserves empty names. Same ID is never remove+add just for role changes. Return operations lists.

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):
    before,after = data
    result = []
    for ident in sorted(set(before)-set(after)): result.append(['remove',ident,before[ident]['role']])
    for ident in sorted(set(after)-set(before),key=lambda x:x): result.append(['add',ident,after[ident]])
    for ident in sorted(set(before)&set(after)):
        old,new = before[ident],after[ident]
        if old['role'] != new['role']: result.append(['replace-role',ident,new['role']])
        elif old['name'] != new['name']: result.append(['set-name',ident,new['name']])
        if old['parent'] != new['parent'] or old['order'] != new['order']: result.append(['move',ident,new['parent'],new['order']])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'x':{'role':'image','name':'old','parent':'a','order':N}},{'x':{'role':'button','name':'new','parent':'b','order':N+1}}],), [['replace-role','x','button'],['move','x','b',N+1]])
check('contract fixture 2', solve([{'x':{'role':'image','name':'old','parent':None,'order':0}},{'x':{'role':'image','name':'','parent':None,'order':0}}],), [['set-name','x','']])
check('contract fixture 3', solve([{'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}},{}],), [['remove','a','group'],['remove','z','image']])
check('contract fixture 4', solve([{}, {'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}}],), [['add','z',{'role':'image','name':'Z','parent':None,'order':0}],['add','a',{'role':'group','name':'A','parent':None,'order':1}]])
check('contract fixture 5', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'a','order':N}}],), [['move','x','a',N]])
check('contract fixture 6', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'b','order':0}}],), [['move','x','b',0]])
check('contract fixture 7', solve([{},{}],), [])
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[['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]][['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]]Passed
contract fixture 2[['set-name', 'x', '']][['set-name', 'x', '']]Passed
contract fixture 3[['remove', 'a', 'group'], ['remove', 'z', 'image']][['remove', 'a', 'group'], ['remove', 'z', 'image']]Passed
contract fixture 4[['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}], ['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}]][['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}], ['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}]]Failed
contract fixture 5[['move', 'x', 'a', 1]][['move', 'x', 'a', 1]]Passed
contract fixture 6[['move', 'x', 'b', 0]][['move', 'x', 'b', 0]]Passed
contract fixture 7[][]Passed

SHA-256 / 8a2c0732e21b255a40c2b8e74aec7b9703bbfcc660d8f0f8dfd5bd71f20e759f

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(data):
    before,after = data
    result = []
    for ident in sorted(set(before)-set(after)): result.append(['remove',ident,before[ident]['role']])
    for ident in sorted(set(after)-set(before),key=lambda x:(-after[x]['order'],x)): result.append(['add',ident,after[ident]])
    for ident in sorted(set(before)&set(after)):
        old,new = before[ident],after[ident]
        if old['role'] != new['role']: result.append(['replace-role',ident,new['role']])
        elif old['name'] != new['name']: result.append(['set-name',ident,new['name']])
        if old['parent'] != new['parent'] or old['order'] != new['order']: result.append(['move',ident,new['parent'],new['order']])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'x':{'role':'image','name':'old','parent':'a','order':N}},{'x':{'role':'button','name':'new','parent':'b','order':N+1}}],), [['replace-role','x','button'],['move','x','b',N+1]])
check('contract fixture 2', solve([{'x':{'role':'image','name':'old','parent':None,'order':0}},{'x':{'role':'image','name':'','parent':None,'order':0}}],), [['set-name','x','']])
check('contract fixture 3', solve([{'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}},{}],), [['remove','a','group'],['remove','z','image']])
check('contract fixture 4', solve([{}, {'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}}],), [['add','z',{'role':'image','name':'Z','parent':None,'order':0}],['add','a',{'role':'group','name':'A','parent':None,'order':1}]])
check('contract fixture 5', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'a','order':N}}],), [['move','x','a',N]])
check('contract fixture 6', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'b','order':0}}],), [['move','x','b',0]])
check('contract fixture 7', solve([{},{}],), [])
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[['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]][['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]]Passed
contract fixture 2[['set-name', 'x', '']][['set-name', 'x', '']]Passed
contract fixture 3[['remove', 'a', 'group'], ['remove', 'z', 'image']][['remove', 'a', 'group'], ['remove', 'z', 'image']]Passed
contract fixture 4[['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}], ['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}]][['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}], ['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}]]Failed
contract fixture 5[['move', 'x', 'a', 1]][['move', 'x', 'a', 1]]Passed
contract fixture 6[['move', 'x', 'b', 0]][['move', 'x', 'b', 0]]Passed
contract fixture 7[][]Passed

SHA-256 / 7cdc49f8062a9cfb70335be6ec6f0f9b41937ad0441e0bfd702ece419d30e1c7

3 / The verified repair

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

N = 1
observations = []
def solve(data):
    before,after = data
    result = []
    for ident in sorted(set(before)-set(after)): result.append(['remove',ident,before[ident]['role']])
    for ident in sorted(set(after)-set(before),key=lambda x:(after[x]['order'],x)): result.append(['add',ident,after[ident]])
    for ident in sorted(set(before)&set(after)):
        old,new = before[ident],after[ident]
        if old['role'] != new['role']: result.append(['replace-role',ident,new['role']])
        elif old['name'] != new['name']: result.append(['set-name',ident,new['name']])
        if old['parent'] != new['parent'] or old['order'] != new['order']: result.append(['move',ident,new['parent'],new['order']])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'x':{'role':'image','name':'old','parent':'a','order':N}},{'x':{'role':'button','name':'new','parent':'b','order':N+1}}],), [['replace-role','x','button'],['move','x','b',N+1]])
check('contract fixture 2', solve([{'x':{'role':'image','name':'old','parent':None,'order':0}},{'x':{'role':'image','name':'','parent':None,'order':0}}],), [['set-name','x','']])
check('contract fixture 3', solve([{'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}},{}],), [['remove','a','group'],['remove','z','image']])
check('contract fixture 4', solve([{}, {'z':{'role':'image','name':'Z','parent':None,'order':0},'a':{'role':'group','name':'A','parent':None,'order':1}}],), [['add','z',{'role':'image','name':'Z','parent':None,'order':0}],['add','a',{'role':'group','name':'A','parent':None,'order':1}]])
check('contract fixture 5', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'a','order':N}}],), [['move','x','a',N]])
check('contract fixture 6', solve([{'x':{'role':'image','name':'X','parent':'a','order':0}},{'x':{'role':'image','name':'X','parent':'b','order':0}}],), [['move','x','b',0]])
check('contract fixture 7', solve([{},{}],), [])
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[['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]][['replace-role', 'x', 'button'], ['move', 'x', 'b', 2]]Passed
contract fixture 2[['set-name', 'x', '']][['set-name', 'x', '']]Passed
contract fixture 3[['remove', 'a', 'group'], ['remove', 'z', 'image']][['remove', 'a', 'group'], ['remove', 'z', 'image']]Passed
contract fixture 4[['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}], ['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}]][['add', 'z', {'name': 'Z', 'order': 0, 'parent': None, 'role': 'image'}], ['add', 'a', {'name': 'A', 'order': 1, 'parent': None, 'role': 'group'}]]Passed
contract fixture 5[['move', 'x', 'a', 1]][['move', 'x', 'a', 1]]Passed
contract fixture 6[['move', 'x', 'b', 0]][['move', 'x', 'b', 0]]Passed
contract fixture 7[][]Passed

SHA-256 / 9354be8a55177f12917ccdb77fbde6bed5abc6e05a83b2081b5ca1d202d92629

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

Case digest / 37c306abadaba54df22d14e96e000eff7a1aabf81a57c8526291327b4e3e9441