[GH-ISSUE #8403] [Bug] Unbound session reports stale provider readiness after repair #6588

Open
opened 2026-11-01 21:12:28 +00:00 by bsakaguchi · 3 comments
Owner

Originally created by @morluto on GitHub (Nov 1, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/8403

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

An open, unbound binary session continues to report a deep provider as unavailable after its configured executable becomes available. A fresh rea doctor --provider kuna --json reports Kuna available, but binary_session and a direct provider operation still report the selection-time failure until the caller reopens the target.

Reproduction

On main 6e9ee97a69cb16c7150d8b550e705cba055ee4f0, with REA_KUNA_COMMAND set to a nonexistent path inside a disposable test directory and other deep providers deliberately unavailable:

  1. Open an owned thin Mach-O with open_binary and inspect binary_session. The session opens with analysis_provider_binding: null; the Kuna candidate says unavailable, executable_missing.
  2. Create a symlink at that configured path to the already installed and verified Kuna 1.986 executable. A fresh rea doctor --provider kuna --json reports that selected provider available and healthy.
  3. Call binary_session with both default summary and complete detail: the Kuna candidate still says executable_missing. procedure_address continues to return provider_unavailable with the old selection rejection.
  4. Call open_binary on the same path with provider_id: "kuna". The new binding is Kuna 1.986, its candidate says available and selected, and procedure_address("_evaluate") succeeds. The controlled symlink is then removed.

Observed on the main revision and on draft #8400 ea357ddf0; the latter did not change this behavior. All successful MCP calls used the SDK with fetched compact output schemas.

Expected behavior

The agent should be able to distinguish historical provider-selection observations from fresh readiness and discover the explicit re-selection/reopen step after repairing a provider. Whether discovery should refresh separately or label selection-time facts needs a design decision. Preserve the active binding and target until the caller explicitly changes them; do not silently switch providers or discard session state.

Impact and scope

An agent following provider setup guidance can see the repaired provider still reported missing and retry the same failing operation without guidance to reopen. The explicit reopen worked for this deliberately created missing-path scenario. This is not a claim about real agent behavior, all failure types, bound sessions, or all providers.

REA version

Source commit 6e9ee97a69cb16c7150d8b550e705cba055ee4f0; also observed on #8400 ea357ddf0.

Runtime and platform

Node 24.22.1, SDK 2.3.1, macOS arm64, Kuna 1.986.

Target and artifact context

Self-built arm64 Mach-O, SHA-256 ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d; statically analyzed, hash unchanged, not executed.

Interface

MCP

Earliest failure stage

Transport or result projection

Relevant output or evidence

After creating the symlink: doctor scope providers: ["kuna"], healthy: true, Kuna inspection available: true, version 1.986; the same MCP session's summary and complete candidate still had availability.status: "unavailable" and code: "executable_missing". A fresh explicit reopen returned a selected Kuna binding and procedure_address returned 0x100000430. Doctor overall environment_healthy was false because the control deliberately left other integrations unavailable.

Typed outcome or recovery expected

Expose the selection observation's freshness and a safe explicit open_binary retry or other owner-defined refresh path. Continue to distinguish target support, installation readiness, and active provider binding.

Analysis or suspected cause

Source-derived: SessionProviderRouter.candidateStatuses returns route.selection.candidates when a selection exists, while unboundOperationError uses the retained route selection. The documented binary_session.analysis_provider_candidates is called authoritative for deep-engine discovery, but these results do not identify their selection-time freshness. This explains the observed stale result; it does not establish the right refresh design.

Additional context

Related #8402 concerns pointing tool-level recovery to candidate selection reasons. That handoff also needs freshness and explicit reopen semantics; it is a distinct issue from generic remediation. Last known good: NOT_ENOUGH_INFO. Proposed additional controls: readiness loss after a provider was selected, Ghidra and other providers, target-free sessions, cancellation and retained edits during re-selection, and MCP full-schema profile.

Bound-session readiness loss control

On main 60c0cf977 and separately on draft #8485, I selected verified Kuna 1.986 through a disposable symlink and successfully resolved a function. After removing the symlink, the bound session's binary_session continued to report the Kuna candidate as available, both before and after a new procedure_assembly failed. A fresh scoped doctor reported that the selected executable was missing. The assembly failure correctly said the admitted command no longer resolved to its executable and advised resolving the failure and reopening the target. Restoring the symlink and explicitly reopening the same target made the lookup work again.

The selected binding's new release-verification fact in #8485 remained its explicitly described selection-time fact; it did not claim to recheck the executable. This control separately demonstrates that candidate availability is also selection-time in a bound session, including after an operation detects a changed executable. It does not establish a need to disrupt or replace a working provider automatically. The owned static fixture and installed Kuna executable hashes remained unchanged; the fixture was not executed. Successful compact MCP replies used advertised-schema validation; error payloads were inspected rather than independently schema-validated. One host, selected path and operation were tested.

Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0.

Originally created by @morluto on GitHub (Nov 1, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8403 ### 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 An open, unbound binary session continues to report a deep provider as unavailable after its configured executable becomes available. A fresh `rea doctor --provider kuna --json` reports Kuna available, but `binary_session` and a direct provider operation still report the selection-time failure until the caller reopens the target. ### Reproduction On main `6e9ee97a69cb16c7150d8b550e705cba055ee4f0`, with `REA_KUNA_COMMAND` set to a nonexistent path inside a disposable test directory and other deep providers deliberately unavailable: 1. Open an owned thin Mach-O with `open_binary` and inspect `binary_session`. The session opens with `analysis_provider_binding: null`; the Kuna candidate says `unavailable`, `executable_missing`. 2. Create a symlink at that configured path to the already installed and verified Kuna 1.986 executable. A fresh `rea doctor --provider kuna --json` reports that selected provider available and healthy. 3. Call `binary_session` with both default summary and complete detail: the Kuna candidate still says `executable_missing`. `procedure_address` continues to return `provider_unavailable` with the old selection rejection. 4. Call `open_binary` on the same path with `provider_id: "kuna"`. The new binding is Kuna 1.986, its candidate says available and selected, and `procedure_address("_evaluate")` succeeds. The controlled symlink is then removed. Observed on the main revision and on draft #8400 `ea357ddf0`; the latter did not change this behavior. All successful MCP calls used the SDK with fetched compact output schemas. ### Expected behavior The agent should be able to distinguish historical provider-selection observations from fresh readiness and discover the explicit re-selection/reopen step after repairing a provider. Whether discovery should refresh separately or label selection-time facts needs a design decision. Preserve the active binding and target until the caller explicitly changes them; do not silently switch providers or discard session state. ### Impact and scope An agent following provider setup guidance can see the repaired provider still reported missing and retry the same failing operation without guidance to reopen. The explicit reopen worked for this deliberately created missing-path scenario. This is not a claim about real agent behavior, all failure types, bound sessions, or all providers. ### REA version Source commit `6e9ee97a69cb16c7150d8b550e705cba055ee4f0`; also observed on #8400 `ea357ddf0`. ### Runtime and platform Node 24.22.1, SDK 2.3.1, macOS arm64, Kuna 1.986. ### Target and artifact context Self-built arm64 Mach-O, SHA-256 `ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d`; statically analyzed, hash unchanged, not executed. ### Interface MCP ### Earliest failure stage Transport or result projection ### Relevant output or evidence After creating the symlink: doctor scope `providers: ["kuna"]`, `healthy: true`, Kuna inspection `available: true`, version `1.986`; the same MCP session's summary and complete candidate still had `availability.status: "unavailable"` and `code: "executable_missing"`. A fresh explicit reopen returned a selected Kuna binding and `procedure_address` returned `0x100000430`. Doctor overall `environment_healthy` was false because the control deliberately left other integrations unavailable. ### Typed outcome or recovery expected Expose the selection observation's freshness and a safe explicit `open_binary` retry or other owner-defined refresh path. Continue to distinguish target support, installation readiness, and active provider binding. ### Analysis or suspected cause Source-derived: [`SessionProviderRouter.candidateStatuses`](https://github.com/morluto/rea/blob/6e9ee97a69cb16c7150d8b550e705cba055ee4f0/src/application/binary/SessionProviderRouter.ts) returns `route.selection.candidates` when a selection exists, while [`unboundOperationError`](https://github.com/morluto/rea/blob/6e9ee97a69cb16c7150d8b550e705cba055ee4f0/src/application/binary/SessionProviderRouter.ts) uses the retained route selection. The documented `binary_session.analysis_provider_candidates` is called authoritative for deep-engine discovery, but these results do not identify their selection-time freshness. This explains the observed stale result; it does not establish the right refresh design. ### Additional context Related #8402 concerns pointing tool-level recovery to candidate selection reasons. That handoff also needs freshness and explicit reopen semantics; it is a distinct issue from generic remediation. Last known good: NOT_ENOUGH_INFO. Proposed additional controls: readiness loss after a provider was selected, Ghidra and other providers, target-free sessions, cancellation and retained edits during re-selection, and MCP full-schema profile. ### Bound-session readiness loss control On main `60c0cf977` and separately on draft #8485, I selected verified Kuna 1.986 through a disposable symlink and successfully resolved a function. After removing the symlink, the bound session's `binary_session` continued to report the Kuna candidate as available, both before and after a new `procedure_assembly` failed. A fresh scoped doctor reported that the selected executable was missing. The assembly failure correctly said the admitted command no longer resolved to its executable and advised resolving the failure and reopening the target. Restoring the symlink and explicitly reopening the same target made the lookup work again. The selected binding's new release-verification fact in #8485 remained its explicitly described selection-time fact; it did not claim to recheck the executable. This control separately demonstrates that candidate availability is also selection-time in a **bound** session, including after an operation detects a changed executable. It does not establish a need to disrupt or replace a working provider automatically. The owned static fixture and installed Kuna executable hashes remained unchanged; the fixture was not executed. Successful compact MCP replies used advertised-schema validation; error payloads were inspected rather than independently schema-validated. One host, selected path and operation were tested. Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0.
Author
Owner

@morluto commented on GitHub (Nov 1, 2026):

Bound-provider controls

On the same clean main revision, I tested the reverse transition with caller-owned temporary symlinks and the same unexecuted Mach-O. These controls change the configured paths, not the installed providers.

  • Kuna 1.986: Opened the target with an explicit Kuna binding, then removed the temporary configured symlink. A fresh Kuna-scoped doctor check reported unavailable, while the session's candidate and procedure_address initially still advertised available. Calling list_strings and procedure_address returned capability_unavailable with the missing-path reason. After restoring the symlink, the candidate remained available but the previously failed operations were now advertised provider_unavailable and still returned the retained failure. Explicitly reopening the same target with provider_id: "kuna" restored operation availability, and procedure_address("_evaluate") succeeded. A subsequent close and fresh open also succeeded. The error's recovery text identified the missing configuration path but did not say to reopen after repair.
  • Ghidra 12.1.4: Opened the target with an explicit Ghidra binding and successfully resolved a procedure, then removed a temporary symlink to its installation directory. A fresh Ghidra-scoped doctor check reported unavailable, while the existing session continued to advertise availability and successfully returned a different procedure address and its assembly. Restoring the symlink and explicitly reopening also succeeded. This test had already started the bridge; it does not establish that a new Ghidra process can start without the installation path or that every existing operation would succeed.

The target digest was unchanged, and close succeeded for each test. Successful calls were checked against the SDK's fetched compact schemas. These observations support reporting selection-time candidates, current installation readiness, actual route/operation health, and the explicit recovery action as distinct facts. They do not justify marking an already running Ghidra route unavailable solely because a fresh installation check fails, nor do they establish behavior for other providers, edits, cancellation, or hosts.

<!-- gh-comment-id:6551080902 --> @morluto commented on GitHub (Nov 1, 2026): ### Bound-provider controls On the same clean main revision, I tested the reverse transition with caller-owned temporary symlinks and the same unexecuted Mach-O. These controls change the configured paths, not the installed providers. - **Kuna 1.986:** Opened the target with an explicit Kuna binding, then removed the temporary configured symlink. A fresh Kuna-scoped doctor check reported unavailable, while the session's candidate and `procedure_address` initially still advertised available. Calling `list_strings` and `procedure_address` returned `capability_unavailable` with the missing-path reason. After restoring the symlink, the candidate remained available but the previously failed operations were now advertised `provider_unavailable` and still returned the retained failure. Explicitly reopening the same target with `provider_id: "kuna"` restored operation availability, and `procedure_address("_evaluate")` succeeded. A subsequent close and fresh open also succeeded. The error's recovery text identified the missing configuration path but did not say to reopen after repair. - **Ghidra 12.1.4:** Opened the target with an explicit Ghidra binding and successfully resolved a procedure, then removed a temporary symlink to its installation directory. A fresh Ghidra-scoped doctor check reported unavailable, while the existing session continued to advertise availability and successfully returned a different procedure address and its assembly. Restoring the symlink and explicitly reopening also succeeded. This test had already started the bridge; it does not establish that a new Ghidra process can start without the installation path or that every existing operation would succeed. The target digest was unchanged, and close succeeded for each test. Successful calls were checked against the SDK's fetched compact schemas. These observations support reporting selection-time candidates, current installation readiness, actual route/operation health, and the explicit recovery action as distinct facts. They do not justify marking an already running Ghidra route unavailable solely because a fresh installation check fails, nor do they establish behavior for other providers, edits, cancellation, or hosts.
Author
Owner

@morluto commented on GitHub (Nov 1, 2026):

Same-profile Ghidra reopen with an ephemeral edit

I extended the Ghidra symlink control on clean main 6e9ee97a with Ghidra 12.1.4 / SDK 2.3.1 MCP on macOS arm64. After opening the owned Mach-O, I renamed _evaluate to audit_readiness_edit using annotate_native_function and resolved the new name. With the temporary installation-path symlink removed, a fresh doctor check reported Ghidra unavailable, but the active session still resolved the renamed function and served another procedure's assembly. After restoring that same symlink, explicitly reopening the same target with provider_id: "ghidra" retained the renamed lookup at 0x100000430; the filtered Evidence bundle summary still listed the original annotation Evidence ID. The target SHA-256 was unchanged and close succeeded.

This is a same-target, same-provider, same-profile control, not proof that switching provider, starting a replacement database, cancelling a transition, or recovering from a dead bridge preserves edits. It supports keeping a healthy running route independent of a fresh installation check and preserving the existing same-profile reopen semantics. Successful MCP calls used fetched compact-profile output schemas.

An initial probe tried inspect_analysis_view on the annotation record and correctly received unsupported_target because that parent operation does not support views. The successful follow-up used the supported filtered Evidence bundle summary; it does not imply that annotation Evidence recreates the live database. Related: #8289.

<!-- gh-comment-id:6551091873 --> @morluto commented on GitHub (Nov 1, 2026): ### Same-profile Ghidra reopen with an ephemeral edit I extended the Ghidra symlink control on clean main `6e9ee97a` with Ghidra 12.1.4 / SDK 2.3.1 MCP on macOS arm64. After opening the owned Mach-O, I renamed `_evaluate` to `audit_readiness_edit` using `annotate_native_function` and resolved the new name. With the temporary installation-path symlink removed, a fresh doctor check reported Ghidra unavailable, but the active session still resolved the renamed function and served another procedure's assembly. After restoring that same symlink, explicitly reopening the same target with `provider_id: "ghidra"` retained the renamed lookup at `0x100000430`; the filtered Evidence bundle summary still listed the original annotation Evidence ID. The target SHA-256 was unchanged and close succeeded. This is a same-target, same-provider, same-profile control, not proof that switching provider, starting a replacement database, cancelling a transition, or recovering from a dead bridge preserves edits. It supports keeping a healthy running route independent of a fresh installation check and preserving the existing same-profile reopen semantics. Successful MCP calls used fetched compact-profile output schemas. An initial probe tried `inspect_analysis_view` on the annotation record and correctly received `unsupported_target` because that parent operation does not support views. The successful follow-up used the supported filtered Evidence bundle summary; it does not imply that annotation Evidence recreates the live database. Related: #8289.
Author
Owner

@morluto commented on GitHub (Nov 1, 2026):

Related active-route finding: #8404 documents a Ghidra startup failure whose provider-wide unavailable state persists per operation after the path is repaired. In that control, unlike the Kuna failure above, retrying each tested operation succeeded without reopening, but discovery kept the other operations unavailable until their own successful retries. The report separates that runtime failure from the selection-time candidate facts discussed here.

<!-- gh-comment-id:6551105453 --> @morluto commented on GitHub (Nov 1, 2026): Related active-route finding: #8404 documents a Ghidra startup failure whose provider-wide unavailable state persists per operation after the path is repaired. In that control, unlike the Kuna failure above, retrying each tested operation succeeded without reopening, but discovery kept the other operations unavailable until their own successful retries. The report separates that runtime failure from the selection-time candidate facts discussed here.
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#6588
No description provided.