Blueprints and Inputs
The shape of a blueprint, its calculations and tables, and how typed inputs check the facts before anything runs.
After reading this guide, you will know:
- The sections a blueprint has, and what goes in each.
- The five input types, and how
defaultandone_ofwork. - How facts are checked before a run, and what the problems look like.
- How to run a calculation other than the first.
- The YAML habits that keep a blueprint readable and correct.
The Shape of a Blueprint
A blueprint is a YAML file with up to three sections:
imports: [...] # other blueprints whose calculations and tables join this one (optional)
tables: {...} # name to a list of rows (optional)
calculations: {...} # name to a calculation: inputs, steps, outputs (at least one)
Each calculation has:
| Key | Holds |
|---|---|
inputs |
name to {type, one_of, default}. Every value the calculation reads that is not a table or a step |
steps |
a list, run in order. Each step has a snake_case name and exactly one step type |
outputs |
the names it hands back. Required |
Names are snake_case (hp_after, not hpAfter or HP after) so formulas can refer to them.
This blueprint prices a fare. It uses every input type:
tables:
zones:
- {zone: inner, price: 3.20}
- {zone: outer, price: 4.80}
calculations:
fare:
inputs:
zone: {type: string, one_of: {table: zones, column: zone}}
rider: {type: string, one_of: [adult, child, senior]}
travel_date: {type: date}
off_peak: {type: boolean, default: false}
transfers: {type: list, default: []}
steps:
- name: base
lookup: {table: zones, where: {zone: zone}, value: price}
- name: concession
formula: 'IF(rider = "adult", 1, 0.5)'
- name: weekend
formula: WEEKDAY(travel_date) = 0 OR WEEKDAY(travel_date) = 6
- name: discount
formula: 'IF(off_peak OR weekend, 0.7, 1)'
- name: price
formula: 'ROUND(base * concession * discount, 2)'
- name: free_transfers
formula: COUNT(transfers)
outputs: [price, weekend, free_transfers]
$ echo '{"zone": "outer", "rider": "senior", "travel_date": "2026-07-04"}' | rmt run fare.yml
price 1.68
weekend true
free_transfers 0
Inputs
| Type | Accepts |
|---|---|
number |
a number. Decimals are exact |
string |
text |
date |
a date written YYYY-MM-DD |
boolean |
true or false |
list |
a list, of numbers, text or rows |
default makes an input optional. When the facts leave it out, the default is used: off_peak is
false and transfers is empty above. A default must have the input’s type.
one_of limits an input to a set of words, for a choice from a menu:
rider: {type: string, one_of: [adult, child, senior]}
When the words are a table’s column, name the column instead of copying them, so they are written once:
zone: {type: string, one_of: {table: zones, column: zone}}
Facts Are Checked First
Before anything runs, the facts are checked against the inputs. Every problem comes back at once:
$ echo '{"zone": "middle", "rider": "student", "travel_date": "next tuesday", "off_peak": "yes"}' | rmt run fare.yml
✗ 4 problems
• fact zone should be one of inner, outer, not "middle"
• fact rider should be one of adult, child, senior, not "student"
• fact travel_date should be a date written YYYY-MM-DD, not "next tuesday"
• fact off_peak should be true or false, not "yes"
A fact that is not an input is a problem too, and so is a missing input that has no default
(facts need armour). From Ruby, the reason_me_this gem raises
ReasonMeThis::InvalidFacts with the same list as its problems.
Rows inside a list are checked when a calculation runs over them, not before. See Running over Lists.
More Than One Calculation
A blueprint can hold several calculations. The first is the default; --calculation runs another:
$ echo '{"x": 2}' | rmt run two.yml --calculation b
tripled 6
$ echo '{"x": 2}' | rmt run two.yml --calculation c
✗ 1 problem
• no calculation c; the calculations are a, b
Calculations run one another with the run and repeat steps. A calculation that another runs declares
every value it reads as an input, including ones the parent provides, and hands back only its outputs.
See Chaining with Imports and Runs.
What check Reports About Shape
rmt check catches mistakes in the shape before anything runs. This blueprint has seven:
tables:
zones:
- {zone: inner, price: 3.20}
calculations:
fare:
inputs:
zone: {type: string, one_of: {table: zones, column: name}}
rider: {type: string, one_of: adult}
off_peak: {type: boolean, default: no_thanks}
day: {type: date, required: true}
steps:
- name: Base Price
lookup: {table: zones, where: {zone: zone}, value: price}
- name: price
formula: base * 2
rules: {pick: first, rules: []}
$ rmt check fare_problems.yml
✗ 7 problems
• fare: input zone takes one_of from column name of zones, which its rows do not have
• fare: input rider has one_of adult; one_of is a list of words, such as [regular, hard, extreme], or a table column, such as {table: kinds, column: kind}
• fare: input off_peak has default "no_thanks", which is not true or false
• fare: input day does not take required; inputs take type, one_of, default
• fare: step Base Price should be a snake_case name, such as base_price
• fare: step price has more than one step type (formula, rules); give it one
• fare: needs outputs, the steps it hands back, such as outputs: [price]
The full list is in Blueprint Format.
YAML Habits
- Quote a formula with a comma inside
{...}. YAML splits flow mappings on commas, so{name: x, formula: MAX(0, y)}breaks. Write{name: x, formula: 'MAX(0, y)'}, or use the block form with one key per line.checkpoints at the quote when a formula cannot be read. - Text in a formula needs double quotes inside the YAML string:
formula: '"critical"', orIF(rider = "adult", 1, 0.5). - Write decimals as plain numbers (
3.20). They load exact; there is no float rounding. - Write dates as YYYY-MM-DD. They load as dates in tables, cases and facts.
- Keys such as
on,yesandnostay keys. YAML 1.1 would read them as booleans; blueprints keep them as words, which is whylookup: {on: travel_date}works. - No aliases.
&nameand*nameare refused; write the values out.
Next Steps
- Step Types - Every step type with an example.
- Formulas and Functions - What a formula can say.
- Tables and Lookups - Rows, effective dates and bands.