Skip to content

feat: add doctor command#883

Merged
thymikee merged 29 commits into
mainfrom
codex/doctor-command
Jul 1, 2026
Merged

feat: add doctor command#883
thymikee merged 29 commits into
mainfrom
codex/doctor-command

Conversation

@thymikee

@thymikee thymikee commented Jun 25, 2026

Copy link
Copy Markdown
Member

Summary

Add a read-only doctor command for RN/Expo/Metro preflight checks, with progressive human output and JSON evidence.

Local doctor now reports available/booted device inventory instead of resolving a default device; stopped simulators/emulators count as available. Adds doctor --remote for remote connection setup checks that skip local device probing.

Closes #874

Validation

Passed focused CLI/parser/provider doctor coverage, typecheck, oxlint, fallow, build, and live CLI smoke for doctor, doctor --platform android, and doctor --remote.

pnpm check:unit still fails in unrelated host/platform tests: Android mocked ADB timeout, iOS status-bar/screenshot timeouts, and an Xcode metadata expectation mismatch.

@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown

Size Report

Metric Base Current Diff
JS raw 1.4 MB 1.5 MB +19.1 kB
JS gzip 464.7 kB 471.3 kB +6.6 kB
npm tarball 564.3 kB 570.9 kB +6.5 kB
npm unpacked 2.0 MB 2.0 MB +19.3 kB

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 29.3 ms 29.4 ms +0.1 ms
CLI --help 50.5 ms 50.3 ms -0.2 ms

Top changed chunks:

Chunk Raw diff Gzip diff
dist/src/session.js +14.4 kB +4.7 kB
dist/src/2948.js +2.8 kB +836 B
dist/src/3340.js +338 B +97 B
dist/src/9722.js -240 B +90 B
dist/src/495.js +91 B +70 B

@thymikee

thymikee commented Jun 25, 2026

Copy link
Copy Markdown
Member Author

I do not see a routing blocker in the doctor command path: the command facet projects through the daemon registry, and the Android probes still run under the request-scoped provider path via the adb executor scope.

One thing I would address before merge: src/daemon/handlers/session-doctor.ts lands as a 571-line handler and mixes option parsing, session/device selection, app discovery, Android foreground/reverse/animation probes, RN overlay checks, Metro probing, output ordering, and progress emission. The repo agent guide asks us to extract focused submodules once implementation files grow past 500 LOC. Please split the probe families out before merge, for example keeping session-doctor.ts as the orchestrator and moving Android/Metro/RN checks into focused session-doctor-* modules or a small doctor-checks/ group. That will make follow-up doctor checks reviewable without growing the handler further.

@thymikee thymikee force-pushed the codex/doctor-command branch from 729bdfb to 484bad5 Compare June 25, 2026 20:14
@thymikee

Copy link
Copy Markdown
Member Author

Re-check after the latest push: this still needs the split before I would call it merge-ready. src/daemon/handlers/session-doctor.ts is now 599 LOC, and the Android/Metro/RN/session/device checks are still all in that handler. CI is green and the route/provider coverage looks fine, but the previous maintainability finding is unresolved.

@thymikee

Copy link
Copy Markdown
Member Author

GitHub now reports this branch as conflicted against main after #884 merged. Please rebase, resolve the conflicts, and reply with what changed plus any validation you reran. I am holding re-review until the branch is clean again.

@thymikee thymikee force-pushed the codex/doctor-command branch from 80975b4 to 51fb503 Compare June 30, 2026 19:53
@thymikee

Copy link
Copy Markdown
Member Author

Current head 51fb503 has failed required checks:

Smoke checks are still settling, but these CI failures need attention before review/readiness. Please address or rerun if the failures are known infra flakes, then reply with what changed and what was validated.

@thymikee

thymikee commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Current head c4193f8 still has failed required checks:

Platform smoke checks are green, but these CI failures block review/readiness. Please address or rerun if they are known infra flakes, then reply with what changed and what was validated.

@thymikee thymikee force-pushed the codex/doctor-command branch from a5e3260 to 753c04f Compare July 1, 2026 08:23
@thymikee

