Problem
The stable service-mode POST /workflows/{id}/cancel route calls Workflow's terminal attemptCancel() and immediately closes the run, cancels open tasks/timers, and revokes leases. It is not the separate cooperative request path shipped for embedded Laravel in workflow#483 / Workflow 2.2.0. A real-Server Python integration case in sdk-python#69 confirms that an in-flight local activity's next heartbeat loses the lease and no local completion is committed.
Published Python/Rust SDK docstrings and the language-neutral docs call cancel_workflow cooperative/graceful and imply workflow cleanup runs. That claim is false for the current service-mode route and could cause customers to skip external cleanup or reconciliation.
Immediate correction
- Audit the PHP, Python, Rust SDK guides/API docs and main service-mode docs. State plainly that current
cancel is terminal; terminate is also terminal with a distinct outcome/reason. Neither guarantees workflow-code finally cleanup. Do not change stable endpoint semantics under a documentation fix.
- Preserve the accurate embedded-Laravel cooperative-request guidance and clearly label its deployment mode.
- Verify rendered/public guidance after publication with focused link/content checks. Do not turn this into a site-wide screenshot pass.
Additive parity work
- Design a separate service-mode cooperative cancellation request using the already shipped Workflow engine primitive without repurposing
/cancel. Expose the request/observable pending state in Server and PHP/Python/Rust SDKs only after one shared protocol/conformance contract is qualified.
- Cover request-before/after task claim, waiting runs, bounded cleanup, duplicate requests, worker loss/replay, termination during cleanup, SDK task
cancel_requested delivery, and local/remote activity fencing. External effects remain at-least-once and need idempotency/reconciliation.
- Publish capability claims only after exact published Server + SDK artifacts pass cross-language conformance. Keep terminal cancel behavior and compatibility intact.
This is a confirmed product/docs contract gap, not a request to reopen the completed embedded feature. Own the immediate correction first; the additive protocol work follows current accepted release commitments. No private Cloud or customer data belongs here.
Closure requirement and cancellation model work
The operator requires this issue to remain open until Durable Workflow's shipped cancellation model is clearly stronger than competing workflow products. Portable compatibility and passing the existing qualification scenarios are prerequisites. They do not complete this issue.
Evaluate current Temporal, Restate and DBOS cancellation contracts and their strongest supported configurations using primary sources, exact versions and reproducible published-artifact scenarios. Document useful customer advantages, competing strengths and material gaps. Fix the gaps needed for a coherent model rather than treating a checklist or unsupported superiority claim as evidence.
Prioritize the following decisions and implementation using engineering judgment:
- Verify parent-close
RequestCancel semantics. Make cooperative propagation explicit and preserve original request lineage and immutable cleanup budget. Define deliberate migration/compatibility behavior for any existing terminal contract.
- Define Activity and Child operation policies equivalent to request-and-continue, wait-for-cancellation-completion and abandon. Specify what acknowledgement proves, what can still run externally, and how cleanup avoids overlapping live work.
- Make
requestCancellation() the discoverable cooperative API, preserving the stable terminal cancel() behavior with clear naming and documentation.
- Expose a coherent durable cancellation context and observable lifecycle: request identity, reason, requester/source, timestamps, original deadline and lineage, plus delivery, cleanup outcome, expiry and termination. Connect workflow authoring to API/CLI/UI diagnostics.
- Qualify and document cancellation observation independent of application heartbeats in PHP/Python/Rust, including worker loss, attempt replacement, bounded cleanup and stale-authority fencing. Specify scheduling and transport limits precisely.
Nested scopes/shielding, inherited budgets across the parent/child/activity tree, deterministic remaining-time helpers, capability diagnostics, bulk requests and downstream fencing tokens will be assessed against those outcomes. Existing mechanisms should be reused where they satisfy the contract. Additional work belongs in the owning repositories and remains linked here.
The current recovery gates continue, but defer freezing protocol 1.20 or publishing the planned feature RC tuple until the model decisions are settled. Preserve protocol 1.19 and existing terminal routes. Publish stable capability claims only after the final exact Server/PHP/Python/Rust artifacts, specification, customer-facing diagnostics and comparative evidence meet these closure requirements.
Required mixed-language cascade before closure
Use one exact published artifact tuple in an isolated stack:
Parent PHP workflow
+-- Python child workflow
| +-- Rust remote activity
+-- PHP local activity
Request cancellation with one root identity and a cleanup deadline exactly 30 seconds after the original request. Demonstrate all of the following in the same run:
- The Python child receives a genuine cooperative request and runs cleanup.
- The Rust remote activity and PHP local activity stop without application heartbeats. Record actual callback stop observations and the SDK/runtime acknowledgements separately from loss of commit authority.
- The stale Rust activity attempt cannot publish a late result.
- SIGKILL a workflow worker during cleanup. A fresh replacement replays the original canonical delivery boundary and resumes durable cleanup.
- A duplicate request returns the original root identity and deadline, including after replacement. No hop, retry or recovery refreshes the budget.
- Cleanup and all runs converge to
Cancelled before the original deadline. Record elapsed time, canonical histories and cleanup outcomes. An expired budget cannot substitute for successful recovery within this scenario.
- One UI/API view explains the entire cascade: root request, original deadline, parent/child lineage, activity stop and fencing, worker loss/replacement, cleanup progress and final outcomes.
Retain commands, artifact versions and digests, raw results, histories and the cascade view. This scenario is a required closure gate alongside the stronger model and competitive evidence above. Keep the issue open until it passes against artifacts users can install.
Problem
The stable service-mode
POST /workflows/{id}/cancelroute calls Workflow's terminalattemptCancel()and immediately closes the run, cancels open tasks/timers, and revokes leases. It is not the separate cooperative request path shipped for embedded Laravel in workflow#483 / Workflow 2.2.0. A real-Server Python integration case in sdk-python#69 confirms that an in-flight local activity's next heartbeat loses the lease and no local completion is committed.Published Python/Rust SDK docstrings and the language-neutral docs call
cancel_workflowcooperative/graceful and imply workflow cleanup runs. That claim is false for the current service-mode route and could cause customers to skip external cleanup or reconciliation.Immediate correction
cancelis terminal;terminateis also terminal with a distinct outcome/reason. Neither guarantees workflow-codefinallycleanup. Do not change stable endpoint semantics under a documentation fix.Additive parity work
/cancel. Expose the request/observable pending state in Server and PHP/Python/Rust SDKs only after one shared protocol/conformance contract is qualified.cancel_requesteddelivery, and local/remote activity fencing. External effects remain at-least-once and need idempotency/reconciliation.This is a confirmed product/docs contract gap, not a request to reopen the completed embedded feature. Own the immediate correction first; the additive protocol work follows current accepted release commitments. No private Cloud or customer data belongs here.
Closure requirement and cancellation model work
The operator requires this issue to remain open until Durable Workflow's shipped cancellation model is clearly stronger than competing workflow products. Portable compatibility and passing the existing qualification scenarios are prerequisites. They do not complete this issue.
Evaluate current Temporal, Restate and DBOS cancellation contracts and their strongest supported configurations using primary sources, exact versions and reproducible published-artifact scenarios. Document useful customer advantages, competing strengths and material gaps. Fix the gaps needed for a coherent model rather than treating a checklist or unsupported superiority claim as evidence.
Prioritize the following decisions and implementation using engineering judgment:
RequestCancelsemantics. Make cooperative propagation explicit and preserve original request lineage and immutable cleanup budget. Define deliberate migration/compatibility behavior for any existing terminal contract.requestCancellation()the discoverable cooperative API, preserving the stable terminalcancel()behavior with clear naming and documentation.Nested scopes/shielding, inherited budgets across the parent/child/activity tree, deterministic remaining-time helpers, capability diagnostics, bulk requests and downstream fencing tokens will be assessed against those outcomes. Existing mechanisms should be reused where they satisfy the contract. Additional work belongs in the owning repositories and remains linked here.
The current recovery gates continue, but defer freezing protocol 1.20 or publishing the planned feature RC tuple until the model decisions are settled. Preserve protocol 1.19 and existing terminal routes. Publish stable capability claims only after the final exact Server/PHP/Python/Rust artifacts, specification, customer-facing diagnostics and comparative evidence meet these closure requirements.
Required mixed-language cascade before closure
Use one exact published artifact tuple in an isolated stack:
Request cancellation with one root identity and a cleanup deadline exactly 30 seconds after the original request. Demonstrate all of the following in the same run:
Cancelledbefore the original deadline. Record elapsed time, canonical histories and cleanup outcomes. An expired budget cannot substitute for successful recovery within this scenario.Retain commands, artifact versions and digests, raw results, histories and the cascade view. This scenario is a required closure gate alongside the stronger model and competitive evidence above. Keep the issue open until it passes against artifacts users can install.