Skip to main content
← Back to list
01Issue
FeatureShippedSwamp CLI
Assigneesstack72

Relationships

#1444 Add --from flag to workflow resume for DAG re-entry on failed runs

Opened by stack72 · 7/28/2026· Shipped 7/28/2026

Summary

Extend the existing workflow resume command (currently gate-suspended runs only) with a --from <step> flag that re-enters a failed workflow's DAG at a specified step. Combined with the guard field (#1437, shipped in #1993), this enables safe workflow recovery — guards decide which steps actually re-execute.

Motivation

When a workflow step fails, the user currently has two options: re-run the entire workflow from scratch, or abandon the run. There's no way to resume from the failed step. For workflows with expensive or irreversible earlier steps (instrument dispensing, API provisioning, long computations), re-running from scratch is wasteful or dangerous.

This was identified during the #1430 design as the workflow-level recovery mechanism. Guard handles idempotency (what should run), resume handles re-entry (where to start).

Design

The --from flag

$ swamp workflow resume <run> --from <step>

Re-enters the DAG at the named step. All steps are re-evaluated — guards decide what actually executes. Steps before and at the same level as --from that have truthy guards are skipped. The failed step (and anything downstream) re-runs.

Example flow

$ swamp workflow run plate-assay run-1
  ✓ step dispense-reagent              data committed
  ✓ step calibrate                     data committed
  ✗ step read-plate failed             USB timeout at well 60
  – step analyse (skipped, depends on read-plate)

$ swamp workflow resume run-1 --from read-plate
  – step dispense-reagent (guarded)    ← guard truthy, didn't dispense twice
  – step calibrate (guarded)           ← guard truthy, calibration reused
  ✓ step read-plate                    ← re-executed, all 96 wells written
  ✓ step analyse                       ← downstream runs normally

forEach handling

--from targets step template names as written in the workflow YAML, not expanded iteration names. For forEach steps, the platform re-expands all iterations and re-evaluates guards — completed iterations are skipped, failed/unstarted iterations execute.

- name: read-plate
  forEach:
    item: well
    in: ${{ range(1, 97) }}
  guard: ${{ data.latest("plate-reader", self.well) }}
  task:
    modelName: plate-reader
    method: read-single-well
$ swamp workflow resume run-1 --from read-plate
  – read-well-1 (guarded)
  ...
  – read-well-59 (guarded)
  ▸ read-well-60               ← failed last time, no data
  ✓ read-well-60
  ▸ read-well-61               ← never ran, no data
  ...
  ✓ read-well-96

Implementation notes

Three status gates in the current code restrict resume to suspended runs and need to be relaxed for failed runs when --from is provided:

  1. resolveSuspendedRun() in suspended_run_resolver.ts — filters for status === "suspended"
  2. WorkflowExecutionService.resume() at line ~2023 — checks existingRun.status !== "suspended"
  3. CLI command's findWaitingApprovalStep() check at line ~270

The existing gate-suspended resume path must be preserved alongside the new --from path. The two should branch early in the CLI command.

Safety

Completed steps are not re-run — for safety, not just efficiency. Re-running a completed step can repeat an irreversible action: dispense liquid twice, re-send an API call, re-provision infrastructure. The guard is the mechanism that prevents this.

Steps without a guard always execute on resume. This is the correct default — if you didn't write a guard, you're saying "always run this step."

  • #1430 — parent issue (writeResource atomicity)
  • #1437 — guard field (shipped in #1993)
  • rollbackOnFailure — method-level deferred-latest write mode (separate issue, addresses the original #1430 writeResource concern)
02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

7/28/2026, 4:55:21 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack727/28/2026, 3:24:58 PM

Sign in to post a ripple.