Skip to content

Fix complete chat transcript paging across ADE clients - #926

Merged
arul28 merged 4 commits into
mainfrom
ade/mobile-app-when-us-scroll-504aae84
Jul 28, 2026
Merged

Fix complete chat transcript paging across ADE clients#926
arul28 merged 4 commits into
mainfrom
ade/mobile-app-when-us-scroll-504aae84

Conversation

@arul28

@arul28 arul28 commented Jul 28, 2026

Copy link
Copy Markdown
Owner

Summary

  • make desktop and web chat history cache-first, byte-bounded, continuously pageable, and retryable without losing the side timeline rail
  • make iOS scrollback automatic and subscription-scoped, remove the transcript-top subagent roster, and keep the full roster in Chat Info
  • add scoped chat history transport for local, remote, personal, and cross-project sessions without booting foreign runtimes
  • make ade code TUI scrollback cache-first with a bounded sliding window and authoritative return-to-latest behavior

Validation

  • quality dual review: clean after 11 fixes and 2 re-review passes
  • desktop affected tests: 556 passed
  • sync and RPC tests: 294 passed
  • TUI tests: 1,020 passed
  • desktop lint: 0 errors
  • desktop and CLI builds: passed
  • docs validation: 202 files passed
  • Swift frontend parse: passed
  • iOS xcodebuild and XCTest not run because the root filesystem has 20 GiB free, below the repository 30 GiB safety gate

Research

The design follows bounded cursor paging and stable-list lessons from SQLite scrolling windows, TanStack Virtual, Legend List, and the T3 Code cache-first snapshot and resume flow while avoiding T3 Code mobile full-thread blob loading.

Open this PR in ADE

Summary by CodeRabbit

  • New Features

    • Added paginated chat history loading across desktop, CLI, sync, and iOS experiences.
    • Added “load earlier messages” controls, loading states, retry actions, and history availability indicators.
    • Added chat minimap support for navigating and fetching earlier messages.
    • Improved history handling when switching chats or viewing detached sessions.
  • Bug Fixes

    • Prevented chat history requests from being routed to the wrong session or machine.
    • Improved recovery when older history is temporarily unavailable.
  • Style

    • Simplified the iOS chat timeline by removing the subagent activity strip.

@vercel

vercel Bot commented Jul 28, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Jul 28, 2026 12:04pm

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@arul28, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 35 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 03b5da0f-2464-4384-a18b-7f2916102bd2

📥 Commits

Reviewing files that changed from the base of the PR and between 4ae3931 and 5794876.

📒 Files selected for processing (8)
  • apps/ade-cli/src/services/sync/brainProjectActionsSyncHandler.ts
  • apps/ade-cli/src/services/sync/syncHostService.test.ts
  • apps/ade-cli/src/services/sync/syncHostService.ts
  • apps/ios/ADE/Services/SyncService.swift
  • apps/ios/ADE/Views/Work/WorkChatSessionView+Actions.swift
  • apps/ios/ADE/Views/Work/WorkChatSessionView.swift
  • apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift
  • apps/ios/ADETests/ADETests.swift
📝 Walkthrough

Walkthrough

ADE adds byte-cursor chat history paging across RPC and sync protocols, desktop and TUI clients, and iOS chat views. The changes add scoped history actions, subscription cursor metadata, bounded page retrieval, detached-history handling, retry states, and older-history UI coverage.

Changes

Chat history protocol and host paging

