FA-8401 / Tree accessibility / Open access
Tree keyboard expansion: Collapse-all leaves unrelated expanded branches open · case 01
Collapse-all leaves unrelated expanded branches open.
ROOT CAUSE
The collapse all operation uses `elif key == 'CollapseAll': expanded.discard(node)` where the contract requires `elif key == 'CollapseAll': expanded.clear()`.
VERIFIED REPAIR
Implement the collapse all operation as `elif key == 'CollapseAll': expanded.clear()`.
Unsuccessful approach: Adding the current node opens a branch instead of closing all.
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[0]
elif key == 'Left':
if node in expanded: expanded.remove(node)
else: node = parents.get(node, node)
elif key == 'CollapseAll': expanded.discard(node)
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', ['z']] | ['a', []] | Failed |
| parameterized child count | ['a', ['a']] | ['a', ['a']] | Passed |
| repeat all | ['a', ['z']] | ['a', []] | Failed |
SHA-256 / 1bf6133744ea5663a6eca333c6a7e4d1442251c0100efe1f2759a80c46c902e8
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 = kids[0]
elif key == 'Left':
if node in expanded: expanded.remove(node)
else: node = parents.get(node, node)
elif key == 'CollapseAll': expanded.add(node)
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', 'z']] | ['a', []] | Failed |
| parameterized child count | ['a', ['a']] | ['a', ['a']] | Passed |
| repeat all | ['a', ['a', 'z']] | ['a', []] | Failed |
SHA-256 / 01acf5e6a11aba2c5b5a8379de52fe51ee5c8fbe59c9c407bdb308eefe7de09b
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:21.061370+00:00.
Case digest / 9da93dd1b8899f19ff07289d0aa56e678267fc21310b7c13d49db73cee277d97