FA-21671 / Assistive announcements / Open access
Ready callback drains but leaves producer booting · case 01
The announcement trace violates the stated producer-readiness contract.
ROOT CAUSE
Fault site: state='ready' out.extend is implemented as state='booting' out.extend
VERIFIED REPAIR
Restore the stated transition: state='ready' out.extend
Unsuccessful approach: The attempted repair substitutes state='failed' out.extend and still violates a regression oracle.
Case contract
Announcement producer has booting/ready/failed state and generation. Start increments generation, enters booting, clears deferred messages. Publish during booting queues; ready publishes directly; failed drops. Ready callback must match generation, drains queued messages FIFO, and is ignored after failure. Fail matching generation clears deferred and announces unavailable once. Retry is a start. Stop fails silently and advances generation. Report speech,state,generation,deferred.
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):
state='failed'; generation=0; pending=[]; out=[]
for e in events:
if e[0] in ('start','retry'):
generation+=1; state='booting'; pending=[]
elif e[0]=='stop': state='failed'; generation+=1; pending=[]
elif e[0]=='publish':
if state=='booting': pending.append(e[1])
elif state=='ready': out.append(e[1])
elif e[0] in ('ready','fail'):
if e[1]!=generation: continue
if state!='booting': continue
if e[0]=='ready':
state='booting'
out.extend(pending)
pending.clear()
else:
state='failed'; pending.clear(); out.append('unavailable')
return [out,state,generation,pending]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['start'],['publish','first'*N],['publish','second'],['ready',1],['publish','third']]", "[['start'],['publish','old'],['retry'],['publish','new'*N],['ready',1]]", "[['start'],['publish','deferred'*N],['fail',1],['ready',1],['publish','should-drop']]", "[['start'],['publish','deferred'*N],['stop'],['ready',1]]", "[['start'],['fail',1],['fail',1],['retry'],['publish','retry'*N],['ready',2]]", "[['publish','dropped'*N],['ready',0]]", '[]']
expected = {1: [[['first', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['new']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 2: [[['firstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 3: [[['firstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 4: [[['firstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 5: [[['firstfirstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]]}[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 | [['first', 'second'], 'booting', 1, ['third']] | [['first', 'second', 'third'], 'ready', 1, []] | Failed |
| trace-2 | [[], 'booting', 2, ['new']] | [[], 'booting', 2, ['new']] | Passed |
| trace-3 | [['unavailable'], 'failed', 1, []] | [['unavailable'], 'failed', 1, []] | Passed |
| trace-4 | [[], 'failed', 2, []] | [[], 'failed', 2, []] | Passed |
| trace-5 | [['unavailable', 'retry'], 'booting', 2, []] | [['unavailable', 'retry'], 'ready', 2, []] | Failed |
| trace-6 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
| trace-7 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
SHA-256 / 36d14fdf0c35db53f35abd339c1e7e50976148a53ee53e90ea3195b41f4aa460
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
state='failed'; generation=0; pending=[]; out=[]
for e in events:
if e[0] in ('start','retry'):
generation+=1; state='booting'; pending=[]
elif e[0]=='stop': state='failed'; generation+=1; pending=[]
elif e[0]=='publish':
if state=='booting': pending.append(e[1])
elif state=='ready': out.append(e[1])
elif e[0] in ('ready','fail'):
if e[1]!=generation: continue
if state!='booting': continue
if e[0]=='ready':
state='failed'
out.extend(pending)
pending.clear()
else:
state='failed'; pending.clear(); out.append('unavailable')
return [out,state,generation,pending]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['start'],['publish','first'*N],['publish','second'],['ready',1],['publish','third']]", "[['start'],['publish','old'],['retry'],['publish','new'*N],['ready',1]]", "[['start'],['publish','deferred'*N],['fail',1],['ready',1],['publish','should-drop']]", "[['start'],['publish','deferred'*N],['stop'],['ready',1]]", "[['start'],['fail',1],['fail',1],['retry'],['publish','retry'*N],['ready',2]]", "[['publish','dropped'*N],['ready',0]]", '[]']
expected = {1: [[['first', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['new']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 2: [[['firstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 3: [[['firstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 4: [[['firstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 5: [[['firstfirstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]]}[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 | [['first', 'second'], 'failed', 1, []] | [['first', 'second', 'third'], 'ready', 1, []] | Failed |
| trace-2 | [[], 'booting', 2, ['new']] | [[], 'booting', 2, ['new']] | Passed |
| trace-3 | [['unavailable'], 'failed', 1, []] | [['unavailable'], 'failed', 1, []] | Passed |
| trace-4 | [[], 'failed', 2, []] | [[], 'failed', 2, []] | Passed |
| trace-5 | [['unavailable', 'retry'], 'failed', 2, []] | [['unavailable', 'retry'], 'ready', 2, []] | Failed |
| trace-6 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
| trace-7 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
SHA-256 / 2ef93f04bc926fc65d5f91ecf5df77cbaa25afac34e804be492631b7bf0e218e
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
state='failed'; generation=0; pending=[]; out=[]
for e in events:
if e[0] in ('start','retry'):
generation+=1; state='booting'; pending=[]
elif e[0]=='stop': state='failed'; generation+=1; pending=[]
elif e[0]=='publish':
if state=='booting': pending.append(e[1])
elif state=='ready': out.append(e[1])
elif e[0] in ('ready','fail'):
if e[1]!=generation: continue
if state!='booting': continue
if e[0]=='ready':
state='ready'
out.extend(pending)
pending.clear()
else:
state='failed'; pending.clear(); out.append('unavailable')
return [out,state,generation,pending]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['start'],['publish','first'*N],['publish','second'],['ready',1],['publish','third']]", "[['start'],['publish','old'],['retry'],['publish','new'*N],['ready',1]]", "[['start'],['publish','deferred'*N],['fail',1],['ready',1],['publish','should-drop']]", "[['start'],['publish','deferred'*N],['stop'],['ready',1]]", "[['start'],['fail',1],['fail',1],['retry'],['publish','retry'*N],['ready',2]]", "[['publish','dropped'*N],['ready',0]]", '[]']
expected = {1: [[['first', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['new']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 2: [[['firstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 3: [[['firstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 4: [[['firstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]], 5: [[['firstfirstfirstfirstfirst', 'second', 'third'], 'ready', 1, []], [[], 'booting', 2, ['newnewnewnewnew']], [['unavailable'], 'failed', 1, []], [[], 'failed', 2, []], [['unavailable', 'retryretryretryretryretry'], 'ready', 2, []], [[], 'failed', 0, []], [[], 'failed', 0, []]]}[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 | [['first', 'second', 'third'], 'ready', 1, []] | [['first', 'second', 'third'], 'ready', 1, []] | Passed |
| trace-2 | [[], 'booting', 2, ['new']] | [[], 'booting', 2, ['new']] | Passed |
| trace-3 | [['unavailable'], 'failed', 1, []] | [['unavailable'], 'failed', 1, []] | Passed |
| trace-4 | [[], 'failed', 2, []] | [[], 'failed', 2, []] | Passed |
| trace-5 | [['unavailable', 'retry'], 'ready', 2, []] | [['unavailable', 'retry'], 'ready', 2, []] | Passed |
| trace-6 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
| trace-7 | [[], 'failed', 0, []] | [[], 'failed', 0, []] | Passed |
SHA-256 / f52c75e4328c7260e45f1f37a25998915ef45e21adbd89a998ab5a99263e9daa
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:31.109607+00:00.
Case digest / 128a6ca41553f20f20b4b058c2f3f4e30ebe747df90218bd1c12ca0aed24cd0b