[Bug]: Finished or input-waiting threads stay stuck in the mobile Working shelf#24901
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/mobile
Steps to reproduce
On the current Android nightly (Working shelf beta on):
- Start a thread so it appears in the Working shelf.
- Let the run finish, or reach a point where the agent asks for input (approval or user input).
- Watch the Home list.
Also reproducible by switching to another app and back while a run finishes.
Expected behavior
A thread that stops working, or that starts waiting on approval/user input, moves out of the Working shelf into the normal visible section right away (input-requesting threads immediately, finished threads after the 2s grace from #24760).
Actual behavior
The thread stays in the Working shelf indefinitely, still shown as working. Collapsing/expanding the shelf, or anything that rebuilds the list, unsticks it. Once stuck it stays stuck because no further events arrive for that thread, so nothing re-renders the list.
Impact
Minor bug or occasional failure
Version or commit
Regression window: 0.1.3-nightly.20261024.3643 (fine) -> 0.1.3-nightly.20261025.3655 and 3669 (stuck). Introduced by #24760 (242d00c), likely interacting with the render-skipping from #24646 (62eb35b).
Environment
Android app (internal APK, versionName 2.1.0 build 464) on Android 15, connected to a remote T3 server on Linux.
Logs or stack traces
No crash; this is a client state bug. Reading the code: createInboxReturnTracker (packages/client-runtime/src/state/threadInbox.ts) only marks a thread as exited during observe(), and observe() re-runs from useThreadListV2 only when the threads array identity changes or the tracker version bumps. After a run's last shell update the array identity stops changing. When the grace timer fires it bumps the version and observe() re-runs, but with the same stale threads closure, so isThreadWorking on the stale shell (runtime still "running") returns true again and re-affirms working: true with no deadline. The exit is reverted and no further timer is armed, so the thread never leaves the shelf. navigationThreadShellsAtom (packages/client-runtime/src/state/threadShell.ts) returning the previous array when arrayElementsEqual contributes to the stable identity.
Workaround
Collapsing and re-expanding the Working shelf (or switching tabs) forces a rebuild and unsticks the rows.