FAILURE MAP
← Case archive

FA-20986 / Assistive announcements / Open access

Delivered event does not enter the receipt ledger · case 01

The announcement trace violates the stated listener-delivery contract.

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

ROOT CAUSE

Fault site: seen[ident].add(e[1]) return is implemented as seen[ident].add(e[2]) return

VERIFIED REPAIR

Restore the stated transition: seen[ident].add(e[1]) return

Unsuccessful approach: The attempted repair substitutes seen[ident].clear() return and still violates a regression oracle.

Case contract

Listeners register [id,language,mode] where mode speech or braille. Register replaces subscriptions and clears that listeners delivered IDs. Publish [event-id,text,language,target-mode] delivers to matching languages or wildcard and matching mode or both, at most once per listener/event. Remove deletes listener and receipt history. Mute excludes a listener without marking delivered. Unmute restores delivery. Report ordered [listener,event,text] and listener 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):
    listeners={}; seen={}; muted=set(); out=[]
    for e in events:
        if e[0]=='register':
            listeners[e[1]]=[e[2],e[3]]
            seen[e[1]]=set()
        elif e[0]=='remove': listeners.pop(e[1],None); seen.pop(e[1],None); muted.discard(e[1])
        elif e[0]=='mute': muted.add(e[1])
        elif e[0]=='unmute': muted.discard(e[1])
        elif e[0]=='publish':
            for ident,(lang,mode) in listeners.items():
                if ident in muted: continue
                if lang not in ('*',e[3]): continue
                if e[4] not in ('both',mode): continue
                if e[1] in seen[ident]: continue
                out.append([ident,e[1],e[2]])
                seen[ident].add(e[2])
    return [out,list(listeners),sorted(muted)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['register','s','en','speech'],['register','b','*','braille'],['publish','x','text'*N,'en','both'],['publish','x','text','en','both']]", "[['register','s','en','speech'],['publish','x','hello'*N,'en','speech'],['register','s','fr','speech'],['publish','x','bonjour','fr','speech']]", "[['register','a','*','speech'],['register','b','en','speech'],['mute','a'],['publish','x','hidden'*N,'en','both'],['unmute','a'],['publish','x','now','en','both']]", "[['register','a','en','speech'],['register','b','en','speech'],['mute','a'],['mute','b'],['publish','x','muted'*N,'en','both'],['unmute','a'],['publish','y','one'*N,'en','both'],['remove','b']]", "[['register','s','en','speech'],['register','b','en','braille'],['publish','x','hello'*N,'en','speech']]", "[['register','a','fr','speech'],['publish','x','hello'*N,'en','speech']]", '[]']
