[GH-ISSUE #8239] [Design] Explain individual failures in compact batch naming #6507

Open
opened 2026-11-01 21:11:45 +00:00 by bsakaguchi · 4 comments
Owner

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

Before submitting

  • I searched the open and closed issues and pull requests for a related discussion.
  • I understand the contribution scope must be reviewed before integration; open questions are welcome here.
  • This discussion does not include credentials, private samples, or sensitive target data.

Decision needed

Should compact batch naming expose a bounded reason and safe recovery for each unsuccessful address, while retaining per-item success and independent transactions?

Context and evidence

On macOS arm64 with real REA/Ghidra 12.1.4 MCP, I named one function and one data label alongside unmapped 0xdeadbeef in a single set_addresses_names request. It returned true, false, true; subsequent pseudocode used both successful names. A separate request using two address spellings for the same location with different requested names returned false for both, leaving the original name. A third request for the same new name at two mapped addresses returned one true and one false; a single-address request of the same occupied name also returned only false. These are distinct conditions with the same Boolean result. The Evidence retains input and per-address booleans; its provider limitation lists possible causes but does not associate a specific cause with an item.

A single-address retry of the unmapped case returned a typed invalid-request issue with Address is not mapped. In the duplicate-name case, retrying with a different explicit name succeeded. These are scripted controls, not a recommendation to retry blindly: a name edit is a mutation, and diagnosing conflict may require checking the current owner and caller intent. Kuna correctly reported naming capability unavailable in the same target context. No target execution or executable modification occurred.

Expected interaction with targets

Read provider metadata and mutate names only in the existing authorized analysis session. Original executable bytes remain unchanged; existing Ghidra project sessions and Windows P0 stay read-only.

Boundary details (optional)

Keep requested and canonical addresses distinct, preserve partial committed success and failure, and state unknown where the producing boundary cannot determine the cause. Do not manufacture exact reasons from a Boolean or suggest retrying an unchanged mutating call. Preserve provider-specific namespace, collision, alias and cleanup semantics; no assumption of atomic batch is proposed.

Options and tradeoffs

Compare documenting existing follow-up calls, an additive per-item reason or diagnostic view associated with the current result, or a separately versioned typed result contract. Reuse the existing naming workflow rather than adding a Ghidra API wrapper. Consider output size and caller compatibility; source observation and resulting Evidence should share one owner.

Verification available so far

I have a prototype or observed results

Success criteria and open questions

Exercise unmapped address, invalid name, duplicate owner, same-address conflicting aliases, readback failure and mixed success through real MCP and controlled provider boundaries. Confirm each reported reason is supported and that failure cannot erase another successful edit. Include ordering, cancellation and partial side-effect reporting as applicable. Hopper, CLI, Windows and autonomous agent decisions were not tested.

References

Related #8238 concerns order-dependent conflicts, #6405 annotation persistence and #1634 Ghidra naming admission. Source revision 53a4ab78451a0654e9c3beb3d43a5e371a288fcc.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8239 ### Before submitting - [x] I searched the open and closed issues and pull requests for a related discussion. - [x] I understand the contribution scope must be reviewed before integration; open questions are welcome here. - [x] This discussion does not include credentials, private samples, or sensitive target data. ### Decision needed Should compact batch naming expose a bounded reason and safe recovery for each unsuccessful address, while retaining per-item success and independent transactions? ### Context and evidence On macOS arm64 with real REA/Ghidra 12.1.4 MCP, I named one function and one data label alongside unmapped `0xdeadbeef` in a single `set_addresses_names` request. It returned `true, false, true`; subsequent pseudocode used both successful names. A separate request using two address spellings for the same location with different requested names returned `false` for both, leaving the original name. A third request for the same new name at two mapped addresses returned one `true` and one `false`; a single-address request of the same occupied name also returned only `false`. These are distinct conditions with the same Boolean result. The Evidence retains input and per-address booleans; its provider limitation lists possible causes but does not associate a specific cause with an item. A single-address retry of the unmapped case returned a typed invalid-request issue with `Address is not mapped`. In the duplicate-name case, retrying with a different explicit name succeeded. These are scripted controls, not a recommendation to retry blindly: a name edit is a mutation, and diagnosing conflict may require checking the current owner and caller intent. Kuna correctly reported naming capability unavailable in the same target context. No target execution or executable modification occurred. ### Expected interaction with targets Read provider metadata and mutate names only in the existing authorized analysis session. Original executable bytes remain unchanged; existing Ghidra project sessions and Windows P0 stay read-only. ### Boundary details (optional) Keep requested and canonical addresses distinct, preserve partial committed success and failure, and state unknown where the producing boundary cannot determine the cause. Do not manufacture exact reasons from a Boolean or suggest retrying an unchanged mutating call. Preserve provider-specific namespace, collision, alias and cleanup semantics; no assumption of atomic batch is proposed. ### Options and tradeoffs Compare documenting existing follow-up calls, an additive per-item reason or diagnostic view associated with the current result, or a separately versioned typed result contract. Reuse the existing naming workflow rather than adding a Ghidra API wrapper. Consider output size and caller compatibility; source observation and resulting Evidence should share one owner. ### Verification available so far I have a prototype or observed results ### Success criteria and open questions Exercise unmapped address, invalid name, duplicate owner, same-address conflicting aliases, readback failure and mixed success through real MCP and controlled provider boundaries. Confirm each reported reason is supported and that failure cannot erase another successful edit. Include ordering, cancellation and partial side-effect reporting as applicable. Hopper, CLI, Windows and autonomous agent decisions were not tested. ### References Related #8238 concerns order-dependent conflicts, #6405 annotation persistence and #1634 Ghidra naming admission. Source revision `53a4ab78451a0654e9c3beb3d43a5e371a288fcc`.
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:6538806994 --> @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):

