FA-11436 / Accessibility interaction semantics / Open access
An owned node appears under two accessibility parents · case 01
An explicit ownership edge adds a second copy instead of moving the child.
ROOT CAUSE
The accessibility hierarchy is built by appending owned children without removing natural-parent links.
VERIFIED REPAIR
Remove claimed nodes from all natural child lists, then append each owner’s ordered claims.
Unsuccessful approach: Removing the old parent link fixes duplication but retaining natural ordering ignores the owner’s explicit child order.
Case contract
Input natural maps parent IDs to ordered immediate child IDs, and owns maps owners to ordered claimed IDs. All IDs exist, claims are unique globally, and combined ownership is acyclic. Return parent child lists preserving unclaimed natural order followed by declared owned order. Claimed natural children are reordered into the owned suffix; do not mutate inputs.
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(natural, owns):
result = {parent:list(children) for parent,children in natural.items()}
for owner,children in owns.items(): result.setdefault(owner, []).extend(children)
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('same parent explicit order', solve({'p':['a',str(N),'b']}, {'p':['b','a']} ), {'p':[str(N),'b','a']})
check('cross parent move', solve({'p':[str(N)],'q':[]}, {'q':[str(N)]}), {'p':[],'q':[str(N)]})
check('owned suffix', solve({'p':['a','b',str(N)]}, {'p':['a']}), {'p':['b',str(N),'a']})
check('no claims', solve({'p':[str(N)],'q':[]}, {}), {'p':[str(N)],'q':[]})
check('empty claims', solve({'p':[str(N)]}, {'p':[]}), {'p':[str(N)]})
check('leaf becomes owner', solve({'root':['owner',str(N)]}, {'owner':[str(N)]}), {'root':['owner'],'owner':[str(N)]})
check('empty hierarchy', 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 |
|---|---|---|---|
| same parent explicit order | {'p': ['a', '1', 'b', 'b', 'a']} | {'p': ['1', 'b', 'a']} | Failed |
| cross parent move | {'p': ['1'], 'q': ['1']} | {'p': [], 'q': ['1']} | Failed |
| owned suffix | {'p': ['a', 'b', '1', 'a']} | {'p': ['b', '1', 'a']} | Failed |
| no claims | {'p': ['1'], 'q': []} | {'p': ['1'], 'q': []} | Passed |
| empty claims | {'p': ['1']} | {'p': ['1']} | Passed |
| leaf becomes owner | {'owner': ['1'], 'root': ['owner', '1']} | {'owner': ['1'], 'root': ['owner']} | Failed |
| empty hierarchy | {} | {} | Passed |
SHA-256 / 02ce5df8d5d6af17474bec0fa24a641b836198fb43d6f0f2a583370f9423bef9
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(natural, owns):
claimed = {child:owner for owner,children in owns.items() for child in children}
result = {parent:[child for child in children if child not in claimed or claimed[child] == parent] for parent,children in natural.items()}
for owner,children in owns.items():
result.setdefault(owner, [])
result[owner].extend(child for child in children if child not in result[owner])
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('same parent explicit order', solve({'p':['a',str(N),'b']}, {'p':['b','a']} ), {'p':[str(N),'b','a']})
check('cross parent move', solve({'p':[str(N)],'q':[]}, {'q':[str(N)]}), {'p':[],'q':[str(N)]})
check('owned suffix', solve({'p':['a','b',str(N)]}, {'p':['a']}), {'p':['b',str(N),'a']})
check('no claims', solve({'p':[str(N)],'q':[]}, {}), {'p':[str(N)],'q':[]})
check('empty claims', solve({'p':[str(N)]}, {'p':[]}), {'p':[str(N)]})
check('leaf becomes owner', solve({'root':['owner',str(N)]}, {'owner':[str(N)]}), {'root':['owner'],'owner':[str(N)]})
check('empty hierarchy', 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 |
|---|---|---|---|
| same parent explicit order | {'p': ['a', '1', 'b']} | {'p': ['1', 'b', 'a']} | Failed |
| cross parent move | {'p': [], 'q': ['1']} | {'p': [], 'q': ['1']} | Passed |
| owned suffix | {'p': ['a', 'b', '1']} | {'p': ['b', '1', 'a']} | Failed |
| no claims | {'p': ['1'], 'q': []} | {'p': ['1'], 'q': []} | Passed |
| empty claims | {'p': ['1']} | {'p': ['1']} | Passed |
| leaf becomes owner | {'owner': ['1'], 'root': ['owner']} | {'owner': ['1'], 'root': ['owner']} | Passed |
| empty hierarchy | {} | {} | Passed |
SHA-256 / 29dc49f96988efea63e896797193c0677c24ee0e3d49e44c2399ffc2800753e8
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(natural, owns):
claimed = {child for children in owns.values() for child in children}
result = {parent:[child for child in children if child not in claimed] for parent,children in natural.items()}
for owner,children in owns.items(): result.setdefault(owner, []).extend(children)
return result
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('same parent explicit order', solve({'p':['a',str(N),'b']}, {'p':['b','a']} ), {'p':[str(N),'b','a']})
check('cross parent move', solve({'p':[str(N)],'q':[]}, {'q':[str(N)]}), {'p':[],'q':[str(N)]})
check('owned suffix', solve({'p':['a','b',str(N)]}, {'p':['a']}), {'p':['b',str(N),'a']})
check('no claims', solve({'p':[str(N)],'q':[]}, {}), {'p':[str(N)],'q':[]})
check('empty claims', solve({'p':[str(N)]}, {'p':[]}), {'p':[str(N)]})
check('leaf becomes owner', solve({'root':['owner',str(N)]}, {'owner':[str(N)]}), {'root':['owner'],'owner':[str(N)]})
check('empty hierarchy', 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 |
|---|---|---|---|
| same parent explicit order | {'p': ['1', 'b', 'a']} | {'p': ['1', 'b', 'a']} | Passed |
| cross parent move | {'p': [], 'q': ['1']} | {'p': [], 'q': ['1']} | Passed |
| owned suffix | {'p': ['b', '1', 'a']} | {'p': ['b', '1', 'a']} | Passed |
| no claims | {'p': ['1'], 'q': []} | {'p': ['1'], 'q': []} | Passed |
| empty claims | {'p': ['1']} | {'p': ['1']} | Passed |
| leaf becomes owner | {'owner': ['1'], 'root': ['owner']} | {'owner': ['1'], 'root': ['owner']} | Passed |
| empty hierarchy | {} | {} | Passed |
SHA-256 / 192f9d99ab96d80ce8dde53b37ed233fe351a7a85b03d85d2992fd9c7daa46cc
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.983485+00:00.
Case digest / 8a3166053b6f0a7e6f8c52aa5ac3dc4b4cb7a06ab6d1e199396ea92909bf10ca