[PR #6832] [MERGED] fix(windows): explain when Windows refuses to load the verified native addon #7422

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6832
Author: @dark13b
Created: 10/23/2026
Status: ✅ Merged
Merged: 10/24/2026
Merged by: @morluto

Base: main ← Head: fix/windows-native-block-and-posix-hopper-paths


📝 Commits (1)

  • 0c03802 fix(windows): explain when Windows refuses to load the verified native addon

📊 Changes

5 files changed (+65 additions, -10 deletions)

View changed files

📝 docs/user-visible-errors.csv (+1 -0)
📝 docs/windows-ghidra-p0.md (+5 -2)
📝 src/process/WindowsAuthority.ts (+9 -6)
📝 src/windows/WindowsNativeLoader.test.ts (+29 -0)
📝 src/windows/WindowsNativeLoader.ts (+21 -2)

📄 Description

Summary

Fixes #5723

When Windows refuses to load rea-windows-x64.node (for example Smart App Control or an App Control policy), rea doctor and the provider diagnostics told the user to restore or rebuild the native files. The file had already passed the manifest version and SHA-256 checks, so that advice cannot help. This reports the refusal as its own failure stage with accurate guidance.

Problem and expected behavior

Smallest trigger: the loader's loadArtifact() throws because the OS blocked the module load (the report quotes "An Application Control policy has blocked this file").

Before: loadWindowsNativeAuthority caught that in its outer catch and returned failureStage: "artifact". inspectWindowsNativeReadiness maps that stage to "Use the matching Windows x64 REA package, or restore native/windows/build/manifest.json and native/windows/build/rea-windows-x64.node ...".

Expected (from the issue): doctor says what the user can do without disabling Smart App Control.

Change and scope

  • src/windows/WindowsNativeLoader.ts: only the host.loadArtifact() call is wrapped. A throw there returns the new failureStage: "load" (still not retryable). The reason keeps the OS error text and adds the exported WINDOWS_NATIVE_LOAD_REFUSED_REMEDIATION: the file matched the manifest so restoring it will not help; if Windows reports an Application Control block, Smart App Control or an App Control for Business policy refused it; Ghidra and JADX need the native controls on Windows while rea setup can still register clients; run REA on a host whose policy allows the file, or ask the maintainers about a signed build. It does not tell the user to disable Smart App Control.
  • src/process/WindowsAuthority.ts: the load stage keeps the documented code runtime_missing (docs/windows-ghidra-p0.md already documents unloadable artifacts that way) and uses the new remediation.
  • docs/windows-ghidra-p0.md (one sentence) and docs/user-visible-errors.csv (row 93) describe the new stage and copy.

Not included:

  • Signing or any release change for the addon. That is a maintainer decision.
  • A setup change. The issue says rea setup returned needs_human with no planned actions. Nothing in src/application/Setup*.ts uses the native controls. With the addon unavailable, the published rea-agents@6.7.0 CLI still planned and applied the claude_code registration (details below), so there is no gate to remove.
  • The generic JADX remediation and the Ghidra ghidra-java row ("Update JAVA_HOME") for this failure. That mapping is separate.
  • Matching on the OS error text. WindowsAuthority.ts says not to guess from it, so the guidance is phrased conditionally.

Contract and boundary impact

  • Semantic owner and earliest changed stage: loadWindowsNativeAuthority in src/windows/WindowsNativeLoader.ts, at the module load, after the manifest and digest checks.
  • Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable.
  • CLI and MCP/tool-catalog contract: the windows_native_failure stage can now be load, and the readiness remediation text changes for that case. Codes are unchanged (runtime_missing). No tool schema changes.
  • Provider, bridge, target-format, or platform compatibility: Windows only; no provider change.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable.
  • Generated metadata (docs/public/product-catalog.json), 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.
  • 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/windows/WindowsNativeLoader.test.ts, one case using the existing loader fixture. loadArtifact throws "An Application Control policy has blocked this file." The test checks failureStage: "load", the OS text kept in reason, no retryable, code runtime_missing, a remediation that mentions Smart App Control, and no "restore native/windows/build" advice.
  • Base reproduction or other evidence: the new test fails without the change (expected load, received artifact) and passes with it. This is a simulated refusal. I could not reproduce the real block because Smart App Control is off on my machine.
  • Setup finding: I ran the published rea-agents@6.7.0 CLI with the addon temporarily unavailable (renamed, restored afterwards) and a scratch HOME/USERPROFILE/APPDATA/LOCALAPPDATA. rea setup --client claude_code --yes --format json returned ready, planned and applied configure_client:claude_code and install_skill:claude_code. A second run returned ready with nothing planned. The unscoped rea doctor showed the native failure only in the jadx and ghidra-java rows. That simulated failure was ENOENT (artifact stage), not the real OS refusal.
  • Where needs_human with an empty plan can come from: registration already present plus a failing in-scope doctor check (Setup.ts returns "Run rea doctor and apply each reported remediation."). I reproduced that shape on main with a failing Node version check, with the addon present or absent. Which in-scope check failed for the reporter is unknown; their report quotes only the out-of-scope jadx row.
  • User-visible CLI/MCP output (if applicable): the new reason reads "REA Windows native controls are unavailable: Windows refused to load the verified native/windows/build/rea-windows-x64.node: The file matched the package manifest, so restoring or reinstalling it will not help. ..." (full text in docs/user-visible-errors.csv, row 93).
  • Remaining proof gaps: no real Smart App Control block, so the exact ERR_DLOPEN_FAILED message format is not observed live; the test uses the text quoted in the issue.

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

Windows 11 x64 (10.0.26200), Node 24.21.0. .nvmrc pins 24.22.1 and main requires ^24.22.1, so this ran below the pin and npm ci needed --engine-strict=false.

  • npm run build:cached — passed
  • npm run test:focused -- src/windows/WindowsNativeLoader.test.ts src/ghidra/GhidraDoctor.test.ts src/ghidra/GhidraProvider.behavior.test.ts src/application/Setup.planning.test.ts src/application/Doctor.test.ts — 5 files, 282 passed
  • npm run test:focused -- tests/boundary/process/providerProcess.test.ts — 3 failed, 18 passed, 5 skipped; the same 3 fail on clean main (checked with my change stashed)
  • npm run check:fast — passed
  • npm run check — exit 0 (lint 0 errors, warnings only; format, knip, metadata and architecture checks passed)
  • npm run docs:check — exit 0

Compatibility, safety, and release

  • Breaking changes or migration steps: none. A caller that matched failureStage: "artifact" for an OS load refusal now sees load.
  • Real Hopper/Ghidra, browser, or OS coverage: no real Ghidra run; the change is in the native loader diagnostics. Windows 11 x64 only; not run on Linux or macOS.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: the loader still verifies version, ABI, architecture and digest before loading and still grants no authority on failure. Only the failure classification and message change.

Author readiness

Human owner: @dark13b

  • 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.

🔄 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/6832 **Author:** [@dark13b](https://github.com/dark13b) **Created:** 10/23/2026 **Status:** ✅ Merged **Merged:** 10/24/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/windows-native-block-and-posix-hopper-paths` --- ### 📝 Commits (1) - [`0c03802`](https://github.com/morluto/rea/commit/0c03802af5fdf06181938f9613b2e7eec18cbd39) fix(windows): explain when Windows refuses to load the verified native addon ### 📊 Changes **5 files changed** (+65 additions, -10 deletions) <details> <summary>View changed files</summary> 📝 `docs/user-visible-errors.csv` (+1 -0) 📝 `docs/windows-ghidra-p0.md` (+5 -2) 📝 `src/process/WindowsAuthority.ts` (+9 -6) 📝 `src/windows/WindowsNativeLoader.test.ts` (+29 -0) 📝 `src/windows/WindowsNativeLoader.ts` (+21 -2) </details> ### 📄 Description ## Summary Fixes #5723 When Windows refuses to load `rea-windows-x64.node` (for example Smart App Control or an App Control policy), `rea doctor` and the provider diagnostics told the user to restore or rebuild the native files. The file had already passed the manifest version and SHA-256 checks, so that advice cannot help. This reports the refusal as its own failure stage with accurate guidance. ## Problem and expected behavior Smallest trigger: the loader's `loadArtifact()` throws because the OS blocked the module load (the report quotes "An Application Control policy has blocked this file"). Before: `loadWindowsNativeAuthority` caught that in its outer `catch` and returned `failureStage: "artifact"`. `inspectWindowsNativeReadiness` maps that stage to "Use the matching Windows x64 REA package, or restore native/windows/build/manifest.json and native/windows/build/rea-windows-x64.node ...". Expected (from the issue): doctor says what the user can do without disabling Smart App Control. ## Change and scope - `src/windows/WindowsNativeLoader.ts`: only the `host.loadArtifact()` call is wrapped. A throw there returns the new `failureStage: "load"` (still not retryable). The reason keeps the OS error text and adds the exported `WINDOWS_NATIVE_LOAD_REFUSED_REMEDIATION`: the file matched the manifest so restoring it will not help; if Windows reports an Application Control block, Smart App Control or an App Control for Business policy refused it; Ghidra and JADX need the native controls on Windows while `rea setup` can still register clients; run REA on a host whose policy allows the file, or ask the maintainers about a signed build. It does not tell the user to disable Smart App Control. - `src/process/WindowsAuthority.ts`: the `load` stage keeps the documented code `runtime_missing` (`docs/windows-ghidra-p0.md` already documents unloadable artifacts that way) and uses the new remediation. - `docs/windows-ghidra-p0.md` (one sentence) and `docs/user-visible-errors.csv` (row 93) describe the new stage and copy. Not included: - Signing or any release change for the addon. That is a maintainer decision. - A setup change. The issue says `rea setup` returned `needs_human` with no planned actions. Nothing in `src/application/Setup*.ts` uses the native controls. With the addon unavailable, the published `rea-agents@6.7.0` CLI still planned and applied the `claude_code` registration (details below), so there is no gate to remove. - The generic JADX remediation and the Ghidra `ghidra-java` row ("Update JAVA_HOME") for this failure. That mapping is separate. - Matching on the OS error text. `WindowsAuthority.ts` says not to guess from it, so the guidance is phrased conditionally. ## Contract and boundary impact - Semantic owner and earliest changed stage: `loadWindowsNativeAuthority` in `src/windows/WindowsNativeLoader.ts`, at the module load, after the manifest and digest checks. - Contribution scope fit and linked maintainer decision: ordinary fix within existing boundaries; not applicable. - CLI and MCP/tool-catalog contract: the `windows_native_failure` stage can now be `load`, and the readiness remediation text changes for that case. Codes are unchanged (`runtime_missing`). No tool schema changes. - Provider, bridge, target-format, or platform compatibility: Windows only; no provider change. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details (if applicable): not applicable. - Generated metadata (`docs/public/product-catalog.json`), 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. - [ ] 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. - [x] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - Tests added or updated: `src/windows/WindowsNativeLoader.test.ts`, one case using the existing loader fixture. `loadArtifact` throws "An Application Control policy has blocked this file." The test checks `failureStage: "load"`, the OS text kept in `reason`, no `retryable`, code `runtime_missing`, a remediation that mentions Smart App Control, and no "restore native/windows/build" advice. - Base reproduction or other evidence: the new test fails without the change (expected `load`, received `artifact`) and passes with it. This is a simulated refusal. I could not reproduce the real block because Smart App Control is off on my machine. - Setup finding: I ran the published `rea-agents@6.7.0` CLI with the addon temporarily unavailable (renamed, restored afterwards) and a scratch HOME/USERPROFILE/APPDATA/LOCALAPPDATA. `rea setup --client claude_code --yes --format json` returned `ready`, planned and applied `configure_client:claude_code` and `install_skill:claude_code`. A second run returned `ready` with nothing planned. The unscoped `rea doctor` showed the native failure only in the `jadx` and `ghidra-java` rows. That simulated failure was ENOENT (artifact stage), not the real OS refusal. - Where `needs_human` with an empty plan can come from: registration already present plus a failing in-scope doctor check (`Setup.ts` returns "Run rea doctor and apply each reported remediation."). I reproduced that shape on `main` with a failing Node version check, with the addon present or absent. Which in-scope check failed for the reporter is unknown; their report quotes only the out-of-scope jadx row. - User-visible CLI/MCP output (if applicable): the new reason reads "REA Windows native controls are unavailable: Windows refused to load the verified native/windows/build/rea-windows-x64.node: <OS error> The file matched the package manifest, so restoring or reinstalling it will not help. ..." (full text in `docs/user-visible-errors.csv`, row 93). - Remaining proof gaps: no real Smart App Control block, so the exact `ERR_DLOPEN_FAILED` message format is not observed live; the test uses the text quoted in the issue. 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 Windows 11 x64 (10.0.26200), Node 24.21.0. `.nvmrc` pins 24.22.1 and `main` requires `^24.22.1`, so this ran below the pin and `npm ci` needed `--engine-strict=false`. - `npm run build:cached` — passed - `npm run test:focused -- src/windows/WindowsNativeLoader.test.ts src/ghidra/GhidraDoctor.test.ts src/ghidra/GhidraProvider.behavior.test.ts src/application/Setup.planning.test.ts src/application/Doctor.test.ts` — 5 files, 282 passed - `npm run test:focused -- tests/boundary/process/providerProcess.test.ts` — 3 failed, 18 passed, 5 skipped; the same 3 fail on clean `main` (checked with my change stashed) - `npm run check:fast` — passed - `npm run check` — exit 0 (lint 0 errors, warnings only; format, knip, metadata and architecture checks passed) - `npm run docs:check` — exit 0 ## Compatibility, safety, and release - Breaking changes or migration steps: none. A caller that matched `failureStage: "artifact"` for an OS load refusal now sees `load`. - Real Hopper/Ghidra, browser, or OS coverage: no real Ghidra run; the change is in the native loader diagnostics. Windows 11 x64 only; not run on Linux or macOS. - Package or release metadata impact: none. - Security, privacy, process, or containment review: the loader still verifies version, ABI, architecture and digest before loading and still grants no authority on failure. Only the failure classification and message change. ## Author readiness Human owner: @dark13b - [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 - [ ] 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. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:47:45 +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#7422
No description provided.