[PR #5324] fix(javascript-recovery): run Wakaru on macOS arm64 with shell resource limits #6880

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

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/5324
Author: @IOkal
Created: 10/20/2026
Status: 🔄 Open

Base: main ← Head: fix/wakaru-macos-arm64-limiter


📝 Commits (1)

  • ea9286d fix(javascript-recovery): run Wakaru on macOS arm64 with shell resource limits

📊 Changes

6 files changed (+257 additions, -27 deletions)

View changed files

📝 docs/javascript-recovery.md (+17 -4)
📝 src/application/CapabilityInventory.ts (+1 -1)
📝 src/javascript/recovery/WakaruCommand.test.ts (+161 -1)
📝 src/javascript/recovery/WakaruCommand.ts (+59 -15)
📝 src/javascript/recovery/WakaruPublication.ts (+2 -2)
📝 src/javascript/recovery/WakaruRelease.ts (+17 -4)

📄 Description

Summary

recover_javascript_sources / rea recover-javascript-sources refuses to run on any host except Linux x64, even when the caller supplies a working Wakaru binary. Wakaru publishes a native darwin-arm64 build (@wakaru/cli-darwin-arm64, pulled in by npm install wakaru@1.14.0), but REA rejects it before launch.

This lets macOS arm64 hosts use caller-supplied Wakaru, and makes the weaker resource containment on that host explicit in the result instead of reusing Linux wording.

Problem and expected behavior

Smallest trigger (macOS arm64, Wakaru 1.14.0 installed from npm):

REA_WAKARU_COMMAND="$(realpath node_modules/@wakaru/cli-darwin-arm64/wakaru)" \
  rea recover-javascript-sources app.js out --extraction-mode structural --format json

Observed on rea-agents 6.7.0:

{"code":"capability_unavailable","category":"unsupported_provider","message":"Provide an absolute REA_WAKARU_COMMAND pointing to a Wakaru ^1.13.0 Linux x64 binary (verified with 1.14.0); ..."}

Two checks cause it: resolveWakaruCommand requires process.platform === "linux" && process.arch === "x64", and every run is launched through util-linux prlimit, which does not exist on macOS.

Expected: a configured, working Wakaru runs on macOS arm64, bounded as far as the host allows, and the result says which bounds apply.

Change and scope

The resource limiter is now chosen from the host (WakaruCommand.ts):

  • Linux x64: unchanged. Same prlimit binary, same argument list, same REA_JAVASCRIPT_PRLIMIT_COMMAND override.
  • macOS arm64: the engine is started through /bin/sh -c 'ulimit -f N && ulimit -c 0 && ulimit -t 120 && exec "$0" "$@"' <engine> <args...>.
    • -f is RECOVERY_LIMITS.outputBytes / 512 blocks, -c 0 disables core dumps, -t is the 120 s CPU limit.
    • The limits are chained with &&, so a limit that cannot be set stops the run instead of starting the engine unbounded.
    • The engine path and arguments are positional parameters ($0, "$@"), never interpolated into the script.
    • REA_JAVASCRIPT_PRLIMIT_COMMAND is not used on this host.
  • Other hosts: still refused. The refusal text now names the supported hosts.

macOS does not allow an address-space ceiling: ulimit -v and ulimit -d fail with Invalid argument, and a 200 MB allocation succeeds under ulimit -v 65536. So the 1 GiB memory cap that Linux applies is not enforced on macOS. The result's limitations now come from recoveryLimitations(limiterKind): the Linux string is unchanged, and the macOS string states that memory use is not capped. RECOVERY_LIMITATIONS keeps its existing value.

Not included: Intel macOS, Windows, and Linux arm64 (not verified). A memory ceiling for macOS.

Contract and boundary impact

  • Semantic owner and earliest changed stage: javascript-recovery engine resolution (resolveWakaruCommand) and command construction (runWakaruCommand).
  • Contribution scope fit and linked maintainer decision: not applicable (ordinary fix within the existing Wakaru provider; no new capability or target interaction).
  • CLI and MCP/tool-catalog contract: no schema change. limitations strings differ on macOS. The capability-inventory remediation text and the refusal message now mention macOS arm64.
  • Provider, bridge, target-format, or platform compatibility: adds macOS arm64 for Wakaru ^1.13.0 (verified with 1.14.0). Linux x64 behavior unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: unchanged. resource_limiter reports /bin/sh on macOS.
  • Target selection, authority, upstream behavior, and cleanup details: process ownership and cleanup paths are unchanged; the shell execs the engine, so the supervised process is the engine.
  • Generated metadata, package, or installation impact: none committed. Docs updated (docs/javascript-recovery.md).

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process. (Launches the caller-supplied Wakaru, as before.)
  • 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

Executed on Darwin 25.6.0 arm64 (macOS), unless noted.

  • Tests added or updated (src/javascript/recovery/WakaruCommand.test.ts, 7 new):

    • unsupported host (win32) is refused and the message names Linux x64 / macOS arm64;
    • macOS host selects /bin/sh / shell-ulimit without requiring prlimit;
    • the prlimit override is ignored on macOS;
    • the Linux invocation (prlimit + args) is asserted byte-for-byte unchanged;
    • the macOS invocation passes the engine and arguments as positional parameters (a path containing $(...) and spaces does not reach the script);
    • the macOS limitation says memory is not capped and does not claim the 1 GiB ceiling; the Linux wording is unchanged;
    • darwin-arm64 only: a real run of an engine script that prints ulimit -f, -c, -t shows 262144, 0, 120 were applied before it started.
  • Base reproduction: installed rea-agents 6.7.0 with REA_WAKARU_COMMAND set to the darwin binary returns the capability_unavailable refusal above.

  • User-visible output with this branch (compiled with tsc + scripts/bundle-runtime.mjs), recovering a real 73 KB webpack bundle with Wakaru 1.14.0 darwin-arm64:

    • exit 0, 15 modules recovered, 0 failed, runtime_equivalence: "unknown";
    • last limitation: macOS adapter: one worker, 120-second CPU and wall-clock deadline, ... macOS cannot enforce an address-space ceiling, so memory use is not capped. ...
  • Remaining proof gaps: the Linux real-provider workflow (verify:javascript:recovery, real-javascript-recovery.yml) was not run here; Linux behavior is covered only by the unchanged-invocation unit test. Intel macOS is untested.

  • 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

  • npx vitest run src/javascript/recovery/WakaruCommand.test.ts — 14 passed (includes the darwin-arm64 real-host test).
  • npx vitest run wakaru recovery Recovery CapabilityInventory capabilit — 153 passed, 7 failed, 44 skipped. The same 7 fail on the base commit without this change (hopperStartupRecovery, sessionEvidenceRecovery, processCleanupRecoveryCli: they need a built dist/ or Hopper). Base run: 146 passed, 7 failed.
  • npx tsc --noEmit — exit 0.
  • npx oxfmt --check on the changed paths — all files correctly formatted.
  • npx oxlint src/javascript/recovery src/application/CapabilityInventory.ts — 8 warnings before and after (none new).
  • npm run verify:module-boundaries — passed (2231 source files).
  • Not run: npm run check, verify:javascript:recovery, Linux CI.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. Linux x64 configuration and output are unchanged. macOS arm64 hosts that were refused are now accepted.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS arm64 real-host unit test and one end-to-end recovery run (above). No Linux run here.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: on macOS the memory ceiling is not enforced (OS limitation). CPU time, output size, core dumps, REA's 120 s deadline, input/output/entry caps and process-group cleanup still apply. A limit that cannot be applied prevents the engine from starting. Resource limits remain per operation, not aggregate host containment, as already documented.

Author readiness

Human owner:

  • 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/5324 **Author:** [@IOkal](https://github.com/IOkal) **Created:** 10/20/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/wakaru-macos-arm64-limiter` --- ### 📝 Commits (1) - [`ea9286d`](https://github.com/morluto/rea/commit/ea9286ddb275d92428471b6a599de7edd4d2a829) fix(javascript-recovery): run Wakaru on macOS arm64 with shell resource limits ### 📊 Changes **6 files changed** (+257 additions, -27 deletions) <details> <summary>View changed files</summary> 📝 `docs/javascript-recovery.md` (+17 -4) 📝 `src/application/CapabilityInventory.ts` (+1 -1) 📝 `src/javascript/recovery/WakaruCommand.test.ts` (+161 -1) 📝 `src/javascript/recovery/WakaruCommand.ts` (+59 -15) 📝 `src/javascript/recovery/WakaruPublication.ts` (+2 -2) 📝 `src/javascript/recovery/WakaruRelease.ts` (+17 -4) </details> ### 📄 Description ## Summary `recover_javascript_sources` / `rea recover-javascript-sources` refuses to run on any host except Linux x64, even when the caller supplies a working Wakaru binary. Wakaru publishes a native `darwin-arm64` build (`@wakaru/cli-darwin-arm64`, pulled in by `npm install wakaru@1.14.0`), but REA rejects it before launch. This lets macOS arm64 hosts use caller-supplied Wakaru, and makes the weaker resource containment on that host explicit in the result instead of reusing Linux wording. ## Problem and expected behavior Smallest trigger (macOS arm64, Wakaru 1.14.0 installed from npm): ```sh REA_WAKARU_COMMAND="$(realpath node_modules/@wakaru/cli-darwin-arm64/wakaru)" \ rea recover-javascript-sources app.js out --extraction-mode structural --format json ``` Observed on `rea-agents` 6.7.0: ```json {"code":"capability_unavailable","category":"unsupported_provider","message":"Provide an absolute REA_WAKARU_COMMAND pointing to a Wakaru ^1.13.0 Linux x64 binary (verified with 1.14.0); ..."} ``` Two checks cause it: `resolveWakaruCommand` requires `process.platform === "linux" && process.arch === "x64"`, and every run is launched through util-linux `prlimit`, which does not exist on macOS. Expected: a configured, working Wakaru runs on macOS arm64, bounded as far as the host allows, and the result says which bounds apply. ## Change and scope The resource limiter is now chosen from the host (`WakaruCommand.ts`): - **Linux x64**: unchanged. Same `prlimit` binary, same argument list, same `REA_JAVASCRIPT_PRLIMIT_COMMAND` override. - **macOS arm64**: the engine is started through `/bin/sh -c 'ulimit -f N && ulimit -c 0 && ulimit -t 120 && exec "$0" "$@"' <engine> <args...>`. - `-f` is `RECOVERY_LIMITS.outputBytes / 512` blocks, `-c 0` disables core dumps, `-t` is the 120 s CPU limit. - The limits are chained with `&&`, so a limit that cannot be set stops the run instead of starting the engine unbounded. - The engine path and arguments are positional parameters (`$0`, `"$@"`), never interpolated into the script. - `REA_JAVASCRIPT_PRLIMIT_COMMAND` is not used on this host. - **Other hosts**: still refused. The refusal text now names the supported hosts. macOS does not allow an address-space ceiling: `ulimit -v` and `ulimit -d` fail with `Invalid argument`, and a 200 MB allocation succeeds under `ulimit -v 65536`. So the 1 GiB memory cap that Linux applies is not enforced on macOS. The result's limitations now come from `recoveryLimitations(limiterKind)`: the Linux string is unchanged, and the macOS string states that memory use is not capped. `RECOVERY_LIMITATIONS` keeps its existing value. Not included: Intel macOS, Windows, and Linux arm64 (not verified). A memory ceiling for macOS. ## Contract and boundary impact - Semantic owner and earliest changed stage: javascript-recovery engine resolution (`resolveWakaruCommand`) and command construction (`runWakaruCommand`). - Contribution scope fit and linked maintainer decision: not applicable (ordinary fix within the existing Wakaru provider; no new capability or target interaction). - CLI and MCP/tool-catalog contract: no schema change. `limitations` strings differ on macOS. The capability-inventory remediation text and the refusal message now mention macOS arm64. - Provider, bridge, target-format, or platform compatibility: adds macOS arm64 for Wakaru ^1.13.0 (verified with 1.14.0). Linux x64 behavior unchanged. - Evidence, artifact, provenance, or reconstruction contract: unchanged. `resource_limiter` reports `/bin/sh` on macOS. - Target selection, authority, upstream behavior, and cleanup details: process ownership and cleanup paths are unchanged; the shell `exec`s the engine, so the supervised process is the engine. - Generated metadata, package, or installation impact: none committed. Docs updated (`docs/javascript-recovery.md`). Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. (Launches the caller-supplied Wakaru, as before.) - [ ] 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 Executed on Darwin 25.6.0 arm64 (macOS), unless noted. - Tests added or updated (`src/javascript/recovery/WakaruCommand.test.ts`, 7 new): - unsupported host (win32) is refused and the message names Linux x64 / macOS arm64; - macOS host selects `/bin/sh` / `shell-ulimit` without requiring prlimit; - the prlimit override is ignored on macOS; - the Linux invocation (`prlimit` + args) is asserted byte-for-byte unchanged; - the macOS invocation passes the engine and arguments as positional parameters (a path containing `$(...)` and spaces does not reach the script); - the macOS limitation says memory is not capped and does not claim the 1 GiB ceiling; the Linux wording is unchanged; - darwin-arm64 only: a real run of an engine script that prints `ulimit -f`, `-c`, `-t` shows `262144`, `0`, `120` were applied before it started. - Base reproduction: installed `rea-agents` 6.7.0 with `REA_WAKARU_COMMAND` set to the darwin binary returns the `capability_unavailable` refusal above. - User-visible output with this branch (compiled with `tsc` + `scripts/bundle-runtime.mjs`), recovering a real 73 KB webpack bundle with Wakaru 1.14.0 darwin-arm64: - exit 0, 15 modules recovered, 0 failed, `runtime_equivalence: "unknown"`; - last limitation: `macOS adapter: one worker, 120-second CPU and wall-clock deadline, ... macOS cannot enforce an address-space ceiling, so memory use is not capped. ...` - Remaining proof gaps: the Linux real-provider workflow (`verify:javascript:recovery`, `real-javascript-recovery.yml`) was not run here; Linux behavior is covered only by the unchanged-invocation unit test. Intel macOS is untested. - [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 - `npx vitest run src/javascript/recovery/WakaruCommand.test.ts` — 14 passed (includes the darwin-arm64 real-host test). - `npx vitest run wakaru recovery Recovery CapabilityInventory capabilit` — 153 passed, 7 failed, 44 skipped. The same 7 fail on the base commit without this change (`hopperStartupRecovery`, `sessionEvidenceRecovery`, `processCleanupRecoveryCli`: they need a built `dist/` or Hopper). Base run: 146 passed, 7 failed. - `npx tsc --noEmit` — exit 0. - `npx oxfmt --check` on the changed paths — all files correctly formatted. - `npx oxlint src/javascript/recovery src/application/CapabilityInventory.ts` — 8 warnings before and after (none new). - `npm run verify:module-boundaries` — passed (2231 source files). - Not run: `npm run check`, `verify:javascript:recovery`, Linux CI. ## Compatibility, safety, and release - Breaking changes or migration steps: none. Linux x64 configuration and output are unchanged. macOS arm64 hosts that were refused are now accepted. - Real Hopper/Ghidra, browser, or OS coverage: macOS arm64 real-host unit test and one end-to-end recovery run (above). No Linux run here. - Package or release metadata impact: none. - Security, privacy, process, or containment review: on macOS the memory ceiling is not enforced (OS limitation). CPU time, output size, core dumps, REA's 120 s deadline, input/output/entry caps and process-group cleanup still apply. A limit that cannot be applied prevents the engine from starting. Resource limits remain per operation, not aggregate host containment, as already documented. ## Author readiness Human owner: <!-- @GitHub-handle --> - [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>
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#6880
No description provided.