[PR #6277] [MERGED] fix(windows): report missing native launch controls as unavailable capabilities #7250

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6277
Author: @AmmarJamil23
Created: 10/22/2026
Status: ✅ Merged
Merged: 10/22/2026
Merged by: @morluto

Base: main ← Head: fix/windows-native-control-capability


📝 Commits (2)

  • 2548806 fix(windows): report missing native launch controls as unavailable capabilities
  • e60a3c5 refactor(errors): drop capability imports superseded by the shared helper

📊 Changes

11 files changed (+298 additions, -57 deletions)

View changed files

📝 src/adb/AdbProvider.ts (+7 -6)
📝 src/browser/WebBundleAnalysisWorker.ts (+6 -9)
📝 src/javascript/analysis/JavaScriptAnalysisWorker.ts (+6 -9)
📝 src/javascript/sourceMaps/SourceMapCommand.ts (+6 -9)
📝 src/pcap/PcapSnapshot.ts (+6 -9)
📝 src/process/PrivateRuntimeRootUnavailableError.ts (+3 -3)
➕ src/process/RuntimeControlUnavailableError.ts (+43 -0)
📝 src/wasm/WabtFailures.ts (+7 -5)
📝 src/windows/WindowsOwnedProcess.test.ts (+40 -1)
📝 src/windows/WindowsOwnedProcess.ts (+27 -6)
➕ tests/process-global/windowsNativeControlCapability.test.ts (+147 -0)

📄 Description

Summary

Fixes #6050.

An admitted Windows native artifact may predate the optional protocolStdin or jobMemoryLimit controls (the loader schema allows both to be omitted). WindowsOwnedProcess correctly refuses such launches, but it threw a plain Error, so providers projected the refusal as execution_failure with generic rea doctor advice; the package remedy appeared only in details.diagnostics.error_message. The refusal is now a typed unavailable-capability outcome: code: capability_unavailable, retryable: false, with the missing control in the primary message and the matching-package recovery in remediation.action.

Problem and expected behavior

Smallest trigger: on Windows under Bun, trace_web_source_location launches the source-map codec with a Job Object memory limit. With an artifact whose inspection omits jobMemoryLimit, the launch is refused before process_spawn (correct), and the public error was:

{"code":"execution_failure","message":"Analysis could not complete. Run `rea doctor` ...","details":{"diagnostics":{"error_message":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package."}}}

Violated invariant (AGENTS.md): expected failures use the tagged error algebra. The issue asks for a non-retryable AnalysisCapabilityUnavailableError carrying the missing control and package remediation.

Change and scope

The root cause is the producing boundary: the refusal had no type, so each consumer could only fall back to a generic adapter error. PrivateRuntimeRootUnavailableError already plays this role for one host control, and six adapters each hand-built the same AnalysisCapabilityUnavailableError from it. Rather than add a seventh special case to every consumer:

  • src/process/RuntimeControlUnavailableError.ts (new): abstract owner of expected host-control refusals (code, retryable, optional remediationAction) plus runtimeControlCapabilityError(providerId, operation, cause), the single projection to AnalysisCapabilityUnavailableError.
  • PrivateRuntimeRootUnavailableError now extends it. Its code, message and retryability are unchanged, and since it sets no remediation its projection is byte-for-byte what the adapters built before.
  • WindowsNativeControlUnavailableError (new, in WindowsOwnedProcess.ts) records the missing control (protocol-stdin | job-memory-limit) and the matching-package remediation; both refusals throw it.
  • The six adapters that recognized the private-runtime-root error (source map, JavaScript worker, web bundle, ADB, pcap snapshot, WABT) now recognize the base type through the shared helper, which removes their duplicated construction.

Not changed: the refusal itself and its position before any native call; the POSIX memoryLimitBytes guard in ProviderProcess (memory limits are only requested on Windows, so that branch is an internal invariant, not a host capability); native readiness/doctor reporting of optional controls (mentioned in the issue as context; left for a separate change).

Contribution scope: ordinary error-classification fix within existing boundaries; no scope decision needed. It does not relax any required control.

Contract and boundary impact

  • Semantic owner and earliest changed stage: Windows owned-process launch admission (WindowsOwnedProcess); projection owned by runtimeControlCapabilityError.
  • Contribution scope fit and linked maintainer decision: not applicable (typed classification of an existing refusal).
  • CLI and MCP/tool-catalog contract: no schema or catalog change; affected tools now return the existing capability_unavailable code for this case instead of execution_failure.
  • Provider, bridge, target-format, or platform compatibility: Windows only for the new refusal type; artifacts with both controls are unaffected.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Target selection, authority, upstream behavior, and cleanup details: unchanged; the launch is still refused before process_spawn, and the acquired runtime root is still released (asserted).
  • Generated metadata, package, or installation impact: none; npm run docs:check passed with no generated changes.

Evidence and regression coverage

  • Tests added or updated:
    • tests/process-global/windowsNativeControlCapability.test.ts: public MCP trace_web_source_location with an earlier-artifact authority (no jobMemoryLimit) and the Bun-on-Windows codec limit; asserts capability_unavailable, retryable: false, the control in the message, package remediation, no native call, and runtime-root release. Portable: it simulates win32, following the issue's reproduction approach.
    • src/windows/WindowsOwnedProcess.test.ts: both refusals throw WindowsNativeControlUnavailableError with the right control and no native call (the protocol-stdin case was previously untested).
  • Base reproduction: with only the src/ changes stashed, the new MCP test fails with code: "execution_failure" against expected capability_unavailable; with the change, it passes.
  • Real Windows observation (not committed, since the repo's testing guide notes simulated Windows controls do not establish native behavior): on Windows 11 x64 with the real loader and the published rea-agents@6.7.0 native artifact (sha512 verified), real inspection reports jobMemoryLimit: true. With that one field removed to model an earlier artifact, and the real platform, runtime root and DACL path, the MCP response changed from the execution_failure above to:
{"code":"capability_unavailable","category":"unsupported_provider","message":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package.","retryable":false,"remediation":{"action":"Install the matching current Windows x64 REA package; its native inspection must prove this control. REA does not launch without it, so retrying the unchanged installation will not succeed."},"details":{"provider_id":"source-map-decoder","operation":"trace_web_source_location","reason":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package."}}

No process_spawn occurred in either run.

  • Remaining proof gaps: Bun itself was not run (the memory-limit policy was set to its Windows+Bun result, as in the issue). The protocol-stdin path is covered at the unit level and through the shared projection, not by an end-to-end JavaScript-worker call. An actual older native artifact was not available.

Validation performed

Windows 11 x64, Node.js 24.18.0 (pinned), locked dependencies.

  • npm run test:focused -- tests/process-global/windowsNativeControlCapability.test.ts — passes with the fix; fails with execution_failure with src/ changes stashed.
  • npm run test:focused -- src/windows/WindowsOwnedProcess.test.ts — 21/21 passed.
  • Consumer and process suites (AdbProvider, SourceMapCommand, SourceMapDecoder, WabtArtifactProvider, WabtFailures, sourceMapRuntimeAvailability, pcapWorkspaceAllocation, webSourceLocationMcp, providerProcess, pcapProviderCrossPlatform, WindowsOwnedProcess) — 32 tests fail on this Windows host both with and without the change (identical set: WabtArtifactProvider 26, SourceMapCommand 3, providerProcess 3; POSIX-oriented expectations). The change introduces no new failures; Linux/macOS CI is needed to confirm those suites.
  • npm run check:fast (typecheck, lint, module boundaries) — passed.
  • npm run verify:test-discovery — passed ("Discovered all 1985 test files exactly once").
  • npm run docs:check — passed; no generated changes.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Callers that saw execution_failure for this refusal now see capability_unavailable (unsupported_provider category), which is the documented code for a provider that cannot execute a declared operation.
  • Real Hopper/Ghidra, browser, or OS coverage: Windows 11 x64 locally (real native loader/runtime root); no Linux/macOS run locally.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: the refusal and its pre-launch position are unchanged; no control is relaxed, and no process starts without the requested control.

Author readiness

Human owner: @AmmarJamil23

  • 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/6277 **Author:** [@AmmarJamil23](https://github.com/AmmarJamil23) **Created:** 10/22/2026 **Status:** ✅ Merged **Merged:** 10/22/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `fix/windows-native-control-capability` --- ### 📝 Commits (2) - [`2548806`](https://github.com/morluto/rea/commit/254880677b75a0e41ad917a5ad6bdc97c7826236) fix(windows): report missing native launch controls as unavailable capabilities - [`e60a3c5`](https://github.com/morluto/rea/commit/e60a3c5d1a8f21ff58b747443854ed5e046cc6b2) refactor(errors): drop capability imports superseded by the shared helper ### 📊 Changes **11 files changed** (+298 additions, -57 deletions) <details> <summary>View changed files</summary> 📝 `src/adb/AdbProvider.ts` (+7 -6) 📝 `src/browser/WebBundleAnalysisWorker.ts` (+6 -9) 📝 `src/javascript/analysis/JavaScriptAnalysisWorker.ts` (+6 -9) 📝 `src/javascript/sourceMaps/SourceMapCommand.ts` (+6 -9) 📝 `src/pcap/PcapSnapshot.ts` (+6 -9) 📝 `src/process/PrivateRuntimeRootUnavailableError.ts` (+3 -3) ➕ `src/process/RuntimeControlUnavailableError.ts` (+43 -0) 📝 `src/wasm/WabtFailures.ts` (+7 -5) 📝 `src/windows/WindowsOwnedProcess.test.ts` (+40 -1) 📝 `src/windows/WindowsOwnedProcess.ts` (+27 -6) ➕ `tests/process-global/windowsNativeControlCapability.test.ts` (+147 -0) </details> ### 📄 Description ## Summary Fixes #6050. An admitted Windows native artifact may predate the optional `protocolStdin` or `jobMemoryLimit` controls (the loader schema allows both to be omitted). `WindowsOwnedProcess` correctly refuses such launches, but it threw a plain `Error`, so providers projected the refusal as `execution_failure` with generic `rea doctor` advice; the package remedy appeared only in `details.diagnostics.error_message`. The refusal is now a typed unavailable-capability outcome: `code: capability_unavailable`, `retryable: false`, with the missing control in the primary message and the matching-package recovery in `remediation.action`. ## Problem and expected behavior Smallest trigger: on Windows under Bun, `trace_web_source_location` launches the source-map codec with a Job Object memory limit. With an artifact whose inspection omits `jobMemoryLimit`, the launch is refused before `process_spawn` (correct), and the public error was: ```json {"code":"execution_failure","message":"Analysis could not complete. Run `rea doctor` ...","details":{"diagnostics":{"error_message":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package."}}} ``` Violated invariant (AGENTS.md): expected failures use the tagged error algebra. The issue asks for a non-retryable `AnalysisCapabilityUnavailableError` carrying the missing control and package remediation. ## Change and scope The root cause is the producing boundary: the refusal had no type, so each consumer could only fall back to a generic adapter error. `PrivateRuntimeRootUnavailableError` already plays this role for one host control, and six adapters each hand-built the same `AnalysisCapabilityUnavailableError` from it. Rather than add a seventh special case to every consumer: - `src/process/RuntimeControlUnavailableError.ts` (new): abstract owner of expected host-control refusals (`code`, `retryable`, optional `remediationAction`) plus `runtimeControlCapabilityError(providerId, operation, cause)`, the single projection to `AnalysisCapabilityUnavailableError`. - `PrivateRuntimeRootUnavailableError` now extends it. Its code, message and retryability are unchanged, and since it sets no remediation its projection is byte-for-byte what the adapters built before. - `WindowsNativeControlUnavailableError` (new, in `WindowsOwnedProcess.ts`) records the missing `control` (`protocol-stdin` | `job-memory-limit`) and the matching-package remediation; both refusals throw it. - The six adapters that recognized the private-runtime-root error (source map, JavaScript worker, web bundle, ADB, pcap snapshot, WABT) now recognize the base type through the shared helper, which removes their duplicated construction. Not changed: the refusal itself and its position before any native call; the POSIX `memoryLimitBytes` guard in `ProviderProcess` (memory limits are only requested on Windows, so that branch is an internal invariant, not a host capability); native readiness/`doctor` reporting of optional controls (mentioned in the issue as context; left for a separate change). Contribution scope: ordinary error-classification fix within existing boundaries; no scope decision needed. It does not relax any required control. ## Contract and boundary impact - Semantic owner and earliest changed stage: Windows owned-process launch admission (`WindowsOwnedProcess`); projection owned by `runtimeControlCapabilityError`. - Contribution scope fit and linked maintainer decision: not applicable (typed classification of an existing refusal). - CLI and MCP/tool-catalog contract: no schema or catalog change; affected tools now return the existing `capability_unavailable` code for this case instead of `execution_failure`. - Provider, bridge, target-format, or platform compatibility: Windows only for the new refusal type; artifacts with both controls are unaffected. - Evidence, artifact, provenance, or reconstruction contract: none. - Target selection, authority, upstream behavior, and cleanup details: unchanged; the launch is still refused before `process_spawn`, and the acquired runtime root is still released (asserted). - Generated metadata, package, or installation impact: none; `npm run docs:check` passed with no generated changes. ## Evidence and regression coverage - Tests added or updated: - `tests/process-global/windowsNativeControlCapability.test.ts`: public MCP `trace_web_source_location` with an earlier-artifact authority (no `jobMemoryLimit`) and the Bun-on-Windows codec limit; asserts `capability_unavailable`, `retryable: false`, the control in the message, package remediation, no native call, and runtime-root release. Portable: it simulates `win32`, following the issue's reproduction approach. - `src/windows/WindowsOwnedProcess.test.ts`: both refusals throw `WindowsNativeControlUnavailableError` with the right `control` and no native call (the protocol-stdin case was previously untested). - Base reproduction: with only the `src/` changes stashed, the new MCP test fails with `code: "execution_failure"` against expected `capability_unavailable`; with the change, it passes. - Real Windows observation (not committed, since the repo's testing guide notes simulated Windows controls do not establish native behavior): on Windows 11 x64 with the real loader and the published `rea-agents@6.7.0` native artifact (sha512 verified), real inspection reports `jobMemoryLimit: true`. With that one field removed to model an earlier artifact, and the real platform, runtime root and DACL path, the MCP response changed from the `execution_failure` above to: ```json {"code":"capability_unavailable","category":"unsupported_provider","message":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package.","retryable":false,"remediation":{"action":"Install the matching current Windows x64 REA package; its native inspection must prove this control. REA does not launch without it, so retrying the unchanged installation will not succeed."},"details":{"provider_id":"source-map-decoder","operation":"trace_web_source_location","reason":"The bundled Windows native artifact does not support Job Object memory limits; use a matching current Windows x64 REA package."}} ``` No `process_spawn` occurred in either run. - Remaining proof gaps: Bun itself was not run (the memory-limit policy was set to its Windows+Bun result, as in the issue). The protocol-stdin path is covered at the unit level and through the shared projection, not by an end-to-end JavaScript-worker call. An actual older native artifact was not available. ## Validation performed Windows 11 x64, Node.js 24.18.0 (pinned), locked dependencies. - `npm run test:focused -- tests/process-global/windowsNativeControlCapability.test.ts` — passes with the fix; fails with `execution_failure` with `src/` changes stashed. - `npm run test:focused -- src/windows/WindowsOwnedProcess.test.ts` — 21/21 passed. - Consumer and process suites (`AdbProvider`, `SourceMapCommand`, `SourceMapDecoder`, `WabtArtifactProvider`, `WabtFailures`, `sourceMapRuntimeAvailability`, `pcapWorkspaceAllocation`, `webSourceLocationMcp`, `providerProcess`, `pcapProviderCrossPlatform`, `WindowsOwnedProcess`) — 32 tests fail on this Windows host both with and without the change (identical set: `WabtArtifactProvider` 26, `SourceMapCommand` 3, `providerProcess` 3; POSIX-oriented expectations). The change introduces no new failures; Linux/macOS CI is needed to confirm those suites. - `npm run check:fast` (typecheck, lint, module boundaries) — passed. - `npm run verify:test-discovery` — passed ("Discovered all 1985 test files exactly once"). - `npm run docs:check` — passed; no generated changes. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Callers that saw `execution_failure` for this refusal now see `capability_unavailable` (`unsupported_provider` category), which is the documented code for a provider that cannot execute a declared operation. - Real Hopper/Ghidra, browser, or OS coverage: Windows 11 x64 locally (real native loader/runtime root); no Linux/macOS run locally. - Package or release metadata impact: none. - Security, privacy, process, or containment review: the refusal and its pre-launch position are unchanged; no control is relaxed, and no process starts without the requested control. ## Author readiness Human owner: @AmmarJamil23 - [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:30 +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#7250
No description provided.