[PR #6014] [MERGED] fix(providers): name JEB, IDA, and one-shot command deadlines #7122

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

📋 Pull Request Information

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

Base: main ← Head: cursor/name-jeb-ida-deadlines-3fdd


📝 Commits (4)

  • 018b64e fix(providers): name JEB, IDA, and one-shot command deadlines
  • cb85d8a merge(main): keep the shared startup timeout ceiling name
  • 946c011 fix(providers): pass remaining deadlines and name the cap that fired
  • b0eca9f fix(frida): preserve non-timeout device lookup failures

📊 Changes

39 files changed (+1089 additions, -199 deletions)

View changed files

📝 docs/client-configuration.md (+2 -2)
📝 docs/frida-instrumentation.md (+1 -1)
📝 docs/ida-provider.md (+1 -1)
📝 docs/jeb-analysis.md (+13 -11)
📝 docs/mcp-contracts.md (+2 -1)
📝 docs/reverse-engineering-tools.md (+11 -6)
📝 src/application/frida/FridaInstrumentationManager.test.ts (+81 -4)
📝 src/application/frida/FridaInstrumentationService.test.ts (+38 -0)
📝 src/application/frida/FridaInstrumentationService.ts (+2 -0)
📝 src/application/reverse/ReverseEngineeringService.ts (+83 -27)
📝 src/cli/reverseEngineeringCommands.ts (+31 -5)
📝 src/composition/jeb.ts (+4 -1)
📝 src/contracts/reverseEngineeringToolContracts.ts (+2 -2)
📝 src/contracts/rizinDebugToolContracts.ts (+1 -1)
📝 src/cutter/CutterBridgeClient.ts (+15 -6)
📝 src/domain/reverseEngineering.ts (+23 -0)
📝 src/frida/FridaInstrumentationManager.ts (+133 -55)
➕ src/frida/fridaCaptureLimits.ts (+97 -0)
📝 src/gdb/GdbSessionManager.ts (+66 -13)
📝 src/ida/IdaBusyHealth.test.ts (+2 -0)

...and 19 more files

📄 Description

Summary

Names the deadlines in the #5910 provider-timeout theme and makes the shared one-shot objdump/rizin clock adjustable. Does not repeat the MCP response-budget work in #6005. Refs #5910 (parent #5808).

Merged main (d8a9673fc). The only conflict was src/config/providerStartupTimeout.ts: this branch keeps main's exported MAX_PROVIDER_STARTUP_TIMEOUT_MS, and JEB remediation uses that name. docs/mcp-contracts.md auto-merged, keeping both the swiftc restart sentence and the JEB discovery sentence.

Problem and expected behavior

JEB tools/call timeouts did not name REA_JEB_MCP_TIMEOUT_MS, and catalog discovery ignored that setting while the docs said the tools/call budget does not extend discovery. A later pass still left the SDK request timeout at its 60000 ms default whenever the configured discovery budget was larger. IDA request timeouts did not name registration timeoutMs. One-shot objdump and rizin used a fixed 120000 ms deadline with no caller control, and the production command runner ignored a passed timeout. Preflight also restarted that clock after stat, so digest could spend the full budget again. Architecture Evidence dropped a selected timeout when there was no artifact path. gdb, Rizin debug, Frida, and Cutter caps in this theme failed without saying they have no override, and some sentences named a cap that had not fired.

A timeout now names the effective milliseconds, the control when one exists, the accepted range, and when a change applies. Raising REA_JEB_MCP_TIMEOUT_MS raises catalog discovery and each tools/call together, and discovery passes the time still remaining as the SDK timeout on connect and every tools/list page. command_timeout_ms (CLI --command-timeout-ms) changes the next one-shot objdump or rizin call. Omitted still means 120000 ms. Target preflight shares one budget across stat and digest. The one-shot command receives that budget again. The post-run digest starts another full budget and shares stat and hash inside that call.

Change and scope

Follow the contribution scope.
Unresolved scope, authority, side effects, or required verification block
integration. Link the required maintainer scope decision for new providers or
capabilities involving target execution, injection, mutation, or protection
recovery; ordinary fixes within existing boundaries may state "not applicable".
Draft PRs may leave the scope decision pending and the readiness and merge checklists
unchecked. Maintainers can help resolve open questions.

Not applicable. This names and wires existing analysis deadlines and adds one caller-selected timeout on commands REA already runs. It does not add a provider, injection, mutation, or protection recovery.

Named, existing controls:

  • JEB: REA_JEB_MCP_TIMEOUT_MS, integer 1..2147483647. Omitted means the pinned MCP SDK default of 60000 ms. Restart and reconnect to apply. The same parsed value is passed as discoveryTimeoutMs and requestTimeoutMs. Connect and each tools/list page pass deadline.remainingMs() as the SDK request timeout, so a configured value above 60000 ms is not replaced by the SDK default. It is still not one end-to-end deadline: discovery and each tools/call each start their own budget.
  • IDA: JSON key timeoutMs in the file named by REA_IDA_MCP_CONFIG (verified in src/ida/IdaConfiguration.ts). Integer 1..2147483647. Omitted means 300000. The file is re-read when the next IDA connection is created; an open session keeps the timeout it connected with. Changing the env path itself is process start. A shorter inner request is the time remaining inside that ceiling, and the error names both when they differ. Readiness-while-busy uses the same key.

Newly adjustable:

  • command_timeout_ms on inspect_with_objdump (including architectures) and execute_rizin_command. Default 120000, range 1..2147483647, next call, no restart. Target preflight shares one budget across stat and digest. The one-shot command receives that budget again. The post-run digest starts another full budget and shares stat and hash inside that call. It does not raise the 16 MiB combined output cap, Ghidra or Hopper startup, or a debugger session deadline. The production runner now uses options.timeout instead of ignoring it. The omitted path stays 120000 ms. A selected value is kept on architecture Evidence; omission leaves the key absent.

Left fixed, with “no runtime override” on the agent-visible failure or limitation:

  • GDB startup 10000 ms, MI command 120000 ms, 16 MiB output, session capacity, and the pending-command queue.
  • Rizin debug startup 30000 ms, command frame 120000 ms, the 16777216 byte frame cap, the 16777216 byte command-output cap, the 4096 frame command cap, session capacity, and the pending-command queue. Evidence names the cap that stopped capture. The internal 1000 ms cleanup drain only marks output truncated and is not its own timeout, so it stays unnamed.
  • Frida local getDeviceById wait of 1000 ms. Frida Core 17.23.2 rejects that wait with Device not found, and only that rejection is reported as the deadline. A device-manager or backend failure, such as Device manager is closed, stays a capability failure with its own message and is not reported as the deadline. Remote devices do not use the lookup. messages_truncated means the session capture budget dropped data. Field truncation names its own cap and does not set that flag. Flags inside a caller payload are ignored. The sentences live in src/frida/fridaCaptureLimits.ts.
  • Cutter request 25000 ms, 16777216 byte frame, and 256-candidate discovery budget. Numbers unchanged.
  • The shared objdump/rizin admission cap of 8 concurrent operations, named while that error was already being edited. command_timeout_ms does not raise it.

Ghidra 330000 (REA_GHIDRA_STARTUP_TIMEOUT_MS), Hopper 120000 (REA_HOPPER_STARTUP_TIMEOUT_MS), and Kuna project/function timeouts already name their controls. They are unchanged. Out of scope: MCP response budget (#6005), JavaScript heap, Android/JADX, browser, native, swiftc, engines, and ASAR.

Contract and boundary impact

  • Semantic owner and earliest changed stage: JEB composition reads REA_JEB_MCP_TIMEOUT_MS and passes it to both connection phases. The connection owner applies the remaining discovery budget to the SDK handshake and each catalog page. IDA configuration owns timeoutMs guidance. src/domain/reverseEngineering.ts owns command_timeout_ms; ReverseEngineeringService applies one budget across preflight stat and digest, then again to the command. Debugger, Frida, and Cutter providers own their fixed-cap sentences. Frida capture-cap wording is owned by src/frida/fridaCaptureLimits.ts. Frida device lookup classifies the provider rejection in FridaInstrumentationManager.#selectDevice; providerError still maps a non-timeout cause to a capability failure.
  • Contribution scope fit and linked maintainer decision: not applicable. Existing command and provider boundaries.
  • CLI and MCP/tool-catalog contract: optional command_timeout_ms / --command-timeout-ms on one-shot objdump, architecture listing, and one-shot rizin. Omitted input stays valid. Tool descriptions name the default, range, and what it does not raise. rizin_debug_command says Evidence names the output-byte, frame-byte, or frame-count cap. Generated catalogs are ignored outputs and were not committed.
  • Provider, bridge, target-format, or platform compatibility: JEB discovery follows an explicit REA_JEB_MCP_TIMEOUT_MS instead of staying at 60000 ms, including on the SDK request timeout. IDA, Ghidra, Hopper, and Kuna numbers are unchanged.
  • Evidence, artifact, provenance, or reconstruction contract: a selected command_timeout_ms is recorded on one-shot Evidence parameters, including architecture listing. Omission leaves the key absent. Timeout Evidence and limitations name the effective deadline or the capture cap that fired.
  • Target selection, authority, upstream behavior, and cleanup details (if applicable): no new target authority. Recovery text still tells the caller to confirm outstanding work and cleanup before retry, and to leave headroom in the outer MCP client deadline.
  • Generated metadata (docs/public/product-catalog.json), package, or installation impact (CI generates and validates ignored catalogs and skills/; edit authored instructions in .agents/skills/reverse-engineer-anything/ and never commit build outputs): none committed. The packaged skill does not document these deadlines.

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.

Existing objdump, rizin, debugger, Frida, and Cutter operations already perform their target interactions. This PR changes deadline selection and recovery text. It does not add a new interaction.

Evidence and regression coverage

  • Tests added or updated: src/jeb/JebMcpConnection.test.ts (discovery budget of 120000 ms on connect and every catalog page), tests/boundary/providers/jebMcpTimeout.test.ts, src/ida/IdaMcpConnection.test.ts, src/ida/IdaBusyHealth.test.ts, tests/composition/reverseEngineering.test.ts (shared preflight clock, architecture Evidence, runOwned limits.timeoutMs), tests/boundary/cli/reverseEngineeringCommands.test.ts, src/application/frida/FridaInstrumentationManager.test.ts (Device not found is the 1000 ms deadline; Device manager is closed stays a capability failure), src/application/frida/FridaInstrumentationService.test.ts, tests/boundary/mcp/fridaLifecycleMcp.test.ts (field truncation does not set messages_truncated), tests/composition/reverseEngineeringEdgeCases.test.ts (admission sentence includes the operation count), tests/boundary/providers/GdbSessionManagerCoverage.test.ts (named MI record cap), tests/boundary/providers/RizinTimeoutEvidence.test.ts, tests/boundary/providers/RizinDebugSessionCoverage.part4.test.ts, tests/boundary/providers/RizinDebugSessionCoverage.part5.test.ts (4096 frame sentence).
  • Base reproduction or other evidence: source inspection. JEB connect and tools/list previously passed only signal, so @modelcontextprotocol/client 2.3.1 kept DEFAULT_REQUEST_TIMEOUT_MSEC 60000. digestFile started the hash timer only after stat returned. #observeProvider replaced architecture parameters with { operation: "architectures" }. runOwnedCommandOutput maps options.timeout to limits.timeoutMs; a test that replaces run never reaches that adapter. Frida field truncation set messages_truncated. Rizin frame-count truncation reused the byte-cap sentence. #selectDevice turned every getDeviceById rejection into AnalysisTimeoutError. Installed Frida 17.23.2 on this machine: getDeviceById for a missing id with a 50 ms timeout rejected after about 50 ms with message Device not found; the same call after close() rejected immediately with Device manager is closed.
  • User-visible CLI/MCP output (if applicable): a 100 ms JEB catalog timeout projects catalog discovery and 100 ms, and the remediation names REA_JEB_MCP_TIMEOUT_MS, 2147483647, 60000, and restart. A tools/call timeout says tools/call. An IDA request of 40 ms inside a 1000 ms ceiling names both and REA_IDA_MCP_CONFIG. A one-shot rizin timeout with no field says command_timeout_ms and 120000 ms and omits the key from parameters. command_timeout_ms: 5000 is the error timeout, is passed to the command runner, and is recorded on parameters, including architecture Evidence. 0 and 2147483648 are AnalysisInputError. A 4096-frame Rizin capture says 4096 frame command limit and does not claim 16777216. Frida type truncation names 4096 and does not set messages_truncated. A Frida Device not found lookup projects provider_timeout at 1000 ms. Device manager is closed projects capability_unavailable and does not say deadlineExpired.
  • Remaining proof gaps: no live JEB, IDA, GDB, Rizin, or Cutter process was used. The Frida observation above is the local device manager only; no target was attached and no script was loaded. GitHub CI on 946c011a failed in Source tests, Test shard (5/8), Reverse tools quality, Portable tests, and CI required for the three stale assertions fixed here. Those jobs have not been re-run on this commit yet. Ghidra, Hopper, and Kuna paths were not re-executed because those files were not changed by the review fixes.

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

On b0eca9fb:

  • npx oxfmt --write on the five edited files — completed.
  • npm run check:fast — typecheck and lint succeeded (2 tasks).
  • npm run test:focused -- src/application/frida/FridaInstrumentationManager.test.ts tests/boundary/mcp/fridaLifecycleMcp.test.ts tests/composition/reverseEngineeringEdgeCases.test.ts tests/boundary/providers/GdbSessionManagerCoverage.test.ts — 4 files, 312 tests passed.

On 946c011a, not repeated after this commit: focused JEB, IDA was not re-run then either, rizin coverage, tests/composition/reverseEngineering.test.ts (27 tests), and npm run test:local -- src/jeb/JebMcpConnection.test.ts (13 tests). Real provider workflows were not run. The JEB tests use the repository HTTP fixture and spy on the installed MCP client. The preflight regression uses an injected stat and a stream that never ends; it does not open a FIFO.

Compatibility, safety, and release

  • Breaking changes or migration steps: none for omitted input. Callers who set REA_JEB_MCP_TIMEOUT_MS now also change catalog discovery, including the SDK request timeout; previously that setting did not. A slow preflight stat now consumes the same budget as the digest instead of granting the hash a fresh full budget. messages_truncated is no longer set for field-only truncation. A non-timeout Frida device lookup failure is capability_unavailable instead of provider_timeout. Timeout and limitation sentences changed. Numeric debugger, Frida, and Cutter caps are unchanged. command_timeout_ms is optional.
  • Real Hopper/Ghidra, browser, or OS coverage: not run. Ghidra, Hopper, and Kuna sources were not edited by the review fixes. The local Frida device-manager probe did not attach to a target.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: a longer command_timeout_ms lets an already admitted objdump or rizin command run longer. It does not raise output, concurrency, or debugger authority. The upper bound is the signed 32-bit timer ceiling, 2147483647 ms.

Author readiness

Human owner: @morluto

  • 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.
Open in Web Open in Cursor 

🔄 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/6014 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/21/2026 **Status:** ✅ Merged **Merged:** 10/21/2026 **Merged by:** [@morluto](https://github.com/morluto) **Base:** `main` ← **Head:** `cursor/name-jeb-ida-deadlines-3fdd` --- ### 📝 Commits (4) - [`018b64e`](https://github.com/morluto/rea/commit/018b64edf99d2ff71fbc4846fa848ddceefa306a) fix(providers): name JEB, IDA, and one-shot command deadlines - [`cb85d8a`](https://github.com/morluto/rea/commit/cb85d8a78fe96259b525e09a37394e68eb22c172) merge(main): keep the shared startup timeout ceiling name - [`946c011`](https://github.com/morluto/rea/commit/946c011a173400bf8ee0b00de6ed556157239c87) fix(providers): pass remaining deadlines and name the cap that fired - [`b0eca9f`](https://github.com/morluto/rea/commit/b0eca9fb48dcda98c8a6335cc29b356018818a29) fix(frida): preserve non-timeout device lookup failures ### 📊 Changes **39 files changed** (+1089 additions, -199 deletions) <details> <summary>View changed files</summary> 📝 `docs/client-configuration.md` (+2 -2) 📝 `docs/frida-instrumentation.md` (+1 -1) 📝 `docs/ida-provider.md` (+1 -1) 📝 `docs/jeb-analysis.md` (+13 -11) 📝 `docs/mcp-contracts.md` (+2 -1) 📝 `docs/reverse-engineering-tools.md` (+11 -6) 📝 `src/application/frida/FridaInstrumentationManager.test.ts` (+81 -4) 📝 `src/application/frida/FridaInstrumentationService.test.ts` (+38 -0) 📝 `src/application/frida/FridaInstrumentationService.ts` (+2 -0) 📝 `src/application/reverse/ReverseEngineeringService.ts` (+83 -27) 📝 `src/cli/reverseEngineeringCommands.ts` (+31 -5) 📝 `src/composition/jeb.ts` (+4 -1) 📝 `src/contracts/reverseEngineeringToolContracts.ts` (+2 -2) 📝 `src/contracts/rizinDebugToolContracts.ts` (+1 -1) 📝 `src/cutter/CutterBridgeClient.ts` (+15 -6) 📝 `src/domain/reverseEngineering.ts` (+23 -0) 📝 `src/frida/FridaInstrumentationManager.ts` (+133 -55) ➕ `src/frida/fridaCaptureLimits.ts` (+97 -0) 📝 `src/gdb/GdbSessionManager.ts` (+66 -13) 📝 `src/ida/IdaBusyHealth.test.ts` (+2 -0) _...and 19 more files_ </details> ### 📄 Description <!-- CURSOR_AGENT_PR_BODY_BEGIN --> ## Summary Names the deadlines in the #5910 provider-timeout theme and makes the shared one-shot objdump/rizin clock adjustable. Does not repeat the MCP response-budget work in #6005. Refs #5910 (parent #5808). Merged `main` (`d8a9673fc`). The only conflict was `src/config/providerStartupTimeout.ts`: this branch keeps main's exported `MAX_PROVIDER_STARTUP_TIMEOUT_MS`, and JEB remediation uses that name. `docs/mcp-contracts.md` auto-merged, keeping both the swiftc restart sentence and the JEB discovery sentence. ## Problem and expected behavior JEB `tools/call` timeouts did not name `REA_JEB_MCP_TIMEOUT_MS`, and catalog discovery ignored that setting while the docs said the tools/call budget does not extend discovery. A later pass still left the SDK request timeout at its 60000 ms default whenever the configured discovery budget was larger. IDA request timeouts did not name registration `timeoutMs`. One-shot objdump and rizin used a fixed 120000 ms deadline with no caller control, and the production command runner ignored a passed timeout. Preflight also restarted that clock after `stat`, so digest could spend the full budget again. Architecture Evidence dropped a selected timeout when there was no artifact path. gdb, Rizin debug, Frida, and Cutter caps in this theme failed without saying they have no override, and some sentences named a cap that had not fired. A timeout now names the effective milliseconds, the control when one exists, the accepted range, and when a change applies. Raising `REA_JEB_MCP_TIMEOUT_MS` raises catalog discovery and each `tools/call` together, and discovery passes the time still remaining as the SDK timeout on connect and every `tools/list` page. `command_timeout_ms` (CLI `--command-timeout-ms`) changes the next one-shot objdump or rizin call. Omitted still means 120000 ms. Target preflight shares one budget across stat and digest. The one-shot command receives that budget again. The post-run digest starts another full budget and shares stat and hash inside that call. ## Change and scope Follow the [contribution scope](https://github.com/morluto/rea/blob/main/CONTRIBUTING.md#contribution-scope). Unresolved scope, authority, side effects, or required verification block integration. Link the required maintainer scope decision for new providers or capabilities involving target execution, injection, mutation, or protection recovery; ordinary fixes within existing boundaries may state "not applicable". Draft PRs may leave the scope decision pending and the readiness and merge checklists unchecked. Maintainers can help resolve open questions. Not applicable. This names and wires existing analysis deadlines and adds one caller-selected timeout on commands REA already runs. It does not add a provider, injection, mutation, or protection recovery. Named, existing controls: - JEB: `REA_JEB_MCP_TIMEOUT_MS`, integer 1..2147483647. Omitted means the pinned MCP SDK default of 60000 ms. Restart and reconnect to apply. The same parsed value is passed as `discoveryTimeoutMs` and `requestTimeoutMs`. Connect and each `tools/list` page pass `deadline.remainingMs()` as the SDK request timeout, so a configured value above 60000 ms is not replaced by the SDK default. It is still not one end-to-end deadline: discovery and each `tools/call` each start their own budget. - IDA: JSON key `timeoutMs` in the file named by `REA_IDA_MCP_CONFIG` (verified in `src/ida/IdaConfiguration.ts`). Integer 1..2147483647. Omitted means 300000. The file is re-read when the next IDA connection is created; an open session keeps the timeout it connected with. Changing the env path itself is process start. A shorter inner request is the time remaining inside that ceiling, and the error names both when they differ. Readiness-while-busy uses the same key. Newly adjustable: - `command_timeout_ms` on `inspect_with_objdump` (including `architectures`) and `execute_rizin_command`. Default 120000, range 1..2147483647, next call, no restart. Target preflight shares one budget across stat and digest. The one-shot command receives that budget again. The post-run digest starts another full budget and shares stat and hash inside that call. It does not raise the 16 MiB combined output cap, Ghidra or Hopper startup, or a debugger session deadline. The production runner now uses `options.timeout` instead of ignoring it. The omitted path stays 120000 ms. A selected value is kept on architecture Evidence; omission leaves the key absent. Left fixed, with “no runtime override” on the agent-visible failure or limitation: - GDB startup 10000 ms, MI command 120000 ms, 16 MiB output, session capacity, and the pending-command queue. - Rizin debug startup 30000 ms, command frame 120000 ms, the 16777216 byte frame cap, the 16777216 byte command-output cap, the 4096 frame command cap, session capacity, and the pending-command queue. Evidence names the cap that stopped capture. The internal 1000 ms cleanup drain only marks output truncated and is not its own timeout, so it stays unnamed. - Frida local `getDeviceById` wait of 1000 ms. Frida Core 17.23.2 rejects that wait with `Device not found`, and only that rejection is reported as the deadline. A device-manager or backend failure, such as `Device manager is closed`, stays a capability failure with its own message and is not reported as the deadline. Remote devices do not use the lookup. `messages_truncated` means the session capture budget dropped data. Field truncation names its own cap and does not set that flag. Flags inside a caller `payload` are ignored. The sentences live in `src/frida/fridaCaptureLimits.ts`. - Cutter request 25000 ms, 16777216 byte frame, and 256-candidate discovery budget. Numbers unchanged. - The shared objdump/rizin admission cap of 8 concurrent operations, named while that error was already being edited. `command_timeout_ms` does not raise it. Ghidra 330000 (`REA_GHIDRA_STARTUP_TIMEOUT_MS`), Hopper 120000 (`REA_HOPPER_STARTUP_TIMEOUT_MS`), and Kuna project/function timeouts already name their controls. They are unchanged. Out of scope: MCP response budget (#6005), JavaScript heap, Android/JADX, browser, native, swiftc, engines, and ASAR. ## Contract and boundary impact - Semantic owner and earliest changed stage: JEB composition reads `REA_JEB_MCP_TIMEOUT_MS` and passes it to both connection phases. The connection owner applies the remaining discovery budget to the SDK handshake and each catalog page. IDA configuration owns `timeoutMs` guidance. `src/domain/reverseEngineering.ts` owns `command_timeout_ms`; `ReverseEngineeringService` applies one budget across preflight stat and digest, then again to the command. Debugger, Frida, and Cutter providers own their fixed-cap sentences. Frida capture-cap wording is owned by `src/frida/fridaCaptureLimits.ts`. Frida device lookup classifies the provider rejection in `FridaInstrumentationManager.#selectDevice`; `providerError` still maps a non-timeout cause to a capability failure. - Contribution scope fit and linked maintainer decision: not applicable. Existing command and provider boundaries. - CLI and MCP/tool-catalog contract: optional `command_timeout_ms` / `--command-timeout-ms` on one-shot objdump, architecture listing, and one-shot rizin. Omitted input stays valid. Tool descriptions name the default, range, and what it does not raise. `rizin_debug_command` says Evidence names the output-byte, frame-byte, or frame-count cap. Generated catalogs are ignored outputs and were not committed. - Provider, bridge, target-format, or platform compatibility: JEB discovery follows an explicit `REA_JEB_MCP_TIMEOUT_MS` instead of staying at 60000 ms, including on the SDK request timeout. IDA, Ghidra, Hopper, and Kuna numbers are unchanged. - Evidence, artifact, provenance, or reconstruction contract: a selected `command_timeout_ms` is recorded on one-shot Evidence parameters, including architecture listing. Omission leaves the key absent. Timeout Evidence and limitations name the effective deadline or the capture cap that fired. - Target selection, authority, upstream behavior, and cleanup details (if applicable): no new target authority. Recovery text still tells the caller to confirm outstanding work and cleanup before retry, and to leave headroom in the outer MCP client deadline. - Generated metadata (`docs/public/product-catalog.json`), package, or installation impact (CI generates and validates ignored catalogs and `skills/`; edit authored instructions in `.agents/skills/reverse-engineer-anything/` and never commit build outputs): none committed. The packaged skill does not document these deadlines. 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. Existing objdump, rizin, debugger, Frida, and Cutter operations already perform their target interactions. This PR changes deadline selection and recovery text. It does not add a new interaction. ## Evidence and regression coverage - Tests added or updated: `src/jeb/JebMcpConnection.test.ts` (discovery budget of 120000 ms on connect and every catalog page), `tests/boundary/providers/jebMcpTimeout.test.ts`, `src/ida/IdaMcpConnection.test.ts`, `src/ida/IdaBusyHealth.test.ts`, `tests/composition/reverseEngineering.test.ts` (shared preflight clock, architecture Evidence, `runOwned` `limits.timeoutMs`), `tests/boundary/cli/reverseEngineeringCommands.test.ts`, `src/application/frida/FridaInstrumentationManager.test.ts` (`Device not found` is the 1000 ms deadline; `Device manager is closed` stays a capability failure), `src/application/frida/FridaInstrumentationService.test.ts`, `tests/boundary/mcp/fridaLifecycleMcp.test.ts` (field truncation does not set `messages_truncated`), `tests/composition/reverseEngineeringEdgeCases.test.ts` (admission sentence includes the operation count), `tests/boundary/providers/GdbSessionManagerCoverage.test.ts` (named MI record cap), `tests/boundary/providers/RizinTimeoutEvidence.test.ts`, `tests/boundary/providers/RizinDebugSessionCoverage.part4.test.ts`, `tests/boundary/providers/RizinDebugSessionCoverage.part5.test.ts` (4096 frame sentence). - Base reproduction or other evidence: source inspection. JEB connect and `tools/list` previously passed only `signal`, so `@modelcontextprotocol/client` 2.3.1 kept `DEFAULT_REQUEST_TIMEOUT_MSEC` 60000. `digestFile` started the hash timer only after stat returned. `#observeProvider` replaced architecture parameters with `{ operation: "architectures" }`. `runOwnedCommandOutput` maps `options.timeout` to `limits.timeoutMs`; a test that replaces `run` never reaches that adapter. Frida field truncation set `messages_truncated`. Rizin frame-count truncation reused the byte-cap sentence. `#selectDevice` turned every `getDeviceById` rejection into `AnalysisTimeoutError`. Installed Frida 17.23.2 on this machine: `getDeviceById` for a missing id with a 50 ms timeout rejected after about 50 ms with message `Device not found`; the same call after `close()` rejected immediately with `Device manager is closed`. - User-visible CLI/MCP output (if applicable): a 100 ms JEB catalog timeout projects `catalog discovery` and `100 ms`, and the remediation names `REA_JEB_MCP_TIMEOUT_MS`, `2147483647`, `60000`, and restart. A tools/call timeout says `tools/call`. An IDA request of 40 ms inside a 1000 ms ceiling names both and `REA_IDA_MCP_CONFIG`. A one-shot rizin timeout with no field says `command_timeout_ms` and `120000 ms` and omits the key from parameters. `command_timeout_ms: 5000` is the error timeout, is passed to the command runner, and is recorded on parameters, including architecture Evidence. `0` and `2147483648` are `AnalysisInputError`. A 4096-frame Rizin capture says `4096 frame command limit` and does not claim `16777216`. Frida type truncation names `4096` and does not set `messages_truncated`. A Frida `Device not found` lookup projects `provider_timeout` at 1000 ms. `Device manager is closed` projects `capability_unavailable` and does not say `deadlineExpired`. - Remaining proof gaps: no live JEB, IDA, GDB, Rizin, or Cutter process was used. The Frida observation above is the local device manager only; no target was attached and no script was loaded. GitHub CI on `946c011a` failed in Source tests, Test shard (5/8), Reverse tools quality, Portable tests, and CI required for the three stale assertions fixed here. Those jobs have not been re-run on this commit yet. Ghidra, Hopper, and Kuna paths were not re-executed because those files were not changed by the review fixes. For evidence-bearing changes: - [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 On `b0eca9fb`: - `npx oxfmt --write` on the five edited files — completed. - `npm run check:fast` — typecheck and lint succeeded (2 tasks). - `npm run test:focused -- src/application/frida/FridaInstrumentationManager.test.ts tests/boundary/mcp/fridaLifecycleMcp.test.ts tests/composition/reverseEngineeringEdgeCases.test.ts tests/boundary/providers/GdbSessionManagerCoverage.test.ts` — 4 files, 312 tests passed. On `946c011a`, not repeated after this commit: focused JEB, IDA was not re-run then either, rizin coverage, `tests/composition/reverseEngineering.test.ts` (27 tests), and `npm run test:local -- src/jeb/JebMcpConnection.test.ts` (13 tests). Real provider workflows were not run. The JEB tests use the repository HTTP fixture and spy on the installed MCP client. The preflight regression uses an injected stat and a stream that never ends; it does not open a FIFO. ## Compatibility, safety, and release - Breaking changes or migration steps: none for omitted input. Callers who set `REA_JEB_MCP_TIMEOUT_MS` now also change catalog discovery, including the SDK request timeout; previously that setting did not. A slow preflight stat now consumes the same budget as the digest instead of granting the hash a fresh full budget. `messages_truncated` is no longer set for field-only truncation. A non-timeout Frida device lookup failure is `capability_unavailable` instead of `provider_timeout`. Timeout and limitation sentences changed. Numeric debugger, Frida, and Cutter caps are unchanged. `command_timeout_ms` is optional. - Real Hopper/Ghidra, browser, or OS coverage: not run. Ghidra, Hopper, and Kuna sources were not edited by the review fixes. The local Frida device-manager probe did not attach to a target. - Package or release metadata impact: none. - Security, privacy, process, or containment review: a longer `command_timeout_ms` lets an already admitted objdump or rizin command run longer. It does not raise output, concurrency, or debugger authority. The upper bound is the signed 32-bit timer ceiling, 2147483647 ms. ## Author readiness Human owner: @morluto - [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. <!-- CURSOR_AGENT_PR_BODY_END --> <div><a href="https://cursor.com/agents/bc-6ae05acd-f197-5498-a220-d111758d3fdd?cursor_ref=pr_footer&cursor_cta=open_in_web"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-web-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-web-light.png"><img alt="Open in Web" width="114" height="28" src="https://cursor.com/assets/images/open-in-web-dark.png"></picture></a>&nbsp;<a href="https://cursor.com/background-agent?bcId=bc-6ae05acd-f197-5498-a220-d111758d3fdd&cursor_ref=pr_footer&cursor_cta=open_in_cursor"><picture><source media="(prefers-color-scheme: dark)" srcset="https://cursor.com/assets/images/open-in-cursor-dark.png"><source media="(prefers-color-scheme: light)" srcset="https://cursor.com/assets/images/open-in-cursor-light.png"><img alt="Open in Cursor" width="131" height="28" src="https://cursor.com/assets/images/open-in-cursor-dark.png"></picture></a>&nbsp;</div> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:45:33 +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#7122
No description provided.