[GH-ISSUE #4628] [Bug] Resolved composite cleanup errors retain execution_failure instead of their typed primary #2409

Closed
opened 2026-10-17 21:04:15 +00:00 by bsakaguchi · 2 comments
Owner

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

Before submitting

  • Searched open and closed reports for cleanup, primary, resolved, execution_failure and retry; related #4475/#4619 concern firmware ownership/input growth, rather than shared post-recovery projection.
  • No credentials or private target data included.

Area

Evidence, artifacts, or reconstruction

Observed behavior

A shared composite error changes from cleanup_incomplete to execution_failure after its cleanup dependency confirms release, although its retained primary is AnalysisInputError / invalid_request. This was executed against compiled production domain code on main 8451d2839 (domain files unchanged in the local firmware patch). It is a domain-boundary reproduction, not a real-provider or public CLI reproduction.

Reproduction

Construct AnalysisInputError('inspect_firmware_regions', ..., [{path:['path'], reason:'out_of_range', message:'input exceeded its supported allowance'}]) and ProviderCleanupError('binwalk', ['selected.bin'], {reason:'close denied'}, {operation:'inspect_firmware_regions'}). Compose them with analysisErrorWithCleanupFailure(primary, cleanup, operation).bindCleanupDependencies([primary, cleanup]). Project the composite, call cleanup.resolveCleanup(), and project it again.

Expected behavior

Once every owned cleanup dependency confirms release, the failure should retain the typed primary outcome and its appropriate recovery. Historical cleanup diagnostics may remain; they must not turn a known input failure into an unknown provider execution failure.

Impact and scope

P2: machine-readable consumers can misclassify an already recovered input refusal. No leak, data loss, real-provider frequency or downstream incident established. Other primary types need explicit controls before a repair is generalized.

REA version

6.5.0; main 8451d28392. Shared domain sources are unchanged in the local firmware investigation.

Runtime and platform

Node 24.18.0, Darwin arm64.

Target and artifact context

No target; expected error objects and explicit cleanup completion at the production domain boundary.

Interface

CLI and MCP share the projection; transport reachability is source-derived and was not executed for this report.

Earliest failure stage

Transport or result projection

Relevant output or evidence

Observed result:

{"before":"cleanup_incomplete","after":"execution_failure","cleanup_incomplete":false,"primary":"invalid_request"}

src/domain/analysisErrorCleanup.ts creates a generic ProviderAdapterError and snapshots the primary into JSON diagnostics. src/domain/analysisErrorProjection.ts switches to the wrapper's generic underlying code when cleanup clears. AnalysisError.bindCleanupDependencies correctly updates cleanup completion but cannot restore the primary type lost by composition.

Evidence provenance: observed domain reproduction plus source-derived explanation. No provider or public transport reproduction claimed.

Typed outcome or recovery expected

Preserve an explicit typed primary reference through composition and confirmed cleanup, with regressions for input, cancellation, timeout and resource failures, mixed cleanup dependencies and failed retry. Do not infer primary identity by parsing diagnostic text/JSON.

Analysis or suspected cause

The composite representation replaces the typed primary with a generic adapter error. Live cleanup dependency ownership and error-kind ownership are separate facts; resolving one does not restore the other.

Additional context

Found while adding firmware snapshot growth and exact-descriptor retry controls for #4619. Firmware stream ownership/input classification can be repaired independently; this shared error-model defect requires its own consumers and projection audit. NOT_ENOUGH_INFO: real provider frequency and downstream impact.

Originally created by @morluto on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4628 ### Before submitting - [x] Searched open and closed reports for cleanup, primary, resolved, execution_failure and retry; related #4475/#4619 concern firmware ownership/input growth, rather than shared post-recovery projection. - [x] No credentials or private target data included. ### Area Evidence, artifacts, or reconstruction ### Observed behavior A shared composite error changes from `cleanup_incomplete` to `execution_failure` after its cleanup dependency confirms release, although its retained primary is `AnalysisInputError` / `invalid_request`. This was executed against compiled production domain code on main 8451d2839 (domain files unchanged in the local firmware patch). It is a domain-boundary reproduction, not a real-provider or public CLI reproduction. ### Reproduction Construct `AnalysisInputError('inspect_firmware_regions', ..., [{path:['path'], reason:'out_of_range', message:'input exceeded its supported allowance'}])` and `ProviderCleanupError('binwalk', ['selected.bin'], {reason:'close denied'}, {operation:'inspect_firmware_regions'})`. Compose them with `analysisErrorWithCleanupFailure(primary, cleanup, operation).bindCleanupDependencies([primary, cleanup])`. Project the composite, call `cleanup.resolveCleanup()`, and project it again. ### Expected behavior Once every owned cleanup dependency confirms release, the failure should retain the typed primary outcome and its appropriate recovery. Historical cleanup diagnostics may remain; they must not turn a known input failure into an unknown provider execution failure. ### Impact and scope P2: machine-readable consumers can misclassify an already recovered input refusal. No leak, data loss, real-provider frequency or downstream incident established. Other primary types need explicit controls before a repair is generalized. ### REA version 6.5.0; main 8451d283920e86936576fdf67615807d1b4ca4a9. Shared domain sources are unchanged in the local firmware investigation. ### Runtime and platform Node 24.18.0, Darwin arm64. ### Target and artifact context No target; expected error objects and explicit cleanup completion at the production domain boundary. ### Interface CLI and MCP share the projection; transport reachability is source-derived and was not executed for this report. ### Earliest failure stage Transport or result projection ### Relevant output or evidence Observed result: ```json {"before":"cleanup_incomplete","after":"execution_failure","cleanup_incomplete":false,"primary":"invalid_request"} ``` `src/domain/analysisErrorCleanup.ts` creates a generic `ProviderAdapterError` and snapshots the primary into JSON diagnostics. `src/domain/analysisErrorProjection.ts` switches to the wrapper's generic underlying code when cleanup clears. `AnalysisError.bindCleanupDependencies` correctly updates cleanup completion but cannot restore the primary type lost by composition. Evidence provenance: observed domain reproduction plus source-derived explanation. No provider or public transport reproduction claimed. ### Typed outcome or recovery expected Preserve an explicit typed primary reference through composition and confirmed cleanup, with regressions for input, cancellation, timeout and resource failures, mixed cleanup dependencies and failed retry. Do not infer primary identity by parsing diagnostic text/JSON. ### Analysis or suspected cause The composite representation replaces the typed primary with a generic adapter error. Live cleanup dependency ownership and error-kind ownership are separate facts; resolving one does not restore the other. ### Additional context Found while adding firmware snapshot growth and exact-descriptor retry controls for #4619. Firmware stream ownership/input classification can be repaired independently; this shared error-model defect requires its own consumers and projection audit. NOT_ENOUGH_INFO: real provider frequency and downstream impact.
Author
Owner

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

Implemented in 3e8236639a, pushed to main.

The composition now retains its typed primary explicitly. Projection and presentation recover that primary only after live cleanup ownership confirms release; they do not infer release from resource names or diagnostic JSON. Primary diagnostics remain unchanged, and composition snapshots remain separately in details.cleanup_history. Captured output and late partial observations survive. Existing dependency binding stays explicit.

Validation executed:

  • 155 focused tests across 10 files passed, including domain input/cancellation/timeout/resource/output controls, nested owners in both release orders, real firmware descriptor retry, CLI projection, MCP failed/successful exact-owner retry on the same SDK connection, and JEB/managed/ADB/Kuna cleanup consumers.
  • Two additional source controls passed for unbound ownership and late partial observations (69 tests across the three domain files after adding them).
  • Typecheck/lint, docs checks and five documentation conformance controls passed; normal commit and pre-push checks passed.
  • A bounded compiled production-domain task (primary failure, denied cleanup retry, successful retry, final projection) changes the final code from execution_failure to invalid_request. Two alternating warm repeats per build: elapsed median 0.05859/0.05852 seconds, CPU 0.03815/0.03804 seconds, sampled peak process-family RSS 60,915,712/60,956,672 bytes; raw replies across all three projections 849/853 cl100k_base tokens. First processes recorded separately; true cold, whole-agent, catalog, request, CLI/MCP transport cost and native-provider cost unmeasured. No performance improvement claimed.

Scope: CLI and MCP controls use controlled provider ports. The firmware regression exercises native descriptor ownership, not a native firmware engine. No real IDA/JEB/ADB/Kuna engine verification or real-provider incidence claimed. Heavy Qodo/profiler jobs were not restarted.

<!-- gh-comment-id:6227727353 --> @morluto commented on GitHub (Oct 17, 2026): Implemented in 3e8236639abffa39deb5d5e939ec8baf6aaf3ca3, pushed to main. The composition now retains its typed primary explicitly. Projection and presentation recover that primary only after live cleanup ownership confirms release; they do not infer release from resource names or diagnostic JSON. Primary diagnostics remain unchanged, and composition snapshots remain separately in `details.cleanup_history`. Captured output and late partial observations survive. Existing dependency binding stays explicit. Validation executed: - 155 focused tests across 10 files passed, including domain input/cancellation/timeout/resource/output controls, nested owners in both release orders, real firmware descriptor retry, CLI projection, MCP failed/successful exact-owner retry on the same SDK connection, and JEB/managed/ADB/Kuna cleanup consumers. - Two additional source controls passed for unbound ownership and late partial observations (69 tests across the three domain files after adding them). - Typecheck/lint, docs checks and five documentation conformance controls passed; normal commit and pre-push checks passed. - A bounded compiled production-domain task (primary failure, denied cleanup retry, successful retry, final projection) changes the final code from `execution_failure` to `invalid_request`. Two alternating warm repeats per build: elapsed median 0.05859/0.05852 seconds, CPU 0.03815/0.03804 seconds, sampled peak process-family RSS 60,915,712/60,956,672 bytes; raw replies across all three projections 849/853 cl100k_base tokens. First processes recorded separately; true cold, whole-agent, catalog, request, CLI/MCP transport cost and native-provider cost unmeasured. No performance improvement claimed. Scope: CLI and MCP controls use controlled provider ports. The firmware regression exercises native descriptor ownership, not a native firmware engine. No real IDA/JEB/ADB/Kuna engine verification or real-provider incidence claimed. Heavy Qodo/profiler jobs were not restarted.
Author
Owner

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

Verified the existing fix in 3e8236639, which is already an ancestor of current main.

The root cause was loss of the typed primary during cleanup composition. The fix retains that primary and lets projection/presentation recover it only after live cleanup ownership confirms release; historical diagnostics remain separate. This avoids reconstructing type from diagnostic JSON or treating a retry attempt as confirmed release.

Current validation passed: 11 domain cleanup tests, four compiled CLI projection tests and one public MCP cleanup-retry test. These include typed outcomes, mixed/nested ownership, denied retry and retained late facts. The issue and affected producers/consumers were reread; no additional patch was needed. This does not qualify real-provider behavior or the rest of the lifecycle audit.

<!-- gh-comment-id:6253745187 --> @morluto commented on GitHub (Oct 18, 2026): Verified the existing fix in [3e8236639](https://github.com/morluto/rea/commit/3e8236639abffa39deb5d5e939ec8baf6aaf3ca3), which is already an ancestor of current main. The root cause was loss of the typed primary during cleanup composition. The fix retains that primary and lets projection/presentation recover it only after live cleanup ownership confirms release; historical diagnostics remain separate. This avoids reconstructing type from diagnostic JSON or treating a retry attempt as confirmed release. Current validation passed: 11 domain cleanup tests, four compiled CLI projection tests and one public MCP cleanup-retry test. These include typed outcomes, mixed/nested ownership, denied retry and retained late facts. The issue and affected producers/consumers were reread; no additional patch was needed. This does not qualify real-provider behavior or the rest of the lifecycle audit.
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#2409
No description provided.