- TaskRunner.run() and WorkflowRunner.run()/resume() accept an optional
stop_reason callable alongside should_stop, distinguishing a genuine
cancellation from other stop conditions (e.g. lost lease).
- is_cancellation_reason() shared helper added to runtime/task.py.
- WorkflowRunner._stop_status() now branches cancelled/failed based on
stop_reason, correcting a prior blanket cancelled-on-any-stop behavior
that conflicted with the host-agent-protocol spec's requirement to
distinguish cancellation from lease-loss stops.
- Default behavior (stop_reason=None) is preserved exactly for both
runners so existing callers/tests are unaffected.
- Task 1 of openspec change task-cancellation.
- Resume no longer infinite-loops when a crash occurs between
append_step_result() and update_run() for a BranchStep: the recorded
branch target is now read from the persisted result instead of
recomputed as None.
- Resume no longer silently discards a recorded step failure that
happened right before the crash; the run correctly ends failed.
- A failed step's own next_step_id (e.g. routing to a BranchStep that
evaluates step_result_success) is now honored instead of
unconditionally forcing the run to failed, per spec.
openspec: workflow-orchestration capability, archived change workflow-orchestration-runtime