expected = {1: [[[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []], [[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'one']], ['a'], []], [[['s', 'x', 'hello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 2: [[[['s', 'x', 'texttext'], ['b', 'x', 'texttext']], ['s', 'b'], []], [[['s', 'x', 'hellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneone']], ['a'], []], [[['s', 'x', 'hellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 3: [[[['s', 'x', 'texttexttext'], ['b', 'x', 'texttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneone']], ['a'], []], [[['s', 'x', 'hellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 4: [[[['s', 'x', 'texttexttexttext'], ['b', 'x', 'texttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 5: [[[['s', 'x', 'texttexttexttexttext'], ['b', 'x', 'texttexttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]]}[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[[['s', 'x', 'text'], ['b', 'x', 'text'], ['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []][[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []]Failed
trace-2[[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []][[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []]Passed
trace-3[[['b', 'x', 'hidden'], ['a', 'x', 'now'], ['b', 'x', 'now']], ['a', 'b'], []][[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []]Failed
trace-4[[['a', 'y', 'one']], ['a'], []][[['a', 'y', 'one']], ['a'], []]Passed
trace-5[[['s', 'x', 'hello']], ['s', 'b'], []][[['s', 'x', 'hello']], ['s', 'b'], []]Passed
trace-6[[], ['a'], []][[], ['a'], []]Passed
trace-7[[], [], []][[], [], []]Passed

SHA-256 / 7f18f6bd7e71b1210ccbbd7a3108ae785d5de20b6c97bd0f823bfded8cf90d7b

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(events):
    listeners={}; seen={}; muted=set(); out=[]
    for e in events:
        if e[0]=='register':
            listeners[e[1]]=[e[2],e[3]]
            seen[e[1]]=set()
        elif e[0]=='remove': listeners.pop(e[1],None); seen.pop(e[1],None); muted.discard(e[1])
        elif e[0]=='mute': muted.add(e[1])
        elif e[0]=='unmute': muted.discard(e[1])
        elif e[0]=='publish':
            for ident,(lang,mode) in listeners.items():
                if ident in muted: continue
                if lang not in ('*',e[3]): continue
                if e[4] not in ('both',mode): continue
                if e[1] in seen[ident]: continue
                out.append([ident,e[1],e[2]])
                seen[ident].clear()
    return [out,list(listeners),sorted(muted)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['register','s','en','speech'],['register','b','*','braille'],['publish','x','text'*N,'en','both'],['publish','x','text','en','both']]", "[['register','s','en','speech'],['publish','x','hello'*N,'en','speech'],['register','s','fr','speech'],['publish','x','bonjour','fr','speech']]", "[['register','a','*','speech'],['register','b','en','speech'],['mute','a'],['publish','x','hidden'*N,'en','both'],['unmute','a'],['publish','x','now','en','both']]", "[['register','a','en','speech'],['register','b','en','speech'],['mute','a'],['mute','b'],['publish','x','muted'*N,'en','both'],['unmute','a'],['publish','y','one'*N,'en','both'],['remove','b']]", "[['register','s','en','speech'],['register','b','en','braille'],['publish','x','hello'*N,'en','speech']]", "[['register','a','fr','speech'],['publish','x','hello'*N,'en','speech']]", '[]']
expected = {1: [[[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []], [[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'one']], ['a'], []], [[['s', 'x', 'hello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 2: [[[['s', 'x', 'texttext'], ['b', 'x', 'texttext']], ['s', 'b'], []], [[['s', 'x', 'hellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneone']], ['a'], []], [[['s', 'x', 'hellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 3: [[[['s', 'x', 'texttexttext'], ['b', 'x', 'texttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneone']], ['a'], []], [[['s', 'x', 'hellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 4: [[[['s', 'x', 'texttexttexttext'], ['b', 'x', 'texttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 5: [[[['s', 'x', 'texttexttexttexttext'], ['b', 'x', 'texttexttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]]}[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[[['s', 'x', 'text'], ['b', 'x', 'text'], ['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []][[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []]Failed
trace-2[[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []][[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []]Passed
trace-3[[['b', 'x', 'hidden'], ['a', 'x', 'now'], ['b', 'x', 'now']], ['a', 'b'], []][[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []]Failed
trace-4[[['a', 'y', 'one']], ['a'], []][[['a', 'y', 'one']], ['a'], []]Passed
trace-5[[['s', 'x', 'hello']], ['s', 'b'], []][[['s', 'x', 'hello']], ['s', 'b'], []]Passed
trace-6[[], ['a'], []][[], ['a'], []]Passed
trace-7[[], [], []][[], [], []]Passed

SHA-256 / 785a55df6b2f76f83122c8220d786629a8f00847a25be93133983e86dad81a75

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(events):
    listeners={}; seen={}; muted=set(); out=[]
    for e in events:
        if e[0]=='register':
            listeners[e[1]]=[e[2],e[3]]
            seen[e[1]]=set()
        elif e[0]=='remove': listeners.pop(e[1],None); seen.pop(e[1],None); muted.discard(e[1])
        elif e[0]=='mute': muted.add(e[1])
        elif e[0]=='unmute': muted.discard(e[1])
        elif e[0]=='publish':
            for ident,(lang,mode) in listeners.items():
                if ident in muted: continue
                if lang not in ('*',e[3]): continue
                if e[4] not in ('both',mode): continue
                if e[1] in seen[ident]: continue
                out.append([ident,e[1],e[2]])
                seen[ident].add(e[1])
    return [out,list(listeners),sorted(muted)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['register','s','en','speech'],['register','b','*','braille'],['publish','x','text'*N,'en','both'],['publish','x','text','en','both']]", "[['register','s','en','speech'],['publish','x','hello'*N,'en','speech'],['register','s','fr','speech'],['publish','x','bonjour','fr','speech']]", "[['register','a','*','speech'],['register','b','en','speech'],['mute','a'],['publish','x','hidden'*N,'en','both'],['unmute','a'],['publish','x','now','en','both']]", "[['register','a','en','speech'],['register','b','en','speech'],['mute','a'],['mute','b'],['publish','x','muted'*N,'en','both'],['unmute','a'],['publish','y','one'*N,'en','both'],['remove','b']]", "[['register','s','en','speech'],['register','b','en','braille'],['publish','x','hello'*N,'en','speech']]", "[['register','a','fr','speech'],['publish','x','hello'*N,'en','speech']]", '[]']
expected = {1: [[[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []], [[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'one']], ['a'], []], [[['s', 'x', 'hello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 2: [[[['s', 'x', 'texttext'], ['b', 'x', 'texttext']], ['s', 'b'], []], [[['s', 'x', 'hellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneone']], ['a'], []], [[['s', 'x', 'hellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 3: [[[['s', 'x', 'texttexttext'], ['b', 'x', 'texttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneone']], ['a'], []], [[['s', 'x', 'hellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 4: [[[['s', 'x', 'texttexttexttext'], ['b', 'x', 'texttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]], 5: [[[['s', 'x', 'texttexttexttexttext'], ['b', 'x', 'texttexttexttexttext']], ['s', 'b'], []], [[['s', 'x', 'hellohellohellohellohello'], ['s', 'x', 'bonjour']], ['s'], []], [[['b', 'x', 'hiddenhiddenhiddenhiddenhidden'], ['a', 'x', 'now']], ['a', 'b'], []], [[['a', 'y', 'oneoneoneoneone']], ['a'], []], [[['s', 'x', 'hellohellohellohellohello']], ['s', 'b'], []], [[], ['a'], []], [[], [], []]]}[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[[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []][[['s', 'x', 'text'], ['b', 'x', 'text']], ['s', 'b'], []]Passed
trace-2[[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []][[['s', 'x', 'hello'], ['s', 'x', 'bonjour']], ['s'], []]Passed
trace-3[[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []][[['b', 'x', 'hidden'], ['a', 'x', 'now']], ['a', 'b'], []]Passed
trace-4[[['a', 'y', 'one']], ['a'], []][[['a', 'y', 'one']], ['a'], []]Passed
trace-5[[['s', 'x', 'hello']], ['s', 'b'], []][[['s', 'x', 'hello']], ['s', 'b'], []]Passed
trace-6[[], ['a'], []][[], ['a'], []]Passed
trace-7[[], [], []][[], [], []]Passed

SHA-256 / b8dcf5f169a7f0bb1cf02e4d44488935cad8ead94e38d9610258628976c35e0c

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

Case digest / ec116b6cc751b3eb06db742dc9a6e577e44825a4c8a61dbfaafdde31eacd877b