[GH-ISSUE #4928] [Bug] Initial artifact cleanup errors remain incomplete after exact owner recovery #3056

Closed
opened 2026-10-31 00:35:38 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • Searched open/closed artifact cleanup and retry reports, including #4458, #4865, #4866 and #4926.
  • Evidence uses repository tests and authored temporary files; no credentials or private artifacts.

Area

Evidence, artifacts, or reconstruction

Observed behavior

At main2183c9598, an initial artifact inventory/extraction cleanup error still reports cleanupIncomplete: true after its exact scope owner successfully releases the resource. Root descriptor admission and ASAR reader extraction both reproduce this. The scope can recover; the original error loses the link to that recovery.

This differs from #4866's capability-less metadata falsely resolving and #4926's kernel consumer refusing further admission. Here the real scope owns and releases the resource, but the initial caller-visible error remains stale.

Reproduction

Extended existing production-boundary regressions, retaining their actual temporary files and exact owner tracking:

  1. artifactInventoryDescriptorCleanup.test.ts: force root admission fstat failure and deny descriptor close, then allow close and call the same client close. The client succeeds and fd becomes -1; the original inventory error remains incomplete.
  2. artifactProvider.cleanupRetry.test.ts: deny the retained ASAR reader close during extraction, allow it, and close the same client. Its exact reader is closed; the original extraction error remains incomplete.
    Executed with npm run test:focused -- tests/boundary/filesystem/artifactInventoryDescriptorCleanup.test.ts tests/boundary/providers/native/artifactProvider.cleanupRetry.test.ts. Two added assertions failed; four existing controls passed. The invalidated-descriptor control correctly remains unresolved and was preserved.

Expected behavior

Bind initial and retry errors to the exact cleanup capabilities at the producing boundary. Confirmed release should resolve only the owners that error actually reports, including all owners in a composite. Preserve the original primary diagnostic and partial observations. Unknown or unconfirmed cleanup must remain incomplete. See docs/tool-design.md#own-the-lifecycle.

Impact and scope

Observed in the real inventory/extraction provider with controlled close failures and real authored files/ASAR. Source-derived: ArtifactResourceScope.release retains a canonical lease internally but returns only the close cause; generic ArtifactReaderFailure.withCleanup wrappers do not expose that lease to bindArtifactFileCleanup. Other initial scope release consumers need review for the same contract loss. NOT_ENOUGH_INFO for naturally occurring fault frequency, public CLI/MCP incident, or Windows/Linux qualification.

REA version

6.5.0 source2183c9598ca9315f5c6995ce37aefbad29c02208

Runtime and platform

Node24.18.0, macOS26.3 arm64.

Target and artifact context

Authored ordinary file and ASAR; no analyzed target program executed.

Interface

Other: production artifact provider and filesystem boundaries.

Earliest failure stage

Cleanup, cancellation, or lifecycle

Relevant output or evidence

Both added assertions expected false and received true for the original error.cleanupIncomplete after confirmed successful close. Existing assertions independently established exact owner reuse, close completion, descriptor fd=-1 and admission behavior. Relevant sources: ArtifactResourceScope.release, inventory/hashStableRootArtifact.ts, extraction/ArtifactExtraction.ts, ArtifactProvider.translateArtifactFailure.

Typed outcome or recovery expected

Initial and composite cleanup failures must carry their exact canonical leases through failure composition and provider translation, with unknown capability represented explicitly.

Originally created by @morluto on GitHub (Oct 18, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4928 ### Before submitting - [x] Searched open/closed artifact cleanup and retry reports, including #4458, #4865, #4866 and #4926. - [x] Evidence uses repository tests and authored temporary files; no credentials or private artifacts. ### Area Evidence, artifacts, or reconstruction ### Observed behavior At main2183c9598, an initial artifact inventory/extraction cleanup error still reports `cleanupIncomplete: true` after its exact scope owner successfully releases the resource. Root descriptor admission and ASAR reader extraction both reproduce this. The scope can recover; the original error loses the link to that recovery. This differs from #4866's capability-less metadata falsely resolving and #4926's kernel consumer refusing further admission. Here the real scope owns and releases the resource, but the initial caller-visible error remains stale. ### Reproduction Extended existing production-boundary regressions, retaining their actual temporary files and exact owner tracking: 1. `artifactInventoryDescriptorCleanup.test.ts`: force root admission fstat failure and deny descriptor close, then allow close and call the same client close. The client succeeds and fd becomes -1; the original inventory error remains incomplete. 2. `artifactProvider.cleanupRetry.test.ts`: deny the retained ASAR reader close during extraction, allow it, and close the same client. Its exact reader is closed; the original extraction error remains incomplete. Executed with `npm run test:focused -- tests/boundary/filesystem/artifactInventoryDescriptorCleanup.test.ts tests/boundary/providers/native/artifactProvider.cleanupRetry.test.ts`. Two added assertions failed; four existing controls passed. The invalidated-descriptor control correctly remains unresolved and was preserved. ### Expected behavior Bind initial and retry errors to the exact cleanup capabilities at the producing boundary. Confirmed release should resolve only the owners that error actually reports, including all owners in a composite. Preserve the original primary diagnostic and partial observations. Unknown or unconfirmed cleanup must remain incomplete. See `docs/tool-design.md#own-the-lifecycle`. ### Impact and scope Observed in the real inventory/extraction provider with controlled close failures and real authored files/ASAR. Source-derived: `ArtifactResourceScope.release` retains a canonical lease internally but returns only the close cause; generic `ArtifactReaderFailure.withCleanup` wrappers do not expose that lease to `bindArtifactFileCleanup`. Other initial scope release consumers need review for the same contract loss. NOT_ENOUGH_INFO for naturally occurring fault frequency, public CLI/MCP incident, or Windows/Linux qualification. ### REA version 6.5.0 source2183c9598ca9315f5c6995ce37aefbad29c02208 ### Runtime and platform Node24.18.0, macOS26.3 arm64. ### Target and artifact context Authored ordinary file and ASAR; no analyzed target program executed. ### Interface Other: production artifact provider and filesystem boundaries. ### Earliest failure stage Cleanup, cancellation, or lifecycle ### Relevant output or evidence Both added assertions expected false and received true for the original `error.cleanupIncomplete` after confirmed successful close. Existing assertions independently established exact owner reuse, close completion, descriptor fd=-1 and admission behavior. Relevant sources: `ArtifactResourceScope.release`, `inventory/hashStableRootArtifact.ts`, `extraction/ArtifactExtraction.ts`, `ArtifactProvider.translateArtifactFailure`. ### Typed outcome or recovery expected Initial and composite cleanup failures must carry their exact canonical leases through failure composition and provider translation, with unknown capability represented explicitly.
bsakaguchi 2026-10-31 00:35:38 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

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

Fixed on main in 2582c267a (shared contract) and bbfe6edd6 (inventory/extraction consumers).

The producing scope now returns each failed release's exact owner and canonical retry lease. Initial cleanup composition uses explicit completed/failed outcomes and retains attempts through root admission, hashing/classification, scanning, extraction rollback and nested JavaScript readers. The discarded cause/resource pairs and duplicated cleanup assembly were removed.

Artifact failures carry explicit complete cleanup authority; missing authority stays unknown. The common binder and affected resource/firmware consumers use that contract. Independent unknown primary cleanup cannot be cleared by a newly released peer. Completed file operations do not acquire an unrelated cleanup dependency from a typed close rejection. The scope also owns current parsed child-resource labels, so a mixed retry updates the original error to only the remaining children without replacing the lease.

Executed on macOS 26.3 arm64 / Node 24.18.0:

  • Baseline: two added assertions failed; four controls passed. Actual root and ASAR owners released successfully while original errors stayed incomplete.
  • Final: 137 tests passed in 18 executed files; 35 platform-dependent firmware tests skipped in one additional file. Includes real descriptor failure/retry and invalidation, mixed owners/children, initial and retry lease identity, standalone file ownership, independent unknown/domain cleanup, opaque cancellation reasons, retained complete inventory, nested readers, ZIP CLI extraction, public MCP artifact flows and controlled firmware file lifetimes.
  • check:fast, docs:check (five conformance tests), discovery 1569 exactly once, normal pre-commit/pre-push hooks passed. Hooks left tested content unchanged. Two bounded source reviews found no remaining blocker after corrections.

Bounded costs against separate baseline 2183c9598: six completed public CLI inspections of the same authored ten-file ZIP, independently verified file hashes and identical entire normalized result. Warm-filesystem medians: elapsed 0.437→0.449s, CPU 0.6600→0.6608 s, 10 ms sampled process-family peak RSS 345.57→341.50 MiB. Reply-only cl100k estimate 6196→6196 tokens. These tiny runs do not establish a speedup, large-archive bounds or recovery/extraction cost. OS caches were not flushed; sampling can miss transient/reparented children. Actual model/full-agent tokens and MCP costs remain unmeasured.

No native Linux/Windows or real firmware-engine qualification is claimed. Unreported cleanup authority remains unknown; the change does not infer ownership from paths, diagnostic strings or cause-chain searches. Heavy CPU stress and Flameox remain stopped. The broader issue/codebase audit remains active.

<!-- gh-comment-id:6243872198 --> @morluto commented on GitHub (Oct 18, 2026): Fixed on main in 2582c267a (shared contract) and bbfe6edd6 (inventory/extraction consumers). The producing scope now returns each failed release's exact owner and canonical retry lease. Initial cleanup composition uses explicit completed/failed outcomes and retains attempts through root admission, hashing/classification, scanning, extraction rollback and nested JavaScript readers. The discarded cause/resource pairs and duplicated cleanup assembly were removed. Artifact failures carry explicit complete cleanup authority; missing authority stays unknown. The common binder and affected resource/firmware consumers use that contract. Independent unknown primary cleanup cannot be cleared by a newly released peer. Completed file operations do not acquire an unrelated cleanup dependency from a typed close rejection. The scope also owns current parsed child-resource labels, so a mixed retry updates the original error to only the remaining children without replacing the lease. Executed on macOS 26.3 arm64 / Node 24.18.0: - Baseline: two added assertions failed; four controls passed. Actual root and ASAR owners released successfully while original errors stayed incomplete. - Final: 137 tests passed in 18 executed files; 35 platform-dependent firmware tests skipped in one additional file. Includes real descriptor failure/retry and invalidation, mixed owners/children, initial and retry lease identity, standalone file ownership, independent unknown/domain cleanup, opaque cancellation reasons, retained complete inventory, nested readers, ZIP CLI extraction, public MCP artifact flows and controlled firmware file lifetimes. - check:fast, docs:check (five conformance tests), discovery 1569 exactly once, normal pre-commit/pre-push hooks passed. Hooks left tested content unchanged. Two bounded source reviews found no remaining blocker after corrections. Bounded costs against separate baseline 2183c9598: six completed public CLI inspections of the same authored ten-file ZIP, independently verified file hashes and identical entire normalized result. Warm-filesystem medians: elapsed 0.437→0.449s, CPU 0.6600→0.6608 s, 10 ms sampled process-family peak RSS 345.57→341.50 MiB. Reply-only cl100k estimate 6196→6196 tokens. These tiny runs do not establish a speedup, large-archive bounds or recovery/extraction cost. OS caches were not flushed; sampling can miss transient/reparented children. Actual model/full-agent tokens and MCP costs remain unmeasured. No native Linux/Windows or real firmware-engine qualification is claimed. Unreported cleanup authority remains unknown; the change does not infer ownership from paths, diagnostic strings or cause-chain searches. Heavy CPU stress and Flameox remain stopped. The broader issue/codebase audit remains active.
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#3056
No description provided.