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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'expanded', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'collapsed', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 children-fail event leaves a notification in expanded instead of load-error.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'expanded', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'empty', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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-expand event leaves a notification in expanded instead of loading.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapsed', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'expanded', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 collapse-during-load event leaves a notification in collapsed instead of collapse-pending.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'expanded', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'empty', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 children-arrive event leaves a notification in expanded instead of collapsed.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'collapsed', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'loading', ('empty', 'first-child-added'): 'collapsed'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 last-child-removed event leaves a notification in collapsed instead of empty.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'expanded'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 = {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'loading'}
    data = json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})) if payload is None else {**json.loads(json.dumps({'children': ['a', 'b'], 'request': 3, 'wanted_open': False})), **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 ('children-arrive','children-fail') and arg.get('request',data['request']) != data['request']: event = 'unknown-event'
            if event in ('expand','uncached-expand','retry-expand'): data['wanted_open'] = True
            if event in ('collapse','collapse-during-load'): data['wanted_open'] = False
            if event == 'children-arrive' and 'children' in arg: data['children'] = list(dict.fromkeys(arg['children']))
            if event == 'last-child-removed': data['children'] = []
            if event == 'first-child-added': data['children'] = [arg.get('child','new')]
            state = table.get((state, event), state)
            if state == 'expanded': data['wanted_open'] = True
            if state in ('collapsed','empty'): data['wanted_open'] = False
    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('collapsed / expand', solve('collapsed', [('expand', N)], N), 'expanded')
check('expanded / collapse', solve('expanded', [('collapse', N)], N), 'collapsed')
check('collapsed / uncached-expand', solve('collapsed', [('uncached-expand', N)], N), 'loading')
check('loading / children-arrive', solve('loading', [('children-arrive', N)], N), 'expanded')
check('loading / children-fail', solve('loading', [('children-fail', N)], N), 'load-error')
check('load-error / retry-expand', solve('load-error', [('retry-expand', N)], N), 'loading')
check('loading / collapse-during-load', solve('loading', [('collapse-during-load', N)], N), 'collapse-pending')
check('collapse-pending / children-arrive', solve('collapse-pending', [('children-arrive', N)], N), 'collapsed')
check('expanded / last-child-removed', solve('expanded', [('last-child-removed', N)], N), 'empty')
check('empty / first-child-added', solve('empty', [('first-child-added', N)], N), 'collapsed')
check('older notification incarnation', solve('collapsed', [('expand', N - 1)], N), 'collapsed')
check('future notification incarnation', solve('collapsed', [('expand', N + 1)], N), 'collapsed')
check('unknown event is inert', solve('collapsed', [('unknown-event', N)], N), 'collapsed')
check('empty delivery batch', solve('collapsed', [], N), 'collapsed')
check('N stale deliveries before current delivery', solve('collapsed', [('expand', N - 1)] * N + [('expand', N)], N), 'expanded')
check('trace expand then collapse', solve('collapsed', [('expand', N), ('collapse', N)], N), 'collapsed')
check('trace expand then last-child-removed', solve('collapsed', [('expand', N), ('last-child-removed', N)], N), 'empty')
check('trace collapse then expand', solve('expanded', [('collapse', N), ('expand', N)], N), 'expanded')
check('trace collapse then uncached-expand', solve('expanded', [('collapse', N), ('uncached-expand', N)], N), 'loading')
check('trace uncached-expand then children-arrive', solve('collapsed', [('uncached-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace uncached-expand then children-fail', solve('collapsed', [('uncached-expand', N), ('children-fail', N)], N), 'load-error')
check('trace uncached-expand then collapse-during-load', solve('collapsed', [('uncached-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace children-arrive then collapse', solve('loading', [('children-arrive', N), ('collapse', N)], N), 'collapsed')
check('trace children-arrive then last-child-removed', solve('loading', [('children-arrive', N), ('last-child-removed', N)], N), 'empty')
check('trace children-fail then retry-expand', solve('loading', [('children-fail', N), ('retry-expand', N)], N), 'loading')
check('trace retry-expand then children-arrive', solve('load-error', [('retry-expand', N), ('children-arrive', N)], N), 'expanded')
check('trace retry-expand then children-fail', solve('load-error', [('retry-expand', N), ('children-fail', N)], N), 'load-error')
check('trace retry-expand then collapse-during-load', solve('load-error', [('retry-expand', N), ('collapse-during-load', N)], N), 'collapse-pending')
check('trace collapse-during-load then children-arrive', solve('loading', [('collapse-during-load', N), ('children-arrive', N)], N), 'collapsed')
check('trace children-arrive then expand', solve('collapse-pending', [('children-arrive', N), ('expand', N)], N), 'expanded')
check('trace children-arrive then uncached-expand', solve('collapse-pending', [('children-arrive', N), ('uncached-expand', N)], N), 'loading')
check('trace last-child-removed then first-child-added', solve('expanded', [('last-child-removed', N), ('first-child-added', N)], N), 'collapsed')
check('trace first-child-added then expand', solve('empty', [('first-child-added', N), ('expand', N)], N), 'expanded')
check('trace first-child-added then uncached-expand', solve('empty', [('first-child-added', N), ('uncached-expand', N)], N), 'loading')
check('domain state regression 1: children', solve('loading', [('children-arrive', N, {'request': 2, 'children': ['old']})], N, {}, 'children'), {'phase': 'loading', 'value': ['a', 'b']})
check('domain state regression 2: children', solve('loading', [('children-arrive', N, {'children': ['x', 'x', 'y']})], N, {}, 'children'), {'phase': 'expanded', 'value': ['x', 'y']})
check('domain state regression 3: wanted_open', solve('collapse-pending', [('children-arrive', N, {'children': ['x']})], N, {}, 'wanted_open'), {'phase': 'collapsed', 'value': False})
check('domain state regression 4: children', solve('expanded', [('last-child-removed', N, {})], N, {}, 'children'), {'phase': 'empty', 'value': []})
check('domain state regression 5: children', solve('empty', [('first-child-added', N, {'child': 'z'})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['z']})
check('domain state regression 6: children', solve('expanded', [('collapse', N, {})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['a', 'b']})
check('domain state regression 7: children', solve('collapsed', [('uncached-expand', N, {}), ('collapse-during-load', N, {}), ('children-arrive', N, {'children': ['x', 'y']})], N, {}, 'children'), {'phase': 'collapsed', 'value': ['x', 'y']})
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 first-child-added event leaves a notification in expanded instead of collapsed.

Grouped notification interaction is a bounded visual-notification workflow with mutable policy state {'children': ['a', 'b'], 'request': 3, 'wanted_open': False}. Its default transition relation is {('collapsed', 'expand'): 'expanded', ('expanded', 'collapse'): 'collapsed', ('collapsed', 'uncached-expand'): 'loading', ('loading', 'children-arrive'): 'expanded', ('loading', 'children-fail'): 'load-error', ('load-error', 'retry-expand'): 'loading', ('loading', 'collapse-during-load'): 'collapse-pending', ('collapse-pending', 'children-arrive'): 'collapsed', ('expanded', 'last-child-removed'): 'empty', ('empty', 'first-child-added'): 'collapsed'}; 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