Skip to main content

Your first model

A clockwright model is one document — no code, no subclassing, no callbacks. That is a deliberate choice: a model that is data can be generated by a script or an agent, hashed for identity, stored alongside its results, and diffed like any other file. It can be written as YAML or as JSON — the same keys either way. This page uses YAML, which is the one to write by hand because it takes comments; JSON is what a generator emits and what the engine prints, and it is the form a model is hashed in. This page walks through the smallest model that is still a real queueing system, validates it, and runs it.

A minimal model​

Save this as booth.yaml. It describes a single inspection booth with one server, and two kinds of item arriving at different rates:

# yaml-language-server: $schema=https://clockwright.dev/schema/model.json
schema_version: 1
name: inspection-booth
tick_scale_per_second: 1000
horizon_seconds: 604800.0
warmup_seconds: 7200.0
resources:
- id: booth
servers: 1
entity_rule:
ranks:
- weights:
- - age
- 1.0
load_seconds: 10.0
unload_seconds: 5.0
products:
- id: standard
steps:
- resource: booth
name: inspect
process_seconds: { kind: uniform, lo: 60.0, hi: 180.0 }
- id: priority
steps:
- resource: booth
name: inspect
process_seconds: { kind: uniform, lo: 60.0, hi: 180.0 }
releases:
- product: standard
interarrival_seconds: { kind: exponential, mean: 240.0 }
priority: 10.0
- product: priority
interarrival_seconds: { kind: exponential, mean: 1800.0 }
priority: 20.0

A quick tour of what each field is doing:

  • The first line points your editor at the published JSON Schema. With a YAML extension that reads it — in VS Code, Red Hat's YAML — a misspelled key is underlined as you type and the right one is offered, before cwright ever sees the file.
  • tick_scale_per_second fixes the clock's resolution — 1000 ticks per second, i.e. millisecond resolution. See Determinism for why the clock is an integer at all.
  • horizon_seconds and warmup_seconds describe how long to simulate after warm-up, and how much to discard before measuring steady state. ⚠️ The warm-up is a hard boundary, not a suggestion: every statistic is reset at that mark. cwright run additionally re-truncates the cycle-time series with MSER-5 — see Experiments — but that covers cycle time alone.
  • resources is the list of tool groups. booth has one server, load_seconds and unload_seconds around the process time, and a dispatch rule (entity_rule) — here, oldest waiting item first.
  • products are routes: an ordered list of steps, each naming which resource performs it and how long it takes.
  • releases describe how work arrives — here, two independent Poisson arrival streams with different priorities, one four times as busy as the other.

The full vocabulary — batching, setups, maintenance, breakdowns, scrap and rework, operators, consumables, and more — is covered in The Model.

Validate it​

cwright validate booth.yaml

validate parses the document, checks it as a whole (every reference resolves, every probability is in range, every constraint is internally consistent), and reports every problem at once rather than stopping at the first one. On success:

ok: inspection-booth (1 resources, 2 products, 2 releases)
model_hash: a258a8d2af4acd3a

The model_hash is a content hash of the document — the same model, byte-for-byte equivalent after canonicalisation, always hashes the same way. It is what makes a cached result reusable and what a result document points back to.

Run it​

cwright run booth.yaml --replications 12 --out result.json

This runs 12 independent replications, determines a common warm-up truncation across all of them, and reports every KPI as a confidence interval, not a bare number — see The results document for the exact shape. --replications must be at least 2; a single run cannot bound anything.

Without --out, the result document is written to stdout, so you can pipe it directly into jq, python3 -c '...', or anything else that reads JSON.

Ask whether a change is worth making​

Suppose you have a second document, booth-2-servers.yaml, identical except servers: 2. Ask whether that is actually an improvement:

cwright compare booth.yaml booth-2-servers.yaml \
--kpi cycle_seconds --indifference 60 --replications 12

compare runs both models the same number of times, pairs them replication-for-replication, and returns one of four verdicts: better, worse, no meaningful difference, or insufficient evidence (with an estimate of how many more replications would settle it). See Experiments for what --indifference means and why it has no default.

Next​

  • The Model — every keyword the schema supports, with three worked examples.
  • CLI reference — every command and its flags.