Problem
Two related correctness issues affect cascade's failure handling today:
1. Cancelled runs are not detected in failure checks.
The failure guard in the orchestrate workflow tests == 'failure' (generator.go:1004). With cancel-in-progress: true (the current default on orchestrate), a run superseded by a newer push enters cancelled state, not failure. The finalize job and any on_failure callbacks see cancelled as a non-failure state and skip — leaving the state file in whatever intermediate condition the cancelled deploy reached.
A deploy that progressed to 60% before cancellation should not silently leave the recorded state as "not deployed". Finalize and failure callbacks should treat cancelled as an actionable condition.
2. on_failure: continue does not suppress the run-level red status.
When a callback is configured with on_failure: continue, cascade currently has no way to emit continue-on-error: true on that specific job, so the overall workflow run still shows as failed even though the operator explicitly said the failure is acceptable.
What to fix
Cancelled detection: update the failure-check condition from == 'failure' to contains(fromJSON('["failure","cancelled"]'), ...) (or equivalent) in every generated failure guard. Finalize and on_failure callbacks should run on both failure and cancelled outcomes.
continue-on-error for on_failure: continue callbacks: when a callback has on_failure: continue, emit continue-on-error: true on its jobs.<id> block so the workflow run is not painted red.
Acceptance criteria
Problem
Two related correctness issues affect cascade's failure handling today:
1. Cancelled runs are not detected in failure checks.
The failure guard in the orchestrate workflow tests
== 'failure'(generator.go:1004). Withcancel-in-progress: true(the current default on orchestrate), a run superseded by a newer push enterscancelledstate, notfailure. The finalize job and anyon_failurecallbacks seecancelledas a non-failure state and skip — leaving the state file in whatever intermediate condition the cancelled deploy reached.A deploy that progressed to 60% before cancellation should not silently leave the recorded state as "not deployed". Finalize and failure callbacks should treat
cancelledas an actionable condition.2.
on_failure: continuedoes not suppress the run-level red status.When a callback is configured with
on_failure: continue, cascade currently has no way to emitcontinue-on-error: trueon that specific job, so the overall workflow run still shows as failed even though the operator explicitly said the failure is acceptable.What to fix
Cancelled detection: update the failure-check condition from
== 'failure'tocontains(fromJSON('["failure","cancelled"]'), ...)(or equivalent) in every generated failure guard. Finalize andon_failurecallbacks should run on bothfailureandcancelledoutcomes.continue-on-errorforon_failure: continuecallbacks: when a callback hason_failure: continue, emitcontinue-on-error: trueon itsjobs.<id>block so the workflow run is not painted red.Acceptance criteria
failureandcancelledjob outcomes.on_failurecallbacks run when a preceding job was cancelled.on_failure: continueemitcontinue-on-error: trueon the job.continuecallback fails.cancelledcondition.