Invalid-name, mixed-result and alias controls

In a fresh real REA b43c329 / Ghidra 12.1.4 MCP session on the owned Mach-O, I submitted a single batch with a valid mapped data-label name, an otherwise mapped address whose requested name contained a NUL, and an unmapped address. It returned {true, false, false}. Readback showed the first requested label applied and the second location kept its original name. Controlled single-address checks returned separate typed invalid-request details: the NUL's UTF-16 index for the invalid name, and Address is not mapped for the third address. Subsequent readback still showed the successful label and unchanged failed label. This is a deliberately constructed diagnostic experiment; it is not advice to blindly retry mutating operations.

A separate same-name request for 0x100004000 and its ram:0x100004000 spelling returned true for both and readback showed one canonical address with the requested name. Repeating the identical batch returned the same Evidence ID, and the export retained one record for that repeated result. The earlier mixed request was retained as its own Evidence record with original inputs and per-key booleans. These outcomes distinguish input keys from distinct committed address edits and confirm that content-addressed Evidence is not an ordered edit journal; #6405 covers the broader persistence/replay question.

The target SHA-256 remained ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d, close succeeded, and no target was executed. This tests one invalid text and one alias case, not readback-failure injection or cancellation. Per-item reasons should come from the producing boundary, retain requested/canonical address identity, and avoid implying two mutations when two spellings name one address.

<!-- gh-comment-id:6542397341 --> @morluto commented on GitHub (Oct 31, 2026): ### Invalid-name, mixed-result and alias controls In a fresh real REA `b43c329` / Ghidra 12.1.4 MCP session on the owned Mach-O, I submitted a single batch with a valid mapped data-label name, an otherwise mapped address whose requested name contained a NUL, and an unmapped address. It returned `{true, false, false}`. Readback showed the first requested label applied and the second location kept its original name. Controlled single-address checks returned separate typed invalid-request details: the NUL's UTF-16 index for the invalid name, and `Address is not mapped` for the third address. Subsequent readback still showed the successful label and unchanged failed label. This is a deliberately constructed diagnostic experiment; it is not advice to blindly retry mutating operations. A separate same-name request for `0x100004000` and its `ram:0x100004000` spelling returned `true` for both and readback showed one canonical address with the requested name. Repeating the identical batch returned the same Evidence ID, and the export retained one record for that repeated result. The earlier mixed request was retained as its own Evidence record with original inputs and per-key booleans. These outcomes distinguish input keys from distinct committed address edits and confirm that content-addressed Evidence is not an ordered edit journal; #6405 covers the broader persistence/replay question. The target SHA-256 remained `ffad1b70c6a5a7ef3f7c3f59126be516520210777d949b35e97c9067f272aa2d`, close succeeded, and no target was executed. This tests one invalid text and one alias case, not readback-failure injection or cancellation. Per-item reasons should come from the producing boundary, retain requested/canonical address identity, and avoid implying two mutations when two spellings name one address.
Author
Owner

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

