[PR #1206] [CLOSED] fix(cli): advertise an address, not a symbol name, on the xrefs selector #2719

Closed
opened 2026-10-17 21:09:27 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/1206
Author: @xecanto
Created: 10/9/2026
Status: ❌ Closed

Base: main ← Head: fix/1186-xrefs-address-selector-help


📝 Commits (1)

  • c56eb8a fix(cli): advertise an address, not a symbol name, on the xrefs selector

📊 Changes

4 files changed (+90 additions, -3 deletions)

View changed files

📝 docs/native-investigation.md (+3 -1)
📝 src/cli/coreBinaryCommands.ts (+6 -2)
📝 src/ghidra/GhidraFunctionValues.test.ts (+33 -0)
➕ tests/boundary/cli/xrefsSelectorHelp.test.ts (+48 -0)

📄 Description

Summary

Fixes #1186.

rea xrefs described both of its selectors as "Address or symbol name", so the reported workflow — rea xrefs ./c-arm64 _table_only --provider ghidra — failed on the spelling the command's own help invited. The operation selects an analyzed address; this PR makes the help and the docs say so, and points at the paths that do resolve a name.

Problem and expected behavior

Smallest trigger: rea xrefs --help advertises "Address or symbol name" for the positional selector and --address, but a bare name is rejected in input validation before any provider resolution:

{"code":"invalid_request","details":{"operation":"xrefs","issues":[{"path":["address"],"reason":"invalid_format",
"message":"Use hexadecimal digits, optionally prefixed with 0x, or an encoded address-space name followed by :0x and hexadecimal digits","expected":"regex"}]}}

The violated invariant is agreement between surfaces, and the evidence says the address-only side is the intended one:

  • src/contracts/officialToolContracts.ts → xrefs: "headless providers such as Ghidra require an explicit address."
  • src/ghidra/GhidraFunctionValues.ts → xrefs: z.object({ document, address: ghidraInputAddressSchema }), hexadecimal or space:0x… only.
  • The name workflow already exists as its own tool: find_xrefs_to_name ("Resolve an exact name against the bound provider's name inventory…"), composed from list_names + xrefs in CapabilityInventory.

So the defect is the promise, not the validation: two selector descriptions in src/cli/coreBinaryCommands.ts and one sentence in docs/native-investigation.md ("xrefs accepts --address=<name-or-address>"). Expected behavior: the help and docs describe an analyzed address, and a caller holding a name is told where to resolve it.

Change and scope

  • Both xrefs selector descriptions now read "Analyzed code or data address" (the --address one keeps its leading-dash guidance).
  • docs/native-investigation.md says xrefs accepts --address=<address>, that it is not a symbol name, and how to resolve one: rea function <name> or rea search on the CLI, find_xrefs_to_name over MCP. The neighbouring --procedure=<name-or-address> sentence is correct and untouched — those selectors do resolve names through resolveProcedure.

Intentionally not included: teaching the xrefs selector to resolve names. That is the other way to close #1186, and it is a contract change rather than a correction — it would widen ghidraInputAddressSchema for one operation, add name resolution for an address-typed selector in bridge/ghidra/ReaGhidraBridge.java, overlap find_xrefs_to_name, and need updated verifiers and catalog artifacts. CONTRIBUTING asks for an issue before a change of that size, and I cannot run the real-Ghidra verification it would need. If that is the direction you want, say so and I will redo it that way — the reporter's underlying wish is the named workflow, and this PR only stops the command promising it.

Contract and boundary impact

  • Semantic owner and earliest changed stage: CLI selector descriptions (src/cli/coreBinaryCommands.ts) and authored docs. No schema, resolution or provider stage changed.
  • CLI and MCP/tool-catalog contract: no change to accepted inputs or outputs. --schema --json descriptions for xrefs change text only; the MCP tool contract for xrefs is untouched.
  • Provider, bridge, target-format, or platform compatibility: none — no provider or bridge code touched.
  • Evidence, artifact, provenance, or reconstruction contract: none.
  • Process execution, authorization, cleanup, or containment impact: none.
  • Generated metadata, package, or installation impact: none. npm run docs:check passes without regenerating anything; no build outputs committed.

Evidence and regression coverage

  • Tests added or updated:
    • tests/boundary/cli/xrefsSelectorHelp.test.ts (new): xrefs --help contains "Analyzed code or data address" and does not contain "symbol name"; the --address=<value> equals-form guidance is retained.
    • src/ghidra/GhidraFunctionValues.test.ts: pins the schema's address-only contract — _table_only is rejected with invalid_format on ["address"], while 0x100000598, 0X100000598, 100000598 and EXTERNAL:0x1 are accepted. This is the behaviour the issue observed, now asserted as deliberate.
  • Base reproduction or other evidence: with src/ and docs/ reverted on this branch, the help test fails — expected 'rea xrefs — List bounded references t…' to contain 'Analyzed code or data address' — and passes with the change. The issue's own run is the base reproduction for the rejection itself; I could not re-run it here (no Ghidra install or JDK on this machine), and nothing in this PR changes that code path.
  • User-visible CLI/MCP output:
    rea xrefs — List bounded references to an analyzed address
    
    Usage: rea xrefs <path> [address] [options]
    
    Arguments:
      path     App or program path
      address  Analyzed code or data address
    
    Options:
      --address <string>       Analyzed code or data address; use --address=<value> for leading dashes
    
  • Remaining proof gaps: no real-provider execution here, so the claim that the named selector still resolves nothing is taken from the schema and the tool contract rather than from a live Ghidra run. A maintainer with Ghidra can confirm in one command (rea xrefs ./c-arm64 _table_only --provider ghidra --json still exits 1, by design, with the help no longer inviting it).

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

Node v24.21.0 on Linux x64, at base cf41561.

  • npm ci — clean install.
  • npm run build:cached — success.
  • npm run check:fast — 3 tasks successful (typecheck, lint).
  • npm run format:check — all matched files correctly formatted (2114 files).
  • npm run verify:test-discovery — "Discovered all 657 test files exactly once."
  • npm run docs:check — 2 tasks successful; no generated document drift.
  • npm run test:fast — 322 files passed, 1 skipped; 3479 tests passed.
  • npm run test:boundary — 308 files passed, 2 failed; 2178 tests passed, 8 failed. Both failing files are pre-existing and environmental: tests/boundary/firmware/firmwareIntegration.test.ts and tests/boundary/mcp/firmwareMcp.test.ts fail because this host has Binwalk 26.6.4 while the admitted range is 3.1.x ("Unsupported tool version 26.6.4; accepted releases are Binwalk 3.1.x"). I confirmed the identical 7 failures in firmwareIntegration on clean cf41561 with my changes stashed.
  • npx vitest run --project adapters src/ghidra/GhidraFunctionValues.test.ts — 25 passed.
  • npx vitest run --project boundary tests/boundary/cli/xrefsSelectorHelp.test.ts — 2 passed.
  • Not run: real-Ghidra verification (npm run verify:ghidra) and the other real-provider workflows — no Ghidra install, JDK, Hopper or IDA on this machine. No provider code is touched by this PR.

Compatibility, safety, and release

  • Breaking changes or migration steps: none. No accepted input, output or exit code changes; only help text and documentation.
  • Real Hopper/Ghidra, browser, or OS coverage: unchanged and not exercised.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: not applicable — no process execution, no new inputs, no logged values.

Review checklist

  • This PR addresses a concrete problem or an agreed enhancement.
  • 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/1206 **Author:** [@xecanto](https://github.com/xecanto) **Created:** 10/9/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/1186-xrefs-address-selector-help` --- ### 📝 Commits (1) - [`c56eb8a`](https://github.com/morluto/rea/commit/c56eb8a81e6a5363a5970d9d508ac56897ce59a1) fix(cli): advertise an address, not a symbol name, on the xrefs selector ### 📊 Changes **4 files changed** (+90 additions, -3 deletions) <details> <summary>View changed files</summary> 📝 `docs/native-investigation.md` (+3 -1) 📝 `src/cli/coreBinaryCommands.ts` (+6 -2) 📝 `src/ghidra/GhidraFunctionValues.test.ts` (+33 -0) ➕ `tests/boundary/cli/xrefsSelectorHelp.test.ts` (+48 -0) </details> ### 📄 Description ## Summary Fixes #1186. `rea xrefs` described both of its selectors as "Address or symbol name", so the reported workflow — `rea xrefs ./c-arm64 _table_only --provider ghidra` — failed on the spelling the command's own help invited. The operation selects an analyzed address; this PR makes the help and the docs say so, and points at the paths that do resolve a name. ## Problem and expected behavior Smallest trigger: `rea xrefs --help` advertises "Address or symbol name" for the positional selector and `--address`, but a bare name is rejected in input validation before any provider resolution: ```json {"code":"invalid_request","details":{"operation":"xrefs","issues":[{"path":["address"],"reason":"invalid_format", "message":"Use hexadecimal digits, optionally prefixed with 0x, or an encoded address-space name followed by :0x and hexadecimal digits","expected":"regex"}]}} ``` The violated invariant is agreement between surfaces, and the evidence says the address-only side is the intended one: - `src/contracts/officialToolContracts.ts` → `xrefs`: "headless providers such as Ghidra require an explicit address." - `src/ghidra/GhidraFunctionValues.ts` → `xrefs: z.object({ document, address: ghidraInputAddressSchema })`, hexadecimal or `space:0x…` only. - The name workflow already exists as its own tool: `find_xrefs_to_name` ("Resolve an exact name against the bound provider's name inventory…"), composed from `list_names` + `xrefs` in `CapabilityInventory`. So the defect is the promise, not the validation: two selector descriptions in `src/cli/coreBinaryCommands.ts` and one sentence in `docs/native-investigation.md` ("`xrefs` accepts `--address=<name-or-address>`"). Expected behavior: the help and docs describe an analyzed address, and a caller holding a name is told where to resolve it. ## Change and scope - Both `xrefs` selector descriptions now read "Analyzed code or data address" (the `--address` one keeps its leading-dash guidance). - `docs/native-investigation.md` says `xrefs` accepts `--address=<address>`, that it is not a symbol name, and how to resolve one: `rea function <name>` or `rea search` on the CLI, `find_xrefs_to_name` over MCP. The neighbouring `--procedure=<name-or-address>` sentence is correct and untouched — those selectors do resolve names through `resolveProcedure`. Intentionally not included: teaching the `xrefs` selector to resolve names. That is the other way to close #1186, and it is a contract change rather than a correction — it would widen `ghidraInputAddressSchema` for one operation, add name resolution for an address-typed selector in `bridge/ghidra/ReaGhidraBridge.java`, overlap `find_xrefs_to_name`, and need updated verifiers and catalog artifacts. CONTRIBUTING asks for an issue before a change of that size, and I cannot run the real-Ghidra verification it would need. **If that is the direction you want, say so and I will redo it that way** — the reporter's underlying wish is the named workflow, and this PR only stops the command promising it. ## Contract and boundary impact - Semantic owner and earliest changed stage: CLI selector descriptions (`src/cli/coreBinaryCommands.ts`) and authored docs. No schema, resolution or provider stage changed. - CLI and MCP/tool-catalog contract: no change to accepted inputs or outputs. `--schema --json` descriptions for `xrefs` change text only; the MCP tool contract for `xrefs` is untouched. - Provider, bridge, target-format, or platform compatibility: none — no provider or bridge code touched. - Evidence, artifact, provenance, or reconstruction contract: none. - Process execution, authorization, cleanup, or containment impact: none. - Generated metadata, package, or installation impact: none. `npm run docs:check` passes without regenerating anything; no build outputs committed. ## Evidence and regression coverage - Tests added or updated: - `tests/boundary/cli/xrefsSelectorHelp.test.ts` (new): `xrefs --help` contains "Analyzed code or data address" and does **not** contain "symbol name"; the `--address=<value>` equals-form guidance is retained. - `src/ghidra/GhidraFunctionValues.test.ts`: pins the schema's address-only contract — `_table_only` is rejected with `invalid_format` on `["address"]`, while `0x100000598`, `0X100000598`, `100000598` and `EXTERNAL:0x1` are accepted. This is the behaviour the issue observed, now asserted as deliberate. - Base reproduction or other evidence: with `src/` and `docs/` reverted on this branch, the help test fails — `expected 'rea xrefs — List bounded references t…' to contain 'Analyzed code or data address'` — and passes with the change. The issue's own run is the base reproduction for the rejection itself; I could not re-run it here (no Ghidra install or JDK on this machine), and nothing in this PR changes that code path. - User-visible CLI/MCP output: ``` rea xrefs — List bounded references to an analyzed address Usage: rea xrefs <path> [address] [options] Arguments: path App or program path address Analyzed code or data address Options: --address <string> Analyzed code or data address; use --address=<value> for leading dashes ``` - Remaining proof gaps: no real-provider execution here, so the claim that the named selector still resolves nothing is taken from the schema and the tool contract rather than from a live Ghidra run. A maintainer with Ghidra can confirm in one command (`rea xrefs ./c-arm64 _table_only --provider ghidra --json` still exits 1, by design, with the help no longer inviting it). 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 Node v24.21.0 on Linux x64, at base `cf41561`. - `npm ci` — clean install. - `npm run build:cached` — success. - `npm run check:fast` — 3 tasks successful (typecheck, lint). - `npm run format:check` — all matched files correctly formatted (2114 files). - `npm run verify:test-discovery` — "Discovered all 657 test files exactly once." - `npm run docs:check` — 2 tasks successful; no generated document drift. - `npm run test:fast` — 322 files passed, 1 skipped; 3479 tests passed. - `npm run test:boundary` — 308 files passed, 2 failed; 2178 tests passed, 8 failed. **Both failing files are pre-existing and environmental**: `tests/boundary/firmware/firmwareIntegration.test.ts` and `tests/boundary/mcp/firmwareMcp.test.ts` fail because this host has Binwalk 26.6.4 while the admitted range is 3.1.x ("Unsupported tool version 26.6.4; accepted releases are Binwalk 3.1.x"). I confirmed the identical 7 failures in `firmwareIntegration` on clean `cf41561` with my changes stashed. - `npx vitest run --project adapters src/ghidra/GhidraFunctionValues.test.ts` — 25 passed. - `npx vitest run --project boundary tests/boundary/cli/xrefsSelectorHelp.test.ts` — 2 passed. - Not run: real-Ghidra verification (`npm run verify:ghidra`) and the other real-provider workflows — no Ghidra install, JDK, Hopper or IDA on this machine. No provider code is touched by this PR. ## Compatibility, safety, and release - Breaking changes or migration steps: none. No accepted input, output or exit code changes; only help text and documentation. - Real Hopper/Ghidra, browser, or OS coverage: unchanged and not exercised. - Package or release metadata impact: none. - Security, privacy, process, or containment review: not applicable — no process execution, no new inputs, no logged values. ## Review checklist - [x] This PR addresses a concrete problem or an agreed enhancement. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked, or the reason for not linking one is stated above. - [x] Tests cover changed observable behavior and meaningful failure paths. - [x] Owning docs, contracts, and generated metadata are updated where needed. - [x] User-visible CLI/MCP changes include representative output. - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-17 21:09:27 +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#2719
No description provided.