FA-75861 / Chat ordering and read receipts / Open access
Advance a stored read marker from a device report: stale session gate · case 01
A queued read report from a session that predates a "mark unread" silently marks the conversation read again.
ROOT CAUSE
The stale session gate decision evaluates `if session_epoch > current_epoch:` where the contract requires `if session_epoch != current_epoch:`.
VERIFIED REPAIR
Use `if session_epoch != current_epoch:` for the stale session gate decision and keep every other rule of the model unchanged.
Unsuccessful approach: Tolerating one epoch of lag still lets the session that existed just before the mark-unread replay its report. The attempted `if session_epoch < current_epoch - 1:` still disagrees with a fixture.
Case contract
A report from a device session whose epoch differs from the current epoch (for example a session that predates a "mark unread") is ignored. Otherwise the report is clamped to latest_seq and the marker only moves forward. Result: {marker, broadcast (true only when the marker changed), unread = max(0, latest_seq - marker)}.
Why this case matters
Read markers drive unread badges on every device; regressions or stale sessions resurrect or hide unread messages.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(marker, report, latest_seq, session_epoch, current_epoch):
if session_epoch > current_epoch:
return {'marker': marker, 'broadcast': False, 'unread': max(0, latest_seq - marker)}
target = min(report, latest_seq)
new = max(marker, target)
return {'marker': new, 'broadcast': new != marker, 'unread': max(0, latest_seq - new)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('stale session after mark-unread', (10, 15, 18, 3, 4), {'broadcast': False, 'marker': 10, 'unread': 8}), ('session two epochs behind', (10, 17, 19, 1, 3), {'broadcast': False, 'marker': 10, 'unread': 9}), ('report beyond latest', (1, 21, 5, 2, 2), {'broadcast': True, 'marker': 5, 'unread': 0}), ('older report arrives late', (51, 41, 61, 1, 1), {'broadcast': False, 'marker': 51, 'unread': 10}), ('equal report no broadcast', (30, 30, 41, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 11}), ('history trimmed below marker', (21, 5, 18, 1, 1), {'broadcast': False, 'marker': 21, 'unread': 0}), ('normal advance', (1, 4, 11, 7, 7), {'broadcast': True, 'marker': 4, 'unread': 7}), ('lower report with zero', (3, 0, 7, 2, 2), {'broadcast': False, 'marker': 3, 'unread': 4})], 2: [('stale session after mark-unread', (20, 25, 28, 3, 4), {'broadcast': False, 'marker': 20, 'unread': 8}), ('session two epochs behind', (20, 27, 29, 1, 3), {'broadcast': False, 'marker': 20, 'unread': 9}), ('report beyond latest', (2, 22, 6, 2, 2), {'broadcast': True, 'marker': 6, 'unread': 0}), ('older report arrives late', (52, 42, 62, 1, 1), {'broadcast': False, 'marker': 52, 'unread': 10}), ('equal report no broadcast', (30, 30, 42, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 12}), ('history trimmed below marker', (22, 5, 18, 1, 1), {'broadcast': False, 'marker': 22, 'unread': 0}), ('normal advance', (2, 5, 12, 7, 7), {'broadcast': True, 'marker': 5, 'unread': 7}), ('lower report with zero', (4, 0, 8, 2, 2), {'broadcast': False, 'marker': 4, 'unread': 4})], 3: [('stale session after mark-unread', (30, 35, 38, 3, 4), {'broadcast': False, 'marker': 30, 'unread': 8}), ('session two epochs behind', (30, 37, 39, 1, 3), {'broadcast': False, 'marker': 30, 'unread': 9}), ('report beyond latest', (3, 23, 7, 2, 2), {'broadcast': True, 'marker': 7, 'unread': 0}), ('older report arrives late', (53, 43, 63, 1, 1), {'broadcast': False, 'marker': 53, 'unread': 10}), ('equal report no broadcast', (30, 30, 43, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 13}), ('history trimmed below marker', (23, 5, 18, 1, 1), {'broadcast': False, 'marker': 23, 'unread': 0}), ('normal advance', (3, 6, 13, 7, 7), {'broadcast': True, 'marker': 6, 'unread': 7}), ('lower report with zero', (5, 0, 9, 2, 2), {'broadcast': False, 'marker': 5, 'unread': 4})], 4: [('stale session after mark-unread', (40, 45, 48, 3, 4), {'broadcast': False, 'marker': 40, 'unread': 8}), ('session two epochs behind', (40, 47, 49, 1, 3), {'broadcast': False, 'marker': 40, 'unread': 9}), ('report beyond latest', (4, 24, 8, 2, 2), {'broadcast': True, 'marker': 8, 'unread': 0}), ('older report arrives late', (54, 44, 64, 1, 1), {'broadcast': False, 'marker': 54, 'unread': 10}), ('equal report no broadcast', (30, 30, 44, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 14}), ('history trimmed below marker', (24, 5, 18, 1, 1), {'broadcast': False, 'marker': 24, 'unread': 0}), ('normal advance', (4, 7, 14, 7, 7), {'broadcast': True, 'marker': 7, 'unread': 7}), ('lower report with zero', (6, 0, 10, 2, 2), {'broadcast': False, 'marker': 6, 'unread': 4})], 5: [('stale session after mark-unread', (50, 55, 58, 3, 4), {'broadcast': False, 'marker': 50, 'unread': 8}), ('session two epochs behind', (50, 57, 59, 1, 3), {'broadcast': False, 'marker': 50, 'unread': 9}), ('report beyond latest', (5, 25, 9, 2, 2), {'broadcast': True, 'marker': 9, 'unread': 0}), ('older report arrives late', (55, 45, 65, 1, 1), {'broadcast': False, 'marker': 55, 'unread': 10}), ('equal report no broadcast', (30, 30, 45, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 15}), ('history trimmed below marker', (25, 5, 18, 1, 1), {'broadcast': False, 'marker': 25, 'unread': 0}), ('normal advance', (5, 8, 15, 7, 7), {'broadcast': True, 'marker': 8, 'unread': 7}), ('lower report with zero', (7, 0, 11, 2, 2), {'broadcast': False, 'marker': 7, 'unread': 4})]}
for _label, _args, _expected in _CASES[N]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| stale session after mark-unread | {'broadcast': True, 'marker': 15, 'unread': 3} | {'broadcast': False, 'marker': 10, 'unread': 8} | Failed |
| session two epochs behind | {'broadcast': True, 'marker': 17, 'unread': 2} | {'broadcast': False, 'marker': 10, 'unread': 9} | Failed |
| report beyond latest | {'broadcast': True, 'marker': 5, 'unread': 0} | {'broadcast': True, 'marker': 5, 'unread': 0} | Passed |
| older report arrives late | {'broadcast': False, 'marker': 51, 'unread': 10} | {'broadcast': False, 'marker': 51, 'unread': 10} | Passed |
| equal report no broadcast | {'broadcast': False, 'marker': 30, 'unread': 11} | {'broadcast': False, 'marker': 30, 'unread': 11} | Passed |
| history trimmed below marker | {'broadcast': False, 'marker': 21, 'unread': 0} | {'broadcast': False, 'marker': 21, 'unread': 0} | Passed |
| normal advance | {'broadcast': True, 'marker': 4, 'unread': 7} | {'broadcast': True, 'marker': 4, 'unread': 7} | Passed |
| lower report with zero | {'broadcast': False, 'marker': 3, 'unread': 4} | {'broadcast': False, 'marker': 3, 'unread': 4} | Passed |
SHA-256 / 7e6c520e24b233ad5a4f20ebae94bf46cdbe1d92c8428e7ec6bd28c3b7a7702a
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(marker, report, latest_seq, session_epoch, current_epoch):
if session_epoch < current_epoch - 1:
return {'marker': marker, 'broadcast': False, 'unread': max(0, latest_seq - marker)}
target = min(report, latest_seq)
new = max(marker, target)
return {'marker': new, 'broadcast': new != marker, 'unread': max(0, latest_seq - new)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('stale session after mark-unread', (10, 15, 18, 3, 4), {'broadcast': False, 'marker': 10, 'unread': 8}), ('session two epochs behind', (10, 17, 19, 1, 3), {'broadcast': False, 'marker': 10, 'unread': 9}), ('report beyond latest', (1, 21, 5, 2, 2), {'broadcast': True, 'marker': 5, 'unread': 0}), ('older report arrives late', (51, 41, 61, 1, 1), {'broadcast': False, 'marker': 51, 'unread': 10}), ('equal report no broadcast', (30, 30, 41, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 11}), ('history trimmed below marker', (21, 5, 18, 1, 1), {'broadcast': False, 'marker': 21, 'unread': 0}), ('normal advance', (1, 4, 11, 7, 7), {'broadcast': True, 'marker': 4, 'unread': 7}), ('lower report with zero', (3, 0, 7, 2, 2), {'broadcast': False, 'marker': 3, 'unread': 4})], 2: [('stale session after mark-unread', (20, 25, 28, 3, 4), {'broadcast': False, 'marker': 20, 'unread': 8}), ('session two epochs behind', (20, 27, 29, 1, 3), {'broadcast': False, 'marker': 20, 'unread': 9}), ('report beyond latest', (2, 22, 6, 2, 2), {'broadcast': True, 'marker': 6, 'unread': 0}), ('older report arrives late', (52, 42, 62, 1, 1), {'broadcast': False, 'marker': 52, 'unread': 10}), ('equal report no broadcast', (30, 30, 42, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 12}), ('history trimmed below marker', (22, 5, 18, 1, 1), {'broadcast': False, 'marker': 22, 'unread': 0}), ('normal advance', (2, 5, 12, 7, 7), {'broadcast': True, 'marker': 5, 'unread': 7}), ('lower report with zero', (4, 0, 8, 2, 2), {'broadcast': False, 'marker': 4, 'unread': 4})], 3: [('stale session after mark-unread', (30, 35, 38, 3, 4), {'broadcast': False, 'marker': 30, 'unread': 8}), ('session two epochs behind', (30, 37, 39, 1, 3), {'broadcast': False, 'marker': 30, 'unread': 9}), ('report beyond latest', (3, 23, 7, 2, 2), {'broadcast': True, 'marker': 7, 'unread': 0}), ('older report arrives late', (53, 43, 63, 1, 1), {'broadcast': False, 'marker': 53, 'unread': 10}), ('equal report no broadcast', (30, 30, 43, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 13}), ('history trimmed below marker', (23, 5, 18, 1, 1), {'broadcast': False, 'marker': 23, 'unread': 0}), ('normal advance', (3, 6, 13, 7, 7), {'broadcast': True, 'marker': 6, 'unread': 7}), ('lower report with zero', (5, 0, 9, 2, 2), {'broadcast': False, 'marker': 5, 'unread': 4})], 4: [('stale session after mark-unread', (40, 45, 48, 3, 4), {'broadcast': False, 'marker': 40, 'unread': 8}), ('session two epochs behind', (40, 47, 49, 1, 3), {'broadcast': False, 'marker': 40, 'unread': 9}), ('report beyond latest', (4, 24, 8, 2, 2), {'broadcast': True, 'marker': 8, 'unread': 0}), ('older report arrives late', (54, 44, 64, 1, 1), {'broadcast': False, 'marker': 54, 'unread': 10}), ('equal report no broadcast', (30, 30, 44, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 14}), ('history trimmed below marker', (24, 5, 18, 1, 1), {'broadcast': False, 'marker': 24, 'unread': 0}), ('normal advance', (4, 7, 14, 7, 7), {'broadcast': True, 'marker': 7, 'unread': 7}), ('lower report with zero', (6, 0, 10, 2, 2), {'broadcast': False, 'marker': 6, 'unread': 4})], 5: [('stale session after mark-unread', (50, 55, 58, 3, 4), {'broadcast': False, 'marker': 50, 'unread': 8}), ('session two epochs behind', (50, 57, 59, 1, 3), {'broadcast': False, 'marker': 50, 'unread': 9}), ('report beyond latest', (5, 25, 9, 2, 2), {'broadcast': True, 'marker': 9, 'unread': 0}), ('older report arrives late', (55, 45, 65, 1, 1), {'broadcast': False, 'marker': 55, 'unread': 10}), ('equal report no broadcast', (30, 30, 45, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 15}), ('history trimmed below marker', (25, 5, 18, 1, 1), {'broadcast': False, 'marker': 25, 'unread': 0}), ('normal advance', (5, 8, 15, 7, 7), {'broadcast': True, 'marker': 8, 'unread': 7}), ('lower report with zero', (7, 0, 11, 2, 2), {'broadcast': False, 'marker': 7, 'unread': 4})]}
for _label, _args, _expected in _CASES[N]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| stale session after mark-unread | {'broadcast': True, 'marker': 15, 'unread': 3} | {'broadcast': False, 'marker': 10, 'unread': 8} | Failed |
| session two epochs behind | {'broadcast': False, 'marker': 10, 'unread': 9} | {'broadcast': False, 'marker': 10, 'unread': 9} | Passed |
| report beyond latest | {'broadcast': True, 'marker': 5, 'unread': 0} | {'broadcast': True, 'marker': 5, 'unread': 0} | Passed |
| older report arrives late | {'broadcast': False, 'marker': 51, 'unread': 10} | {'broadcast': False, 'marker': 51, 'unread': 10} | Passed |
| equal report no broadcast | {'broadcast': False, 'marker': 30, 'unread': 11} | {'broadcast': False, 'marker': 30, 'unread': 11} | Passed |
| history trimmed below marker | {'broadcast': False, 'marker': 21, 'unread': 0} | {'broadcast': False, 'marker': 21, 'unread': 0} | Passed |
| normal advance | {'broadcast': True, 'marker': 4, 'unread': 7} | {'broadcast': True, 'marker': 4, 'unread': 7} | Passed |
| lower report with zero | {'broadcast': False, 'marker': 3, 'unread': 4} | {'broadcast': False, 'marker': 3, 'unread': 4} | Passed |
SHA-256 / ce5dcf1f666b3ba11f12e619a20944e7b30c639688f22750fe473d10d31fc3c8
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(marker, report, latest_seq, session_epoch, current_epoch):
if session_epoch != current_epoch:
return {'marker': marker, 'broadcast': False, 'unread': max(0, latest_seq - marker)}
target = min(report, latest_seq)
new = max(marker, target)
return {'marker': new, 'broadcast': new != marker, 'unread': max(0, latest_seq - new)}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('stale session after mark-unread', (10, 15, 18, 3, 4), {'broadcast': False, 'marker': 10, 'unread': 8}), ('session two epochs behind', (10, 17, 19, 1, 3), {'broadcast': False, 'marker': 10, 'unread': 9}), ('report beyond latest', (1, 21, 5, 2, 2), {'broadcast': True, 'marker': 5, 'unread': 0}), ('older report arrives late', (51, 41, 61, 1, 1), {'broadcast': False, 'marker': 51, 'unread': 10}), ('equal report no broadcast', (30, 30, 41, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 11}), ('history trimmed below marker', (21, 5, 18, 1, 1), {'broadcast': False, 'marker': 21, 'unread': 0}), ('normal advance', (1, 4, 11, 7, 7), {'broadcast': True, 'marker': 4, 'unread': 7}), ('lower report with zero', (3, 0, 7, 2, 2), {'broadcast': False, 'marker': 3, 'unread': 4})], 2: [('stale session after mark-unread', (20, 25, 28, 3, 4), {'broadcast': False, 'marker': 20, 'unread': 8}), ('session two epochs behind', (20, 27, 29, 1, 3), {'broadcast': False, 'marker': 20, 'unread': 9}), ('report beyond latest', (2, 22, 6, 2, 2), {'broadcast': True, 'marker': 6, 'unread': 0}), ('older report arrives late', (52, 42, 62, 1, 1), {'broadcast': False, 'marker': 52, 'unread': 10}), ('equal report no broadcast', (30, 30, 42, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 12}), ('history trimmed below marker', (22, 5, 18, 1, 1), {'broadcast': False, 'marker': 22, 'unread': 0}), ('normal advance', (2, 5, 12, 7, 7), {'broadcast': True, 'marker': 5, 'unread': 7}), ('lower report with zero', (4, 0, 8, 2, 2), {'broadcast': False, 'marker': 4, 'unread': 4})], 3: [('stale session after mark-unread', (30, 35, 38, 3, 4), {'broadcast': False, 'marker': 30, 'unread': 8}), ('session two epochs behind', (30, 37, 39, 1, 3), {'broadcast': False, 'marker': 30, 'unread': 9}), ('report beyond latest', (3, 23, 7, 2, 2), {'broadcast': True, 'marker': 7, 'unread': 0}), ('older report arrives late', (53, 43, 63, 1, 1), {'broadcast': False, 'marker': 53, 'unread': 10}), ('equal report no broadcast', (30, 30, 43, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 13}), ('history trimmed below marker', (23, 5, 18, 1, 1), {'broadcast': False, 'marker': 23, 'unread': 0}), ('normal advance', (3, 6, 13, 7, 7), {'broadcast': True, 'marker': 6, 'unread': 7}), ('lower report with zero', (5, 0, 9, 2, 2), {'broadcast': False, 'marker': 5, 'unread': 4})], 4: [('stale session after mark-unread', (40, 45, 48, 3, 4), {'broadcast': False, 'marker': 40, 'unread': 8}), ('session two epochs behind', (40, 47, 49, 1, 3), {'broadcast': False, 'marker': 40, 'unread': 9}), ('report beyond latest', (4, 24, 8, 2, 2), {'broadcast': True, 'marker': 8, 'unread': 0}), ('older report arrives late', (54, 44, 64, 1, 1), {'broadcast': False, 'marker': 54, 'unread': 10}), ('equal report no broadcast', (30, 30, 44, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 14}), ('history trimmed below marker', (24, 5, 18, 1, 1), {'broadcast': False, 'marker': 24, 'unread': 0}), ('normal advance', (4, 7, 14, 7, 7), {'broadcast': True, 'marker': 7, 'unread': 7}), ('lower report with zero', (6, 0, 10, 2, 2), {'broadcast': False, 'marker': 6, 'unread': 4})], 5: [('stale session after mark-unread', (50, 55, 58, 3, 4), {'broadcast': False, 'marker': 50, 'unread': 8}), ('session two epochs behind', (50, 57, 59, 1, 3), {'broadcast': False, 'marker': 50, 'unread': 9}), ('report beyond latest', (5, 25, 9, 2, 2), {'broadcast': True, 'marker': 9, 'unread': 0}), ('older report arrives late', (55, 45, 65, 1, 1), {'broadcast': False, 'marker': 55, 'unread': 10}), ('equal report no broadcast', (30, 30, 45, 5, 5), {'broadcast': False, 'marker': 30, 'unread': 15}), ('history trimmed below marker', (25, 5, 18, 1, 1), {'broadcast': False, 'marker': 25, 'unread': 0}), ('normal advance', (5, 8, 15, 7, 7), {'broadcast': True, 'marker': 8, 'unread': 7}), ('lower report with zero', (7, 0, 11, 2, 2), {'broadcast': False, 'marker': 7, 'unread': 4})]}
for _label, _args, _expected in _CASES[N]:
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| stale session after mark-unread | {'broadcast': False, 'marker': 10, 'unread': 8} | {'broadcast': False, 'marker': 10, 'unread': 8} | Passed |
| session two epochs behind | {'broadcast': False, 'marker': 10, 'unread': 9} | {'broadcast': False, 'marker': 10, 'unread': 9} | Passed |
| report beyond latest | {'broadcast': True, 'marker': 5, 'unread': 0} | {'broadcast': True, 'marker': 5, 'unread': 0} | Passed |
| older report arrives late | {'broadcast': False, 'marker': 51, 'unread': 10} | {'broadcast': False, 'marker': 51, 'unread': 10} | Passed |
| equal report no broadcast | {'broadcast': False, 'marker': 30, 'unread': 11} | {'broadcast': False, 'marker': 30, 'unread': 11} | Passed |
| history trimmed below marker | {'broadcast': False, 'marker': 21, 'unread': 0} | {'broadcast': False, 'marker': 21, 'unread': 0} | Passed |
| normal advance | {'broadcast': True, 'marker': 4, 'unread': 7} | {'broadcast': True, 'marker': 4, 'unread': 7} | Passed |
| lower report with zero | {'broadcast': False, 'marker': 3, 'unread': 4} | {'broadcast': False, 'marker': 3, 'unread': 4} | Passed |
SHA-256 / dd2d1a000597884213acafaeb41562829e91b9cbf08e39227985d1c7d03a7829
Verification & scope
Stipulated offline chat model; not a complete messaging protocol, client or server implementation. 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:10.889598+00:00.
Case digest / 432e90202df2eaa98c3462ebb3ef033f583b9cfb861f7a41314b81a260a42728