[GH-ISSUE #5729] [Bug] Navigation discovery recommends provider configuration before a target is open #3475

Closed
opened 2026-10-31 00:40:54 +00:00 by bsakaguchi · 2 comments
Owner

Originally created by @coygeek on GitHub (Oct 21, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5729

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Provider or capability discovery

Observed behavior

Before any target is open, MCP binary_session {} reports get_navigation_context unavailable with reason:"provider_missing" and tells the caller to configure provider operations. An immediate get_navigation_context {} call in the same connection instead returns target_unavailable and directs the caller to open_binary. Discovery gives a different recovery action from the tool's actual missing prerequisite. The sibling controls get_call_graph and trace_call_path both report target_required.

Reproduction

From a built source checkout with locked dependencies installed, run the following. This exact sequence was independently verified at the baseline below and replayed against freshly built current main; both reproduced the no-target mismatch. The main replay changed only the disposable working-directory location. No target fixture, external API, or GUI is required.

work_dir="$(mktemp -d)"
mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" "$work_dir/cache" "$work_dir/state" "$work_dir/tmp"
cat > "$work_dir/probe.py" <<'PYTHON'
import json, os, select, subprocess
from pathlib import Path

work = Path(os.environ['HOME']).parent
log = (work / 'server-stderr.txt').open('w')
p = subprocess.Popen(['node', 'scripts/rea.mjs', 'mcp'],
                     stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                     stderr=log, text=True)

def send(message):
    p.stdin.write(json.dumps(message) + '\n')
    p.stdin.flush()

def request(number, method, params):
    send({'jsonrpc': '2.0', 'id': number, 'method': method, 'params': params})
    while True:
        if not select.select([p.stdout], [], [], 30)[0]:
            raise RuntimeError('MCP response timeout')
        line = p.stdout.readline()
        if not line:
            raise RuntimeError('MCP server ended before response')
        message = json.loads(line)
        if message.get('id') == number:
            return message

def call(number, name):
    reply = request(number, 'tools/call', {'name': name, 'arguments': {}})['result']
    return (reply.get('structuredContent', {}).get('result')
            or json.loads(reply['content'][0]['text']))

try:
    request(1, 'initialize', {
        'protocolVersion': '2025-11-25', 'capabilities': {},
        'clientInfo': {'name': 'navigation-repro', 'version': '1'}})
    send({'jsonrpc': '2.0', 'method': 'notifications/initialized'})
    session = call(2, 'binary_session')
    print(json.dumps({'open': session['open']}))
    for group in session['tool_availability']['groups']:
        names = [name for name in group['names'] if name in
                 ('get_navigation_context', 'get_call_graph', 'trace_call_path')]
        if names:
            print(json.dumps({'names': names, 'available': group['available'],
                              'reason': group['reason'],
                              'remediation': group['remediation']}))
    print(json.dumps({'navigation_call': call(3, 'get_navigation_context')}))
finally:
    p.stdin.close()
    try:
        p.wait(timeout=20)
    except subprocess.TimeoutExpired:
        p.terminate()
        p.wait(timeout=10)
    log.close()
PYTHON
env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \
  XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \
  XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent \
  python3 "$work_dir/probe.py"

Expected behavior

With open:false, navigation should remain unavailable and identify the missing target with reason:"target_required" and target-opening guidance consistent with its immediate invocation error. Preserve the documented navigation mode information and genuine provider restrictions.

The discovery contract says this inventory supplies current target/provider/host/client facts used to choose operations. It does not specify universal precedence for simultaneous failures. Here, the earlier missing-target prerequisite is established by the actual invocation and the target guard, with the two sibling controls agreeing.

Impact and scope

P2: machine-readable discovery sends callers toward provider configuration when the immediate prerequisite is opening a target. This is a bounded recovery defect in the discovery-first workflow; direct invocation still provides usable open_binary recovery guidance. No data loss or security boundary crossing was observed. Downstream client operation-selection behavior, other hosts, and successful real-provider navigation were not measured.

REA version

rea-agents 6.7.0; verified baseline 9d8e7803326a382cbbb3ffdb900f5e93e5442d68. Rechecked after npm run build:cached on current main d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f: still reproduces. The dependency lockfile is unchanged between these revisions.

Runtime and platform

Node.js v26.12.0; macOS 27.0.1; arm64. Production MCP stdio entry point, isolated HOME/XDG/TMPDIR, REA_LOG_LEVEL=silent. No deep-analysis engine or GUI was started.

Target and artifact context

No active target, target fixture, or configured analysis provider is needed. This report concerns the fresh no-target state only.

Interface

MCP

Earliest failure stage

Transport or result projection

Relevant output or evidence

Observed on the freshly built main replay, with unrelated inventory metadata omitted:

{"open":false}
{"names":["get_navigation_context"],"available":false,"reason":"provider_missing","remediation":"Configure a provider for one of: current_document, current_address, resolve_containing_procedure."}
{"names":["get_call_graph"],"available":false,"reason":"target_required","remediation":"Call open_binary with a supported local target."}
{"names":["trace_call_path"],"available":false,"reason":"target_required","remediation":"Call open_binary with a supported local target."}

The next navigation call returns:

{"error":{"code":"target_unavailable","category":"unavailable","message":"No app is open. Ask the user which app to investigate, then call open_binary with its local path.","retryable":false,"remediation":{"action":"No app is open. Ask the user which app to investigate, then call open_binary with its local path."}}}

Evidence provenance: observed. Local verification: independently reproduced. Reproduction completeness: complete for the fresh-session discovery/invocation mismatch. The replay exited 0.

Typed outcome or recovery expected

Repeat the isolated sequence: navigation must remain unavailable, report target_required, and provide target-opening guidance. Keep both sibling controls unavailable with their existing target-required recovery. Preserve current-selection/explicit-document mode facts; merely advertising navigation as available would not restore this contract. These are proposed restoration checks; no patch was tested.

Analysis or suspected cause

Source-derived reasoning: CapabilityInventory.ts:350-379 evaluates navigation's provider-mode composition before target availability. Its active-target kinds and no-target gate also exclude this tool's session surface, so moving the branch alone would not establish target gating. Actual navigation dispatch reaches the target prerequisite through registerSessionTools.ts:234-253 and BinarySessionExecution.ts:66. This agrees with the observed missing-target invocation error; it is not a tested fix.

Additional context

Prepared with AI assistance and independently verified. Related #1166 concerns target-dependent inspection tools falsely advertised available; navigation is already unavailable and needs its reason/remediation corrected. #5447 concerns the opposite target gate error for independent session tools. #4687 and #5068 concern traversal-mode composition with an open target; both controls now correctly report target_required here. #5711 concerns unsupported-host pcap discovery. Their restoration checks can pass while this navigation recovery mismatch persists.

NOT_ENOUGH_INFO: last known good revision, first affected revision, successful native-provider navigation, and downstream client occurrence frequency were not established.

Originally created by @coygeek on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5729 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Provider or capability discovery ### Observed behavior Before any target is open, MCP `binary_session {}` reports `get_navigation_context` unavailable with `reason:"provider_missing"` and tells the caller to configure provider operations. An immediate `get_navigation_context {}` call in the same connection instead returns `target_unavailable` and directs the caller to `open_binary`. Discovery gives a different recovery action from the tool's actual missing prerequisite. The sibling controls `get_call_graph` and `trace_call_path` both report `target_required`. ### Reproduction From a built source checkout with locked dependencies installed, run the following. This exact sequence was independently verified at the baseline below and replayed against freshly built current main; both reproduced the no-target mismatch. The main replay changed only the disposable working-directory location. No target fixture, external API, or GUI is required. ```sh work_dir="$(mktemp -d)" mkdir -p "$work_dir/home" "$work_dir/cfg" "$work_dir/data" "$work_dir/cache" "$work_dir/state" "$work_dir/tmp" cat > "$work_dir/probe.py" <<'PYTHON' import json, os, select, subprocess from pathlib import Path work = Path(os.environ['HOME']).parent log = (work / 'server-stderr.txt').open('w') p = subprocess.Popen(['node', 'scripts/rea.mjs', 'mcp'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=log, text=True) def send(message): p.stdin.write(json.dumps(message) + '\n') p.stdin.flush() def request(number, method, params): send({'jsonrpc': '2.0', 'id': number, 'method': method, 'params': params}) while True: if not select.select([p.stdout], [], [], 30)[0]: raise RuntimeError('MCP response timeout') line = p.stdout.readline() if not line: raise RuntimeError('MCP server ended before response') message = json.loads(line) if message.get('id') == number: return message def call(number, name): reply = request(number, 'tools/call', {'name': name, 'arguments': {}})['result'] return (reply.get('structuredContent', {}).get('result') or json.loads(reply['content'][0]['text'])) try: request(1, 'initialize', { 'protocolVersion': '2025-11-25', 'capabilities': {}, 'clientInfo': {'name': 'navigation-repro', 'version': '1'}}) send({'jsonrpc': '2.0', 'method': 'notifications/initialized'}) session = call(2, 'binary_session') print(json.dumps({'open': session['open']})) for group in session['tool_availability']['groups']: names = [name for name in group['names'] if name in ('get_navigation_context', 'get_call_graph', 'trace_call_path')] if names: print(json.dumps({'names': names, 'available': group['available'], 'reason': group['reason'], 'remediation': group['remediation']})) print(json.dumps({'navigation_call': call(3, 'get_navigation_context')})) finally: p.stdin.close() try: p.wait(timeout=20) except subprocess.TimeoutExpired: p.terminate() p.wait(timeout=10) log.close() PYTHON env -i PATH="$PATH" HOME="$work_dir/home" XDG_CONFIG_HOME="$work_dir/cfg" \ XDG_DATA_HOME="$work_dir/data" XDG_CACHE_HOME="$work_dir/cache" \ XDG_STATE_HOME="$work_dir/state" TMPDIR="$work_dir/tmp" REA_LOG_LEVEL=silent \ python3 "$work_dir/probe.py" ``` ### Expected behavior With `open:false`, navigation should remain unavailable and identify the missing target with `reason:"target_required"` and target-opening guidance consistent with its immediate invocation error. Preserve the documented navigation mode information and genuine provider restrictions. The [discovery contract](https://github.com/morluto/rea/blob/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f/docs/mcp-contracts.md#L470-L480) says this inventory supplies current target/provider/host/client facts used to choose operations. It does not specify universal precedence for simultaneous failures. Here, the earlier missing-target prerequisite is established by the actual invocation and the target guard, with the two sibling controls agreeing. ### Impact and scope P2: machine-readable discovery sends callers toward provider configuration when the immediate prerequisite is opening a target. This is a bounded recovery defect in the discovery-first workflow; direct invocation still provides usable `open_binary` recovery guidance. No data loss or security boundary crossing was observed. Downstream client operation-selection behavior, other hosts, and successful real-provider navigation were not measured. ### REA version `rea-agents` 6.7.0; verified baseline `9d8e7803326a382cbbb3ffdb900f5e93e5442d68`. Rechecked after `npm run build:cached` on current main `d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f`: still reproduces. The dependency lockfile is unchanged between these revisions. ### Runtime and platform Node.js v26.12.0; macOS 27.0.1; arm64. Production MCP stdio entry point, isolated HOME/XDG/TMPDIR, `REA_LOG_LEVEL=silent`. No deep-analysis engine or GUI was started. ### Target and artifact context No active target, target fixture, or configured analysis provider is needed. This report concerns the fresh no-target state only. ### Interface MCP ### Earliest failure stage Transport or result projection ### Relevant output or evidence Observed on the freshly built main replay, with unrelated inventory metadata omitted: ```json {"open":false} {"names":["get_navigation_context"],"available":false,"reason":"provider_missing","remediation":"Configure a provider for one of: current_document, current_address, resolve_containing_procedure."} {"names":["get_call_graph"],"available":false,"reason":"target_required","remediation":"Call open_binary with a supported local target."} {"names":["trace_call_path"],"available":false,"reason":"target_required","remediation":"Call open_binary with a supported local target."} ``` The next navigation call returns: ```json {"error":{"code":"target_unavailable","category":"unavailable","message":"No app is open. Ask the user which app to investigate, then call open_binary with its local path.","retryable":false,"remediation":{"action":"No app is open. Ask the user which app to investigate, then call open_binary with its local path."}}} ``` Evidence provenance: observed. Local verification: independently reproduced. Reproduction completeness: complete for the fresh-session discovery/invocation mismatch. The replay exited 0. ### Typed outcome or recovery expected Repeat the isolated sequence: navigation must remain unavailable, report `target_required`, and provide target-opening guidance. Keep both sibling controls unavailable with their existing target-required recovery. Preserve current-selection/explicit-document mode facts; merely advertising navigation as available would not restore this contract. These are proposed restoration checks; no patch was tested. ### Analysis or suspected cause Source-derived reasoning: [CapabilityInventory.ts:350-379](https://github.com/morluto/rea/blob/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f/src/application/CapabilityInventory.ts#L350-L379) evaluates navigation's provider-mode composition before target availability. Its [active-target kinds](https://github.com/morluto/rea/blob/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f/src/application/CapabilityInventory.ts#L195-L201) and [no-target gate](https://github.com/morluto/rea/blob/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f/src/application/CapabilityInventory.ts#L682-L699) also exclude this tool's `session` surface, so moving the branch alone would not establish target gating. Actual navigation dispatch reaches the target prerequisite through [registerSessionTools.ts:234-253](https://github.com/morluto/rea/blob/d0067ba34a39ea47dd7e11bb2e6169bc0938cc3f/src/server/registerSessionTools.ts#L234-L253) and `BinarySessionExecution.ts:66`. This agrees with the observed missing-target invocation error; it is not a tested fix. ### Additional context Prepared with AI assistance and independently verified. Related #1166 concerns target-dependent inspection tools falsely advertised available; navigation is already unavailable and needs its reason/remediation corrected. #5447 concerns the opposite target gate error for independent session tools. #4687 and #5068 concern traversal-mode composition with an open target; both controls now correctly report `target_required` here. #5711 concerns unsupported-host pcap discovery. Their restoration checks can pass while this navigation recovery mismatch persists. NOT_ENOUGH_INFO: last known good revision, first affected revision, successful native-provider navigation, and downstream client occurrence frequency were not established.
Author
Owner

@XinwangTao commented on GitHub (Oct 21, 2026):

Confirmed inconsistency — discovery says "configure provider" while the immediate call says "open a binary first", and the sibling tools correctly report target_required. The recovery action in discovery should match the tool's actual missing prerequisite: when no target is open, the no-target gate (target_required / open_binary) must take precedence over any provider-configuration hint. Recommending provider setup for a tool that cannot run until a target exists is misleading for any client that acts on discovery hints directly.

<!-- gh-comment-id:6311466103 --> @XinwangTao commented on GitHub (Oct 21, 2026): Confirmed inconsistency — discovery says "configure provider" while the immediate call says "open a binary first", and the sibling tools correctly report target_required. The recovery action in discovery should match the tool's actual missing prerequisite: when no target is open, the no-target gate (target_required / open_binary) must take precedence over any provider-configuration hint. Recommending provider setup for a tool that cannot run until a target exists is misleading for any client that acts on discovery hints directly.
Author
Owner

@coygeek commented on GitHub (Oct 24, 2026):

Checked the reported fix on main at d87e73f2db.

get_navigation_context explicitly requires an active target. Its inventory branch retains provider-mode facts but overlays targetAvailability, whose no-target decision is target_required with open_binary remediation. The regression asserts unavailable/target_required and both unavailable modes in a fresh no-target status; open-target tests retain explicit-document mode behavior and genuine provider/host restrictions.

Implementation: sessionToolContracts.ts, CapabilityInventory.ts.

The relevant regression checks in CapabilityInventory.test.ts passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.

<!-- gh-comment-id:6380703528 --> @coygeek commented on GitHub (Oct 24, 2026): Checked the reported fix on `main` at d87e73f2db50be72d33a4b3c7199af35518b441c. get_navigation_context explicitly requires an active target. Its inventory branch retains provider-mode facts but overlays targetAvailability, whose no-target decision is target_required with open_binary remediation. The regression asserts unavailable/target_required and both unavailable modes in a fresh no-target status; open-target tests retain explicit-document mode behavior and genuine provider/host restrictions. Implementation: [sessionToolContracts.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/contracts/sessionToolContracts.ts#L171), [CapabilityInventory.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/application/CapabilityInventory.ts#L387). The relevant regression checks in [CapabilityInventory.test.ts](https://github.com/morluto/rea/blob/d87e73f2db50be72d33a4b3c7199af35518b441c/src/application/CapabilityInventory.test.ts) passed in the focused test run on this revision. This closure is based on the current source and those checks; provider fixtures do not establish a real-engine run. Closing as completed on main.
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#3475
No description provided.