Skip to content

feat(gateway): optional afterSeq catch-up cursor on chat.history#100267

Closed
steipete wants to merge 6 commits into
mainfrom
feat/gateway-chat-history-after-seq
Closed

feat(gateway): optional afterSeq catch-up cursor on chat.history#100267
steipete wants to merge 6 commits into
mainfrom
feat/gateway-chat-history-after-seq

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Part of #100197

What Problem This Solves

Resolves a problem where reconnecting Gateway clients (Control UI, WebChat, native apps) had to refetch the entire chat.history payload after a WebSocket drop, even when they only missed a handful of messages. Offset pagination pages from the newest end and cannot express "give me only what I missed since point X".

Why This Change Was Made

chat.history messages already carry a stable, monotonic transcript sequence (__openclaw.seq, the 1-based visible-entry index over the active transcript branch). This change adds an optional afterSeq cursor that returns only entries newer than that sequence, oldest-first, with nextAfterSeq/hasMore for follow-up pages. Catch-up is lossless by design: when the history byte budget would trim a cursor page, it trims from the newest end at transcript-seq group boundaries — always delivering at least one complete seq group so mirror rows of a single raw entry are never split across the cursor — and nextAfterSeq only advances past rows actually delivered, so trimmed rows arrive on the next page; untrimmed pages advance over the full raw range consumed so projection-filtered entries can never stall the loop. The change is additive: no protocol version bump, the parameter is optional, offset pagination and its tail-preserving budget behavior are unchanged, and combining afterSeq with offset is rejected as invalid. The generated Swift protocol model gains the field with a defaulted initializer parameter so existing native call sites keep compiling.

User Impact

API and app clients can resume a chat session after a reconnect by fetching only the messages they missed — losslessly, even for oversized backlogs that exceed the per-response byte budget. Clients that never send afterSeq see byte-identical behavior. Companion client PRs (iOS, Android) adopt the cursor and are stacked on this branch.

Evidence

  • node scripts/run-vitest.mjs src/gateway/server.chat.gateway-server-chat-b.test.ts -t "afterSeq" — 5 passed: cursor returns only newer messages oldest-first; budget-constrained pages keep the oldest rows and iterating with the returned cursor recovers all messages exactly once in order; a page of only projection-filtered rows still advances the cursor; absent param keeps the existing response shape; invalid cursors rejected cleanly.
  • node scripts/run-vitest.mjs src/gateway/server-methods/chat-history-budget.test.ts — 18 passed: head-preserving cursor cap keeps oldest rows, delivers an over-budget first seq group whole instead of splitting it, trims later groups at the prior boundary; tail-preserving budget helpers untouched.
  • node scripts/run-vitest.mjs src/gateway/server.chat.gateway-server-chat-b.test.ts -t "pagination" — 2 passed: existing offset pagination (including the final-budgeted-page case) unchanged.
  • oxfmt --check clean on touched files; scripts/protocol-gen-swift.ts regeneration diff is exactly the afterSeq field (4 lines).
  • Codex autoreview, three rounds across the series: round 1 found cursor-past-trimmed-rows loss (fixed, 79ff19f), round 2 found first-seq-group splitting (fixed, 6d7fff6), final review on the fix commit clean ("patch is correct", 0.86).

