[GH-ISSUE #8282] [Bug] Cached native value traces cite source Evidence absent from exported bundles #6521

Closed
opened 2026-11-01 21:11:53 +00:00 by bsakaguchi · 16 comments
Owner

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

Before submitting

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

Area

Evidence, artifacts, or reconstruction

Observed behavior

After the same Ghidra function analyses were replayed from the session's snapshot cache, trace_native_values returned per-procedure, node and edge evidence_id values absent from the exported session bundle. The trace's top-level evidence_links still pointed to the retained original function dossiers. Importing the bundle into a fresh server and looking up the original source succeeded; looking up the ID cited by a replayed trace node failed with evidence_integrity_mismatch, reason: missing.

Reproduction

Using real stdio MCP on a source-owned arm64 Mach-O containing _evaluate and its direct callee:

  1. open_binary with Ghidra.
  2. Call trace_native_values for _evaluate with max_depth: 1, max_functions: 4, max_call_sites: 20, max_nodes: 100, max_edges: 200, limit: 100, offset: 0. Save the source IDs from normalized_result.procedures.
  3. Call it again with identical parameters except limit: 3. Its source IDs differ, despite the same function addresses and matching p-code node payloads. A third call repeating step 2 uses the same changed IDs as step 3; pagination is therefore not required to trigger it.
  4. export_evidence_bundle before close_binary. In a fresh server import that bundle and call inspect_analysis_view with source: {kind: "retained-evidence", evidence_id: <source ID>} and view: {kind: "summary"}. The first trace's source ID succeeds; the later trace's ID fails as missing. The exported bundle contains the original IDs and not the replay IDs, while the later trace's top-level links cite the original IDs.

One control walked seven three-node pages. Together they contained the same 19 node IDs and 17 edges as the unpaged result when compared excluding the per-item Evidence ID; this finding concerns provenance, not a claimed missing graph row. Reproduced in two fresh Ghidra sessions on the same fixture.

Expected behavior

Every per-item source Evidence ID should resolve to the actual retained or exported observation that supports it, including snapshot-cache replay. The top-level trace links, per-item IDs, and bundle closure should agree without discarding replay limitations. Preserve cold, warm, pagination, and offline bundle workflows; exact behavior for other providers is untested.

Impact and scope

An agent cannot follow a replayed node or procedure's cited source through the exported bundle, even though that trace returned successfully. This reproduction does not establish incorrect p-code or missing results. CLI, other providers, imported snapshots, mutation and cancellation are untested.

REA version

b43c329df779708e43ae297f498a844e45d9c923 (built source). The cited producer, replay and workflow source files are unchanged at origin/main 23de10bb2849cdce8ddbe70504aa7cc57de75a98; that later revision was not runtime tested.

Runtime and platform

Node 24.22.1, macOS 26.3 arm64, Ghidra 12.1.4, JDK 21, MCP compact output schema profile.

Target and artifact context

Self-built arm64 Mach-O executable, SHA-256 ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d. Digest unchanged. It was analyzed statically and not executed.

Interface

MCP

Earliest failure stage

Artifact or evidence registration

Relevant output or evidence

Cold trace source: ev_66e25d96dff81b3518ee782ff4a8d49fffd4fc79aab52fee926e9cdaee5ac8b9 (present in bundle; view succeeds).

Replay trace source for the same procedure: ev_8105433b83d8f9998ad039d436cf83378c1ebb96e9bc00145c94314aeb080eca (absent in bundle; view fails as missing). Those IDs identify this fixture and session configuration only.

Analysis or suspected cause

Source-derived hypothesis: traceNativeValues constructs a fresh source Evidence ID from each execution rather than using its authenticated evidenceId. AnalysisSnapshotCache.lookup returns the original evidenceId while adding a replay limitation, so reconstructing a new ID from that modified observation can differ from the retained record. The composed workflow records the execution's retained identity and sources. Confirm the exact producing boundary and assess other consumers before selecting a fix.

Additional context

Minimal fixture shape: a noinline evaluate(struct record *r) conditionally calls noinline adjust((int)r->id); adjust reads a volatile global. Existing real-provider E2E checks graph and binding semantics but a cold/warm source-closure assertion is a proposed regression. No runtime execution or performance measurement was performed.

cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0

Kuna 1.988 cold and repeated source controls

On macOS arm64 with official Kuna 1.988 and a source-owned x86-64 ELF, separate REA #8651 head c103de06 returned an unavailable-def-use unknown but cited an unretained per-procedure source ID on the first and repeated trace_native_values calls in compact and full stdio MCP profiles. The top-level Evidence links were empty; following that source with inspect_analysis_view returned evidence_integrity_mismatch with reason: missing. On #8384 head a20c186e, the same trace retained and linked the source and the summary view resolved while the unknown remained. The unexecuted target SHA-256 d3baa5cf385b68e3a8de02ed0884d9c9e781bd2c6b63201250635e4dc37655e8 was unchanged. The #8384 branch predates the 1.988 verification-policy update and labeled the release unverified. This control used the live session bundle; it did not test offline export/import for this fixture.

Both PRs independently used workflow revision 2 for distinct trace changes. #8651 now adds a separate value_flow_limitations commitment instead; integration must preserve #8384's ownership revision as well. A combined experimental checkout with both commitments preserved passed these live controls, but it is not a merged implementation.

Ghidra offline handoff control

On built REA main 9ebbe67e05af08b567e215340da993c08dae378f, Ghidra 12.1.4, and a separate self-built arm64 Mach-O, repeating trace_native_values and exporting its Evidence reproduced the missing replay source in both compact and full stdio MCP profiles. After importing the bundle into a fresh server without opening a binary, the trace record was present but its repeated-trace procedure source was absent and its summary lookup failed with evidence_integrity_mismatch. The top-level trace still linked the retained original source; the trace retained its aliasing limitation.

In a separate checkout of #8384 head a20c186eb81785c96267f33cec3929ea5aeb8130, the same real-provider workflow retained both the trace and the cited source, and the offline summary lookup succeeded in both profiles. The older PR checkout was tested independently, not merged with current main. The target was analyzed without execution and its SHA-256 64acc2d130f29358567f75185e430de7a457a2d2cd0f0cbf22dbc379a4cac2e7 remained unchanged. This control does not establish behavior for other providers or targets.

Combined replay and value-trace control

A disposable, uncommitted merge of #8384 head a20c186eb81785c96267f33cec3929ea5aeb8130 and #8734 head fec97adc1225bbfa02b425af732e2609780948d4 built successfully. Against real Ghidra 12.1.4 in both MCP profiles, the repeated value-trace offline handoff retained and resolved the original procedure source, retained the trace and aliasing limitation, and the separate repeated pseudocode handoff reported a complete retained closure containing its original source after import without an open binary. Both static fixture digests were unchanged. These controls exercise two distinct fixtures and workflows; they do not establish full integration coverage or behavior after either PR changes.

Originally created by @morluto on GitHub (Oct 31, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8282 ### Before submitting - [x] I searched open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior After the same Ghidra function analyses were replayed from the session's snapshot cache, `trace_native_values` returned per-procedure, node and edge `evidence_id` values absent from the exported session bundle. The trace's top-level `evidence_links` still pointed to the retained original function dossiers. Importing the bundle into a fresh server and looking up the original source succeeded; looking up the ID cited by a replayed trace node failed with `evidence_integrity_mismatch`, `reason: missing`. ### Reproduction Using real stdio MCP on a source-owned arm64 Mach-O containing `_evaluate` and its direct callee: 1. `open_binary` with Ghidra. 2. Call `trace_native_values` for `_evaluate` with `max_depth: 1`, `max_functions: 4`, `max_call_sites: 20`, `max_nodes: 100`, `max_edges: 200`, `limit: 100`, `offset: 0`. Save the source IDs from `normalized_result.procedures`. 3. Call it again with identical parameters except `limit: 3`. Its source IDs differ, despite the same function addresses and matching p-code node payloads. A third call repeating step 2 uses the same changed IDs as step 3; pagination is therefore not required to trigger it. 4. `export_evidence_bundle` before `close_binary`. In a fresh server import that bundle and call `inspect_analysis_view` with `source: {kind: "retained-evidence", evidence_id: <source ID>}` and `view: {kind: "summary"}`. The first trace's source ID succeeds; the later trace's ID fails as missing. The exported bundle contains the original IDs and not the replay IDs, while the later trace's top-level links cite the original IDs. One control walked seven three-node pages. Together they contained the same 19 node IDs and 17 edges as the unpaged result when compared excluding the per-item Evidence ID; this finding concerns provenance, not a claimed missing graph row. Reproduced in two fresh Ghidra sessions on the same fixture. ### Expected behavior Every per-item source Evidence ID should resolve to the actual retained or exported observation that supports it, including snapshot-cache replay. The top-level trace links, per-item IDs, and bundle closure should agree without discarding replay limitations. Preserve cold, warm, pagination, and offline bundle workflows; exact behavior for other providers is untested. ### Impact and scope An agent cannot follow a replayed node or procedure's cited source through the exported bundle, even though that trace returned successfully. This reproduction does not establish incorrect p-code or missing results. CLI, other providers, imported snapshots, mutation and cancellation are untested. ### REA version `b43c329df779708e43ae297f498a844e45d9c923` (built source). The cited producer, replay and workflow source files are unchanged at `origin/main` `23de10bb2849cdce8ddbe70504aa7cc57de75a98`; that later revision was not runtime tested. ### Runtime and platform Node 24.22.1, macOS 26.3 arm64, Ghidra 12.1.4, JDK 21, MCP compact output schema profile. ### Target and artifact context Self-built arm64 Mach-O executable, SHA-256 `ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d`. Digest unchanged. It was analyzed statically and not executed. ### Interface MCP ### Earliest failure stage Artifact or evidence registration ### Relevant output or evidence Cold trace source: `ev_66e25d96dff81b3518ee782ff4a8d49fffd4fc79aab52fee926e9cdaee5ac8b9` (present in bundle; view succeeds). Replay trace source for the same procedure: `ev_8105433b83d8f9998ad039d436cf83378c1ebb96e9bc00145c94314aeb080eca` (absent in bundle; view fails as missing). Those IDs identify this fixture and session configuration only. ### Analysis or suspected cause Source-derived hypothesis: [`traceNativeValues`](https://github.com/morluto/rea/blob/b43c329df779708e43ae297f498a844e45d9c923/src/application/native/NativeValueTrace.ts) constructs a fresh source Evidence ID from each execution rather than using its authenticated `evidenceId`. [`AnalysisSnapshotCache.lookup`](https://github.com/morluto/rea/blob/b43c329df779708e43ae297f498a844e45d9c923/src/application/binary/AnalysisSnapshotCache.ts) returns the original `evidenceId` while adding a replay limitation, so reconstructing a new ID from that modified observation can differ from the retained record. The composed workflow records the execution's retained identity and sources. Confirm the exact producing boundary and assess other consumers before selecting a fix. ### Additional context Minimal fixture shape: a noinline `evaluate(struct record *r)` conditionally calls noinline `adjust((int)r->id)`; `adjust` reads a volatile global. Existing real-provider E2E checks graph and binding semantics but a cold/warm source-closure assertion is a proposed regression. No runtime execution or performance measurement was performed. cc @gensokyo-dev @kaoru0822-kitauji @N0zoM1z0 ### Kuna 1.988 cold and repeated source controls On macOS arm64 with official Kuna 1.988 and a source-owned x86-64 ELF, separate REA #8651 head `c103de06` returned an unavailable-def-use unknown but cited an unretained per-procedure source ID on the first and repeated `trace_native_values` calls in compact and full stdio MCP profiles. The top-level Evidence links were empty; following that source with `inspect_analysis_view` returned `evidence_integrity_mismatch` with `reason: missing`. On #8384 head `a20c186e`, the same trace retained and linked the source and the summary view resolved while the unknown remained. The unexecuted target SHA-256 `d3baa5cf385b68e3a8de02ed0884d9c9e781bd2c6b63201250635e4dc37655e8` was unchanged. The #8384 branch predates the 1.988 verification-policy update and labeled the release unverified. This control used the live session bundle; it did not test offline export/import for this fixture. Both PRs independently used workflow revision 2 for distinct trace changes. #8651 now adds a separate `value_flow_limitations` commitment instead; integration must preserve #8384's ownership revision as well. A combined experimental checkout with both commitments preserved passed these live controls, but it is not a merged implementation. ### Ghidra offline handoff control On built REA main `9ebbe67e05af08b567e215340da993c08dae378f`, Ghidra 12.1.4, and a separate self-built arm64 Mach-O, repeating `trace_native_values` and exporting its Evidence reproduced the missing replay source in both compact and full stdio MCP profiles. After importing the bundle into a fresh server without opening a binary, the trace record was present but its repeated-trace procedure source was absent and its summary lookup failed with `evidence_integrity_mismatch`. The top-level trace still linked the retained original source; the trace retained its aliasing limitation. In a separate checkout of #8384 head `a20c186eb81785c96267f33cec3929ea5aeb8130`, the same real-provider workflow retained both the trace and the cited source, and the offline summary lookup succeeded in both profiles. The older PR checkout was tested independently, not merged with current main. The target was analyzed without execution and its SHA-256 `64acc2d130f29358567f75185e430de7a457a2d2cd0f0cbf22dbc379a4cac2e7` remained unchanged. This control does not establish behavior for other providers or targets. ### Combined replay and value-trace control A disposable, uncommitted merge of #8384 head `a20c186eb81785c96267f33cec3929ea5aeb8130` and #8734 head `fec97adc1225bbfa02b425af732e2609780948d4` built successfully. Against real Ghidra 12.1.4 in both MCP profiles, the repeated value-trace offline handoff retained and resolved the original procedure source, retained the trace and aliasing limitation, and the separate repeated pseudocode handoff reported a complete retained closure containing its original source after import without an open binary. Both static fixture digests were unchanged. These controls exercise two distinct fixtures and workflows; they do not establish full integration coverage or behavior after either PR changes.
Author
Owner

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

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

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

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

Existing real-provider test coverage

The repository already has a meaningful unmocked CLI + stdio MCP Ghidra test in scripts/lib/native-value-e2e.mjs: it validates real argument/parameter/return edges, checks CLI/MCP graph equality, and confirms the trace itself is in the session Evidence bundle. For per-node source IDs, it currently asserts only the ev_... shape; the later bundle check asserts membership for the trace, separately requested function Evidence, and comparison, not each graph node/procedure/edge source ID. The trace is run once in each fresh CLI/MCP session before those checks, so the cache-replay behavior in this report is not exercised.

Proposed real E2E regression: repeat the trace in the same MCP session to exercise replay, then resolve every nonempty per-item source ID from the exported bundle and confirm the retained source supports the node or edge. Keep the original cold CLI/MCP graph and binding assertions. This is a source inspection of the existing assertions plus the real reproduction above; no new test was run as part of this comment.

<!-- gh-comment-id:6541568993 --> @morluto commented on GitHub (Oct 31, 2026): ### Existing real-provider test coverage The repository already has a meaningful unmocked CLI + stdio MCP Ghidra test in [`scripts/lib/native-value-e2e.mjs`](https://github.com/morluto/rea/blob/b43c329df779708e43ae297f498a844e45d9c923/scripts/lib/native-value-e2e.mjs): it validates real argument/parameter/return edges, checks CLI/MCP graph equality, and confirms the trace itself is in the session Evidence bundle. For per-node source IDs, it currently asserts only the `ev_...` shape; the later bundle check asserts membership for the trace, separately requested function Evidence, and comparison, not each graph node/procedure/edge source ID. The trace is run once in each fresh CLI/MCP session before those checks, so the cache-replay behavior in this report is not exercised. Proposed real E2E regression: repeat the trace in the same MCP session to exercise replay, then resolve every nonempty per-item source ID from the exported bundle and confirm the retained source supports the node or edge. Keep the original cold CLI/MCP graph and binding assertions. This is a source inspection of the existing assertions plus the real reproduction above; no new test was run as part of this comment.
Author
Owner

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

Additional real Ghidra MCP call-order control on the same fixture and b43c329: in one session I called complete analyze_function(_evaluate), inspect_native_api, trace_feature, get_call_graph, trace_call_path, and trace_native_values, then repeated the sequence and exported the bundle. All calls succeeded; the target hash was unchanged.

The second direct dossier received a different Evidence ID with a snapshot-replay limitation, and both direct dossier records were present in the bundle. Because the second dossier was independently requested before the second value trace, its newly recorded ID also happened to satisfy one of that trace's per-procedure citations. The other warm traced procedure's ID was still missing from the bundle; its top-level source link pointed to the retained original. This is a concrete way an extra direct request can mask part of the closure defect, so a regression should test the trace-only case as well as mixed call order.

For these particular calls, every ID present in the API, feature, call-graph and call-path responses appeared in the same exported bundle; this is a narrow negative control, not proof that those workflows or providers have complete closure in general. The first exploratory attempt passed an invalid detail argument to inspect_native_api; the corrected run omitted it and is the one summarized here. No runtime execution occurred.

<!-- gh-comment-id:6542089001 --> @morluto commented on GitHub (Oct 31, 2026): Additional real Ghidra MCP call-order control on the same fixture and `b43c329`: in one session I called complete `analyze_function(_evaluate)`, `inspect_native_api`, `trace_feature`, `get_call_graph`, `trace_call_path`, and `trace_native_values`, then repeated the sequence and exported the bundle. All calls succeeded; the target hash was unchanged. The second direct dossier received a different Evidence ID with a snapshot-replay limitation, and both direct dossier records were present in the bundle. Because the second dossier was independently requested before the second value trace, its newly recorded ID also happened to satisfy one of that trace's per-procedure citations. The other warm traced procedure's ID was still missing from the bundle; its top-level source link pointed to the retained original. This is a concrete way an extra direct request can mask part of the closure defect, so a regression should test the trace-only case as well as mixed call order. For these particular calls, every ID present in the API, feature, call-graph and call-path responses appeared in the same exported bundle; this is a narrow negative control, not proof that those workflows or providers have complete closure in general. The first exploratory attempt passed an invalid `detail` argument to `inspect_native_api`; the corrected run omitted it and is the one summarized here. No runtime execution occurred.
Author
Owner

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

Durable snapshot control on the same self-owned, unexecuted Mach-O, real REA b43c329 / Ghidra 12.1.4 MCP:

  1. A fresh session traced _evaluate with limit:100; its two procedure Evidence IDs were present. close_binary(snapshot_path:<new path>) succeeded with two primitive entries, one workflow entry and three Evidence records.
  2. A fresh MCP server reopened that exact target/provider/snapshot and requested the same trace with limit:3. It returned successfully with a snapshot-replay limitation, three nodes and next_offset:3. Both procedure-level IDs differed from the original IDs; its top-level evidence_links still named the original retained dossiers.
  3. Export the second session's Evidence bundle and import it in a third, target-free MCP server. inspect_analysis_view succeeded for both original procedure IDs and returned missing-Evidence errors for both IDs cited by the replayed trace. The exported bundle contained the original linked IDs and neither replayed procedure ID.

The original snapshot hash was unchanged across reopening and the target hash stayed unchanged; no target was executed. This extends the earlier in-session warm-cache reproduction to an explicitly saved and imported REA snapshot. It does not prove whether an independent live provider process started during the second session or cover other provider/version combinations. A future real-provider regression should include both in-session reuse and cross-session snapshot replay, then resolve each cited per-item ID offline.

<!-- gh-comment-id:6542097500 --> @morluto commented on GitHub (Oct 31, 2026): Durable snapshot control on the same self-owned, unexecuted Mach-O, real REA `b43c329` / Ghidra 12.1.4 MCP: 1. A fresh session traced `_evaluate` with `limit:100`; its two procedure Evidence IDs were present. `close_binary(snapshot_path:<new path>)` succeeded with two primitive entries, one workflow entry and three Evidence records. 2. A fresh MCP server reopened that exact target/provider/snapshot and requested the same trace with `limit:3`. It returned successfully with a snapshot-replay limitation, three nodes and `next_offset:3`. Both procedure-level IDs differed from the original IDs; its top-level `evidence_links` still named the original retained dossiers. 3. Export the second session's Evidence bundle and import it in a third, target-free MCP server. `inspect_analysis_view` succeeded for both original procedure IDs and returned missing-Evidence errors for both IDs cited by the replayed trace. The exported bundle contained the original linked IDs and neither replayed procedure ID. The original snapshot hash was unchanged across reopening and the target hash stayed unchanged; no target was executed. This extends the earlier in-session warm-cache reproduction to an explicitly saved and imported REA snapshot. It does not prove whether an independent live provider process started during the second session or cover other provider/version combinations. A future real-provider regression should include both in-session reuse and cross-session snapshot replay, then resolve each cited per-item ID offline.
Author
Owner

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

Exact-request control for the saved-snapshot reproduction: after saving a limit:100, offset:0 trace and reopening its snapshot in a fresh server, repeating that identical request returned 19 nodes and 17 edges matching the original graph payload when per-item Evidence IDs were excluded. It still cited two new per-procedure IDs absent from the exported bundle. Both original top-level source links were present and both original procedure IDs resolved in a third offline server; both exact-replay IDs failed lookup. A subsequent limit:3 trace cited the same missing IDs.

So changing page parameters is not necessary for the saved-snapshot failure. The replay limitation reported that the underlying analyze_function results came from a local snapshot; this observation does not independently establish process-launch behavior. Original target and snapshot hashes were unchanged. The initial test script had a syntax error before connecting and was corrected; only the successful run is reported.

<!-- gh-comment-id:6542148145 --> @morluto commented on GitHub (Oct 31, 2026): Exact-request control for the saved-snapshot reproduction: after saving a `limit:100, offset:0` trace and reopening its snapshot in a fresh server, repeating that **identical** request returned 19 nodes and 17 edges matching the original graph payload when per-item Evidence IDs were excluded. It still cited two new per-procedure IDs absent from the exported bundle. Both original top-level source links were present and both original procedure IDs resolved in a third offline server; both exact-replay IDs failed lookup. A subsequent `limit:3` trace cited the same missing IDs. So changing page parameters is not necessary for the saved-snapshot failure. The replay limitation reported that the underlying `analyze_function` results came from a local snapshot; this observation does not independently establish process-launch behavior. Original target and snapshot hashes were unchanged. The initial test script had a syntax error before connecting and was corrected; only the successful run is reported.
Author
Owner

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

Resave control with the same REA b43c329 / Ghidra 12.1.4 fixture: I reopened the previously saved snapshot, repeated the exact value trace, and closed the session with a new snapshot_path. The save succeeded (2 primitive entries, 1 workflow entry, 4 Evidence records). The new snapshot contained both the original cold trace with resolvable procedure IDs and a retained replay trace whose two procedure IDs were absent from its own Evidence records; that replay trace's top-level evidence_links still named the two retained originals.

A new MCP server opened the new snapshot successfully and repeated the trace. It again returned the same two replay procedure IDs; inspect_analysis_view on each returned a missing-Evidence error. Export from this reopened session retained the same four records. This checks actual save/reopen behavior and the records embedded in that snapshot, not an assertion that general snapshot validation promises to recursively inspect every nested identifier. The original snapshot and target SHA-256 remained unchanged, and the target was not executed.

Source-derived ownership detail: AnalysisSnapshotCache.lookup supplies the bound execution.evidenceId and adds the replay limitation; WorkflowEvidence collects that bound ID as a source link. NativeValueTrace separately constructs an Evidence object from the execution and uses its newly computed ID for procedure/node/edge citations. Those paths explain the differing identities in this case; a structural fix should preserve the retained source identity and the replay caveat without minting an unregistered citation. Include resave/reopen in the regression alongside the already reported in-session, original-snapshot and mixed-call controls. The named source files were unchanged at current origin/main 23de10b; that revision was not runtime-tested.

<!-- gh-comment-id:6542288909 --> @morluto commented on GitHub (Oct 31, 2026): Resave control with the same REA `b43c329` / Ghidra 12.1.4 fixture: I reopened the previously saved snapshot, repeated the exact value trace, and closed the session with a **new** `snapshot_path`. The save succeeded (2 primitive entries, 1 workflow entry, 4 Evidence records). The new snapshot contained both the original cold trace with resolvable procedure IDs and a retained replay trace whose two procedure IDs were absent from its own Evidence records; that replay trace's top-level `evidence_links` still named the two retained originals. A new MCP server opened the new snapshot successfully and repeated the trace. It again returned the same two replay procedure IDs; `inspect_analysis_view` on each returned a missing-Evidence error. Export from this reopened session retained the same four records. This checks actual save/reopen behavior and the records embedded in that snapshot, not an assertion that general snapshot validation promises to recursively inspect every nested identifier. The original snapshot and target SHA-256 remained unchanged, and the target was not executed. Source-derived ownership detail: `AnalysisSnapshotCache.lookup` supplies the bound `execution.evidenceId` and adds the replay limitation; `WorkflowEvidence` collects that bound ID as a source link. `NativeValueTrace` separately constructs an Evidence object from the execution and uses its newly computed ID for procedure/node/edge citations. Those paths explain the differing identities in this case; a structural fix should preserve the retained source identity and the replay caveat without minting an unregistered citation. Include resave/reopen in the regression alongside the already reported in-session, original-snapshot and mixed-call controls. The named source files were unchanged at current `origin/main` `23de10b`; that revision was not runtime-tested.
Author
Owner

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

A bounded explicit recovery works for this exact snapshot and selector history. In a fresh server reopened on the resaved snapshot, both procedure IDs in the replay trace initially failed inspect_analysis_view. Calling analyze_function({procedure:"_evaluate", detail:"complete"}) and analyze_function({procedure:"0x100000410", detail:"complete"}) returned the two previously missing IDs, respectively. Both original lookups then succeeded, and a subsequent export included the two newly retained dossier records. The supplied selectors match the original retained source-record parameters (name for the seed, address for the callee); the replayed observations carried the snapshot caveat. Target and reopened snapshot hashes remained unchanged; no target was executed.

This demonstrates a possible manual repair and why an extra dossier request can mask the defect. It is not a general guarantee: selector aliases, differing profiles, changed snapshots and other provider behavior were not tested. A regression should first check closure before any separate dossier requests, and can then exercise this recovery as a distinct control.

<!-- gh-comment-id:6542293058 --> @morluto commented on GitHub (Oct 31, 2026): A bounded explicit recovery works for this exact snapshot and selector history. In a fresh server reopened on the resaved snapshot, both procedure IDs in the replay trace initially failed `inspect_analysis_view`. Calling `analyze_function({procedure:"_evaluate", detail:"complete"})` and `analyze_function({procedure:"0x100000410", detail:"complete"})` returned the two previously missing IDs, respectively. Both original lookups then succeeded, and a subsequent export included the two newly retained dossier records. The supplied selectors match the original retained source-record parameters (name for the seed, address for the callee); the replayed observations carried the snapshot caveat. Target and reopened snapshot hashes remained unchanged; no target was executed. This demonstrates a possible manual repair and why an extra dossier request can mask the defect. It is not a general guarantee: selector aliases, differing profiles, changed snapshots and other provider behavior were not tested. A regression should first check closure **before** any separate dossier requests, and can then exercise this recovery as a distinct control.
Author
Owner

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

Offline source discovery and ambiguity control

Using the previously exported replay bundle, I tested a fresh target-free REA b43c329df779708e43ae297f498a844e45d9c923 MCP server. After import, binary_session reported open: false. Both replay trace procedure IDs still failed inspect_analysis_view as missing. The trace's two top-level evidence_links did resolve to retained analyze_function dossiers. Independently, get_evidence_bundle({detail:"summary", filters:{operation:"analyze_function", target_sha256, analysis_profile_digest, procedure_address}}) returned exactly one original dossier for each of the two addresses, and those IDs were the trace's top-level links. No provider was opened or re-run.

A second control imported the separately recovered bundle from the earlier explicit analyze_function test. There, the formerly missing IDs resolved, but the same target/profile/address filters returned two dossiers per address: original and subsequently retained replay IDs. Thus metadata discovery can help an analyst find the original linked sources offline in the first bundle, but address/profile equality alone does not select a unique record or repair an incorrect citation. Inspect the exact links and observations; do not silently substitute IDs or infer semantic equivalence from matching coordinates. Both bundle digests remained unchanged. This is a bounded manual recovery, not a fix for the producer's source-closure defect or a general proof that all traces contain uniquely attributable sources.

<!-- gh-comment-id:6544480229 --> @morluto commented on GitHub (Oct 31, 2026): ### Offline source discovery and ambiguity control Using the previously exported replay bundle, I tested a fresh target-free REA `b43c329df779708e43ae297f498a844e45d9c923` MCP server. After import, `binary_session` reported `open: false`. Both replay trace procedure IDs still failed `inspect_analysis_view` as missing. The trace's two top-level `evidence_links` did resolve to retained `analyze_function` dossiers. Independently, `get_evidence_bundle({detail:"summary", filters:{operation:"analyze_function", target_sha256, analysis_profile_digest, procedure_address}})` returned exactly one original dossier for each of the two addresses, and those IDs were the trace's top-level links. No provider was opened or re-run. A second control imported the separately recovered bundle from the earlier explicit `analyze_function` test. There, the formerly missing IDs resolved, but the same target/profile/address filters returned **two** dossiers per address: original and subsequently retained replay IDs. Thus metadata discovery can help an analyst find the original linked sources offline in the first bundle, but address/profile equality alone does not select a unique record or repair an incorrect citation. Inspect the exact links and observations; do not silently substitute IDs or infer semantic equivalence from matching coordinates. Both bundle digests remained unchanged. This is a bounded manual recovery, not a fix for the producer's source-closure defect or a general proof that all traces contain uniquely attributable sources.
Author
Owner

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

Rechecked the original public stdio MCP workflow on REA main a989c0e458c91af177e097abd7be0fd021b0401d with Ghidra 12.1.4. A cold value trace and two warm traces (including an exact repeat of the cold request) succeeded. The cold trace's first procedure cited ev_66e25d96…, while both warm traces cited ev_8105433b… for that same procedure; the warm trace's top-level links continued to cite the cold IDs.

After exporting the session Evidence and importing it into a fresh target-free server, the cold procedure ID resolved to its analyze_function view, but the warm procedure ID failed with reason: missing. This confirms the reported closure failure on that REA revision; it does not establish incorrect p-code, general behavior for other providers, or correctness of a proposed fix. The statically analyzed source-owned fixture's digest matched the prior report (ffad1b70…) after the run; it was not executed.

<!-- gh-comment-id:6545263809 --> @morluto commented on GitHub (Oct 31, 2026): Rechecked the original public stdio MCP workflow on REA main `a989c0e458c91af177e097abd7be0fd021b0401d` with Ghidra 12.1.4. A cold value trace and two warm traces (including an exact repeat of the cold request) succeeded. The cold trace's first procedure cited `ev_66e25d96…`, while both warm traces cited `ev_8105433b…` for that same procedure; the warm trace's top-level links continued to cite the cold IDs. After exporting the session Evidence and importing it into a fresh target-free server, the cold procedure ID resolved to its `analyze_function` view, but the warm procedure ID failed with `reason: missing`. This confirms the reported closure failure on that REA revision; it does not establish incorrect p-code, general behavior for other providers, or correctness of a proposed fix. The statically analyzed source-owned fixture's digest matched the prior report (`ffad1b70…`) after the run; it was not executed.
Author
Owner

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

Rechecked after #8309 on REA 2d5dec26c31662764c9adfe3ff996174901b8d49 with Ghidra 12.1.4 and the same unexecuted arm64 fixture. A cold full trace and warm repeat reported different first-procedure source IDs (ev_66e25d96… and ev_8105433b…). After export and import into a fresh target-free server, inspect_analysis_view resolved the cold source to analyze_function, while the warm source still failed with reason missing. The target SHA-256 remained unchanged. This checks the first procedure's source closure on this fixture, not every graph node; pagination completeness itself passed separately under #8283.

<!-- gh-comment-id:6545806890 --> @morluto commented on GitHub (Oct 31, 2026): Rechecked after #8309 on REA `2d5dec26c31662764c9adfe3ff996174901b8d49` with Ghidra 12.1.4 and the same unexecuted arm64 fixture. A cold full trace and warm repeat reported different first-procedure source IDs (`ev_66e25d96…` and `ev_8105433b…`). After export and import into a fresh target-free server, `inspect_analysis_view` resolved the cold source to `analyze_function`, while the warm source still failed with reason `missing`. The target SHA-256 remained unchanged. This checks the first procedure's source closure on this fixture, not every graph node; pagination completeness itself passed separately under #8283.
Author
Owner

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

I tested the suspected ownership boundary on REA 2d5dec26c31662764c9adfe3ff996174901b8d49 with a throwaway local experiment, not a proposed or submitted fix. In traceNativeValues, the experiment used execution.value.evidenceId for the cited source when present, falling back to the currently constructed ID when absent; no other source code was changed.

On the same real Ghidra 12.1.4 fixture and MCP workflow, the unmodified build's warm trace cited two distinct source IDs absent from its bundle. Both failed offline lookup after import. With the experiment, all unique IDs cited by the warm trace's procedures, nodes and edges were present in the bundle, both procedure IDs resolved offline to analyze_function, and the trace still carried the snapshot-replay limitation. The cold/warm trace topology and the tested page/node/edge-limit controls also passed; the target hash was unchanged, and it was not executed. Successful calls used SDK validation against the advertised compact schema.

Source inspection explains the contrast: BinarySession retains the original observation and returns its evidenceId; snapshot lookup carries the bound original ID and adds a replay limitation; traceNativeValues independently builds an Evidence record from that modified execution and uses its newly computed ID. The composed workflow separately links the retained original ID.

This experiment supports the diagnosis but is not a complete repair: the fallback still needs an explicit ownership/registration decision when evidenceId is absent, and imported snapshots, ambiguous bindings, cancellation/partial observations, alternate providers and all consumers need appropriate coverage. Do not assume that merely selecting a reconstructed ID makes it retained. The original worktree and main were not changed.

<!-- gh-comment-id:6545829686 --> @morluto commented on GitHub (Oct 31, 2026): I tested the suspected ownership boundary on REA `2d5dec26c31662764c9adfe3ff996174901b8d49` with a **throwaway local experiment**, not a proposed or submitted fix. In `traceNativeValues`, the experiment used `execution.value.evidenceId` for the cited source when present, falling back to the currently constructed ID when absent; no other source code was changed. On the same real Ghidra 12.1.4 fixture and MCP workflow, the unmodified build's warm trace cited two distinct source IDs absent from its bundle. Both failed offline lookup after import. With the experiment, all unique IDs cited by the warm trace's procedures, nodes and edges were present in the bundle, both procedure IDs resolved offline to `analyze_function`, and the trace still carried the snapshot-replay limitation. The cold/warm trace topology and the tested page/node/edge-limit controls also passed; the target hash was unchanged, and it was not executed. Successful calls used SDK validation against the advertised compact schema. Source inspection explains the contrast: `BinarySession` retains the original observation and returns its `evidenceId`; snapshot lookup carries the bound original ID and adds a replay limitation; `traceNativeValues` independently builds an Evidence record from that modified execution and uses its newly computed ID. The composed workflow separately links the retained original ID. This experiment supports the diagnosis but is **not a complete repair**: the fallback still needs an explicit ownership/registration decision when `evidenceId` is absent, and imported snapshots, ambiguous bindings, cancellation/partial observations, alternate providers and all consumers need appropriate coverage. Do not assume that merely selecting a reconstructed ID makes it retained. The original worktree and main were not changed.
Author
Owner

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

Extended the isolated source-ID experiment to an actual snapshot boundary. On REA 2d5dec26c31662764c9adfe3ff996174901b8d49, I saved a snapshot after a cold real-Ghidra trace, then used the same snapshot in separate fresh servers with the unmodified build and the one-line exploratory build from the previous comment. A different page request forced a composed trace over replayed sources. On unmodified main, both procedure IDs failed lookup in the live reopened session and after export/import into a target-free server. In the experiment, both resolved to retained analyze_function records in both places; the snapshot-replay caveat remained present, and the selected page's node IDs matched. The SDK validated successful responses against the compact advertised schema.

I repeated the reopen against an owned copy of the target at a different path with the same SHA-256. In the experiment, the new trace identified the caller-selected copy, while the two retained source records identified their original historical path and the same content digest. The baseline still cited missing IDs. This is a reason to preserve the original source record's provenance when linking it; a source path and the current target path need not be identical. The original snapshot and both target copies were unchanged and not executed. This remains a bounded experiment, not a complete proposed fix or proof for ambiguous/unbound snapshot identities, other providers, or cancellation.

<!-- gh-comment-id:6545848895 --> @morluto commented on GitHub (Oct 31, 2026): Extended the isolated source-ID experiment to an actual snapshot boundary. On REA `2d5dec26c31662764c9adfe3ff996174901b8d49`, I saved a snapshot after a cold real-Ghidra trace, then used the **same snapshot** in separate fresh servers with the unmodified build and the one-line exploratory build from the previous comment. A different page request forced a composed trace over replayed sources. On unmodified main, both procedure IDs failed lookup in the live reopened session and after export/import into a target-free server. In the experiment, both resolved to retained `analyze_function` records in both places; the snapshot-replay caveat remained present, and the selected page's node IDs matched. The SDK validated successful responses against the compact advertised schema. I repeated the reopen against an owned copy of the target at a different path with the same SHA-256. In the experiment, the new trace identified the caller-selected copy, while the two retained source records identified their original historical path and the same content digest. The baseline still cited missing IDs. This is a reason to preserve the original source record's provenance when linking it; a source path and the current target path need not be identical. The original snapshot and both target copies were unchanged and not executed. This remains a bounded experiment, not a complete proposed fix or proof for ambiguous/unbound snapshot identities, other providers, or cancellation.
Author
Owner

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

Follow-up: ambiguous snapshot provenance and the no-owner fallback

On REA 60149282fcfc05ac32fbc94434c107710120da6f I tested the previous one-line source-ID experiment in a new isolated worktree, using Ghidra 12.1.4 and the real SDK/MCP workflow. The snapshot was based on a real Ghidra trace, then deliberately constructed to contain two separately authenticated records matching the _evaluate cached query: the second has the same observed content but a different Evidence link and ID. REA's snapshot parser accepted it. This is an ambiguity control, not a claim that the fixture arose naturally.

  • With the ordinary snapshot, unmodified REA cited two missing procedure sources; both were missing live and after export/import. The experiment cited both retained sources, which resolved to analyze_function in both places.
  • With the ambiguous snapshot, unmodified REA cited a resolvable _evaluate ID but a missing cached callee ID. The experiment cited resolvable IDs for both. The returned page had three nodes and three edges in all four runs; this is not an exhaustive graph-equivalence claim.
  • Source inspection explains why the first procedure differs: an ambiguous binding is rejected for replay and the session must ask the provider for a fresh observation instead of choosing an arbitrary historical record. In this fixture the fresh result's ID equals the original record. The callee remained replayable, so it exercises the original bug in the same trace.
  • Removing the matching source record altogether from an owned snapshot copy was rejected by parseAnalysisSnapshot as having no profile-bound Evidence record. That is distinct from the valid ambiguous case.

There is still a real design question around the experiment's ?? fallback. In an in-memory fixed-adapter test, I supplied a captured Ghidra dossier through a simulated port with no source evidenceId and no session recorder. The experimental server returned a successful trace with a constructed procedure ID and empty top-level links, but a subsequent inspect_analysis_view lookup could not find that ID; get_evidence_bundle was not advertised in that fixed configuration. This is an embedded/fixed-port boundary test, not a claim about a normal real-provider session. It shows that constructing an ID alone is not proof of retention and that the fallback cannot be treated as a complete ownership fix.

Both saved snapshots and the unexecuted target had unchanged hashes after the real-provider runs; successful MCP responses used the SDK's advertised compact-schema validation. On the experiment, the existing NativeValueTrace and AnalysisSnapshotCache source test files passed 72 tests; they do not replace the source-closure or no-owner scenarios above. No production change is proposed here. A repair needs an explicit source-retention contract for executions without an owned ID, plus appropriate ambiguous-binding, offline closure and fixed-adapter behavior; cancellation and other providers remain unverified.

<!-- gh-comment-id:6547189050 --> @morluto commented on GitHub (Oct 31, 2026): ### Follow-up: ambiguous snapshot provenance and the no-owner fallback On REA `60149282fcfc05ac32fbc94434c107710120da6f` I tested the previous one-line source-ID experiment in a new isolated worktree, using Ghidra 12.1.4 and the real SDK/MCP workflow. The snapshot was based on a real Ghidra trace, then **deliberately constructed** to contain two separately authenticated records matching the `_evaluate` cached query: the second has the same observed content but a different Evidence link and ID. REA's snapshot parser accepted it. This is an ambiguity control, not a claim that the fixture arose naturally. - With the ordinary snapshot, unmodified REA cited two missing procedure sources; both were missing live and after export/import. The experiment cited both retained sources, which resolved to `analyze_function` in both places. - With the ambiguous snapshot, unmodified REA cited a resolvable `_evaluate` ID but a missing cached callee ID. The experiment cited resolvable IDs for both. The returned page had three nodes and three edges in all four runs; this is not an exhaustive graph-equivalence claim. - Source inspection explains why the first procedure differs: an ambiguous binding is rejected for replay and the session must ask the provider for a fresh observation instead of choosing an arbitrary historical record. In this fixture the fresh result's ID equals the original record. The callee remained replayable, so it exercises the original bug in the same trace. - Removing the matching source record altogether from an owned snapshot copy was rejected by `parseAnalysisSnapshot` as having no profile-bound Evidence record. That is distinct from the valid ambiguous case. There is still a real design question around the experiment's `??` fallback. In an **in-memory fixed-adapter test**, I supplied a captured Ghidra dossier through a simulated port with no source `evidenceId` and no session recorder. The experimental server returned a successful trace with a constructed procedure ID and empty top-level links, but a subsequent `inspect_analysis_view` lookup could not find that ID; `get_evidence_bundle` was not advertised in that fixed configuration. This is an embedded/fixed-port boundary test, not a claim about a normal real-provider session. It shows that constructing an ID alone is not proof of retention and that the fallback cannot be treated as a complete ownership fix. Both saved snapshots and the unexecuted target had unchanged hashes after the real-provider runs; successful MCP responses used the SDK's advertised compact-schema validation. On the experiment, the existing `NativeValueTrace` and `AnalysisSnapshotCache` source test files passed 72 tests; they do not replace the source-closure or no-owner scenarios above. No production change is proposed here. A repair needs an explicit source-retention contract for executions without an owned ID, plus appropriate ambiguous-binding, offline closure and fixed-adapter behavior; cancellation and other providers remain unverified.
Author
Owner

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

Real Kuna session: missing source without snapshot replay

On current main d54a4661da20382ad8456564a08569fdd24131c5, real Kuna 1.986 and a fresh isolated cache, trace_native_values for the owned Mach-O _audit_call_zero returned one procedure with an evidence_id and an explicit unknown that Kuna has no native def-use model. Its top-level evidence_links was empty. Before closing the same MCP session, inspect_analysis_view for that procedure ID failed with evidence_integrity_mismatch / missing, and the complete session bundle did not contain the ID. No snapshot was loaded. Successful MCP responses used the fetched compact SDK schema; the target was unchanged and not executed.

A related CLI check on isolated PR #8297 wrote a bundle for the same real Kuna workflow: the trace's procedure ID was again absent, and target-free offline lookup failed. Complete and summary CLI delivery both returned success. Real Ghidra fresh/selected-project controls on that PR retained and resolved all cited procedure sources. Details and current-main test-fixture drift are at https://github.com/morluto/rea/pull/8297#issuecomment-6547543524.

Source-derived: traceNativeValues still constructs an ID from the execution, while executeComposedWorkflow adds a source link only when an owned evidenceId or source record exists. Kuna declares live cache policy and filesystem effects, so the generic session source-retention rule does not admit this observation. That is a separate absence-of-owner case from Ghidra's replayed-ID mismatch; simply choosing execution.evidenceId with a reconstructed fallback does not establish retention. This is one fixture and provider version, not a broad rate or a claim that a missing def-use model is itself a bug.

<!-- gh-comment-id:6547546763 --> @morluto commented on GitHub (Oct 31, 2026): ### Real Kuna session: missing source without snapshot replay On current main `d54a4661da20382ad8456564a08569fdd24131c5`, real Kuna 1.986 and a fresh isolated cache, `trace_native_values` for the owned Mach-O `_audit_call_zero` returned one procedure with an `evidence_id` and an explicit unknown that Kuna has no native def-use model. Its top-level `evidence_links` was empty. Before closing the same MCP session, `inspect_analysis_view` for that procedure ID failed with `evidence_integrity_mismatch / missing`, and the complete session bundle did not contain the ID. No snapshot was loaded. Successful MCP responses used the fetched compact SDK schema; the target was unchanged and not executed. A related CLI check on isolated PR #8297 wrote a bundle for the same real Kuna workflow: the trace's procedure ID was again absent, and target-free offline lookup failed. Complete and summary CLI delivery both returned success. Real Ghidra fresh/selected-project controls on that PR retained and resolved all cited procedure sources. Details and current-main test-fixture drift are at https://github.com/morluto/rea/pull/8297#issuecomment-6547543524. Source-derived: `traceNativeValues` still constructs an ID from the execution, while `executeComposedWorkflow` adds a source link only when an owned `evidenceId` or source record exists. Kuna declares live cache policy and filesystem effects, so the generic session source-retention rule does not admit this observation. That is a separate absence-of-owner case from Ghidra's replayed-ID mismatch; simply choosing `execution.evidenceId` with a reconstructed fallback does not establish retention. This is one fixture and provider version, not a broad rate or a claim that a missing def-use model is itself a bug.
Author
Owner

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

Further REA-side investigation on main d54a4661d, with a disposable local prototype (not a proposed production patch):

  • The trace currently constructs a source Evidence ID from each analyze_function result, even if the session did not retain that source. Replayed Ghidra results can also carry an existing, different retained ID. Retaining an observation and allowing snapshot replay are separate decisions.
  • In the prototype, the composed trace collects an uncached function observation as source Evidence; an already retained observation keeps its existing ID. The shared CLI/MCP result boundary records the collected sources, and the parent links them. This did not change the snapshot cache policy or add entries to it.
  • Real Kuna 1.986 MCP: both repeated traces linked their function source, and its inspect_analysis_view succeeded after exporting and importing the bundle into a new, targetless session. With this prototype combined locally with #8297, the real Kuna CLI summary export likewise contained both the trace and its source, and the source resolved in a fresh MCP session. The static fixture's SHA-256 was unchanged.
  • Real Ghidra 12.1.4 MCP: two function IDs were preserved across a cold trace, snapshot reopen, and a differently paged replay; all six offline lookups after bundle import succeeded. The fixture and saved snapshot hashes were unchanged.
  • A controlled production-boundary test returned cancellation after one source completed: the completed source was passed to the recorder and the cancellation remained the primary error. An adapter without a recorder returned an explicit capability error. These are simulated boundary checks, not a real-provider cancellation test.

This exposes a design decision before integration: requiring a source recorder changes behavior for adapters that currently lack one. Retaining full function dossiers also has a resource cost; this small Kuna fixture produced a 5,801-byte serialized source record, but that is not a bound or representative measurement for larger functions. A production fix needs an ownership contract for IDs, an explicit retention/resource policy, real cancellation coverage, and CLI export coverage. The local experiment does not establish that it is safe or ready to merge.

<!-- gh-comment-id:6547588102 --> @morluto commented on GitHub (Oct 31, 2026): Further REA-side investigation on main `d54a4661d`, with a disposable local prototype (not a proposed production patch): - The trace currently constructs a source Evidence ID from each `analyze_function` result, even if the session did not retain that source. Replayed Ghidra results can also carry an existing, different retained ID. Retaining an observation and allowing snapshot replay are separate decisions. - In the prototype, the composed trace collects an uncached function observation as source Evidence; an already retained observation keeps its existing ID. The shared CLI/MCP result boundary records the collected sources, and the parent links them. This did not change the snapshot cache policy or add entries to it. - Real Kuna 1.986 MCP: both repeated traces linked their function source, and its `inspect_analysis_view` succeeded after exporting and importing the bundle into a new, targetless session. With this prototype combined locally with #8297, the real Kuna CLI summary export likewise contained both the trace and its source, and the source resolved in a fresh MCP session. The static fixture's SHA-256 was unchanged. - Real Ghidra 12.1.4 MCP: two function IDs were preserved across a cold trace, snapshot reopen, and a differently paged replay; all six offline lookups after bundle import succeeded. The fixture and saved snapshot hashes were unchanged. - A controlled production-boundary test returned cancellation after one source completed: the completed source was passed to the recorder and the cancellation remained the primary error. An adapter without a recorder returned an explicit capability error. These are simulated boundary checks, not a real-provider cancellation test. This exposes a design decision before integration: requiring a source recorder changes behavior for adapters that currently lack one. Retaining full function dossiers also has a resource cost; this small Kuna fixture produced a 5,801-byte serialized source record, but that is not a bound or representative measurement for larger functions. A production fix needs an ownership contract for IDs, an explicit retention/resource policy, real cancellation coverage, and CLI export coverage. The local experiment does not establish that it is safe or ready to merge.
Author
Owner

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

Cancellation follow-up with a real Kuna 1.986 observation, using a deliberately instrumented boundary:

  1. In separate disposable builds of main d54a4661d and the source-retention experiment described above, I inserted a test-only pause immediately after the real analyze_function call returned to REA. In the experiment, the pause was immediately after the completed observation had been added to its local source ledger. The pause returned an AnalysisCancelledError when the public MCP client's signal was cancelled; this explicitly injects the timing and error, rather than relying on a real provider interrupt.
  2. For each build I opened the same static Mach-O fixture with Kuna, waited for the pause marker, cancelled trace_native_values through the MCP SDK, and queried get_evidence_bundle in the same session. The SDK call reported cancellation in both cases. Neither session had a completed trace.
  3. The instrumented main control had zero retained analyze_function records. The experiment had one, and inspect_analysis_view resolved it in that session. The fixture SHA-256 was unchanged in both runs.

This demonstrates the composed-workflow handoff for this controlled late-cancellation boundary and real provider output; it does not establish behavior if cancellation interrupts Kuna itself, during final cleanup, after session closure, or with multiple completed observations. It also does not resolve the recorder and memory policy questions above.

<!-- gh-comment-id:6547605583 --> @morluto commented on GitHub (Oct 31, 2026): Cancellation follow-up with a real Kuna 1.986 observation, using a deliberately instrumented boundary: 1. In separate disposable builds of main `d54a4661d` and the source-retention experiment described above, I inserted a test-only pause immediately after the real `analyze_function` call returned to REA. In the experiment, the pause was immediately after the completed observation had been added to its local source ledger. The pause returned an `AnalysisCancelledError` when the public MCP client's signal was cancelled; this explicitly injects the timing and error, rather than relying on a real provider interrupt. 2. For each build I opened the same static Mach-O fixture with Kuna, waited for the pause marker, cancelled `trace_native_values` through the MCP SDK, and queried `get_evidence_bundle` in the same session. The SDK call reported cancellation in both cases. Neither session had a completed trace. 3. The instrumented main control had zero retained `analyze_function` records. The experiment had one, and `inspect_analysis_view` resolved it in that session. The fixture SHA-256 was unchanged in both runs. This demonstrates the composed-workflow handoff for this controlled late-cancellation boundary and real provider output; it does not establish behavior if cancellation interrupts Kuna itself, during final cleanup, after session closure, or with multiple completed observations. It also does not resolve the recorder and memory policy questions above.
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#6521
No description provided.