You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(mobile): Back from a PR opened in a chat returns to the chat on Android - #27653
On Android, opening a PR from a chat (or a chat from a PR, or one stacked PR from another) replaced the whole stack, so Back landed on a list instead of the page you came from, and the next Back left the app. iOS already pushes these pages.
Cause and fix
Link callers took an Android-only select branch (useOpenWorkspaceDetail, and one in useNavigateToPullRequest), which replaces the stack and switches the list tab. Per Selecting versus drilling in, opening a page from another page is a drill-in, which pushes so Back returns. On top of that, PR and chat pages selected their own tab whenever they gained focus, and Back reset straight to the list.
open PR/chat/stacked-PR link
- android: select (replace stack, select tab)+ push (same as iOS)
PR/chat page focus
- select "pullRequests" | "threads"
Back (toolbar or system)
- reset to list unless a distinct thread is below+ go to the previous page, skipping duplicate copies of the same thread+ nothing below: reset to list
app cold-starts on a page (outside link)
+ start on that page's list
List rows still select. The list tab now changes only when you tap a tab or a list row, so Back from a page returns to the list you came from.
Evidence
Android 16 emulator, system Back.
Chats → chat → PR link → Back → Back
Before: Back from the PR skips the chat and lands on the Pulls list.
After: Back returns to the chat, then to the Chats list.
Pulls → PR → Work on PR → Back → Back
Before: Back from the new chat skips the PR and lands on the Chats list.
After: Back returns to the PR, then to the Pulls list with Pulls still selected.
The GIFs predate the rebase. On the rebased branch, both paths give the same results with system Back and with the toolbar back arrow. Not tested on a device: stacked-PR links, because the test data has no stacked PRs, and cold-start links, because the dev client's launcher screen catches them before the app loads. Stacked PRs use the same push and Back path. If the cold-start tab weren't picked up, the list would start on Chats, as it does today.
android-workspace-navigation.test.ts, extended inside the existing Back test:
[Home, Thread, PR] → Back → [Home, Thread]. Fails on main, where it gives [Home].
[Home, T, child, child-copy] → Back → [Home, T]. Fails on main, where it gives [Home].
vp run check:changed passes.
Merge Danger
Door: two-way. It changes no data or contracts, and a revert restores the old behavior.
Blast Radius: small. Android's link and Back navigation only: iOS was already on the push path, and the shared Back hook keeps its iOS branch unchanged.
Fixed by Claude Opus 5.5 in Claude Code (T3 Code). First implementation by GPT-6.1-Sol (Codex). Reviewed by GLM-5.3 Flash; device pass partly run by DeepSeek V4.1 Flash.
Macroscope's review found this PR requires human approval — The change preserves Android chat/PR navigation history so Back returns to the originating page. It also changes cold-start PR links to select Pulls instead of Chats, requiring confirmation of that new initial-list behavior.
You can add or adjust custom eligibility rules. Learn more.
No actionable comments were generated in the recent review.
Walkthrough
Android workspace tabs now derive from navigation routes. Pull-request and thread links push routes onto the navigation stack. Android Back uses route history to return to a prior page or the workspace list.
Changes: Android workspace navigation
Layer / File(s)
Summary
Derive and initialize workspace tabs apps/mobile/src/features/layout/workspace/workspace-tabs-state.ts, apps/mobile/src/features/layout/workspace/WorkspaceTabsContext.tsx, apps/mobile/src/features/layout/workspace/AndroidWorkspaceTabsProvider.tsx, apps/mobile/src/features/layout/AdaptiveWorkspaceLayout.tsx
workspaceTabOf maps route names to workspace tabs. The Android provider initializes tab state from the first non-Home route, and detail selection uses the same mapping.
Push pull-request and thread routes apps/mobile/src/features/pull-requests/PullRequestStackCard.tsx, apps/mobile/src/features/pull-requests/usePullRequestThreads.ts, apps/mobile/src/native/useOpenPullRequest.ts
Pull-request and thread navigation dispatches stack pushes. Pull-request opening uses stack push or replace navigation.
Navigate Back using route history apps/mobile/src/lib/android-workspace-navigation.ts, apps/mobile/src/features/layout/workspace/useAndroidWorkspaceNavigation.ts, apps/mobile/src/features/pull-requests/PullRequestRouteScreen.tsx, apps/mobile/src/features/threads/*, apps/mobile/src/lib/android-workspace-navigation.test.ts
Android Back selects a prior route, skips matching parent-thread entries when needed, and returns to the workspace list when no target exists. Back-navigation hooks no longer take a tab argument. Tests cover pull-request and thread route history.
sequenceDiagram
actor User
participant PullRequestLink
participant NavigationStack
participant AndroidBack
User->>PullRequestLink: Open pull request from thread
PullRequestLink->>NavigationStack: Push PullRequest route
User->>AndroidBack: Press Back
AndroidBack->>NavigationStack: Find prior route and navigate back
pingdotgg/t3code#27050: Changes the same Android link-opening paths and Back-stack behavior.
pingdotgg/t3code#31310: Changes the same pull-request and thread entry points to use workspace detail selection instead of route pushes.
pingdotgg/t3code#18839: Addresses the same Android chat and pull-request Back-stack behavior with changes to overlapping navigation paths.
Suggested labels:bugfix
Suggested reviewers:t3dotgg, pixpmusic
Merge Risk: Minimal · up to 50711
The change makes Android links push destinations onto the stack and makes Back return to the prior page. No actionable merge-blocking risk was found; stacked-PR links and cold-start links remain untested by the author.
Pre-merge checks: 4
Check name
Status
Explanation
Title check
The title names the main change: Android back navigation from a PR opened in a chat now returns to the chat. It follows the conventional commit format and matches the linked issue #24753 and the chang…
Description check
The description follows the template well. It has a Problem section with the Android stack-replacement behavior, a Change section that explains the push-based fix and the removal of focus-time tab sel…
Linked Issues check
Issue [#24753] requires that on Android, Back from a pull request opened in a thread returns to that thread, not the Pull Requests list. The whole-PR summary (merge base d90ac5c to head 50711ed) shows…
Out of Scope Changes check
The changed files support the Android navigation behavior in [#24753] and the closely related Back and link paths. They do not add unrelated functionality:
- Link and Back paths: `useOpenPullRequest.…
Full details: Title check
Explanation
The title names the main change: Android back navigation from a PR opened in a chat now returns to the chat. It follows the conventional commit format and matches the linked issue #24753 and the changeset, which pushes linked pages onto the stack.
Full details: Description check
Explanation
The description follows the template well. It has a Problem section with the Android stack-replacement behavior, a Change section that explains the push-based fix and the removal of focus-time tab selection, a Scope section that links issue #24753 and explains the drill-in rule, and a Verification section with before/after GIFs, the two unit-test cases, and the check command. The Merge Danger block is extra but harmless. Minor gaps: the stacked-PR and cold-start paths were not device-tested, and the author disclosed this. The template's single-problem rule is also met.
Full details: Linked Issues check
Explanation
Issue [#24753] requires that on Android, Back from a pull request opened in a thread returns to that thread, not the Pull Requests list. The whole-PR summary (merge base d90ac5c to head 50711ed) shows the required behavior:
useNavigateToPullRequest (apps/mobile/src/native/useOpenPullRequest.ts) no longer takes the Android-only select branch. It pushes a PullRequest route unless replace is set. This keeps the thread in the stack.
PullRequestStackCard and usePullRequestThreads open destinations with StackActions.push. This applies the same push path to stacked-PR and PR-to-thread links.
androidWorkspaceBackTarget (apps/mobile/src/lib/android-workspace-navigation.ts) returns to the preceding page. It skips duplicate copies of the same thread. returnToAndroidWorkspaceList calls goBack for the immediate previous route, or resets to the list when no page is below.
android-workspace-navigation.test.ts covers [Home, Thread, PR] returning to [Home, Thread]. The test is an existing Back test that was extended for this case.
The PR description also reports Android 16 emulator runs for the chat-to-PR path. The commenter reports the same result on head 2afaf60 with a real dev server. The objectives do not change the issue requirement. Remaining untested paths (stacked-PR links, cold-start external links, iOS) are outside the Android thread-to-PR Back requirement, or are not verified by the evidence. This does not block the PASS for the linked requirement.
Full details: Out of Scope Changes check
Explanation
The changed files support the Android navigation behavior in [#24753] and the closely related Back and link paths. They do not add unrelated functionality:
Link and Back paths: useOpenPullRequest.ts, PullRequestStackCard.tsx, usePullRequestThreads.ts, android-workspace-navigation.ts, useAndroidWorkspaceNavigation.ts. These change how Android opens and returns from pages, which is the bug.
Tab selection: workspaceTabOf, initialTab in WorkspaceTabsProvider, AndroidWorkspaceTabsProvider, and workspace-tabs-state.ts. Focus no longer selects the tab. A cold start on a page uses that page's list. These follow from the Back result. The list tab must match the page the user returns to.
Call-site updates: PullRequestRouteScreen, ThreadHeader, ThreadRouteScreen, NewTaskDraftScreen, NewTaskDraftRouteScreen. These drop the tab argument from back-navigation hooks, which the hook signature change requires.
Tests: android-workspace-navigation.test.ts covers the Back behavior.
The iOS back path is unchanged. The PR description says the shared hook keeps its iOS branch. The broader tab-focus and cold-start changes go beyond the single PR-from-thread case in the issue. They are still part of the same Android navigation mechanism and are described in the PR. They are not unrelated changes.
Finishing Touches
Generate unit tests (beta)
Create a new PR
Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.
…ndroid
Android opened PR, chat and stacked-PR links by replacing the workspace
stack, and PR/chat pages switched the list tab when focused, so Back
landed on the PR list. Links now push like on iOS, Back follows history
(skipping duplicate thread copies), and the tab only changes on explicit
tab or list selection.
Fixespingdotgg#24753
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The tab is no longer selected when a page gains focus, so a cold-start
link straight into a PR left the list on Chats. Seed the starting tab
from the first page in the launch stack, reusing the page-to-tab mapping
list selection already uses.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Verified on Android emulator (API 35) against a real dev server
verified head 2afaf60e9ac9aafc2c3dd3545e05ab192e7cbf0b on the t3 android emulator with the cached native dev client, metro serving the pr checkout, and an isolated dev server on port 13773. registered a real project and completed two real codex gpt-6.1-sol turns through that server. no mocks or demo data.
chats → real chat → assistant's pr link → system back returns to the same chat → back returns to chats with chats selected.
repeated the same path with the toolbar back arrow.
pr → work on pr opens its draft → back returns to the pr → back returns to the originating chat.
opened the second completed codex chat and returned to chats.
reproduced the original failure using github/main at 61cb845d9699d0ecce5a9b660d3b32907914df8b, the same native client, server, project, and chat: back from the pr skips the chat and returns to pulls. switched back to the pr checkout and verified the corrected path again.
before, back lands on pulls:
after, back returns to the originating chat:
recording of chat → pr → back → chat → back → chats:
no code changes were needed. the current head has 30 successful ci checks, with none failing or pending.
Not verified
ios cannot run on this linux vm. stacked-pr links, cold-start external links, duplicate-thread git-confirmation routes, opening an existing linked thread from a pr, and sending a new turn from the work-on-pr draft were not exercised.
Android API 36, light theme, default scale. Pixel 9: 1080x2424 portrait; Pixel Tablet: 2560x1600 landscape; Pixel 9 Pro Fold: unfolded 2076x2152. Each side used its exact commit, separate Metro/backend and fresh database with identical synthetic RPC fixtures. Mobile navigation code was unmodified.
Steps: Chats > Search navigation > linked PR > Back twice, using system and toolbar Back. Pulls > PR > Continue thread > Back twice. Remove the synthetic chat link identically, then repeat with Work on PR and an unsent draft. Open another stack layer and Back twice. Cold-launch PR/chat deep links and Back. On tablet, repeat chat navigation with Files open.
Android screenrecord sometimes omits an unchanged final frame. Supplementary endpoints were checked against identical screenshots at least 500 ms apart:
The primary Chats list pair has the same single visited row and no Done badges. Clocks and relative ages differ; repeated Work-on-PR attempts can leave unsent local drafts. Cold-start loading banners are redacted until the page renders; navigation and results remain visible. Every selected capture was opened and inspected.
- Mobile's ephemeral-ended screen calls useWorkspaceBackNavigation() without
the argument upstream pingdotgg#27653 dropped.
- ThreadLaunchService.fork.test provides the orchestrator layer, which now
supplies the EventSinkV2 the launch service needs.
- Upstream pingdotgg#28822 lets ACP registry agents compact through their advertised
/compact, so the fork's supportsCompaction flag goes; the fork test
advertises compact like upstream's mock agent.
- status.fork.test gives each OMP RPC launch its own pipes, since status now
also lists models with --no-extensions (pingdotgg#24110).
github-actionsBot
added a commit
to omarcresp/t3code-flake
that referenced
this pull request
Nov 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
size:L100-499 changed lines (additions + deletions).vouch:unvouchedAuthor is not yet trusted in the VOUCHED list.
3 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes https://git.cafe/pingdotgg/t3code/issues/24753. Replaces https://git.cafe/pingdotgg/t3code/pulls/27050, which was closed for missing before/after captures; those are below. Rebased onto current
main. First-send behavior is untouched; only links and Back change.Problem
On Android, opening a PR from a chat (or a chat from a PR, or one stacked PR from another) replaced the whole stack, so Back landed on a list instead of the page you came from, and the next Back left the app. iOS already pushes these pages.
Cause and fix
Link callers took an Android-only select branch (
useOpenWorkspaceDetail, and one inuseNavigateToPullRequest), which replaces the stack and switches the list tab. Per Selecting versus drilling in, opening a page from another page is a drill-in, which pushes so Back returns. On top of that, PR and chat pages selected their own tab whenever they gained focus, and Back reset straight to the list.List rows still select. The list tab now changes only when you tap a tab or a list row, so Back from a page returns to the list you came from.
Evidence
Android 16 emulator, system Back.
Chats → chat → PR link → Back → Back
Before: Back from the PR skips the chat and lands on the Pulls list.
After: Back returns to the chat, then to the Chats list.
Pulls → PR → Work on PR → Back → Back
Before: Back from the new chat skips the PR and lands on the Chats list.
After: Back returns to the PR, then to the Pulls list with Pulls still selected.
The GIFs predate the rebase. On the rebased branch, both paths give the same results with system Back and with the toolbar back arrow. Not tested on a device: stacked-PR links, because the test data has no stacked PRs, and cold-start links, because the dev client's launcher screen catches them before the app loads. Stacked PRs use the same push and Back path. If the cold-start tab weren't picked up, the list would start on Chats, as it does today.
android-workspace-navigation.test.ts, extended inside the existing Back test:[Home, Thread, PR]→ Back →[Home, Thread]. Fails onmain, where it gives[Home].[Home, T, child, child-copy]→ Back →[Home, T]. Fails onmain, where it gives[Home].vp run check:changedpasses.Merge Danger
Door: two-way. It changes no data or contracts, and a revert restores the old behavior.
Blast Radius: small. Android's link and Back navigation only: iOS was already on the push path, and the shared Back hook keeps its iOS branch unchanged.
Fixed by Claude Opus 5.5 in Claude Code (T3 Code). First implementation by GPT-6.1-Sol (Codex). Reviewed by GLM-5.3 Flash; device pass partly run by DeepSeek V4.1 Flash.
🤖 Generated with Claude Code
Fixes #24753