FA-8731 / Assistive semantics / Open access
Progress indicator representation: Indeterminate progress is announced as zero completion · case 01
Indeterminate progress is announced as zero completion.
ROOT CAUSE
The indeterminate operation uses `if value is None: return {'role':'progressbar', 'label':label, 'busy':True, 'value':0}` where the contract requires `if value is None: return {'role':'progressbar', 'label':label, 'busy':True}`.
VERIFIED REPAIR
Implement the indeterminate operation as `if value is None: return {'role':'progressbar', 'label':label, 'busy':True}`.
Unsuccessful approach: Reporting not busy hides ongoing indeterminate work.
Case contract
Indeterminate indicators omit numeric value and are busy; determinate values clamp, percentages normalize the range, zero-span means complete, and busy reflects explicit state.
Why this case matters
A deterministic model of progress indicator representation; 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(value, minimum, maximum, label, busy):
if value is None: return {'role':'progressbar', 'label':label, 'busy':True, 'value':0}
value = max(minimum, min(value, maximum))
ratio = (value-minimum)/(maximum-minimum) if maximum > minimum else 1
return {'role':'progressbar', 'label':label, 'busy':busy, 'value':value, 'percent':round(ratio*100)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('indeterminate', solve(None, 0, 100, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True})
check('below', solve(-5, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 10, 'percent': 0})
check('above', solve(40, 10, 30, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 30, 'percent': 100})
check('offset', solve(20, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 20, 'percent': 50})
check('empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
check('parameterized progress range', solve(2*N,N,3*N,'Task',True), dict(role='progressbar',label='Task',busy=True,value=2*N,percent=50))
for repetition in range(N):
check('repeat empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
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 |
|---|---|---|---|
| indeterminate | {'busy': True, 'label': 'Upload', 'role': 'progressbar', 'value': 0} | {'busy': True, 'label': 'Upload', 'role': 'progressbar'} | Failed |
| below | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | Passed |
| above | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | Passed |
| offset | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | Passed |
| empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
| parameterized progress range | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | Passed |
| repeat empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
SHA-256 / f33237f0f3610712cc1eafa09ca4a087095578fc914b170e0f8d5837a64a7f54
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(value, minimum, maximum, label, busy):
if value is None: return {'role':'progressbar', 'label':label, 'busy':False}
value = max(minimum, min(value, maximum))
ratio = (value-minimum)/(maximum-minimum) if maximum > minimum else 1
return {'role':'progressbar', 'label':label, 'busy':busy, 'value':value, 'percent':round(ratio*100)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('indeterminate', solve(None, 0, 100, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True})
check('below', solve(-5, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 10, 'percent': 0})
check('above', solve(40, 10, 30, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 30, 'percent': 100})
check('offset', solve(20, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 20, 'percent': 50})
check('empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
check('parameterized progress range', solve(2*N,N,3*N,'Task',True), dict(role='progressbar',label='Task',busy=True,value=2*N,percent=50))
for repetition in range(N):
check('repeat empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
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 |
|---|---|---|---|
| indeterminate | {'busy': False, 'label': 'Upload', 'role': 'progressbar'} | {'busy': True, 'label': 'Upload', 'role': 'progressbar'} | Failed |
| below | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | Passed |
| above | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | Passed |
| offset | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | Passed |
| empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
| parameterized progress range | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | Passed |
| repeat empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
SHA-256 / bcedce4882e0ac15cba3a830f5365de0cb626be492485a4f999c110d607f5cfc
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(value, minimum, maximum, label, busy):
if value is None: return {'role':'progressbar', 'label':label, 'busy':True}
value = max(minimum, min(value, maximum))
ratio = (value-minimum)/(maximum-minimum) if maximum > minimum else 1
return {'role':'progressbar', 'label':label, 'busy':busy, 'value':value, 'percent':round(ratio*100)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('indeterminate', solve(None, 0, 100, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True})
check('below', solve(-5, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 10, 'percent': 0})
check('above', solve(40, 10, 30, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 30, 'percent': 100})
check('offset', solve(20, 10, 30, 'Upload', True), {'role': 'progressbar', 'label': 'Upload', 'busy': True, 'value': 20, 'percent': 50})
check('empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
check('parameterized progress range', solve(2*N,N,3*N,'Task',True), dict(role='progressbar',label='Task',busy=True,value=2*N,percent=50))
for repetition in range(N):
check('repeat empty range', solve(10, 10, 10, 'Upload', False), {'role': 'progressbar', 'label': 'Upload', 'busy': False, 'value': 10, 'percent': 100})
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 |
|---|---|---|---|
| indeterminate | {'busy': True, 'label': 'Upload', 'role': 'progressbar'} | {'busy': True, 'label': 'Upload', 'role': 'progressbar'} | Passed |
| below | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | {'busy': True, 'label': 'Upload', 'percent': 0, 'role': 'progressbar', 'value': 10} | Passed |
| above | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 30} | Passed |
| offset | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | {'busy': True, 'label': 'Upload', 'percent': 50, 'role': 'progressbar', 'value': 20} | Passed |
| empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
| parameterized progress range | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | {'busy': True, 'label': 'Task', 'percent': 50, 'role': 'progressbar', 'value': 2} | Passed |
| repeat empty range | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | {'busy': False, 'label': 'Upload', 'percent': 100, 'role': 'progressbar', 'value': 10} | Passed |
SHA-256 / 56d1db0e38e5408b333be054bfcc8baf39a216863a244e7db6dc8a2ee1cc10f7
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:23.831147+00:00.
Case digest / 7fbfcd2855b8df1b03d1cf79d8f5ed86be2d0a6e99c076e501f89b3cd8ca651a