[GH-ISSUE #8211] [Bug] Kuna cleanup error omits the available close retry #6489

Closed
opened 2026-11-01 21:11:34 +00:00 by bsakaguchi · 3 comments
Owner

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

Originally assigned to: @kaoru0822-kitauji on GitHub.

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

A close_binary error retained a Kuna project's unresolved process and staging ownership, but its only remediation was “Review the reported local resources before opening another target.” It did not identify the available same-connection cleanup retry. After the transient processes exited, a second close_binary succeeded and removed the retained staging directory. The first error correctly preserved uncertainty; the issue is discovery of the recovery, not that cleanup should have been declared successful.

Reproduction

On macOS arm64 with source commit 38433cfb4577b133d7598f9439c6448299cb44eb and Kuna 1.986, open an owned 1,200-function Mach-O through MCP with a fresh isolated cache. Use a caller-owned wrapper that sleeps 12 seconds before executing the real decompile-project, forwarding all other commands. Start procedure_assembly, cancel its only waiter after 3 seconds, then call close_binary. The first close returned cleanup_incomplete: macOS withheld the process environment for the still-live system shell/sleep processes, so REA could not prove their ownership. Keep the same MCP connection open, wait for the delayed processes to exit, and call close_binary again. The second close returned success; staging and published-project directories were empty and the target SHA-256 remained unchanged.

A prior controlled run reproduced the first incomplete close, but the harness closed the MCP connection before retrying and retained its staging directory. The complete same-connection recovery above ran once. The injected delay is a deliberately artificial launcher scenario, not a reproduction on the normal Kuna executable or a claim about its natural failure rate. No target was executed.

Expected behavior

When this specific session-owned cleanup is retained and close_binary is a supported retry, the response should tell an agent to keep the connection, allow the reported condition to settle or be resolved, and retry close_binary, checking the result. Distinguish this from retrying the original analysis and avoid promising a retry will succeed or suggesting unverified process termination. If a different cleanup owner has no such retry, preserve its own applicable recovery.

Impact and scope

The caller can see the uncertain resources, but must discover the retry elsewhere; the error says retryable: false and does not name a next tool. This can lead an agent to abandon the connection and its retry owner. retryable may refer to the failed operation rather than cleanup, so the needed distinction should be explicit. Observed only in the controlled macOS MCP case above; ordinary Kuna and other providers are untested.

REA version

38433cfb4577b133d7598f9439c6448299cb44eb (PR #8187 branch)

Runtime and platform

Node 24.22.1; macOS 26.3 arm64; caller-owned shell wrapper around Kuna 1.986.

Target and artifact context

Self-built Mach-O dylib, 1,200 simple functions; isolated cache; target not executed.

Interface

MCP

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

First close_binary: code: cleanup_incomplete, retryable: false, remediation “Review the reported local resources before opening another target.” Details retained the provider, staging path, process group and reason platform_binary_environment_withheld for two live candidates. Second close_binary on the same connection: isError: false, result: null; the owned staging directory was empty. The two target SHA-256 observations matched.

Typed outcome or recovery expected

Retain cleanup_incomplete and the owned-resource details while reporting a concrete conditional cleanup retry at the owner that can actually perform it. Preserve explicit unknown ownership and fail closed on each retry.

Analysis or suspected cause

The observed response is produced by the generic ProviderCleanupError message in src/domain/providerCleanupError.ts; source inspection alone does not establish that all cleanup owners support retry. The Kuna guide documents retained cleanup and close_binary retry. Scope the improvement to the applicable owner rather than adding unconditional retry advice to every cleanup error.

Additional context

Related lifecycle audit #4227 and Kuna progress/shared-wait discussion #8176. The behavior after transport shutdown with unresolved cleanup, other platforms, and cancellation during final publication remain unverified.

Originally created by @morluto on GitHub (Oct 30, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/8211 Originally assigned to: @kaoru0822-kitauji on GitHub. ### 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 A `close_binary` error retained a Kuna project's unresolved process and staging ownership, but its only remediation was “Review the reported local resources before opening another target.” It did not identify the available same-connection cleanup retry. After the transient processes exited, a second `close_binary` succeeded and removed the retained staging directory. The first error correctly preserved uncertainty; the issue is discovery of the recovery, not that cleanup should have been declared successful. ### Reproduction On macOS arm64 with source commit `38433cfb4577b133d7598f9439c6448299cb44eb` and Kuna 1.986, open an owned 1,200-function Mach-O through MCP with a fresh isolated cache. Use a caller-owned wrapper that sleeps 12 seconds before executing the real `decompile-project`, forwarding all other commands. Start `procedure_assembly`, cancel its only waiter after 3 seconds, then call `close_binary`. The first close returned `cleanup_incomplete`: macOS withheld the process environment for the still-live system shell/sleep processes, so REA could not prove their ownership. Keep the same MCP connection open, wait for the delayed processes to exit, and call `close_binary` again. The second close returned success; staging and published-project directories were empty and the target SHA-256 remained unchanged. A prior controlled run reproduced the first incomplete close, but the harness closed the MCP connection before retrying and retained its staging directory. The complete same-connection recovery above ran once. The injected delay is a deliberately artificial launcher scenario, not a reproduction on the normal Kuna executable or a claim about its natural failure rate. No target was executed. ### Expected behavior When this specific session-owned cleanup is retained and `close_binary` is a supported retry, the response should tell an agent to keep the connection, allow the reported condition to settle or be resolved, and retry `close_binary`, checking the result. Distinguish this from retrying the original analysis and avoid promising a retry will succeed or suggesting unverified process termination. If a different cleanup owner has no such retry, preserve its own applicable recovery. ### Impact and scope The caller can see the uncertain resources, but must discover the retry elsewhere; the error says `retryable: false` and does not name a next tool. This can lead an agent to abandon the connection and its retry owner. `retryable` may refer to the failed operation rather than cleanup, so the needed distinction should be explicit. Observed only in the controlled macOS MCP case above; ordinary Kuna and other providers are untested. ### REA version `38433cfb4577b133d7598f9439c6448299cb44eb` (PR #8187 branch) ### Runtime and platform Node 24.22.1; macOS 26.3 arm64; caller-owned shell wrapper around Kuna 1.986. ### Target and artifact context Self-built Mach-O dylib, 1,200 simple functions; isolated cache; target not executed. ### Interface MCP ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence First `close_binary`: `code: cleanup_incomplete`, `retryable: false`, remediation “Review the reported local resources before opening another target.” Details retained the provider, staging path, process group and reason `platform_binary_environment_withheld` for two live candidates. Second `close_binary` on the same connection: `isError: false`, `result: null`; the owned staging directory was empty. The two target SHA-256 observations matched. ### Typed outcome or recovery expected Retain `cleanup_incomplete` and the owned-resource details while reporting a concrete conditional cleanup retry at the owner that can actually perform it. Preserve explicit unknown ownership and fail closed on each retry. ### Analysis or suspected cause The observed response is produced by the generic `ProviderCleanupError` message in [`src/domain/providerCleanupError.ts`](https://github.com/morluto/rea/blob/38433cfb4577b133d7598f9439c6448299cb44eb/src/domain/providerCleanupError.ts); source inspection alone does not establish that all cleanup owners support retry. The Kuna guide documents retained cleanup and `close_binary` retry. Scope the improvement to the applicable owner rather than adding unconditional retry advice to every cleanup error. ### Additional context Related lifecycle audit #4227 and Kuna progress/shared-wait discussion #8176. The behavior after transport shutdown with unresolved cleanup, other platforms, and cancellation during final publication remain unverified.
bsakaguchi 2026-11-01 21:11:34 +00:00
  • closed this issue
  • added the
    bug
    triage
    labels
Author
Owner

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

A repeat of the controlled wrapper-delay scenario also checked the public session state around cleanup. After the first close_binary returned cleanup_incomplete, binary_session returned open: false, cleanup_pending: true, and retained the original analysis run ID; analysis_activity and process lineage were explicitly not_observed. After the delayed processes exited and a second close_binary succeeded, cleanup_pending became false and the run ID cleared. The owned staging directory was empty and the original target digest was unchanged. This confirms the session exposes the retained-cleanup distinction in this scenario; the missing piece reported here remains the actionable retry instruction in the error, not a claim that status says idle or loses ownership.

<!-- gh-comment-id:6533841227 --> @morluto commented on GitHub (Oct 30, 2026): A repeat of the controlled wrapper-delay scenario also checked the public session state around cleanup. After the first `close_binary` returned `cleanup_incomplete`, `binary_session` returned `open: false`, `cleanup_pending: true`, and retained the original analysis run ID; `analysis_activity` and process lineage were explicitly `not_observed`. After the delayed processes exited and a second `close_binary` succeeded, `cleanup_pending` became false and the run ID cleared. The owned staging directory was empty and the original target digest was unchanged. This confirms the session exposes the retained-cleanup distinction in this scenario; the missing piece reported here remains the actionable retry instruction in the error, not a claim that status says idle or loses ownership.
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:6538797032 --> @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):

Current-main recovery and discovery control on REA 60149282fcfc05ac32fbc94434c107710120da6f: with the same kind of caller-owned delay around real Kuna 1.986, a marker confirmed the wrapper received decompile-project before the SDK cancelled the only assembly request; the wrapper deferred launching the real export. The first close_binary returned cleanup_incomplete with owned-resource details and the same generic remediation. binary_session reported open: false, cleanup_pending: true, and the retained run ID.

While that cleanup was pending, binary_session marked procedure_assembly unavailable with target_required and advised Call open_binary with a supported local target. Attempting to open a different supported ELF on the same connection returned cleanup_incomplete; the pending flag and original run ID remained. Once the injected delay had passed, a second close_binary succeeded, the pending flag and run ID cleared, and opening the ELF and resolving audit_target succeeded. Both target digests were unchanged; the isolated staging and project directories were empty after close. Successful responses were checked against the fetched compact SDK schemas.

This adds a session-discovery recovery mismatch to the existing error-remediation report: when cleanup is retained, the ordinary target-required suggestion alone cannot complete the tested action. It does not justify opening a new target before cleanup, treating unknown ownership as absent, or promising that a close retry will always succeed. The delay was injected, this is one macOS run and one owner path, and no target was executed. A first harness attempt failed before the delay because its custom environment variable was not passed to the provider; it is not part of the lifecycle result.

A second controlled run tested the alternative recovery: after the failed early open and the same wait, binary_session still reported cleanup_pending: true, but retrying open_binary directly for the other ELF succeeded, cleared the pending state, assigned a new run ID, and allowed procedure_address. Final close succeeded and staging/projects were empty. Thus close_binary is an available explicit retry, not the only way to complete cleanup in this case; the open attempt can retry it too. The missing guidance is the conditional pending-cleanup step and its uncertainty, not a categorical instruction that a separate close is mandatory.

<!-- gh-comment-id:6546765631 --> @morluto commented on GitHub (Oct 31, 2026): Current-main recovery and discovery control on REA `60149282fcfc05ac32fbc94434c107710120da6f`: with the same kind of caller-owned delay around real Kuna 1.986, a marker confirmed the wrapper received `decompile-project` before the SDK cancelled the only assembly request; the wrapper deferred launching the real export. The first `close_binary` returned `cleanup_incomplete` with owned-resource details and the same generic remediation. `binary_session` reported `open: false`, `cleanup_pending: true`, and the retained run ID. While that cleanup was pending, `binary_session` marked `procedure_assembly` unavailable with `target_required` and advised `Call open_binary with a supported local target.` Attempting to open a *different* supported ELF on the same connection returned `cleanup_incomplete`; the pending flag and original run ID remained. Once the injected delay had passed, a second `close_binary` succeeded, the pending flag and run ID cleared, and opening the ELF and resolving `audit_target` succeeded. Both target digests were unchanged; the isolated staging and project directories were empty after close. Successful responses were checked against the fetched compact SDK schemas. This adds a session-discovery recovery mismatch to the existing error-remediation report: when cleanup is retained, the ordinary target-required suggestion alone cannot complete the tested action. It does **not** justify opening a new target before cleanup, treating unknown ownership as absent, or promising that a close retry will always succeed. The delay was injected, this is one macOS run and one owner path, and no target was executed. A first harness attempt failed before the delay because its custom environment variable was not passed to the provider; it is not part of the lifecycle result. A second controlled run tested the alternative recovery: after the failed early open and the same wait, `binary_session` still reported `cleanup_pending: true`, but retrying `open_binary` directly for the other ELF succeeded, cleared the pending state, assigned a new run ID, and allowed `procedure_address`. Final close succeeded and staging/projects were empty. Thus `close_binary` is an available explicit retry, not the only way to complete cleanup in this case; the open attempt can retry it too. The missing guidance is the conditional pending-cleanup step and its uncertainty, not a categorical instruction that a separate close is mandatory.
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#6489
No description provided.