FA-21566 / Assistive announcements / Open access
Unrelated voice language enters fallback candidates · case 01
The announcement trace violates the stated voice-negotiation contract.
ROOT CAUSE
Fault site: rows=[v for v in rows if v[1]==lang or v[1].split('-')[0]==lang.split('-')[0] or v[1]=='en'] is implemented as rows=list(rows)
VERIFIED REPAIR
Restore the stated transition: rows=[v for v in rows if v[1]==lang or v[1].split('-')[0]==lang.split('-')[0] or v[1]=='en']
Unsuccessful approach: The attempted repair substitutes rows=[v for v in rows if v[1]==lang or v[1]=='en'] and still violates a regression oracle.
Case contract
Voice inventory rows are [id,language,local,quality,features]. Request [language,offline,required-features,preferred-id]. Selection excludes unavailable or missing-feature voices, honors exact preferred only among eligible, then ranks exact language before base-language before en fallback, local before remote, higher quality, then lexical ID. Add replaces same ID; remove marks unavailable; enable restores it. Return selected IDs or None, inventory IDs and disabled IDs.
Why this case matters
Deterministic controlled model of assistive announcement delivery.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
voices={}; disabled=set(); out=[]
for e in events:
if e[0]=='add': voices[e[1]]=e[1:]
elif e[0]=='remove': disabled.add(e[1])
elif e[0]=='enable': disabled.discard(e[1])
elif e[0]=='request':
lang,offline,required,preferred=e[1:]
rows=[v for k,v in voices.items() if k not in disabled]
rows=[v for v in rows if not offline or v[2]]
rows=[v for v in rows if set(required)<=set(v[4])]
rows=list(rows)
if not rows: out.append(None); continue
def rank(v):
language_rank=0 if v[1]==lang else (1 if v[1].split('-')[0]==lang.split('-')[0] else 2)
return (v[0]!=preferred,language_rank,not v[2],-v[3],v[0])
out.append(min(rows,key=rank)[0])
return [out,list(voices),sorted(disabled)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','a','en',True,1,['marks']],['add','b','en',True,N+5,['marks','spell']],['request','en',True,['marks'],None]]", "[['add','a','fr',False,9,['marks']],['add','b','fr',True,1,['marks']],['request','fr',False,[],None],['request','fr',True,[],None],['request','fr',False,[],'a']]", "[['add','z','fr-CA',True,1,[]],['add','a','fr',True,9,[]],['add','e','en',True,1,[]],['request','fr-CA',False,[],None],['request','fr-BE',False,[],None],['request','fr-CA',False,[],'e']]", "[['add','a','en',True,9,['marks']],['add','b','en',True,2,['marks','spell','pause']],['request','en',True,['marks','spell'],None],['add','a','en',True,10,['marks','spell']],['request','en',True,['spell'],None]]", "[['add','a','en',True,N+5,[]],['add','b','en',True,1,[]],['remove','a'],['request','en',False,[],None],['remove','b'],['enable','b'],['request','en',False,[],None]]", "[['add','remote','ja',False,N,[]],['request','ja',False,[],None],['request','ja',True,[],None],['request','de',False,[],'remote']]", "[['request','en',True,[],None]]"]
expected = {1: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 2: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 3: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 4: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 5: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]]}[N]
for i, expression in enumerate(fixtures):
check("trace-"+str(i+1), solve(eval(expression)), expected[i])
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 |
|---|---|---|---|
| trace-1 | [['b'], ['a', 'b'], []] | [['b'], ['a', 'b'], []] | Passed |
| trace-2 | [['b', 'b', 'a'], ['a', 'b'], []] | [['b', 'b', 'a'], ['a', 'b'], []] | Passed |
| trace-3 | [['z', 'a', 'e'], ['z', 'a', 'e'], []] | [['z', 'a', 'e'], ['z', 'a', 'e'], []] | Passed |
| trace-4 | [['b', 'a'], ['a', 'b'], []] | [['b', 'a'], ['a', 'b'], []] | Passed |
| trace-5 | [['b', 'b'], ['a', 'b'], ['a']] | [['b', 'b'], ['a', 'b'], ['a']] | Passed |
| trace-6 | [['remote', None, 'remote'], ['remote'], []] | [['remote', None, None], ['remote'], []] | Failed |
| trace-7 | [[None], [], []] | [[None], [], []] | Passed |
SHA-256 / 0e9d4e900f49b9aef362d01ab78ae396c9b7d596096e8a9f9bd87af7d94d2574
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
voices={}; disabled=set(); out=[]
for e in events:
if e[0]=='add': voices[e[1]]=e[1:]
elif e[0]=='remove': disabled.add(e[1])
elif e[0]=='enable': disabled.discard(e[1])
elif e[0]=='request':
lang,offline,required,preferred=e[1:]
rows=[v for k,v in voices.items() if k not in disabled]
rows=[v for v in rows if not offline or v[2]]
rows=[v for v in rows if set(required)<=set(v[4])]
rows=[v for v in rows if v[1]==lang or v[1]=='en']
if not rows: out.append(None); continue
def rank(v):
language_rank=0 if v[1]==lang else (1 if v[1].split('-')[0]==lang.split('-')[0] else 2)
return (v[0]!=preferred,language_rank,not v[2],-v[3],v[0])
out.append(min(rows,key=rank)[0])
return [out,list(voices),sorted(disabled)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','a','en',True,1,['marks']],['add','b','en',True,N+5,['marks','spell']],['request','en',True,['marks'],None]]", "[['add','a','fr',False,9,['marks']],['add','b','fr',True,1,['marks']],['request','fr',False,[],None],['request','fr',True,[],None],['request','fr',False,[],'a']]", "[['add','z','fr-CA',True,1,[]],['add','a','fr',True,9,[]],['add','e','en',True,1,[]],['request','fr-CA',False,[],None],['request','fr-BE',False,[],None],['request','fr-CA',False,[],'e']]", "[['add','a','en',True,9,['marks']],['add','b','en',True,2,['marks','spell','pause']],['request','en',True,['marks','spell'],None],['add','a','en',True,10,['marks','spell']],['request','en',True,['spell'],None]]", "[['add','a','en',True,N+5,[]],['add','b','en',True,1,[]],['remove','a'],['request','en',False,[],None],['remove','b'],['enable','b'],['request','en',False,[],None]]", "[['add','remote','ja',False,N,[]],['request','ja',False,[],None],['request','ja',True,[],None],['request','de',False,[],'remote']]", "[['request','en',True,[],None]]"]
expected = {1: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 2: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 3: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 4: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 5: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]]}[N]
for i, expression in enumerate(fixtures):
check("trace-"+str(i+1), solve(eval(expression)), expected[i])
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 |
|---|---|---|---|
| trace-1 | [['b'], ['a', 'b'], []] | [['b'], ['a', 'b'], []] | Passed |
| trace-2 | [['b', 'b', 'a'], ['a', 'b'], []] | [['b', 'b', 'a'], ['a', 'b'], []] | Passed |
| trace-3 | [['z', 'e', 'e'], ['z', 'a', 'e'], []] | [['z', 'a', 'e'], ['z', 'a', 'e'], []] | Failed |
| trace-4 | [['b', 'a'], ['a', 'b'], []] | [['b', 'a'], ['a', 'b'], []] | Passed |
| trace-5 | [['b', 'b'], ['a', 'b'], ['a']] | [['b', 'b'], ['a', 'b'], ['a']] | Passed |
| trace-6 | [['remote', None, None], ['remote'], []] | [['remote', None, None], ['remote'], []] | Passed |
| trace-7 | [[None], [], []] | [[None], [], []] | Passed |
SHA-256 / a4db479915b85dcdc90888f82a1a75108c9676fe13c0ccf1180861831de1f157
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
voices={}; disabled=set(); out=[]
for e in events:
if e[0]=='add': voices[e[1]]=e[1:]
elif e[0]=='remove': disabled.add(e[1])
elif e[0]=='enable': disabled.discard(e[1])
elif e[0]=='request':
lang,offline,required,preferred=e[1:]
rows=[v for k,v in voices.items() if k not in disabled]
rows=[v for v in rows if not offline or v[2]]
rows=[v for v in rows if set(required)<=set(v[4])]
rows=[v for v in rows if v[1]==lang or v[1].split('-')[0]==lang.split('-')[0] or v[1]=='en']
if not rows: out.append(None); continue
def rank(v):
language_rank=0 if v[1]==lang else (1 if v[1].split('-')[0]==lang.split('-')[0] else 2)
return (v[0]!=preferred,language_rank,not v[2],-v[3],v[0])
out.append(min(rows,key=rank)[0])
return [out,list(voices),sorted(disabled)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','a','en',True,1,['marks']],['add','b','en',True,N+5,['marks','spell']],['request','en',True,['marks'],None]]", "[['add','a','fr',False,9,['marks']],['add','b','fr',True,1,['marks']],['request','fr',False,[],None],['request','fr',True,[],None],['request','fr',False,[],'a']]", "[['add','z','fr-CA',True,1,[]],['add','a','fr',True,9,[]],['add','e','en',True,1,[]],['request','fr-CA',False,[],None],['request','fr-BE',False,[],None],['request','fr-CA',False,[],'e']]", "[['add','a','en',True,9,['marks']],['add','b','en',True,2,['marks','spell','pause']],['request','en',True,['marks','spell'],None],['add','a','en',True,10,['marks','spell']],['request','en',True,['spell'],None]]", "[['add','a','en',True,N+5,[]],['add','b','en',True,1,[]],['remove','a'],['request','en',False,[],None],['remove','b'],['enable','b'],['request','en',False,[],None]]", "[['add','remote','ja',False,N,[]],['request','ja',False,[],None],['request','ja',True,[],None],['request','de',False,[],'remote']]", "[['request','en',True,[],None]]"]
expected = {1: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 2: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 3: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 4: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]], 5: [[['b'], ['a', 'b'], []], [['b', 'b', 'a'], ['a', 'b'], []], [['z', 'a', 'e'], ['z', 'a', 'e'], []], [['b', 'a'], ['a', 'b'], []], [['b', 'b'], ['a', 'b'], ['a']], [['remote', None, None], ['remote'], []], [[None], [], []]]}[N]
for i, expression in enumerate(fixtures):
check("trace-"+str(i+1), solve(eval(expression)), expected[i])
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 |
|---|---|---|---|
| trace-1 | [['b'], ['a', 'b'], []] | [['b'], ['a', 'b'], []] | Passed |
| trace-2 | [['b', 'b', 'a'], ['a', 'b'], []] | [['b', 'b', 'a'], ['a', 'b'], []] | Passed |
| trace-3 | [['z', 'a', 'e'], ['z', 'a', 'e'], []] | [['z', 'a', 'e'], ['z', 'a', 'e'], []] | Passed |
| trace-4 | [['b', 'a'], ['a', 'b'], []] | [['b', 'a'], ['a', 'b'], []] | Passed |
| trace-5 | [['b', 'b'], ['a', 'b'], ['a']] | [['b', 'b'], ['a', 'b'], ['a']] | Passed |
| trace-6 | [['remote', None, None], ['remote'], []] | [['remote', None, None], ['remote'], []] | Passed |
| trace-7 | [[None], [], []] | [[None], [], []] | Passed |
SHA-256 / 106057a0e719a31ce229386466b4b3f9f445e738eecdb6b0f6987d30a031c506
Verification & scope
Stipulated bounded policy, not a browser, speech engine, platform API, or standards conformance claim. 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:40:30.017166+00:00.
Case digest / bbdc2e7fe30c84b11bde01cc078dadc9c15326c7aa44ecffc181d638c0fa235e