Skip to content

feat(mobile): mount ProtocolBlockScreen when protocol compat is blocked - #9780

Merged
brennanb2025 merged 3 commits into
mainfrom
brennanb2025/mobile-block-screen
Jul 22, 2026
Merged

brennanb2025 merged 3 commits into
mainfrom
brennanb2025/mobile-block-screen

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Summary

ProtocolBlockScreen was only mounted inside the base host-list screen, so deep links and nested /h/[hostId] routes could continue into an incompatible desktop instead of showing the required update screen. This moves compatibility enforcement to the host layout choke point used by every host route.

  • Adds HostProtocolGate above the full host UI (sidebar + detail stack), while the host list and other hosts remain usable.
  • Waits for the first connected-host compatibility probe before mounting nested routes, preventing newer RPCs from firing before compatibility is known.
  • Shares the loaded status.get gates with HostScreen, avoiding the duplicate remote probe the parent gate would otherwise add on common phone/tablet paths.
  • Keeps already-validated routes mounted during reconnect revalidation so active terminals are not torn down; a later blocked verdict still replaces the route.
  • Preserves fail-open behavior for a failed status probe with conservative feature gates, and exposes both recovery CTAs: App Store for mobile-too-old, GitHub Releases for desktop-too-old.
  • Leaves the canonical protocol evaluator and its Metro mirror contract unchanged.

Tests

HostProtocolGate.test.ts exercises the real useHostStatusGates → evaluateCompat → ProtocolBlockScreen wiring with only client acquisition mocked:

  1. mobile-too-old renders the App Store block screen and removes host content
  2. desktop-too-old renders the GitHub Releases block screen and removes host content
  3. compatible status renders host content and shares capabilities with one status.get
  4. connection-pending state leaves the host connection UI available
  5. first connected-host probe fences child-route mounting
  6. reconnect revalidation keeps an already-validated route mounted
  7. a failed status probe fails open without enabling capability-gated actions

Verification completed locally:

  • Mobile: 304 test files passed; 2,177 tests passed, 2 skipped
  • Mobile tsc --noEmit, oxlint, and oxfmt clean
  • Root Node typecheck and max-lines ratchet clean
  • Electron production build clean
  • Isolated Electron app + daemon boot clean

Screenshots / manual QA

Manual iPhone 17 Pro simulator coverage includes current/current compatibility, both forced block reasons, Back to hosts, a Resume deep link into a nested session route, and a final compatible-host pass after restoring the production constants.

Desktop too old Mobile too old Compatible path restored
Desktop too old Mobile too old Compatible host restored

Detailed review notes and Electron boot evidence: #9780 (comment)

ProtocolBlockScreen existed since PR #1440 but was never mounted: on a
'blocked' compat verdict the only output was a console.warn, so a future
MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION bump would have silently shown a
broken host UI instead of the update screen.

Add HostProtocolGate — a choke point in app/h/_layout.tsx above every
/h/[hostId] route — that consumes useHostStatusGates and replaces the
blocked host's entire UI (sidebar + detail stack) with ProtocolBlockScreen.
The host list and other hosts stay usable; the screen's own 'Back to
hosts' escape hatch routes to '/'. Both block reasons render their
respective CTAs (mobile-too-old → App Store, desktop-too-old → GitHub
Releases). Compat logic stays in the src/shared mirror contract — no fork.
@coderabbitai

coderabbitai Bot commented Jul 21, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3b63061e-8a55-4141-af4f-60509a6bff0c

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5501e and 097acda.

📒 Files selected for processing (2)
  • mobile/src/components/HostProtocolGate.test.ts
  • mobile/src/components/ProtocolBlockScreen.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • mobile/src/components/HostProtocolGate.test.ts

📝 Walkthrough

Walkthrough

Adds host-scoped protocol compatibility gating to the mobile host layout. The gate now handles pending probes, blocked compatibility verdicts, and shared host capability state, while host screens consume the shared context. Tests cover outdated clients, compatible clients, pending connections, reconnects, unresolved probes, and failed status requests.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers summary, tests, and screenshots, but it omits required AI Review Report, Security Audit, Notes, and checklist-style Testing sections. Add the missing template sections: a checklist-form Testing block, AI Review Report, Security Audit, and Notes, or explain why any are not applicable.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: mounting ProtocolBlockScreen when protocol compatibility is blocked.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Deep review + manual QA follow-up

I found and fixed two meaningful issues in 7d5501e7d1:

  • The parent gate and HostScreen each issued status.get, so common phone and tablet routes paid for the same remote probe twice. The gate now provides the loaded status gates to the host screen; the regression test asserts exactly one request.
  • A connected host mounted child routes while compatibility was still unknown, allowing nested screens to call newer RPCs before the hard block arrived. The first probe now fences route mounting. Reconnect probes keep an already-validated route mounted so terminals are not torn down, and a status error still fails open with conservative feature gates.

Automated verification:

  • Mobile: 304 files passed; 2,177 tests passed, 2 skipped
  • Mobile typecheck, oxlint, and oxfmt: clean
  • Root Node typecheck and max-lines ratchet: clean
  • Electron production build: clean
  • Isolated Electron dev boot: app + daemon started successfully

Manual verification used a dedicated iPhone 17 Pro simulator (iOS 26.5) paired to a temporary desktop runtime. I exercised current/current compatibility, both forced block reasons, Back to hosts, a Resume deep link into the nested session route, and restored the production constants before the final compatible-host pass.

Desktop too old Mobile too old Restored compatible path
Desktop too old Mobile too old Compatible host restored
Isolated Electron boot evidence

Isolated Electron dev boot

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Android update-path UI preview

The shared native block screen rendered with the Android update target. Android now points users to GitHub Releases until Play Store distribution exists. (Captured in the available iOS simulator because this machine has no Android SDK/AVD configured.)

Android update-path UI preview

@brennanb2025
brennanb2025 merged commit 405b9f2 into main Jul 22, 2026
5 checks passed
enrick-dev pushed a commit to enrick-dev/orca that referenced this pull request Oct 15, 2026
…ed (stablyai#9780)

* feat(mobile): mount ProtocolBlockScreen when protocol compat is blocked

ProtocolBlockScreen existed since PR stablyai#1440 but was never mounted: on a
'blocked' compat verdict the only output was a console.warn, so a future
MIN_COMPATIBLE_RUNTIME_CLIENT_VERSION bump would have silently shown a
broken host UI instead of the update screen.

Add HostProtocolGate — a choke point in app/h/_layout.tsx above every
/h/[hostId] route — that consumes useHostStatusGates and replaces the
blocked host's entire UI (sidebar + detail stack) with ProtocolBlockScreen.
The host list and other hosts stay usable; the screen's own 'Back to
hosts' escape hatch routes to '/'. Both block reasons render their
respective CTAs (mobile-too-old → App Store, desktop-too-old → GitHub
Releases). Compat logic stays in the src/shared mirror contract — no fork.

* fix(mobile): fence incompatible host routes efficiently

* fix(mobile): route Android updates to releases
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant