[GH-ISSUE #5205] [Bug] Ownership liveness rechecks drop process-settlement cancellation #3191

Closed
opened 2026-10-31 00:37:41 +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/5205

Before submitting

  • Searched open and closed issues for related reports.
  • Removed credentials and sensitive target data.

Area / interface / failure stage

Process capture or runtime observation; shared production ownership-observation boundary used during CLI/MCP settlement; cleanup, cancellation, or lifecycle.

Observed behavior

When a run-token read is unavailable, observeOwnedProcessGroups starts a liveness recheck without the caller's abort signal. A deterministic source-boundary regression shows the cancelled observation stays pending until that second process-table read is explicitly released. Only then does it reject with the caller's original reason.

Reproduction

On source ca71e91d23672646af917ede8ae82c7fea395341, add a regression to src/process/ProcessOwnership.observation.test.ts: initial listing returns an owned-group member; its token is unavailable; hold the second listing behind an explicit release barrier, honoring any received abort signal. Wait for second-list entry, abort with a specific Error, and inspect observation settlement after an event-loop turn before releasing the barrier in finally.

Ran pinned Node 24.18.0: npm run test:local -- src/process/ProcessOwnership.observation.test.ts. The new case failed (settledBeforeRelease was false); the other 10 tests passed. The second listing received no signal. After explicit release, the observation rejected with the exact caller reason. No group was signaled.

Expected behavior

Carry the accepted abort signal through the per-member liveness recheck and await the host's cancellation finalization. Cancellation must also survive a host returning a successful late listing. A genuine inspection failure without cancellation should remain unverifiable.

Impact and scope

Source-derived consequence: a slow ps liveness probe can delay cancelling process-capture settlement even though the initial table/token reads support cancellation. The production host already supervises abort through command exit (#5199); the recheck does not receive that control. The runtime reproduction uses a controlled host boundary, not naturally delayed system ps. Native Linux/Windows behavior was not reproduced.

REA version / runtime / target

Source ca71e91d23672646af917ede8ae82c7fea395341; macOS arm64; Node 24.18.0. Controlled process-table/token host, no target execution.

Relevant evidence and analysis

The test's before-release assertion was expected false to be true. The group observer omits the signal when calling processIsGone; that helper calls host.listProcesses() and treats all rejection as an optional probe failure. Forward the signal and preserve cancellation at this owner. Related #4322 concerns ownership/exit reconciliation and remains separate; this fix does not relax mismatch policy.

Originally created by @morluto on GitHub (Oct 19, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5205 ### Before submitting - [x] Searched open and closed issues for related reports. - [x] Removed credentials and sensitive target data. ### Area / interface / failure stage Process capture or runtime observation; shared production ownership-observation boundary used during CLI/MCP settlement; cleanup, cancellation, or lifecycle. ### Observed behavior When a run-token read is unavailable, `observeOwnedProcessGroups` starts a liveness recheck without the caller's abort signal. A deterministic source-boundary regression shows the cancelled observation stays pending until that second process-table read is explicitly released. Only then does it reject with the caller's original reason. ### Reproduction On source `ca71e91d23672646af917ede8ae82c7fea395341`, add a regression to `src/process/ProcessOwnership.observation.test.ts`: initial listing returns an owned-group member; its token is unavailable; hold the second listing behind an explicit release barrier, honoring any received abort signal. Wait for second-list entry, abort with a specific Error, and inspect observation settlement after an event-loop turn before releasing the barrier in `finally`. Ran pinned Node 24.18.0: `npm run test:local -- src/process/ProcessOwnership.observation.test.ts`. The new case failed (`settledBeforeRelease` was false); the other 10 tests passed. The second listing received no signal. After explicit release, the observation rejected with the exact caller reason. No group was signaled. ### Expected behavior Carry the accepted abort signal through the per-member liveness recheck and await the host's cancellation finalization. Cancellation must also survive a host returning a successful late listing. A genuine inspection failure without cancellation should remain unverifiable. ### Impact and scope Source-derived consequence: a slow `ps` liveness probe can delay cancelling process-capture settlement even though the initial table/token reads support cancellation. The production host already supervises abort through command exit (#5199); the recheck does not receive that control. The runtime reproduction uses a controlled host boundary, not naturally delayed system `ps`. Native Linux/Windows behavior was not reproduced. ### REA version / runtime / target Source `ca71e91d23672646af917ede8ae82c7fea395341`; macOS arm64; Node 24.18.0. Controlled process-table/token host, no target execution. ### Relevant evidence and analysis The test's before-release assertion was `expected false to be true`. [The group observer](https://github.com/morluto/rea/blob/ca71e91d23672646af917ede8ae82c7fea395341/src/process/ProcessOwnershipObservation.ts#L80) omits the signal when calling `processIsGone`; [that helper](https://github.com/morluto/rea/blob/ca71e91d23672646af917ede8ae82c7fea395341/src/process/ProcessOwnershipObservation.ts#L564) calls `host.listProcesses()` and treats all rejection as an optional probe failure. Forward the signal and preserve cancellation at this owner. Related #4322 concerns ownership/exit reconciliation and remains separate; this fix does not relax mismatch policy.
bsakaguchi 2026-10-31 00:37:41 +00:00
  • closed this issue
  • added the
    triage
    bug
    labels
Author
Owner

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

Fixed on main in 39275420ea.

The per-member liveness fallback dropped the accepted abort signal after a token read failed. It now forwards that signal into the process-table owner and preserves cancellation instead of classifying it as an optional inspection failure. A host returning success after abort still rejects with the exact caller reason. Uncancelled probe failures remain unverifiable, and callers without a signal retain the same invocation behavior.

The held-second-list regression failed on ca71e91d2: cancellation could not settle until the fixture explicitly released the listing. Both cancellation regressions now pass. The focused selection passed 55 tests, including ownership validation, settlement deadlines, real macOS CLI/MCP cancellation, and the five POSIX command-finalization controls. The final observation file passed 12 tests after splitting its test groups to meet the repository lint limit. npm run check and npm run docs:check passed.

Three real CLI captures preserved the same terminal/normal-exit/verified-cleanup oracle. Repeated candidate medians: elapsed 1.998 s, process-family CPU 1.899 s, sampled family peak RSS 518.3 MB, full reply 2,060 estimated cl100k tokens / 7,642 bytes. Earlier e8da baseline medians were 1.949 s / 1.839 s / 515.0 MB / 2,063 estimated tokens / 7,642 bytes. These small, non-alternating runs cover the accumulated sampling changes, not an isolated performance effect of signal forwarding; true cold runs, actual agent task tokens, and MCP discovery costs were not measured. No speedup claim.

The held-read interleaving is a controlled host-boundary reproduction. Native Linux/Windows behavior was not verified. The separate #4322 ownership/exit reconciliation remains unresolved; this change preserves the current ownership policy and does not discard or reinterpret token mismatch facts.

<!-- gh-comment-id:6262439873 --> @morluto commented on GitHub (Oct 19, 2026): Fixed on `main` in 39275420ea18ad803eccfcc2702865b98ed36e44. The per-member liveness fallback dropped the accepted abort signal after a token read failed. It now forwards that signal into the process-table owner and preserves cancellation instead of classifying it as an optional inspection failure. A host returning success after abort still rejects with the exact caller reason. Uncancelled probe failures remain unverifiable, and callers without a signal retain the same invocation behavior. The held-second-list regression failed on ca71e91d2: cancellation could not settle until the fixture explicitly released the listing. Both cancellation regressions now pass. The focused selection passed 55 tests, including ownership validation, settlement deadlines, real macOS CLI/MCP cancellation, and the five POSIX command-finalization controls. The final observation file passed 12 tests after splitting its test groups to meet the repository lint limit. `npm run check` and `npm run docs:check` passed. Three real CLI captures preserved the same terminal/normal-exit/verified-cleanup oracle. Repeated candidate medians: elapsed 1.998 s, process-family CPU 1.899 s, sampled family peak RSS 518.3 MB, full reply 2,060 estimated cl100k tokens / 7,642 bytes. Earlier e8da baseline medians were 1.949 s / 1.839 s / 515.0 MB / 2,063 estimated tokens / 7,642 bytes. These small, non-alternating runs cover the accumulated sampling changes, not an isolated performance effect of signal forwarding; true cold runs, actual agent task tokens, and MCP discovery costs were not measured. No speedup claim. The held-read interleaving is a controlled host-boundary reproduction. Native Linux/Windows behavior was not verified. The separate #4322 ownership/exit reconciliation remains unresolved; this change preserves the current ownership policy and does not discard or reinterpret token mismatch facts.
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#3191
No description provided.