[PR #7127] [MERGED] fix(mcp)!: return a compact binary_session status by default #7659

Closed
opened 2026-11-03 13:39:26 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/7127
Author: @kaoru0822-kitauji
Created: 10/25/2026
Status: ✅ Merged
Merged: 10/25/2026
Merged by: @kaoru0822-kitauji

Base: main ← Head: fix/7109-binary-session-compact


📝 Commits (2)

  • d4b9d51 fix(mcp)!: return a compact binary_session status by default
  • 5f64263 fix(mcp): key binary_session output fields by detail

📊 Changes

28 files changed (+985 additions, -184 deletions)

View changed files

📝 .agents/skills/reverse-engineer-anything/SKILL.md (+10 -6)
📝 .agents/skills/reverse-engineer-anything/references/connection-and-recovery.md (+1 -1)
📝 .agents/skills/reverse-engineer-anything/references/native-and-artifacts.md (+12 -9)
📝 docs/mcp-contracts.md (+20 -8)
📝 scripts/lib/mcp-verifier-results.mjs (+10 -4)
📝 src/application/CapabilityInventory.test.ts (+42 -0)
📝 src/application/CapabilityInventory.ts (+38 -19)
📝 src/application/binary/BinarySession.ts (+7 -1)
📝 src/application/binary/BinarySessionPort.ts (+6 -1)
📝 src/application/binary/BinarySessionStatus.test.ts (+124 -15)
📝 src/application/binary/BinarySessionStatus.ts (+41 -14)
📝 src/contracts/sessionStatusContract.ts (+23 -0)
📝 src/contracts/sessionToolContracts.ts (+1 -1)
📝 src/contracts/toolOutputSchemaGroups.ts (+31 -21)
📝 src/contracts/toolOutputSchemaPrimitives.ts (+155 -43)
📝 src/process/RegexMatcher.test.ts (+42 -7)
📝 src/process/RegexMatcher.ts (+15 -7)
📝 src/server/promptCompletion.ts (+4 -1)
📝 src/server/registerSessionStatusTool.ts (+18 -2)
📝 tests/acceptance/applications/runtime.test.ts (+2 -2)

...and 8 more files

📄 Description

What broke: binary_session {} with no target open returned about 66 KB (an estimated 19K tokens). It grew 21% in 6.8.0, and the skill's recovery flow pays that on every retry.
Fix: the regex capability limitation goes back to stating facts (the recovery steps stay on the errors), and binary_session gains detail: "summary" | "complete". The default summary is 15.7 KB and keeps every decision fact. It lists what it leaves out in omitted_fields.
Risk: callers that read candidate diagnostics/capabilities or tool surface/effects/annotations from the default response must now pass {"detail": "complete"}. This is marked !.

Summary

Fixes #7109.

Before this change, the target-free binary_session {} returned every provider's rejection diagnostics, each candidate's capability sets, and tool availability grouped by static catalog flags. That is 66,077 bytes on a host with no deep-analysis provider configured. The skill sends agents here when a tool is unadvertised and during connection recovery. Now the default is a summary of 15,668 bytes that still answers "what can I call, and if not, why and how do I fix it". {"detail": "complete"} returns the previous shape.

Problem and expected behavior

Regression source (6.7.0 → 6.8.0, +10,309 chars in analysis_provider_candidates):

  • The shared regex capability limitation (regexMatchingLimitation, src/process/RegexMatcher.ts) grew from 198 to 1,646–1,694 chars. It appears once for each search operation of each provider (Hopper, IDA, Kuna × search_procedures/search_strings), so six times. That accounts for +9,276 chars. The commits that grew it:
  • db8556e72 (#4862) added that limitation to IDA's two search operations.
  • 264862bf2 added IDA registration diagnostics (configuration_details, configuration_remediation, +384 chars). New effect flags account for the rest.

The pre-existing ~55 KB baseline was itself mostly diagnostics and capability sets that an idle status check does not need.

Change and scope

  • Producer fix. The regex limitation now names the effective deadline and heap, their sources, the runtime setting IDs, the launch variables, and the settings tools: 588–636 chars instead of 1,646–1,694. The full bounds and step-by-step recovery stay on regexMatchingDeadlineError and regexWorkerHeapError, where they are actionable. They match docs/native-investigation.md. This also shrinks every IDA regex search's Evidence limitations, which pushed the same text.
  • Opt-in detail. binary_session had no detail, summary or paging contract. This adds detail using the repository's existing summary/complete vocabulary.
    • The summary keeps:
      • open state, target identity and the binding
      • current-route capabilities
      • run, activity and health status
      • client_features and server_identity
      • per candidate: provider, selected, and availability and target-support status/code/reason
      • every tool's available/reason/remediation/modes/client_requirements, grouped by those facts only
    • It drops provider diagnostics, candidate capabilities, and tool group surface/effects/annotations, and lists those paths in omitted_fields. Omitted fields are not false or empty.
    • The tool description names the option, because the default compact input-schema profile strips argument descriptions.
  • One implementation. binarySessionStatus (application) projects candidates, and compactToolAvailability (application) projects tool groups. The MCP handler passes the caller's detail. CLI capabilities/providers keep complete provider facts through the same projection, and prompt completion asks for the summary.
  • Consumers.
    • The verifier helper expandMcpSessionStatus keeps summary candidates only for a contract-validated MCP summary. CLI expandProviderOutput still requires candidate capabilities.
    • Tests that assert static flags or diagnostics now request complete.
    • Skill guidance (SKILL.md, native-and-artifacts.md, connection-and-recovery.md) and docs/mcp-contracts.md describe the summary and the opt-in.
  • Not included. I did not change the IDA not_configured reason prefix ("REA configuration is invalid: …"), which reads oddly for an unset variable. I also did not touch #7107/#7119 schema-presentation files.

Contract and boundary impact

  • Semantic owner and earliest changed stage: the regex limitation producer (src/process/RegexMatcher.ts). The session status projection (src/application/binary/BinarySessionStatus.ts, src/application/CapabilityInventory.ts) and the contract (src/contracts/sessionStatusContract.ts, toolOutputSchemaPrimitives.ts).

  • Contribution scope fit and linked maintainer decision: not applicable. This is a regression and efficiency fix within the existing tool.

  • CLI and MCP/tool-catalog contract: binary_session gets a new optional input, detail (default summary). The output adds detail and, for summaries, omitted_fields. Candidates and tool_availability accept the summary or complete form. The output schema keys each result's candidate, tool-group and omission fields by detail: every session kind is crossed with the summary and complete shapes, and omitted_fields is required for a summary and forbidden for complete. The advertised binary_session definition grows from 24,062 to 35,107 bytes, paid once per session in tools/list. CLI output is unchanged.

  • Provider, bridge, target-format, or platform compatibility: provider adapters only receive shorter regex limitation text. No provider behavior changes.

  • Evidence, artifact, provenance, or reconstruction contract: IDA regex search Evidence carries the shorter limitation. Unknown and unavailable status, code and reason stay visible in the summary.

  • Target selection, authority, upstream behavior, and cleanup details: none. cleanup_pending, provider_operation_health and the mid-finalization unknown reason stay inline.

  • Generated metadata, package, or installation impact: the generated catalog picks up the new input and description. docs:check and metadata:check pass.

  • Documentation or usability only; no target interaction.

Evidence and regression coverage

Measured on macOS arm64 with a real stdio @modelcontextprotocol/client 2.3.1 against the built server. No REA_*/Ghidra/IDA/JADX/Kuna variables were set, with an isolated HOME. Results were identical with the real host environment, which has no provider configured. LLDB is present. Ghidra, IDA and Hopper are absent. Sizes are bytes of result.content[0].text; structuredContent carries the same JSON again. Token counts are estimates at 3.5 bytes/token, not tokenizer counts.

binary_session call 6.8.0 (npm) main bc143125e this PR, {} this PR, {"detail":"complete"}
no target 66,233 B (~18.9K tok) 66,077 B (~18.9K tok) 15,668 B (~4.5K tok) 59,749 B (~17.1K tok)
/System/Applications/Calculator.app open 69,114 B (~19.7K tok) 68,958 B (~19.7K tok) 18,088 B (~5.2K tok) 62,630 B (~17.9K tok)

Idle summary breakdown: tool_availability 9,274, route capabilities 3,180, analysis_provider_candidates 1,395, server_identity 1,128 and omitted_fields 268. On main, analysis_provider_candidates was 35,794 and tool_availability was 25,587. The summary has 16 tool groups where main had 78. I did not compare call latency: binary_session still runs every availability probe, and single-run timings (0.5–3.4 s) were dominated by noise. CPU time and peak memory were not measured.

Representative summary output (idle, excerpt):

{"open": false, "detail": "summary",
 "omitted_fields": ["analysis_provider_candidates.availability.diagnostics", "analysis_provider_candidates.target_support.diagnostics", "analysis_provider_candidates.capabilities", "tool_availability.groups.surface", "tool_availability.groups.effects", "tool_availability.groups.annotations"],
 "analysis_provider_candidates": [
  {"provider": {"id": "ghidra", "name": "Ghidra", "version": null},
   "availability": {"status": "unavailable", "code": "not_configured", "reason": "Set GHIDRA_INSTALL_DIR to an extracted Ghidra 12.1.x release directory."},
   "target_support": {"status": "unknown", "code": null, "reason": "No target is open."},
   "selected": false}, "…"],
 "tool_availability": {"client_requirements": {"…": "…"}, "groups": [{"names": ["address_name", "…"], "available": false, "reason": "target_required", "remediation": "Call open_binary with a supported local target."}, "…"]}}

Counterexamples tested:

  • Recovering from an unadvertised tool. The summary's union of group names equals TOOL_CONTRACTS. Each tool's available/reason/remediation/modes/client_requirements equals the complete projection (providerSelectionMcp.test.ts, runtime.test.ts, sqliteDatabaseCli.test.ts, sessionMcp.test.ts).
  • Available provider. The summary is {status: "available", code: null, reason: null}. Its diagnostics and capabilities are returned with complete.
  • Provider mid-startup or finalization. The summary keeps status: "unknown" and the "finalization is in progress" reason. complete keeps diagnostics.finalization (providerSelectionMcp.test.ts, cancelled and physical cases, plus a unit case).
  • Target open. The same checks run after open_binary. Route capabilities and the binding match between summary and complete, and an unsupported target-support code and reason are kept (unit).
  • Unavailable or unconfigured provider. code: "not_configured" and the reason are kept.
  • Invalid detail. It is rejected without starting a provider.
  • Mismatched detail and shape. Each detail relabelled, a summary without omitted_fields, complete with omitted_fields, and swapped candidates or tool groups in each direction are all rejected. This holds for both the canonical contract and the advertised tools/list schema through the SDK AjvJsonSchemaValidator (providerSelectionMcp.test.ts).
  • Verifier paths. A summary MCP status keeps its candidates. A capability-less candidate throws in complete MCP status and in CLI provider output (tests/boundary/process/mcpVerifierResults.test.ts).
  • Regex limitation. The tests check facts, not wording: the 5000 ms deadline, the 128 MiB request and effective heap values, their sources, both setting IDs and both launch variables. The text stays under 700 characters and does not repeat the producers' recovery text. The deadline and heap errors still carry the full recovery, including the unknown-heap launch flags (RegexMatcher.test.ts).

Remaining proof gaps:

  • Real Hopper, Ghidra, IDA and Kuna were not run. Their verifiers read only fields the summary keeps, or route capabilities, but they were not executed.
  • scripts/verify-claude-client.mjs was not run.

Validation performed

  • Real stdio MCP measurements above (6.8.0 npm, main bc143125e built, this branch built): done.
  • npm run typecheck: pass.
  • npm run check:fast: pass, on 5f64263a0 with main fc43e285e.
  • npm run format:check: pass.
  • npm run docs:check: pass.
  • npm run metadata:check: pass.
  • npm run test:focused -- tests/boundary/mcp/toolSchemaValidity.test.ts tests/boundary/mcp/deferredRuntime.test.ts tests/boundary/mcp/contractPresentation.test.ts: 46/46 pass, so the advertised JSON Schemas validate.
  • vitest run --maxWorkers=2 on unit and source tests:
    • BinarySessionStatus, CapabilityInventory, RegexMatcher, regexMatchingDeadline, regexWorkerHeapRequest, IdaProvider, BundleResourcesMcp, AnalysisProviderRegistry, analysisErrorProjection and toolOutputReferences: pass.
    • providerSelectionMcp, serverIdentity, fridaLifecycleMcp, jebMcp, electronMcp, sessionMcp and runtime: pass after the test updates.
  • vitest run --maxWorkers=2 across 67 related test files (every file that mentions binary_session, tool_availability or the regex limitation, plus the unit and verifier tests), after rebuilding 5f64263a0: 64 pass. Three tests also fail on unmodified main bc143125e on this host (Node 26.5.0, below the engines range):
    • dshClientSetup (setup dry-run exits 1)
    • sqliteDatabaseCli "beyond SQLite bind capacity"
    • hopperStartupRecovery "denial-shaped failure" (Hopper is not installed)

Compatibility, safety, and release

  • Breaking change. binary_session {} used to return analysis_provider_candidates[].availability.diagnostics, target_support.diagnostics and capabilities, and tool_availability.groups[].surface/effects/annotations. These are now omitted by default and listed in omitted_fields. To migrate, pass {"detail": "complete"}, which returns the previous shape plus detail: "complete". Keeping complete as the default would keep the ~66 KB cost on every recovery check, which is what this issue is about. A client that sends detail to an older server is rejected by that server's strict input schema.
  • Real Hopper/Ghidra, browser, or OS coverage: macOS arm64 only. No real deep-analysis provider was available.
  • Package or release metadata impact: the generated MCP catalog changes.
  • Security, privacy, process, or containment review: no new effects. The summary only removes fields.

Author readiness

Human owner: @kaoru0822-kitauji

  • 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/7127 **Author:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Created:** 10/25/2026 **Status:** ✅ Merged **Merged:** 10/25/2026 **Merged by:** [@kaoru0822-kitauji](https://github.com/kaoru0822-kitauji) **Base:** `main` ← **Head:** `fix/7109-binary-session-compact` --- ### 📝 Commits (2) - [`d4b9d51`](https://github.com/morluto/rea/commit/d4b9d512e355ec992b658341676092ff0bf1bc18) fix(mcp)!: return a compact binary_session status by default - [`5f64263`](https://github.com/morluto/rea/commit/5f64263a0808c39ba312febd188ea72803f6bce7) fix(mcp): key binary_session output fields by detail ### 📊 Changes **28 files changed** (+985 additions, -184 deletions) <details> <summary>View changed files</summary> 📝 `.agents/skills/reverse-engineer-anything/SKILL.md` (+10 -6) 📝 `.agents/skills/reverse-engineer-anything/references/connection-and-recovery.md` (+1 -1) 📝 `.agents/skills/reverse-engineer-anything/references/native-and-artifacts.md` (+12 -9) 📝 `docs/mcp-contracts.md` (+20 -8) 📝 `scripts/lib/mcp-verifier-results.mjs` (+10 -4) 📝 `src/application/CapabilityInventory.test.ts` (+42 -0) 📝 `src/application/CapabilityInventory.ts` (+38 -19) 📝 `src/application/binary/BinarySession.ts` (+7 -1) 📝 `src/application/binary/BinarySessionPort.ts` (+6 -1) 📝 `src/application/binary/BinarySessionStatus.test.ts` (+124 -15) 📝 `src/application/binary/BinarySessionStatus.ts` (+41 -14) 📝 `src/contracts/sessionStatusContract.ts` (+23 -0) 📝 `src/contracts/sessionToolContracts.ts` (+1 -1) 📝 `src/contracts/toolOutputSchemaGroups.ts` (+31 -21) 📝 `src/contracts/toolOutputSchemaPrimitives.ts` (+155 -43) 📝 `src/process/RegexMatcher.test.ts` (+42 -7) 📝 `src/process/RegexMatcher.ts` (+15 -7) 📝 `src/server/promptCompletion.ts` (+4 -1) 📝 `src/server/registerSessionStatusTool.ts` (+18 -2) 📝 `tests/acceptance/applications/runtime.test.ts` (+2 -2) _...and 8 more files_ </details> ### 📄 Description **What broke:** `binary_session {}` with no target open returned about 66 KB (an estimated 19K tokens). It grew 21% in 6.8.0, and the skill's recovery flow pays that on every retry. **Fix:** the regex capability limitation goes back to stating facts (the recovery steps stay on the errors), and `binary_session` gains `detail: "summary" | "complete"`. The default summary is 15.7 KB and keeps every decision fact. It lists what it leaves out in `omitted_fields`. **Risk:** callers that read candidate `diagnostics`/`capabilities` or tool `surface`/`effects`/`annotations` from the default response must now pass `{"detail": "complete"}`. This is marked `!`. ## Summary Fixes #7109. Before this change, the target-free `binary_session {}` returned every provider's rejection diagnostics, each candidate's capability sets, and tool availability grouped by static catalog flags. That is 66,077 bytes on a host with no deep-analysis provider configured. The skill sends agents here when a tool is unadvertised and during connection recovery. Now the default is a summary of 15,668 bytes that still answers "what can I call, and if not, why and how do I fix it". `{"detail": "complete"}` returns the previous shape. ## Problem and expected behavior Regression source (6.7.0 → 6.8.0, +10,309 chars in `analysis_provider_candidates`): - The shared regex capability limitation (`regexMatchingLimitation`, `src/process/RegexMatcher.ts`) grew from 198 to 1,646–1,694 chars. It appears once for each search operation of each provider (Hopper, IDA, Kuna × `search_procedures`/`search_strings`), so six times. That accounts for **+9,276 chars**. The commits that grew it: - 8413ec08f (#6099): launch heap flags. - c7efd3a38 (#6267): deadline bounds and recovery. - 9512a8080 (#6301): heap-request bounds and recovery. - f3ed1657f (#7049): runtime `update_analysis_settings` wording. - db8556e72 (#4862) added that limitation to IDA's two search operations. - 264862bf2 added IDA registration diagnostics (`configuration_details`, `configuration_remediation`, +384 chars). New effect flags account for the rest. The pre-existing ~55 KB baseline was itself mostly diagnostics and capability sets that an idle status check does not need. ## Change and scope - **Producer fix.** The regex limitation now names the effective deadline and heap, their sources, the runtime setting IDs, the launch variables, and the settings tools: 588–636 chars instead of 1,646–1,694. The full bounds and step-by-step recovery stay on `regexMatchingDeadlineError` and `regexWorkerHeapError`, where they are actionable. They match `docs/native-investigation.md`. This also shrinks every IDA regex search's Evidence `limitations`, which pushed the same text. - **Opt-in detail.** `binary_session` had no detail, summary or paging contract. This adds `detail` using the repository's existing `summary`/`complete` vocabulary. - The summary keeps: - open state, target identity and the binding - current-route `capabilities` - run, activity and health status - `client_features` and `server_identity` - per candidate: `provider`, `selected`, and availability and target-support `status`/`code`/`reason` - every tool's `available`/`reason`/`remediation`/`modes`/`client_requirements`, grouped by those facts only - It drops provider `diagnostics`, candidate `capabilities`, and tool group `surface`/`effects`/`annotations`, and lists those paths in `omitted_fields`. Omitted fields are not false or empty. - The tool description names the option, because the default compact input-schema profile strips argument descriptions. - **One implementation.** `binarySessionStatus` (application) projects candidates, and `compactToolAvailability` (application) projects tool groups. The MCP handler passes the caller's `detail`. CLI `capabilities`/`providers` keep complete provider facts through the same projection, and prompt completion asks for the summary. - **Consumers.** - The verifier helper `expandMcpSessionStatus` keeps summary candidates only for a contract-validated MCP summary. CLI `expandProviderOutput` still requires candidate capabilities. - Tests that assert static flags or diagnostics now request `complete`. - Skill guidance (`SKILL.md`, `native-and-artifacts.md`, `connection-and-recovery.md`) and `docs/mcp-contracts.md` describe the summary and the opt-in. - **Not included.** I did not change the IDA `not_configured` reason prefix ("REA configuration is invalid: …"), which reads oddly for an unset variable. I also did not touch #7107/#7119 schema-presentation files. ## Contract and boundary impact - Semantic owner and earliest changed stage: the regex limitation producer (`src/process/RegexMatcher.ts`). The session status projection (`src/application/binary/BinarySessionStatus.ts`, `src/application/CapabilityInventory.ts`) and the contract (`src/contracts/sessionStatusContract.ts`, `toolOutputSchemaPrimitives.ts`). - Contribution scope fit and linked maintainer decision: not applicable. This is a regression and efficiency fix within the existing tool. - CLI and MCP/tool-catalog contract: `binary_session` gets a new optional input, `detail` (default `summary`). The output adds `detail` and, for summaries, `omitted_fields`. Candidates and `tool_availability` accept the summary or complete form. The output schema keys each result's candidate, tool-group and omission fields by `detail`: every session kind is crossed with the summary and complete shapes, and `omitted_fields` is required for a summary and forbidden for complete. The advertised `binary_session` definition grows from 24,062 to 35,107 bytes, paid once per session in `tools/list`. CLI output is unchanged. - Provider, bridge, target-format, or platform compatibility: provider adapters only receive shorter regex limitation text. No provider behavior changes. - Evidence, artifact, provenance, or reconstruction contract: IDA regex search Evidence carries the shorter limitation. Unknown and unavailable status, code and reason stay visible in the summary. - Target selection, authority, upstream behavior, and cleanup details: none. `cleanup_pending`, `provider_operation_health` and the mid-finalization `unknown` reason stay inline. - Generated metadata, package, or installation impact: the generated catalog picks up the new input and description. `docs:check` and `metadata:check` pass. - [x] Documentation or usability only; no target interaction. ## Evidence and regression coverage Measured on macOS arm64 with a real stdio `@modelcontextprotocol/client` 2.3.1 against the built server. No `REA_*`/Ghidra/IDA/JADX/Kuna variables were set, with an isolated `HOME`. Results were identical with the real host environment, which has no provider configured. LLDB is present. Ghidra, IDA and Hopper are absent. Sizes are bytes of `result.content[0].text`; `structuredContent` carries the same JSON again. Token counts are **estimates** at 3.5 bytes/token, not tokenizer counts. | `binary_session` call | 6.8.0 (npm) | main bc143125e | this PR, `{}` | this PR, `{"detail":"complete"}` | | --- | --- | --- | --- | --- | | no target | 66,233 B (~18.9K tok) | 66,077 B (~18.9K tok) | **15,668 B (~4.5K tok)** | 59,749 B (~17.1K tok) | | `/System/Applications/Calculator.app` open | 69,114 B (~19.7K tok) | 68,958 B (~19.7K tok) | **18,088 B (~5.2K tok)** | 62,630 B (~17.9K tok) | Idle summary breakdown: `tool_availability` 9,274, route `capabilities` 3,180, `analysis_provider_candidates` 1,395, `server_identity` 1,128 and `omitted_fields` 268. On main, `analysis_provider_candidates` was 35,794 and `tool_availability` was 25,587. The summary has 16 tool groups where main had 78. I did not compare call latency: `binary_session` still runs every availability probe, and single-run timings (0.5–3.4 s) were dominated by noise. CPU time and peak memory were not measured. Representative summary output (idle, excerpt): ```json {"open": false, "detail": "summary", "omitted_fields": ["analysis_provider_candidates.availability.diagnostics", "analysis_provider_candidates.target_support.diagnostics", "analysis_provider_candidates.capabilities", "tool_availability.groups.surface", "tool_availability.groups.effects", "tool_availability.groups.annotations"], "analysis_provider_candidates": [ {"provider": {"id": "ghidra", "name": "Ghidra", "version": null}, "availability": {"status": "unavailable", "code": "not_configured", "reason": "Set GHIDRA_INSTALL_DIR to an extracted Ghidra 12.1.x release directory."}, "target_support": {"status": "unknown", "code": null, "reason": "No target is open."}, "selected": false}, "…"], "tool_availability": {"client_requirements": {"…": "…"}, "groups": [{"names": ["address_name", "…"], "available": false, "reason": "target_required", "remediation": "Call open_binary with a supported local target."}, "…"]}} ``` Counterexamples tested: - **Recovering from an unadvertised tool.** The summary's union of group names equals `TOOL_CONTRACTS`. Each tool's `available`/`reason`/`remediation`/`modes`/`client_requirements` equals the complete projection (`providerSelectionMcp.test.ts`, `runtime.test.ts`, `sqliteDatabaseCli.test.ts`, `sessionMcp.test.ts`). - **Available provider.** The summary is `{status: "available", code: null, reason: null}`. Its diagnostics and capabilities are returned with `complete`. - **Provider mid-startup or finalization.** The summary keeps `status: "unknown"` and the "finalization is in progress" reason. `complete` keeps `diagnostics.finalization` (`providerSelectionMcp.test.ts`, cancelled and physical cases, plus a unit case). - **Target open.** The same checks run after `open_binary`. Route capabilities and the binding match between summary and complete, and an unsupported target-support code and reason are kept (unit). - **Unavailable or unconfigured provider.** `code: "not_configured"` and the reason are kept. - **Invalid `detail`.** It is rejected without starting a provider. - **Mismatched detail and shape.** Each detail relabelled, a summary without `omitted_fields`, complete with `omitted_fields`, and swapped candidates or tool groups in each direction are all rejected. This holds for both the canonical contract and the advertised `tools/list` schema through the SDK `AjvJsonSchemaValidator` (`providerSelectionMcp.test.ts`). - **Verifier paths.** A summary MCP status keeps its candidates. A capability-less candidate throws in complete MCP status and in CLI provider output (`tests/boundary/process/mcpVerifierResults.test.ts`). - **Regex limitation.** The tests check facts, not wording: the 5000 ms deadline, the 128 MiB request and effective heap values, their sources, both setting IDs and both launch variables. The text stays under 700 characters and does not repeat the producers' recovery text. The deadline and heap errors still carry the full recovery, including the unknown-heap launch flags (`RegexMatcher.test.ts`). Remaining proof gaps: - Real Hopper, Ghidra, IDA and Kuna were not run. Their verifiers read only fields the summary keeps, or route capabilities, but they were not executed. - `scripts/verify-claude-client.mjs` was not run. ## Validation performed - Real stdio MCP measurements above (6.8.0 npm, main bc143125e built, this branch built): done. - `npm run typecheck`: pass. - `npm run check:fast`: pass, on 5f64263a0 with main fc43e285e. - `npm run format:check`: pass. - `npm run docs:check`: pass. - `npm run metadata:check`: pass. - `npm run test:focused -- tests/boundary/mcp/toolSchemaValidity.test.ts tests/boundary/mcp/deferredRuntime.test.ts tests/boundary/mcp/contractPresentation.test.ts`: 46/46 pass, so the advertised JSON Schemas validate. - `vitest run --maxWorkers=2` on unit and source tests: - `BinarySessionStatus`, `CapabilityInventory`, `RegexMatcher`, `regexMatchingDeadline`, `regexWorkerHeapRequest`, `IdaProvider`, `BundleResourcesMcp`, `AnalysisProviderRegistry`, `analysisErrorProjection` and `toolOutputReferences`: pass. - `providerSelectionMcp`, `serverIdentity`, `fridaLifecycleMcp`, `jebMcp`, `electronMcp`, `sessionMcp` and `runtime`: pass after the test updates. - `vitest run --maxWorkers=2` across 67 related test files (every file that mentions `binary_session`, `tool_availability` or the regex limitation, plus the unit and verifier tests), after rebuilding 5f64263a0: 64 pass. Three tests also fail on unmodified main bc143125e on this host (Node 26.5.0, below the engines range): - `dshClientSetup` (setup dry-run exits 1) - `sqliteDatabaseCli` "beyond SQLite bind capacity" - `hopperStartupRecovery` "denial-shaped failure" (Hopper is not installed) ## Compatibility, safety, and release - **Breaking change.** `binary_session {}` used to return `analysis_provider_candidates[].availability.diagnostics`, `target_support.diagnostics` and `capabilities`, and `tool_availability.groups[].surface/effects/annotations`. These are now omitted by default and listed in `omitted_fields`. To migrate, pass `{"detail": "complete"}`, which returns the previous shape plus `detail: "complete"`. Keeping complete as the default would keep the ~66 KB cost on every recovery check, which is what this issue is about. A client that sends `detail` to an older server is rejected by that server's strict input schema. - **Real Hopper/Ghidra, browser, or OS coverage:** macOS arm64 only. No real deep-analysis provider was available. - **Package or release metadata impact:** the generated MCP catalog changes. - **Security, privacy, process, or containment review:** no new effects. The summary only removes fields. ## Author readiness Human owner: @kaoru0822-kitauji - [x] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [x] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [x] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [ ] The PR has one focused outcome and the title follows `type(scope): outcome`. - [ ] Related issue is linked, or the reason for not linking one is stated above. - [ ] Tests cover changed observable behavior and meaningful failure paths. - [ ] Owning docs, contracts, and generated metadata are updated where needed. - [ ] User-visible CLI/MCP changes include representative output. - [ ] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 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-03 13:39:26 +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#7659
No description provided.