[GH-ISSUE #8362] [Bug] Kuna call paths can report complete negative despite omitted direct calls #6563

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

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

Before submitting

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

Area

Native analysis or decompilation

Observed behavior

On the fixture below, trace_call_path with verified Kuna 1.986 reports goal_status: not_reached, complete relationship coverage at both visited nodes, no failures, and no residual unknowns for _main → _goal. But the binary contains two direct call instructions _main → _middle → _goal. REA itself reports the first edge and an xref to _middle; direct Kuna disassembly decodes the second. Ghidra reports the two-edge static path as reached. This is a static evidence discrepancy, not a claim that the target was executed.

Reproduction

On macOS arm64, assemble the following and link with clang -arch arm64 -Wl,-e,_main fixture.s -o fixture:

.section __TEXT,__text,regular,pure_instructions
.p2align 2
.globl _main
_main: bl _middle
  ret
.globl _goal
_goal: mov w0, #42
  ret
.globl _direct_goal
_direct_goal: bl _goal
  ret
.globl _unrelated
_unrelated: mov w0, #9
  ret
.section __TEXT,__const
.p2align 2
.globl _middle
_middle: bl _goal
  ret
.section __DATA,__data
.globl _data
_data: .long 42

Start REA MCP with REA_KUNA_COMMAND pointing to verified Kuna 1.986. Call open_binary with the fixture and provider_id: "kuna", then call trace_call_path with {"start":"_main","goal":"_goal"}. As a control, {"start":"_direct_goal","goal":"_goal"} returns reached. With Ghidra 12.1.4, both positive paths return reached. Tested with both compact and full advertised MCP schema profiles, with SDK output validation; exporting and importing the evidence into a new MCP session preserved the result.

Expected behavior

A negative path result and its relationship coverage should reflect an omitted direct call as unknown or incomplete when the provider cannot establish that its call graph covers the relevant code. An explicit limitation already says targets outside the inventory remain unknown; it should not coexist with an unqualified complete negative for this counterexample. The Ghidra and direct-disassembly results provide independent checks of the static instructions. The appropriate recovery or implementation is open for design; this report does not imply that every omitted data symbol should become a function.

Impact and scope

An agent can retain and reuse a definite-looking negative path despite a known direct static route. Reproduced on this synthetic Mach-O arm64 target in both MCP profiles. Other formats and real-world frequency are not established. The executable was not run, and its digest was unchanged.

REA version

d54a4661da

Runtime and platform

Node 24.22.1; macOS 26.3 arm64; Kuna 1.986 verified release; Ghidra 12.1.4 / JDK 21 control.

Target and artifact context

Synthetic Mach-O arm64 executable, SHA-256 788ab9e10b0313cb3a60c3ca59baa0333b271b0ba022122b85408896932ef0b8. Addresses from this build: _main 0x1000003c0, _goal 0x1000003c8, _middle 0x1000003e0.

Interface

MCP

Earliest failure stage

Native analysis or reconstruction

Relevant output or evidence

  • REA procedure_callees(_main) returns 0x1000003e0; xrefs(0x1000003e0) returns 0x1000003c0.
  • REA's path contains only _main → _middle, with both nodes' relationship_coverage.status set to complete and goal_status: not_reached.
  • kuna disassemble fixture 0x1000003e0 --addr --as code --bytes 8 --json decodes bl 0x1000003c8; ret.
  • REA with Ghidra returns _main → _middle → _goal and reached; _main → _unrelated is a negative control.

Analysis or suspected cause

Source-derived: KunaReferenceQueries.ts assigns complete callee coverage when node.hasIndirectCalls is false. That flag alone does not establish that the graph covered all direct calls in this fixture. How best to propagate provider inventory/body coverage is an open design question.

An unverified build of current Kuna source (8c74a944d74f8d3349755e05441a9628b4753111) produced a related result: REA reported the first node's callees as empty and complete even though its xref still found the direct call. This is not a verified release or an upgrade recommendation.

Additional context

Related to the section classification issue #8352 and the separate Ghidra indirect-reference path issue #8277. A proposed real-provider regression should check the two-hop path, the direct positive and unrelated controls, and coverage semantics rather than only the ordinary positive path. The existing real Kuna reference verifier checks an ordinary expected caller and a reached path; this fixture exercises a different boundary.

cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0

Released Kuna 1.988 control

On REA main 53363166f, the released Kuna 1.988 still returned a complete-looking not_reached result on the original two-hop fixture. Its graph now omits the first _main to _middle edge entirely: procedure_callees(_main) returned [], while xrefs returned the real call site. The path visited only _main, reported its relationship coverage as complete, and had no residual unknowns. The separately discovered _direct_goal to _goal positive control remained reached; _main to unrelated remained not reached. The existing limitation says targets outside Kuna's discovered function inventory remain unknown.

A paired fixture changes the instruction at _middle from bl _goal to nop. Direct Kuna 1.988 forced-code disassembly confirmed the differing instructions, yet REA returned the same normalized negative result for both fixtures. Real Ghidra 12.1.4 on the same files returned reached for the original and not reached for the paired control. Full advertised MCP schema was fetched for the Kuna control; the targets were unchanged and not executed. This is one macOS arm64, source-owned static fixture pair, not a prevalence estimate. Updating the recommended Kuna release does not by itself resolve the coverage contract.

Conservative producer-side coverage experiment

An isolated unmerged experiment changed Kuna relationship coverage to unknown when the graph does not establish completeness outside its discovered nodes; indirect-call cases remain partial and also carry the inventory limitation. It retains observed edges. With real Kuna 1.986 and 1.988, full-schema stdio MCP, and the original two-hop plus paired NOP fixture, the prior negative becomes unknown; the direct observed positive remains reached. An unrelated negative also becomes unknown, and even the observed positive has truncated: true under the existing trace contract because its expansion coverage is unknown. This is a deliberate broad tradeoff, not a claim of additional recovered edges. The full real Kuna verifier passed on 1.988 on macOS arm64 with Mach-O and ELF fixtures and complete cleanup; it did not exercise this negative-path case.

A separate 1.988 snapshot control saved the old not_reached Evidence on main and reopened it under the experiment. The historical Evidence was preserved exactly and the fresh result was unknown with a different Evidence ID, but the workflow analysis-profile digest was the same. Before product integration, give the changed producer/derived coverage semantics an appropriate identity and decide snapshot applicability without silently rewriting history. Also consider the usefulness cost: all Kuna negative paths become unknown, not just this fixture, and repeated per-node uncertainty expands results. No automatic provider switch, speculative edge, compatibility shim, or implementation is proposed by this experiment. One host and owned static fixtures; no agent-selection or broad-corpus measurement.

Outgoing-xref alternative

Direct released Kuna 1.986 and 1.988 xrefs --from <address> --kind call --json on both the original and paired NOP fixtures report _main's call site and target _middle; 1.988 leaves to_function null. Querying the exact _middle address returns an empty successful result on both binaries, even though forced-code disassembly shows a bl _goal in the original and a nop in the paired control. Thus outgoing xrefs can recover the first observed edge on this case but cannot alone establish completeness at the omitted middle address or distinguish the two fixtures. The commands were run directly, not through a new REA operation; target hashes were unchanged, binaries were not executed, and no general provider-frequency or performance claim is made. Treat edge discovery and evidence that its source was actually analyzed as distinct facts.

A direct 1.988 xrefs --to 0x1000003c8 --kind call --json control also produced the same single _direct_goal call site on both fixtures; it did not report the _middle call in the original. This does not show that all incoming references are incomplete, but it rules out using this incoming query alone as a proof of absence on the controlled pair.

Upstream report: https://github.com/Noelo-Lab/kuna/issues/1406 asks whether an explicitly selected source in this unflagged section should be walked or report that it was not covered. REA's responsibility to avoid unqualified completeness remains independent of the upstream outcome.

Existing discovery-scope PR on Kuna 1.988

The broader #8443 head b7160bd7 separates provider-graph relationship reads from discovery coverage. Real full-schema stdio MCP with Kuna 1.988 on the original two-hop and paired NOP fixtures returned goal_status: unknown and search_scope.observed_goal_status: not_reached; the observed direct positive remained reached, and the unrelated negative was also unknown. The same control on 1.986 reported partial discovery at the data-classified node; 1.988 omitted that node and reported discovery unknown. The unexecuted target hashes were unchanged. This supports the existing PR's general boundary, rather than a new xrefs wrapper.

A 1.988 snapshot containing the older negative was refused by #8443 as a profile mismatch. Manual extraction of the embedded Evidence bundle followed by target-free import preserved the old record exactly; fresh analysis returned unknown under a different profile. This extraction is not a built-in migration workflow. Snapshot and target bytes remained unchanged; one host and controlled fixtures only.

Kuna 1.989 and explicit-source coverage

On the proposed version-bump PR #8691 (fc2ca7115), real Kuna 1.989 in both full and compact stdio MCP profiles still returned the same complete-looking not_reached for _main to _goal on the original call and paired NOP fixtures. procedure_callees(_main) was empty and xrefs(_middle) retained _main's call site. The direct positive remained reached and the unrelated negative remained not reached. Independent xcrun llvm-objdump --disassemble --section=__const showed bl _goal in the original and nop in the paired fixture. Both target digests were unchanged; neither executable ran.

Direct Kuna 1.989 xrefs --from 0x1000003e0 --kind call --json now distinguishes the two fixtures: one call row in the original, none in the NOP control. Both report coverage.decoded: true, executable mapping and the non-code section; the notes say the explicitly requested address was decoded and other queries do not walk that section. This addresses the upstream explicit-source case in Noelo-Lab/kuna#1406, but REA's existing graph-based path query still does not consume that direct observation. It is not proof that the whole program's discovery is complete or a recommendation to silently equate a negative xref with absence.

As a separate control, current discovery-scope PR #8443 head ef5a7e68b on the same two fixtures and Kuna 1.989 returned unknown with search_scope.observed_goal_status: not_reached in both schema profiles. The direct positive stayed reached; the unrelated negative also became unknown. This confirms the tradeoff for the sampled 1.989 artifacts; it does not recover the missing path or establish broad coverage.

Kuna 1.990 and discovery-scope fix

On macOS arm64, I rebuilt the source-owned call and paired NOP Mach-O fixtures above. Independent llvm-objdump showed bl _goal at _middle in one and nop in the other. On the REA 1.990 verification branch 187f3d8cc, real Kuna 1.990 returned not_reached with no residual unknowns for _main to _goal in both binaries; the direct _direct_goal to _goal control returned reached. On #8443 head ef5a7e68b, the same queries returned unknown with search_scope.observed_goal_status: not_reached, while the direct positive stayed reached. _main to the unrelated function also changed from not_reached to unknown. Both compact and full MCP profiles were exercised; both target hashes (f314f698ea2c0fb730decd6cc087f9f1818d3c83173571416b3e07f1c124f1e0, 867753d9b9e1fc62436a24c4db0683cb82c4f469e368e4b99ef52ea3ff74285b) remained unchanged and neither target ran. This confirms the conservative discovery-scope behavior on one controlled fixture pair, not recovery of the missing edge or a prevalence estimate.

Explicit-source query on Kuna 1.990

Direct Kuna 1.990 xrefs --from 0x1000003e0 --kind call --json distinguished the paired fixtures above: it returned _middle to _goal in the call fixture and zero rows in the NOP fixture. Both responses reported coverage.decoded: true, section: __TEXT,__const, code_section: false, executable: true, and a note that this explicitly requested source was decoded while other queries do not walk that section. This confirms the behavior reported fixed upstream in Kuna #1412 for the 1.990 release; it is not whole-program discovery coverage or runtime reachability. REA's current Kuna xrefs adapter invokes the incoming --to form, so this direct query is not an existing REA outgoing-reference workflow. See #8190 for that design boundary.

Ghidra control on the rebuilt pair

On #8443 head ef5a7e68b with real Ghidra 12.1.4/JDK 21, the same rebuilt fixture pair and compact/full MCP profiles returned reached for _main to _goal in the call fixture and unknown with observed not_reached for the NOP fixture. The direct positive was reached in both; the unrelated negative was unknown. Both target digests remained unchanged. This is a working explicit Ghidra alternative for recovering this observed path, not proof that Ghidra's negative is complete or that every binary has equivalent coordinates across providers.

Same-session investigation and selector recovery

On #8443 with Kuna 1.990, both MCP profiles returned the discovery-qualified unknown path; a separately requested incoming xrefs at _middle returned _main's call site. Attempting Kuna procedure_assembly at _middle failed because it was absent from the provider inventory, but its top-level remediation still suggested schema repair. Explicitly selecting Ghidra on the same connection returned the two-edge path and preserved the original Kuna trace Evidence exactly. On separate #8397 head 65939bc4a, the same Kuna assembly failure retained the exact address and recommended inventory inspection without schema-repair recovery; the explicit Ghidra handoff again reached the goal. These were separate branch controls, not a combined integration or an automatic provider switch. The target digest remained unchanged; it was not executed.

Combined call-scope and selector-recovery control

In a disposable integration checkout combining #8443 ef5a7e68b with #8397 65939bc4a, the same 1.990 fixture and real Ghidra 12.1.4 were exercised through compact and full MCP. Kuna trace_call_path returned unknown with observed not_reached; incoming xrefs found _main's call to _middle; procedure_assembly at _middle returned the inventory-scoped selector guidance without schema-repair recovery. Explicitly selecting Ghidra on the same connection returned the two observed edges to _goal, and the prior Kuna trace remained identical in the retained bundle. Successful tool responses validated against the advertised output schemas. The target SHA-256 stayed f314f698ea2c0fb730decd6cc087f9f1818d3c83173571416b3e07f1c124f1e0 and was not executed. This is an uncommitted local integration, not an automatic fallback, autonomous-agent trace, or assertion that either PR contains the other.

Originally created by @morluto on GitHub (Oct 31, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8362 ### 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 Native analysis or decompilation ### Observed behavior On the fixture below, `trace_call_path` with verified Kuna 1.986 reports `goal_status: not_reached`, complete relationship coverage at both visited nodes, no failures, and no residual unknowns for `_main` → `_goal`. But the binary contains two direct call instructions `_main` → `_middle` → `_goal`. REA itself reports the first edge and an xref to `_middle`; direct Kuna disassembly decodes the second. Ghidra reports the two-edge static path as reached. This is a static evidence discrepancy, not a claim that the target was executed. ### Reproduction On macOS arm64, assemble the following and link with `clang -arch arm64 -Wl,-e,_main fixture.s -o fixture`: ```asm .section __TEXT,__text,regular,pure_instructions .p2align 2 .globl _main _main: bl _middle ret .globl _goal _goal: mov w0, #42 ret .globl _direct_goal _direct_goal: bl _goal ret .globl _unrelated _unrelated: mov w0, #9 ret .section __TEXT,__const .p2align 2 .globl _middle _middle: bl _goal ret .section __DATA,__data .globl _data _data: .long 42 ``` Start REA MCP with `REA_KUNA_COMMAND` pointing to verified Kuna 1.986. Call `open_binary` with the fixture and `provider_id: "kuna"`, then call `trace_call_path` with `{"start":"_main","goal":"_goal"}`. As a control, `{"start":"_direct_goal","goal":"_goal"}` returns `reached`. With Ghidra 12.1.4, both positive paths return `reached`. Tested with both compact and full advertised MCP schema profiles, with SDK output validation; exporting and importing the evidence into a new MCP session preserved the result. ### Expected behavior A negative path result and its relationship coverage should reflect an omitted direct call as unknown or incomplete when the provider cannot establish that its call graph covers the relevant code. An explicit limitation already says targets outside the inventory remain unknown; it should not coexist with an unqualified complete negative for this counterexample. The Ghidra and direct-disassembly results provide independent checks of the static instructions. The appropriate recovery or implementation is open for design; this report does not imply that every omitted data symbol should become a function. ### Impact and scope An agent can retain and reuse a definite-looking negative path despite a known direct static route. Reproduced on this synthetic Mach-O arm64 target in both MCP profiles. Other formats and real-world frequency are not established. The executable was not run, and its digest was unchanged. ### REA version d54a4661da20382ad8456564a08569fdd24131c5 ### Runtime and platform Node 24.22.1; macOS 26.3 arm64; Kuna 1.986 verified release; Ghidra 12.1.4 / JDK 21 control. ### Target and artifact context Synthetic Mach-O arm64 executable, SHA-256 `788ab9e10b0313cb3a60c3ca59baa0333b271b0ba022122b85408896932ef0b8`. Addresses from this build: `_main` `0x1000003c0`, `_goal` `0x1000003c8`, `_middle` `0x1000003e0`. ### Interface MCP ### Earliest failure stage Native analysis or reconstruction ### Relevant output or evidence - REA `procedure_callees(_main)` returns `0x1000003e0`; `xrefs(0x1000003e0)` returns `0x1000003c0`. - REA's path contains only `_main → _middle`, with both nodes' `relationship_coverage.status` set to `complete` and `goal_status: not_reached`. - `kuna disassemble fixture 0x1000003e0 --addr --as code --bytes 8 --json` decodes `bl 0x1000003c8; ret`. - REA with Ghidra returns `_main → _middle → _goal` and `reached`; `_main → _unrelated` is a negative control. ### Analysis or suspected cause Source-derived: [KunaReferenceQueries.ts](https://github.com/morluto/rea/blob/d54a4661da20382ad8456564a08569fdd24131c5/src/kuna/KunaReferenceQueries.ts#L171-L195) assigns complete callee coverage when `node.hasIndirectCalls` is false. That flag alone does not establish that the graph covered all direct calls in this fixture. How best to propagate provider inventory/body coverage is an open design question. An unverified build of current Kuna source (`8c74a944d74f8d3349755e05441a9628b4753111`) produced a related result: REA reported the first node's callees as empty and complete even though its xref still found the direct call. This is not a verified release or an upgrade recommendation. ### Additional context Related to the section classification issue #8352 and the separate Ghidra indirect-reference path issue #8277. A proposed real-provider regression should check the two-hop path, the direct positive and unrelated controls, and coverage semantics rather than only the ordinary positive path. The existing real Kuna reference verifier checks an ordinary expected caller and a reached path; this fixture exercises a different boundary. cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 ### Released Kuna 1.988 control On REA main `53363166f`, the released Kuna 1.988 still returned a complete-looking `not_reached` result on the original two-hop fixture. Its graph now omits the first `_main` to `_middle` edge entirely: `procedure_callees(_main)` returned `[]`, while `xrefs` returned the real call site. The path visited only `_main`, reported its relationship coverage as `complete`, and had no residual unknowns. The separately discovered `_direct_goal` to `_goal` positive control remained reached; `_main` to unrelated remained not reached. The existing limitation says targets outside Kuna's discovered function inventory remain unknown. A paired fixture changes the instruction at `_middle` from `bl _goal` to `nop`. Direct Kuna 1.988 forced-code disassembly confirmed the differing instructions, yet REA returned the same normalized negative result for both fixtures. Real Ghidra 12.1.4 on the same files returned reached for the original and not reached for the paired control. Full advertised MCP schema was fetched for the Kuna control; the targets were unchanged and not executed. This is one macOS arm64, source-owned static fixture pair, not a prevalence estimate. Updating the recommended Kuna release does not by itself resolve the coverage contract. ### Conservative producer-side coverage experiment An isolated unmerged experiment changed Kuna relationship coverage to `unknown` when the graph does not establish completeness outside its discovered nodes; indirect-call cases remain partial and also carry the inventory limitation. It retains observed edges. With real Kuna 1.986 and 1.988, full-schema stdio MCP, and the original two-hop plus paired NOP fixture, the prior negative becomes `unknown`; the direct observed positive remains `reached`. An unrelated negative also becomes `unknown`, and even the observed positive has `truncated: true` under the existing trace contract because its expansion coverage is unknown. This is a deliberate broad tradeoff, not a claim of additional recovered edges. The full real Kuna verifier passed on 1.988 on macOS arm64 with Mach-O and ELF fixtures and complete cleanup; it did not exercise this negative-path case. A separate 1.988 snapshot control saved the old `not_reached` Evidence on main and reopened it under the experiment. The historical Evidence was preserved exactly and the fresh result was `unknown` with a different Evidence ID, but the workflow analysis-profile digest was the same. Before product integration, give the changed producer/derived coverage semantics an appropriate identity and decide snapshot applicability without silently rewriting history. Also consider the usefulness cost: all Kuna negative paths become unknown, not just this fixture, and repeated per-node uncertainty expands results. No automatic provider switch, speculative edge, compatibility shim, or implementation is proposed by this experiment. One host and owned static fixtures; no agent-selection or broad-corpus measurement. ### Outgoing-xref alternative Direct released Kuna 1.986 and 1.988 `xrefs --from <address> --kind call --json` on both the original and paired NOP fixtures report `_main`'s call site and target `_middle`; 1.988 leaves `to_function` null. Querying the exact `_middle` address returns an empty successful result on both binaries, even though forced-code disassembly shows a `bl _goal` in the original and a `nop` in the paired control. Thus outgoing xrefs can recover the first observed edge on this case but cannot alone establish completeness at the omitted middle address or distinguish the two fixtures. The commands were run directly, not through a new REA operation; target hashes were unchanged, binaries were not executed, and no general provider-frequency or performance claim is made. Treat edge discovery and evidence that its source was actually analyzed as distinct facts. A direct 1.988 `xrefs --to 0x1000003c8 --kind call --json` control also produced the same single `_direct_goal` call site on both fixtures; it did not report the `_middle` call in the original. This does not show that all incoming references are incomplete, but it rules out using this incoming query alone as a proof of absence on the controlled pair. Upstream report: https://github.com/Noelo-Lab/kuna/issues/1406 asks whether an explicitly selected source in this unflagged section should be walked or report that it was not covered. REA's responsibility to avoid unqualified completeness remains independent of the upstream outcome. ### Existing discovery-scope PR on Kuna 1.988 The broader #8443 head `b7160bd7` separates provider-graph relationship reads from discovery coverage. Real full-schema stdio MCP with Kuna 1.988 on the original two-hop and paired NOP fixtures returned `goal_status: unknown` and `search_scope.observed_goal_status: not_reached`; the observed direct positive remained reached, and the unrelated negative was also unknown. The same control on 1.986 reported partial discovery at the data-classified node; 1.988 omitted that node and reported discovery unknown. The unexecuted target hashes were unchanged. This supports the existing PR's general boundary, rather than a new xrefs wrapper. A 1.988 snapshot containing the older negative was refused by #8443 as a profile mismatch. Manual extraction of the embedded Evidence bundle followed by target-free import preserved the old record exactly; fresh analysis returned unknown under a different profile. This extraction is not a built-in migration workflow. Snapshot and target bytes remained unchanged; one host and controlled fixtures only. ### Kuna 1.989 and explicit-source coverage On the proposed version-bump PR #8691 (`fc2ca7115`), real Kuna 1.989 in both full and compact stdio MCP profiles still returned the same complete-looking `not_reached` for `_main` to `_goal` on the original call and paired NOP fixtures. `procedure_callees(_main)` was empty and `xrefs(_middle)` retained `_main`'s call site. The direct positive remained reached and the unrelated negative remained not reached. Independent `xcrun llvm-objdump --disassemble --section=__const` showed `bl _goal` in the original and `nop` in the paired fixture. Both target digests were unchanged; neither executable ran. Direct Kuna 1.989 `xrefs --from 0x1000003e0 --kind call --json` now distinguishes the two fixtures: one call row in the original, none in the NOP control. Both report `coverage.decoded: true`, executable mapping and the non-code section; the notes say the explicitly requested address was decoded and other queries do not walk that section. This addresses the upstream explicit-source case in Noelo-Lab/kuna#1406, but REA's existing graph-based path query still does not consume that direct observation. It is not proof that the whole program's discovery is complete or a recommendation to silently equate a negative xref with absence. As a separate control, current discovery-scope PR #8443 head `ef5a7e68b` on the same two fixtures and Kuna 1.989 returned `unknown` with `search_scope.observed_goal_status: not_reached` in both schema profiles. The direct positive stayed reached; the unrelated negative also became unknown. This confirms the tradeoff for the sampled 1.989 artifacts; it does not recover the missing path or establish broad coverage. ### Kuna 1.990 and discovery-scope fix On macOS arm64, I rebuilt the source-owned call and paired NOP Mach-O fixtures above. Independent `llvm-objdump` showed `bl _goal` at `_middle` in one and `nop` in the other. On the REA 1.990 verification branch `187f3d8cc`, real Kuna 1.990 returned `not_reached` with no residual unknowns for `_main` to `_goal` in both binaries; the direct `_direct_goal` to `_goal` control returned `reached`. On #8443 head `ef5a7e68b`, the same queries returned `unknown` with `search_scope.observed_goal_status: not_reached`, while the direct positive stayed `reached`. `_main` to the unrelated function also changed from `not_reached` to `unknown`. Both compact and full MCP profiles were exercised; both target hashes (`f314f698ea2c0fb730decd6cc087f9f1818d3c83173571416b3e07f1c124f1e0`, `867753d9b9e1fc62436a24c4db0683cb82c4f469e368e4b99ef52ea3ff74285b`) remained unchanged and neither target ran. This confirms the conservative discovery-scope behavior on one controlled fixture pair, not recovery of the missing edge or a prevalence estimate. ### Explicit-source query on Kuna 1.990 Direct Kuna 1.990 `xrefs --from 0x1000003e0 --kind call --json` distinguished the paired fixtures above: it returned `_middle` to `_goal` in the call fixture and zero rows in the NOP fixture. Both responses reported `coverage.decoded: true`, `section: __TEXT,__const`, `code_section: false`, `executable: true`, and a note that this explicitly requested source was decoded while other queries do not walk that section. This confirms the behavior reported fixed upstream in [Kuna #1412](https://github.com/Noelo-Lab/kuna/pull/1412) for the 1.990 release; it is not whole-program discovery coverage or runtime reachability. REA's current Kuna `xrefs` adapter invokes the incoming `--to` form, so this direct query is not an existing REA outgoing-reference workflow. See #8190 for that design boundary. ### Ghidra control on the rebuilt pair On #8443 head `ef5a7e68b` with real Ghidra 12.1.4/JDK 21, the same rebuilt fixture pair and compact/full MCP profiles returned `reached` for `_main` to `_goal` in the call fixture and `unknown` with observed `not_reached` for the NOP fixture. The direct positive was reached in both; the unrelated negative was unknown. Both target digests remained unchanged. This is a working explicit Ghidra alternative for recovering this observed path, not proof that Ghidra's negative is complete or that every binary has equivalent coordinates across providers. ### Same-session investigation and selector recovery On #8443 with Kuna 1.990, both MCP profiles returned the discovery-qualified unknown path; a separately requested incoming `xrefs` at `_middle` returned `_main`'s call site. Attempting Kuna `procedure_assembly` at `_middle` failed because it was absent from the provider inventory, but its top-level remediation still suggested schema repair. Explicitly selecting Ghidra on the same connection returned the two-edge path and preserved the original Kuna trace Evidence exactly. On separate #8397 head `65939bc4a`, the same Kuna assembly failure retained the exact address and recommended inventory inspection without schema-repair recovery; the explicit Ghidra handoff again reached the goal. These were separate branch controls, not a combined integration or an automatic provider switch. The target digest remained unchanged; it was not executed. ### Combined call-scope and selector-recovery control In a disposable integration checkout combining #8443 `ef5a7e68b` with #8397 `65939bc4a`, the same 1.990 fixture and real Ghidra 12.1.4 were exercised through compact and full MCP. Kuna `trace_call_path` returned `unknown` with observed `not_reached`; incoming `xrefs` found `_main`'s call to `_middle`; `procedure_assembly` at `_middle` returned the inventory-scoped selector guidance without schema-repair recovery. Explicitly selecting Ghidra on the same connection returned the two observed edges to `_goal`, and the prior Kuna trace remained identical in the retained bundle. Successful tool responses validated against the advertised output schemas. The target SHA-256 stayed `f314f698ea2c0fb730decd6cc087f9f1818d3c83173571416b3e07f1c124f1e0` and was not executed. This is an uncommitted local integration, not an automatic fallback, autonomous-agent trace, or assertion that either PR contains the other.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

Additional real-provider MCP check on the same fixture, with full output-schema validation:

  • procedure_callers({"procedure":"_goal"}) with verified Kuna 1.986 returns only _direct_goal (0x1000003d0) and marks callers coverage complete; it omits _middle (0x1000003e0), even though direct Kuna disassembly decodes its bl _goal.
  • trace_call_path({"start":"_goal","goal":"_main","direction":"backward"}) returns not_reached, both visited nodes complete, no failures and no residual unknowns. The normal _goal → _direct_goal backward control returns reached.
  • Ghidra reports both direct callers and reaches _main in the reverse search. Both providers report _goal → _unrelated as not_reached for this fixture. get_call_graph also exposes the omitted caller with complete node coverage under Kuna.
  • Kuna xrefs(_goal) finds the ordinary caller and omits _middle; unlike relationship coverage, its existing limitation explicitly says an empty result does not prove no reference exists. Here it is nonempty but still incomplete.

An unverified current Kuna source build produced the same reverse results; no release-wide claim is implied. The target was not executed and its hash was unchanged. This extends the same coverage issue to caller queries and reverse traversal, so it should be addressed together, with forward and backward controls in the regression.

Source-derived context: the adapter marks callers complete whenever the graph reports no indirect calls; this fixture shows that absence of indirect calls alone does not prove all direct incoming calls were examined. It does not by itself prescribe where the provider/adapter should establish completeness.

<!-- gh-comment-id:6548045807 --> @morluto commented on GitHub (Oct 31, 2026): Additional real-provider MCP check on the same fixture, with full output-schema validation: - `procedure_callers({"procedure":"_goal"})` with verified Kuna 1.986 returns only `_direct_goal` (`0x1000003d0`) and marks callers coverage `complete`; it omits `_middle` (`0x1000003e0`), even though direct Kuna disassembly decodes its `bl _goal`. - `trace_call_path({"start":"_goal","goal":"_main","direction":"backward"})` returns `not_reached`, both visited nodes complete, no failures and no residual unknowns. The normal `_goal` → `_direct_goal` backward control returns `reached`. - Ghidra reports both direct callers and reaches `_main` in the reverse search. Both providers report `_goal` → `_unrelated` as `not_reached` for this fixture. `get_call_graph` also exposes the omitted caller with complete node coverage under Kuna. - Kuna `xrefs(_goal)` finds the ordinary caller and omits `_middle`; unlike relationship coverage, its existing limitation explicitly says an empty result does not prove no reference exists. Here it is nonempty but still incomplete. An unverified current Kuna source build produced the same reverse results; no release-wide claim is implied. The target was not executed and its hash was unchanged. This extends the same coverage issue to caller queries and reverse traversal, so it should be addressed together, with forward and backward controls in the regression. Source-derived context: the adapter marks callers complete whenever the graph reports no indirect calls; this fixture shows that absence of indirect calls alone does not prove all direct incoming calls were examined. It does not by itself prescribe where the provider/adapter should establish completeness.
Author
Owner

@morluto commented on GitHub (Oct 31, 2026):

A further real-provider control shows the same discovery boundary affects positive paths as well as negative ones. On a new synthetic arm64 Mach-O (SHA-256 4540cb983e8b428e159e15b884c822232bff1f214292bd2b8546e2cd7f7b83d1), _main has observed calls to both _middle and _via_one; _via_one → _via_two → _goal is the longer route. _middle is in __TEXT,__const and its bytes decode as bl _goal; ret.

With verified Kuna 1.986 and REA main d54a4661, public MCP trace_call_path(_main, _goal) reports the three-edge route through _via_one, reached, truncated: false, all visited relationship coverage complete, and no residual unknowns. Ghidra 12.1.4 reports the two-edge static route through _middle. Direct Kuna forced-code disassembly of _middle confirms the encoded bl target, and LLVM disassembly confirms _main calls _middle. The returned Kuna path is shortest within its returned graph; the experiment does not establish that it is shortest over all statically decodable calls. This fixture was not executed; _middle is in a non-code section, so neither this observation nor Ghidra's static path establishes executable/runtime reachability. Full MCP schemas were validated, and the target digest stayed unchanged.

I also tested an isolated unmerged experiment that changes the adapter's no-indirect-call coverage from complete to unknown, leaving observed edges intact. On the original fixture, both the missing forward and backward paths change from not_reached to unknown; the direct positive controls remain reached, and the unrelated negative controls also become unknown. On the new fixture, the longer positive route remains available but is marked truncated with residual unknowns. Existing documentation explicitly defines trace_call_path.truncated that way. The same change propagates unknown coverage into Kuna function dossiers and changes one observed different-dossier calls comparison from changed to unknown; its self-comparison was already unknown for separate identity reasons. These are observations of the experiment, not a proposed finished patch.

The design distinction matters: tool-design.md describes relationship_coverage as completeness of the provider-observed set, while this counterexample concerns discovery beyond that set. A fix needs to distinguish exhaustive retrieval of the observed graph from evidence about discovery or target completeness, and make the scope of negative and shortest-path claims machine-readable. Merely making every Kuna relationship unknown loses that distinction and has broad comparison consequences. A production change must also consider snapshot/profile invalidation and historical Evidence; this small experiment did not change profiles or test cache migration. Other providers, targets and operating systems remain unverified.

<!-- gh-comment-id:6548443750 --> @morluto commented on GitHub (Oct 31, 2026): A further real-provider control shows the same discovery boundary affects **positive** paths as well as negative ones. On a new synthetic arm64 Mach-O (SHA-256 `4540cb983e8b428e159e15b884c822232bff1f214292bd2b8546e2cd7f7b83d1`), `_main` has observed calls to both `_middle` and `_via_one`; `_via_one → _via_two → _goal` is the longer route. `_middle` is in `__TEXT,__const` and its bytes decode as `bl _goal; ret`. With verified Kuna 1.986 and REA main `d54a4661`, public MCP `trace_call_path(_main, _goal)` reports the three-edge route through `_via_one`, `reached`, `truncated: false`, all visited relationship coverage `complete`, and no residual unknowns. Ghidra 12.1.4 reports the two-edge static route through `_middle`. Direct Kuna forced-code disassembly of `_middle` confirms the encoded `bl` target, and LLVM disassembly confirms `_main` calls `_middle`. The returned Kuna path is shortest **within its returned graph**; the experiment does not establish that it is shortest over all statically decodable calls. This fixture was not executed; `_middle` is in a non-code section, so neither this observation nor Ghidra's static path establishes executable/runtime reachability. Full MCP schemas were validated, and the target digest stayed unchanged. I also tested an isolated **unmerged experiment** that changes the adapter's no-indirect-call coverage from `complete` to `unknown`, leaving observed edges intact. On the original fixture, both the missing forward and backward paths change from `not_reached` to `unknown`; the direct positive controls remain `reached`, and the unrelated negative controls also become `unknown`. On the new fixture, the longer positive route remains available but is marked `truncated` with residual unknowns. Existing documentation explicitly defines `trace_call_path.truncated` that way. The same change propagates unknown coverage into Kuna function dossiers and changes one observed different-dossier calls comparison from `changed` to `unknown`; its self-comparison was already unknown for separate identity reasons. These are observations of the experiment, not a proposed finished patch. The design distinction matters: [tool-design.md](https://github.com/morluto/rea/blob/d54a4661da20382ad8456564a08569fdd24131c5/docs/tool-design.md#L124-L128) describes `relationship_coverage` as completeness of the **provider-observed** set, while this counterexample concerns discovery beyond that set. A fix needs to distinguish exhaustive retrieval of the observed graph from evidence about discovery or target completeness, and make the scope of negative and shortest-path claims machine-readable. Merely making every Kuna relationship `unknown` loses that distinction and has broad comparison consequences. A production change must also consider snapshot/profile invalidation and historical Evidence; this small experiment did not change profiles or test cache migration. Other providers, targets and operating systems remain unverified.
Author
Owner

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

Explicit provider-switch and offline composition control

On REA #8440 head 025272ee2a9763a3f174a9dba7a8eda8fc722cf3 (verifier-only change) with real Kuna 1.986, Ghidra 12.1.4/JDK 21, macOS arm64 and stdio MCP, I used the original source-owned __TEXT,__const fixture from this issue:

  1. Kuna trace_call_path(_main, _goal) returned not_reached; its _main dossier was retained. Direct Kuna forced-code disassembly at _middle separately decoded bl _goal; ret.
  2. Explicitly switched the same target to Ghidra, retained dossiers for _main and _middle, and tried build_call_path with the Kuna _main dossier plus Ghidra _middle. REA returned invalid_request, explaining that the Evidence mixes providers. Both original provider records remained retained.
  3. Using the two Ghidra dossiers instead returned a two-hop static path, citing both exact sources. After exporting the bundle and closing, a fresh target-free MCP server imported it: the mixed request was still refused, while the Ghidra-only path returned exactly the same Evidence as before export.

The target SHA-256 788ab9e10b0313cb3a60c3ca59baa0333b271b0ba022122b85408896932ef0b8 remained unchanged and it was not executed. The fixture places _middle in a non-code section of an executable segment; the result is evidence about static decoding and reported relationships, not runtime execution. This is one target and host. The provider-mixing refusal is an explicit current contract, not itself a defect: joining observations requires a defensible coordinate/provenance policy. It shows an available recovery using a separate Ghidra analysis while keeping Kuna's original result, and why raw cross-provider union should not be assumed safe.

<!-- gh-comment-id:6553359738 --> @morluto commented on GitHub (Nov 1, 2026): ### Explicit provider-switch and offline composition control On REA #8440 head `025272ee2a9763a3f174a9dba7a8eda8fc722cf3` (verifier-only change) with real Kuna 1.986, Ghidra 12.1.4/JDK 21, macOS arm64 and stdio MCP, I used the original source-owned `__TEXT,__const` fixture from this issue: 1. Kuna `trace_call_path(_main, _goal)` returned `not_reached`; its `_main` dossier was retained. Direct Kuna forced-code disassembly at `_middle` separately decoded `bl _goal; ret`. 2. Explicitly switched the same target to Ghidra, retained dossiers for `_main` and `_middle`, and tried `build_call_path` with the Kuna `_main` dossier plus Ghidra `_middle`. REA returned `invalid_request`, explaining that the Evidence mixes providers. Both original provider records remained retained. 3. Using the two Ghidra dossiers instead returned a two-hop static path, citing both exact sources. After exporting the bundle and closing, a fresh target-free MCP server imported it: the mixed request was still refused, while the Ghidra-only path returned exactly the same Evidence as before export. The target SHA-256 `788ab9e10b0313cb3a60c3ca59baa0333b271b0ba022122b85408896932ef0b8` remained unchanged and it was not executed. The fixture places `_middle` in a non-code section of an executable segment; the result is evidence about static decoding and reported relationships, not runtime execution. This is one target and host. The provider-mixing refusal is an explicit current contract, not itself a defect: joining observations requires a defensible coordinate/provenance policy. It shows an available recovery using a separate Ghidra analysis while keeping Kuna's original result, and why raw cross-provider union should not be assumed safe.
Author
Owner

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

Existing cross-provider comparison control

Using the same real-provider fixture and session in the preceding control, I passed the retained Kuna _main and Ghidra entry dossiers (both at 0x1000003c0) to compare_functions. It returned function_match.status: ambiguous, overall unknown, and all eight dimensions unknown. The calls dimension reported that a common executable coordinate context was not established; the output retained provider-specific limitations and linked both original dossiers. A Ghidra dossier compared with itself returned same-entry and unchanged. After bundle export, a fresh target-free server imported the records and produced exactly the same cross-provider comparison Evidence.

This is a useful existing way to keep uncertainty visible while inspecting these observations; it does not map coordinates, identify an omitted call, or make the Kuna path exhaustive. The two tools answer different questions, so this comparison is not by itself a contradiction of the path result. The known fixture's hash stayed unchanged and it was not executed. One target, host and provider pair were checked. Related coordinate-mapping design: #8372.

Offline single-provider path control

On the same fixture and host with real Kuna 1.986 and stdio MCP, I retained the _main dossier and attempted to obtain _middle directly. Its name lookup failed; selecting 0x1000003e0 returned an explicit input error explaining that its Mach-O section declares no instructions. Using the available _main dossier in build_call_path returned status: unknown, search_scope.exhaustive: false, and a limitation that no dossier covers reachable 0x1000003e0. After export and import into a fresh target-free session, the complete result matched exactly. The original live trace_call_path still returned not_reached for the same start and goal.

This is a useful conservative existing workflow for this fixture, not a workaround that finds the missing edge. It shows the discrepancy is not universal across REA's path tools: offline dossier composition identifies its missing source, while live tracing has already accepted an empty relationship response for the provider-derived address. A fix needs to preserve that distinction and must not claim more complete graph discovery from the dossier's relationship_coverage: complete alone. The static target's SHA-256 was unchanged and it was not executed. One synthetic target and provider release only.

<!-- gh-comment-id:6553369349 --> @morluto commented on GitHub (Nov 1, 2026): ### Existing cross-provider comparison control Using the same real-provider fixture and session in the preceding control, I passed the retained Kuna `_main` and Ghidra `entry` dossiers (both at `0x1000003c0`) to `compare_functions`. It returned `function_match.status: ambiguous`, overall `unknown`, and all eight dimensions unknown. The calls dimension reported that a common executable coordinate context was not established; the output retained provider-specific limitations and linked both original dossiers. A Ghidra dossier compared with itself returned `same-entry` and `unchanged`. After bundle export, a fresh target-free server imported the records and produced exactly the same cross-provider comparison Evidence. This is a useful existing way to keep uncertainty visible while inspecting these observations; it does not map coordinates, identify an omitted call, or make the Kuna path exhaustive. The two tools answer different questions, so this comparison is not by itself a contradiction of the path result. The known fixture's hash stayed unchanged and it was not executed. One target, host and provider pair were checked. Related coordinate-mapping design: #8372. ### Offline single-provider path control On the same fixture and host with real Kuna 1.986 and stdio MCP, I retained the `_main` dossier and attempted to obtain `_middle` directly. Its name lookup failed; selecting `0x1000003e0` returned an explicit input error explaining that its Mach-O section declares no instructions. Using the available `_main` dossier in `build_call_path` returned `status: unknown`, `search_scope.exhaustive: false`, and a limitation that no dossier covers reachable `0x1000003e0`. After export and import into a fresh target-free session, the complete result matched exactly. The original live `trace_call_path` still returned `not_reached` for the same start and goal. This is a useful conservative existing workflow for this fixture, not a workaround that finds the missing edge. It shows the discrepancy is not universal across REA's path tools: offline dossier composition identifies its missing source, while live tracing has already accepted an empty relationship response for the provider-derived address. A fix needs to preserve that distinction and must not claim more complete graph discovery from the dossier's `relationship_coverage: complete` alone. The static target's SHA-256 was unchanged and it was not executed. One synthetic target and provider release only.
Author
Owner

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

Provider graph classification and a no-call control

A direct run of released Kuna 1.986 on the original fixture adds a concrete source fact to the diagnosis. decompile-graph --functions '' emits _main as kind: normal, but the call destination 0x1000003e0 as kind: data, size 0, hasIndirectCalls: false; the graph includes _main → 0x1000003e0 as a call and no outgoing call from that destination. Explicitly selecting both addresses with decompile-graph --addr returns _main's body and warns that the destination is not executable content and is exported without a body. The destination's codeC and assembly are null. The release's graph producer describes data as a bodyless classification. This is Kuna's classification, not proof of runtime reachability or a reason to reinterpret data as code automatically.

On REA 025272ee2 using the same installed provider and public stdio MCP, explicit procedure_callees({procedure:"0x1000003e0"}) returned [] with relationship_coverage: complete; the retained graph-source summary omitted the node's kind. In the same session analyze_function at that address rejected it because the Mach-O section declares no instructions. The live path nevertheless expanded that address and returned not_reached with complete coverage. The agent sees conflicting practical implications from the two workflows without the graph node classification in the relationship Evidence.

For a separate negative control, I rebuilt the same authored source with the destination changed from bl _goal; ret to nop; ret (SHA-256 ce7eab76b09d27ee9843c07f7c6b178bd55873269dd47682e2591a33ad69e0e2). Direct forced-code disassembly confirmed those instructions. Kuna's functions rows and edges rows were identical to the original fixture's graph, including the data node and _main's call to it. REA returned identical normalized procedure_callees and trace_call_path results and coverage for the two fixtures; subject digests and graph source paths/digests differ. The original fixture's forced-code disassembly contains the call; the control does not. Both targets were unchanged during analysis and neither was executed. This is static decoding evidence for two deliberately constructed fixtures, not a runtime claim or frequency estimate.

This is an actionable boundary, but not a complete solution to the issue. The current parser retains node.kind, while KunaReferenceQueries makes coverage depend on hasIndirectCalls and omits kind from the recorded source summary. A path expansion of a bodyless provider node is a specific place to preserve the provider's classification and uncertainty; unvisited graph nodes and all callers need separate reasoning. Every Mach-O graph here also contains uncalled data nodes such as the header, so downgrading all graphs merely because any data row exists would be overly broad. Conversely, the identical rows show a graph-only consumer cannot determine which of these two bodies contains a call. Preserve observed edges, distinguish graph retrieval from discovery, and retain the existing conservative treatment of incomplete evidence; no code change or general discovery guarantee is proposed here.

A further real Ghidra 12.1.4/JDK 21 stdio MCP control on both exact files returned the two-hop static path on the original and not_reached on the nop variant. Full advertised output schemas were used, and both target hashes remained unchanged. This corroborates the differing static instructions; neither fixture establishes execution or general engine completeness.

<!-- gh-comment-id:6553986330 --> @morluto commented on GitHub (Nov 1, 2026): ### Provider graph classification and a no-call control A direct run of **released Kuna 1.986** on the original fixture adds a concrete source fact to the diagnosis. `decompile-graph --functions ''` emits `_main` as `kind: normal`, but the call destination `0x1000003e0` as `kind: data`, size `0`, `hasIndirectCalls: false`; the graph includes `_main → 0x1000003e0` as a call and no outgoing call from that destination. Explicitly selecting both addresses with `decompile-graph --addr` returns `_main`'s body and warns that the destination is not executable content and is exported without a body. The destination's `codeC` and `assembly` are null. The release's [graph producer](https://github.com/Noelo-Lab/kuna/blob/v1.986/decompiler/crates/kuna-cli/src/decompile_graph.rs#L351-L383) describes `data` as a bodyless classification. This is Kuna's classification, not proof of runtime reachability or a reason to reinterpret data as code automatically. On REA `025272ee2` using the same installed provider and public stdio MCP, explicit `procedure_callees({procedure:"0x1000003e0"})` returned `[]` with `relationship_coverage: complete`; the retained graph-source summary omitted the node's `kind`. In the same session `analyze_function` at that address rejected it because the Mach-O section declares no instructions. The live path nevertheless expanded that address and returned `not_reached` with complete coverage. The agent sees conflicting practical implications from the two workflows without the graph node classification in the relationship Evidence. For a separate negative control, I rebuilt the same authored source with the destination changed from `bl _goal; ret` to `nop; ret` (SHA-256 `ce7eab76b09d27ee9843c07f7c6b178bd55873269dd47682e2591a33ad69e0e2`). Direct forced-code disassembly confirmed those instructions. Kuna's `functions` rows and `edges` rows were **identical** to the original fixture's graph, including the `data` node and `_main`'s call to it. REA returned identical normalized `procedure_callees` and `trace_call_path` results and coverage for the two fixtures; subject digests and graph source paths/digests differ. The original fixture's forced-code disassembly contains the call; the control does not. Both targets were unchanged during analysis and neither was executed. This is static decoding evidence for two deliberately constructed fixtures, not a runtime claim or frequency estimate. This is an actionable boundary, but not a complete solution to the issue. The current parser retains `node.kind`, while `KunaReferenceQueries` makes coverage depend on `hasIndirectCalls` and omits `kind` from the recorded source summary. A path expansion of a bodyless provider node is a specific place to preserve the provider's classification and uncertainty; unvisited graph nodes and all callers need separate reasoning. Every Mach-O graph here also contains uncalled data nodes such as the header, so downgrading all graphs merely because any data row exists would be overly broad. Conversely, the identical rows show a graph-only consumer cannot determine which of these two bodies contains a call. Preserve observed edges, distinguish graph retrieval from discovery, and retain the existing conservative treatment of incomplete evidence; no code change or general discovery guarantee is proposed here. A further real Ghidra 12.1.4/JDK 21 stdio MCP control on both exact files returned the two-hop static path on the original and `not_reached` on the `nop` variant. Full advertised output schemas were used, and both target hashes remained unchanged. This corroborates the differing static instructions; neither fixture establishes execution or general engine completeness.
Author
Owner

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

Narrow experiment: useful evidence, not a complete fix

In an isolated, uncommitted REA experiment on main 6e9ee97a, I kept Kuna's observed graph edges, included the parsed node kind in its source summary, and changed only a data node's outgoing coverage from complete to unknown. This deliberately reuses the existing coverage field to test the consequences; it does not yet distinguish observed-graph retrieval from discovery and is not a proposed final contract.

With real Kuna 1.986 and full-schema stdio MCP on the two fixtures above:

  • The bodyless node's direct procedure_callees returned unknown with its provider classification; the ordinary _direct_goal node remained complete.
  • Both _main → _goal searches became unknown; the known direct positive remained reached. The backward _goal → _main search still reported not_reached, because that traversal never expands the data-labeled node. This targeted change alone cannot resolve the issue.
  • On the separate shortest-path fixture, the observed three-hop Kuna path remained reached but became truncated with a residual uncertainty at the bodyless node; Ghidra still found the separate two-hop static path. The input hashes were unchanged and neither target was executed.

The persistence control also constrains the design. A baseline Kuna session saved a snapshot containing the old not_reached Evidence, with zero primitive and zero workflow cache entries. The experiment reopened that snapshot and produced a fresh unknown result while preserving the original historical record. Because this exploratory patch intentionally changed neither provider nor workflow profile, the two different conclusions had the same profile digest. A production semantic change needs an explicit identity/revision decision covering both primitive relationship outputs and composed paths, alongside a clear historical-Evidence story; this experiment does not implement that decision or a migration. The original snapshot and target hashes remained unchanged.

The observed distinction matters more than this patch: the existing documented coverage field describes retrieval of the provider-observed set, while the missing question is discovery of possible calls. Replacing one with the other would discard that separation. A provider-neutral discovery/search-scope fact and explicit unknowns may be cleaner, but still need tests for incoming relationships, positive shortest paths, consumers, snapshots and full/compact clients. These are three synthetic static fixtures on one host, not a runtime or prevalence claim.

<!-- gh-comment-id:6554018057 --> @morluto commented on GitHub (Nov 1, 2026): ### Narrow experiment: useful evidence, not a complete fix In an isolated, uncommitted REA experiment on main `6e9ee97a`, I kept Kuna's observed graph edges, included the parsed node `kind` in its source summary, and changed **only a `data` node's outgoing coverage** from `complete` to `unknown`. This deliberately reuses the existing coverage field to test the consequences; it does not yet distinguish observed-graph retrieval from discovery and is not a proposed final contract. With real Kuna 1.986 and full-schema stdio MCP on the two fixtures above: - The bodyless node's direct `procedure_callees` returned `unknown` with its provider classification; the ordinary `_direct_goal` node remained `complete`. - Both `_main → _goal` searches became `unknown`; the known direct positive remained `reached`. The **backward** `_goal → _main` search still reported `not_reached`, because that traversal never expands the data-labeled node. This targeted change alone cannot resolve the issue. - On the separate [shortest-path fixture](https://github.com/morluto/rea/issues/8362#issuecomment-6548443750), the observed three-hop Kuna path remained `reached` but became `truncated` with a residual uncertainty at the bodyless node; Ghidra still found the separate two-hop static path. The input hashes were unchanged and neither target was executed. The persistence control also constrains the design. A baseline Kuna session saved a snapshot containing the old `not_reached` Evidence, with zero primitive and zero workflow cache entries. The experiment reopened that snapshot and produced a fresh `unknown` result while preserving the original historical record. Because this exploratory patch intentionally changed **neither provider nor workflow profile**, the two different conclusions had the same profile digest. A production semantic change needs an explicit identity/revision decision covering both primitive relationship outputs and composed paths, alongside a clear historical-Evidence story; this experiment does not implement that decision or a migration. The original snapshot and target hashes remained unchanged. The observed distinction matters more than this patch: the existing documented coverage field describes retrieval of the provider-observed set, while the missing question is discovery of possible calls. Replacing one with the other would discard that separation. A provider-neutral discovery/search-scope fact and explicit unknowns may be cleaner, but still need tests for incoming relationships, positive shortest paths, consumers, snapshots and full/compact clients. These are three synthetic static fixtures on one host, not a runtime or prevalence claim.
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#6563
No description provided.