[PR #963] [MERGED] fix(linux): improve Hopper reliability and CachyOS support #2537

Closed
opened 2026-10-17 21:07:18 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/963
Author: @Namnarak
Created: 10/7/2026
Status: ✅ Merged
Merged: 10/7/2026
Merged by: @N0zoM1z0

Base: main ← Head: fix/linux-hopper-reliability


📝 Commits (5)

  • f7a5b66 fix(linux): support CachyOS Hopper hosts
  • f5fbbc3 fix(config): reuse user-local Hopper launcher
  • 16777fe fix(hopper): harden Linux demo dialog handling
  • 9fe3714 chore: retrigger CI after PR title fix
  • d8288ef fix(linux): align Hopper defaults and support docs

📊 Changes

21 files changed (+329 additions, -37 deletions)

View changed files

📝 CONTRIBUTING.md (+1 -1)
📝 README.md (+4 -4)
📝 README_ar.md (+3 -3)
📝 README_ja.md (+2 -2)
📝 README_ko.md (+2 -2)
📝 README_zh.md (+2 -2)
📝 docs/user-visible-errors.csv (+2 -2)
📝 scripts/hopper-demo-x11.py (+65 -7)
📝 src/application/Doctor.test.ts (+1 -1)
📝 src/application/DoctorDiagnostics.ts (+1 -1)
📝 src/application/LinuxHopper.test.ts (+3 -0)
📝 src/application/LinuxHopper.ts (+1 -0)
📝 src/application/Setup.recovery.test.ts (+1 -1)
📝 src/application/SetupHost.ts (+1 -1)
📝 src/config.test.ts (+1 -6)
📝 src/config/parseConfig.ts (+27 -4)
📝 tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts (+46 -0)
➕ tests/composition/hopperConfig.test.ts (+38 -0)
📝 tests/conformance/readmeConsistency.test.ts (+1 -0)
➕ tests/fixtures/hopperCleanupTimeout.py (+50 -0)

...and 1 more files

📄 Description

Summary

This PR improves the reliability of REA's Linux Hopper integration based on failures reproduced and tested on CachyOS.

It includes four related fixes:

  • detect Hopper's demo Registration dialog semantically instead of matching one exact window geometry
  • keep Hopper child cleanup bounded instead of waiting indefinitely after SIGTERM
  • make runtime Hopper launcher discovery consistent with rea doctor for the legacy user-local installation
  • explicitly support CachyOS without implicitly marking every Arch-derived distribution as supported

Test environment

Tested locally on:

  • CachyOS Linux (ID=cachyos, ID_LIKE=arch)
  • Wayland desktop host
  • REA private Xvfb/X11 Hopper session
  • Hopper 6.4.2 demo build
  • Hopper launcher at ~/.local/share/rea/hopper/bin/Hopper

Real-world testing so far has been performed on one machine/environment, so I do not want to claim universal compatibility yet.

Hopper demo dialog detection

The helper currently expects the Registration dialog to have one exact geometry:

EXPECTED_DIALOG = (189, 370, 901, 284)
DEMO_CLICK = (305, 632)

On the tested system, the actual Registration dialog was 930x284, causing exit code 76 (unsupported_demo_dialog) even though the Hopper binary matched the supported digest.

The dialog exposes useful X11 metadata:

WM_NAME = "Registration"
_NET_WM_NAME = "Registration — Hopper Disassembler"
WM_CLASS = "Hopper", "Hopper"
WM_TRANSIENT_FOR = <Hopper Disassembler window>

This change identifies the Registration window and verifies that its WM_TRANSIENT_FOR parent is the Hopper Disassembler window. The Demo click is then calculated relative to the detected dialog instead of using an absolute screen coordinate.

I also tested moving and resizing the dialog to 1200x284, outside the previous exact geometry, and the helper still detected and dismissed it correctly.

Hopper launcher path consistency

rea doctor already checks the legacy user-local path:

~/.local/share/rea/hopper/bin/Hopper

but normal REA commands default to:

/opt/hopper/bin/Hopper

This can produce a state where Doctor reports Hopper healthy while analysis commands fail with executable_missing.

The runtime selection now keeps explicit configuration authoritative and otherwise uses:

  1. HOPPER_LAUNCHER_PATH
  2. executable /opt/hopper/bin/Hopper
  3. executable user-local Hopper
  4. the existing system path as the diagnostic fallback

An explicitly configured launcher path is never overridden.

CachyOS support

CachyOS reports:

ID=cachyos
ID_LIKE=arch

REA already classifies its package family as Arch, but the host support check only accepts id === "arch".

This change explicitly admits cachyos rather than accepting every ID_LIKE=arch distribution.

Validated classification:

Arch      -> supported
CachyOS   -> supported
Manjaro   -> unsupported
Garuda    -> unsupported

Bounded Hopper cleanup

One error cleanup path used:

child.terminate()
child.wait()

with no timeout.

The helper already has a bounded stop_process() implementation, so the child cleanup now reuses it.

A test process intentionally ignoring SIGTERM was terminated via SIGKILL after the existing ~2 second timeout, as expected.

Validation

Targeted tests:

  • src/application/LinuxHopper.test.ts
  • tests/composition/hopperConfig.test.ts
  • tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts

Result: 45/45 passed

Additional checks passed:

  • typecheck
  • lint
  • format check
  • knip
  • build
  • Python syntax checks

I also ran the built branch against real Hopper without setting HOPPER_LAUNCHER_PATH.

The following completed successfully:

  • rea analyze
  • rea search
  • rea function
  • rea decompile

A small ELF fixture with a known main -> alpha -> beta call graph and known string was also used during testing.

No leftover Hopper/Xvfb analysis processes were observed after the completed runs.

Testing limitation

The fixes appear correct for the reproduced failure modes and the tested environment, but broader Linux/Hopper/X11 coverage would still be useful before considering the behavior universally verified.

AI assistance disclosure

This investigation, patch preparation, and testing were performed with assistance from ChatGPT.

ChatGPT was given access to my local development environment through tools connected to my account and was used to inspect REA, reproduce the failures, prepare the patches, run tests, and compare the local implementation against upstream.

This PR was prepared and submitted through my connected GitHub account by ChatGPT on my behalf, with my explicit approval. I reviewed the results before authorizing the upstream submission.

Existing upstream fix not included

During debugging I also encountered a Hopper bridge issue involving list_strings / list_names, but that issue is already fixed in newer REA code, so it is intentionally not included here.


🔄 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/963 **Author:** [@Namnarak](https://github.com/Namnarak) **Created:** 10/7/2026 **Status:** ✅ Merged **Merged:** 10/7/2026 **Merged by:** [@N0zoM1z0](https://github.com/N0zoM1z0) **Base:** `main` ← **Head:** `fix/linux-hopper-reliability` --- ### 📝 Commits (5) - [`f7a5b66`](https://github.com/morluto/rea/commit/f7a5b66df2151864b00dc81cf2e29ecb3fe97aec) fix(linux): support CachyOS Hopper hosts - [`f5fbbc3`](https://github.com/morluto/rea/commit/f5fbbc3fdf90cc5fd836a538ebd0697b817d8063) fix(config): reuse user-local Hopper launcher - [`16777fe`](https://github.com/morluto/rea/commit/16777fe7b00c96f8a34553fcf02c326bfe9413d9) fix(hopper): harden Linux demo dialog handling - [`9fe3714`](https://github.com/morluto/rea/commit/9fe37142ee4eabb5c7272133f7724c185b1ae714) chore: retrigger CI after PR title fix - [`d8288ef`](https://github.com/morluto/rea/commit/d8288ef1c8bb06e5b35823c5c9c0186abd5d05f8) fix(linux): align Hopper defaults and support docs ### 📊 Changes **21 files changed** (+329 additions, -37 deletions) <details> <summary>View changed files</summary> 📝 `CONTRIBUTING.md` (+1 -1) 📝 `README.md` (+4 -4) 📝 `README_ar.md` (+3 -3) 📝 `README_ja.md` (+2 -2) 📝 `README_ko.md` (+2 -2) 📝 `README_zh.md` (+2 -2) 📝 `docs/user-visible-errors.csv` (+2 -2) 📝 `scripts/hopper-demo-x11.py` (+65 -7) 📝 `src/application/Doctor.test.ts` (+1 -1) 📝 `src/application/DoctorDiagnostics.ts` (+1 -1) 📝 `src/application/LinuxHopper.test.ts` (+3 -0) 📝 `src/application/LinuxHopper.ts` (+1 -0) 📝 `src/application/Setup.recovery.test.ts` (+1 -1) 📝 `src/application/SetupHost.ts` (+1 -1) 📝 `src/config.test.ts` (+1 -6) 📝 `src/config/parseConfig.ts` (+27 -4) 📝 `tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts` (+46 -0) ➕ `tests/composition/hopperConfig.test.ts` (+38 -0) 📝 `tests/conformance/readmeConsistency.test.ts` (+1 -0) ➕ `tests/fixtures/hopperCleanupTimeout.py` (+50 -0) _...and 1 more files_ </details> ### 📄 Description ## Summary This PR improves the reliability of REA's Linux Hopper integration based on failures reproduced and tested on CachyOS. It includes four related fixes: - detect Hopper's demo Registration dialog semantically instead of matching one exact window geometry - keep Hopper child cleanup bounded instead of waiting indefinitely after SIGTERM - make runtime Hopper launcher discovery consistent with `rea doctor` for the legacy user-local installation - explicitly support CachyOS without implicitly marking every Arch-derived distribution as supported ## Test environment Tested locally on: - CachyOS Linux (`ID=cachyos`, `ID_LIKE=arch`) - Wayland desktop host - REA private Xvfb/X11 Hopper session - Hopper 6.4.2 demo build - Hopper launcher at `~/.local/share/rea/hopper/bin/Hopper` Real-world testing so far has been performed on one machine/environment, so I do not want to claim universal compatibility yet. ## Hopper demo dialog detection The helper currently expects the Registration dialog to have one exact geometry: ```py EXPECTED_DIALOG = (189, 370, 901, 284) DEMO_CLICK = (305, 632) ``` On the tested system, the actual Registration dialog was `930x284`, causing exit code 76 (`unsupported_demo_dialog`) even though the Hopper binary matched the supported digest. The dialog exposes useful X11 metadata: ```text WM_NAME = "Registration" _NET_WM_NAME = "Registration — Hopper Disassembler" WM_CLASS = "Hopper", "Hopper" WM_TRANSIENT_FOR = <Hopper Disassembler window> ``` This change identifies the Registration window and verifies that its `WM_TRANSIENT_FOR` parent is the Hopper Disassembler window. The Demo click is then calculated relative to the detected dialog instead of using an absolute screen coordinate. I also tested moving and resizing the dialog to `1200x284`, outside the previous exact geometry, and the helper still detected and dismissed it correctly. ## Hopper launcher path consistency `rea doctor` already checks the legacy user-local path: ```text ~/.local/share/rea/hopper/bin/Hopper ``` but normal REA commands default to: ```text /opt/hopper/bin/Hopper ``` This can produce a state where Doctor reports Hopper healthy while analysis commands fail with `executable_missing`. The runtime selection now keeps explicit configuration authoritative and otherwise uses: 1. `HOPPER_LAUNCHER_PATH` 2. executable `/opt/hopper/bin/Hopper` 3. executable user-local Hopper 4. the existing system path as the diagnostic fallback An explicitly configured launcher path is never overridden. ## CachyOS support CachyOS reports: ```text ID=cachyos ID_LIKE=arch ``` REA already classifies its package family as Arch, but the host support check only accepts `id === "arch"`. This change explicitly admits `cachyos` rather than accepting every `ID_LIKE=arch` distribution. Validated classification: ```text Arch -> supported CachyOS -> supported Manjaro -> unsupported Garuda -> unsupported ``` ## Bounded Hopper cleanup One error cleanup path used: ```py child.terminate() child.wait() ``` with no timeout. The helper already has a bounded `stop_process()` implementation, so the child cleanup now reuses it. A test process intentionally ignoring SIGTERM was terminated via SIGKILL after the existing ~2 second timeout, as expected. ## Validation Targeted tests: - `src/application/LinuxHopper.test.ts` - `tests/composition/hopperConfig.test.ts` - `tests/boundary/providers/hopper/linuxPrivateDisplay.test.ts` Result: **45/45 passed** Additional checks passed: - typecheck - lint - format check - knip - build - Python syntax checks I also ran the built branch against real Hopper without setting `HOPPER_LAUNCHER_PATH`. The following completed successfully: - `rea analyze` - `rea search` - `rea function` - `rea decompile` A small ELF fixture with a known `main -> alpha -> beta` call graph and known string was also used during testing. No leftover Hopper/Xvfb analysis processes were observed after the completed runs. ## Testing limitation The fixes appear correct for the reproduced failure modes and the tested environment, but broader Linux/Hopper/X11 coverage would still be useful before considering the behavior universally verified. ## AI assistance disclosure This investigation, patch preparation, and testing were performed with assistance from ChatGPT. ChatGPT was given access to my local development environment through tools connected to my account and was used to inspect REA, reproduce the failures, prepare the patches, run tests, and compare the local implementation against upstream. This PR was prepared and submitted through my connected GitHub account by ChatGPT on my behalf, with my explicit approval. I reviewed the results before authorizing the upstream submission. ## Existing upstream fix not included During debugging I also encountered a Hopper bridge issue involving `list_strings` / `list_names`, but that issue is already fixed in newer REA code, so it is intentionally not included here. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:07:18 +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#2537
No description provided.