Skip to content

fix(messages): confirm a short history page before calling it the start - #402

Merged
leemour merged 1 commit into
mainfrom
fix/unread-and-short-pages
Oct 4, 2026
Merged

leemour merged 1 commit into
mainfrom
fix/unread-and-short-pages

Conversation

@leemour

@leemour leemour commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Task

TASK-370:

Why

  • There is no paging signal from MAX. The chats.history spec (src/spec/operations/chats.ts) lists only messages in the answer. The 2026-09-25 web-tab captures record the requests, but no answer bodies. That is an absence of evidence, not proof. Nothing we hold says whether older messages exist.
  • A short page may sit mid-chat. Whether MAX ever does this is unverified. If it does, store fetch marks the chat complete and messages list drops the hint for older messages.
  • #chatsCut was set and never read (#readRestOfChats). When the one CHATS_LIST after the login was refused, or came back with 26 or more chats, the chat list still said hasMore: false.

What

  • A short, nonempty page back is confirmed with one more CHAT_HISTORY: { chatId, from: oldest - 1, forward: 0, backward: 1, getMessages: true }. These are exactly web.max.ru's fields, with no interactive, so it marks nothing read.
    • It goes straight to the wire, so it adds no reactions request (opcode 180) and no contact-name lookups.
    • One message back means hasMore: true; none means the start of the chat. A full page still counts as more, and an empty page as the end.
    • Cost: one extra request for each short page. That includes the per-chat reads of inbox and inbox --new for a chat with fewer messages than --limit.
  • The forward (after) branch is unchanged. It already asks for one more than the page.
  • chats.list reports hasMore: true on its last nonempty page when the list was cut. An empty page past the end still says false, so a script that pages ends.
  • Coverage limit, stated plainly: MAX gives the first ~41 chats (15 from the login plus one CHATS_LIST page). On a bigger account, the rest is now reported (partial), but still not read. Reading the rest means following the CHATS_LIST marker. That is new protocol behaviour on the real account, so it needs its own plan, and it is not built here.
  • Until max-cli bumps to the cli-messaging release with #548, inbox on a cut account prints the old "only the 100 newest chats were looked at". The number is wrong, but it does say the list was incomplete.
  • Tests: the history mocks now page by from/backward as MAX does (pagedHistory in src/testing/mock-max.ts), and the download fixture's time now matches its id. Counts that now include the confirming request are updated: inbox, review, store.
  • Docs: docs/usage.md (a user page) is rewritten. docs/dev/ARCHITECTURE.md is corrected in place, with a correction mark.

Testing

  • pnpm lint && pnpm typecheck && pnpm test:coverage && pnpm docs:check && pnpm parity:check all pass, on main b5d3691.

  • New tests in src/client.test.ts:

    • a short page followed by one older message gives hasMore: true, with the exact confirming request and no extra reactions request;
    • a short page followed by an empty answer gives false;
    • a cut chat list says hasMore on its last nonempty page only.

    All three fail on main.

  • The adapter contract was run against fix(inbox): look at every chat for unread, new and review cli-messaging#548's kit: 22 passed, 2 skipped, the same as on main.

  • Noticed, not fixed: on main, src/store.test.ts "asks MAX for --page-size messages a page" fails when run alone (-t) and passes in a full-file run, so it depends on test order.

  • Not verified: anything against live MAX. Fakes only.

🤖 Generated with Claude Code

messages.list answered hasMore only for a full page back, so a page MAX
returned short in the middle of a chat read as its first message: messages
list dropped the older-page hint and store fetch marked the chat complete.
MAX's CHAT_HISTORY answer carries messages and nothing else (the spec, and
the web-tab captures record no answer body), so there is no paging signal
to follow. A short, nonempty page is now confirmed with one more
CHAT_HISTORY for a single message older than its oldest, sent straight to
the wire with web.max.ru's fields, so it costs no reactions or name lookup.

chats.list also reports hasMore on its last nonempty page when the login's
chat list was cut (#chatsCut was set and never read), so inbox, review and
chats list can say the list was incomplete.

The test mocks now page history by from/backward as MAX does
(pagedHistory), and the download fixture's time matches its id.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@leemour
leemour force-pushed the fix/unread-and-short-pages branch from e6a0a4a to 0b0f641 Compare October 4, 2026 21:38
@leemour
leemour merged commit 8d481ea into main Oct 4, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant