FAILURE MAP
← Case archive

FA-75991 / Chat ordering and read receipts / Open access

Place the "new messages" divider in a loaded window: send implies read · case 01

After the user replies in the middle of new messages, the divider still sits above messages they answered.

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

ROOT CAUSE

The send implies read decision evaluates `if author == me and seq == eff + 1:` where the contract requires `if author == me and seq > eff:`.

VERIFIED REPAIR

Use `if author == me and seq > eff:` for the send implies read decision and keep every other rule of the model unchanged.

Unsuccessful approach: Letting only the first own reply advance the marker ignores later replies. The attempted `if author == me and seq > eff and eff == marker:` still disagrees with a fixture.

Case contract

messages are ascending [seq, author] pairs of the loaded window that starts at window_start. Sending a message implies having read everything before it, so the effective marker is the larger of marker and the highest seq authored by me. The divider goes before the first loaded message after the effective marker not written by me (index, or None). older_unread is true when some unread seq lies before the loaded window (effective marker < window_start - 1).

Why this case matters

The divider tells users where to resume reading; misplacing it hides or repeats unread history.

1 / The failure

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

N = 1
observations = []
def solve(messages, me, marker, window_start):
    eff = marker
    for seq, author in messages:
        if author == me and seq == eff + 1:
            eff = seq
    index = None
    for i, (seq, author) in enumerate(messages):
        if seq > eff and author != me:
            index = i
            break
    return {'index': index, 'older_unread': eff < window_start - 1}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('interleaved own replies', ([[11, 'bo'], [12, 'me'], [13, 'bo'], [14, 'me'], [15, 'cy']], 'me', 10, 11), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [22, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 7, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 2: [('interleaved own replies', ([[12, 'bo'], [13, 'me'], [14, 'bo'], [15, 'me'], [16, 'cy']], 'me', 11, 12), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [23, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 8, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 3: [('interleaved own replies', ([[13, 'bo'], [14, 'me'], [15, 'bo'], [16, 'me'], [17, 'cy']], 'me', 12, 13), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [24, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 9, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 4: [('interleaved own replies', ([[14, 'bo'], [15, 'me'], [16, 'bo'], [17, 'me'], [18, 'cy']], 'me', 13, 14), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [25, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 10, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 5: [('interleaved own replies', ([[15, 'bo'], [16, 'me'], [17, 'bo'], [18, 'me'], [19, 'cy']], 'me', 14, 15), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [26, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 11, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})]}
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 fixtureActualExpectedOutcome
interleaved own replies{'index': 0, 'older_unread': False}{'index': 4, 'older_unread': False}Failed
window starts right after marker{'index': 0, 'older_unread': False}{'index': 0, 'older_unread': False}Passed
one unloaded unread{'index': 0, 'older_unread': True}{'index': 0, 'older_unread': True}Passed
all read{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
only own messages after marker{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
first unread foreign{'index': 1, 'older_unread': False}{'index': 1, 'older_unread': False}Passed

SHA-256 / 26271ddd4ba7e10adcb3630c9151b574be035612095a239873e812a390ff6746

2 / The unsuccessful fix

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

N = 1
observations = []
def solve(messages, me, marker, window_start):
    eff = marker
    for seq, author in messages:
        if author == me and seq > eff and eff == marker:
            eff = seq
    index = None
    for i, (seq, author) in enumerate(messages):
        if seq > eff and author != me:
            index = i
            break
    return {'index': index, 'older_unread': eff < window_start - 1}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('interleaved own replies', ([[11, 'bo'], [12, 'me'], [13, 'bo'], [14, 'me'], [15, 'cy']], 'me', 10, 11), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [22, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 7, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 2: [('interleaved own replies', ([[12, 'bo'], [13, 'me'], [14, 'bo'], [15, 'me'], [16, 'cy']], 'me', 11, 12), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [23, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 8, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 3: [('interleaved own replies', ([[13, 'bo'], [14, 'me'], [15, 'bo'], [16, 'me'], [17, 'cy']], 'me', 12, 13), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [24, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 9, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 4: [('interleaved own replies', ([[14, 'bo'], [15, 'me'], [16, 'bo'], [17, 'me'], [18, 'cy']], 'me', 13, 14), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [25, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 10, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 5: [('interleaved own replies', ([[15, 'bo'], [16, 'me'], [17, 'bo'], [18, 'me'], [19, 'cy']], 'me', 14, 15), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [26, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 11, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})]}
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 fixtureActualExpectedOutcome
interleaved own replies{'index': 2, 'older_unread': False}{'index': 4, 'older_unread': False}Failed
window starts right after marker{'index': 0, 'older_unread': False}{'index': 0, 'older_unread': False}Passed
one unloaded unread{'index': 0, 'older_unread': True}{'index': 0, 'older_unread': True}Passed
all read{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
only own messages after marker{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
first unread foreign{'index': 1, 'older_unread': False}{'index': 1, 'older_unread': False}Passed

SHA-256 / e650d510ea14ad7c6b5b2a13dd8ab5044e43daa8dff427e841963e7b00ac799e

3 / The verified repair

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

N = 1
observations = []
def solve(messages, me, marker, window_start):
    eff = marker
    for seq, author in messages:
        if author == me and seq > eff:
            eff = seq
    index = None
    for i, (seq, author) in enumerate(messages):
        if seq > eff and author != me:
            index = i
            break
    return {'index': index, 'older_unread': eff < window_start - 1}
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
_CASES = {1: [('interleaved own replies', ([[11, 'bo'], [12, 'me'], [13, 'bo'], [14, 'me'], [15, 'cy']], 'me', 10, 11), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [22, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 7, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 2: [('interleaved own replies', ([[12, 'bo'], [13, 'me'], [14, 'bo'], [15, 'me'], [16, 'cy']], 'me', 11, 12), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [23, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 8, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 3: [('interleaved own replies', ([[13, 'bo'], [14, 'me'], [15, 'bo'], [16, 'me'], [17, 'cy']], 'me', 12, 13), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [24, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 9, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 4: [('interleaved own replies', ([[14, 'bo'], [15, 'me'], [16, 'bo'], [17, 'me'], [18, 'cy']], 'me', 13, 14), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [25, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 10, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})], 5: [('interleaved own replies', ([[15, 'bo'], [16, 'me'], [17, 'bo'], [18, 'me'], [19, 'cy']], 'me', 14, 15), {'index': 4, 'older_unread': False}), ('window starts right after marker', ([[20, 'bo'], [21, 'bo']], 'me', 19, 20), {'index': 0, 'older_unread': False}), ('one unloaded unread', ([[20, 'bo'], [26, 'bo']], 'me', 18, 20), {'index': 0, 'older_unread': True}), ('all read', ([[5, 'bo'], [6, 'cy']], 'me', 11, 5), {'index': None, 'older_unread': False}), ('only own messages after marker', ([[1, 'bo'], [2, 'me']], 'me', 1, 1), {'index': None, 'older_unread': False}), ('first unread foreign', ([[3, 'bo'], [4, 'cy'], [5, 'dd']], 'me', 3, 3), {'index': 1, 'older_unread': False})]}
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 fixtureActualExpectedOutcome
interleaved own replies{'index': 4, 'older_unread': False}{'index': 4, 'older_unread': False}Passed
window starts right after marker{'index': 0, 'older_unread': False}{'index': 0, 'older_unread': False}Passed
one unloaded unread{'index': 0, 'older_unread': True}{'index': 0, 'older_unread': True}Passed
all read{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
only own messages after marker{'index': None, 'older_unread': False}{'index': None, 'older_unread': False}Passed
first unread foreign{'index': 1, 'older_unread': False}{'index': 1, 'older_unread': False}Passed

SHA-256 / b96673fbbd3711b5170fb321e0f037bff2e88667ddcad455b30f91e43de39784

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:12.153465+00:00.

Case digest / 9605d048ccaa284a4f80e8399befa32d99822d2bc2f83ae06e7268077cb651b1