FAILURE MAP
← Case archive

FA-21546 / Assistive announcements / Open access

Unavailable voice remains selectable · case 01

The announcement trace violates the stated voice-negotiation contract.

Verified by executionVariant 1 · 7 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Fault site: elif e[0]=='remove': disabled.add(e[1]) is implemented as elif e[0]=='remove': pass

VERIFIED REPAIR

Restore the stated transition: elif e[0]=='remove': disabled.add(e[1])

Unsuccessful approach: The attempted repair substitutes elif e[0]=='remove': disabled.update(voices) 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': pass
        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 fixtureActualExpectedOutcome
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[['a', 'a'], ['a', 'b'], []][['b', 'b'], ['a', 'b'], ['a']]Failed
trace-6[['remote', None, None], ['remote'], []][['remote', None, None], ['remote'], []]Passed
trace-7[[None], [], []][[None], [], []]Passed

SHA-256 / 6762a0ce4ce0015969a59b807f0bbebd288ab8b05d2e640598de921e7c412705

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.update(voices)
        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 fixtureActualExpectedOutcome
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[[None, 'b'], ['a', 'b'], ['a']][['b', 'b'], ['a', 'b'], ['a']]Failed
trace-6[['remote', None, None], ['remote'], []][['remote', None, None], ['remote'], []]Passed
trace-7[[None], [], []][[None], [], []]Passed

SHA-256 / ae2e96df13638aa72f78cd9733232ae1947c920900f7498d5059d763355cdf95

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 fixtureActualExpectedOutcome
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:29.839773+00:00.

Case digest / 97a7dfb6547936d2a9acf6d1c0756f3ef9c17e660b4f11ad23771370f02383e9