Layer / File(s) Summary
Protocol, authorization, and sync host paging
apps/ade-cli/src/adeRpcServer*, apps/ade-cli/src/services/sync/*, apps/desktop/src/shared/types/sync.ts
Chat history actions are session-scoped, sync envelopes carry byte-cursor metadata, and hosts validate and serve chat_history pages for local and foreign sessions. Tests cover authorization, scope mismatches, unavailable pages, and snapshot cursors.

Desktop history routing

Layer / File(s) Summary
Desktop history limits and routing
apps/desktop/src/main/services/ipc/*, apps/desktop/src/preload/*, apps/desktop/src/renderer/components/chat/*, apps/desktop/src/renderer/webclient/adapter/*
Desktop history APIs forward maxBytes, select compatible paging commands, pin requests to the rendered session, and expose a minimap continuation control.

TUI scrollback

Layer / File(s) Summary
TUI detached history and scrollback
apps/ade-cli/src/tuiClient/*
TUI scrollback uses bounded byte/event history, detached live-event buffers, sliding windows, retryable error states, cursor guards, and updated older-history indicators.

iOS sync and views

Layer / File(s) Summary
iOS sync cursors and paging
apps/ios/ADE/Services/SyncService.swift, apps/ios/ADE/Models/RemoteModels.swift, apps/ios/ADETests/ADETests.swift
iOS decodes subscription cursor metadata, tracks per-session cursors, gates paging by host capability, and sends chat_history requests for supported subscriptions.
iOS older-history UI and loading
apps/ios/ADE/Views/Work/*
Timeline loading now uses guarded async requests, retry/error states, cursor validation, visibility budgeting, and top-position scroll triggers; the subagent strip view is removed.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • arul28/ADE#431: Updates the same desktop event-history IPC handler with related argument forwarding and service handling.
  • arul28/ADE#555: Adds the paged chat-history handler consumed by this sync and client flow.
  • arul28/ADE#676: Extends the same ADE RPC chat-action authorization and session-scoping logic.

Suggested labels: desktop, ios, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing chat transcript/history paging across ADE clients.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/mobile-app-when-us-scroll-504aae84

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@arul28 arul28 changed the title chat-transcript-loading-fixes -> Primary Fix complete chat transcript paging across ADE clients Jul 28, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (2)
apps/ios/ADETests/ADETests.swift (1)

13498-13531: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider adding a forward-cursor regression case.

workChatOlderTranscriptPageAdvances is covered for nextCursor < beforeOffset (advances), == beforeOffset (stalls), nil (exhausted), and -1 (invalid), but not for a cursor that moves the wrong way (nextCursor > beforeOffset), e.g. a misbehaving host returning a cursor further forward than the page just fetched. That's the same infinite-loop failure mode the -1 and stall cases already guard against.

♻️ Suggested additional assertion
     XCTAssertFalse(workChatOlderTranscriptPageAdvances(
       beforeOffset: 4_096,
       nextCursor: -1
     ))
+    XCTAssertFalse(workChatOlderTranscriptPageAdvances(
+      beforeOffset: 4_096,
+      nextCursor: 8_192
+    ))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ios/ADETests/ADETests.swift` around lines 13498 - 13531, Add a
regression assertion in testMobileHistoryRoutingRequiresScopedProgressingCursors
verifying workChatOlderTranscriptPageAdvances returns false when nextCursor is
greater than beforeOffset, such as beforeOffset 4,096 and nextCursor 8,192. Keep
the existing advancing, exhausted, stalled, and negative-cursor cases unchanged.
apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift (1)

2229-2236: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse workChatOlderTranscriptPageAdvances instead of reimplementing the advance check.

This guard duplicates exactly the rule already encoded (and unit-tested via testMobileHistoryRoutingRequiresScopedProgressingCursors) in workChatOlderTranscriptPageAdvances, which loadOlderTranscriptEntries already calls a few lines above for the canonical-fallback path. Reusing it here keeps the two paging paths' cursor-progress rules from drifting apart.

♻️ Proposed refactor
-      guard page.startOffset >= 0, page.startOffset < cursor else {
-        return .failed
-      }
+      guard workChatOlderTranscriptPageAdvances(beforeOffset: cursor, nextCursor: page.startOffset) else {
+        return .failed
+      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift` around lines 2229 -
2236, In the loaded-page validation within loadOlderTranscriptEntries, replace
the duplicated page.startOffset range guard with the existing
workChatOlderTranscriptPageAdvances helper. Preserve the current .failed result
for invalid or non-progressing cursor advances and keep the surrounding
sessionFound handling unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/ade-cli/src/services/sync/brainProjectActionsSyncHandler.ts`:
- Around line 913-921: Update the chat history paging handler around
personalChatScope.call and normalizeChatHistoryPage to log failures in the catch
block using the existing sync.chat_history_failed event and established logging
conventions from syncHostService.ts or nearby handlers, while preserving the
unavailableChatHistoryPage fallback behavior.

In `@apps/ade-cli/src/services/sync/syncHostService.ts`:
- Around line 7646-7663: Update the chat_history scope resolution near
subscribedScope and requestedScope to reuse the same local-versus-foreign
classification as chat_subscribe’s resolveForeignChatScope. Ensure
projectId/projectRootPath values matching the host produce the "project" scope,
while only genuinely foreign projects produce "foreign-project", so the scope
comparison remains consistent across subscribe, unsubscribe, and history paging.

In `@apps/ios/ADE/Services/SyncService.swift`:
- Line 2751: Update the chat_history pagination flow in SyncService and its
chatHistoryCursorBySession state so each validated page stores startOffset when
hasMore is true, or clears the cursor to 0 when history is complete; leave the
existing cursor unchanged for unavailable or invalid pages. Add a regression
test covering page fetch, live event synchronization via
WorkSessionDestinationView.syncTranscriptFromLiveEvents, and the subsequent page
request to verify the cursor advances and no page repeats.

In `@apps/ios/ADE/Views/Work/WorkChatSessionView.swift`:
- Around line 1118-1122: Update the .onDisappear handler in WorkChatSessionView
to reset olderHistoryLoadInFlight and olderHistoryLoadError after cancelling and
clearing olderHistoryLoadTask, matching the four-field reset behavior in
resetScrollStateForCurrentSession and resetTimelineSourceIfNeeded. Preserve the
existing timeline snapshot cancellation.

---

Nitpick comments:
In `@apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift`:
- Around line 2229-2236: In the loaded-page validation within
loadOlderTranscriptEntries, replace the duplicated page.startOffset range guard
with the existing workChatOlderTranscriptPageAdvances helper. Preserve the
current .failed result for invalid or non-progressing cursor advances and keep
the surrounding sessionFound handling unchanged.

In `@apps/ios/ADETests/ADETests.swift`:
- Around line 13498-13531: Add a regression assertion in
testMobileHistoryRoutingRequiresScopedProgressingCursors verifying
workChatOlderTranscriptPageAdvances returns false when nextCursor is greater
than beforeOffset, such as beforeOffset 4,096 and nextCursor 8,192. Keep the
existing advancing, exhausted, stalled, and negative-cursor cases unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a6b50780-0ea8-46a8-9187-f4377daf2d48

📥 Commits

Reviewing files that changed from the base of the PR and between 7a87abc and 4ae3931.

⛔ Files ignored due to path filters (7)
  • docs/ARCHITECTURE.md is excluded by !docs/**
  • docs/features/ade-code/README.md is excluded by !docs/**
  • docs/features/chat/composer-and-ui.md is excluded by !docs/**
  • docs/features/chat/transcript-and-turns.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/ios-companion.md is excluded by !docs/**
  • docs/features/web-client/README.md is excluded by !docs/**
📒 Files selected for processing (32)
  • apps/ade-cli/src/adeRpcServer.test.ts
  • apps/ade-cli/src/adeRpcServer.ts
  • apps/ade-cli/src/services/sync/brainProjectActionsSyncHandler.ts
  • apps/ade-cli/src/services/sync/syncHostService.test.ts
  • apps/ade-cli/src/services/sync/syncHostService.ts
  • apps/ade-cli/src/tuiClient/__tests__/ChatView.test.tsx
  • apps/ade-cli/src/tuiClient/__tests__/olderHistory.test.ts
  • apps/ade-cli/src/tuiClient/adeApi.ts
  • apps/ade-cli/src/tuiClient/app.tsx
  • apps/ade-cli/src/tuiClient/components/ChatView.tsx
  • apps/ade-cli/src/tuiClient/olderHistory.ts
  • apps/desktop/src/main/services/ipc/registerIpc.ts
  • apps/desktop/src/main/services/ipc/runtimeBridge.test.ts
  • apps/desktop/src/preload/global.d.ts
  • apps/desktop/src/preload/preload.test.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/components/chat/AgentChatMessageList.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.test.tsx
  • apps/desktop/src/renderer/components/chat/AgentChatPane.tsx
  • apps/desktop/src/renderer/components/chat/ChatUserMinimap.test.tsx
  • apps/desktop/src/renderer/components/chat/ChatUserMinimap.tsx
  • apps/desktop/src/renderer/webclient/adapter/__tests__/adapter.test.ts
  • apps/desktop/src/renderer/webclient/adapter/agentChat.ts
  • apps/desktop/src/shared/types/sync.ts
  • apps/ios/ADE/Models/RemoteModels.swift
  • apps/ios/ADE/Services/SyncService.swift
  • apps/ios/ADE/Views/Work/WorkChatRichCardViews.swift
  • apps/ios/ADE/Views/Work/WorkChatSessionView+Actions.swift
  • apps/ios/ADE/Views/Work/WorkChatSessionView.swift
  • apps/ios/ADE/Views/Work/WorkSessionDestinationView.swift
  • apps/ios/ADE/Views/Work/WorkTimelineHelpers.swift
  • apps/ios/ADETests/ADETests.swift

Comment thread apps/ade-cli/src/services/sync/brainProjectActionsSyncHandler.ts Outdated
Comment thread apps/ade-cli/src/services/sync/syncHostService.ts Outdated
Comment thread apps/ios/ADE/Services/SyncService.swift
Comment thread apps/ios/ADE/Views/Work/WorkChatSessionView.swift
@arul28

arul28 commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

@codex review

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

Copy link
Copy Markdown

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: 9336681608

ℹ️ 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 +7681 to +7685
const subscribedScope = peer.chatSubscriptionScopes.get(sessionId);
const requestedScope = requestedChatSubscriptionScope(payload);
if (
!peer.subscribedChatSessionIds.has(sessionId)
|| subscribedScope !== requestedScope

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Match history requests to the exact subscribed project

For foreign-project subscriptions, this comparison only checks the coarse "foreign-project" category. If two projects contain the same session ID, a peer subscribed to project A can send a chat_history request scoped to project B and pass this gate; the response is then read from project A's stored resolvedChatTranscriptPaths entry. Track and compare the exact project/root scope so stale or colliding cross-project requests cannot return another project's transcript.

Useful? React with 👍 / 👎.

truncated: boolean;
tailStartOffset: number;
}> {
const size = await readHistoryFileSize(transcriptPath);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Return an empty snapshot when the transcript file is absent

When a registered foreign chat has not created its transcript yet, createForeignChatTranscriptResolver intentionally returns its confined candidate path even if it does not exist. Removing the previous catch means readHistoryFileSize now rejects in that normal state (and when a transcript disappears during a race); the outer message queue only logs the error and sends no chat_subscribe response, leaving the client waiting for a timeout instead of receiving the former empty snapshot. Preserve the empty-snapshot fallback for filesystem-not-found/read failures while still propagating cancellation.

Useful? React with 👍 / 👎.

@arul28

arul28 commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

@codex review

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

Copy link
Copy Markdown

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: 7e9c577d60

ℹ️ 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 +1043 to +1044
if topY < -workChatOlderHistoryRearmDistance {
olderHistoryTriggerArmed = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Re-arm pagination when the content remains shorter than the viewport

When the first automatic request adds too little visible content to move topY below the 420-point re-arm threshold—for example, after a sparse page or six event pages that produce no timeline rows—olderHistoryTriggerArmed remains false after line 1054. The view has removed the normal manual load button, and a short timeline cannot be scrolled far enough to satisfy this condition, so the remaining positive history cursor becomes permanently inaccessible until the view is recreated. Re-arm after a successful page when host history remains and the content still cannot scroll away from the trigger zone.

Useful? React with 👍 / 👎.

@arul28

arul28 commented Jul 28, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 57948766fe

ℹ️ 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".

@arul28
arul28 merged commit 8e3b8e6 into main Jul 28, 2026
33 checks passed
@arul28
arul28 deleted the ade/mobile-app-when-us-scroll-504aae84 branch July 28, 2026 12:19
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