[PR #3557] [CLOSED] fix(update): report optional native module readiness #5822

Closed
opened 2026-10-31 01:09:42 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/3557
Author: @dakjdakd
Created: 10/14/2026
Status: ❌ Closed

Base: main ← Head: fix/update-optional-native-readiness


📝 Commits (2)

  • ad86916 fix(update): report optional native module readiness
  • f6336c4 fix(update): preserve probe failure diagnostics

📊 Changes

8 files changed (+462 additions, -1 deletions)

View changed files

📝 docs/installation.md (+16 -0)
📝 src/application/Update.test.ts (+43 -0)
📝 src/application/Update.ts (+15 -0)
📝 src/application/UpdateRuntime.ts (+8 -0)
📝 src/cliLogging.test.ts (+1 -0)
➕ src/domain/OptionalProviderReadiness.ts (+20 -0)
➕ src/frida/FridaBindingReadiness.ts (+139 -0)
📝 tests/process-global/updateMaintenance.test.ts (+220 -1)

📄 Description

Summary

Fixes #3556.

After version verification, rea update separately reports whether Frida's native module loads. Human and JSON results preserve the diagnostic and provide a manual recovery command scoped to the resolved Frida package when available.

The updater continues to disable dependency lifecycle scripts. A successful CLI update remains updated with exit 0 when Frida is unavailable. An already-current installation also receives a fresh readiness check, allowing the user to verify recovery without forcing another installation.

Problem and expected behavior

The published 6.4.0 → 6.5.0 npm update succeeds with --ignore-scripts, verifies rea --version, and reports success. Version 6.5.0 adds optional Frida 17.23.2, whose native binding is supplied by its install script rather than included in its tarball. As a result, the update can complete while import("frida") fails with Could not locate the bindings file. The next Frida command returns provider-unavailable, but the update result has offered no warning or recovery action.

Readiness must refer to the updated installation, preserve the actual error, and remain unknown if the probe fails. It must not inspect cached modules or the caller's project.

Change and scope

The eight changed files implement one outcome:

File Responsibility
src/domain/OptionalProviderReadiness.ts Defines the additive, provider-neutral readiness result and optional recovery argv/working directory.
src/application/Update.ts Requests readiness after successful version verification and for identified current installations; includes it in the result.
src/application/UpdateRuntime.ts Connects the installed package root and owning manager to the Frida probe with package-runner identity removed.
src/frida/FridaBindingReadiness.ts Owns Frida resolution, isolated import, boundary parsing, error classification, and scoped repair instructions.
src/application/Update.test.ts Covers propagation, successful exit classification, current installations, and skipping checks when ownership or verification is unavailable.
src/cliLogging.test.ts Updates the existing host fixture for the required readiness effect.
tests/process-global/updateMaintenance.test.ts Adds real subprocess coverage for loading, errors, absence, hoisting, and manual recovery selection.
docs/installation.md Explains the optional readiness contract, lifecycle restriction, and explicit recovery workflow.

The fresh Node subprocess resolves Frida relative to the identified REA installation, imports the entry, and checks the expected export without calling the device manager. Recovery requires a resolved Frida manifest with an install script, including when the dependency is hoisted.

The probe uses the shared process primitive with a 10-second deadline, 5-second termination grace, and 64 KiB output limit. Its JSON is validated at the boundary. Module absence, module loading failure, and an unsuccessful probe retain different outcomes. Unknown errors do not become claims that a native binding is missing.

Recovery is returned as arguments plus a working directory. npm uses npm --prefix <resolved-frida-root> run install --ignore-scripts=false; Bun uses bun run --cwd <resolved-frida-root> install. Both are manual actions directed at the resolved dependency. The updater never runs them or enables scripts for the entire dependency tree.

Contract and boundary impact

  • Semantic owner and earliest changed stage: Post-verification update reporting owns whether optional readiness is requested and returned. The Frida adapter owns resolution, import diagnostics, and its repair action.
  • Contribution scope fit and maintainer decision: An ordinary installation/reporting fix within existing boundaries; a new-provider or target-execution scope decision is not applicable.
  • CLI and MCP/tool-catalog contract: Additive optionalProviderReadiness on successful update results. It is present for identified current installations and omitted when ownership is unknown. No MCP tool or catalog changes.
  • Provider/platform compatibility: Checks Frida's module load in a fresh Node process. Device availability, transport, permissions, and actual instrumentation remain outside this claim.
  • Evidence and provenance: Preserves the actual load error and resolved installation location. Probe failure remains explicit uncertainty.
  • Authority and cleanup: Only an updater child process is launched. Shared supervision bounds its lifetime and collected output. No device manager, attach, spawn, or target operation is invoked.
  • Package/generated impact: One new runtime module and one type contract; no dependency, version, generated catalog, or committed build artifact changes.

Expected effects:

  • Read existing files or captured data.
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Contact network services.
  • Change process memory, registers, files, or configuration.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

The process/code effects refer to the Node import probe; network/file effects include the existing package update. Suggested repair runs only when explicitly invoked.

Evidence and regression coverage

The published 6.4.0 CLI updated an isolated npm prefix to 6.5.0 and exited 0; list-frida-devices --json then exited 1 with the missing-binding diagnostic. New workflow assertions fail against the original implementation because it returns no readiness result.

Six added subprocess tests exercise ready loading without calling the exported device-manager function; preservation of a load error; hoisted dependency resolution and Bun command selection; missing install-script handling; an absent dependency without a misleading rebuild command; and probe-process failure reported as unknown. The npm recovery argv is actually executed against a safe local install-script fixture, establishing argument and directory handling without downloading a native binding.

The fixed tarball's public CLI, installed in an isolated prefix, exits 0 in human and JSON modes and reports the actual missing binding. With paths abbreviated:

{
  "status": "current",
  "currentVersion": "6.5.0",
  "latestVersion": "6.5.0",
  "installMethod": "npm",
  "optionalProviderReadiness": [{
    "provider": "frida",
    "scope": "native-module",
    "status": "unavailable",
    "reason": "module-load-failed",
    "detail": "Error: Could not locate the bindings file. Tried: ...",
    "remediation": "Frida could not load. Run the recovery command in its working directory to execute Frida's install script (it may download or build its native binding), then rerun rea update. Other dependency install scripts remain disabled during updates.",
    "recovery": {
      "command": ["npm", "--prefix", "<resolved-frida-root>", "run", "install", "--ignore-scripts=false"],
      "workingDirectory": "<installed-rea-root>"
    }
  }]
}

Human output exposes the same facts:

status: current
optionalProviderReadiness[1]:
  - provider: frida
    scope: native-module
    status: unavailable
    reason: module-load-failed
    detail: "Error: Could not locate the bindings file. Tried: ..."
    recovery:
      command[6]: npm,"--prefix","<resolved-frida-root>",run,install,"--ignore-scripts=false"
      workingDirectory: "<installed-rea-root>"

A successful import returns status: "ready". A failed probe returns status: "unknown", reason: "probe-failed", and its diagnostic. If the subprocess times out or exceeds its output limit, the adapter reads the captured failure through execFileOutputFailure and retains bounded stdout and stderr alongside the failure message, exit metadata, and truncation status. It does not infer that Frida is missing or offer an installation recovery command from an incomplete probe. Neither asserts device readiness.

For the updated path, the fixed compiled runUpdate and real systemUpdateHost were invoked with a 6.4.0 starting version and an isolated installed root. They performed an actual registry installation of 6.5.0, verified its executable, and returned updated plus Frida unavailable, exit 0. This is a production-boundary source-workflow check, not a claim that the published updater already contains the fix.

Validation performed

Final checks used Node 24.18.0 and npm 11.16.0 on Windows x64.

  • npm run check — passed, including typecheck, lint, formatting, unused-code, metadata, module-boundary, and architecture checks.
  • npm run docs:check — passed, including five README consistency tests.
  • npm run verify:test-discovery — passed; all 1,284 test files discovered once.
  • Focused update/logging/process-global and shared process tests — 83 passed, with 10 platform-condition skips; six existing Bun recorder failures remain reproduced on the unmodified baseline. All nine readiness subprocess cases passed, including real timeout, stdout-limit, and stderr-limit coverage. The three diagnostic cases retain both captured streams and execution/truncation metadata, keep readiness unknown without a recovery command, and confirm that the probe process has exited before returning.
  • npm pack --dry-run --json and actual npm pack — passed. Isolated global installation of the fixed tarball and public CLI human/JSON checks passed.
  • npm run verify:package — blocked at its repository-skill step by Windows spawn npm ENOENT; the independent pack/install/CLI checks above completed.

Compatibility, safety, and release

No breaking call, migration, configuration change, or package-manager upgrade is introduced. updated/current retain successful exit behavior for an unavailable optional module. Existing maintenance planning remains separate.

Actual Frida native-ready/device instrumentation and execution of the real Bun repair command were not verified. Bun's hoisted path/argv selection is covered at the boundary; the native-ready case uses a module fixture. The Windows native artifact used for package checks came from the published 6.5.0 package and was manifest/hash verified, not locally rebuilt or committed. No Hopper/Ghidra workflow is affected or claimed.

Author readiness

Human owner: @dakjdakd

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

The human owner's final review and readiness declaration remain pending.

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/3557 **Author:** [@dakjdakd](https://github.com/dakjdakd) **Created:** 10/14/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/update-optional-native-readiness` --- ### 📝 Commits (2) - [`ad86916`](https://github.com/morluto/rea/commit/ad869164990a4191bde6b43fc5c5c0fb8388a5aa) fix(update): report optional native module readiness - [`f6336c4`](https://github.com/morluto/rea/commit/f6336c444f820f98d3a052f7f8da4281e90f08a9) fix(update): preserve probe failure diagnostics ### 📊 Changes **8 files changed** (+462 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `docs/installation.md` (+16 -0) 📝 `src/application/Update.test.ts` (+43 -0) 📝 `src/application/Update.ts` (+15 -0) 📝 `src/application/UpdateRuntime.ts` (+8 -0) 📝 `src/cliLogging.test.ts` (+1 -0) ➕ `src/domain/OptionalProviderReadiness.ts` (+20 -0) ➕ `src/frida/FridaBindingReadiness.ts` (+139 -0) 📝 `tests/process-global/updateMaintenance.test.ts` (+220 -1) </details> ### 📄 Description ## Summary Fixes #3556. After version verification, `rea update` separately reports whether Frida's native module loads. Human and JSON results preserve the diagnostic and provide a manual recovery command scoped to the resolved Frida package when available. The updater continues to disable dependency lifecycle scripts. A successful CLI update remains `updated` with exit 0 when Frida is unavailable. An already-current installation also receives a fresh readiness check, allowing the user to verify recovery without forcing another installation. ## Problem and expected behavior The published 6.4.0 → 6.5.0 npm update succeeds with `--ignore-scripts`, verifies `rea --version`, and reports success. Version 6.5.0 adds optional Frida 17.23.2, whose native binding is supplied by its install script rather than included in its tarball. As a result, the update can complete while `import("frida")` fails with `Could not locate the bindings file`. The next Frida command returns provider-unavailable, but the update result has offered no warning or recovery action. Readiness must refer to the updated installation, preserve the actual error, and remain unknown if the probe fails. It must not inspect cached modules or the caller's project. ## Change and scope The eight changed files implement one outcome: | File | Responsibility | | --- | --- | | `src/domain/OptionalProviderReadiness.ts` | Defines the additive, provider-neutral readiness result and optional recovery argv/working directory. | | `src/application/Update.ts` | Requests readiness after successful version verification and for identified current installations; includes it in the result. | | `src/application/UpdateRuntime.ts` | Connects the installed package root and owning manager to the Frida probe with package-runner identity removed. | | `src/frida/FridaBindingReadiness.ts` | Owns Frida resolution, isolated import, boundary parsing, error classification, and scoped repair instructions. | | `src/application/Update.test.ts` | Covers propagation, successful exit classification, current installations, and skipping checks when ownership or verification is unavailable. | | `src/cliLogging.test.ts` | Updates the existing host fixture for the required readiness effect. | | `tests/process-global/updateMaintenance.test.ts` | Adds real subprocess coverage for loading, errors, absence, hoisting, and manual recovery selection. | | `docs/installation.md` | Explains the optional readiness contract, lifecycle restriction, and explicit recovery workflow. | The fresh Node subprocess resolves Frida relative to the identified REA installation, imports the entry, and checks the expected export without calling the device manager. Recovery requires a resolved Frida manifest with an install script, including when the dependency is hoisted. The probe uses the shared process primitive with a **10-second deadline**, **5-second termination grace**, and **64 KiB output limit**. Its JSON is validated at the boundary. Module absence, module loading failure, and an unsuccessful probe retain different outcomes. Unknown errors do not become claims that a native binding is missing. Recovery is returned as arguments plus a working directory. npm uses `npm --prefix <resolved-frida-root> run install --ignore-scripts=false`; Bun uses `bun run --cwd <resolved-frida-root> install`. Both are manual actions directed at the resolved dependency. The updater never runs them or enables scripts for the entire dependency tree. ## Contract and boundary impact - **Semantic owner and earliest changed stage:** Post-verification update reporting owns whether optional readiness is requested and returned. The Frida adapter owns resolution, import diagnostics, and its repair action. - **Contribution scope fit and maintainer decision:** An ordinary installation/reporting fix within existing boundaries; a new-provider or target-execution scope decision is not applicable. - **CLI and MCP/tool-catalog contract:** Additive `optionalProviderReadiness` on successful update results. It is present for identified current installations and omitted when ownership is unknown. No MCP tool or catalog changes. - **Provider/platform compatibility:** Checks Frida's module load in a fresh Node process. Device availability, transport, permissions, and actual instrumentation remain outside this claim. - **Evidence and provenance:** Preserves the actual load error and resolved installation location. Probe failure remains explicit uncertainty. - **Authority and cleanup:** Only an updater child process is launched. Shared supervision bounds its lifetime and collected output. No device manager, attach, spawn, or target operation is invoked. - **Package/generated impact:** One new runtime module and one type contract; no dependency, version, generated catalog, or committed build artifact changes. Expected effects: - [x] Read existing files or captured data. - [x] Launch or attach to a process. - [x] Inject instrumentation or run scripts/code. - [x] Contact network services. - [x] Change process memory, registers, files, or configuration. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. The process/code effects refer to the Node import probe; network/file effects include the existing package update. Suggested repair runs only when explicitly invoked. ## Evidence and regression coverage The published 6.4.0 CLI updated an isolated npm prefix to 6.5.0 and exited 0; `list-frida-devices --json` then exited 1 with the missing-binding diagnostic. New workflow assertions fail against the original implementation because it returns no readiness result. Six added subprocess tests exercise ready loading without calling the exported device-manager function; preservation of a load error; hoisted dependency resolution and Bun command selection; missing install-script handling; an absent dependency without a misleading rebuild command; and probe-process failure reported as unknown. The npm recovery argv is actually executed against a safe local install-script fixture, establishing argument and directory handling without downloading a native binding. The fixed tarball's public CLI, installed in an isolated prefix, exits 0 in human and JSON modes and reports the actual missing binding. With paths abbreviated: ```json { "status": "current", "currentVersion": "6.5.0", "latestVersion": "6.5.0", "installMethod": "npm", "optionalProviderReadiness": [{ "provider": "frida", "scope": "native-module", "status": "unavailable", "reason": "module-load-failed", "detail": "Error: Could not locate the bindings file. Tried: ...", "remediation": "Frida could not load. Run the recovery command in its working directory to execute Frida's install script (it may download or build its native binding), then rerun rea update. Other dependency install scripts remain disabled during updates.", "recovery": { "command": ["npm", "--prefix", "<resolved-frida-root>", "run", "install", "--ignore-scripts=false"], "workingDirectory": "<installed-rea-root>" } }] } ``` Human output exposes the same facts: ```text status: current optionalProviderReadiness[1]: - provider: frida scope: native-module status: unavailable reason: module-load-failed detail: "Error: Could not locate the bindings file. Tried: ..." recovery: command[6]: npm,"--prefix","<resolved-frida-root>",run,install,"--ignore-scripts=false" workingDirectory: "<installed-rea-root>" ``` A successful import returns `status: "ready"`. A failed probe returns `status: "unknown"`, `reason: "probe-failed"`, and its diagnostic. If the subprocess times out or exceeds its output limit, the adapter reads the captured failure through `execFileOutputFailure` and retains bounded stdout and stderr alongside the failure message, exit metadata, and truncation status. It does not infer that Frida is missing or offer an installation recovery command from an incomplete probe. Neither asserts device readiness. For the `updated` path, the fixed compiled `runUpdate` and real `systemUpdateHost` were invoked with a 6.4.0 starting version and an isolated installed root. They performed an actual registry installation of 6.5.0, verified its executable, and returned `updated` plus Frida unavailable, exit 0. This is a production-boundary source-workflow check, not a claim that the published updater already contains the fix. ## Validation performed Final checks used Node **24.18.0** and npm **11.16.0** on Windows x64. - `npm run check` — passed, including typecheck, lint, formatting, unused-code, metadata, module-boundary, and architecture checks. - `npm run docs:check` — passed, including five README consistency tests. - `npm run verify:test-discovery` — passed; all 1,284 test files discovered once. - Focused update/logging/process-global and shared process tests — **83 passed**, with 10 platform-condition skips; six existing Bun recorder failures remain reproduced on the unmodified baseline. All nine readiness subprocess cases passed, including real timeout, stdout-limit, and stderr-limit coverage. The three diagnostic cases retain both captured streams and execution/truncation metadata, keep readiness unknown without a recovery command, and confirm that the probe process has exited before returning. - `npm pack --dry-run --json` and actual `npm pack` — passed. Isolated global installation of the fixed tarball and public CLI human/JSON checks passed. - `npm run verify:package` — blocked at its repository-skill step by Windows `spawn npm ENOENT`; the independent pack/install/CLI checks above completed. ## Compatibility, safety, and release No breaking call, migration, configuration change, or package-manager upgrade is introduced. `updated`/`current` retain successful exit behavior for an unavailable optional module. Existing maintenance planning remains separate. Actual Frida native-ready/device instrumentation and execution of the real Bun repair command were not verified. Bun's hoisted path/argv selection is covered at the boundary; the native-ready case uses a module fixture. The Windows native artifact used for package checks came from the published 6.5.0 package and was manifest/hash verified, not locally rebuilt or committed. No Hopper/Ghidra workflow is affected or claimed. ## Author readiness Human owner: @dakjdakd - [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. The human owner's final review and readiness declaration remain pending. ## 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-10-31 01:09:42 +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#5822
No description provided.