[P0] Async Future boundary swallows control exceptions from MCP and other runtimes #162

Closed
opened 2026-08-21 23:02:43 +00:00 by lost-rob0t · 1 comment
lost-rob0t commented 2026-08-21 23:02:43 +00:00 (Migrated from github.com)

Failure

The restored aggregate PlUnit suite exposes at least two previously hidden failures:

  • rlm_mcp_2026_matrix_test:cancellation_control_exception_propagates reports no_exception;
  • rlm_mcp_dual_test:time_limit_exception_propagates_through_server reports no_exception.

The domain runtime does rethrow these control exceptions. They are lost one layer later: rlm_async:async_execute_task/2 catches every worker exception and async_exception_outcome/3 stringifies it into an ordinary async_error{kind:exception,...}. Synchronous facades then await the Future and can no longer recover the control exception.

Required invariant

The canonical Future boundary must distinguish control-flow exceptions from ordinary failures:

  • preserve supported cancellation/abort/time-limit control exceptions as ground data in the terminal Future state;
  • rlm_future_await/[2,3] must rethrow a preserved control exception;
  • ordinary exceptions must remain structured async_error{kind:exception,...} results;
  • explicit rlm_future_cancel/2 behavior remains the existing structured kind:cancelled outcome;
  • callbacks/status inspection remain finite and do not execute exception terms.

Acceptance

  • worker-thrown time_limit_exceeded survives submit -> await as the same exception;
  • worker-thrown rlm_cancelled(Token) survives submit -> await;
  • ordinary worker exceptions remain structured and printable;
  • explicit Future cancellation semantics are unchanged;
  • both restored MCP control-exception regressions pass;
  • no sync facade bypasses canonical async submission.

Discovered during false-green remediation after #60.

## Failure The restored aggregate PlUnit suite exposes at least two previously hidden failures: - `rlm_mcp_2026_matrix_test:cancellation_control_exception_propagates` reports `no_exception`; - `rlm_mcp_dual_test:time_limit_exception_propagates_through_server` reports `no_exception`. The domain runtime does rethrow these control exceptions. They are lost one layer later: `rlm_async:async_execute_task/2` catches every worker exception and `async_exception_outcome/3` stringifies it into an ordinary `async_error{kind:exception,...}`. Synchronous facades then await the Future and can no longer recover the control exception. ## Required invariant The canonical Future boundary must distinguish control-flow exceptions from ordinary failures: - preserve supported cancellation/abort/time-limit control exceptions as ground data in the terminal Future state; - `rlm_future_await/[2,3]` must rethrow a preserved control exception; - ordinary exceptions must remain structured `async_error{kind:exception,...}` results; - explicit `rlm_future_cancel/2` behavior remains the existing structured `kind:cancelled` outcome; - callbacks/status inspection remain finite and do not execute exception terms. ## Acceptance - [ ] worker-thrown `time_limit_exceeded` survives submit -> await as the same exception; - [ ] worker-thrown `rlm_cancelled(Token)` survives submit -> await; - [ ] ordinary worker exceptions remain structured and printable; - [ ] explicit Future cancellation semantics are unchanged; - [ ] both restored MCP control-exception regressions pass; - [ ] no sync facade bypasses canonical async submission. Discovered during false-green remediation after #60.
lost-rob0t commented 2026-08-24 08:54:09 +00:00 (Migrated from github.com)

Completed on current main ab426de54a54101ca3a6d8197db77e4c1f9d009f. Acceptance evidence: time-limit and RLM cancellation control exceptions survive submit/await and are rethrown; ordinary exceptions remain structured; explicit future cancellation and canonical async ownership pass; MCP time-limit/cancellation propagation passes. Focused gate 48/48; fresh aggregate 74 suites and 767/767, with 0 failures/timeouts/blocked/fixme. PR #163 was closed as superseded because its stale head would remove newer mainline work.

Completed on current main `ab426de54a54101ca3a6d8197db77e4c1f9d009f`. Acceptance evidence: time-limit and RLM cancellation control exceptions survive submit/await and are rethrown; ordinary exceptions remain structured; explicit future cancellation and canonical async ownership pass; MCP time-limit/cancellation propagation passes. Focused gate 48/48; fresh aggregate 74 suites and 767/767, with 0 failures/timeouts/blocked/fixme. PR #163 was closed as superseded because its stale head would remove newer mainline work.
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
nsaspy/prolog-rlm#162
No description provided.