fix(cdp): fast-fail cdp_status when the Dev Client picker blocks the bundle (closes #184)#187
Merged
Merged
Conversation
…bundle (closes #184) cdp_status with the Expo Dev Client "Development servers" picker up AND Metro running hung ~33.5s: stale C++ targets pass filterValidTargets, the 1+1 probe passes, and performSetup's waitForReact then burns its full 30s before returning a misleading ok:true. Fix: thread a connect intent ('default' | 'status') through autoConnect -> discoverAndConnect -> connectToTarget. For a status-scoped connect against a non-Hermes target, run a bounded React-reachability probe (default 5s, RN_PICKER_PROBE_BUDGET_MS-overridable) BEFORE setup()'s 30s waitForReact. If React isn't reachable, throw the typed PickerBlockingBundleError, which bypasses both the connectToTarget retry loop and the discoverAndConnect candidate loop; status.ts maps it to a fast failResult with code PICKER_BLOCKING and an actionable message ("select your Metro server, then retry cdp_status"). Deliberately NOT changing the global REACT_READY_TIMEOUT_MS (shared by every connect path) and NOT adding a pre-autoConnect target-shape heuristic (which false-positives on healthy reloads). Hermes targets skip the probe entirely, so legitimate slow first-builds keep the full budget; non-status connect paths are unchanged. New pure helpers (tested without a real WebSocket, per the repo's formatConnectFailureMessage/stickyPlatformFilters convention): - probeReactReachable(evaluate, budgetMs, pollMs) -> boolean (setup.ts) - shouldRunPickerProbe(intent, target), PickerBlockingBundleError (connect.ts) Full suite 1563 pass; tsc clean. End-to-end picker-up assertion belongs to the deferred Dev Client harness CI (DC-Task 9 / #136). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lykhoyda
added a commit
that referenced
this pull request
May 31, 2026
…to-dismiss (#196) * docs(#136): design spec for dev-client picker dismiss tool + launch wiring (sub-3) Approach B: cdp_dismiss_dev_client_picker MCP tool (Android-as-is) + iOS guard + best-effort device_deeplink dismissal, routed through one shared helper. Sub-1/sub-2 already shipped (#174/#187); this covers the remaining sub-3. * docs(#136): implementation plan for dev-client picker dismiss (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#136): add guarded clearDevClientPickerIfPresent seam (sub-3) Wraps the unchanged Android handleDevClientPicker(); iOS short-circuits with an actionable message and never touches the legacy agent-device path. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#136): map picker outcome to ToolResult in dismiss handler (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#136): register cdp_dismiss_dev_client_picker MCP tool (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * feat(#136): best-effort Dev Client picker dismiss after Android deep links (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(#136): document cdp_dismiss_dev_client_picker; bump tool count 75->76 (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * chore(#136): add changeset (patch) for dev-client picker dismiss tool Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * build(#136): compile dist for dev-client picker dismiss tool (sub-3) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Closes #184.
Problem
cdp_status({platform:'ios'})with the Expo Dev Client "Development servers" picker up and Metro running hung ~33.5s, loggedReact not ready after 30000ms, then returned a misleadingok:true. Root cause: stale C++ targets passfilterValidTargets, the1+1pre-flight probe passes (the C++ connection answers), andperformSetup'swaitForReact(REACT_READY_TIMEOUT_MS=30_000)then burns its full 30s because the picker blocks the bundle so React never readies.Fix
Thread a connect intent (
'default' | 'status') throughautoConnect → discoverAndConnect → connectToTarget. For a status-scoped connect against a non-Hermes target, run a bounded React-reachability probe (default 5s,RN_PICKER_PROBE_BUDGET_MS-overridable) beforesetup()'s 30swaitForReact. If React isn't reachable within the budget, throw the typedPickerBlockingBundleError— which bypasses both theconnectToTargetretry loop and thediscoverAndConnectcandidate loop — andstatus.tsmaps it to a fastfailResultwith codePICKER_BLOCKINGand an actionable message:A working Bridgeless app's target is also a
[C++ connection], but its React is reachable, so the probe succeeds and the connect proceeds normally — only a genuinely blocked/never-ready target throws.What it deliberately does NOT do (the two regressions #184 called out)
REACT_READY_TIMEOUT_MS— it's shared by every connect path and would regress legitimate slow first-builds.autoConnecttarget-shape heuristic —/json/listreturns 0 Hermes targets transiently during healthy reloads, so that would false-positive.Files (~5, as the issue estimated)
cdp/connect.ts(intent threading,PickerBlockingBundleError,shouldRunPickerProbe, probe + both catch sites),cdp/setup.ts(probeReactReachable),cdp-client.ts(intent param),tools/status.ts('status'intent + mapping),types.ts(PICKER_BLOCKINGcode).Testing
probeReactReachable,shouldRunPickerProbe,PickerBlockingBundleError), written failing-first — the connect layer opens a real WebSocket, so the decision logic is extracted into pure helpers per the repo's existingformatConnectFailureMessage/stickyPlatformFiltersconvention.tsc --noEmitclean; existing connect tests unaffected.cdp_statusreturns < ~6s) belongs to the deferred Dev Client harness CI (DC-Task 9 / Multi-device routing + dev-client picker hangs (combined session feedback) #136), per the issue.🤖 Generated with Claude Code