FA-54656 / Accessibility interaction semantics / Open access
Defunct accessibility objects retain readable properties · case 01
Defunct accessibility objects retain readable properties.
ROOT CAUSE
The dead read decision in the property query batch adapter violates its declared contract.
VERIFIED REPAIR
Apply the exact contract at the dead read decision: record is None or not record[0]
Unsuccessful approach: The local repair substitutes record is None or record[0] is None but still mishandles the regression fixtures.
Case contract
Input [objects,queries,revision,expected_revision]. objects map IDs to [alive,properties]; queries [id,property]. Allowed props name,value,description,role; a missing property is unsupported while an existing None is successful null. Results retain query order and duplicates, each [status,value]; status stale for every query when revisions differ, gone for missing/defunct object, unsupported for unknown/absent property, ok otherwise. Empty queries produce empty output. Return [revision,results], actual revision always. Values are returned as JSON-compatible content; object aliasing is outside this query-only model.
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):
objects,queries,revision,expected = data
results = []
for ident,prop in queries:
if expected != revision: results.append(['stale',None]); continue
record = objects.get(ident)
if record is None: results.append(['gone',None]); continue
values = record[1]
if prop not in {'name','value','description','role'} or prop not in values:
results.append(['unsupported',None]); continue
results.append(['ok',values.get(prop)])
return [revision,results]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'a':[True,{'name':'A'+str(N),'value':None,'description':'','role':'image'}]},[['a','name'],['a','value'],['a','description'],['a','name']],N,N],), [N,[['ok','A'+str(N)],['ok',None],['ok',''],['ok','A'+str(N)]]])
check('contract fixture 2', solve([{'a':[True,{'secret':'s','name':'A'}]},[['a','secret'],['a','role']],N,N],), [N,[['unsupported',None],['unsupported',None]]])
check('contract fixture 3', solve([{'dead':[False,{'name':'secret'}]},[['missing','name'],['dead','name']],N,N],), [N,[['gone',None],['gone',None]]])
check('contract fixture 4', solve([{'a':[True,{'name':'A'}]},[['a','name'],['missing','role']],N,N-1],), [N,[['stale',None],['stale',None]]])
check('contract fixture 5', solve([{'a':[True,{'name':'A'}]},[['a','name']],N,N+1],), [N,[['stale',None]]])
check('contract fixture 6', solve([{},[],N,N],), [N,[]])
check('contract fixture 7', solve([{'z':[True,{'name':'Z'}],'a':[True,{'name':'A'}]},[['z','name'],['a','name']],N,N],), [N,[['ok','Z'],['ok','A']]])
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 |
|---|---|---|---|
| contract fixture 1 | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | Passed |
| contract fixture 2 | [1, [['unsupported', None], ['unsupported', None]]] | [1, [['unsupported', None], ['unsupported', None]]] | Passed |
| contract fixture 3 | [1, [['gone', None], ['ok', 'secret']]] | [1, [['gone', None], ['gone', None]]] | Failed |
| contract fixture 4 | [1, [['stale', None], ['stale', None]]] | [1, [['stale', None], ['stale', None]]] | Passed |
| contract fixture 5 | [1, [['stale', None]]] | [1, [['stale', None]]] | Passed |
| contract fixture 6 | [1, []] | [1, []] | Passed |
| contract fixture 7 | [1, [['ok', 'Z'], ['ok', 'A']]] | [1, [['ok', 'Z'], ['ok', 'A']]] | Passed |
SHA-256 / 1d63c5c546dc5a0a481488587a86a2872382b949a0dc91878b00ac913cec87f5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
objects,queries,revision,expected = data
results = []
for ident,prop in queries:
if expected != revision: results.append(['stale',None]); continue
record = objects.get(ident)
if record is None or record[0] is None: results.append(['gone',None]); continue
values = record[1]
if prop not in {'name','value','description','role'} or prop not in values:
results.append(['unsupported',None]); continue
results.append(['ok',values.get(prop)])
return [revision,results]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'a':[True,{'name':'A'+str(N),'value':None,'description':'','role':'image'}]},[['a','name'],['a','value'],['a','description'],['a','name']],N,N],), [N,[['ok','A'+str(N)],['ok',None],['ok',''],['ok','A'+str(N)]]])
check('contract fixture 2', solve([{'a':[True,{'secret':'s','name':'A'}]},[['a','secret'],['a','role']],N,N],), [N,[['unsupported',None],['unsupported',None]]])
check('contract fixture 3', solve([{'dead':[False,{'name':'secret'}]},[['missing','name'],['dead','name']],N,N],), [N,[['gone',None],['gone',None]]])
check('contract fixture 4', solve([{'a':[True,{'name':'A'}]},[['a','name'],['missing','role']],N,N-1],), [N,[['stale',None],['stale',None]]])
check('contract fixture 5', solve([{'a':[True,{'name':'A'}]},[['a','name']],N,N+1],), [N,[['stale',None]]])
check('contract fixture 6', solve([{},[],N,N],), [N,[]])
check('contract fixture 7', solve([{'z':[True,{'name':'Z'}],'a':[True,{'name':'A'}]},[['z','name'],['a','name']],N,N],), [N,[['ok','Z'],['ok','A']]])
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 |
|---|---|---|---|
| contract fixture 1 | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | Passed |
| contract fixture 2 | [1, [['unsupported', None], ['unsupported', None]]] | [1, [['unsupported', None], ['unsupported', None]]] | Passed |
| contract fixture 3 | [1, [['gone', None], ['ok', 'secret']]] | [1, [['gone', None], ['gone', None]]] | Failed |
| contract fixture 4 | [1, [['stale', None], ['stale', None]]] | [1, [['stale', None], ['stale', None]]] | Passed |
| contract fixture 5 | [1, [['stale', None]]] | [1, [['stale', None]]] | Passed |
| contract fixture 6 | [1, []] | [1, []] | Passed |
| contract fixture 7 | [1, [['ok', 'Z'], ['ok', 'A']]] | [1, [['ok', 'Z'], ['ok', 'A']]] | Passed |
SHA-256 / 2790b043199bb1b5e406f26d920e19698546615e1813279d0da0409fa2c1e164
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(data):
objects,queries,revision,expected = data
results = []
for ident,prop in queries:
if expected != revision: results.append(['stale',None]); continue
record = objects.get(ident)
if record is None or not record[0]: results.append(['gone',None]); continue
values = record[1]
if prop not in {'name','value','description','role'} or prop not in values:
results.append(['unsupported',None]); continue
results.append(['ok',values.get(prop)])
return [revision,results]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('contract fixture 1', solve([{'a':[True,{'name':'A'+str(N),'value':None,'description':'','role':'image'}]},[['a','name'],['a','value'],['a','description'],['a','name']],N,N],), [N,[['ok','A'+str(N)],['ok',None],['ok',''],['ok','A'+str(N)]]])
check('contract fixture 2', solve([{'a':[True,{'secret':'s','name':'A'}]},[['a','secret'],['a','role']],N,N],), [N,[['unsupported',None],['unsupported',None]]])
check('contract fixture 3', solve([{'dead':[False,{'name':'secret'}]},[['missing','name'],['dead','name']],N,N],), [N,[['gone',None],['gone',None]]])
check('contract fixture 4', solve([{'a':[True,{'name':'A'}]},[['a','name'],['missing','role']],N,N-1],), [N,[['stale',None],['stale',None]]])
check('contract fixture 5', solve([{'a':[True,{'name':'A'}]},[['a','name']],N,N+1],), [N,[['stale',None]]])
check('contract fixture 6', solve([{},[],N,N],), [N,[]])
check('contract fixture 7', solve([{'z':[True,{'name':'Z'}],'a':[True,{'name':'A'}]},[['z','name'],['a','name']],N,N],), [N,[['ok','Z'],['ok','A']]])
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 |
|---|---|---|---|
| contract fixture 1 | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | [1, [['ok', 'A1'], ['ok', None], ['ok', ''], ['ok', 'A1']]] | Passed |
| contract fixture 2 | [1, [['unsupported', None], ['unsupported', None]]] | [1, [['unsupported', None], ['unsupported', None]]] | Passed |
| contract fixture 3 | [1, [['gone', None], ['gone', None]]] | [1, [['gone', None], ['gone', None]]] | Passed |
| contract fixture 4 | [1, [['stale', None], ['stale', None]]] | [1, [['stale', None], ['stale', None]]] | Passed |
| contract fixture 5 | [1, [['stale', None]]] | [1, [['stale', None]]] | Passed |
| contract fixture 6 | [1, []] | [1, []] | Passed |
| contract fixture 7 | [1, [['ok', 'Z'], ['ok', 'A']]] | [1, [['ok', 'Z'], ['ok', 'A']]] | Passed |
SHA-256 / 648cdba9b1de295fe6afb170cb655067067abfa9d9367d15fa7efa9450647d53
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:50.421775+00:00.
Case digest / 1afa196b71957320281b472bedd8b5655360e7fe2b4272a0112e1ea4f71188fb