-
-
Notifications
You must be signed in to change notification settings - Fork 0
Recipe Specification
Praveen Kumar edited this page Jul 11, 2026
·
3 revisions
Recipes are YAML documents with version: 1. They are the durable artifact
CleanFrame is built around.
version: 1 # required
source_fingerprint: { ... } # optional; enables drift detection
columns: # map of source column name → ColumnRecipe
"Customer Name":
rename_to: customer_name
ops: [strip_whitespace, title_case]
frame_ops: # optional list
- dedup: {subset: [email], keep: first}
validate: # optional list of rules
- {column: email, check: valid_email, on_fail: quarantine}
meta: # optional free-form
generated_by: rules| Field | Meaning |
|---|---|
| key | Source column name as it appears in the input file |
rename_to |
Output name after Phase 2 |
ops |
Ordered list of column ops (see below) |
Ops may be bare names or mappings with parameters:
ops:
- strip_whitespace
- parse_date:
formats: ["%d/%m/%Y", "%Y-%m-%d"]
dayfirst: true
- normalize_values:
Bengaluru: Bangalore
BLR: BangaloreThe planner emits ops in canonical OP_ORDER. When editing by hand, prefer the
same order so transforms compose safely:
strip_whitespacecollapse_whitespaceto_naextract_currencyremove_symbolsnormalize_unitparse_numberroundcastparse_datenormalize_emailnormalize_phonereplacenormalize_values-
capitalize/title_case/lowercase/uppercase -
fill_na(never auto-proposed — human only)
| Op | Params |
|---|---|
to_na |
tokens, case_insensitive
|
parse_date |
formats, dayfirst, output (iso default) |
parse_number |
decimal/thousands separators, strip symbols |
cast |
to: float | int | string | bool | datetime | category — int rounds floats
|
normalize_phone |
country_code |
normalize_values |
mapping {variant: canonical}
|
extract_currency |
emits <col>_currency
|
normalize_unit |
to target unit |
replace |
pattern, repl, regex — patterns length/complexity limited |
fill_na |
value or strategy (mean/median/mode) |
round |
ndigits |
| Op | Params |
|---|---|
dedup |
subset, keep, case_insensitive
|
drop_columns |
list of names |
validate:
- column: amount_inr
check: ">= 0"
on_fail: quarantine
- column: email
check: valid_email
on_fail: quarantine
- column: code
check: "matches: ^[A-Z]{3}$"
on_fail: warnnot_null, unique, valid_email, valid_url, valid_phone
- Comparisons:
>= 0,<= 100,== 1,!= 0,>,< - Membership:
in [a, b, c] - Regex:
matches: <pattern>orregex: <pattern>
| Policy | Behaviour |
|---|---|
quarantine |
Move row to quarantine frame (default) |
error |
Raise ValidationFailure
|
warn |
Log only |
drop |
Discard row (explicit) |
null |
Blank the offending cell |
strict mode promotes every policy to error.
Stored so apply_recipe can detect drift. Includes column names, dtypes, row
count, and a sample hash. Do not hand-edit unless you know why.
assert Recipe.from_yaml(recipe.to_yaml()) == recipe
assert recipe.to_yaml() == Recipe.from_yaml(recipe.to_yaml()).to_yaml()Ops with parameters must implement coerce / compact so YAML stays minimal
and lossless — see CONTRIBUTING.md.