[GH-ISSUE #4578] [Bug] Cleanup aggregates keep released child resources in live diagnostics #2377

Closed
opened 2026-10-17 21:03:55 +00:00 by bsakaguchi · 3 comments
Owner

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

Before submitting

  • Searched open and closed issues for aggregate cleanup resource reports and exact cleanupResources references.
  • Removed credentials and private target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

Controlled domain reproduction: after one child of a cleanup aggregate confirms release, the aggregate correctly remains incomplete for its other child but cleanupResources and projectAnalysisError(...).details.resources still include the released child's resource. Nested aggregates repeat the stale list. Physical resource release and error ownership are simulated; this does not establish a real provider leak.

Reproduction

At source base f22e8e72685c05e372c62582c7bc5fcd085b2fa6 plus local registry audit work, added two focused domain controls to src/domain/providerCleanupError.test.ts. Create two ProviderCleanupError children, bind an aggregate using bindCleanupDependencies, bind that aggregate with a third child, then resolve the first child. Run npm run test:local -- src/domain/providerCleanupError.test.ts: both new controls fail because alpha-file/beta-file remains in the aggregate's live resources after its matching child resolved. The three existing tests pass.

Expected behavior

Derive the live cleanup resource list from the exact unresolved dependency owners, recursively through known bound groups. Preserve historical resource diagnostics separately. Keep the aggregate incomplete until every owner confirms release; do not clear siblings or guess release from resource text.

Impact and scope

Observed misleading cleanup resource attribution in the shared domain error projection. Natural provider incidence and platform-specific cleanup failures are NOT_ENOUGH_INFO. Found while addressing #4569 mixed profile outcomes. #4467 and earlier descriptor-owner reports concern cleanup flags/lease confirmation; this report isolates stale resource lists during partial group recovery.

REA version

Source f22e8e72685c05e372c62582c7bc5fcd085b2fa6 plus local registry audit work; the failing bound-error representation is unchanged at that base.

Runtime and platform

Node 24.18.0, macOS arm64; domain-only Vitest controls, no native engine or Windows cleanup run.

Target and artifact context

Synthetic resource names alpha-file, beta-file, third-file; no private target.

Interface

Other (shared CLI/MCP domain error projection).

Earliest failure stage

Cleanup, cancellation, or lifecycle.

Originally created by @morluto on GitHub (Oct 16, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4578 ### Before submitting - [x] Searched open and closed issues for aggregate cleanup resource reports and exact `cleanupResources` references. - [x] Removed credentials and private target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior **Controlled domain reproduction:** after one child of a cleanup aggregate confirms release, the aggregate correctly remains incomplete for its other child but `cleanupResources` and `projectAnalysisError(...).details.resources` still include the released child's resource. Nested aggregates repeat the stale list. Physical resource release and error ownership are simulated; this does not establish a real provider leak. ### Reproduction At source base `f22e8e72685c05e372c62582c7bc5fcd085b2fa6` plus local registry audit work, added two focused domain controls to `src/domain/providerCleanupError.test.ts`. Create two `ProviderCleanupError` children, bind an aggregate using `bindCleanupDependencies`, bind that aggregate with a third child, then resolve the first child. Run `npm run test:local -- src/domain/providerCleanupError.test.ts`: both new controls fail because `alpha-file`/`beta-file` remains in the aggregate's live resources after its matching child resolved. The three existing tests pass. ### Expected behavior Derive the live cleanup resource list from the exact unresolved dependency owners, recursively through known bound groups. Preserve historical resource diagnostics separately. Keep the aggregate incomplete until every owner confirms release; do not clear siblings or guess release from resource text. ### Impact and scope Observed misleading cleanup resource attribution in the shared domain error projection. Natural provider incidence and platform-specific cleanup failures are NOT_ENOUGH_INFO. Found while addressing #4569 mixed profile outcomes. #4467 and earlier descriptor-owner reports concern cleanup flags/lease confirmation; this report isolates stale resource lists during partial group recovery. ### REA version Source `f22e8e72685c05e372c62582c7bc5fcd085b2fa6` plus local registry audit work; the failing bound-error representation is unchanged at that base. ### Runtime and platform Node 24.18.0, macOS arm64; domain-only Vitest controls, no native engine or Windows cleanup run. ### Target and artifact context Synthetic resource names `alpha-file`, `beta-file`, `third-file`; no private target. ### Interface Other (shared CLI/MCP domain error projection). ### Earliest failure stage Cleanup, cancellation, or lifecycle.
Author
Owner

@nikhilsaxena04 commented on GitHub (Oct 16, 2026):

I've investigated and fixed this issue on branch fix/4578-cleanup-aggregate-live-resources (diff & branch comparison).

Cause & Fix

  • Root Cause: AnalysisError.cleanupResources was statically initialized at construction time. When one child of a composed cleanup aggregate resolves its cleanup, the aggregate correctly remains incomplete for other active children, but its live cleanupResources list retained the released child's resource.
  • Fix:
    1. Updated AnalysisError to dynamically refresh live cleanup resources from active, unresolved dependencies upon dependency binding and resolution, recursively propagating updates down through dependent aggregates.
    2. In AnalysisError.resolveCleanup(), pruned released dependencies and cleared cleanupResources once all bound dependencies confirm release.
    3. In ProviderCleanupError, passed cleanup options with resources to super() to inherit base lifecycle state without property shadowing.
    4. Added focused unit tests in src/domain/providerCleanupError.test.ts verifying that child resolution removes released resources from the aggregate and nested aggregates while preserving historical diagnostics.

All unit tests and npm run check:fast pass cleanly.

<!-- gh-comment-id:6225048497 --> @nikhilsaxena04 commented on GitHub (Oct 16, 2026): I've investigated and fixed this issue on branch `fix/4578-cleanup-aggregate-live-resources` ([diff & branch comparison](https://github.com/morluto/rea/compare/main...nikhilsaxena04:fix/4578-cleanup-aggregate-live-resources)). ### Cause & Fix - **Root Cause**: `AnalysisError.cleanupResources` was statically initialized at construction time. When one child of a composed cleanup aggregate resolves its cleanup, the aggregate correctly remains incomplete for other active children, but its live `cleanupResources` list retained the released child's resource. - **Fix**: 1. Updated `AnalysisError` to dynamically refresh live cleanup resources from active, unresolved dependencies upon dependency binding and resolution, recursively propagating updates down through dependent aggregates. 2. In `AnalysisError.resolveCleanup()`, pruned released dependencies and cleared `cleanupResources` once all bound dependencies confirm release. 3. In `ProviderCleanupError`, passed cleanup options with resources to `super()` to inherit base lifecycle state without property shadowing. 4. Added focused unit tests in `src/domain/providerCleanupError.test.ts` verifying that child resolution removes released resources from the aggregate and nested aggregates while preserving historical diagnostics. All unit tests and `npm run check:fast` pass cleanly.
Author
Owner

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

Addressed a remaining final-release edge in 26bb85c007 on main. Clearing the last cleanup dependency previously made an empty bound set look unbound, restoring historical resource names even though cleanupIncomplete was false. The owner now distinguishes never-bound attribution from a bound, completed dependency set; historical cleanup.resources remains intact.

An isolated domain regression failed on the baseline. The native plist mixed file/tracer-owner control also exercises partial then final release: live resources shrink to the pending tracer, then become empty after both owners confirm completion. No real LLDB process was used. The final post-rebase 156-test focused run passed, including shared cleanup/error projections and native boundaries; static/docs and push checks passed. Native integration is in e09a503f44 (#4723).

<!-- gh-comment-id:6231891110 --> @morluto commented on GitHub (Oct 17, 2026): Addressed a remaining final-release edge in 26bb85c007109dd4eed11a5b9fcbd39f494f0b6e on main. Clearing the last cleanup dependency previously made an empty bound set look unbound, restoring historical resource names even though cleanupIncomplete was false. The owner now distinguishes never-bound attribution from a bound, completed dependency set; historical cleanup.resources remains intact. An isolated domain regression failed on the baseline. The native plist mixed file/tracer-owner control also exercises partial then final release: live resources shrink to the pending tracer, then become empty after both owners confirm completion. No real LLDB process was used. The final post-rebase 156-test focused run passed, including shared cleanup/error projections and native boundaries; static/docs and push checks passed. Native integration is in e09a503f44fba1639b71907a018d71161360f5ae (#4723).
Author
Owner

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

Closing as fixed on main after reconciling this report with the landed owner/consumer changes.

  • 26bb85c00: fix(core): keep released cleanup dependencies empty.
  • bf7fad390: fix(cleanup): project resources from unresolved owners.

Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.

<!-- gh-comment-id:6256002595 --> @morluto commented on GitHub (Oct 18, 2026): <!-- rea-backlog-reconciliation-2026-10-19-4578 --> Closing as fixed on `main` after reconciling this report with the landed owner/consumer changes. - [26bb85c00](https://github.com/morluto/rea/commit/26bb85c007109dd4eed11a5b9fcbd39f494f0b6e): fix(core): keep released cleanup dependencies empty. - [bf7fad390](https://github.com/morluto/rea/commit/bf7fad390c26db32d39671429ba35418ff2506da): fix(cleanup): project resources from unresolved owners. Evidence scope: this closure uses the landed source, regression coverage and validation already recorded in the linked commits/thread. No new local tests or native-provider reproduction were run during this backlog pass; previously documented platform and real-provider gaps still apply.
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#2377
No description provided.