FA-8386 / Tree accessibility / Open access
Tree keyboard expansion: Right-arrow on an expanded parent focuses its last child · case 01
Right-arrow on an expanded parent focuses its last child.
ROOT CAUSE
The enter child operation uses `node = kids[-1]` where the contract requires `node = kids[0]`.
VERIFIED REPAIR
Implement the enter child operation as `node = kids[0]`.
Unsuccessful approach: Keeping focus on the parent prevents descending.
Case contract
Right expands then enters the first child; Left collapses only the current branch or focuses its parent; roots retain focus; collapse-all clears every expansion.
Why this case matters
A deterministic model of tree keyboard expansion; this isolates one interface invariant without requiring a browser.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(node, expanded, parents, children, key):
expanded = set(expanded)
kids = children.get(node, [])
if key == 'Right' and kids:
if node not in expanded: expanded.add(node)
else: node = kids[-1]
elif key == 'Left':
if node in expanded: expanded.remove(node)
else: node = parents.get(node, node)
elif key == 'CollapseAll': expanded.clear()
return (node, sorted(expanded))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('expand', solve('a', ['z'], {}, {'a':['b','c']}, 'Right'), ('a', ['a', 'z']))
check('descend', solve('a', ['a'], {}, {'a':['b','c']}, 'Right'), ('b', ['a']))
check('collapse', solve('a', ['a','z'], {}, {'a':['b']}, 'Left'), ('a', ['z']))
check('parent', solve('b', [], {'b':'a'}, {}, 'Left'), ('a', []))
check('root', solve('a', [], {}, {}, 'Left'), ('a', []))
check('all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('a', []))
check('parameterized child count', solve('a', [], {}, {'a':list(range(N))}, 'Right'), ('a',['a']))
for repetition in range(N):
check('repeat all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('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 |
|---|---|---|---|
| expand | ['a', ['a', 'z']] | ['a', ['a', 'z']] | Passed |
| descend | ['c', ['a']] | ['b', ['a']] | Failed |
| collapse | ['a', ['z']] | ['a', ['z']] | Passed |
| parent | ['a', []] | ['a', []] | Passed |
| root | ['a', []] | ['a', []] | Passed |
| all | ['a', []] | ['a', []] | Passed |
| parameterized child count | ['a', ['a']] | ['a', ['a']] | Passed |
| repeat all | ['a', []] | ['a', []] | Passed |
SHA-256 / de7ea0a2f1e28f9157d9c7228f1705fa7ca0d9c60f71ee1f30400a4114a1cae8
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(node, expanded, parents, children, key):
expanded = set(expanded)
kids = children.get(node, [])
if key == 'Right' and kids:
if node not in expanded: expanded.add(node)
else: node = node
elif key == 'Left':
if node in expanded: expanded.remove(node)
else: node = parents.get(node, node)
elif key == 'CollapseAll': expanded.clear()
return (node, sorted(expanded))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('expand', solve('a', ['z'], {}, {'a':['b','c']}, 'Right'), ('a', ['a', 'z']))
check('descend', solve('a', ['a'], {}, {'a':['b','c']}, 'Right'), ('b', ['a']))
check('collapse', solve('a', ['a','z'], {}, {'a':['b']}, 'Left'), ('a', ['z']))
check('parent', solve('b', [], {'b':'a'}, {}, 'Left'), ('a', []))
check('root', solve('a', [], {}, {}, 'Left'), ('a', []))
check('all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('a', []))
check('parameterized child count', solve('a', [], {}, {'a':list(range(N))}, 'Right'), ('a',['a']))
for repetition in range(N):
check('repeat all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('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 |
|---|---|---|---|
| expand | ['a', ['a', 'z']] | ['a', ['a', 'z']] | Passed |
| descend | ['a', ['a']] | ['b', ['a']] | Failed |
| collapse | ['a', ['z']] | ['a', ['z']] | Passed |
| parent | ['a', []] | ['a', []] | Passed |
| root | ['a', []] | ['a', []] | Passed |
| all | ['a', []] | ['a', []] | Passed |
| parameterized child count | ['a', ['a']] | ['a', ['a']] | Passed |
| repeat all | ['a', []] | ['a', []] | Passed |
SHA-256 / 277676f442897ee21b03a98f0afce6b45e150238f6764f5ae43f29c27618d357
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(node, expanded, parents, children, key):
expanded = set(expanded)
kids = children.get(node, [])
if key == 'Right' and kids:
if node not in expanded: expanded.add(node)
else: node = kids[0]
elif key == 'Left':
if node in expanded: expanded.remove(node)
else: node = parents.get(node, node)
elif key == 'CollapseAll': expanded.clear()
return (node, sorted(expanded))
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('expand', solve('a', ['z'], {}, {'a':['b','c']}, 'Right'), ('a', ['a', 'z']))
check('descend', solve('a', ['a'], {}, {'a':['b','c']}, 'Right'), ('b', ['a']))
check('collapse', solve('a', ['a','z'], {}, {'a':['b']}, 'Left'), ('a', ['z']))
check('parent', solve('b', [], {'b':'a'}, {}, 'Left'), ('a', []))
check('root', solve('a', [], {}, {}, 'Left'), ('a', []))
check('all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('a', []))
check('parameterized child count', solve('a', [], {}, {'a':list(range(N))}, 'Right'), ('a',['a']))
for repetition in range(N):
check('repeat all', solve('a', ['a','z'], {}, {}, 'CollapseAll'), ('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 |
|---|---|---|---|
| expand | ['a', ['a', 'z']] | ['a', ['a', 'z']] | Passed |
| descend | ['b', ['a']] | ['b', ['a']] | Passed |
| collapse | ['a', ['z']] | ['a', ['z']] | Passed |
| parent | ['a', []] | ['a', []] | Passed |
| root | ['a', []] | ['a', []] | Passed |
| all | ['a', []] | ['a', []] | Passed |
| parameterized child count | ['a', ['a']] | ['a', ['a']] | Passed |
| repeat all | ['a', []] | ['a', []] | Passed |
SHA-256 / d8cc0e4d8b47f71a93b2eb97d9a27e6666808598de5a935b5c45db1e6e515900
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:20.858710+00:00.
Case digest / 9b95adf83f8a5aa49aa2d924e12deb16b4ad4e502b1fc8d40314ef40169609b6