FAILURE MAP
← Case archive

FA-75101 / CRDT convergence / Open access

Epoch-resettable counter: a newer epoch is merged into pre-reset slots · case 01

Increments made before a reset reappear after the reset propagates.

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

ROOT CAUSE

On receiving a newer epoch the receiver keeps its old slots and merges the new ones in by maximum.

VERIFIED REPAIR

When the incoming epoch is newer, replace the local slots with the incoming slots and adopt the epoch.

Unsuccessful approach: Copying the slots without adopting the epoch lets a later merge from the old epoch overwrite them again.

Case contract

Each replica holds an epoch and grow-only slots for that epoch. ["inc", r, k] grows r's slot; ["reset", r] increments r's epoch and clears all its slots. ["sync", s, d]: if s's epoch is higher, d adopts s's epoch and a copy of s's slots; if equal, slots merge by maximum; if lower, nothing changes. Return values (sum of slots) and epochs.

Why this case matters

Reset-wins counters need an epoch so a reset is not undone by increments that were concurrent with it.

1 / The failure

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

N = 1
observations = []
def solve(events, replicas):
    E = {r: 0 for r in replicas}
    S = {r: {} for r in replicas}
    for ev in events:
        if ev[0] == 'inc':
            r = ev[1]
            S[r][r] = S[r].get(r, 0) + ev[2]
        elif ev[0] == 'reset':
            r = ev[1]
            E[r] += 1
            S[r] = {}
        else:
            s, d = ev[1], ev[2]
            if E[s] > E[d]:
                E[d] = E[s]
            if E[s] >= E[d]:
                for k, v in S[s].items():
                    S[d][k] = max(S[d].get(k, 0), v)
    return {'values': [sum(S[r].values()) for r in replicas], 'epochs': [E[r] for r in replicas]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('reset wins over concurrent older increments', [[['inc', 'a', 1], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 6], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 6, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 1], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 1], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 1], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    2: [('reset wins over concurrent older increments', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 7], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 7, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 2], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 2], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 2], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 2], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 2], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    3: [('reset wins over concurrent older increments', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 8], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 8, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 3], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 3], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 3], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 3], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 3], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    4: [('reset wins over concurrent older increments', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 9], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 9, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 4], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 4], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 4], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 4], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    5: [('reset wins over concurrent older increments', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 10], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 10, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 5], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 5], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 5], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 5], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 5], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
}[N]
for label, args, expected in cases:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
reset wins over concurrent older increments{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [0, 0, 0]}Failed
stale epoch is ignored{'epochs': [1, 0, 0], 'values': [3, 6, 0]}{'epochs': [1, 0, 0], 'values': [3, 6, 0]}Passed
equal epochs merge by maximum{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Passed
second reset opens a new epoch{'epochs': [2, 0, 2], 'values': [1, 0, 1]}{'epochs': [2, 0, 2], 'values': [1, 0, 1]}Passed
reset clears every slot{'epochs': [1, 0, 0], 'values': [1, 3, 0]}{'epochs': [1, 0, 0], 'values': [1, 3, 0]}Passed
independent resets reach the same epoch{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Passed
epoch adoption copies the newer slots{'epochs': [1, 1, 1], 'values': [2, 3, 3]}{'epochs': [1, 1, 1], 'values': [2, 2, 2]}Failed
epoch is local knowledge{'epochs': [2, 1, 0], 'values': [0, 1, 0]}{'epochs': [2, 1, 0], 'values': [0, 1, 0]}Passed

SHA-256 / e00262c9cd987440c40e64a4dcc5ada7ebc1aea6aa9e03121c658d481897581d

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(events, replicas):
    E = {r: 0 for r in replicas}
    S = {r: {} for r in replicas}
    for ev in events:
        if ev[0] == 'inc':
            r = ev[1]
            S[r][r] = S[r].get(r, 0) + ev[2]
        elif ev[0] == 'reset':
            r = ev[1]
            E[r] += 1
            S[r] = {}
        else:
            s, d = ev[1], ev[2]
            if E[s] > E[d]:
                S[d] = dict(S[s])
            elif E[s] == E[d]:
                for k, v in S[s].items():
                    S[d][k] = max(S[d].get(k, 0), v)
    return {'values': [sum(S[r].values()) for r in replicas], 'epochs': [E[r] for r in replicas]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('reset wins over concurrent older increments', [[['inc', 'a', 1], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 6], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 6, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 1], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 1], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 1], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    2: [('reset wins over concurrent older increments', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 7], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 7, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 2], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 2], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 2], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 2], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 2], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    3: [('reset wins over concurrent older increments', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 8], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 8, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 3], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 3], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 3], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 3], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 3], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    4: [('reset wins over concurrent older increments', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 9], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 9, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 4], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 4], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 4], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 4], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    5: [('reset wins over concurrent older increments', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 10], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 10, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 5], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 5], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 5], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 5], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 5], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
}[N]
for label, args, expected in cases:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
reset wins over concurrent older increments{'epochs': [1, 0, 0], 'values': [0, 0, 0]}{'epochs': [1, 1, 0], 'values': [0, 0, 0]}Failed
stale epoch is ignored{'epochs': [1, 0, 0], 'values': [3, 6, 0]}{'epochs': [1, 0, 0], 'values': [3, 6, 0]}Passed
equal epochs merge by maximum{'epochs': [1, 0, 0], 'values': [1, 1, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Failed
second reset opens a new epoch{'epochs': [0, 0, 2], 'values': [1, 0, 1]}{'epochs': [2, 0, 2], 'values': [1, 0, 1]}Failed
reset clears every slot{'epochs': [1, 0, 0], 'values': [1, 3, 0]}{'epochs': [1, 0, 0], 'values': [1, 3, 0]}Passed
independent resets reach the same epoch{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Passed
epoch adoption copies the newer slots{'epochs': [1, 0, 0], 'values': [2, 2, 2]}{'epochs': [1, 1, 1], 'values': [2, 2, 2]}Failed
epoch is local knowledge{'epochs': [2, 1, 0], 'values': [0, 1, 0]}{'epochs': [2, 1, 0], 'values': [0, 1, 0]}Passed

SHA-256 / e68f72f0e98479892c5305bebc97de11c9d9b1a18f3940b8be2c13e6372661df

3 / The verified repair

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

N = 1
observations = []
def solve(events, replicas):
    E = {r: 0 for r in replicas}
    S = {r: {} for r in replicas}
    for ev in events:
        if ev[0] == 'inc':
            r = ev[1]
            S[r][r] = S[r].get(r, 0) + ev[2]
        elif ev[0] == 'reset':
            r = ev[1]
            E[r] += 1
            S[r] = {}
        else:
            s, d = ev[1], ev[2]
            if E[s] > E[d]:
                E[d] = E[s]
                S[d] = dict(S[s])
            elif E[s] == E[d]:
                for k, v in S[s].items():
                    S[d][k] = max(S[d].get(k, 0), v)
    return {'values': [sum(S[r].values()) for r in replicas], 'epochs': [E[r] for r in replicas]}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = {
    1: [('reset wins over concurrent older increments', [[['inc', 'a', 1], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 6], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 6, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 1], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 1], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 3, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 1], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    2: [('reset wins over concurrent older increments', [[['inc', 'a', 2], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 7], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 7, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 2], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 2], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 2], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 2], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [4, 4, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 2], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    3: [('reset wins over concurrent older increments', [[['inc', 'a', 3], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 8], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 8, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 3], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 3], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 3], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 3], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [5, 5, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 3], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    4: [('reset wins over concurrent older increments', [[['inc', 'a', 4], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 9], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 9, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 4], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 4], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 4], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [6, 6, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 4], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
    5: [('reset wins over concurrent older increments', [[['inc', 'a', 5], ['sync', 'a', 'b'], ['inc', 'b', 2], ['reset', 'a'], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [0, 0, 0], 'epochs': [1, 1, 0]}), ('stale epoch is ignored', [[['reset', 'a'], ['inc', 'a', 3], ['inc', 'b', 10], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [3, 10, 0], 'epochs': [1, 0, 0]}), ('equal epochs merge by maximum', [[['reset', 'a'], ['sync', 'a', 'b'], ['inc', 'a', 5], ['inc', 'b', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('second reset opens a new epoch', [[['inc', 'c', 4], ['reset', 'c'], ['inc', 'c', 5], ['reset', 'c'], ['inc', 'c', 1], ['sync', 'c', 'a']], ['a', 'b', 'c']], {'values': [1, 0, 1], 'epochs': [2, 0, 2]}), ('reset clears every slot', [[['inc', 'a', 5], ['inc', 'b', 3], ['sync', 'b', 'a'], ['reset', 'a'], ['inc', 'a', 1]], ['a', 'b', 'c']], {'values': [1, 3, 0], 'epochs': [1, 0, 0]}), ('independent resets reach the same epoch', [[['inc', 'a', 1], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 5], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'a']], ['a', 'b', 'c']], {'values': [7, 7, 0], 'epochs': [1, 1, 0]}), ('epoch adoption copies the newer slots', [[['inc', 'b', 5], ['reset', 'a'], ['inc', 'a', 2], ['sync', 'a', 'b'], ['sync', 'b', 'c']], ['a', 'b', 'c']], {'values': [2, 2, 2], 'epochs': [1, 1, 1]}), ('epoch is local knowledge', [[['reset', 'a'], ['reset', 'a'], ['reset', 'b'], ['inc', 'b', 1]], ['a', 'b', 'c']], {'values': [0, 1, 0], 'epochs': [2, 1, 0]})],
}[N]
for label, args, expected in cases:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
reset wins over concurrent older increments{'epochs': [1, 1, 0], 'values': [0, 0, 0]}{'epochs': [1, 1, 0], 'values': [0, 0, 0]}Passed
stale epoch is ignored{'epochs': [1, 0, 0], 'values': [3, 6, 0]}{'epochs': [1, 0, 0], 'values': [3, 6, 0]}Passed
equal epochs merge by maximum{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Passed
second reset opens a new epoch{'epochs': [2, 0, 2], 'values': [1, 0, 1]}{'epochs': [2, 0, 2], 'values': [1, 0, 1]}Passed
reset clears every slot{'epochs': [1, 0, 0], 'values': [1, 3, 0]}{'epochs': [1, 0, 0], 'values': [1, 3, 0]}Passed
independent resets reach the same epoch{'epochs': [1, 1, 0], 'values': [3, 3, 0]}{'epochs': [1, 1, 0], 'values': [3, 3, 0]}Passed
epoch adoption copies the newer slots{'epochs': [1, 1, 1], 'values': [2, 2, 2]}{'epochs': [1, 1, 1], 'values': [2, 2, 2]}Passed
epoch is local knowledge{'epochs': [2, 1, 0], 'values': [0, 1, 0]}{'epochs': [2, 1, 0], 'values': [0, 1, 0]}Passed

SHA-256 / ecd333b789518dff63ea8e8295f64877fe9fe6bca5d85ccf5e8c517456034405

Verification & scope

A deterministic, bounded teaching model of one replicated data type with stipulated operation and merge rules; it is not a production CRDT library and makes no claim of conformance to any specific published design. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:49:03.006697+00:00.

Case digest / 02030ab74af9c4132b62b663b587a1c8f973b9d47a7143a1e275d7592fb2c710