FA-21136 / Assistive announcements / Open access
One-use consent permits repeated speech · case 01
The announcement trace violates the stated confirmation-gate contract.
ROOT CAUSE
Fault site: grants.pop(e[1],None) return is implemented as pass return
VERIFIED REPAIR
Restore the stated transition: grants.pop(e[1],None) return
Unsuccessful approach: The attempted repair substitutes grants.clear() return and still violates a regression oracle.
Case contract
Sensitive announcements require a one-use consent token bound to message ID and text revision. Draft replaces text and increments revision. Grant captures current revision. Speak requires current matching consent, emits text and consumes consent. Revoke removes consent; delete removes draft and consent. Nonsensitive preview emits only fixed redacted cue without consuming consent. Expire removes all grants but preserves drafts. Return speech and remaining grant/draft revisions.
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):
drafts={}; grants={}; out=[]
for e in events:
if e[0]=='draft': drafts[e[1]]=[drafts.get(e[1],[0,''])[0]+1,e[2]]
elif e[0]=='grant' and e[1] in drafts: grants[e[1]]=drafts[e[1]][0]
elif e[0]=='revoke': grants.pop(e[1],None)
elif e[0]=='delete': drafts.pop(e[1],None); grants.pop(e[1],None)
elif e[0]=='expire': grants.clear()
elif e[0]=='preview' and e[1] in drafts: out.append('private announcement available')
elif e[0]=='speak':
if e[1] not in drafts: continue
if grants.get(e[1])!=drafts[e[1]][0]: continue
out.append(drafts[e[1]][1])
pass
return [out,sorted(grants.items()),[[k,v[0]] for k,v in drafts.items()]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['draft','a','secret'*N],['grant','a'],['speak','a'],['speak','a']]", "[['draft','a','old'],['grant','a'],['draft','a','new'*N],['speak','a'],['grant','a'],['speak','a']]", "[['draft','a','secret'*N],['draft','b','other'],['grant','a'],['grant','b'],['revoke','a'],['speak','b']]", "[['draft','a','secret'*N],['grant','a'],['preview','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['delete','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['expire'],['speak','a']]", "[['speak','missing']]", "[['draft','a','a'*N],['draft','b','b'],['grant','a'],['grant','b'],['speak','a']]"]
expected = {1: [[['secret'], [], [['a', 1]]], [['new'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['a'], [('b', 1)], [['a', 1], ['b', 1]]]], 2: [[['secretsecret'], [], [['a', 1]]], [['newnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aa'], [('b', 1)], [['a', 1], ['b', 1]]]], 3: [[['secretsecretsecret'], [], [['a', 1]]], [['newnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 4: [[['secretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 5: [[['secretsecretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaaa'], [('b', 1)], [['a', 1], ['b', 1]]]]}[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 | [['secret', 'secret'], [['a', 1]], [['a', 1]]] | [['secret'], [], [['a', 1]]] | Failed |
| trace-2 | [['new'], [['a', 2]], [['a', 2]]] | [['new'], [], [['a', 2]]] | Failed |
| trace-3 | [['other'], [['b', 1]], [['a', 1], ['b', 1]]] | [['other'], [], [['a', 1], ['b', 1]]] | Failed |
| trace-4 | [['private announcement available', 'secret'], [['a', 1]], [['a', 1]]] | [['private announcement available', 'secret'], [], [['a', 1]]] | Failed |
| trace-5 | [[], [], []] | [[], [], []] | Passed |
| trace-6 | [[], [], [['a', 1]]] | [[], [], [['a', 1]]] | Passed |
| trace-7 | [[], [], []] | [[], [], []] | Passed |
| trace-8 | [['a'], [['a', 1], ['b', 1]], [['a', 1], ['b', 1]]] | [['a'], [['b', 1]], [['a', 1], ['b', 1]]] | Failed |
SHA-256 / 6683a6a35d51a75e5fc0b81520a6abbc29e8f67b4b0b62d55b130b73255613ff
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
drafts={}; grants={}; out=[]
for e in events:
if e[0]=='draft': drafts[e[1]]=[drafts.get(e[1],[0,''])[0]+1,e[2]]
elif e[0]=='grant' and e[1] in drafts: grants[e[1]]=drafts[e[1]][0]
elif e[0]=='revoke': grants.pop(e[1],None)
elif e[0]=='delete': drafts.pop(e[1],None); grants.pop(e[1],None)
elif e[0]=='expire': grants.clear()
elif e[0]=='preview' and e[1] in drafts: out.append('private announcement available')
elif e[0]=='speak':
if e[1] not in drafts: continue
if grants.get(e[1])!=drafts[e[1]][0]: continue
out.append(drafts[e[1]][1])
grants.clear()
return [out,sorted(grants.items()),[[k,v[0]] for k,v in drafts.items()]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['draft','a','secret'*N],['grant','a'],['speak','a'],['speak','a']]", "[['draft','a','old'],['grant','a'],['draft','a','new'*N],['speak','a'],['grant','a'],['speak','a']]", "[['draft','a','secret'*N],['draft','b','other'],['grant','a'],['grant','b'],['revoke','a'],['speak','b']]", "[['draft','a','secret'*N],['grant','a'],['preview','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['delete','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['expire'],['speak','a']]", "[['speak','missing']]", "[['draft','a','a'*N],['draft','b','b'],['grant','a'],['grant','b'],['speak','a']]"]
expected = {1: [[['secret'], [], [['a', 1]]], [['new'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['a'], [('b', 1)], [['a', 1], ['b', 1]]]], 2: [[['secretsecret'], [], [['a', 1]]], [['newnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aa'], [('b', 1)], [['a', 1], ['b', 1]]]], 3: [[['secretsecretsecret'], [], [['a', 1]]], [['newnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 4: [[['secretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 5: [[['secretsecretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaaa'], [('b', 1)], [['a', 1], ['b', 1]]]]}[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 | [['secret'], [], [['a', 1]]] | [['secret'], [], [['a', 1]]] | Passed |
| trace-2 | [['new'], [], [['a', 2]]] | [['new'], [], [['a', 2]]] | Passed |
| trace-3 | [['other'], [], [['a', 1], ['b', 1]]] | [['other'], [], [['a', 1], ['b', 1]]] | Passed |
| trace-4 | [['private announcement available', 'secret'], [], [['a', 1]]] | [['private announcement available', 'secret'], [], [['a', 1]]] | Passed |
| trace-5 | [[], [], []] | [[], [], []] | Passed |
| trace-6 | [[], [], [['a', 1]]] | [[], [], [['a', 1]]] | Passed |
| trace-7 | [[], [], []] | [[], [], []] | Passed |
| trace-8 | [['a'], [], [['a', 1], ['b', 1]]] | [['a'], [['b', 1]], [['a', 1], ['b', 1]]] | Failed |
SHA-256 / 3d0a31262e9a1202c40ec3a54b83e2c7011e80f8286d4b67d1c54dc35aeef1de
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(events):
drafts={}; grants={}; out=[]
for e in events:
if e[0]=='draft': drafts[e[1]]=[drafts.get(e[1],[0,''])[0]+1,e[2]]
elif e[0]=='grant' and e[1] in drafts: grants[e[1]]=drafts[e[1]][0]
elif e[0]=='revoke': grants.pop(e[1],None)
elif e[0]=='delete': drafts.pop(e[1],None); grants.pop(e[1],None)
elif e[0]=='expire': grants.clear()
elif e[0]=='preview' and e[1] in drafts: out.append('private announcement available')
elif e[0]=='speak':
if e[1] not in drafts: continue
if grants.get(e[1])!=drafts[e[1]][0]: continue
out.append(drafts[e[1]][1])
grants.pop(e[1],None)
return [out,sorted(grants.items()),[[k,v[0]] for k,v in drafts.items()]]
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = ["[['draft','a','secret'*N],['grant','a'],['speak','a'],['speak','a']]", "[['draft','a','old'],['grant','a'],['draft','a','new'*N],['speak','a'],['grant','a'],['speak','a']]", "[['draft','a','secret'*N],['draft','b','other'],['grant','a'],['grant','b'],['revoke','a'],['speak','b']]", "[['draft','a','secret'*N],['grant','a'],['preview','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['delete','a'],['speak','a']]", "[['draft','a','secret'*N],['grant','a'],['expire'],['speak','a']]", "[['speak','missing']]", "[['draft','a','a'*N],['draft','b','b'],['grant','a'],['grant','b'],['speak','a']]"]
expected = {1: [[['secret'], [], [['a', 1]]], [['new'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['a'], [('b', 1)], [['a', 1], ['b', 1]]]], 2: [[['secretsecret'], [], [['a', 1]]], [['newnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aa'], [('b', 1)], [['a', 1], ['b', 1]]]], 3: [[['secretsecretsecret'], [], [['a', 1]]], [['newnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 4: [[['secretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaa'], [('b', 1)], [['a', 1], ['b', 1]]]], 5: [[['secretsecretsecretsecretsecret'], [], [['a', 1]]], [['newnewnewnewnew'], [], [['a', 2]]], [['other'], [], [['a', 1], ['b', 1]]], [['private announcement available', 'secretsecretsecretsecretsecret'], [], [['a', 1]]], [[], [], []], [[], [], [['a', 1]]], [[], [], []], [['aaaaa'], [('b', 1)], [['a', 1], ['b', 1]]]]}[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 | [['secret'], [], [['a', 1]]] | [['secret'], [], [['a', 1]]] | Passed |
| trace-2 | [['new'], [], [['a', 2]]] | [['new'], [], [['a', 2]]] | Passed |
| trace-3 | [['other'], [], [['a', 1], ['b', 1]]] | [['other'], [], [['a', 1], ['b', 1]]] | Passed |
| trace-4 | [['private announcement available', 'secret'], [], [['a', 1]]] | [['private announcement available', 'secret'], [], [['a', 1]]] | Passed |
| trace-5 | [[], [], []] | [[], [], []] | Passed |
| trace-6 | [[], [], [['a', 1]]] | [[], [], [['a', 1]]] | Passed |
| trace-7 | [[], [], []] | [[], [], []] | Passed |
| trace-8 | [['a'], [['b', 1]], [['a', 1], ['b', 1]]] | [['a'], [['b', 1]], [['a', 1], ['b', 1]]] | Passed |
SHA-256 / 65dcfa94088a4b077d65c157fa3bf0ff8d2f6c61aeba16d9fc18dce9ecf8d1da
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:25.659850+00:00.
Case digest / 475f69e52d2ab05488524f22ee4fb9d0a6a219c80c90a3091a785e45c0ee1e03