diff --git a/examples/creamy-tofu-broccoli/README.adoc b/examples/creamy-tofu-broccoli/README.adoc index 7e9e0ec..4efbb14 100644 --- a/examples/creamy-tofu-broccoli/README.adoc +++ b/examples/creamy-tofu-broccoli/README.adoc @@ -15,6 +15,12 @@ The example demonstrates that the RPF Core Model can describe a complete recipe `recipe.rpf.yaml` is an experimental design artefact. It is not a proposed serialization format. Its purpose is readability and a faithful representation of the Core Model. +== Material Flow View + +The Core Model defines the recipe's semantics. `material-flow.adoc` and `graph.mmd` project those semantics into a Material Flow View for human readers. + +The Material Flow View follows ingredients and process states as they change and merge. It does not add meaning, change the recipe, or define an alternative model. Read `material-flow.adoc` for the canonical reader-oriented diagram and renderer guidance; `graph.mmd` is a Mermaid approximation of that view. + == Modelling Challenges The source recipe gives alternatives for mushrooms and for tahini or peanut butter. These are represented as alternative Ingredient choices, rather than as new conceptual entities. The source also leaves rice and garnish quantities open; the corresponding consumption relationships therefore use `as needed` or `to taste`. @@ -26,4 +32,5 @@ No additional core concepts appeared necessary. By-products, cooking time, cookw == Files - `recipe.rpf.yaml` is the readable experimental graph. -- `graph.mmd` is the Mermaid rendering of the same Ingredient-Operation-State graph. +- `material-flow.adoc` is the canonical state-first Material Flow View and its rendering guidance. +- `graph.mmd` is a Mermaid approximation of the Material Flow View. diff --git a/examples/creamy-tofu-broccoli/graph.mmd b/examples/creamy-tofu-broccoli/graph.mmd index fc4b1e6..dd0cc50 100644 --- a/examples/creamy-tofu-broccoli/graph.mmd +++ b/examples/creamy-tofu-broccoli/graph.mmd @@ -1,63 +1,60 @@ -flowchart TD - tofu["Ingredient: firm tofu"] --> press(["Operation: press tofu"]) - press --> pressed[["State: pressed tofu"]] - pressed --> cutTofu(["Operation: cut tofu"]) - cutTofu --> cubed[["State: cubed tofu"]] - cubed --> coat(["Operation: coat tofu"]) - cornstarch["Ingredient: cornstarch"] --> coat - coat --> coated[["State: coated tofu"]] - coated --> fryTofu(["Operation: fry tofu"]) - rapeseedOil["Ingredient: rapeseed oil"] --> fryTofu - fryTofu --> friedTofu[["State: fried tofu"]] +%% Human-oriented material-flow approximation. +%% Operations label transitions; boxes are ingredients or resulting process states. +flowchart LR + subgraph tofuFlow["Tofu flow"] + direction TB + tofu["Firm tofu"] -->|Press| pressed["Pressed tofu"] + pressed -->|Cut| cubed["Cubed tofu"] + cornstarch["Cornstarch"] -->|Coat| coated["Coated tofu"] + cubed -->|Coat| coated + rapeseedOil["Rapeseed oil"] -->|Fry| friedTofu["Fried tofu"] + coated -->|Fry| friedTofu + end - broccoli["Ingredient: broccoli"] --> cutBroccoli(["Operation: cut broccoli"]) - cutBroccoli --> broccoliFlorets[["State: broccoli florets"]] - mushrooms["Ingredient: mushrooms"] --> sliceMushrooms(["Operation: slice mushrooms"]) - sliceMushrooms --> slicedMushrooms[["State: sliced mushrooms"]] - onion["Ingredient: yellow onion"] --> sliceOnion(["Operation: slice onion"]) - sliceOnion --> slicedOnion[["State: sliced onion"]] - garlic["Ingredient: garlic"] --> chopGarlic(["Operation: chop garlic"]) - chopGarlic --> choppedGarlic[["State: chopped garlic"]] - ginger["Ingredient: fresh ginger"] --> grateGinger(["Operation: grate ginger"]) - grateGinger --> gratedGinger[["State: grated ginger"]] - slicedOnion --> saute(["Operation: saute aromatics and mushrooms"]) - slicedMushrooms --> saute - choppedGarlic --> saute - gratedGinger --> saute - saute --> sauteed[["State: sauteed aromatics and mushrooms"]] - broccoliFlorets --> fryVegetables(["Operation: fry broccoli with vegetables"]) - sauteed --> fryVegetables - fryVegetables --> friedVegetables[["State: fried vegetables"]] + subgraph vegetableFlow["Vegetable flow"] + direction TB + onion["Yellow onion"] -->|Slice| slicedOnion["Sliced onion"] + mushrooms["Mushrooms"] -->|Slice| slicedMushrooms["Sliced mushrooms"] + garlic["Garlic"] -->|Chop| choppedGarlic["Chopped garlic"] + ginger["Fresh ginger"] -->|Grate| gratedGinger["Grated ginger"] + slicedOnion -->|Saute| sauteed["Sauteed aromatics and mushrooms"] + slicedMushrooms -->|Saute| sauteed + choppedGarlic -->|Saute| sauteed + gratedGinger -->|Saute| sauteed + broccoli["Broccoli"] -->|Cut| florets["Broccoli florets"] + florets -->|Fry together| friedVegetables["Fried vegetables"] + sauteed -->|Fry together| friedVegetables + end - cream["Ingredient: cooking cream"] --> mixSauce(["Operation: mix cream, sesame, and miso sauce"]) - stock["Ingredient: vegetable stock"] --> mixSauce - miso["Ingredient: white miso"] --> mixSauce - soy["Ingredient: Japanese soy sauce"] --> mixSauce - tahini["Ingredient: tahini or peanut butter"] --> mixSauce - mirin["Ingredient: mirin"] --> mixSauce - sesameOil["Ingredient: sesame oil"] --> mixSauce - vinegar["Ingredient: rice vinegar"] --> mixSauce - honey["Ingredient: honey"] --> mixSauce - cornstarch --> mixSauce - coldWater["Ingredient: cold water"] --> mixSauce - mixSauce --> mixedSauce[["State: mixed cream, sesame, and miso sauce"]] - friedVegetables --> combineSauce(["Operation: combine vegetables and sauce"]) - mixedSauce --> combineSauce - combineSauce --> vegetablesInSauce[["State: vegetables in sauce"]] - vegetablesInSauce --> simmerVegetables(["Operation: simmer vegetables in sauce"]) - simmerVegetables --> simmeredVegetables[["State: simmered vegetables in sauce"]] - friedTofu --> simmerTofu(["Operation: simmer tofu in sauce"]) - simmeredVegetables --> simmerTofu - simmerTofu --> tofuBroccoliSauce[["State: tofu and broccoli in sesame and miso sauce"]] + subgraph sauceFlow["Sauce flow"] + direction TB + cream["Cooking cream"] -->|Mix| mixedSauce["Mixed cream, sesame, and miso sauce"] + stock["Vegetable stock"] -->|Mix| mixedSauce + miso["White miso"] -->|Mix| mixedSauce + soy["Japanese soy sauce"] -->|Mix| mixedSauce + tahini["Tahini or peanut butter"] -->|Mix| mixedSauce + mirin["Mirin"] -->|Mix| mixedSauce + sesameOil["Sesame oil"] -->|Mix| mixedSauce + vinegar["Rice vinegar"] -->|Mix| mixedSauce + honey["Honey"] -->|Mix| mixedSauce + sauceCornstarch["Cornstarch"] -->|Mix| mixedSauce + coldWater["Cold water"] -->|Mix| mixedSauce + friedVegetables -->|Combine| vegetablesInSauce["Vegetables in sauce"] + mixedSauce -->|Combine| vegetablesInSauce + vegetablesInSauce -->|Simmer| simmeredVegetables["Simmered vegetables in sauce"] + end - rice["Ingredient: jasmine rice"] --> cookRice(["Operation: cook jasmine rice"]) - water["Ingredient: water"] --> cookRice - cookRice --> cookedRice[["State: cooked jasmine rice"]] - springOnion["Ingredient: spring onion"] --> sliceSpringOnion(["Operation: slice spring onion"]) - sliceSpringOnion --> slicedSpringOnion[["State: sliced spring onion"]] + friedTofu -->|Simmer together| tofuBroccoliSauce["Tofu and broccoli in sesame and miso sauce"] + simmeredVegetables -->|Simmer together| tofuBroccoliSauce - cookedRice --> assemble(["Operation: assemble dish"]) - tofuBroccoliSauce --> assemble - sesameSeeds["Ingredient: toasted sesame seeds"] --> assemble - slicedSpringOnion --> assemble - assemble --> finished[["State: creamy tofu and broccoli dish"]] + subgraph servingFlow["Rice and garnish"] + direction TB + rice["Jasmine rice"] -->|Cook| cookedRice["Cooked jasmine rice"] + springOnion["Spring onion"] -->|Slice| slicedSpringOnion["Sliced spring onion"] + sesameSeeds["Toasted sesame seeds"] + end + + cookedRice -->|Assemble| finished["Creamy tofu and broccoli dish"] + tofuBroccoliSauce -->|Assemble| finished + slicedSpringOnion -->|Assemble| finished + sesameSeeds -->|Assemble| finished diff --git a/examples/creamy-tofu-broccoli/material-flow.adoc b/examples/creamy-tofu-broccoli/material-flow.adoc new file mode 100644 index 0000000..2bb39d3 --- /dev/null +++ b/examples/creamy-tofu-broccoli/material-flow.adoc @@ -0,0 +1,82 @@ += Material Flow View + +== Purpose + +This view presents the Creamy Tofu and Broccoli recipe as material flow for human readers. It follows ingredients and resulting process states through each transformation, then makes their merges explicit. + +The view is derived from the RPF Core Model. Each material label is an Ingredient or State from the recipe, and each transformation label corresponds to an Operation. The view adds no concepts and does not alter the semantics of the underlying recipe. + +== Complete Material Flow + +[source,text] +---- +TOFU FLOW VEGETABLE FLOW + +Firm tofu Yellow onion ─ Slice ─┐ + │ Press Mushrooms ─── Slice ─┤ +Pressed tofu Garlic ─────── Chop ──┤ Saute + │ Cut Ginger ─────── Grate ─┘ +Cubed tofu │ + │ Coat + cornstarch Sauteed aromatics +Coated tofu and mushrooms + │ Fry + rapeseed oil │ +Fried tofu ┌─┘ + │ Fry together +Broccoli ─ Cut ─ Broccoli florets ───────────────────┘ + │ + Fried vegetables + +SAUCE FLOW + +Cooking cream ────────┐ White miso ────────────┐ +Vegetable stock ──────┤ Japanese soy sauce ────┤ +Tahini or peanut butter ──── Mirin ─────────────────┤ +Sesame oil ───────────┤ Rice vinegar ──────────┤ Mix +Honey ────────────────┤ Cornstarch + cold water ┤ + └─────────────────────────────┘ + │ + Mixed cream, sesame, and miso sauce + +Fried vegetables ────────────────────────────────┐ +Mixed cream, sesame, and miso sauce ──────────────┤ Combine + │ + Vegetables in sauce + │ Simmer + Simmered vegetables + │ +Fried tofu ───────────────────────────────────────┤ Simmer together + │ + Tofu and broccoli in sesame and miso sauce + +RICE AND GARNISH FLOW + +Jasmine rice ─ Cook ─ Cooked jasmine rice ────────────┐ +Toasted sesame seeds ─────────────────────────────────┤ Assemble +Spring onion ─ Slice ─ Sliced spring onion ───────────┤ +Tofu and broccoli in sesame and miso sauce ───────────┘ + │ + Creamy tofu and broccoli dish +---- + +== Relationship to the Semantic Graph + +The semantic graph is the source of truth: it precisely records which Ingredients and States are consumed by each Operation and which State each Operation produces. + +The Material Flow View is a projection of that graph. It suppresses identifiers, data fields, and relationship notation in favour of readable material names, transformation labels, vertical state progression, and visible merge points. It does not imply a schedule, a required order of independent work, or a workflow engine. + +== Renderer Guidance + +A renderer SHOULD present the view as separate vertical flows for independently prepared materials. For each flow it SHOULD: + +- show the Ingredient or current State as the primary visual object; +- place the transformation name on the transition to the next State; +- make every multi-input transformation a visible merge; and +- show the State resulting from that merge before it is used again. + +The presentation MUST remain a faithful projection of the semantic graph. In particular, it MUST NOT merge distinct States, invent material transformations, or imply workflow dependencies that are absent from the Core Model. + +== Mermaid Approximation and Recommended Rendering + +`graph.mmd` follows the same material-flow vocabulary, but Mermaid uses automatic layout. It cannot reliably preserve vertical lanes, align merge junctions, or ensure that a complex diagram reads in the intended order. + +For a production renderer, an SVG or HTML/CSS-grid layout is recommended. It can assign each independent material flow a fixed lane, reserve merge columns, and render operation labels directly on transitions. The ASCII view above is the canonical reader-oriented representation for this example; Mermaid is retained as a portable approximation.