Skip to content

fix(mobile): update the iOS Git header menu when status changes - #16330

Open
juliusmarminge wants to merge 1 commit into
t3code/mobile-perf/refresh-git-after-reconnectfrom
t3code/mobile-perf/update-native-git-header
Open

juliusmarminge wants to merge 1 commit into
t3code/mobile-perf/refresh-git-after-reconnectfrom
t3code/mobile-perf/update-native-git-header

Conversation

@juliusmarminge

@juliusmarminge juliusmarminge commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

This is a separate bug from the reconnect refresh in #16329. On iOS, the thread header's Git menu kept showing an old status (for example Clean) even after the Git status refreshed. NativeStackScreenOptions stabilizes header item factories and re-applies options only when the content signature changes. ThreadHeader passed optionsVersion={projectScripts}, so a new Git status never reached the native menu.

useThreadHeaderOptions now returns optionsVersion as the memoized header items that are on screen. Those items already depend on gitStatus, branch, and quick action. On Android it returns [], because the actions there render as children. The signature still compares content, so streaming re-renders with equal items do not call setOptions. ThreadHeader moves verbatim into its own module so the test can render the production wiring. The only change is the optionsVersion line.

Before / after

Same release fixture, viewport, and synthetic 300-message thread on both bundles. Background for more than 16 s, add an untracked file, resume, open the header Git menu.

