Repository navigation
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Related, not a duplicate: #12134 is about desktop collapsing traces to a generic Thought label. Julius's triage there already names this mobile path: clients that do not send reasoningMessages=true get reasoning remapped to system, and mobile then prints that text as a normal message. This report is that Android bug.
Area
apps/mobile
Steps to reproduce
- Run a current T3 server that persists provider thinking traces (feat(chat): show provider thinking traces #11784 and later).
- Open the same thread in the Android app (Play build, or any client that does not send
reasoningMessages=true, or one that resumes a pre-opt-in SQLite snapshot). - Send a prompt that produces a thinking/reasoning trace (Codex summary, Claude thinking, OpenCode, etc.).
- Compare the same turn on web/desktop.
Expected behavior
Thinking is visually distinct from the answer: a Thinking / Thought disclosure (brain icon, muted chrome), not assistant body text. The actual answer stays a regular message.
Actual behavior
On Android the remapped system traces render with the same assistant markdown as the answer. There is no Thought row. You cannot tell thinking from the reply. Web/desktop either hide system rows or show real Thought disclosures after they opt in.
This is the compatibility remap in ActivityPayloadProjection: without reasoningMessages=true, reasoning becomes system with the same id/text/sequence. Mobile ThreadFeed only special-cases role === "reasoning"; everything else that is not a user bubble is assistant markdown.
Android hits it more than iOS because:
- The Play build is often behind the server that just started sending traces, so it never opts in.
- SQLite snapshots written under the remap keep
role: "system".afterSequenceresume does not rewrite them. - Thread subscribe only opts in when
initialConfig.reasoningMessages === true. If that config is missing (orElseSucceed({})after Android suspends the socket), the client stays on the old wire format.
Impact
Major degradation or frequent failure
Version or commit
main after #11784 (052c7ae and later)
Environment
Android mobile app talking to a current T3 server.
Screenshots, recordings, or supporting files
Workaround
Use web/desktop, or an Android build that sends reasoningMessages=true and has a cache that was not written under the system-role remap.
Activity
bradhave94 commentedon Sep 16, 2026
Before, on Android: thinking traces render as regular assistant text. No Thought row.