FA-21521 / Assistive announcements / Open access
Successful handoff retains a stale target for later commits · case 01
The announcement trace violates the stated device-handoff contract.
ROOT CAUSE
Fault site: target=None elif e[0]=='remove': is implemented as pass elif e[0]=='remove':
VERIFIED REPAIR
Restore the stated transition: target=None elif e[0]=='remove':
Unsuccessful approach: The attempted repair substitutes target=old elif e[0]=='remove': and still violates a regression oracle.
Case contract
Output routes start at local device. Queue snapshots requested route and utterance text. Begin-handoff sets a target while retaining current route. Commit switches current route and migrates only pending items on old route; cancel-handoff leaves queue unchanged. Device removal drops queued output to that device and chooses local if current removed. Send requires route available and sends one queued item; unavailable items remain. Add makes device available. Return [device,text] output and pending routes.
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):
current='local'; target=None; devices={'local'}; q=[]; out=[]
for e in events:
if e[0]=='add': devices.add(e[1])
elif e[0]=='queue': q.append([current,e[1]])
elif e[0]=='begin': target=e[1]
elif e[0]=='cancel': target=None
elif e[0]=='commit' and target in devices:
old=current; current=target
q=[[current if route==old else route,text] for route,text in q]
pass
elif e[0]=='remove':
devices.discard(e[1])
q=[x for x in q if x[0]!=e[1]]
if current==e[1]: current='local'
elif e[0]=='send' and q:
index=next((i for i,x in enumerate(q) if x[0] in devices),None)
if index is not None: out.append(q.pop(index))
return [out,q,current,target,sorted(devices)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','Headset'],['queue','hello'*N],['begin','Headset'],['queue','before'],['commit'],['queue','after'],['send']]", "[['queue','keep'*N],['begin','missing'],['commit']]", "[['queue','keep'*N],['begin','remote'],['queue','during'*N],['cancel'],['send']]", "[['add','head'],['begin','head'],['commit'],['queue','remote'*N],['remove','head']]", "[['add','head'],['begin','head'],['commit'],['queue','keep'*N],['remove','unused']]", "[['add','remote'],['queue','local'*N],['remove','remote'],['send']]", '[]']
expected = {1: [[[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keep']], 'local', 'missing', ['local']], [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keep']], 'head', None, ['head', 'local']], [[['local', 'local']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 2: [[[['Headset', 'hellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeep']], [['local', 'duringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 3: [[[['Headset', 'hellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeep']], [['local', 'duringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 4: [[[['Headset', 'hellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeep']], [['local', 'duringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 5: [[[['Headset', 'hellohellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeepkeep']], [['local', 'duringduringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]]}[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 | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', 'Headset', ['Headset', 'local']] | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']] | Failed |
| trace-2 | [[], [['local', 'keep']], 'local', 'missing', ['local']] | [[], [['local', 'keep']], 'local', 'missing', ['local']] | Passed |
| trace-3 | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | Passed |
| trace-4 | [[], [], 'local', 'head', ['local']] | [[], [], 'local', None, ['local']] | Failed |
| trace-5 | [[], [['head', 'keep']], 'head', 'head', ['head', 'local']] | [[], [['head', 'keep']], 'head', None, ['head', 'local']] | Failed |
| trace-6 | [[['local', 'local']], [], 'local', None, ['local']] | [[['local', 'local']], [], 'local', None, ['local']] | Passed |
| trace-7 | [[], [], 'local', None, ['local']] | [[], [], 'local', None, ['local']] | Passed |
SHA-256 / 3b7770edce053ae09bb2706b90c44a0f88f15259f23b6a537bf66a47ebc555ff
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
current='local'; target=None; devices={'local'}; q=[]; out=[]
for e in events:
if e[0]=='add': devices.add(e[1])
elif e[0]=='queue': q.append([current,e[1]])
elif e[0]=='begin': target=e[1]
elif e[0]=='cancel': target=None
elif e[0]=='commit' and target in devices:
old=current; current=target
q=[[current if route==old else route,text] for route,text in q]
target=old
elif e[0]=='remove':
devices.discard(e[1])
q=[x for x in q if x[0]!=e[1]]
if current==e[1]: current='local'
elif e[0]=='send' and q:
index=next((i for i,x in enumerate(q) if x[0] in devices),None)
if index is not None: out.append(q.pop(index))
return [out,q,current,target,sorted(devices)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','Headset'],['queue','hello'*N],['begin','Headset'],['queue','before'],['commit'],['queue','after'],['send']]", "[['queue','keep'*N],['begin','missing'],['commit']]", "[['queue','keep'*N],['begin','remote'],['queue','during'*N],['cancel'],['send']]", "[['add','head'],['begin','head'],['commit'],['queue','remote'*N],['remove','head']]", "[['add','head'],['begin','head'],['commit'],['queue','keep'*N],['remove','unused']]", "[['add','remote'],['queue','local'*N],['remove','remote'],['send']]", '[]']
expected = {1: [[[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keep']], 'local', 'missing', ['local']], [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keep']], 'head', None, ['head', 'local']], [[['local', 'local']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 2: [[[['Headset', 'hellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeep']], [['local', 'duringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 3: [[[['Headset', 'hellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeep']], [['local', 'duringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 4: [[[['Headset', 'hellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeep']], [['local', 'duringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 5: [[[['Headset', 'hellohellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeepkeep']], [['local', 'duringduringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]]}[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 | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', 'local', ['Headset', 'local']] | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']] | Failed |
| trace-2 | [[], [['local', 'keep']], 'local', 'missing', ['local']] | [[], [['local', 'keep']], 'local', 'missing', ['local']] | Passed |
| trace-3 | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | Passed |
| trace-4 | [[], [], 'local', 'local', ['local']] | [[], [], 'local', None, ['local']] | Failed |
| trace-5 | [[], [['head', 'keep']], 'head', 'local', ['head', 'local']] | [[], [['head', 'keep']], 'head', None, ['head', 'local']] | Failed |
| trace-6 | [[['local', 'local']], [], 'local', None, ['local']] | [[['local', 'local']], [], 'local', None, ['local']] | Passed |
| trace-7 | [[], [], 'local', None, ['local']] | [[], [], 'local', None, ['local']] | Passed |
SHA-256 / ac146de0628fc1f6b56fb5cfbd3539d0b557cd761ed4f0ef5acf7a3c2aecabed
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
current='local'; target=None; devices={'local'}; q=[]; out=[]
for e in events:
if e[0]=='add': devices.add(e[1])
elif e[0]=='queue': q.append([current,e[1]])
elif e[0]=='begin': target=e[1]
elif e[0]=='cancel': target=None
elif e[0]=='commit' and target in devices:
old=current; current=target
q=[[current if route==old else route,text] for route,text in q]
target=None
elif e[0]=='remove':
devices.discard(e[1])
q=[x for x in q if x[0]!=e[1]]
if current==e[1]: current='local'
elif e[0]=='send' and q:
index=next((i for i,x in enumerate(q) if x[0] in devices),None)
if index is not None: out.append(q.pop(index))
return [out,q,current,target,sorted(devices)]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['add','Headset'],['queue','hello'*N],['begin','Headset'],['queue','before'],['commit'],['queue','after'],['send']]", "[['queue','keep'*N],['begin','missing'],['commit']]", "[['queue','keep'*N],['begin','remote'],['queue','during'*N],['cancel'],['send']]", "[['add','head'],['begin','head'],['commit'],['queue','remote'*N],['remove','head']]", "[['add','head'],['begin','head'],['commit'],['queue','keep'*N],['remove','unused']]", "[['add','remote'],['queue','local'*N],['remove','remote'],['send']]", '[]']
expected = {1: [[[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keep']], 'local', 'missing', ['local']], [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keep']], 'head', None, ['head', 'local']], [[['local', 'local']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 2: [[[['Headset', 'hellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeep']], [['local', 'duringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 3: [[[['Headset', 'hellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeep']], [['local', 'duringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 4: [[[['Headset', 'hellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeep']], [['local', 'duringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]], 5: [[[['Headset', 'hellohellohellohellohello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']], [[], [['local', 'keepkeepkeepkeepkeep']], 'local', 'missing', ['local']], [[['local', 'keepkeepkeepkeepkeep']], [['local', 'duringduringduringduringduring']], 'local', None, ['local']], [[], [], 'local', None, ['local']], [[], [['head', 'keepkeepkeepkeepkeep']], 'head', None, ['head', 'local']], [[['local', 'locallocallocallocallocal']], [], 'local', None, ['local']], [[], [], 'local', None, ['local']]]}[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 | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']] | [[['Headset', 'hello']], [['Headset', 'before'], ['Headset', 'after']], 'Headset', None, ['Headset', 'local']] | Passed |
| trace-2 | [[], [['local', 'keep']], 'local', 'missing', ['local']] | [[], [['local', 'keep']], 'local', 'missing', ['local']] | Passed |
| trace-3 | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | [[['local', 'keep']], [['local', 'during']], 'local', None, ['local']] | Passed |
| trace-4 | [[], [], 'local', None, ['local']] | [[], [], 'local', None, ['local']] | Passed |
| trace-5 | [[], [['head', 'keep']], 'head', None, ['head', 'local']] | [[], [['head', 'keep']], 'head', None, ['head', 'local']] | Passed |
| trace-6 | [[['local', 'local']], [], 'local', None, ['local']] | [[['local', 'local']], [], 'local', None, ['local']] | Passed |
| trace-7 | [[], [], 'local', None, ['local']] | [[], [], 'local', None, ['local']] | Passed |
SHA-256 / 0f629dda7fbbc8588a75fbc148c0b0edd2dc5d28ac23e4234d16e0e58ef87579
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.574841+00:00.
Case digest / fcc9f3d9980d78526cead4f2b2c29802da2082720526608a88c2b80c4e56f352