One slot, three shapes
The concept table says a principle has an interface of ingredient roles, a dish binds them, and a variant overrides them. In the record those are three small JSON shapes, and one key, role, runs through all of them.
| Level | Column | One entry | Example |
|---|---|---|---|
| Principle | roles | {role, examples} | 향채 (aromatic), with garlic and scallion as examples |
| Dish | bindings | {role, value, confidence} | 기름 (fat) bound to olive oil, high confidence |
| Variant | overrides | {role, from, to, why} | 기름: olive oil to perilla oil, for its nutty aroma |
The role name is the thread. A principle says it needs an aromatic, a fat and a main ingredient. Gambas al ajillo answers with garlic, olive oil and prawns. A home version answers again for one role only: the fat, from olive oil to perilla oil, with a reason. The doc writes that kind of lineage as "Tapas-bar gambas → Perilla-oil gambas (fat: olive oil → perilla oil, because …)". Read it as a diff against the parent. One slot, the old value, the new value, and why.
Who writes each shape
Roles and bindings come from readings. When I read a plate, the rubric asks me for each dish's bindings and each principle's roles, with short Korean role names such as 향채 (aromatic), 기름 (fat), 주재료 (main ingredient) and 열 (heat). That follows Dad's naming ruling: principle names and explanations in Korean, dish names in their own language with a Korean gloss, the app's chrome in English. Pydantic models in backend/reading.py give each shape its fields and a default for every one, so a missing key arrives as an empty string or a medium confidence instead of an error. Track 3 covers how that parse forgives and normalises.
Overrides come only from Dad. There are two doors. On the web, a dish or variant page has a Make my version form. In a conversation on either client, I can propose a variant action, and it becomes a class only when Dad applies it. Both doors end in the same method, derive_variant in backend/domain.py.
The rules a variant has to pass
- It derives from a dish or another variant, never from a principle. An abstract class is not overridden directly. You override a concrete dish, which already binds the roles.
- Every override names a role and a new value. An entry missing either is dropped.
fromandwhyare optional, and each field is trimmed to a length cap. - At least one override must survive, or the variant is refused. A version that changes nothing is the same dish.
- It is born adopted, with origin
dad, takes its parent's cuisine, and starts with exactly one parent. - If a plate is named, the plate is tied to it, so a photographed home version starts with evidence.
The route adds its own bounds before any of that runs. VariantIn in backend/app.py takes a name of 1 to 200 characters and 1 to 12 overrides, each with a role and a target value.
The form starts from the parent's answer
On the web, choosing a role in the Make my version form fills from with the value the dish binds to that role, and the role field suggests the dish's own binding roles. You begin with the parent's answer and change it, which is what an override is. For tying, the form offers only this dish's plates that were cooked at home, because a version you made is evidence from your own stove. The phone has no such form; there a variant arrives only as an action applied from a conversation.
An interface made of names
Here the analogy stops being exact, and it is worth seeing where. In a typed language an interface is checked: a class that forgets a method does not compile. Sizzle's interface is a vocabulary. Nothing checks that a dish binds every role its principle lists, or that an override's role appears among the parent's bindings. The form suggests roles and requires none. A role is a short Korean name, and two readings can name the same slot a little differently.
For a record grown from photos and conversation, that is a fair trade. A strict checker would refuse a reading over spelling and lose the plate's knowledge with it. The cost is that consistent role names are a habit, on my side when I read and on Dad's when he names an override. If you want the vocabulary itself, interface, overriding and the rest, OO Quest Track 7, The Complete Toolkit lays it out; this lesson only shows where each word landed.