[GH-ISSUE #8235] [Bug] Paged native call graphs order depth 10 before depth 2 #6504

Open
opened 2026-11-01 21:11:43 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

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

Area

MCP or agent integration

Observed behavior

Paged get_call_graph views order the graph's numeric depth keys as text. A 20-function call chain produced the ordered levels 0, 1, 10, 11, ..., 19, 2, 3, ..., 9. A page of three therefore contains depths 0, 1 and 10; depth 2 appears on the fifth page. All rows remain retrievable and each retains its actual level.

Reproduction

  1. Build a disposable arm64 Mach-O containing 20 distinct noinline functions audit_0 through audit_19, each calling the next, plus an unrelated function. Open it through real REA MCP with Ghidra 12.1.4 or Kuna 1.986.
  2. Call get_call_graph({"address":"_audit_0","direction":"forward","detail":"summary"}). Both providers returned 20 graph rows in the order above.
  3. On Ghidra's retained parent, call inspect_analysis_view with view: {"kind":"native-observation","offset":0,"limit":3}, then follow next_offset. The first page has levels 0,1,10; the page at offset 12 has 2,3,4. The last page is exhausted; all 20 rows were present.

The Ghidra complete result held graph keys 0 through 19; the view reorders them. REA traversed the providers' observed call relations and did not execute or change the target. Fixture SHA-256 was unchanged. NOT_ENOUGH_INFO: standalone fixture is not attached, and no autonomous agent behavior was measured.

Expected behavior

For production graph levels that represent breadth-first numeric depth, a small first page should expose nearer levels before deeper levels, while preserving stable row identity and deterministic pagination. If other historical Evidence can contain nonnumeric level keys, define their treatment explicitly. Preserve the existing complete graph, per-node caveats, and historical-view compatibility when deciding how to change ordering.

Impact and scope

An agent inspecting a bounded page must read through unrelated deeper levels to recover nearby callees. Page coverage and row data themselves were accurate in this test; no missing graph edges or semantic misclassification are claimed. This was observed with two real providers on one fixture; CLI, large graphs, changed view versions, and model success rates were not tested.

REA version

53a4ab78451a0654e9c3beb3d43a5e371a288fcc

Runtime and platform

Node 24.22.1, macOS 26.3 arm64; Ghidra 12.1.4 and Kuna 1.986.

Target and artifact context

Self-built arm64 Mach-O dylib, SHA-256 c025eb0e222a025941ec2ac4666db019029f7e24254d45fd2f953315b2228e67.

Interface

MCP

Earliest failure stage

Transport or result projection

Relevant output or evidence

offset: 0, limit: 3 returned levels 0,1,10, next_offset:3; offset: 12, limit: 3 returned 2,3,4. The current view owner deliberately sorts level keys by Unicode code point to make canonical row order independent of object insertion order. Existing tests also exercise nonnumeric keys, so preserve deterministic behavior rather than relying on insertion order.

Typed outcome or recovery expected

The complete retained graph and explicit depth values allow manual reconstruction today. Consider deterministic numeric-first ordering for canonical nonnegative depth keys, with a stable rule for other keys and versioned or otherwise safe handling of old page offsets.

Analysis or suspected cause

Source-derived: graph traversal emits numeric depth as string keys, while the view sorts those keys lexicographically. This changes navigation order rather than the underlying graph.

Additional context

Related #8200 concerns preserving call-site context, not depth ordering. Last known good version: NOT_ENOUGH_INFO.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8235 ### 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 MCP or agent integration ### Observed behavior Paged `get_call_graph` views order the graph's numeric depth keys as text. A 20-function call chain produced the ordered levels `0, 1, 10, 11, ..., 19, 2, 3, ..., 9`. A page of three therefore contains depths 0, 1 and 10; depth 2 appears on the fifth page. All rows remain retrievable and each retains its actual level. ### Reproduction 1. Build a disposable arm64 Mach-O containing 20 distinct `noinline` functions `audit_0` through `audit_19`, each calling the next, plus an unrelated function. Open it through real REA MCP with Ghidra 12.1.4 or Kuna 1.986. 2. Call `get_call_graph({"address":"_audit_0","direction":"forward","detail":"summary"})`. Both providers returned 20 graph rows in the order above. 3. On Ghidra's retained parent, call `inspect_analysis_view` with `view: {"kind":"native-observation","offset":0,"limit":3}`, then follow `next_offset`. The first page has levels `0,1,10`; the page at offset 12 has `2,3,4`. The last page is exhausted; all 20 rows were present. The Ghidra complete result held graph keys 0 through 19; the view reorders them. REA traversed the providers' observed call relations and did not execute or change the target. Fixture SHA-256 was unchanged. NOT_ENOUGH_INFO: standalone fixture is not attached, and no autonomous agent behavior was measured. ### Expected behavior For production graph levels that represent breadth-first numeric depth, a small first page should expose nearer levels before deeper levels, while preserving stable row identity and deterministic pagination. If other historical Evidence can contain nonnumeric level keys, define their treatment explicitly. Preserve the existing complete graph, per-node caveats, and historical-view compatibility when deciding how to change ordering. ### Impact and scope An agent inspecting a bounded page must read through unrelated deeper levels to recover nearby callees. Page coverage and row data themselves were accurate in this test; no missing graph edges or semantic misclassification are claimed. This was observed with two real providers on one fixture; CLI, large graphs, changed view versions, and model success rates were not tested. ### REA version `53a4ab78451a0654e9c3beb3d43a5e371a288fcc` ### Runtime and platform Node 24.22.1, macOS 26.3 arm64; Ghidra 12.1.4 and Kuna 1.986. ### Target and artifact context Self-built arm64 Mach-O dylib, SHA-256 `c025eb0e222a025941ec2ac4666db019029f7e24254d45fd2f953315b2228e67`. ### Interface MCP ### Earliest failure stage Transport or result projection ### Relevant output or evidence `offset: 0, limit: 3` returned levels `0,1,10`, `next_offset:3`; `offset: 12, limit: 3` returned `2,3,4`. [The current view owner](https://github.com/morluto/rea/blob/53a4ab78451a0654e9c3beb3d43a5e371a288fcc/src/domain/analysisView/nativeGraphView.ts#L59) deliberately sorts level keys by Unicode code point to make canonical row order independent of object insertion order. Existing tests also exercise nonnumeric keys, so preserve deterministic behavior rather than relying on insertion order. ### Typed outcome or recovery expected The complete retained graph and explicit depth values allow manual reconstruction today. Consider deterministic numeric-first ordering for canonical nonnegative depth keys, with a stable rule for other keys and versioned or otherwise safe handling of old page offsets. ### Analysis or suspected cause Source-derived: graph traversal emits numeric depth as string keys, while the view sorts those keys lexicographically. This changes navigation order rather than the underlying graph. ### Additional context Related #8200 concerns preserving call-site context, not depth ordering. Last known good version: NOT_ENOUGH_INFO.
Author
Owner

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

Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.

<!-- gh-comment-id:6538805008 --> @morluto commented on GitHub (Oct 31, 2026): Looping in @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 for visibility on the Ghidra, Kuna, and REA tool-design investigation.
Author
Owner

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

Real-provider validation of the exact open PR #8268 head 88bc12c6626dad6a1c9d37886b230ec85794f7e3, macOS arm64, Ghidra 12.1.4 and Kuna 1.986. Using the original unexecuted 20-level Mach-O fixture, each real MCP session returned summary levels 0–19 in numeric order. Following every inspect_analysis_view page with limit 3 returned all 20 levels exactly once; each row's address and calls matched the corresponding complete graph. Both sessions closed and the target hash stayed unchanged. This is one fixture/host, not the missing Windows MCP test.

There is a concrete cross-version offset compatibility question. I used main e6d061897 and real Ghidra to retain the graph, read its first page (0,1,10, next offset 3), and export the Evidence bundle. A fresh server on the PR head imported that exact bundle and continued from offset 3. The resulting combined levels were 0,1,10,3,4,...,19: level 2 was skipped and level 10 appeared twice. Restarting pagination at offset 0 on the new version returns all rows correctly. The test preserves the same parent Evidence identity; it does not establish how often clients persist offsets across upgrades.

The ordering fix is effective within one version. Please decide/document the cross-version cursor contract or version/reject stale continuation state if appropriate; the current raw offset carries no ordering-version information. Avoid claiming old offsets remain equivalent across the change. No provider or target mutation is involved in the replay.

<!-- gh-comment-id:6540822100 --> @morluto commented on GitHub (Oct 31, 2026): Real-provider validation of the exact open [PR #8268](https://github.com/morluto/rea/pull/8268) head `88bc12c6626dad6a1c9d37886b230ec85794f7e3`, macOS arm64, Ghidra 12.1.4 and Kuna 1.986. Using the original unexecuted 20-level Mach-O fixture, each real MCP session returned summary levels 0–19 in numeric order. Following every `inspect_analysis_view` page with limit 3 returned all 20 levels exactly once; each row's address and calls matched the corresponding complete graph. Both sessions closed and the target hash stayed unchanged. This is one fixture/host, not the missing Windows MCP test. There is a concrete cross-version offset compatibility question. I used main `e6d061897` and real Ghidra to retain the graph, read its first page (`0,1,10`, next offset 3), and export the Evidence bundle. A fresh server on the PR head imported that exact bundle and continued from offset 3. The resulting combined levels were `0,1,10,3,4,...,19`: level 2 was skipped and level 10 appeared twice. Restarting pagination at offset 0 on the new version returns all rows correctly. The test preserves the same parent Evidence identity; it does not establish how often clients persist offsets across upgrades. The ordering fix is effective within one version. Please decide/document the cross-version cursor contract or version/reject stale continuation state if appropriate; the current raw offset carries no ordering-version information. Avoid claiming old offsets remain equivalent across the change. No provider or target mutation is involved in the replay.
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#6504
No description provided.