fix(swift-ios): keep thread catch-up complete and visible - #9678
Conversation
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit beb19de. Configure here.
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This PR substantially changes existing iOS thread synchronization and presentation behavior, coordinating WebSocket and HTTP recovery while altering cached-content, retry, attachment, and status handling. The focused tests reduce risk, but the concurrent state-management scope and customer-visible runtime impact warrant human review. You can add or adjust custom eligibility rules. Learn more. |

Messages could go missing when they arrived during a required thread snapshot read. The follow-up read was skipped because the WebSocket was still open, and the app could label incomplete cached content as current.
Track skipped event cursors and keep fetching until the replacement covers them. Required reads start without the fixed 250 ms delay and cancel older fallback reads. Cached messages stay visible with a catch-up or failure label. Confirmed live thread data takes precedence over stale environment status.
Image, PDF, and video URL requests no longer block text recovery. Late results from an old thread or connection cannot replace current content.
Verification:
Simulator states, with the same cached content kept visible:
Based on the main SwiftUI branch. No transcript layout or scrolling changes.
Created with GPT-6 Astra (preview) in Codex.
Note
Medium Risk
Touches real-time thread streaming, snapshot/HTTP race recovery, and sync state presentation—high user-visible impact but bounded to iOS native client with strong test coverage.
Overview
Fixes thread detail sync on iOS so messages are not dropped or shown as “live” while a mandatory snapshot is still in flight.
NativeFeatureClientnow tracks when a replacement snapshot must include events that arrived without a usable cursor (detailSnapshotRequiredAfterEpoch/threadHistoryEpoch). Forced HTTP refreshes skip the 250 ms coalesce delay, cancel stale catch-up fallbacks, and surface.catchingUp; refresh failures can emit.failedwithout treating cancellation as an error. Socket snapshots from an older subscription are ignored until the required read completes; a fresher socket snapshot can supersede a held HTTP read. Trailing refreshes after coalesced work useforce: truewhen there was no base thread to reduce.refreshThreadrejects outdated snapshots (threadSnapshotOutdated) when history moved during the read, and attachment URL hydration is scheduled asynchronously for all attachments missing URLs so PDF/video/image lookups do not block text catch-up.UI (
ThreadDetailView,ThreadRefreshPresentation,FeatureRootModel): cached transcript stays visible during catch-up/retry; working timers and empty-state copy are suppressed while a refresh banner is shown;.livethread sync wins over stale environment disconnect/reconnect probes; duplicate.threadSyncvalues no longer churn observation.Adds extensive catch-up integration tests and brief user docs for thread connection status and Retry.
Reviewed by Cursor Bugbot for commit 02ba3e2. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Fix thread catch-up visibility and snapshot ordering in Swift iOS client
catching-upstate immediately, cancel stale fallback reads, force trailing reads to run without coalescing delay, and surface non-cancellation failures as failed thread-sync events instead of silently discarding them.scheduleAttachmentHydrationresolves every attachment without a URL.refreshThreadignores in-flight reads that cross an epoch change and may surfaceNativeFeatureClientError.threadSnapshotOutdatedto callers when no replacement is pending; verify callers handle this new retryable error case.Macroscope summarized 02ba3e2.