Documented degradation (unchanged class from offset pagination): a single seq group whose bytes exceed the entire budget ships as one over-budget page — deliberate, protects losslessness.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation app: web-ui App: web-ui gateway Gateway runtime scripts Repository scripts size: L maintainer Maintainer-authored PR labels Jul 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d7fff6ebf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gateway/server-methods/chat.ts Outdated
Comment on lines +3019 to +3022
const readPage = await readSessionMessagesAfterSeqWithStatsAsync(readScope, {
afterSeq,
maxMessages: max,
allowResetArchiveFallback: true,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve pair context for afterSeq pages

When an afterSeq catch-up page ends between a stale subagent_announce user row and its adjacent assistant reply (for example limit: 1), this reads exactly max rows and nextAfterSeq advances before dropPreSessionStartAnnouncePairs has the paired assistant context. The first page drops only the announce row, then the next page starts at the stale assistant and renders it; the existing recent/offset history paths overread one row specifically to avoid this boundary leak, so the cursor path needs the same context or must avoid advancing past an uninspected pair.

Useful? React with 👍 / 👎.

@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 8:59 AM ET / 12:59 UTC.

Summary
Adds an optional afterSeq cursor to Gateway chat.history, updates projection/cursor handling, generated Swift models, docs, changelog text, and gateway tests.

PR surface: Source +245, Tests +635, Docs +3, Other +4. Total +887 across 13 files.

Reproducibility: yes. Source inspection of the PR head shows the CLI-bound offset guard and the full-transcript cursor read/projection path; I did not run tests because this review is read-only.

Review metrics: 1 noteworthy metric.

  • Protocol request surface: 1 optional chat.history parameter added. Gateway RPC additions are compatibility-sensitive because generated clients and stacked mobile PRs depend on the new cursor semantics.

Stored data model
Persistent data-model change detected: serialized state: src/gateway/server-methods/chat-history-budget.test.ts, serialized state: src/gateway/server.chat.gateway-server-chat-b.test.ts, serialized state: src/gateway/session-transcript-readers.ts, serialized state: src/gateway/session-utils.fs.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100197
Summary: This PR is the Gateway-side candidate for the open reconnect sequence-cursor workstream; the iOS and Android PRs are stacked client adoptions of the same contract.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦪 silver shellfish
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof from a real setup is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Restore CLI-bound offset pagination and add/adjust regression coverage for that existing contract.
  • Make afterSeq catch-up read/project only a bounded projection-safe window instead of the whole transcript.
  • [P1] Add redacted real behavior proof from a live Gateway reconnect or client run.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR provides tests and CI-style evidence only; before merge the contributor should add redacted live output, logs, a terminal screenshot, or a short recording of real reconnect catch-up, then update the PR body so ClawSweeper re-reviews automatically or ask a maintainer to comment @clawsweeper re-review.

Risk before merge

  • [P1] Existing clients that request offset for a CLI-bound session can lose the offset/nextOffset contract and repeat a full imported page instead of advancing through paged history.
  • [P1] A reconnect that missed a small number of rows in a large session still materializes and projects the full active transcript before filtering, so the new catch-up path can stall under large-history conditions.
  • [P1] The new Gateway protocol contract is stacked under open iOS and Android adoption PRs, so cursor semantics need maintainer acceptance before the client stack depends on them.
  • [P1] Contributor proof is limited to tests and CI; there is no redacted live reconnect/Gateway-client run showing the changed behavior after the fix.

Maintainer options:

  1. Fix Pagination And Catch-Up Before Merge (recommended)
    Preserve CLI-bound offset pagination, make cursor catch-up read/project a bounded projection-safe window, and remove the release-owned changelog edit before the protocol lands.
  2. Pause The Gateway/Mobile Stack
    Delay this PR until maintainers can review the Gateway cursor and stacked mobile reconnect behavior as one upgrade contract.
  3. Accept The Protocol Risk
    Maintainers could intentionally accept the current contract and performance tradeoff, but that would ship known compatibility and large-history risks.

Next step before merge

  • [P1] The PR has a protected maintainer label, a new Gateway protocol contract, missing real behavior proof, and concrete blockers that should be handled in normal PR review rather than a standalone repair lane.

Maintainer decision needed

  • Question: Should OpenClaw accept the additive chat.history.afterSeq Gateway cursor contract once the offset compatibility, bounded catch-up, changelog, and proof blockers are fixed?
  • Rationale: This PR creates a new Gateway RPC contract that stacked mobile clients will depend on, and the maintainer-labeled canonical issue frames it as a protocol/product workstream rather than a narrow bug fix.
  • Likely owner: steipete — steipete owns the canonical reconnect issue and has the clearest current-main history on the affected Gateway chat-history path.
  • Options:
    • Accept After Repairs (recommended): Land the cursor after preserving current offset behavior, bounding catch-up work, removing the changelog edit, and proving real reconnect behavior across the stack.
    • Pause Stack Review: Hold this Gateway PR until the iOS and Android reconnect PRs are reviewed together with the older-gateway fallback contract.
    • Reject Or Redesign Cursor: Keep full-history refresh as the supported reconnect path for now and reopen the cursor design with a narrower protocol proposal.

Security
Cleared: No concrete security or supply-chain concern was found; the diff changes Gateway protocol/schema logic, generated Swift models, docs, changelog text, and tests without new dependencies, workflows, secrets handling, or downloaded code.

Review findings

  • [P2] Keep CLI offset pagination on the paged path — src/gateway/server-methods/chat.ts:3065
  • [P2] Keep cursor catch-up proportional to the requested window — src/gateway/server-methods/chat.ts:3039
  • [P3] Drop the release-owned changelog edit — CHANGELOG.md:9
Review details

Best possible solution:

Keep the additive cursor direction only if maintainers accept the protocol contract, while preserving existing offset pagination, making afterSeq catch-up bounded with projection-safe context, removing release-owned changelog edits, and adding real reconnect proof before merge.

Do we have a high-confidence way to reproduce the issue?

Yes. Source inspection of the PR head shows the CLI-bound offset guard and the full-transcript cursor read/projection path; I did not run tests because this review is read-only.

Is this the best way to solve the issue?

No. The additive cursor is a plausible layer, but this is not the best mergeable implementation until it preserves current offset behavior, bounds catch-up work, and includes real reconnect proof.

Full review comments:

  • [P2] Keep CLI offset pagination on the paged path — src/gateway/server-methods/chat.ts:3065
    The new !hasImportedCliHistory guard makes chat.history requests with offset fall through to the full CLI-import path, and the added test now expects no offset echo for that case. Current main and the sibling embedded Gateway treat any provided offset as pagination, so existing load-more consumers can repeat the imported tail instead of advancing.
    Confidence: 0.88
  • [P2] Keep cursor catch-up proportional to the requested window — src/gateway/server-methods/chat.ts:3039
    This branch calls readSessionMessagesWithStatsAsync for every afterSeq request, and that helper expands every indexed transcript entry before the later seq filter. A reconnect that missed one row in a long session still materializes and projects the whole transcript, so the catch-up path can stall under the large-history condition it is meant to avoid.
    Confidence: 0.86
  • [P3] Drop the release-owned changelog edit — CHANGELOG.md:9
    This normal feature PR edits CHANGELOG.md, but OpenClaw's repository policy leaves changelog generation to the release flow. Keep the release-note context in the PR body or squash message instead so release automation remains the source of truth.
    Confidence: 0.93

Overall correctness: patch is incorrect
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against a5f0a37373a9.

Label changes

Label changes:

  • add merge-risk: 🚨 compatibility: The PR changes existing CLI-bound offset requests so they no longer take the paged offset branch or return offset metadata.
  • remove merge-risk: 🚨 session-state: Current PR review merge-risk labels are merge-risk: 🚨 compatibility, merge-risk: 🚨 message-delivery, merge-risk: 🚨 availability.

Label justifications:

  • P1: The PR targets reconnect recovery for active Gateway/mobile chat sessions, where missed events and heavy full-history refreshes affect real client workflows.
  • merge-risk: 🚨 compatibility: The PR changes existing CLI-bound offset requests so they no longer take the paged offset branch or return offset metadata.
  • merge-risk: 🚨 message-delivery: Incorrect cursor or pagination behavior can omit, duplicate, or repeat projected chat history rows during reconnect catch-up.
  • merge-risk: 🚨 availability: The afterSeq path can materialize and project the full transcript for a small catch-up request, which can stall large active sessions.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦪 silver shellfish and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR provides tests and CI-style evidence only; before merge the contributor should add redacted live output, logs, a terminal screenshot, or a short recording of real reconnect catch-up, then update the PR body so ClawSweeper re-reviews automatically or ask a maintainer to comment @clawsweeper re-review.
Evidence reviewed

PR surface:

Source +245, Tests +635, Docs +3, Other +4. Total +887 across 13 files.

View PR surface stats
Area Files Added Removed Net
Source 6 262 17 +245
Tests 3 639 4 +635
Docs 2 3 0 +3
Config 0 0 0 0
Generated 0 0 0 0
Other 2 6 2 +4
Total 13 910 23 +887

What I checked:

  • Repository policy read: Root and scoped Gateway/server-methods/docs/scripts AGENTS.md files were read; the Gateway protocol and hot-path guidance affected this review. (AGENTS.md:1, a5f0a37373a9)
  • Current main lacks afterSeq: A current-main grep found no afterSeq in the Gateway protocol/schema/history surfaces, and the current schema only exposes the existing offset and maxChars fields. (packages/gateway-protocol/src/schema/logs-chat.ts:30, a5f0a37373a9)
  • PR adds protocol request surface: The PR head adds optional afterSeq to ChatHistoryParamsSchema, making this an additive Gateway RPC contract rather than a cleanup-only change. (packages/gateway-protocol/src/schema/logs-chat.ts:36, 262de5ba0f4b)
  • Cursor path materializes full transcript: The PR head's afterSeq branch calls readSessionMessagesWithStatsAsync, and that helper returns index.entries.flatMap(...) for the full transcript before filtering the requested cursor window. (src/gateway/server-methods/chat.ts:3039, 262de5ba0f4b)
  • CLI-bound offset branch changes existing behavior: Current main enters offset pagination whenever offset is provided, while the PR head skips that branch for CLI-bound sessions and its new test expects no offset echo for a CLI-bound offset request. (src/gateway/server-methods/chat.ts:3065, 262de5ba0f4b)
  • Sibling embedded gateway still treats offset as pagination: The embedded Gateway stub still handles params.offset !== undefined as a paged request and deliberately avoids CLI imports on paged requests, so the PR creates divergent Gateway behavior. (src/agents/tools/embedded-gateway-stub.ts:280, a5f0a37373a9)

Likely related people:

  • steipete: The canonical reconnect issue and this PR are authored by steipete, and current-main blame ties the existing chat.history pagination implementation to recent commit 8b229a9. (role: proposal owner and recent gateway/protocol contributor; confidence: high; commits: 8b229a938c28, 262de5ba0f4b; files: src/gateway/server-methods/chat.ts, packages/gateway-protocol/src/schema/logs-chat.ts, docs/web/webchat.md)
  • LZY3538: Recent history on src/gateway/session-utils.fs.ts includes session/transcript behavior work in commit e6ec74c, which is adjacent to the reader helpers this PR changes. (role: adjacent session-history contributor; confidence: medium; commits: e6ec74c25430; files: src/gateway/session-utils.fs.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (2 earlier review cycles)
  • reviewed 2026-07-05T10:24:56.042Z sha 6d7fff6 :: needs real behavior proof before merge. :: [P2] Preserve pair context for cursor pages | [P3] Make the first-seq loop lint-clean
  • reviewed 2026-07-05T11:32:57.241Z sha 05c305a :: needs real behavior proof before merge. :: [P2] Preserve pair context for cursor pages | [P2] Preserve tool-send context across cursor pages | [P2] Keep default history loads bounded | [P3] Make the first-seq loop lint-clean

@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P1 High-priority user-facing bug, regression, or broken workflow. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 05c305a8b4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/gateway/server-methods/chat.ts Outdated
Comment on lines +3033 to +3034
messages: augmentChatHistoryWithCanvasBlocks(
projectChatDisplayMessages(recencyFilteredMessages, { maxChars: effectiveMaxChars }),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve tool-send context across cursor pages

When an afterSeq page boundary splits a visible message tool send, e.g. the page contains only the assistant toolCall and the next page contains the successful toolResult/NO_REPLY, this projects each slice independently so mirrorMessageToolVisibleReplies never sees both sides and no page returns the user-visible sent text. This can happen whenever reconnect catch-up misses more than the requested limit (or a budget-trimmed page cuts there), so cursor paging should overread/carry projection context or slice after projection at safe transcript boundaries.

Useful? React with 👍 / 👎.

Comment thread src/gateway/server-methods/chat.ts Outdated
Comment on lines 3118 to 3122
const localReadPage = await readRecentSessionMessagesWithStatsAsync(readScope, {
...localHistoryReadOptions,
maxBytes: Math.max(maxHistoryBytes * 2, 1024 * 1024),
allowResetArchiveFallback: true,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep default history loads bounded

For ordinary chat.history loads with no offset or afterSeq, this now calls readRecentSessionMessagesWithStatsAsync; that helper obtains totalMessages via readSessionMessageCountFromPathAsync, which builds readSessionTranscriptIndex over the full JSONL whenever the transcript stat changes. On large active sessions, every reload after an append loses the previous bounded tail-read behavior and scans/parses the whole transcript before returning the recent window, so the hot reconnect/load path can stall as history grows.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 5, 2026
@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch from 05c305a to d522cc6 Compare July 5, 2026 12:19

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d522cc66d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

totalMessages: readPage.totalMessages,
};
}
if (offset !== undefined && !hasImportedCliHistory) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep offset pagination active for CLI-bound sessions

When a session has a Claude CLI binding, this guard skips the existing offset branch, so chat.history requests that explicitly pass offset fall through to the recent/full path and return no offset/nextOffset metadata. That breaks existing offset consumers: the sibling embedded gateway still treats params.offset !== undefined as a paged request and deliberately avoids merging full CLI imports at src/agents/tools/embedded-gateway-stub.ts:280-339, so load-more/history paging for CLI-bound sessions repeats the tail instead of advancing.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch from d522cc6 to c9a5ce2 Compare July 5, 2026 12:25

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c9a5ce2ac7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +3039 to +3041
const readPage = await readSessionMessagesWithStatsAsync(readScope, {
allowResetArchiveFallback: true,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep cursor catch-up reads bounded

When a client reconnects with afterSeq on a large active session, this reads the entire transcript and then projects the whole message array before filtering down to the requested cursor window. The transcript index cache is keyed by file mtime/size, so every append invalidates it; a normal reconnect that missed only one new row still reparses/projects all prior history, which can stall the new mobile catch-up path that is meant to fetch only missed rows. The cursor path should read a bounded indexed window plus the needed projection context instead of making each catch-up proportional to full session size.

Useful? React with 👍 / 👎.

@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch from c9a5ce2 to eb669c2 Compare July 5, 2026 12:34
steipete added 4 commits July 5, 2026 08:50
… pages

The default (no offset/afterSeq) chat.history path numbered __openclaw.seq
within its byte-bounded tail window, so clients seeding the afterSeq
reconnect cursor from a plain full fetch would start from a window-local
value and re-walk or duplicate transcript rows. Reuse the stats reader so
recent-tail rows carry the same transcript-global seq as cursor and offset
pages; the response envelope is unchanged.
@steipete
steipete force-pushed the feat/gateway-chat-history-after-seq branch from eb669c2 to 262de5b Compare July 5, 2026 12:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 262de5ba0f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread CHANGELOG.md

### Changes

- **Gateway chat reconnect recovery:** add session-scoped `chat.history` sequence cursors so mobile clients can fetch only missed projected transcript rows after reconnecting, with lossless pagination and older-Gateway fallback. (#100197, #100267)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Remove normal PR changelog entry

Root AGENTS.md says CHANGELOG.md is release-only and that release generation owns it, so this normal feature commit should not add an Unreleased entry directly. Leaving this in can conflict with the generated release notes or produce duplicate/manual release content; put the release-note context in the PR body or squash message instead.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. and removed merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Land-ready on exact head 262de5ba0f4bcc51069059a703333c4e708d08bd after rebasing onto current main.

  • chat.history now exposes a session-scoped afterSeq catch-up cursor while preserving the existing bounded ordinary-history path and full-history fallback for unsupported/imported CLI sessions.
  • Projection is evaluated over the active branch before cursor slicing, equal-sequence rows stay together, completion-restamped rows remain oldest-first, and byte trimming cannot advance beyond an unseen visible row.
  • Blacksmith Testbox proof: 142 focused Gateway tests plus the full check:changed gate passed on tbx_01kws15x4w2281ahx3aheygz6z; check:test-types passed on tbx_01kws3wkwaazbm6x4jwbc2k8r2; 80/80 SessionHistorySseState tests passed on tbx_01kws497emxyxttg9m81sthvq9.
  • Source-blind API behavior validation passed 8/8 reconnect, projection-boundary, byte-budget, invalid-cursor, and imported-history scenarios on tbx_01kws220hmdgxfe3rwzf32zm8w.
  • Protocol Swift generation produced no diff, git diff --check passed, and fresh Codex autoreview was clean after every accepted fix; the final cursor-restamp adjustment was clean at 0.99 confidence.
  • Exact-head hosted CI/Testbox passed after the final current-main rebase.

Native iOS and Android consumers remain the two stacked follow-ups; both have clean client-specific autoreviews against this exact Gateway contract.

@steipete

steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #100277.

The Gateway already ships the canonical reconnect snapshot needed here through chat.history.inFlightRun and sessionInfo.hasActiveRun; the TUI consumes the same active-run contract. Adding afterSeq would expand the public protocol, generated models, pagination semantics, and client state machines while solving the wrong ownership problem.

#100277 was rewritten against the existing contract. It restores active-run ownership client-side across bootstrap, foreground resume, sequence gaps, post-send retries, completion refreshes, session changes, and agent/global-session routing. The rewritten exact head has 128 focused Swift tests passing, a macOS package build, clean SwiftFormat, direct Gateway/Codex contract review, and a clean final autoreview.

Closing this alternate protocol path so the cluster has one canonical fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: web-ui App: web-ui docs Improvements or additions to documentation gateway Gateway runtime maintainer Maintainer-authored PR merge-risk: 🚨 availability 🚨 May cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. scripts Repository scripts size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant