Repository navigation
fix(mobile): a run that finishes during a resume is not marked read unseen - #28193
playcations wants to merge 1 commit into
Conversation
…nseen An open thread marked a finished run read the moment it arrived. Resuming the app on a thread, a completion that landed during the sync was marked read even if the user backed out before seeing it. Opening a synced thread still counts at once; after the app leaves the foreground or the environment syncs, the view counts again only once the thread has shown, synced and in the foreground, for two seconds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — Resumed or synchronizing mobile threads now wait two seconds before counting as read. The changed default timing and new line-level lint suppression require human review. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
View interruption and settling apps/mobile/src/features/threads/threadViewInterruption.ts, apps/mobile/src/features/threads/useSettledThreadView.ts, apps/mobile/src/features/threads/threadViewInterruption.test.ts |
The view state records interruptions. The hook returns an uninterrupted visible thread immediately and waits two seconds after visibility resumes following an interruption. Tests cover initial views, interruptions, thread changes, unchanged state, and null keys. |
Screen visit-tracking integration apps/mobile/src/features/threads/ThreadDetailScreen.tsx |
The screen passes shell synchronization status to useSettledThreadView and mounts visit tracking with the returned thread target. |
Estimated code review effort: 2 (Simple) | ~12 minutes
Sequence Diagram(s)
sequenceDiagram
participant ThreadDetailScreen
participant useSettledThreadView
participant AppState
participant ThreadVisitTracker
ThreadDetailScreen->>useSettledThreadView: Provide thread reference and shell synchronization status
useSettledThreadView->>AppState: Check whether the app is active
useSettledThreadView-->>ThreadDetailScreen: Return thread reference immediately or after settling
ThreadDetailScreen->>ThreadVisitTracker: Mount with returned thread reference
Possibly related PRs
- pingdotgg/t3code#24973: Introduced the shared thread visit tracker mounted by
ThreadDetailScreen. - pingdotgg/t3code#24783: Gated the mobile thread visit watermark on active screen state.
- pingdotgg/t3code#26261: Uses thread read and completion state to drive inbox and Live Activity presentation.
Suggested reviewers: juliusmarminge
Merge Risk: 
Minimal · up to 63699
-
The changed visit behavior has no identified merge-blocking defect. The narrowed resume behavior has not yet been tested on a device.
Pre-merge checks: 
4
-
Full details: Description check
-
Explanation
The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the reproduction steps, implementation, affected scope, focused tests, broader checks, device verification, and agent details. The scope section does not link an issue or approval comment, but it explains why this is a small, focused bug fix, so the description is sufficiently complete.
-
Finishing Touches
-
Generate unit tests (beta)
-
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
|
Note Written by Verified in a real dev environmentNo changed runtime behavior could be verified on this Linux Boat VM. I inspected the description, discussion, commits and complete diff at Device discovery returned: Not verifiedThe original bug on main, the fix on the PR head, and neighboring mobile behavior remain unverified. Native device access is disabled and no Android device is connected. The repository mobile verification workflow requires stopping when the device tools are unavailable. I did not start a dev server, install dependencies, create app data, run a provider turn, or change code. There are no runtime screenshots or recordings to attach. A native Android or iOS run is still required: start a real Codex |
Device verificationOn a physical Pixel (Android 10), I compared two release builds from the same base: Steps: open a thread while it is working, background the app, wait until the run has finished (about 70 seconds), resume the app on that thread, then back out.
One device quirk, the same on both builds: this Pixel stops presenting the app's frames after in-app navigation. I took each screenshot after a background and resume on the thread list, which doesn't change read state, and confirmed each row's state from the UI hierarchy. As a side check, the finished thread left Working on the |

Problem
On mobile, an open thread marks a finished run read the moment it arrives. When you resume the app on a thread, the sync can deliver a run that finished while the app was in the background before you've looked at it. If you back out right away, the thread is already marked read, so its Done marker is gone even though you never saw the result.
Repro: open a thread, background the app while its run is working, wait for the run to finish, then resume and back out as soon as the sync completes. The thread no longer shows Done.
Change
ThreadDetailScreenmounts the visit tracker through a smalluseSettledThreadViewhook:The rule for when a view was interrupted is a pure function in
threadViewInterruption.ts. The shared visit tracker inclient-runtimeis unchanged, so web is unaffected.Scope and approval
A small, focused mobile fix: a resumed or syncing thread screen was marking runs read before the user could see them. Opening a thread normally behaves exactly as before.
Verification
vp test run apps/mobile/src/features/threads/threadViewInterruption.test.ts: 4 tests for the interruption rule: a synced open counts at once, an open during a sync waits, and a resume or sync interrupts the view until another thread opens.vp run check:changed: format, lint, knip, typecheck, tests, and react compiler pass. I checked the compiled hook: a new view token is created whenever the thread becomes visible again, so the wait restarts after a resume even if no timer ran in the background.Implemented with Claude Opus 5.5 in Claude Code, through T3 Code.
🤖 Generated with Claude Code