FAILURE MAP
← Case archive

FA-11396 / Accessibility interaction semantics / Open access

Removing a presentational wrapper deletes its meaningful descendants · case 01

A text-bearing child disappears when its structural wrapper has no exposed role.

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

ROOT CAUSE

Suppressing wrapper semantics is confused with suppressing the entire subtree.

VERIFIED REPAIR

Map each presentational wrapper to its nearest exposed ancestor before assigning child parents.

Unsuccessful approach: Keeping every descendant as a root preserves content but destroys the nearest meaningful parent relationship.

Case contract

Input is preorder [id,parent,presentational] with unique IDs and earlier parents. Return [id,exposed_parent] for nonpresentational nodes. Presentational nodes disappear but their descendants retain the nearest nonpresentational ancestor, or None.

Why this case matters

A controlled offline accessibility-data model. It isolates the stated contract; it does not simulate browser accessibility APIs or claim full ARIA conformance.

1 / The failure

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

N = 1
observations = []
def solve(nodes):
    gone = set()
    result = []
    for ident,parent,presentation in nodes:
        if presentation or parent in gone: gone.add(ident)
        else: result.append([ident,parent])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('nested wrapper', solve([('a',None,False),('w','a',True),(str(N),'w',False)]), [['a',None],[str(N),'a']])
check('root wrapper', solve([('w',None,True),(str(N),'w',False)]), [[str(N),None]])
check('multiple wrappers', solve([('a',None,False),('w','a',True),('v','w',True),(str(N),'v',False)]), [['a',None],[str(N),'a']])
check('meaningful child parent', solve([('a',None,False),('b','a',False),(str(N),'b',False)]), [['a',None],['b','a'],[str(N),'b']])
check('only wrapper', solve([(str(N),None,True)]), [])
check('empty', 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
nested wrapper[['a', None]][['a', None], ['1', 'a']]Failed
root wrapper[][['1', None]]Failed
multiple wrappers[['a', None]][['a', None], ['1', 'a']]Failed
meaningful child parent[['a', None], ['b', 'a'], ['1', 'b']][['a', None], ['b', 'a'], ['1', 'b']]Passed
only wrapper[][]Passed
empty[][]Passed

SHA-256 / aaf2e652d045c496359d4e8925f19bc65f69a20ce6b2d21e16c913eaf1d8f809

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(nodes):
    present = {ident for ident,parent,presentation in nodes if presentation}
    return [[ident, None if parent in present else parent] for ident,parent,presentation in nodes if not presentation]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('nested wrapper', solve([('a',None,False),('w','a',True),(str(N),'w',False)]), [['a',None],[str(N),'a']])
check('root wrapper', solve([('w',None,True),(str(N),'w',False)]), [[str(N),None]])
check('multiple wrappers', solve([('a',None,False),('w','a',True),('v','w',True),(str(N),'v',False)]), [['a',None],[str(N),'a']])
check('meaningful child parent', solve([('a',None,False),('b','a',False),(str(N),'b',False)]), [['a',None],['b','a'],[str(N),'b']])
check('only wrapper', solve([(str(N),None,True)]), [])
check('empty', 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
nested wrapper[['a', None], ['1', None]][['a', None], ['1', 'a']]Failed
root wrapper[['1', None]][['1', None]]Passed
multiple wrappers[['a', None], ['1', None]][['a', None], ['1', 'a']]Failed
meaningful child parent[['a', None], ['b', 'a'], ['1', 'b']][['a', None], ['b', 'a'], ['1', 'b']]Passed
only wrapper[][]Passed
empty[][]Passed

SHA-256 / 53bd37219f654ea40cf05b02a92d44e822b1a30f49cb8a0f3a5bf24a19238c11

3 / The verified repair

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

N = 1
observations = []
def solve(nodes):
    nearest = {None: None}
    result = []
    for ident,parent,presentation in nodes:
        ancestor = nearest[parent]
        nearest[ident] = ancestor if presentation else ident
        if not presentation: result.append([ident,ancestor])
    return result
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('nested wrapper', solve([('a',None,False),('w','a',True),(str(N),'w',False)]), [['a',None],[str(N),'a']])
check('root wrapper', solve([('w',None,True),(str(N),'w',False)]), [[str(N),None]])
check('multiple wrappers', solve([('a',None,False),('w','a',True),('v','w',True),(str(N),'v',False)]), [['a',None],[str(N),'a']])
check('meaningful child parent', solve([('a',None,False),('b','a',False),(str(N),'b',False)]), [['a',None],['b','a'],[str(N),'b']])
check('only wrapper', solve([(str(N),None,True)]), [])
check('empty', 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
nested wrapper[['a', None], ['1', 'a']][['a', None], ['1', 'a']]Passed
root wrapper[['1', None]][['1', None]]Passed
multiple wrappers[['a', None], ['1', 'a']][['a', None], ['1', 'a']]Passed
meaningful child parent[['a', None], ['b', 'a'], ['1', 'b']][['a', None], ['b', 'a'], ['1', 'b']]Passed
only wrapper[][]Passed
empty[][]Passed

SHA-256 / 31848d8967daba617f1d8126ac18d396289f17d42cf901d1afdfa760aa6e373c

Verification & scope

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

Case digest / 47110da19cce9cd7af9a1a9c4bb3106cb84c897e8ad53d58cbf1c37f0aa158a9