Specification
Foodlang is a .food.yaml profile built on Open Recipe Format (ORF)-style YAML.
A Foodlang document is a valid ORF-style recipe plus an X-foodlang extension
block.
The full, authoritative specification lives in
SPEC.md in the
repository root. This page summarises it.
Looking for the hand-written authoring format? See The
.foodformat for its v0.1 grammar.
The .food authoring format
A .food document has one top-level node:
recipe "Name" {
ingredients {
milk 10 oz
}
steps {
pour milk
}
}
Required: an ingredients block (NAME AMOUNT UNIT per line) and a steps
block (ACTION ... per line). Optional: yield AMOUNT UNIT, description TEXT,
tag NAME. The flat form (ingredient milk 10 oz, step pour milk) is also
accepted.
Use separated amount and unit (standard KDL):
ingredient milk 10 oz # ✅
step stir 5 sec # ✅
Not glued tokens:
ingredient milk 10oz # 🚫
step stir 5s # 🚫
Base recipe (ORF-compatible)
recipe_name: Simple Latte
yields:
- amount: 1
unit: serving
ingredients:
- coffee grounds:
amounts:
- amount: 18
unit: g
processing:
- ground
steps:
- step: Grind the coffee.
The X-Phases block
When a .food recipe is authored with a phases block, the structured
.food.yaml carries those phases in an X-Phases ORF extension block (the
X- prefix follows the ORF convention for non-core fields). Each phase is a
named stage with optional key=value parameters and positional inputs:
X-Phases:
- phase: preinfuse
subject: coffee
params:
- { key: pressure, value: 2, unit: bar }
- { key: flow, value: 2, unit: mlps }
- { key: time, value: 6, unit: s }
- phase: brew
subject: coffee
output: shot
params:
- { key: pressure, value: 9, unit: bar }
- { key: stop, value: 40, unit: g }
- { key: max, value: 28, unit: s }
- phase: build
subject: cup
params:
- { ref: vanilla_syrup }
- { ref: shot }
- { ref: stir, value: 5, unit: s }
- { ref: ice }
- { ref: milk }
This is the structured equivalent of the .food phases block:
phases {
preinfuse coffee { pressure 2 bar; flow 2 mlps; time 6 s }
brew coffee to shot { pressure 9 bar; stop 40 g; max 28 s }
build cup { vanilla_syrup; shot; stir 5 s; ice; milk }
}
X-Phases round-trips losslessly: .food ⇄ .food.yaml. A phase has an
action, an optional subject (before {), an optional output (after to),
and a list of params — each a key/value/unit setting or a ref. Machine
targets (e.g. decent, s88, food-exec) read these phases through the
execution plan.
The X-foodlang block
X-foodlang:
version: 0.1
profiles: [process, appliance, robot, web]
transformations: []
equipment: []
checks: []
appliance_targets: {}
robot: {}
industrial: {}
exports: {}
Transformations
The core concept — typed inputs become typed outputs.
- id: extract_espresso
type: extraction
inputs:
- ingredient: coffee grounds
state: ground
amount: { value: 18, unit: g }
- ingredient: water
state: hot
amount: { value: 40, unit: mL }
outputs:
- ingredient: espresso
state: brewed
amount: { value: 40, unit: mL }
parameters:
temperature: { value: 93, unit: Cel }
Equipment, checks, targets
- equipment —
{ id, name, capabilities[] }. - checks —
{ id, description, required?, expression?, on_fail }. - appliance_targets —
opcua,home_connect,mqtt,matter(mappings). - robot.action_graph — DAG of
{ id, action, depends_on?, inputs?, outputs? }. - industrial.s88 —
procedure[]of{ operation, phases[] }. - exports — boolean hints of intended outputs.
Validation levels
| Level | Name |
|---|---|
| 0 | readable |
| 1 | parseable |
| 2 | structured ingredients |
| 3 | process-aware |
| 4 | appliance-mappable |
| 5 | robot-plannable |
| 6 | industrial-mappable |
Each level reports pass, partial, or fail.