FA-33316 / Menu interactions / Open access
Radial menu rounds near-edge hits into the next sector · case 01
Radial menu rounds near-edge hits into the next sector.
ROOT CAUSE
The radial-menu-hit model applies `round(p['angle']/(360/p['count']))` at its sector operation instead of the stipulated transformation.
VERIFIED REPAIR
Apply `int(p['angle']//(360/p['count']))` at sector.
Unsuccessful approach: The attempted repair `int(p['angle']//(360/p['count']))+1` still violates the sector oracle.
Case contract
A radial menu has half-open angular sectors, an inactive central disk and a bounded outer radius; only displayed command sectors are hittable.
Why this case matters
Cascading and context menus require coherent command and session state as content changes.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
if action == 'center':
return None if p['radius']<p['inner'] else 'ring'
if action == 'outer':
return p['radius']<=p['outer']
if action == 'angle':
return (p['degrees']-p['rotation'])%360
if action == 'sector':
return round(p['angle']/(360/p['count']))
if action == 'empty-sector':
return p['commands'][p['sector']] if p['sector']<len(p['commands']) else None
if action == 'gap':
return p['local']>=p['gap']/2 and p['local']<p['width']-p['gap']/2
return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('center contract', solve('center', {'radius':N,'inner':N+2}), None)
check('outer contract', solve('outer', {'radius':N+10,'outer':N+9}), False)
check('angle contract', solve('angle', {'degrees':N+30,'rotation':20}), N+10)
check('sector contract', solve('sector', {'angle':80+N,'count':4}), 0)
check('empty-sector contract', solve('empty-sector', {'commands':[N,N+1],'sector':3}), None)
check('gap contract', solve('gap', {'local':N/10,'gap':4,'width':90}), False)
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
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 |
|---|---|---|---|
| center contract | None | None | Passed |
| outer contract | False | False | Passed |
| angle contract | 11 | 11 | Passed |
| sector contract | 1 | 0 | Failed |
| empty-sector contract | None | None | Passed |
| gap contract | False | False | Passed |
| unknown operation | {'error': 'unsupported menu operation'} | {'error': 'unsupported menu operation'} | Passed |
SHA-256 / b567af01ace7250df3fddd41d3954530ae3de990225ff5b808e82fcc24126bc4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
if action == 'center':
return None if p['radius']<p['inner'] else 'ring'
if action == 'outer':
return p['radius']<=p['outer']
if action == 'angle':
return (p['degrees']-p['rotation'])%360
if action == 'sector':
return int(p['angle']//(360/p['count']))+1
if action == 'empty-sector':
return p['commands'][p['sector']] if p['sector']<len(p['commands']) else None
if action == 'gap':
return p['local']>=p['gap']/2 and p['local']<p['width']-p['gap']/2
return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('center contract', solve('center', {'radius':N,'inner':N+2}), None)
check('outer contract', solve('outer', {'radius':N+10,'outer':N+9}), False)
check('angle contract', solve('angle', {'degrees':N+30,'rotation':20}), N+10)
check('sector contract', solve('sector', {'angle':80+N,'count':4}), 0)
check('empty-sector contract', solve('empty-sector', {'commands':[N,N+1],'sector':3}), None)
check('gap contract', solve('gap', {'local':N/10,'gap':4,'width':90}), False)
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
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 |
|---|---|---|---|
| center contract | None | None | Passed |
| outer contract | False | False | Passed |
| angle contract | 11 | 11 | Passed |
| sector contract | 1 | 0 | Failed |
| empty-sector contract | None | None | Passed |
| gap contract | False | False | Passed |
| unknown operation | {'error': 'unsupported menu operation'} | {'error': 'unsupported menu operation'} | Passed |
SHA-256 / 2199443ed77134cf6e9ea76463ada23e6979c57bc7bde0e84242136c25b959a2
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
import math
import unicodedata
N = 1
observations = []
def solve(action, p):
if action == 'center':
return None if p['radius']<p['inner'] else 'ring'
if action == 'outer':
return p['radius']<=p['outer']
if action == 'angle':
return (p['degrees']-p['rotation'])%360
if action == 'sector':
return int(p['angle']//(360/p['count']))
if action == 'empty-sector':
return p['commands'][p['sector']] if p['sector']<len(p['commands']) else None
if action == 'gap':
return p['local']>=p['gap']/2 and p['local']<p['width']-p['gap']/2
return {'error': 'unsupported menu operation'}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('center contract', solve('center', {'radius':N,'inner':N+2}), None)
check('outer contract', solve('outer', {'radius':N+10,'outer':N+9}), False)
check('angle contract', solve('angle', {'degrees':N+30,'rotation':20}), N+10)
check('sector contract', solve('sector', {'angle':80+N,'count':4}), 0)
check('empty-sector contract', solve('empty-sector', {'commands':[N,N+1],'sector':3}), None)
check('gap contract', solve('gap', {'local':N/10,'gap':4,'width':90}), False)
check('unknown operation', solve('unknown', {}), {'error': 'unsupported menu operation'})
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 |
|---|---|---|---|
| center contract | None | None | Passed |
| outer contract | False | False | Passed |
| angle contract | 11 | 11 | Passed |
| sector contract | 0 | 0 | Passed |
| empty-sector contract | None | None | Passed |
| gap contract | False | False | Passed |
| unknown operation | {'error': 'unsupported menu operation'} | {'error': 'unsupported menu operation'} | Passed |
SHA-256 / 3c277bc3a44c873d7e4c62420912c9bd779b6a52d5dcad71e6abb24396bee9dd
Verification & scope
Offline supplied-valid-payload model; excludes DOM, keyboard, focus, selection, announcements and browser 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:42:21.192267+00:00.
Case digest / e9cdf4a60f31da08b4eb2a5736138d94d84ee2f8b3143c815ae39fcb89a4a0c0