Pipelines

Step kinds, the default lifecycle, custom pipelines, and resume.

A pipeline is the ordered list of steps contractor run executes for a blueprint. Pipelines are defined in YAML — either inside a schema or in contractor/config.yaml — and resolved at run time against a precedence chain. The runtime is process-detached: a contractor pipeline-shim child process owns the run, and the dashboard or CLI tail it through the global SQLite database.

Step kinds

Every step in a pipeline is one of three kinds:

agent

Spawns the configured AI backend (default: Claude) with a slash-command prompt. Phase references in a schema's pipeline: resolve to agent steps automatically. Fields:

  • id — step id used in logs, the dashboard, and --gate-after flags.
  • slashCommand — e.g. implement.md. The runner reads the rendered slash command from .claude/commands/blueprint/.
  • prompt — optional override for the agent prompt. Defaults are per-phase (e.g. Implement all remaining tasks for blueprint "<name>".).
  • model, effort — backend-agnostic overrides (today honored by the claude backend only).
  • criticaltrue (default) means a failure ends the run; false lets the pipeline continue.
  • when — optional guard (e.g. when: scope) that skips the step under a condition.
  • needs_prepared_worktree — when true, the runner injects a synthetic prepare step before this one (see Worktrees).

shell

Runs a shell command in the worktree. Useful for typecheck/test gates, deploy hooks, or formatter passes. Fields:

  • id — defaults to the command string when generated from a schema.
  • command — the shell command. Supports {{scope}} substitution from the blueprint's scope.
  • critical, when, needs_prepared_worktree — as above.

gate

Pauses the pipeline and waits for a user decision. Fields:

  • id, description — the description appears in the dashboard's gate prompt.
  • when — optional guard.

Gate decisions are stored in the global DB. See Gates.

The default lifecycle

Both shipped schemas resolve to the same three-phase pipeline plus a single gate before close:

If no schema, no project config, and no --pipeline flag specify a pipeline, contractor falls back to a hardcoded default with the same shape (buildStandardLifecycle). That fallback runs without a needs_prepared_worktree flag — schemas opt in.

Custom pipelines

A repo can define alternative pipelines under pipelines: in contractor/config.yaml:

The same map is supported in ~/.contractor/config.yaml (user-level) for pipelines you want available across every repo on the machine. Project pipelines win over global pipelines on name collisions.

Select a pipeline at run time:

Or pin one to a blueprint by adding pipeline: fast-iteration to its .contractor.yaml.

Resolution precedence

When contractor run resolves the pipeline for a blueprint, it walks this chain top-to-bottom and stops at the first match:

  1. --pipeline <name> CLI flag.
  2. pipeline: field in the blueprint's .contractor.yaml.
  3. pipeline: field in contractor/config.yaml.
  4. The schema's pipeline: section in schema.yaml.
  5. The hardcoded contractor-lifecycle default.

When the resolved name is set (cases 1–3), contractor looks up the named definition in the project pipelines map first, then the global pipelines map. An unknown name fails the run with Unknown pipeline "<name>". Available pipelines: ….

--resume

A failed pipeline run can be re-spawned without re-running its successful steps:

last-failed resolves to the most recent failed pipeline run for the current repo. Either form spawns a new shim process whose initial step state is hydrated from the parent run's child rows: completed, skipped, and cancelled steps are preserved as terminal; failed and running (orphaned) steps are reset to pending. findResumeIndex then picks the first non-terminal step and the new shim picks up there.

Two things to know:

  • Only failed runs can be resumed. A cancelled or completed run rejects with an error.
  • Resume does not snapshot the worktree. If you edited files between failure and resume, the new run sees the current worktree state. That is usually what you want — fixing the failure is the point — but be aware that the resumed step starts against your edits, not the state that existed at failure.

For resuming a single agent session inside a pipeline, the claude --resume <session-id> hint that contractor prints on agent failure remains available as a manual alternative.