Update after #8306 merged: real REA 7c9ed94259fef560fdbec0c9b640348c5d54c391 / Ghidra 12.1.4 MCP now returns per-address reasons in raw_result.failures and groups contested destinations in raw_result.conflicts. The real namespace verifier passed controls for duplicate_requested_name, name_held_by_selected_address, name_held_by_unselected_address, and invalid_name, including readbacks and reversed member order. In a separate ephemeral session, conflicting spellings of the same address reported conflicting_alias_names without changing it; an independent valid edit in a batch with invalid and unmapped addresses succeeded, while the other two reported invalid_address and unmapped_address respectively. Both source-owned targets remained unchanged; neither was executed.

This addresses much of the Ghidra diagnostic gap described above. These runs did not induce a readback mismatch or cancellation, validate Hopper/Windows, or evaluate autonomous recovery; whether the remaining scope merits keeping this design issue open is a maintainer decision. Full verification lane was not run to completion. More detail: #8238 (comment https://github.com/morluto/rea/issues/8238#issuecomment-6545723423).

<!-- gh-comment-id:6545725615 --> @morluto commented on GitHub (Oct 31, 2026): Update after #8306 merged: real REA `7c9ed94259fef560fdbec0c9b640348c5d54c391` / Ghidra 12.1.4 MCP now returns per-address reasons in `raw_result.failures` and groups contested destinations in `raw_result.conflicts`. The real namespace verifier passed controls for `duplicate_requested_name`, `name_held_by_selected_address`, `name_held_by_unselected_address`, and `invalid_name`, including readbacks and reversed member order. In a separate ephemeral session, conflicting spellings of the same address reported `conflicting_alias_names` without changing it; an independent valid edit in a batch with invalid and unmapped addresses succeeded, while the other two reported `invalid_address` and `unmapped_address` respectively. Both source-owned targets remained unchanged; neither was executed. This addresses much of the Ghidra diagnostic gap described above. These runs did not induce a readback mismatch or cancellation, validate Hopper/Windows, or evaluate autonomous recovery; whether the remaining scope merits keeping this design issue open is a maintainer decision. Full verification lane was not run to completion. More detail: #8238 (comment https://github.com/morluto/rea/issues/8238#issuecomment-6545723423).
Author
Owner

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

A real REA 7c9ed94259fef560fdbec0c9b640348c5d54c391 / Ghidra 12.1.4 MCP recovery control illustrates why the per-item reason and pre-batch state matter. I first gave B the name held, then submitted {A: held, B: moved, unmapped: other}. The result was false, true, false: A reported name_held_by_selected_address with B as holder, B was renamed, and the unmapped key reported unmapped_address. Readbacks confirmed A unchanged and B moved. I deliberately submitted the identical map once more: A and B then both succeeded, because B had released held, while the unmapped key still failed. Readbacks confirmed the second change.

This follows the documented pre-batch semantics; it is not a defect or a recommendation to blindly retry mutations. It is a concrete case for telling an agent to inspect partial results and current state before deciding whether another mutating call matches the analyst's intent. The two results had distinct Evidence IDs despite identical parameters; exporting the bundle and importing it into a fresh target-free server preserved both complete records and their reasons exactly. Obtaining complete records required fetching the canonical full bundle and selecting locally; a filtered detail: complete call was rejected as documented (#8307 concerns selective payload access). No target execution or executable modification occurred; the source-owned fixture hash was unchanged. This does not test cancellation, concurrent mutation, or autonomous agent behavior.

<!-- gh-comment-id:6545743126 --> @morluto commented on GitHub (Oct 31, 2026): A real REA `7c9ed94259fef560fdbec0c9b640348c5d54c391` / Ghidra 12.1.4 MCP recovery control illustrates why the per-item reason and pre-batch state matter. I first gave B the name `held`, then submitted `{A: held, B: moved, unmapped: other}`. The result was `false, true, false`: A reported `name_held_by_selected_address` with B as holder, B was renamed, and the unmapped key reported `unmapped_address`. Readbacks confirmed A unchanged and B moved. I deliberately submitted the identical map once more: A and B then both succeeded, because B had released `held`, while the unmapped key still failed. Readbacks confirmed the second change. This follows the documented pre-batch semantics; it is not a defect or a recommendation to blindly retry mutations. It is a concrete case for telling an agent to inspect partial results and current state before deciding whether another mutating call matches the analyst's intent. The two results had distinct Evidence IDs despite identical parameters; exporting the bundle and importing it into a fresh target-free server preserved both complete records and their reasons exactly. Obtaining complete records required fetching the canonical full bundle and selecting locally; a filtered `detail: complete` call was rejected as documented (#8307 concerns selective payload access). No target execution or executable modification occurred; the source-owned fixture hash was unchanged. This does not test cancellation, concurrent mutation, or autonomous agent behavior.
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#6507
No description provided.