Before: parent bundle 521c10fc… (#16329 only), file added After: this fix 068d9912…, file added After: this fix, file deleted
Before: header Git menu shows master, Clean despite a changed file After: header Git menu shows master, 1 changed After: header Git menu shows master, Clean after deleting the file

Each resume issued exactly one vcs.refreshStatus on both bundles, so the before shot shows a refreshed status that never reached the native menu. Release simulator (iPhone 17 Pro, iOS 27, Hermes, no Metro). A video is not needed for a static label. Aggregate evidence: git-header-evidence.json.

Tests

useThreadHeaderOptions.test.tsx renders the real ThreadHeader → ScreenHeader → NativeStackScreenOptions; only navigation, RN, layout, appearance, and the mail toolbar are mocked.

  • Reverting to projectScripts fails the status test (Clean vs 1 changed).
  • Removing the signature guard fails the second test: 20 equivalent re-renders with fresh callbacks trigger extra setOptions.

Not claimed: CPU, battery, or latency impact; physical-device runs. Android has no native header item factories, so it is unaffected.

Opus 5.5 via Claude Code in T3 Code.

🤖 Generated with Claude Code


Devin Review

@juliusmarminge
juliusmarminge added this pull request to stack #15249 October 6, 2026 03:10
@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label Oct 6, 2026
@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 6, 2026
@github-actions github-actions Bot added the size:L 100-499 changed lines (additions + deletions). label Oct 6, 2026
@juliusmarminge
juliusmarminge marked this pull request as ready for review October 6, 2026 03:11
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ℹ️ No successful main baseline artifact is available yet. This run establishes the initial measurement.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire — 5.0 KiB — 6.8 KiB ✅
Codex Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Codex Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Codex Live turn WebSocket decoded — 20.9 KiB — 29.3 KiB ✅
Codex Live turn messages — 2 — 8 ✅
Claude Total thread wire — 5.0 KiB — 6.8 KiB ✅
Claude Thread snapshot wire — 3.8 KiB — 4.9 KiB ✅
Claude Live turn WebSocket wire — 1.2 KiB — 2.0 KiB ✅
Claude Live turn WebSocket decoded — 21.2 KiB — 29.3 KiB ✅
Claude Live turn messages — 2 — 8 ✅

Baseline: unavailable · PR result: 1e584b7 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

options,
// Header item factories are stabilized, so the native header only re-reads them when
// this version changes. Keying on the items keeps the Git menu status live.
optionsVersion: layout.usesSplitView ? threadCenterHeaderItems : compactRightHeaderItems,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 High threads/useThreadHeaderOptions.tsx:115

When gitStatus.isDefaultRef changes from false to true while the branch name and ahead count are unchanged, optionsVersion remains identical, so the native menu keeps the old onPress callback and runs push instead of commit_push, bypassing the default-branch confirmation. Include the quick-action kind/action or the relevant status fields in optionsVersion so setOptions refreshes the callback.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @apps/mobile/src/features/threads/useThreadHeaderOptions.tsx around line 115:

When `gitStatus.isDefaultRef` changes from `false` to `true` while the branch name and ahead count are unchanged, `optionsVersion` remains identical, so the native menu keeps the old `onPress` callback and runs `push` instead of `commit_push`, bypassing the default-branch confirmation. Include the quick-action kind/action or the relevant status fields in `optionsVersion` so `setOptions` refreshes the callback.

@macroscopeapp

macroscopeapp Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Would Approve

Macroscope's review found this PR approvable — This is a narrowly scoped iOS mobile bug fix with a mechanical component extraction and regression coverage, and it does not alter schemas, deployment, security-sensitive code, product defaults, or static-analysis settings. A remaining high-severity finding describes a possible stale Git action callback during default-branch transitions and should be handled by the repository’s blocking-review process.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@coderabbitai

coderabbitai Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Important

Review skipped

We couldn't safely recover the incremental review. No full review was started, and the last reviewed checkpoint was preserved. Retry later, or explicitly request a full review by commenting @coderabbitai full review.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Team
  • Run ID: 3eb25d9c-6cd8-4cf1-a8fe-7f76f285d142
📥 Commits

Reviewing files that changed from the base of the PR and between 3eb1c7a and 7bff9d5.

📒 Files selected for processing (5)
  • apps/mobile/src/features/threads/ThreadHeader.tsx
  • apps/mobile/src/features/threads/ThreadRouteScreen.tsx
  • apps/mobile/src/features/threads/useThreadHeaderOptions.android.ts
  • apps/mobile/src/features/threads/useThreadHeaderOptions.test.tsx
  • apps/mobile/src/features/threads/useThreadHeaderOptions.tsx

Limit details: You’ve used all 10 included reviews currently available.


📝 Walkthrough

Walkthrough

The thread header moves from ThreadRouteScreen into ThreadHeader. Header options now include an item-based version, and tests cover updates to Git status and equivalent-content renders.

Changes

Thread header

Layer / File(s) Summary
Native header refresh tracking
apps/mobile/src/features/threads/useThreadHeaderOptions.tsx, apps/mobile/src/features/threads/useThreadHeaderOptions.android.ts, apps/mobile/src/features/threads/useThreadHeaderOptions.test.tsx
The options hook returns a version based on the active layout's header items. Android returns an empty version array. Tests check Git-status updates and confirm equivalent-content rerenders do not trigger additional setOptions calls.
Thread header actions and route integration
apps/mobile/src/features/threads/ThreadHeader.tsx, apps/mobile/src/features/threads/ThreadRouteScreen.tsx
ThreadHeader renders native options, conditional inspector controls, and Android header actions. ThreadRouteScreen imports it in place of its local header component.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • pingdotgg/t3code#12389: Introduced ThreadHeader and useThreadHeaderOptions, which this change updates to track native header item changes.

Merge Risk: ⚪ Minimal · up to 7bff9

The iOS Git header can receive updated status without an identified regression from this change. Mergeable after normal checks.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 7 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the iOS Git header menu status-refresh fix and uses a concise conventional format.
Description check ✅ Passed The description explains the problem and change, and provides detailed test results, before-and-after screenshots, and verification limits. It does not clearly address the template’s Scope and approva…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

The native header only re-reads its stabilized item factories when
optionsVersion changes, and the thread header keyed it on project scripts
alone. A refreshed Git status (for example after reconnect) never reached the
header Git popover, which kept showing the old "Clean" state.

Key optionsVersion on the memoized header items instead. The options
signature still compares by content, so streaming re-renders with equal
items do not re-apply options. ThreadHeader moves to its own module so the
test drives the production header wiring.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@juliusmarminge
juliusmarminge force-pushed the t3code/mobile-perf/update-native-git-header branch from 7bff9d5 to 1e584b7 Compare October 7, 2026 02:34

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant