FlowDrop Workflow Specification 1.0-draft

Cancel and pause signals are observed between job iterations

A signal never interrupts a job mid-flight. It is observed at the boundary between iterations, which is why a cancelled run has no half-executed node.

The rule

Normative: this is the rule
  1. An engine polls for a pending signal between job iterations; the in-flight job always finishes first, and the absence of a signal continues the loop.
  2. A cancel signal marks the run cancelled, stamps its execution time, and announces the outcome twice: a cancellation event and a run-completed announcement carrying the cancelled status, so that cancellation is announced like any other terminal outcome (ORC-15).
  3. It then answers with status cancelled and metadata naming the engine, the signal and the reason.
  4. A pause signal pauses the run and announces only the pause, with no completion announcement, answers with status paused and the same metadata keys, and leaves the signal record pending, because that record is the run's resume key.

What it means

A cancel and a pause are both observed only at the boundary between job iterations, never mid-node — the job already running always finishes first. Past that boundary the two diverge in a way that is easy to get backwards. Cancel is terminal: it announces the cancellation itself, and separately announces the run as complete (carrying the cancelled status), because anything that only listens for completion — a session closing out, a parent run waiting on this one — must hear that the run is over. Pause is not terminal: it announces only the pause, and nothing tells a completion listener the run has ended, because it has not. The signal a pause left behind stays exactly as it was, because that record is the same one a later resolution resumes against (INT-3).

Example

The same kind of poll, answered with a cancel and with a pause.

A run answering a pending cancelcancelled
{ "status": "cancelled", "metadata": { "signal_id": "signal-1", "reason": "operator stopped the run" } }
The same run, answering a pending pause insteadpaused
{ "status": "paused", "metadata": { "signal_id": "signal-1" } }

Only the cancel is followed by a second, completion announcement; the pause produces exactly one.

Rule identifiers are permanent and are never renumbered. Each implementation publishes its own standing against these rules; this specification does not.spec 1.0-draft · INT-5 · changed in spec 1.0