The published PHP SDK 2.0.3 can return WorkflowFailed for a genuine workflow deadline expiration. Server 2.2.0 represents the execution as status=failed, is_terminal=true, failure.failure_category=timeout, with a terminal WorkflowTimedOut history event. Client::terminalResult handles WorkflowCompleted/Failed/Cancelled/Terminated but not WorkflowTimedOut, and consequently falls through to WorkflowFailed for this response.
Reproduction: start a workflow that waits beyond its configured run deadline on a runtime with its matching/repair role running. Once describe reports terminal failure_category=timeout and history contains WorkflowTimedOut, call the selected handle result. This is separate from the client-side polling timeout, which currently also uses WorkflowTimedOut and must not be mistaken for proof of a terminal execution.
Acceptance: add a fake-transport regression with the actual terminal response/history shape; map WorkflowTimedOut history to the typed exception while preserving the selected run; retain the existing client wait-timeout behavior unless an intentional compatible API change is made. Check the Python and Rust terminal timeout mapping for parity and add coverage where needed. No infrastructure or credentials are required to reproduce this SDK mapping defect.
The published PHP SDK 2.0.3 can return WorkflowFailed for a genuine workflow deadline expiration. Server 2.2.0 represents the execution as status=failed, is_terminal=true, failure.failure_category=timeout, with a terminal WorkflowTimedOut history event. Client::terminalResult handles WorkflowCompleted/Failed/Cancelled/Terminated but not WorkflowTimedOut, and consequently falls through to WorkflowFailed for this response.
Reproduction: start a workflow that waits beyond its configured run deadline on a runtime with its matching/repair role running. Once describe reports terminal failure_category=timeout and history contains WorkflowTimedOut, call the selected handle result. This is separate from the client-side polling timeout, which currently also uses WorkflowTimedOut and must not be mistaken for proof of a terminal execution.
Acceptance: add a fake-transport regression with the actual terminal response/history shape; map WorkflowTimedOut history to the typed exception while preserving the selected run; retain the existing client wait-timeout behavior unless an intentional compatible API change is made. Check the Python and Rust terminal timeout mapping for parity and add coverage where needed. No infrastructure or credentials are required to reproduce this SDK mapping defect.