thymikee commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Re-reviewing current head 00cbcb1: I see two blockers before calling this merge-ready.

  1. Stopped Android AVDs now leak into normal target resolution, not just doctor inventory. listAndroidDevices() returns stopped AVDs as { id: avdName, booted: false }, and the normal resolveTargetDevice -> listLocalDeviceInventory -> resolveDevice path can return a sole stopped emulator before any booted filtering. That means a non-boot command such as open --platform android with only one stopped AVD will resolve id=Pixel_... and then wait/run adb against the AVD name rather than a connected emulator serial. Please keep stopped AVDs scoped to doctor/devices inventory, or make normal resolution exclude them unless the command path can boot them.

  2. The doctor CLI cannot accept the non-default Metro endpoint that the issue/probe hint points users toward. doctorCliSchema.allowedFlags only includes targetApp and remote, while common flags do not include metroHost/metroPort. As a result, agent-device doctor --metro-port 8082 is rejected even though feat: add RN/Expo/Metro-aware doctor command #874 proposed that shape and probeMetro tells users to use --metro-host/--metro-port for non-default endpoints. Please either wire those flags through doctor or adjust the contract/hints so users have a real way to point doctor at the intended Metro.

@thymikee

thymikee commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Re-reviewing c118b87 after the prior blocker comment: both actionable blockers still appear to remain.

  1. listAndroidDevices() still appends stopped AVDs to the normal Android inventory (id is the AVD name, booted: false). That inventory still flows through listLocalDeviceInventory() -> resolveTargetDevice() -> resolveDevice(), and a sole stopped AVD can still be returned by the early single-candidate path or selected as the only emulator candidate. That means non-boot commands can still resolve an AVD name as if it were an adb serial. Stopped AVDs need to stay doctor/devices-only, or normal target resolution needs to filter/reject them unless the command is explicitly booting by AVD name.

  2. doctor still does not accept the Metro override flags. src/commands/management/doctor.ts keeps allowedFlags: ['targetApp', 'remote'], so agent-device doctor --metro-port ... is still rejected in strict parsing even though the linked issue and recovery hint require that command to work.

Checks are currently pending-only, but these are shipped-path blockers rather than CI noise.

thymikee added 19 commits July 1, 2026 13:03
…in failures

Two gaps found while verifying the doctor command on a real environment:

- Metro host/port were uncontrollable from the CLI: --metro-host/--metro-port
  were rejected by allowedFlags, and readDoctorOptions only read them from
  req.runtime (populated by remote/connection profiles, never a plain CLI
  flag). The Metro check's own hint told users to 'pass the correct
  --metro-host/--metro-port', which did not exist. Declare the flags and read
  them from req.flags (runtime kept as fallback) so the probe can target any
  endpoint, e.g. from outside an RN/Expo project directory.

- A broken per-platform toolchain was silently hidden: readDoctorDeviceInventory
  dropped inventory failures whenever any other platform returned devices, so a
  broken Xcode or Android SDK still reported a green 'pass'. Keep the failures
  and surface each as a warn (device-<platform>) when other platforms have
  devices; scoped --platform runs stay quiet.
@thymikee thymikee force-pushed the codex/doctor-command branch from c118b87 to e3eb132 Compare July 1, 2026 11:11
@thymikee

thymikee commented Jul 1, 2026

Copy link
Copy Markdown
Member Author

Re-reviewing latest clean head e3eb132 after the previous blocker note: the two shipped-path blockers still appear unchanged.

  1. doctor still rejects the Metro override flags. src/commands/management/doctor.ts keeps allowedFlags: ['targetApp', 'remote'], so strict parsing still rejects agent-device doctor --metro-port ... / --metro-host ... even though the linked issue and recovery hint need that command shape.

  2. Stopped Android AVDs still flow through normal target resolution. listAndroidDevices() still appends stopped AVD entries with id equal to the AVD name and booted: false; listLocalDeviceInventory() still returns them for platform: 'android'; and resolveDevice() can still return a sole stopped AVD via the single-candidate path or pick it as the only emulator candidate. That means non-boot commands can still resolve an AVD name where an adb serial is required.

Checks are green, but these are product-path blockers rather than CI blockers.

@thymikee thymikee merged commit d21b8ce into main Jul 1, 2026
21 checks passed
@thymikee thymikee deleted the codex/doctor-command branch July 1, 2026 12:24
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-07-01 12:24 UTC

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.

feat: add RN/Expo/Metro-aware doctor command

1 participant