soustack 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/README.md +4 -4
  2. package/dist/cli/index.js +4412 -1275
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/index.d.mts +106 -80
  5. package/dist/index.d.ts +106 -80
  6. package/dist/index.js +4527 -1360
  7. package/dist/index.js.map +1 -1
  8. package/dist/index.mjs +4527 -1360
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/scrape/index.d.mts +86 -74
  11. package/dist/scrape/index.d.ts +86 -74
  12. package/dist/scrape/index.js +91 -64
  13. package/dist/scrape/index.js.map +1 -1
  14. package/dist/scrape/index.mjs +91 -64
  15. package/dist/scrape/index.mjs.map +1 -1
  16. package/package.json +15 -6
  17. package/spec/.sync-meta.json +149 -0
  18. package/spec/SOUSTACK_SPEC_VERSION +1 -0
  19. package/spec/defs/common.schema.json +46 -0
  20. package/spec/defs/duration.schema.json +33 -0
  21. package/spec/defs/entities.schema.json +111 -0
  22. package/spec/defs/ingredientQuantified.schema.json +9 -0
  23. package/spec/defs/quantity.schema.json +16 -0
  24. package/spec/defs/scalingRule.schema.json +127 -0
  25. package/spec/defs/temperature.schema.json +63 -0
  26. package/spec/fixtures/content/illustrated-step.valid.json +24 -0
  27. package/spec/fixtures/invalid/equipment-unknown-reference.invalid.json +38 -0
  28. package/spec/fixtures/invalid/mise-en-place-unknown-equipment.invalid.json +37 -0
  29. package/spec/fixtures/invalid/mise-en-place-unknown-input.invalid.json +41 -0
  30. package/spec/fixtures/invalid/storage-leftovers-missing-method.invalid.json +31 -0
  31. package/spec/fixtures/invalid/storage-leftovers-wrong-type.invalid.json +23 -0
  32. package/spec/fixtures/level/base-full.valid.json +162 -0
  33. package/spec/fixtures/level/base-missing-yield.invalid.json +12 -0
  34. package/spec/fixtures/level/lite-min.valid.json +14 -0
  35. package/spec/fixtures/profile/profile-base.valid.json +20 -0
  36. package/spec/fixtures/profile/profile-equipped.valid.json +28 -0
  37. package/spec/fixtures/profile/profile-illustrated.valid.json +28 -0
  38. package/spec/fixtures/profile/profile-lite.valid.json +13 -0
  39. package/spec/fixtures/profile/profile-prepped.valid.json +31 -0
  40. package/spec/fixtures/profile/profile-scalable-missing-scaling.invalid.json +29 -0
  41. package/spec/fixtures/profile/profile-scalable.valid.json +49 -0
  42. package/spec/fixtures/profile/profile-timed-missing-structured.invalid.json +30 -0
  43. package/spec/fixtures/scaling/bakers-percent-missing-ref.invalid.json +41 -0
  44. package/spec/fixtures/scaling/bakers-percent.valid.json +51 -0
  45. package/spec/fixtures/scaling/discrete-range.invalid.json +36 -0
  46. package/spec/fixtures/scaling/missing-quantified.invalid.json +40 -0
  47. package/spec/fixtures/scaling/reject-bakersPercentage.invalid.json +50 -0
  48. package/spec/fixtures/stacks/compute-missing-timed.invalid.json +32 -0
  49. package/spec/fixtures/stacks/dietary-no-signal.invalid.json +16 -0
  50. package/spec/fixtures/stacks/illustrated-empty.invalid.json +13 -0
  51. package/spec/fixtures/stacks/quantified-string.invalid.json +22 -0
  52. package/spec/fixtures/stacks/referenced-missing-input.invalid.json +32 -0
  53. package/spec/fixtures/stacks/storage-min.valid.json +20 -0
  54. package/spec/fixtures/stacks/storage-no-duration.invalid.json +16 -0
  55. package/spec/fixtures/stacks/timed-implies-structured.valid.json +50 -0
  56. package/spec/fixtures/stacks/timed-range.invalid.json +33 -0
  57. package/spec/fixtures/valid/equipment-scaling-rules.valid.json +76 -0
  58. package/spec/fixtures/valid/equipment-strings.valid.json +31 -0
  59. package/spec/fixtures/valid/equipment-structured-uses.valid.json +47 -0
  60. package/spec/fixtures/valid/mise-en-place-basic.valid.json +31 -0
  61. package/spec/fixtures/valid/mise-en-place-referenced-equipment.valid.json +51 -0
  62. package/spec/fixtures/valid/prep-ingredient-strings.valid.json +48 -0
  63. package/spec/fixtures/valid/prep-ingredient-structured.valid.json +45 -0
  64. package/spec/fixtures/valid/profile-equipped.valid.json +29 -0
  65. package/spec/fixtures/valid/profile-prepped.valid.json +32 -0
  66. package/spec/fixtures/valid/quantified-nested-ingredient-sections.valid.json +61 -0
  67. package/spec/fixtures/valid/referenced-scaling.valid.json +67 -0
  68. package/spec/fixtures/valid/storage-leftovers-simple.valid.json +27 -0
  69. package/spec/fixtures/valid/storage-leftovers-structured.valid.json +43 -0
  70. package/spec/fixtures/valid/structured-nested-step-sections.valid.json +84 -0
  71. package/spec/schemas/stacks-registry.schema.json +108 -0
  72. package/spec/soustack.schema.json +2379 -0
  73. package/spec/stacks/compute.schema.json +7 -0
  74. package/spec/stacks/compute@1.md +22 -0
  75. package/spec/stacks/dietary.schema.json +45 -0
  76. package/spec/stacks/dietary@1.md +24 -0
  77. package/spec/stacks/equipment.schema.json +98 -0
  78. package/spec/stacks/equipment@1.md +244 -0
  79. package/spec/stacks/illustrated.schema.json +54 -0
  80. package/spec/stacks/illustrated@1.md +24 -0
  81. package/spec/stacks/prep.schema.json +76 -0
  82. package/spec/stacks/prep@1.md +276 -0
  83. package/spec/stacks/quantified.schema.json +74 -0
  84. package/spec/stacks/quantified@1.md +24 -0
  85. package/spec/stacks/referenced.schema.json +96 -0
  86. package/spec/stacks/referenced@1.md +23 -0
  87. package/spec/stacks/registry.json +112 -0
  88. package/spec/stacks/scaling.schema.json +99 -0
  89. package/spec/stacks/scaling@1.md +238 -0
  90. package/spec/stacks/storage.schema.json +132 -0
  91. package/spec/stacks/storage@1.md +256 -0
  92. package/spec/stacks/structured.schema.json +48 -0
  93. package/spec/stacks/structured@1.md +24 -0
  94. package/spec/stacks/substitutions.schema.json +43 -0
  95. package/spec/stacks/substitutions@1.md +24 -0
  96. package/spec/stacks/techniques.schema.json +28 -0
  97. package/spec/stacks/techniques@1.md +23 -0
  98. package/spec/stacks/timed.schema.json +60 -0
  99. package/spec/stacks/timed@1.md +23 -0
  100. package/src/defs/common.schema.json +46 -0
  101. package/src/defs/duration.schema.json +33 -0
  102. package/src/defs/entities.schema.json +111 -0
  103. package/src/defs/ingredientQuantified.schema.json +9 -0
  104. package/src/defs/quantity.schema.json +16 -0
  105. package/src/defs/scalingRule.schema.json +127 -0
  106. package/src/defs/temperature.schema.json +63 -0
  107. package/src/profiles/base.schema.json +2 -2
  108. package/src/profiles/equipped.schema.json +10 -0
  109. package/src/profiles/illustrated.schema.json +4 -4
  110. package/src/profiles/lite.schema.json +10 -0
  111. package/src/profiles/prepped.schema.json +10 -0
  112. package/src/profiles/scalable.schema.json +6 -6
  113. package/src/profiles/timed.schema.json +10 -0
  114. package/src/schema.json +2271 -248
  115. package/src/schemas/stacks-registry.schema.json +108 -0
  116. package/src/soustack.schema.json +2271 -248
  117. package/src/stacks/compute.schema.json +7 -0
  118. package/src/stacks/compute@1.md +22 -0
  119. package/src/stacks/dietary.schema.json +45 -0
  120. package/src/stacks/dietary@1.md +24 -0
  121. package/src/stacks/equipment.schema.json +98 -0
  122. package/src/stacks/equipment@1.md +244 -0
  123. package/src/stacks/illustrated.schema.json +54 -0
  124. package/src/stacks/illustrated@1.md +24 -0
  125. package/src/stacks/prep.schema.json +76 -0
  126. package/src/stacks/prep@1.md +276 -0
  127. package/src/stacks/quantified.schema.json +74 -0
  128. package/src/stacks/quantified@1.md +24 -0
  129. package/src/stacks/referenced.schema.json +96 -0
  130. package/src/stacks/referenced@1.md +23 -0
  131. package/src/stacks/registry.json +112 -0
  132. package/src/stacks/scaling.schema.json +99 -0
  133. package/src/stacks/scaling@1.md +238 -0
  134. package/src/stacks/storage.schema.json +132 -0
  135. package/src/stacks/storage@1.md +256 -0
  136. package/src/stacks/structured.schema.json +48 -0
  137. package/src/stacks/structured@1.md +24 -0
  138. package/src/stacks/substitutions.schema.json +43 -0
  139. package/src/stacks/substitutions@1.md +24 -0
  140. package/src/stacks/techniques.schema.json +28 -0
  141. package/src/stacks/techniques@1.md +23 -0
  142. package/src/stacks/timed.schema.json +60 -0
  143. package/src/stacks/timed@1.md +23 -0
  144. package/src/profiles/cookable.schema.json +0 -18
  145. package/src/profiles/quantified.schema.json +0 -43
  146. package/src/profiles/schedulable.schema.json +0 -43
