▸ 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 >=1.5.12schema version 3

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. 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.

Events are observers, never controls#

An event is a notification, not a gate. A failed delivery — even of ProgramCompleted — never changes the program run's outcome or what the operator sees; it lands in the delivery log and, under WARN, raises a banner. (Earlier releases had a FAIL_PROGRAM mode that coupled the run to delivery success; it was removed in cheetah-service v1.5.1 — see choose a failure mode.) If your system is the record-of-truth, reconcile through the open REST API rather than gating the line on your endpoint.

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; program_name is the same program's operator-facing name at dispatch time (null if the program was deleted before the event fired).
  • Robotrobot_id identifies the robot that executed the program run — a short id from the cell's configuration, not a UUID (null if the program has no robot; the first of them when a program drives several).
  • 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#

▸ LAST VERIFIED Wed Sep 02 2026 00:00:00 GMT+0000 (Coordinated Universal Time) ▸▸ /content/concepts/lifecycle-events.md
▸ DOCS UNDER CONSTRUCTION LAST UPDATED 2026-09-20 ▸ CHANGELOG