[PR #6253] [MERGED] fix(doctor): check only the current platform's Hopper launcher candidates #7228

Closed
opened 2026-11-01 21:46:19 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6253
Author: @SandstromPL
Created: 10/22/2026
Status: ✅ Merged
Merged: 10/23/2026
Merged by: @baron

Base: main ← Head: fix/doctor-hopper-platform-candidates


📝 Commits (5)

  • 0151bdc fix(doctor): check only the current platform's Hopper launcher candidates
  • 5ffad47 fix(doctor): keep the renamed Hopper bundle scan asynchronous
  • 1cce496 Merge upstream/main into fix/doctor-hopper-platform-candidates
  • 85c57a6 Merge upstream/main into fix/doctor-hopper-platform-candidates
  • 4dab6bc test(doctor): model renamed launchers with runtime's POSIX joins

📊 Changes

9 files changed (+205 additions, -105 deletions)

View changed files

📝 docs/installation.md (+3 -1)
📝 src/application/Doctor.test.ts (+84 -10)
📝 src/application/Doctor.ts (+6 -25)
📝 src/application/DoctorDiagnostics.ts (+10 -30)
➕ src/application/HopperLauncherDiscovery.ts (+49 -0)
📝 src/application/LinuxHopper.ts (+1 -1)
📝 src/application/MacHopperPaths.test.ts (+15 -12)
📝 src/application/MacHopperPaths.ts (+27 -9)
📝 src/config/parseConfig.ts (+10 -17)

📄 Description

Summary

Fixes #6228.

With no HOPPER_LAUNCHER_PATH, rea doctor built one launcher list for every platform. On macOS that list included the Linux system paths /opt/hopper-v4/bin/hopper and /usr/bin/hopper, ahead of renamed Hopper*.app bundles. On Linux it included the macOS system application and ~/Applications bundles. Runtime discovery (defaultHopperLauncherPath) already checked only the current platform. As a result:

  • Doctor could report a Linux-only path as a healthy Hopper on macOS.
  • That path won over a valid renamed bundle that runtime would select.
  • Setup trusts doctor's hopperPath: it writes it into client registrations as HOPPER_LAUNCHER_PATH and treats Hopper as configured. So setup could register that Linux path on macOS and stop offering a Hopper install.

After this change, doctor and runtime read one per-platform owner. Doctor checks only the current platform's candidates, in runtime's order.

Problem and expected behavior

  • Smallest trigger (from the issue): macOS, no override, no canonical application, /opt/hopper-v4/bin/hopper executable. Doctor reported that path with healthy: true, while runtime selected its macOS fallback. When a renamed bundle was also present, doctor still returned the Linux path while runtime selected the bundle.
  • Violated invariant: docs/installation.md defines the automatic launcher order separately for macOS and Linux. Doctor is the readiness check for the launcher CLI/MCP startup uses.

Change and scope

  • New owner, src/application/HopperLauncherDiscovery.ts: hopperLauncherDiscovery(platform, home) returns, for one platform:
    • the fixed candidates, probed in order;
    • whether renamed macOS bundles are probed afterwards (probesMacApplicationBundles);
    • the runtime fallback.
  • What each platform gets:
    • macOS: the canonical system and ~/Applications launchers, then renamed bundles. Fallback: the system launcher.
    • Linux: linuxHopperLauncherCandidates. Fallback: the REA-managed /opt/hopper/bin/Hopper.
    • Other platforms: no automatic candidates. Runtime keeps its existing fallback.
  • Runtime: defaultHopperLauncherPath (src/config/parseConfig.ts) reads the owner. Its selections are unchanged on every platform.
  • Doctor: findHopper (src/application/DoctorDiagnostics.ts) reads the owner too.
    • A configured HOPPER_LAUNCHER_PATH is still checked alone.
    • Otherwise doctor probes the fixed candidates, then, on macOS only, renamed bundles and then the Homebrew cask application.
    • Renamed bundles are now scanned only after the fixed candidates fail.
    • The Homebrew probe no longer runs on Linux or Windows. The hopper-disassembler cask is macOS-only, and the docs already describe it as a macOS doctor diagnostic.
  • Removed duplication:
    • MacHopperPaths.ts now owns both renamed-bundle scans: the lazy synchronous generator runtime needs (localMacHopperRenamedLauncherCandidates), and the asynchronous readMacHopperRenamedLauncherCandidates the production doctor host uses, so doctor never blocks the event loop on a slow ~/Applications. Both share the directory filter and macHopperRenamedLauncherCandidates, so the naming and ordering rules have one owner. Doctor's separate scan in Doctor.ts is deleted.
    • macHopperLauncherCandidates, the canonical-plus-renamed generator, is replaced by the renamed-only generator. The redundant name filter in its directory read is dropped.
    • systemLinuxHopperLauncherCandidates is no longer exported. Only doctor's cross-platform list used it from outside.
  • Docs: docs/installation.md now says doctor checks only the current platform's candidates, in the same order, and that other platforms have no automatic candidates.
  • Remaining related cleanup, intentionally not included:
    • Linux executability still differs. On Linux, doctor's executable check also runs ldd and rejects launchers with missing shared libraries; runtime checks only that the file is executable and a regular file. If /opt/hopper/bin/Hopper is missing a library and /usr/bin/hopper is fine, doctor reports /usr/bin/hopper while runtime selects /opt/hopper/bin/Hopper. This existed before; fixing it means choosing one executability rule for both, so it belongs in a separate change.
    • Windows remediation. On Windows, doctor's Hopper remediation still says "Run rea setup to install Hopper", although HopperProvider reports unsupported_host there.

Contribution scope: an ordinary fix within existing doctor and launcher-discovery boundaries, so a maintainer scope decision is not applicable.

Contract and boundary impact

  • Semantic owner and earliest changed stage: hopperLauncherDiscovery in src/application/HopperLauncherDiscovery.ts, consumed by runtime configuration and doctor discovery.
  • Contribution scope fit and linked maintainer decision: routine fix; not applicable.
  • CLI and MCP/tool-catalog contract: no flag, schema or catalog change.
    • rea doctor may now report no Hopper (missing_analysis_engine) where it previously reported another platform's path as healthy.
    • On macOS, a valid renamed bundle now wins over a Linux path.
  • Provider, bridge, target-format, or platform compatibility:
    • Runtime launcher selection is unchanged.
    • Doctor discovery changes on every platform, as described above.
    • Setup follows doctor: on macOS, a launcher at a Linux-only path is no longer written into client registrations, and setup can offer a Hopper install there again.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Target selection, authority, upstream behavior, and cleanup details: doctor runs fewer probes: no renamed-bundle scan when a canonical launcher exists, and no Homebrew process on Linux or Windows. No new probes.
  • Generated metadata, package, or installation impact: none.

Expected effects (check known effects; use documentation-only on its own).
Unchecked items do not establish absence; leave uncertainties visible.

  • Read existing files or captured data. (doctor's existing launcher-path probes and application-directory listing)
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration.
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • Tests added or updated:
    • src/application/Doctor.test.ts, new describe("doctor Hopper discovery matches runtime selection"): a 7-row table using the doctor host fixture with modeled executables, and a per-case temporary home holding a real Applications/Hopper 5.app directory for runtime's scan. Each row asserts:
      • doctor's hopperPath;
      • that it equals runtime's selection whenever that selection is executable;
      • how many renamed-bundle scans and Homebrew probes ran;
      • missing_analysis_engine when nothing is found.
    • Rows:
      • macOS, Linux path only: none.
      • macOS, Linux path plus renamed bundle: the renamed bundle.
      • macOS, Linux path plus canonical launcher: canonical.
      • macOS, renamed bundle plus canonical launcher: canonical, with no bundle scan.
      • Linux, macOS paths only: none.
      • Linux, macOS plus Linux paths: the Linux path.
      • Windows: nothing probed.
    • Removed: "detects a manually installed Hopper application" duplicated the macOS renamed-bundle row.
    • src/application/MacHopperPaths.test.ts: a real temporary home checks that runtime's synchronous scan and doctor's asynchronous scan return the same candidates: a renamed bundle is kept, while the canonical name and a non-directory Hopper*.app are skipped. The deleted canonical-membership check is still covered by the canonical-candidates test.
  • Base reproduction (executed): with only the source files reverted to bd5d189a8, all 7 new rows fail.
    • The two macOS cases from the issue get /opt/hopper-v4/bin/hopper.
    • The Linux and Windows rows get the macOS system launcher.
    • The two canonical macOS rows fail only on the scan count, because the base scanned renamed bundles eagerly.
  • User-visible CLI/MCP output: for the issue's macOS Linux-path-only case, the hopper check changes from ok: true, classification: "healthy", detail: "/opt/hopper-v4/bin/hopper" to ok: false with classification: "missing_analysis_engine". This is asserted at service level, not from a CLI run.
  • Remaining proof gaps:
    • No real macOS or Windows host; platforms are modeled through the doctor host fixture.
    • No real Hopper installation or launch.
    • Performance was not measured. The only cost change is fewer probes.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable.
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

Run on Linux with Node 24.18.0 and npm 11.16.0, on bd5d189a8:

  • npm run test:local -- on Doctor, Doctor.*, all Setup* service tests, MacHopperPaths, LinuxHopper, config, GhidraDoctor and doctorRuntime: 12 files, 277 tests passed.
  • npm run test:focused -- tests/boundary/filesystem/hopperLauncherSelection.test.ts tests/boundary/cli/doctorHopperDiscovery.test.ts tests/boundary/filesystem/doctorSystemHostFilesystem.test.ts tests/boundary/cli/setupProviderReadiness.test.ts tests/boundary/filesystem/setupUnavailableProvider.test.ts tests/boundary/cli/cliSetup.test.ts tests/boundary/filesystem/setupConfig.test.ts: 7 files, 49 tests passed.
  • After keeping doctor's scan asynchronous (Greptile review): the same unit set, 12 files, 277 tests passed; the first five boundary files above, 15 tests passed; npm run check:fast passed.
  • After merging upstream/main at 4043e71f6 (merge commit 1cce496f6): the same unit set, 12 files, 278 tests passed; the seven boundary files above, 50 tests passed; npx tsc --noEmit -p ., npm run check:fast and npm run docs:check passed; npm run verify:test-discovery discovered all 2020 test files exactly once.
  • CI on 5ffad47e1 failed only in the Windows capability lane: tests/acceptance/webModuleCli.test.ts exceeded its 15000 ms process deadline after printing its complete result. That test traces web modules and does not touch files in this PR; the same lane passed on 0151bdc56. This push reruns CI.
  • CI on 1cce496f6 passed, including the Windows lane.
  • After merging upstream/main at 9eb829aca, conflicts with #3422 (Linux architecture gate) and #5235 (POSIX joins in MacHopperPaths.ts) were resolved: MacHopperPaths.ts keeps both renamed-bundle scans on posix.join, DoctorDiagnostics.ts keeps the shared owner plus #3422's LINUX_HOPPER_SETUP_HOSTS, and the scan agreement test now uses #5235's Windows-safe temporary home.
    • The same unit set: 12 files, 313 tests passed. The seven boundary files above: 51 tests passed.
    • npx tsc --noEmit -p ., npm run check:fast and npm run docs:check passed; npm run verify:test-discovery discovered all 2105 test files exactly once.
  • Greptile follow-up (4dab6bc9f): the doctor discovery table now models launchers with posix.join, matching runtime since #5235, while filesystem setup stays native. Doctor, Doctor.*, MacHopperPaths and config tests: 4 files, 148 tests passed; npm run check:fast passed. The modeled and runtime launcher strings were checked to agree for drive-letter, UNC and POSIX homes; the table was not run on Windows locally.
  • npm run test:local -- src/application/Doctor.test.ts with only the source files reverted: 7 failed (the new rows), 59 passed.
  • npx tsc --noEmit -p .: clean.
  • npm run check:fast (typecheck and lint): passed.
    • npx oxlint on the changed files: 0 errors.
    • Doctor.ts and LinuxHopper.ts keep their existing size and complexity warnings. Doctor.ts shrinks from 746 to 727 lines; systemDoctorHost grows from 225 to 226 lines.
  • npm run docs:check: passed.
  • npm run verify:test-discovery: discovered all 1971 test files exactly once.
  • npx oxfmt --check on the changed files and git diff --check: clean.
  • Not run: npm run check:pr, real Hopper or macOS/Windows verification.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Runtime selection is unchanged. Doctor stops reporting another platform's launcher; users relying on such a path can set HOPPER_LAUNCHER_PATH, which doctor still checks as given.
  • Real Hopper/Ghidra, browser, or OS coverage: Linux only; macOS and Windows behavior is modeled with the doctor host fixture.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: doctor runs fewer filesystem probes and no Homebrew process on Linux or Windows. Nothing new is executed or written.

Author readiness

Human owner: @SandstromPL

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked, or the reason for not linking one is stated above.
  • Tests cover changed observable behavior and meaningful failure paths.
  • Owning docs, contracts, and generated metadata are updated where needed.
  • User-visible CLI/MCP changes include representative output.
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🤖 Generated with Claude Code


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/6253 **Author:** [@SandstromPL](https://github.com/SandstromPL) **Created:** 10/22/2026 **Status:** ✅ Merged **Merged:** 10/23/2026 **Merged by:** [@baron](https://github.com/baron) **Base:** `main` ← **Head:** `fix/doctor-hopper-platform-candidates` --- ### 📝 Commits (5) - [`0151bdc`](https://github.com/morluto/rea/commit/0151bdc56b544e1d3a07b6e0646f0a04db07340b) fix(doctor): check only the current platform's Hopper launcher candidates - [`5ffad47`](https://github.com/morluto/rea/commit/5ffad47e16cba56de5d2ef2107176c74932b081e) fix(doctor): keep the renamed Hopper bundle scan asynchronous - [`1cce496`](https://github.com/morluto/rea/commit/1cce496f6a858fe2ebf491c9ab4c4e619ec5fb2c) Merge upstream/main into fix/doctor-hopper-platform-candidates - [`85c57a6`](https://github.com/morluto/rea/commit/85c57a659aaf82101e4cb9be34b3de331bfbc655) Merge upstream/main into fix/doctor-hopper-platform-candidates - [`4dab6bc`](https://github.com/morluto/rea/commit/4dab6bc9f3c8dc8b761559c46b56a446cd20ac0d) test(doctor): model renamed launchers with runtime's POSIX joins ### 📊 Changes **9 files changed** (+205 additions, -105 deletions) <details> <summary>View changed files</summary> 📝 `docs/installation.md` (+3 -1) 📝 `src/application/Doctor.test.ts` (+84 -10) 📝 `src/application/Doctor.ts` (+6 -25) 📝 `src/application/DoctorDiagnostics.ts` (+10 -30) ➕ `src/application/HopperLauncherDiscovery.ts` (+49 -0) 📝 `src/application/LinuxHopper.ts` (+1 -1) 📝 `src/application/MacHopperPaths.test.ts` (+15 -12) 📝 `src/application/MacHopperPaths.ts` (+27 -9) 📝 `src/config/parseConfig.ts` (+10 -17) </details> ### 📄 Description ## Summary Fixes #6228. With no `HOPPER_LAUNCHER_PATH`, `rea doctor` built one launcher list for every platform. On macOS that list included the Linux system paths `/opt/hopper-v4/bin/hopper` and `/usr/bin/hopper`, ahead of renamed `Hopper*.app` bundles. On Linux it included the macOS system application and `~/Applications` bundles. Runtime discovery (`defaultHopperLauncherPath`) already checked only the current platform. As a result: - Doctor could report a Linux-only path as a healthy Hopper on macOS. - That path won over a valid renamed bundle that runtime would select. - Setup trusts doctor's `hopperPath`: it writes it into client registrations as `HOPPER_LAUNCHER_PATH` and treats Hopper as configured. So setup could register that Linux path on macOS and stop offering a Hopper install. After this change, doctor and runtime read one per-platform owner. Doctor checks only the current platform's candidates, in runtime's order. ## Problem and expected behavior - **Smallest trigger (from the issue):** macOS, no override, no canonical application, `/opt/hopper-v4/bin/hopper` executable. Doctor reported that path with `healthy: true`, while runtime selected its macOS fallback. When a renamed bundle was also present, doctor still returned the Linux path while runtime selected the bundle. - **Violated invariant:** `docs/installation.md` defines the automatic launcher order separately for macOS and Linux. Doctor is the readiness check for the launcher CLI/MCP startup uses. ## Change and scope - **New owner, `src/application/HopperLauncherDiscovery.ts`:** `hopperLauncherDiscovery(platform, home)` returns, for one platform: - the fixed candidates, probed in order; - whether renamed macOS bundles are probed afterwards (`probesMacApplicationBundles`); - the runtime fallback. - **What each platform gets:** - **macOS:** the canonical system and `~/Applications` launchers, then renamed bundles. Fallback: the system launcher. - **Linux:** `linuxHopperLauncherCandidates`. Fallback: the REA-managed `/opt/hopper/bin/Hopper`. - **Other platforms:** no automatic candidates. Runtime keeps its existing fallback. - **Runtime:** `defaultHopperLauncherPath` (`src/config/parseConfig.ts`) reads the owner. Its selections are unchanged on every platform. - **Doctor:** `findHopper` (`src/application/DoctorDiagnostics.ts`) reads the owner too. - A configured `HOPPER_LAUNCHER_PATH` is still checked alone. - Otherwise doctor probes the fixed candidates, then, on macOS only, renamed bundles and then the Homebrew cask application. - Renamed bundles are now scanned only after the fixed candidates fail. - The Homebrew probe no longer runs on Linux or Windows. The `hopper-disassembler` cask is macOS-only, and the docs already describe it as a macOS doctor diagnostic. - **Removed duplication:** - `MacHopperPaths.ts` now owns both renamed-bundle scans: the lazy synchronous generator runtime needs (`localMacHopperRenamedLauncherCandidates`), and the asynchronous `readMacHopperRenamedLauncherCandidates` the production doctor host uses, so doctor never blocks the event loop on a slow `~/Applications`. Both share the directory filter and `macHopperRenamedLauncherCandidates`, so the naming and ordering rules have one owner. Doctor's separate scan in `Doctor.ts` is deleted. - `macHopperLauncherCandidates`, the canonical-plus-renamed generator, is replaced by the renamed-only generator. The redundant name filter in its directory read is dropped. - `systemLinuxHopperLauncherCandidates` is no longer exported. Only doctor's cross-platform list used it from outside. - **Docs:** `docs/installation.md` now says doctor checks only the current platform's candidates, in the same order, and that other platforms have no automatic candidates. - **Remaining related cleanup, intentionally not included:** - **Linux executability still differs.** On Linux, doctor's `executable` check also runs `ldd` and rejects launchers with missing shared libraries; runtime checks only that the file is executable and a regular file. If `/opt/hopper/bin/Hopper` is missing a library and `/usr/bin/hopper` is fine, doctor reports `/usr/bin/hopper` while runtime selects `/opt/hopper/bin/Hopper`. This existed before; fixing it means choosing one executability rule for both, so it belongs in a separate change. - **Windows remediation.** On Windows, doctor's Hopper remediation still says "Run rea setup to install Hopper", although `HopperProvider` reports `unsupported_host` there. Contribution scope: an ordinary fix within existing doctor and launcher-discovery boundaries, so a maintainer scope decision is not applicable. ## Contract and boundary impact - **Semantic owner and earliest changed stage:** `hopperLauncherDiscovery` in `src/application/HopperLauncherDiscovery.ts`, consumed by runtime configuration and doctor discovery. - **Contribution scope fit and linked maintainer decision:** routine fix; not applicable. - **CLI and MCP/tool-catalog contract:** no flag, schema or catalog change. - `rea doctor` may now report no Hopper (`missing_analysis_engine`) where it previously reported another platform's path as healthy. - On macOS, a valid renamed bundle now wins over a Linux path. - **Provider, bridge, target-format, or platform compatibility:** - Runtime launcher selection is unchanged. - Doctor discovery changes on every platform, as described above. - Setup follows doctor: on macOS, a launcher at a Linux-only path is no longer written into client registrations, and setup can offer a Hopper install there again. - **Evidence, artifact, provenance, or reconstruction contract:** none. - **Target selection, authority, upstream behavior, and cleanup details:** doctor runs fewer probes: no renamed-bundle scan when a canonical launcher exists, and no Homebrew process on Linux or Windows. No new probes. - **Generated metadata, package, or installation impact:** none. Expected effects (check known effects; use documentation-only on its own). Unchecked items do not establish absence; leave uncertainties visible. - [x] Read existing files or captured data. (doctor's existing launcher-path probes and application-directory listing) - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - **Tests added or updated:** - **`src/application/Doctor.test.ts`, new `describe("doctor Hopper discovery matches runtime selection")`:** a 7-row table using the doctor host fixture with modeled executables, and a per-case temporary home holding a real `Applications/Hopper 5.app` directory for runtime's scan. Each row asserts: - doctor's `hopperPath`; - that it equals runtime's selection whenever that selection is executable; - how many renamed-bundle scans and Homebrew probes ran; - `missing_analysis_engine` when nothing is found. - **Rows:** - macOS, Linux path only: none. - macOS, Linux path plus renamed bundle: the renamed bundle. - macOS, Linux path plus canonical launcher: canonical. - macOS, renamed bundle plus canonical launcher: canonical, with no bundle scan. - Linux, macOS paths only: none. - Linux, macOS plus Linux paths: the Linux path. - Windows: nothing probed. - **Removed:** "detects a manually installed Hopper application" duplicated the macOS renamed-bundle row. - **`src/application/MacHopperPaths.test.ts`:** a real temporary home checks that runtime's synchronous scan and doctor's asynchronous scan return the same candidates: a renamed bundle is kept, while the canonical name and a non-directory `Hopper*.app` are skipped. The deleted canonical-membership check is still covered by the canonical-candidates test. - **Base reproduction (executed):** with only the source files reverted to `bd5d189a8`, all 7 new rows fail. - The two macOS cases from the issue get `/opt/hopper-v4/bin/hopper`. - The Linux and Windows rows get the macOS system launcher. - The two canonical macOS rows fail only on the scan count, because the base scanned renamed bundles eagerly. - **User-visible CLI/MCP output:** for the issue's macOS Linux-path-only case, the `hopper` check changes from `ok: true`, `classification: "healthy"`, `detail: "/opt/hopper-v4/bin/hopper"` to `ok: false` with `classification: "missing_analysis_engine"`. This is asserted at service level, not from a CLI run. - **Remaining proof gaps:** - No real macOS or Windows host; platforms are modeled through the doctor host fixture. - No real Hopper installation or launch. - Performance was not measured. The only cost change is fewer probes. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed Run on Linux with Node 24.18.0 and npm 11.16.0, on `bd5d189a8`: - `npm run test:local --` on `Doctor`, `Doctor.*`, all `Setup*` service tests, `MacHopperPaths`, `LinuxHopper`, `config`, `GhidraDoctor` and `doctorRuntime`: 12 files, 277 tests passed. - `npm run test:focused -- tests/boundary/filesystem/hopperLauncherSelection.test.ts tests/boundary/cli/doctorHopperDiscovery.test.ts tests/boundary/filesystem/doctorSystemHostFilesystem.test.ts tests/boundary/cli/setupProviderReadiness.test.ts tests/boundary/filesystem/setupUnavailableProvider.test.ts tests/boundary/cli/cliSetup.test.ts tests/boundary/filesystem/setupConfig.test.ts`: 7 files, 49 tests passed. - After keeping doctor's scan asynchronous (Greptile review): the same unit set, 12 files, 277 tests passed; the first five boundary files above, 15 tests passed; `npm run check:fast` passed. - After merging `upstream/main` at `4043e71f6` (merge commit `1cce496f6`): the same unit set, 12 files, 278 tests passed; the seven boundary files above, 50 tests passed; `npx tsc --noEmit -p .`, `npm run check:fast` and `npm run docs:check` passed; `npm run verify:test-discovery` discovered all 2020 test files exactly once. - CI on `5ffad47e1` failed only in the Windows capability lane: `tests/acceptance/webModuleCli.test.ts` exceeded its 15000 ms process deadline after printing its complete result. That test traces web modules and does not touch files in this PR; the same lane passed on `0151bdc56`. This push reruns CI. - CI on `1cce496f6` passed, including the Windows lane. - After merging `upstream/main` at `9eb829aca`, conflicts with #3422 (Linux architecture gate) and #5235 (POSIX joins in `MacHopperPaths.ts`) were resolved: `MacHopperPaths.ts` keeps both renamed-bundle scans on `posix.join`, `DoctorDiagnostics.ts` keeps the shared owner plus #3422's `LINUX_HOPPER_SETUP_HOSTS`, and the scan agreement test now uses #5235's Windows-safe temporary home. - The same unit set: 12 files, 313 tests passed. The seven boundary files above: 51 tests passed. - `npx tsc --noEmit -p .`, `npm run check:fast` and `npm run docs:check` passed; `npm run verify:test-discovery` discovered all 2105 test files exactly once. - Greptile follow-up (`4dab6bc9f`): the doctor discovery table now models launchers with `posix.join`, matching runtime since #5235, while filesystem setup stays native. `Doctor`, `Doctor.*`, `MacHopperPaths` and `config` tests: 4 files, 148 tests passed; `npm run check:fast` passed. The modeled and runtime launcher strings were checked to agree for drive-letter, UNC and POSIX homes; the table was not run on Windows locally. - `npm run test:local -- src/application/Doctor.test.ts` with only the source files reverted: 7 failed (the new rows), 59 passed. - `npx tsc --noEmit -p .`: clean. - `npm run check:fast` (typecheck and lint): passed. - `npx oxlint` on the changed files: 0 errors. - `Doctor.ts` and `LinuxHopper.ts` keep their existing size and complexity warnings. `Doctor.ts` shrinks from 746 to 727 lines; `systemDoctorHost` grows from 225 to 226 lines. - `npm run docs:check`: passed. - `npm run verify:test-discovery`: discovered all 1971 test files exactly once. - `npx oxfmt --check` on the changed files and `git diff --check`: clean. - Not run: `npm run check:pr`, real Hopper or macOS/Windows verification. ## Compatibility, safety, and release - **Breaking changes or migration steps:** none. Runtime selection is unchanged. Doctor stops reporting another platform's launcher; users relying on such a path can set `HOPPER_LAUNCHER_PATH`, which doctor still checks as given. - **Real Hopper/Ghidra, browser, or OS coverage:** Linux only; macOS and Windows behavior is modeled with the doctor host fixture. - **Package or release metadata impact:** none. - **Security, privacy, process, or containment review:** doctor runs fewer filesystem probes and no Homebrew process on Linux or Windows. Nothing new is executed or written. ## Author readiness <!-- The human owner completes these declarations before requesting review. The PR author is the owner by default. A different owner must explicitly accept ownership on this PR. AI agents must leave these declarations to a human to dictate to them or there could be catastrophic consequences for many users of REA. Draft PRs may leave them unchecked. These declarations record initial readiness when opening the PR for review; later pushes do not require a new human sign-off. Keep the description and validation evidence current as the work changes. See CONTRIBUTING.md#pull-request-ownership-and-readiness. --> Human owner: @SandstromPL - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:46:19 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7228
No description provided.