[GH-ISSUE #5166] [Bug] Process cleanup reports share mutable state with retained resource authority #3174

Closed
opened 2026-10-31 00:37:30 +00:00 by bsakaguchi · 1 comment
Owner

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

Before submitting

  • Related #5144 covers stale status after real retry; #5140 covers unretained snapshot handles. Neither describes report edits changing the resource owner's completion decisions.
  • Controlled local paths/diagnostics only.

Area

Process capture lifecycle / cleanup ownership.

Observed behavior and evidence

A controlled compiled-boundary probe at dfe8378cf5 created a real temporary root and denied its removal. ProcessCaptureResourceScope.release() returned a failed cleanup report. After an explicit in-process Reflect.set(report.temporary_root, 'state', 'cleaned'), both retryCleanup() and close() resolved, with only one actual removal attempt and the real root still present.

{"closeResolved":true,"actualRemovalAttempts":1,"rootStillPresent":true,"controlledInProcessReportMutation":true}

The probe subsequently removed the exact root using real fs.rm. Reproduced once on macOS arm64 / Node24.18.0. A new source regression also reproduces the failure in the candidate #5144 ownership fix before the report boundary is detached.

Expected behavior / root cause

Cleanup reports are historical observations, not cleanup authority. The producer returns the same nested resource outcome objects held in private owner fields; changing a report changes the owner's retry decisions. Return independent report snapshots so only actual owner operations can confirm completion. A TypeScript readonly declaration does not separate object ownership at runtime.

Reproduction scope and limitations

This is deliberate in-process mutation of the returned report; no mutation through serialized CLI/MCP responses or target application is claimed. Natural frequency, affected callers and real-provider impact: NOT_ENOUGH_INFO. No native analysis engine or target process was launched. The resource and failed-removal/retry boundary were real; the denial and report edit were controlled.

Proposed validation

After editing a historical report, retry must still attempt the actual unresolved resource and reject while denial remains. Restore real removal, verify confirmed retry and ENOENT, and preserve historical reports independently of live cleanup status. Related #5144 should bind errors to exact owners without trusting mutable observation objects.

Originally created by @morluto on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5166 ### Before submitting - [x] Related #5144 covers stale status after real retry; #5140 covers unretained snapshot handles. Neither describes report edits changing the resource owner's completion decisions. - [x] Controlled local paths/diagnostics only. ### Area Process capture lifecycle / cleanup ownership. ### Observed behavior and evidence A controlled compiled-boundary probe at dfe8378cf5a727e3d93d47a5986233175c6ef898 created a real temporary root and denied its removal. `ProcessCaptureResourceScope.release()` returned a failed cleanup report. After an explicit in-process `Reflect.set(report.temporary_root, 'state', 'cleaned')`, both `retryCleanup()` and `close()` resolved, with only one actual removal attempt and the real root still present. ```json {"closeResolved":true,"actualRemovalAttempts":1,"rootStillPresent":true,"controlledInProcessReportMutation":true} ``` The probe subsequently removed the exact root using real `fs.rm`. Reproduced once on macOS arm64 / Node24.18.0. A new source regression also reproduces the failure in the candidate #5144 ownership fix before the report boundary is detached. ### Expected behavior / root cause Cleanup reports are historical observations, not cleanup authority. The producer returns the same nested resource outcome objects held in private owner fields; changing a report changes the owner's retry decisions. Return independent report snapshots so only actual owner operations can confirm completion. A TypeScript readonly declaration does not separate object ownership at runtime. ### Reproduction scope and limitations This is deliberate in-process mutation of the returned report; no mutation through serialized CLI/MCP responses or target application is claimed. Natural frequency, affected callers and real-provider impact: NOT_ENOUGH_INFO. No native analysis engine or target process was launched. The resource and failed-removal/retry boundary were real; the denial and report edit were controlled. ### Proposed validation After editing a historical report, retry must still attempt the actual unresolved resource and reject while denial remains. Restore real removal, verify confirmed retry and ENOENT, and preserve historical reports independently of live cleanup status. Related #5144 should bind errors to exact owners without trusting mutable observation objects.
Author
Owner

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

Fixed on main in 974487f00.

The owner's report getter now returns an independent snapshot of all three resource outcomes, including nested unverified-process facts. Cleanup decisions remain private to the resource owner. The report and its exact retry lease are distinct values; changing the observation cannot change release authority.

The clean baseline probe showed one denied actual removal, successful scope close, and a still-present real root after deliberate in-process report mutation. The final regression verifies retry attempts the still-owned root again, remains incomplete while denial persists, and confirms actual removal after restoration. All six owner cases pass, with 72 affected tests/7 files passing after this final change; static/architecture, docs and discovery checks pass.

This fixes the controlled in-process ownership flaw. No mutation through serialized CLI/MCP output, target application, natural denial or real analysis-provider teardown is claimed.

<!-- gh-comment-id:6258635154 --> @morluto commented on GitHub (Oct 19, 2026): Fixed on main in [`974487f00`](https://github.com/morluto/rea/commit/974487f00f2d68912c7c2c9e033a2760a343a82e). The owner's report getter now returns an independent snapshot of all three resource outcomes, including nested unverified-process facts. Cleanup decisions remain private to the resource owner. The report and its exact retry lease are distinct values; changing the observation cannot change release authority. The clean baseline probe showed one denied actual removal, successful scope close, and a still-present real root after deliberate in-process report mutation. The final regression verifies retry attempts the still-owned root again, remains incomplete while denial persists, and confirms actual removal after restoration. All six owner cases pass, with 72 affected tests/7 files passing after this final change; static/architecture, docs and discovery checks pass. This fixes the controlled in-process ownership flaw. No mutation through serialized CLI/MCP output, target application, natural denial or real analysis-provider teardown is claimed.
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#3174
No description provided.