Job execution flow
A Loom job is the unit of runnable work inside pipeline.execute. In the current runtime contract, a job no longer looks like one opaque block. It is a sequence of explicit phases, some always present and some optional.
Use this page when you need to understand:
- What happens before user script execution
- Which optional phases can appear around that execution
- What still runs after a failure
Job phase order
The normalized phase codes above are what you will see in events.jsonl and phase-report.json.
Which phases are always present
| Phase | Why it is always useful |
|---|---|
job.provider_prepare | Anchors provider setup and pre-execution system work |
job.execution | Anchors user execution as one job-level envelope |
job.cleanup | Closes the job lifecycle, even when the job never ran |
Which phases are optional
| Phase | When it appears |
|---|---|
job.cache_restore | Cache restore work happened before execution |
job.artifact_restore | The current artifact_extract section emitted and was normalized into an artifact phase |
job.cache_save | Cache save work happened after execution |
Optional means "not emitted when there is no work," not "unstable."
How section names map to phase codes
Some directory names still reflect implementation-specific section labels. The runtime normalizes them into stable phase codes:
| Section directory | Phase code you should reason about |
|---|---|
system/provider | job.provider_prepare |
system/services | job.provider_prepare |
system/image_build | job.provider_prepare |
system/cache_restore | job.cache_restore |
system/cache_save | job.cache_save |
system/artifact_extract | job.artifact_restore |
system/cleanup | job.cleanup |
Use the phase code as the stable mental model. Use the section name to find the file on disk.
Current artifact section behavior
The current local runtime does not expose a broader restore or publish artifact lifecycle as a first-class user-facing contract.
What it does expose today is:
- A raw system section named
artifact_extract - A normalized artifact phase identity of
job.artifact_restore - Artifact metrics and skip reasons on that section's summary, manifest entry, and events
Treat that normalization as the current contract. Do not assume a separate current job.artifact_publish phase for local-run diagnostics.
What job.execution contains
job.execution is the user execution envelope for the whole job. Inside it, each script: line becomes a step-scoped execution.script phase.
That means you get:
- A job-level execution boundary
- A mirrored execution event stream at
jobs/<job_id>/user/execution/events.jsonl - One per-step event stream at
jobs/<job_id>/user/execution/script/<NN>/events.jsonl
Failure behavior
The current behavior to rely on:
- Steps run sequentially
- The first failing step ends user execution
- Later script steps do not run
- Post-execution phases such as cache save may still emit if Loom performs that work
- Cleanup still closes the job lifecycle
Skip behavior
Skipped work is represented, not hidden.
| Situation | What you see |
|---|---|
| A cache or artifact phase is intentionally skipped | Section summary and manifest entry show status: "skipped" plus skip_reason |
| A downstream job never runs | The job still emits a skipped job.cleanup finish rather than disappearing |
| A later step never starts because an earlier step failed | The started step fails; later steps do not emit runtime output |
Best artifacts for job-level debugging
| Artifact | Best use |
|---|---|
jobs/<job_id>/summary.json | Confirm job outcome quickly |
jobs/<job_id>/manifest.json | Branch to the failing step or failing system section |
jobs/<job_id>/user/execution/events.jsonl | Read the whole user execution envelope |
jobs/<job_id>/user/execution/script/<NN>/events.jsonl | Read one failing step |
jobs/<job_id>/system/<section>/summary.json | Inspect structured skip and metrics data |
jobs/<job_id>/system/<section>/events.jsonl | Inspect provider, cache, artifact, or cleanup output |
Current behavior to rely on
- A job must become eligible before any job phase can start.
job.provider_preparefinishes before later job phases begin.job.executionencloses the step loop.- Optional restore phases happen before execution.
job.cleanupcloses the job lifecycle.
If you need the larger schedule around those jobs, continue to Pipeline execution flow.