fix(mobile): return finished threads from the Working shelf#25398
Problem
A completed thread can remain in the mobile Working shelf after its two-second grace period. Reproduce by starting a run, keeping Home visible while it finishes, and leaving the list untouched: the row reads Done but stays under Working until a later list rebuild.
Change
Pass the inbox tracker version into the memoized observation so React Compiler includes it in the cache key. The timer notification now refreshes shelf placement. The tracker accepts an optional version argument; existing callers and grace/attention rules retain their behavior.
Scope and approval
Fixes https://github.com/pingdotgg/t3code/issues/24901
Triaged bug via the automated issue flow. GitCafe: #24901. This restores the existing completion behavior without adding settings, persisted state, or protocol changes.
Verification
- Red first: the new Metro compiler regression test failed on main because the observation cache guard omitted
inboxVersion; it passes with the fix. vp run check:changed: passed formatting, lint, both knip checks, all seven affected-package typechecks, and 980 tests across compiler coverage and inbox tracking. The final rerun confirmed the cached passing result with exit 0.- Independent GPT-6.1-Sol and Claude Opus 5.5 code reviews returned MERGE with no findings.
- Real Android development clients, React Compiler enabled, remote connection to an isolated server using explicit
--home-dir. Native fingerprint0328f4ec326e7e4bf1bf87625118f3ff2f7a18d7; no release-build claim.
Evidence
Proof audit and independent rebuild addendum found the Android proof sufficient. The independent head phone run repeated the automatic return; its settled frame differs by 2,746 pixels (0.105%) in clock, cellular indicator, and the older control's later status label. Independent recording, rebuild script, and transcript are public. Cold-start blank UI and local persistence warnings were observed during setup; the verified transition used a loaded, live connection.
Fixture matrix, full evidence index and capture recipe, server completion transcript, diff generator, and compiler reproduction helper.
For each recording, send Run sleep 30 in shell then reply Done. Do not edit files., observe the thread working, then leave the list visible across completion and grace without tapping or navigating. Exact UTC milestones, raw recordings, narrated derivatives, scripts, and device details are in the index.
| Android phone Home, Pixel 9 portrait, light, 1080×2424 captured pixels | Before | After | Diff0 | DiffT |
|---|---|---|---|---|
| Completed target returns above the idle control; empty Working header disappears | Before recording bfc7177f | After recording d3de380d | Zero-threshold absolute difference amplified 8 times | Pixels whose per-channel difference exceeds 16 of 255 |
Android tablet sidebar, Pixel Tablet landscape, light, 2560×1600 captured pixels: head recording. The collapsed shelf retains the selected target during work, then returns it automatically and removes the zero-count header. The final reselection recording ends with the conversation still loading; loaded content and identity after that action are supported by the linked accessibility transcript, not by a settled final video frame.
What else changed in the captures: wall clock/status-bar indicators differ, the target has one additional real turn at head, and the client/Metro restarted between revisions. Intended visible differences are shelf removal and fresh return ordering. No style change or pixel-identical claim is made. Android stops encoding a static tail: the base recording covers the running-to-Done transition, while the linked later unmodified still and persisted completion show it remained stuck 31 seconds after completion.
Unverified: native iOS tablet sidebar (A3). Its cached client installed, but pool orientation/launch/snapshot operations repeatedly timed out. No iOS runtime pass is claimed. Unchanged attention, placement, and continuation rules remain covered by existing tracker tests; no broader provider or transport sweep was performed.
Models and harnesses: Claude Opus 5.5 through Claude Code; GPT-6.1-Sol through Codex in T3 Code.
Checks
Added 3 commits
Approvability
Verdict: Approved at d3de380
Macroscope's review found this PR approvable — This is a narrowly scoped mobile bug fix that reconnects the existing inbox timer notification to the memoized thread-list calculation, so finished threads leave the Working shelf after the established grace period. The accompanying compiler regression test verifies the dependency, with no product-default, schema, or deployment changes.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review.
External image Recent review info
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: fix/issue-24901
- File: .coderabbit.config.ts
- Commit: d3de380
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
a5774e2d-b01d-4999-b1cd-53e93f6c80d1
External image Commits
Reviewing files that changed from the base of the PR and between d171a88fc4fa00b1ca7ce6af7854e55cc3cc88ec and d3de380d7a5f39986844467f53b2da9165e834ee.
External image Files selected for processing: 3
apps/mobile/src/features/threads/useThreadListV2.tsapps/mobile/src/reactCompilerCoverage.test.tspackages/client-runtime/src/state/threadInbox.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.
Walkthrough
The mobile thread list now passes
inboxVersionto the inbox return tracker. The tracker accepts an optional version argument, and a React Compiler coverage test checks that the compiledobservecall guard includesinboxVersion.Changes: Mobile inbox observation
Layer / File(s) Summary Version-aware tracker observation
packages/client-runtime/src/state/threadInbox.ts,apps/mobile/src/features/threads/useThreadListV2.ts,apps/mobile/src/reactCompilerCoverage.test.tsThe tracker’s observemethod accepts an optional version.useThreadListV2passesinboxVersion, and a compiler coverage test checks that the call guard includes it.Priority: External image Normal
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Low
Possibly related PRs
- pingdotgg/t3code#24907: Implements the same Working-shelf fix and includes the version argument and React Compiler coverage.
- pingdotgg/t3code#24760: Introduced the grace period and tracker notifications consumed by this change.
- pingdotgg/t3code#24646: Introduced
useThreadListV2and the inbox observation contract updated here.
Suggested labels:
bugfix,size:SSuggested reviewers:
t3dotgg
Merge Risk: External image Minimal · up to d3de3
No actionable merge-blocking issue is established for this change; it is ready for normal merge checks.
Pre-merge checks: Passed 3 · Failed 1
Failed Failed checks: 1 warning
Check name Status Explanation Resolution Linked Issues check Warning Issue #24901requires a finished thread to leave the Working shelf after the two-second grace period while Home remains visible. The change invalidates the memo wheninboxVersionchanges, but `obser…Update the tracker or observation flow so a timer expiry remains authoritative when the next observation receives the unchanged stale thread snapshot. Add a runtime regression test that keeps the thread list unchanged, advances past `WORKIN… Passed Passed checks: 3 passed
Check name Status Explanation Description check Passed The description includes all required sections. It clearly explains the bug, the fix, scope and approval, focused verification, limitations, and supporting evidence. Title check Passed The title clearly and concisely describes the primary change: completed mobile threads return from the Working shelf. Out of Scope Changes check Passed The PR changes only the mobile thread-list observation, the client-runtime tracker API needed to expose the version read, and a focused React Compiler regression test. These changes directly support i… Full details: Out of Scope Changes check
Explanation
The PR changes only the mobile thread-list observation, the client-runtime tracker API needed to expose the version read, and a focused React Compiler regression test. These changes directly support issue
#24901. No unrelated settings, persistence, protocol, or provider changes are present.
Full details: Linked Issues check
Explanation
Issue
#24901requires a finished thread to leave the Working shelf after the two-second grace period while Home remains visible. The change invalidates the memo wheninboxVersionchanges, butobservethen recomputesactualfrom the suppliedthreads. The timer first sets the tracker state toworking: false, then the rerun can receive the same stale thread with an active runtime and setworkingback totrue. The added test checks only the compiled cache guard. It does not verify the finished-thread behavior with an unchanged stale thread list. The input and attention rules remain supported by the existing tracker logic, but the finished-thread requirement is not established and the shown state flow can reintroduce the reported bug.Resolution
Update the tracker or observation flow so a timer expiry remains authoritative when the next observation receives the unchanged stale thread snapshot. Add a runtime regression test that keeps the thread list unchanged, advances past
WORKING_EXIT_GRACE_MS, and verifies that the thread is no longer working and is returned to the normal section.
Finishing Touches
📝 Generate docstrings
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.