---
id: STATE-PFM-DJE-005
title: Data run step
object: DOM-PFM-DJE-005
product_area: platform
module: data-job-engine
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
states:
  - name: pending
    meaning: No child job has been submitted; dependencies determine eligibility.
  - name: running
    meaning: A child job exists and its progress is polled on execution passes.
  - name: succeeded
    meaning: >-
      The child has finished the work it could perform; copied refusals can
      still affect readiness.
  - name: blocked
    meaning: >-
      The child ended with unresolved dependencies; one additional submission is
      available.
  - name: failed
    meaning: >-
      A child failure or nonrecoverable progress read ends this dataset and
      fails the parent.
  - name: skipped
    meaning: The parent ended before this dataset was submitted.
transitions:
  - from: pending
    to: running
    trigger: Submit an eligible dataset
    guard: The parent is running and dependencies are succeeded or blocked
    side_effects:
      - >-
        call the owner with current staff credentials; save child identity and
        attempt
    who: The pass
    provenance: observed
    source: 'services-platform:modules/data-jobs/services/runs/run-driver.ts:submitStep'
  - from: running
    to: succeeded
    trigger: Read a settled successful child
    guard: Progress supplies a recognized successful result
    side_effects:
      - copy outcome counts
    who: The pass
    provenance: observed
    source: >-
      services-platform:modules/data-jobs/services/runs/run-driver.ts:advanceDataRun
  - from: running
    to: blocked
    trigger: Read a settled blocked child
    guard: Progress supplies blocked outcomes
    side_effects:
      - copy its outcome counts
    who: The pass
    provenance: observed
    source: >-
      services-platform:modules/data-jobs/services/runs/run-driver.ts:advanceDataRun
  - from: blocked
    to: running
    trigger: Resubmit dependency-blocked work
    guard: Dependencies have finished and fewer than two attempts are recorded
    side_effects:
      - create another job from the same uploaded dataset
    who: The pass
    provenance: test
    source: >-
      services-platform:modules/data-jobs/tests/integration/services/runs/run-driver.integration.spec.js#tries
      a blocked dataset a second time, and only a second time
  - from: running
    to: failed
    trigger: Fail dataset progress
    guard: >-
      The child failed or a non-access read error is permanent or beyond the
      30-minute grace
    side_effects:
      - save failure detail and fail the parent on this pass
    who: The pass
    provenance: observed
    source: 'services-platform:modules/data-jobs/services/runs/run-driver.ts:pollStep'
  - from: pending
    to: skipped
    trigger: Skip unsubmitted work
    guard: The parent failed or was cancelled
    side_effects:
      - record a skipped outcome without child submission
    who: The run
    provenance: observed
    source: >-
      services-platform:modules/data-jobs/services/persistence/data-runs.ts:skipPendingSteps
invalid:
  - from: blocked
    to: running
    why: The driver offers no third attempt for blocked work.
  - from: succeeded
    to: running
    why: A successful step cannot submit another child.
  - from: skipped
    to: running
    why: A skipped step cannot restart its final parent.
concurrency: >-
  Table checks require a child identity for submitted states. Transient read
  errors leave progress unchanged for 30 minutes after the last successful
  write; access denial is returned to the caller. Unexpected successful payloads
  can be treated as running indefinitely. Child submission and step recording
  are separate operations.
evidence:
  - >-
    services-platform at ad3f6a65: modules/data-jobs/db/data-run-steps.table.ts
    (states, checks, MAX_STEP_ATTEMPTS); services/runs/run-driver.ts;
    services/runs/data-job-port.ts (readProgress, DATA_JOB_UNREADABLE_GRACE_MS).
---

# Data Run Step

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> pending
  pending --> running: submit an eligible dataset
  running --> succeeded: read a settled successful child
  running --> blocked: read a settled blocked child
  blocked --> running: resubmit dependency-blocked work
  running --> failed: fail dataset progress
  pending --> skipped: skip unsubmitted work
```

## Transitions Explained

Eligibility accepts dependencies that succeeded or ended blocked. The owner submits the dataset and later progress reads update the step. A blocked result gets one more child submission; a permanent or prolonged read failure fails the parent. A successful child may still have refusals that the readiness calculation reports.

## What Cannot Happen

The driver does not intentionally submit a third attempt. Successful and skipped steps are not reopened. Concurrent submission passes are a separate gap rather than an approved extra attempt.

## Concurrency and Timing

Progress-read grace starts from the last saved step progress. Unexpected successful response shapes can renew running progress forever. Submission errors can leave a child untracked or the step pending.
