FAILURE MAP
← Case archive

FA-21646 / Assistive announcements / Open access

Stopped producer keeps current callback generation · case 01

The announcement trace violates the stated producer-readiness contract.

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

ROOT CAUSE

Fault site: elif e[0]=='stop': state='failed'; generation+=1; pending=[] is implemented as elif e[0]=='stop': state='failed'; pending=[]

VERIFIED REPAIR

Restore the stated transition: elif e[0]=='stop': state='failed'; generation+=1; pending=[]

Unsuccessful approach: The attempted repair substitutes elif e[0]=='stop': state='failed'; generation+=1 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'; 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 fixtureActualExpectedOutcome
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', 1, []][[], 'failed', 2, []]Failed
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 / 798e9cd5c971b35cd70faed520846b48d79b2dc5cbf8350346da1627bf1d67a0

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
        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 fixtureActualExpectedOutcome
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, ['deferred']][[], 'failed', 2, []]Failed
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 / eeb37c8604328a79326043c374fc48cdbf46ecbb96d6eca312f5b79eda89624e

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

Case digest / d70ade6fa982491ef89a2197bdbd171e5c7061e703ad33484d439754706964b8