{ "$comment": "Every .web.* sibling the Route A web build resolves ahead of its native file. One entry per documented React Native Web gap; config/scripts/mobile-web-app-web-overrides.test.mjs fails on an unlisted one, a listed file that is gone, or one with no native sibling.", "overrides": [ { "file": "src/transport/client-context.web.tsx", "reason": "The page has no websocket transport and no pairing keychain. This is the single transport substitution point: it serves the BridgeRpcClient the entry built, for every hostId, because the bridge protocol names no host. The entry mounts nothing until init lands, so this provider never holds a client that cannot answer." }, { "file": "packages/expo-two-way-audio/src/ExpoTwoWayAudioModule.web.ts", "reason": "Vendored with the module, not added for Route A. Nothing on the page reaches it any more: dictation's capture went behind src/platform/dictation-capture.web.ts, which asks the shell for the microphone, so the only importer of @orca/expo-two-way-audio is the native half of that seam. The file stays because it ships with the vendored module, and it answers denied microphone permission and no playback, which is what a browser outside the shell can honestly say." }, { "file": "src/navigation/use-back-claim.web.ts", "reason": "There is no hardware Back key inside a WebView: react-native-web answers BackHandler.addEventListener with a console warning and an inert subscription, so every sheet that claimed the key on the page armed nothing and one press left the whole session route. The native file registers the key; this one claims it from the shell over the bridge, and the shell hands one press back for the newest claim to spend." }, { "file": "src/navigation/route-handoff.web.ts", "reason": "The page is one document standing in for one screen, so a route it does not render has to be handed to the app that does. The native file is the router; this one posts a navigate notify for a target outside the page's routes and pushes locally for one inside them." }, { "file": "src/transport/host-store.web.ts", "reason": "expo-secure-store resolves to {} on web, so the real store answers loadHosts() with an empty array and every screen that looks this host up paints \"Host not found\" over the host the shell just opened. This one serves the profile init carried, without the credential the bridge already holds." }, { "file": "src/transport/host-removal-lifecycle.web.ts", "reason": "Removing a host is pairing work and the page holds neither the host list nor the credential, so the real lifecycle's removeHost resolved without doing anything and the screen reported success for a host that was still paired. This one refuses with PageHostRemovalUnavailableError, whose message names the app's host list. It is also the fence that keeps push-registration.ts out of the page bundle: the native file's import of it was that subsystem's only path into a page route, and the page has neither the device token nor the gateway client push needs." }, { "file": "src/transport/host-device-token-store.web.ts", "reason": "expo-secure-store resolves to {} on web, and the bridge carries the RPC, so the page holds no device token." }, { "file": "src/platform/host-os.web.ts", "reason": "Platform.OS is web inside the shell's page, but the keyboard the page lifts over is the phone's, reported in that OS's own terms: iOS counts the home indicator. Keyboard and inset arithmetic branches on the host OS, so this answers the phone's OS from the WebView's user agent, and the page computes what the native screen computes." }, { "file": "app/_layout.web.tsx", "reason": "The page's route tree starts at app/h, so without a root layout expo-router mounts DefaultNavigator, an all-edges SafeAreaView that would pad every screen a second time. The native root owns pairing and push and cannot reach the page. This one adds no padding and feeds the insets the shell sent in init to react-native-safe-area-context, whose web provider reads env(safe-area-inset-*) as 0 in both WebViews." }, { "file": "app/h/[hostId]/index.web.tsx", "reason": "The shell renders this page for this route, so the page has no shell to mount inside itself. Its native file reaches OrcaMobileWebShellView, whose requireNativeViewManager call runs at import and throws in a browser." }, { "file": "src/platform/text-input-font-size.web.ts", "reason": "iOS zooms the page on focus of any text input under 16px and does not zoom back out, which leaves the document at a scale other than 1 for a whole typing session. keyboard-occlusion.web.ts reads a scale other than 1 as 'not a keyboard' on purpose, because geometry cannot separate a zoom from a keyboard, so the commit bar and the note composer would never lift on the platform they were written for. The web file raises the app's 14px body size to that floor; the native file is the body size, so a phone renders exactly what it rendered before. maximum-scale=1 on the viewport meta was the other fix and was rejected: Android WebView honours it and it would take deliberate pinch zoom away from low-vision users." }, { "file": "src/platform/text-input-content-height.web.ts", "reason": "react-native-web renders a multiline TextInput as a