broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'read-confirmed', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'read-pending', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The open-preview event leaves a notification in read-confirmed instead of previewing.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'read-confirmed', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

meaning: Fixture-count band, not measured model difficulty

deps: stdlib

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'read-pending', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The close-preview event leaves a notification in read-confirmed instead of unread.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-confirmed', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'unread', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The mark-read event leaves a notification in read-confirmed instead of read-pending.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'unread', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'previewing', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The receipt-accepted event leaves a notification in unread instead of read-confirmed.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-confirmed', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'unread', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The receipt-rejected event leaves a notification in read-confirmed instead of read-error.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-confirmed', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

source:
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(initial, events, generation, payload=None, observe=None):
    table = {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'previewing', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}
    data = json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})) if payload is None else {**json.loads(json.dumps({'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'})), **json.loads(json.dumps(payload))}
    state = initial
    for delivery in events:
        event, event_generation = delivery[:2]
        arg = delivery[2] if len(delivery) > 2 else {}
        if event_generation == generation:
            previous = state
            if event in ('receipt-accepted','receipt-rejected','unread-accepted','unread-rejected') and arg.get('revision',data['revision']) != data['revision']: event = 'unknown-event'
            state = table.get((state, event), state)
            if state == 'read-confirmed':
                data['ack_revision'] = data['revision']
                data['unread_ids'] = [x for x in data['unread_ids'] if x != data['item']]
            if state == 'unread' and data['item'] not in data['unread_ids']: data['unread_ids'].append(data['item'])
    return {'phase': state, 'value': data[observe]} if observe else state
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('unread / open-preview', solve('unread', [('open-preview', N)], N), 'previewing')
check('previewing / close-preview', solve('previewing', [('close-preview', N)], N), 'unread')
check('previewing / mark-read', solve('previewing', [('mark-read', N)], N), 'read-pending')
check('read-pending / receipt-accepted', solve('read-pending', [('receipt-accepted', N)], N), 'read-confirmed')
check('read-pending / receipt-rejected', solve('read-pending', [('receipt-rejected', N)], N), 'read-error')
check('read-error / retry-receipt', solve('read-error', [('retry-receipt', N)], N), 'read-pending')
check('read-confirmed / mark-unread', solve('read-confirmed', [('mark-unread', N)], N), 'unread-pending')
check('unread-pending / unread-accepted', solve('unread-pending', [('unread-accepted', N)], N), 'unread')
check('unread-pending / unread-rejected', solve('unread-pending', [('unread-rejected', N)], N), 'unread-error')
check('unread-error / dismiss-error', solve('unread-error', [('dismiss-error', N)], N), 'read-confirmed')
check('older notification incarnation', solve('unread', [('open-preview', N - 1)], N), 'unread')
check('future notification incarnation', solve('unread', [('open-preview', N + 1)], N), 'unread')
check('unknown event is inert', solve('unread', [('unknown-event', N)], N), 'unread')
check('empty delivery batch', solve('unread', [], N), 'unread')
check('N stale deliveries before current delivery', solve('unread', [('open-preview', N - 1)] * N + [('open-preview', N)], N), 'previewing')
check('trace open-preview then close-preview', solve('unread', [('open-preview', N), ('close-preview', N)], N), 'unread')
check('trace open-preview then mark-read', solve('unread', [('open-preview', N), ('mark-read', N)], N), 'read-pending')
check('trace close-preview then open-preview', solve('previewing', [('close-preview', N), ('open-preview', N)], N), 'previewing')
check('trace mark-read then receipt-accepted', solve('previewing', [('mark-read', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace mark-read then receipt-rejected', solve('previewing', [('mark-read', N), ('receipt-rejected', N)], N), 'read-error')
check('trace receipt-accepted then mark-unread', solve('read-pending', [('receipt-accepted', N), ('mark-unread', N)], N), 'unread-pending')
check('trace receipt-rejected then retry-receipt', solve('read-pending', [('receipt-rejected', N), ('retry-receipt', N)], N), 'read-pending')
check('trace retry-receipt then receipt-accepted', solve('read-error', [('retry-receipt', N), ('receipt-accepted', N)], N), 'read-confirmed')
check('trace retry-receipt then receipt-rejected', solve('read-error', [('retry-receipt', N), ('receipt-rejected', N)], N), 'read-error')
check('trace mark-unread then unread-accepted', solve('read-confirmed', [('mark-unread', N), ('unread-accepted', N)], N), 'unread')
check('trace mark-unread then unread-rejected', solve('read-confirmed', [('mark-unread', N), ('unread-rejected', N)], N), 'unread-error')
check('trace unread-accepted then open-preview', solve('unread-pending', [('unread-accepted', N), ('open-preview', N)], N), 'previewing')
check('trace unread-rejected then dismiss-error', solve('unread-pending', [('unread-rejected', N), ('dismiss-error', N)], N), 'read-confirmed')
check('trace dismiss-error then mark-unread', solve('unread-error', [('dismiss-error', N), ('mark-unread', N)], N), 'unread-pending')
check('domain state regression 1: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 1})], N, {}, 'ack_revision'), {'phase': 'read-pending', 'value': 0})
check('domain state regression 2: ack_revision', solve('read-pending', [('receipt-accepted', N, {'revision': 2})], N, {}, 'ack_revision'), {'phase': 'read-confirmed', 'value': 2})
check('domain state regression 3: unread_ids', solve('read-pending', [('receipt-accepted', N, {})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
check('domain state regression 4: unread_ids', solve('unread-pending', [('unread-accepted', N, {})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread', 'value': ['other', 'n']})
check('domain state regression 5: unread_ids', solve('unread', [('open-preview', N, {})], N, {}, 'unread_ids'), {'phase': 'previewing', 'value': ['n', 'other']})
check('domain state regression 6: unread_ids', solve('unread-pending', [('unread-accepted', N, {'revision': 1})], N, {'unread_ids': ['other']}, 'unread_ids'), {'phase': 'unread-pending', 'value': ['other']})
check('domain state regression 7: unread_ids', solve('unread', [('open-preview', N, {}), ('mark-read', N, {}), ('receipt-accepted', N, {'revision': 1}), ('receipt-accepted', N, {'revision': 2})], N, {}, 'unread_ids'), {'phase': 'read-confirmed', 'value': ['other']})
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)

prompt:
The retry-receipt event leaves a notification in read-confirmed instead of read-pending.

Inbox read receipt rendering is a bounded visual-notification workflow with mutable policy state {'revision': 2, 'ack_revision': 0, 'unread_ids': ['n', 'other'], 'item': 'n'}. Its default transition relation is {('unread', 'open-preview'): 'previewing', ('previewing', 'close-preview'): 'unread', ('previewing', 'mark-read'): 'read-pending', ('read-pending', 'receipt-accepted'): 'read-confirmed', ('read-pending', 'receipt-rejected'): 'read-error', ('read-error', 'retry-receipt'): 'read-pending', ('read-confirmed', 'mark-unread'): 'unread-pending', ('unread-pending', 'unread-accepted'): 'unread', ('unread-pending', 'unread-rejected'): 'unread-error', ('unread-error', 'dismiss-error'): 'read-confirmed'}; domain inputs can suppress or redirect transitions and update policy fields, as specified in solve. Different-generation events are inert. Batches apply in order. Optional observe returns the selected policy field alongside the phase.

split: open-access