▸ ROOT / CONCEPTS/ LIFECYCLE EVENTS

Program Lifecycle Events

What Cheetah's program lifecycle events mean, where they sit in the life of a program run, and how they relate to programs, robots, and parts.

▸ BETA
▸ APPLIES TO
cheetah service >=0.0.126schema version 2

A lifecycle event is Cheetah's real-time notification of what happens during a program run. There are four, each about exactly one program run. For the exact payload of each, see the event reference; for how they're delivered, see webhooks.

The life of a program run#

A program run is created, begins executing, and then ends exactly one of three ways: completed, failed, or cancelled. Each transition emits one event, POSTed to your endpoint the moment it happens:

FIG_009 [ EVENT TIMING ] © CHEETAH INSPECTION CELL program runs · hosted by cheetah PROGRAM LIFECYCLE EVENTS pushed · < 1 kB each YOUR ENDPOINT webhook receiver PROGRAM RUN 1 START MOVE SCAN MOVE SCAN ANALYZE END QUALITY REPORT POST · ProgramStarted process ProgramStarted EXACTLY ONE OF POST · ProgramCancelled process ProgramCancelled POST · ProgramFailed process ProgramFailed POST · ProgramCompleted carries the quality report process ProgramCompleted PROGRAM RUN 2 PROGRAM RUN 3 SAME PATTERN, EVERY PROGRAM RUN
▸ FIG_009 — WHERE EVENTS FIRE IN THE LIFE OF A PROGRAM RUN

ProgramStarted fires once, when the program run begins executing. After that, a program run reaches a terminal event:

  • ProgramCompleted — the program ran to the end and a QC outcome was produced. This is the only terminal event that carries a result.
  • ProgramFailed — the program run itself failed: a step errored and the inspection never finished. No QC outcome exists. This event says nothing about part quality.
  • ProgramCancelled — an operator stopped the program run. No outcome.

A failed program run is not a failed inspection. A part that fails QC still completes its program run — that emits ProgramCompleted with passed: false. ProgramFailed is only ever about the program run itself breaking before any QC outcome existed.

Between the events, nothing fires — moves, scans, and analysis emit no traffic. Events stay at the program-run level (what is not an event yet).

The terminal events are mutually exclusive — a program run emits exactly one. The edge case: in FAIL_PROGRAM mode, a failed ProgramCompleted delivery fails the program run without emitting another event (control path). Treat any terminal event as closing the program run you opened on ProgramStarted.

Delivery order is not guaranteed — ProgramStarted can arrive after a terminal event. Order by the payload's timestamps and run_id, never by arrival (retries and idempotency).

Where the QC outcome comes from#

ProgramCompleted fires after the program run's checks are aggregated into the QC outcome — which is why it alone carries passed and the per-check qc_checks array. The other events have no outcome to report.

If your integration records inspection results, ProgramCompleted is the event you care about. The other three are state transitions.

When an event is in the control path#

By default events are observers — a failed delivery doesn't change what the operator sees. FAIL_PROGRAM mode puts ProgramCompleted delivery in the control path: a failed delivery flips the program run to FAILED and suppresses the outcome from the operator — no ProgramFailed event follows; the failure is recorded on the run itself. Right when your system is the official record; it couples the line to your endpoint's availability. Full trade-off: choose a failure mode.

How events relate to the rest of the model#

Every lifecycle event identifies the entities the program run touched, so you can route and record it without a follow-up API call:

  • Programprogram_id identifies what was run.
  • Robotrobot_id identifies the cell that executed the program run (may be null if not recorded).
  • Partserial_number identifies the physical unit inspected (may be null if none was captured); revision counts the inspections of that unit, incrementing each time the same part is re-inspected.
  • Program runrun_id is the stable identity of the program run itself, constant across all of its events.

Finer-grained data — sessions, frames, individual scans — is not in the payloads; fetch it by run_id through the open REST API.

What is not an event yet#

The four program-run events are the entire catalogue today: no step-level events (StepStarted, StepCompleted), no per-sensor or per-scan events, no events for activity outside a program run (calibration, configuration changes). For step-by-step progress, poll the program run through the API. The event surface is expected to grow.

Next#

▸▸ /content/concepts/lifecycle-events.md
▸ DOCS UNDER CONSTRUCTION LAST UPDATED 2026-07-25 ▸ CHANGELOG