FA-11391 / Accessibility interaction semantics / Open access
A visible child escapes a hidden ancestor · case 01
A descendant remains exposed despite a hidden container.
ROOT CAUSE
Each node is filtered independently instead of pruning hidden subtrees.
VERIFIED REPAIR
Carry the inherited hidden state through every ancestor.
Unsuccessful approach: Checking only the immediate parent still exposes grandchildren of a hidden node.
Case contract
Input is preorder [id,parent_id,hidden] for a forest with unique IDs and parents preceding children. Return exposed IDs in input order; any hidden ancestor excludes a node even if its own hidden flag is false.
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):
return [ident for ident, parent, hidden in nodes if not hidden]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('hidden grandparent', solve([('a',None,True),('b','a',False),(str(N),'b',False)]), [])
check('hidden parent', solve([('a',None,True),(str(N),'a',False)]), [])
check('visible ancestors', solve([('a',None,False),(str(N),'a',False)]), ['a',str(N)])
check('hidden leaf', solve([('a',None,False),(str(N),'a',True)]), ['a'])
check('independent roots', solve([('a',None,True),(str(N),None,False)]), [str(N)])
check('empty forest', 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| hidden grandparent | ['b', '1'] | [] | Failed |
| hidden parent | ['1'] | [] | Failed |
| visible ancestors | ['a', '1'] | ['a', '1'] | Passed |
| hidden leaf | ['a'] | ['a'] | Passed |
| independent roots | ['1'] | ['1'] | Passed |
| empty forest | [] | [] | Passed |
SHA-256 / 5b3bc5c32f6190d4e8ca1be1fa67d580dfdda8f2c4a9a194a138fb9e12ff3392
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(nodes):
flags = {ident: hidden for ident, parent, hidden in nodes}
return [ident for ident, parent, hidden in nodes if not hidden and not flags.get(parent, False)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('hidden grandparent', solve([('a',None,True),('b','a',False),(str(N),'b',False)]), [])
check('hidden parent', solve([('a',None,True),(str(N),'a',False)]), [])
check('visible ancestors', solve([('a',None,False),(str(N),'a',False)]), ['a',str(N)])
check('hidden leaf', solve([('a',None,False),(str(N),'a',True)]), ['a'])
check('independent roots', solve([('a',None,True),(str(N),None,False)]), [str(N)])
check('empty forest', 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| hidden grandparent | ['1'] | [] | Failed |
| hidden parent | [] | [] | Passed |
| visible ancestors | ['a', '1'] | ['a', '1'] | Passed |
| hidden leaf | ['a'] | ['a'] | Passed |
| independent roots | ['1'] | ['1'] | Passed |
| empty forest | [] | [] | Passed |
SHA-256 / 51044f99f38625973eac4598bf69feb73f032f90190f14adc4eaab927f64196d
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(nodes):
excluded = {}
result = []
for ident, parent, hidden in nodes:
excluded[ident] = hidden or excluded.get(parent, False)
if not excluded[ident]: result.append(ident)
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('hidden grandparent', solve([('a',None,True),('b','a',False),(str(N),'b',False)]), [])
check('hidden parent', solve([('a',None,True),(str(N),'a',False)]), [])
check('visible ancestors', solve([('a',None,False),(str(N),'a',False)]), ['a',str(N)])
check('hidden leaf', solve([('a',None,False),(str(N),'a',True)]), ['a'])
check('independent roots', solve([('a',None,True),(str(N),None,False)]), [str(N)])
check('empty forest', 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| hidden grandparent | [] | [] | Passed |
| hidden parent | [] | [] | Passed |
| visible ancestors | ['a', '1'] | ['a', '1'] | Passed |
| hidden leaf | ['a'] | ['a'] | Passed |
| independent roots | ['1'] | ['1'] | Passed |
| empty forest | [] | [] | Passed |
SHA-256 / 5b1cd697dce82c1162e788a12f4b59281b44707ac9a69695b6ce8834df48ce2a
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.447501+00:00.
Case digest / 7c7e936550c8f54676a80b1990bd679b64416da90f8d68ce30674025a82c25f9