@@ -0,0 +1,276 @@
1
+ #prep@1
2
+
3
+ ---
4
+
5
+ ## Purpose
6
+
7
+ The `prep@1` stack enables recipes to include preparation guidance at both the ingredient level and as explicit mise en place tasks. This makes recipes more operational by providing clear prep instructions and planning checklists.
8
+
9
+ This stack is adoption-first: ingredient prep can be simple strings for minimal friction, or structured objects for more detailed guidance.
10
+
11
+ ---
12
+
13
+ ## Requirements
14
+
15
+ A document that declares `prep@1`:
16
+
17
+ • MUST satisfy all structural rules enabled by this stack.
18
+ • MUST satisfy the semantic rules described below.
19
+
20
+ ---
21
+
22
+ ## Data Model
23
+
24
+ When `prep@1` is declared, the document MUST include a top-level `miseEnPlace` array.
25
+
26
+ ### Mise En Place Array
27
+
28
+ The `miseEnPlace` array contains one or more tasks. Each task is a structured object that describes a prep step.
29
+
30
+ ### Ingredient-Level Prep
31
+
32
+ Ingredient objects MAY include an optional `prep` field that describes how the ingredient should be prepared. The `prep` field supports multiple formats:
33
+
34
+ • A single string (simple prep phrase)
35
+ • An array of strings (multiple prep notes)
36
+ • An array of structured prep items
37
+
38
+ ---
39
+
40
+ ## Ingredient Prep Formats
41
+
42
+ ### String Format
43
+
44
+ A simple string describing the prep:
45
+
46
+ ```json
47
+ {
48
+ "id": "onion",
49
+ "name": "Onion",
50
+ "prep": "finely diced"
51
+ }
52
+ ```
53
+
54
+ ### Array of Strings
55
+
56
+ Multiple prep notes:
57
+
58
+ ```json
59
+ {
60
+ "id": "garlic",
61
+ "name": "Garlic",
62
+ "prep": ["peeled", "minced"]
63
+ }
64
+ ```
65
+
66
+ ### Structured Prep Items
67
+
68
+ More detailed prep instructions with verbs and details:
69
+
70
+ ```json
71
+ {
72
+ "id": "tomato",
73
+ "name": "Tomato",
74
+ "prep": [
75
+ { "verb": "dice", "detail": "fine" },
76
+ { "verb": "reserve", "detail": "half for garnish" }
77
+ ]
78
+ }
79
+ ```
80
+
81
+ Each prep item object includes:
82
+
83
+ • `verb` (required): string describing the action (freeform; no controlled vocabulary in v1)
84
+ • `detail` (optional): string providing additional context
85
+
86
+ ---
87
+
88
+ ## Mise En Place Tasks
89
+
90
+ ### Minimal Task
91
+
92
+ A task with only required text:
93
+
94
+ ```json
95
+ {
96
+ "miseEnPlace": [
97
+ { "text": "Finely dice the onion" },
98
+ { "text": "Mince the garlic" }
99
+ ]
100
+ }
101
+ ```
102
+
103
+ ### Task with ID
104
+
105
+ Tasks may include an optional `id` for cross-referencing:
106
+
107
+ ```json
108
+ {
109
+ "miseEnPlace": [
110
+ { "id": "dice-onion", "text": "Finely dice the onion" },
111
+ { "id": "mince-garlic", "text": "Mince the garlic" }
112
+ ]
113
+ }
114
+ ```
115
+
116
+ Task IDs MUST be unique within the `miseEnPlace` array (semantic validation).
117
+
118
+ ### Task with Ingredient References
119
+
120
+ When `referenced@1` is present, tasks may reference ingredient IDs:
121
+
122
+ ```json
123
+ {
124
+ "miseEnPlace": [
125
+ {
126
+ "text": "Prepare the vegetables",
127
+ "inputs": ["onion", "garlic"]
128
+ }
129
+ ]
130
+ }
131
+ ```
132
+
133
+ Each id in `inputs` MUST exist in the ingredients array (semantic validation when both stacks are present).
134
+
135
+ ### Task with Equipment References
136
+
137
+ When `equipment@1` is present, tasks may reference equipment IDs:
138
+
139
+ ```json
140
+ {
141
+ "miseEnPlace": [
142
+ {
143
+ "text": "Sharpen the knife",
144
+ "usesEquipment": ["knife"]
145
+ }
146
+ ]
147
+ }
148
+ ```
149
+
150
+ Each id in `usesEquipment` MUST exist in the equipment array (semantic validation when both stacks are present).
151
+
152
+ ### Combined References
153
+
154
+ Tasks may include both `inputs` and `usesEquipment`:
155
+
156
+ ```json
157
+ {
158
+ "miseEnPlace": [
159
+ {
160
+ "text": "Dice the onion with a sharp knife",
161
+ "inputs": ["onion"],
162
+ "usesEquipment": ["knife"]
163
+ }
164
+ ]
165
+ }
166
+ ```
167
+
168
+ ---
169
+
170
+ ## Semantics
171
+
172
+ ### Prep Field
173
+
174
+ The ingredient `prep` field is descriptive and freeform. In v1, there is no controlled vocabulary for prep verbs or details. Tools may interpret these as hints for display or planning, but validation does not enforce specific values.
175
+
176
+ ### Mise En Place
177
+
178
+ The `miseEnPlace` array is an explicit checklist of prep tasks. Tools may render this as a prep plan, separate from the main cooking instructions. Tasks are ordered and may be presented as a sequential checklist.
179
+
180
+ ---
181
+
182
+ ## Composition
183
+
184
+ The prep stack is composable with other stacks:
185
+
186
+ • No hard dependency on `referenced@1` or `equipment@1` (references are optional and only validated when those stacks are present)
187
+ • Works with `structured@1` to enable ingredient object definitions
188
+ • Remains monotonic: does not close objects needed by other stacks
189
+ • Ingredient `prep` is optional even when the stack is present
190
+
191
+ ---
192
+
193
+ ## Semantic Validation Rules (Normative)
194
+
195
+ Validators MUST enforce the following rules:
196
+
197
+ 1. Mise en place task ID uniqueness
198
+ If tasks include `id` values, all task IDs MUST be unique within the `miseEnPlace` array.
199
+
200
+ 2. Ingredient reference resolution
201
+ If both `prep@1` and `referenced@1` are present, and a task includes `inputs`, all referenced ingredient IDs MUST exist in the ingredients array.
202
+
203
+ 3. Equipment reference resolution
204
+ If both `prep@1` and `equipment@1` are present, and a task includes `usesEquipment`, all referenced equipment IDs MUST exist in the equipment array (as object ids, not string items).
205
+
206
+ ---
207
+
208
+ ## Examples
209
+
210
+ Minimal mise en place
211
+
212
+ ```json
213
+ {
214
+ "miseEnPlace": [
215
+ { "text": "Finely dice the onion" },
216
+ { "text": "Mince the garlic" }
217
+ ]
218
+ }
219
+ ```
220
+
221
+ Ingredient prep with strings
222
+
223
+ ```json
224
+ {
225
+ "ingredients": [
226
+ {
227
+ "id": "onion",
228
+ "name": "Onion",
229
+ "prep": "finely diced"
230
+ },
231
+ {
232
+ "id": "garlic",
233
+ "name": "Garlic",
234
+ "prep": ["peeled", "minced"]
235
+ }
236
+ ]
237
+ }
238
+ ```
239
+
240
+ Structured prep items
241
+
242
+ ```json
243
+ {
244
+ "ingredients": [
245
+ {
246
+ "id": "tomato",
247
+ "name": "Tomato",
248
+ "prep": [
249
+ { "verb": "dice", "detail": "fine" },
250
+ { "verb": "reserve", "detail": "half for garnish" }
251
+ ]
252
+ }
253
+ ]
254
+ }
255
+ ```
256
+
257
+ Mise en place with references
258
+
259
+ ```json
260
+ {
261
+ "equipment": [
262
+ { "id": "knife", "name": "Chef's knife" }
263
+ ],
264
+ "ingredients": [
265
+ { "id": "onion", "name": "Onion" }
266
+ ],
267
+ "miseEnPlace": [
268
+ {
269
+ "text": "Dice the onion with a sharp knife",
270
+ "inputs": ["onion"],
271
+ "usesEquipment": ["knife"]
272
+ }
273
+ ]
274
+ }
275
+ ```
276
+
@@ -0,0 +1,74 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://soustack.spec/stacks/quantified.schema.json",
4
+ "title": "Quantified Stack",
5
+ "type": "object",
6
+ "properties": {
7
+ "ingredients": {
8
+ "type": "array",
9
+ "items": {
10
+ "anyOf": [
11
+ { "$ref": "#/$defs/ingredient" },
12
+ { "$ref": "#/$defs/ingredientSection" }
13
+ ]
14
+ }
15
+ }
16
+ },
17
+ "required": ["ingredients"],
18
+ "$defs": {
19
+ "ingredient": {
20
+ "type": "object",
21
+ "properties": {
22
+ "id": { "type": "string" },
23
+ "name": { "type": "string" },
24
+ "quantity": { "$ref": "../defs/quantity.schema.json" },
25
+ "temperature": { "$ref": "../defs/temperature.schema.json" },
26
+ "notes": { "type": "string" },
27
+ "prep": {
28
+ "oneOf": [
29
+ { "type": "string", "minLength": 1 },
30
+ {
31
+ "type": "array",
32
+ "minItems": 1,
33
+ "items": {
34
+ "anyOf": [
35
+ { "type": "string", "minLength": 1 },
36
+ { "$ref": "../stacks/prep.schema.json#/$defs/prepItem" }
37
+ ]
38
+ }
39
+ }
40
+ ]
41
+ },
42
+ "metadata": { "type": "object", "additionalProperties": true },
43
+ "scaling": { "$ref": "../defs/scalingRule.schema.json" }
44
+ },
45
+ "required": ["id", "name", "quantity"],
46
+ "additionalProperties": false,
47
+ "patternProperties": {
48
+ "^x-": { "$ref": "../defs/common.schema.json#/properties/extensionLaneValue" }
49
+ }
50
+ },
51
+ "ingredientSection": {
52
+ "type": "object",
53
+ "properties": {
54
+ "section": { "type": "string" },
55
+ "ingredients": {
56
+ "type": "array",
57
+ "items": {
58
+ "anyOf": [
59
+ { "$ref": "#/$defs/ingredient" },
60
+ { "$ref": "#/$defs/ingredientSection" }
61
+ ]
62
+ }
63
+ },
64
+ "metadata": { "type": "object", "additionalProperties": true }
65
+ },
66
+ "required": ["section", "ingredients"],
67
+ "additionalProperties": false,
68
+ "patternProperties": {
69
+ "^x-": { "$ref": "../defs/common.schema.json#/properties/extensionLaneValue" }
70
+ }
71
+ }
72
+ },
73
+ "additionalProperties": false
74
+ }
@@ -0,0 +1,24 @@
1
+ # quantified@1
2
+
3
+ ## Purpose
4
+ The `quantified@1` stack enables recipes to declare precise ingredient quantities with units, enabling scaling and computation.
5
+
6
+ ## Adds
7
+ - Top-level `ingredients` array with structured ingredient objects containing `id`, `name`, and `quantity` fields.
8
+ - Ingredients may include `temperature`, `notes`, `prep`, `scaling`, and `metadata`.
9
+ - Support for nested ingredient sections.
10
+
11
+ ## Requires
12
+ - None
13
+
14
+ ## Semantics
15
+ - MUST: Each ingredient object must include `id`, `name`, and `quantity` fields.
16
+ - MUST: Ingredient IDs must be unique within the ingredients array.
17
+ - NOTE: This stack is a prerequisite for `scaling@1`.
18
+
19
+ ## Composition Notes
20
+ - This stack is monotonic: it adds requirements or fields without removing expressiveness.
21
+ - Interaction: Required by `scaling@1` for scaling behavior. Works with `structured@1` for stable ingredient references.
22
+
23
+
24
+
@@ -0,0 +1,96 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://soustack.spec/stacks/referenced.schema.json",
4
+ "title": "Referenced Stack",
5
+ "type": "object",
6
+ "properties": {
7
+ "ingredients": {
8
+ "type": "array",
9
+ "items": {
10
+ "anyOf": [
11
+ { "$ref": "#/$defs/ingredient" },
12
+ { "$ref": "#/$defs/ingredientSection" }
13
+ ]
14
+ }
15
+ },
16
+ "instructions": {
17
+ "type": "array",
18
+ "items": {
19
+ "anyOf": [
20
+ { "$ref": "#/$defs/referencedStep" },
21
+ { "$ref": "#/$defs/referencedSection" }
22
+ ]
23
+ }
24
+ }
25
+ },
26
+ "required": ["ingredients", "instructions"],
27
+ "allOf": [
28
+ { "$ref": "./structured.schema.json" }
29
+ ],
30
+ "$defs": {
31
+ "ingredient": {
32
+ "allOf": [
33
+ { "$ref": "../defs/entities.schema.json#/$defs/IngredientBase" },
34
+ { "required": ["id"] }
35
+ ]
36
+ },
37
+ "ingredientSection": {
38
+ "type": "object",
39
+ "properties": {
40
+ "section": { "type": "string" },
41
+ "ingredients": {
42
+ "type": "array",
43
+ "items": {
44
+ "anyOf": [
45
+ { "$ref": "#/$defs/ingredient" },
46
+ { "$ref": "#/$defs/ingredientSection" }
47
+ ]
48
+ }
49
+ },
50
+ "metadata": { "type": "object", "additionalProperties": true }
51
+ },
52
+ "required": ["section", "ingredients"],
53
+ "additionalProperties": false,
54
+ "patternProperties": {
55
+ "^x-": { "$ref": "../defs/common.schema.json#/properties/extensionLaneValue" }
56
+ }
57
+ },
58
+ "referencedStep": {
59
+ "allOf": [
60
+ { "$ref": "../defs/entities.schema.json#/$defs/StepBase" },
61
+ {
62
+ "properties": {
63
+ "inputs": {
64
+ "allOf": [
65
+ { "$ref": "../defs/entities.schema.json#/$defs/StepBase/properties/inputs" },
66
+ { "minItems": 1 }
67
+ ]
68
+ }
69
+ },
70
+ "required": ["id", "inputs"]
71
+ }
72
+ ]
73
+ },
74
+ "referencedSection": {
75
+ "type": "object",
76
+ "properties": {
77
+ "section": { "type": "string" },
78
+ "steps": {
79
+ "type": "array",
80
+ "items": {
81
+ "anyOf": [
82
+ { "$ref": "#/$defs/referencedStep" },
83
+ { "$ref": "#/$defs/referencedSection" }
84
+ ]
85
+ }
86
+ },
87
+ "metadata": { "type": "object", "additionalProperties": true }
88
+ },
89
+ "required": ["section", "steps"],
90
+ "additionalProperties": false,
91
+ "patternProperties": {
92
+ "^x-": { "$ref": "../defs/common.schema.json#/properties/extensionLaneValue" }
93
+ }
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,23 @@
1
+ # referenced@1
2
+
3
+ ## Purpose
4
+ The `referenced@1` stack enables steps to explicitly reference ingredient IDs, creating clear input-output relationships for planning and validation.
5
+
6
+ ## Adds
7
+ - Step objects must include an `inputs` array with at least one ingredient ID reference.
8
+ - Ingredient objects must include `id` fields.
9
+
10
+ ## Requires
11
+ - `structured@1`
12
+
13
+ ## Semantics
14
+ - MUST: Each step must include an `inputs` array with at least one element.
15
+ - MUST: All ingredient IDs referenced in step `inputs` must exist in the ingredients array.
16
+ - NOTE: This stack implies `structured@1` (steps are objects with IDs).
17
+
18
+ ## Composition Notes
19
+ - This stack is monotonic: it adds requirements or fields without removing expressiveness.
20
+ - Interaction: Required by `substitutions@1` for substitution target resolution. Works with `prep@1` for mise en place task references.
21
+
22
+
23
+
@@ -0,0 +1,112 @@
1
+ {
2
+ "$schema": "../schemas/stacks-registry.schema.json",
3
+ "registryVersion": 1,
4
+ "spec": {
5
+ "name": "soustack",
6
+ "currentSpecVersion": "0.3.0",
7
+ "canonicalStacksFormat": "map"
8
+ },
9
+ "profiles": {
10
+ "lite": { "title": "Lite", "description": "Lowest-friction publishing with minimal structure", "requiresProfiles": [], "requiresStacks": [] },
11
+ "base": { "title": "Base", "description": "Minimum cookable baseline with yield + time", "requiresProfiles": ["lite"], "requiresStacks": [] },
12
+ "scalable": { "title": "Scalable", "description": "Quantified + scaling", "requiresProfiles": ["base"], "requiresStacks": ["quantified", "scaling"] },
13
+ "timed": { "title": "Timed", "description": "Structured + timed", "requiresProfiles": ["base"], "requiresStacks": ["structured", "timed"] },
14
+ "illustrated": { "title": "Illustrated", "description": "Media present", "requiresProfiles": ["base"], "requiresStacks": ["illustrated"] },
15
+ "equipped": { "title": "Equipped", "description": "Recipe declares required tools/equipment.", "requiresProfiles": ["base"], "requiresStacks": ["equipment"] },
16
+ "prepped": { "title": "Prepped", "description": "Recipe includes prep guidance and/or mise en place tasks.", "requiresProfiles": ["base"], "requiresStacks": ["prep"] }
17
+ },
18
+ "stacks": {
19
+ "quantified": {
20
+ "title": "Quantified",
21
+ "latestMajor": 1,
22
+ "requires": [],
23
+ "schema": { "major": { "1": "stacks/quantified.schema.json" } },
24
+ "docs": { "major": { "1": "stacks/quantified@1.md" } }
25
+ },
26
+ "scaling": {
27
+ "title": "Scaling",
28
+ "latestMajor": 1,
29
+ "requires": ["quantified"],
30
+ "schema": { "major": { "1": "stacks/scaling.schema.json" } },
31
+ "docs": { "major": { "1": "stacks/scaling@1.md" } }
32
+ },
33
+ "structured": {
34
+ "title": "Structured",
35
+ "latestMajor": 1,
36
+ "requires": [],
37
+ "schema": { "major": { "1": "stacks/structured.schema.json" } },
38
+ "docs": { "major": { "1": "stacks/structured@1.md" } }
39
+ },
40
+ "timed": {
41
+ "title": "Timed",
42
+ "latestMajor": 1,
43
+ "requires": ["structured"],
44
+ "schema": { "major": { "1": "stacks/timed.schema.json" } },
45
+ "docs": { "major": { "1": "stacks/timed@1.md" } }
46
+ },
47
+ "referenced": {
48
+ "title": "Referenced",
49
+ "latestMajor": 1,
50
+ "requires": ["structured"],
51
+ "schema": { "major": { "1": "stacks/referenced.schema.json" } },
52
+ "docs": { "major": { "1": "stacks/referenced@1.md" } }
53
+ },
54
+ "illustrated": {
55
+ "title": "Illustrated",
56
+ "latestMajor": 1,
57
+ "requires": [],
58
+ "schema": { "major": { "1": "stacks/illustrated.schema.json" } },
59
+ "docs": { "major": { "1": "stacks/illustrated@1.md" } }
60
+ },
61
+ "dietary": {
62
+ "title": "Dietary",
63
+ "latestMajor": 1,
64
+ "requires": [],
65
+ "schema": { "major": { "1": "stacks/dietary.schema.json" } },
66
+ "docs": { "major": { "1": "stacks/dietary@1.md" } }
67
+ },
68
+ "substitutions": {
69
+ "title": "Substitutions",
70
+ "latestMajor": 1,
71
+ "requires": ["referenced"],
72
+ "schema": { "major": { "1": "stacks/substitutions.schema.json" } },
73
+ "docs": { "major": { "1": "stacks/substitutions@1.md" } }
74
+ },
75
+ "techniques": {
76
+ "title": "Techniques",
77
+ "latestMajor": 1,
78
+ "requires": [],
79
+ "schema": { "major": { "1": "stacks/techniques.schema.json" } },
80
+ "docs": { "major": { "1": "stacks/techniques@1.md" } }
81
+ },
82
+ "storage": {
83
+ "title": "Storage",
84
+ "latestMajor": 1,
85
+ "requires": [],
86
+ "schema": { "major": { "1": "stacks/storage.schema.json" } },
87
+ "docs": { "major": { "1": "stacks/storage@1.md" } }
88
+ },
89
+ "compute": {
90
+ "title": "Compute",
91
+ "latestMajor": 1,
92
+ "requires": ["quantified", "timed"],
93
+ "schema": { "major": { "1": "stacks/compute.schema.json" } },
94
+ "docs": { "major": { "1": "stacks/compute@1.md" } }
95
+ },
96
+ "equipment": {
97
+ "title": "Equipment",
98
+ "latestMajor": 1,
99
+ "requires": [],
100
+ "schema": { "major": { "1": "stacks/equipment.schema.json" } },
101
+ "docs": { "major": { "1": "stacks/equipment@1.md" } }
102
+ },
103
+ "prep": {
104
+ "title": "Prep",
105
+ "latestMajor": 1,
106
+ "requires": [],
107
+ "schema": { "major": { "1": "stacks/prep.schema.json" } },
108
+ "docs": { "major": { "1": "stacks/prep@1.md" } }
109
+ }
110
+ }
111
+ }
112
+