[GH-ISSUE #4686] [Bug] EVM command failure conversion drops the owner-recorded cancellation reason #2445

Closed
opened 2026-10-17 21:04:45 +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/4686

Before submitting

  • I searched open and closed issues and PRs for EVM cancellation reasons and EvmoleFailures.
  • The evidence contains no credentials or private target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

A direct compiled adapter invocation converts an OwnedCommandFailure with an exact owner-recorded cancellation reason into AnalysisCancelledError with cause === undefined. No EVM worker or public CLI/MCP reproduction was performed.

Reproduction

On the pinned Node toolchain after building:

import { OwnedCommandFailure } from './dist/process/OwnedCommand.js';
import { evmInterfaceFailure } from './dist/evm/EvmoleFailures.js';
const reason = { requested: 'stop owned command' };
const source = new OwnedCommandFailure('cancelled', 'controlled cancellation', null, null, { cancellation: { reason } });
const result = evmInterfaceFailure(source, 'worker', '/authored/selected.hex');
console.log(source.cancellation.reason === reason, result._tag, result.cause === reason, result.cause === undefined);

Executed once; output: true AnalysisCancelledError false true.

Expected behavior

Preserve the owner's exact opaque reason in the typed cancellation cause. docs/tool-design.md requires caller reasons to survive owner/adaptor wrapping without interpretation.

Impact and scope

Confirmed reason loss at the EVM command-failure adapter. Public occurrence frequency and client impact are NOT_ENOUGH_INFO: no real command cancellation, EVM engine or client delivery was exercised. Timeout, physical failure and cleanup classifications must remain distinct.

REA version

Source d694aef22 (the unchanged failure adapter is also present at parent 585308988). Compiled local runtime used for the probe.

Runtime and platform

Node 24.18.0; Darwin arm64. EVM production profile requires Linux x64; this probe exercises only platform-independent failure projection.

Target and artifact context

No target loaded; /authored/selected.hex is an explicit synthetic diagnostic path.

Interface

Other: provider failure adapter, consumed by CLI/MCP workflows.

Earliest failure stage

Transport or result projection

Relevant output or evidence

src/evm/EvmoleFailures.ts, cause.reason === "cancelled" branch copies output and cleanup fields but omits cause.cancellation.reason. src/process/OwnedCommand.ts retains the opaque reason separately from physical errors. The direct invocation above confirmed the omission.

Typed outcome or recovery expected

AnalysisCancelledError.cause === reason, including null, strings, objects and typed error objects; do not adopt cleanup authority from the reason. Preserve original output. A physical failure with a recorded later cancellation must stay physical, and unresolved cleanup must keep its classification.

Additional context

Related #4638 concerns shared-command provenance; #4683 concerns completed EVM Evidence during final root removal. This is the remaining EVM command-failure consumer. No regression range established. Proposed checks: exact reason identity, physical/timeout precedence, captured output and cleanup controls.

Originally created by @morluto on GitHub (Oct 17, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/4686 ### Before submitting - [x] I searched open and closed issues and PRs for EVM cancellation reasons and EvmoleFailures. - [x] The evidence contains no credentials or private target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior A direct compiled adapter invocation converts an `OwnedCommandFailure` with an exact owner-recorded cancellation reason into `AnalysisCancelledError` with `cause === undefined`. No EVM worker or public CLI/MCP reproduction was performed. ### Reproduction On the pinned Node toolchain after building: ```js import { OwnedCommandFailure } from './dist/process/OwnedCommand.js'; import { evmInterfaceFailure } from './dist/evm/EvmoleFailures.js'; const reason = { requested: 'stop owned command' }; const source = new OwnedCommandFailure('cancelled', 'controlled cancellation', null, null, { cancellation: { reason } }); const result = evmInterfaceFailure(source, 'worker', '/authored/selected.hex'); console.log(source.cancellation.reason === reason, result._tag, result.cause === reason, result.cause === undefined); ``` Executed once; output: `true AnalysisCancelledError false true`. ### Expected behavior Preserve the owner's exact opaque reason in the typed cancellation cause. `docs/tool-design.md` requires caller reasons to survive owner/adaptor wrapping without interpretation. ### Impact and scope Confirmed reason loss at the EVM command-failure adapter. Public occurrence frequency and client impact are NOT_ENOUGH_INFO: no real command cancellation, EVM engine or client delivery was exercised. Timeout, physical failure and cleanup classifications must remain distinct. ### REA version Source d694aef22 (the unchanged failure adapter is also present at parent 585308988). Compiled local runtime used for the probe. ### Runtime and platform Node 24.18.0; Darwin arm64. EVM production profile requires Linux x64; this probe exercises only platform-independent failure projection. ### Target and artifact context No target loaded; `/authored/selected.hex` is an explicit synthetic diagnostic path. ### Interface Other: provider failure adapter, consumed by CLI/MCP workflows. ### Earliest failure stage Transport or result projection ### Relevant output or evidence `src/evm/EvmoleFailures.ts`, `cause.reason === "cancelled"` branch copies output and cleanup fields but omits `cause.cancellation.reason`. `src/process/OwnedCommand.ts` retains the opaque reason separately from physical errors. The direct invocation above confirmed the omission. ### Typed outcome or recovery expected `AnalysisCancelledError.cause === reason`, including null, strings, objects and typed error objects; do not adopt cleanup authority from the reason. Preserve original output. A physical failure with a recorded later cancellation must stay physical, and unresolved cleanup must keep its classification. ### Additional context Related #4638 concerns shared-command provenance; #4683 concerns completed EVM Evidence during final root removal. This is the remaining EVM command-failure consumer. No regression range established. Proposed checks: exact reason identity, physical/timeout precedence, captured output and cleanup controls.
Author
Owner

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

Published in 0ec4826633 on main.

The EVM failure consumer now copies OwnedCommandFailure.cancellation.reason as the exact opaque cancellation cause. It neither resamples a signal nor interprets a typed reason as cleanup authority. Existing physical, timeout and unresolved-cleanup branches keep precedence.

The direct compiled probe now reports exact reason identity preserved. On unchanged adapter code, four exact-reason controls failed and four positive/precedence controls passed; all eight pass after the repair. Controls include undefined, null, string, object and typed cancellation reasons, retained stdout/stderr, physical and timeout outcomes, and unresolved cleanup resources. The typed reason's foreign cleanup marker is not adopted. The overlapping service/adapter run passed 21 checks; check:fast, docs:check with five README checks, and normal commit/pre-push hooks passed.

Scope is the platform-independent EVM failure boundary on Node24.18/Darwin arm64. No real Linux x64 worker cancellation, public CLI/MCP cancellation delivery, performance or peak-family-memory measurement was performed. Related #4683 retains its supported-host runtime verification gap.

<!-- gh-comment-id:6230083957 --> @morluto commented on GitHub (Oct 17, 2026): Published in 0ec4826633482be4ac3bbc194cc677f50db72a87 on main. The EVM failure consumer now copies `OwnedCommandFailure.cancellation.reason` as the exact opaque cancellation cause. It neither resamples a signal nor interprets a typed reason as cleanup authority. Existing physical, timeout and unresolved-cleanup branches keep precedence. The direct compiled probe now reports exact reason identity preserved. On unchanged adapter code, four exact-reason controls failed and four positive/precedence controls passed; all eight pass after the repair. Controls include undefined, null, string, object and typed cancellation reasons, retained stdout/stderr, physical and timeout outcomes, and unresolved cleanup resources. The typed reason's foreign cleanup marker is not adopted. The overlapping service/adapter run passed 21 checks; `check:fast`, `docs:check` with five README checks, and normal commit/pre-push hooks passed. Scope is the platform-independent EVM failure boundary on Node24.18/Darwin arm64. No real Linux x64 worker cancellation, public CLI/MCP cancellation delivery, performance or peak-family-memory measurement was performed. Related #4683 retains its supported-host runtime verification gap.
Author
Owner

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

Reconciled against current main (279c590ef). The adapter repair is already present in 0ec482663: the cancelled OwnedCommandFailure branch passes cause.cancellation?.reason as the typed cancellation cause.

Fresh validation: all eight src/evm/EvmoleFailures.test.ts controls passed, including exact undefined/null/string/object/foreign typed reasons, captured output, and primary physical/timeout/cleanup precedence. No duplicate production repair was needed.

This verifies the same direct adapter boundary reported here; no real EVM worker, native Linux limiter or public OS-signal delivery is claimed. Closing as addressed.

<!-- gh-comment-id:6244418028 --> @morluto commented on GitHub (Oct 18, 2026): Reconciled against current main (279c590ef). The adapter repair is already present in 0ec482663: the cancelled OwnedCommandFailure branch passes cause.cancellation?.reason as the typed cancellation cause. Fresh validation: all eight src/evm/EvmoleFailures.test.ts controls passed, including exact undefined/null/string/object/foreign typed reasons, captured output, and primary physical/timeout/cleanup precedence. No duplicate production repair was needed. This verifies the same direct adapter boundary reported here; no real EVM worker, native Linux limiter or public OS-signal delivery is claimed. Closing as addressed.
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#2445
No description provided.