@q1k-oss/btree-workflows 0.0.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 (203) hide show
  1. package/.claude/settings.local.json +31 -0
  2. package/CLAUDE.md +181 -0
  3. package/LICENSE +21 -0
  4. package/README.md +920 -0
  5. package/behaviour-tree-workflows-landing/index.html +16 -0
  6. package/behaviour-tree-workflows-landing/package-lock.json +2074 -0
  7. package/behaviour-tree-workflows-landing/package.json +31 -0
  8. package/behaviour-tree-workflows-landing/public/favicon.svg +17 -0
  9. package/behaviour-tree-workflows-landing/src/App.css +103 -0
  10. package/behaviour-tree-workflows-landing/src/App.tsx +176 -0
  11. package/behaviour-tree-workflows-landing/src/components/BlackboardInspector.css +89 -0
  12. package/behaviour-tree-workflows-landing/src/components/BlackboardInspector.tsx +64 -0
  13. package/behaviour-tree-workflows-landing/src/components/ExampleSelector.css +64 -0
  14. package/behaviour-tree-workflows-landing/src/components/ExampleSelector.tsx +34 -0
  15. package/behaviour-tree-workflows-landing/src/components/ExecutionLog.css +107 -0
  16. package/behaviour-tree-workflows-landing/src/components/ExecutionLog.tsx +85 -0
  17. package/behaviour-tree-workflows-landing/src/components/Header.css +50 -0
  18. package/behaviour-tree-workflows-landing/src/components/Header.tsx +26 -0
  19. package/behaviour-tree-workflows-landing/src/components/StatusBadge.css +45 -0
  20. package/behaviour-tree-workflows-landing/src/components/StatusBadge.tsx +15 -0
  21. package/behaviour-tree-workflows-landing/src/components/Toolbar.css +74 -0
  22. package/behaviour-tree-workflows-landing/src/components/Toolbar.tsx +53 -0
  23. package/behaviour-tree-workflows-landing/src/components/TreeVisualizer.css +67 -0
  24. package/behaviour-tree-workflows-landing/src/components/TreeVisualizer.tsx +192 -0
  25. package/behaviour-tree-workflows-landing/src/components/YamlEditor.css +18 -0
  26. package/behaviour-tree-workflows-landing/src/components/YamlEditor.tsx +96 -0
  27. package/behaviour-tree-workflows-landing/src/lib/count-nodes.ts +11 -0
  28. package/behaviour-tree-workflows-landing/src/lib/execution-engine.ts +96 -0
  29. package/behaviour-tree-workflows-landing/src/lib/tree-layout.ts +136 -0
  30. package/behaviour-tree-workflows-landing/src/lib/yaml-examples.ts +549 -0
  31. package/behaviour-tree-workflows-landing/src/main.tsx +9 -0
  32. package/behaviour-tree-workflows-landing/src/stubs/activepieces.ts +18 -0
  33. package/behaviour-tree-workflows-landing/src/stubs/fs.ts +24 -0
  34. package/behaviour-tree-workflows-landing/src/stubs/path.ts +16 -0
  35. package/behaviour-tree-workflows-landing/src/stubs/temporal-activity.ts +6 -0
  36. package/behaviour-tree-workflows-landing/src/stubs/temporal-workflow.ts +22 -0
  37. package/behaviour-tree-workflows-landing/tsconfig.json +25 -0
  38. package/behaviour-tree-workflows-landing/vite.config.ts +40 -0
  39. package/demo-google-sheets.ts +181 -0
  40. package/demo-runtime-variables.ts +174 -0
  41. package/demo-template.ts +208 -0
  42. package/docs/ARCHITECTURE_SUMMARY.md +613 -0
  43. package/docs/NODE_REFERENCE.md +504 -0
  44. package/docs/README.md +53 -0
  45. package/docs/custom-nodes-architecture.md +826 -0
  46. package/docs/observability.md +175 -0
  47. package/docs/yaml-specification.md +990 -0
  48. package/examples/temporal/README.md +117 -0
  49. package/examples/temporal/activities.ts +373 -0
  50. package/examples/temporal/client.ts +115 -0
  51. package/examples/temporal/python-worker/activities.py +339 -0
  52. package/examples/temporal/python-worker/requirements.txt +12 -0
  53. package/examples/temporal/python-worker/worker.py +106 -0
  54. package/examples/temporal/worker.ts +66 -0
  55. package/examples/temporal/workflows.ts +6 -0
  56. package/examples/temporal/yaml-workflow-loader.ts +105 -0
  57. package/examples/yaml-test.ts +97 -0
  58. package/examples/yaml-workflows/01-simple-sequence.yaml +25 -0
  59. package/examples/yaml-workflows/02-parallel-timeout.yaml +45 -0
  60. package/examples/yaml-workflows/03-ecommerce-checkout.yaml +94 -0
  61. package/examples/yaml-workflows/04-ai-agent-workflow.yaml +346 -0
  62. package/examples/yaml-workflows/05-order-processing.yaml +146 -0
  63. package/examples/yaml-workflows/06-activity-test.yaml +71 -0
  64. package/examples/yaml-workflows/07-activity-simple-test.yaml +43 -0
  65. package/examples/yaml-workflows/08-file-processing.yaml +141 -0
  66. package/examples/yaml-workflows/09-http-request.yaml +137 -0
  67. package/examples/yaml-workflows/README.md +211 -0
  68. package/package.json +38 -0
  69. package/src/actions/code-execution.schema.ts +27 -0
  70. package/src/actions/code-execution.ts +218 -0
  71. package/src/actions/generate-file.test.ts +516 -0
  72. package/src/actions/generate-file.ts +166 -0
  73. package/src/actions/http-request.test.ts +784 -0
  74. package/src/actions/http-request.ts +228 -0
  75. package/src/actions/index.ts +20 -0
  76. package/src/actions/parse-file.test.ts +448 -0
  77. package/src/actions/parse-file.ts +139 -0
  78. package/src/actions/python-script.test.ts +439 -0
  79. package/src/actions/python-script.ts +154 -0
  80. package/src/base-node.test.ts +511 -0
  81. package/src/base-node.ts +605 -0
  82. package/src/behavior-tree.test.ts +431 -0
  83. package/src/behavior-tree.ts +283 -0
  84. package/src/blackboard.test.ts +222 -0
  85. package/src/blackboard.ts +192 -0
  86. package/src/composites/conditional.schema.ts +19 -0
  87. package/src/composites/conditional.test.ts +309 -0
  88. package/src/composites/conditional.ts +129 -0
  89. package/src/composites/for-each.schema.ts +23 -0
  90. package/src/composites/for-each.test.ts +254 -0
  91. package/src/composites/for-each.ts +132 -0
  92. package/src/composites/index.ts +15 -0
  93. package/src/composites/memory-sequence.schema.ts +19 -0
  94. package/src/composites/memory-sequence.test.ts +223 -0
  95. package/src/composites/memory-sequence.ts +98 -0
  96. package/src/composites/parallel.schema.ts +28 -0
  97. package/src/composites/parallel.test.ts +502 -0
  98. package/src/composites/parallel.ts +157 -0
  99. package/src/composites/reactive-sequence.schema.ts +19 -0
  100. package/src/composites/reactive-sequence.test.ts +170 -0
  101. package/src/composites/reactive-sequence.ts +85 -0
  102. package/src/composites/recovery.schema.ts +19 -0
  103. package/src/composites/recovery.test.ts +366 -0
  104. package/src/composites/recovery.ts +90 -0
  105. package/src/composites/selector.schema.ts +19 -0
  106. package/src/composites/selector.test.ts +387 -0
  107. package/src/composites/selector.ts +85 -0
  108. package/src/composites/sequence.schema.ts +19 -0
  109. package/src/composites/sequence.test.ts +337 -0
  110. package/src/composites/sequence.ts +72 -0
  111. package/src/composites/sub-tree.schema.ts +21 -0
  112. package/src/composites/sub-tree.test.ts +893 -0
  113. package/src/composites/sub-tree.ts +177 -0
  114. package/src/composites/while.schema.ts +24 -0
  115. package/src/composites/while.test.ts +381 -0
  116. package/src/composites/while.ts +149 -0
  117. package/src/data-store/index.ts +10 -0
  118. package/src/data-store/memory-store.ts +161 -0
  119. package/src/data-store/types.ts +94 -0
  120. package/src/debug/breakpoint.test.ts +47 -0
  121. package/src/debug/breakpoint.ts +30 -0
  122. package/src/debug/index.ts +17 -0
  123. package/src/debug/resume-point.test.ts +49 -0
  124. package/src/debug/resume-point.ts +29 -0
  125. package/src/decorators/delay.schema.ts +21 -0
  126. package/src/decorators/delay.test.ts +261 -0
  127. package/src/decorators/delay.ts +140 -0
  128. package/src/decorators/force-result.schema.ts +32 -0
  129. package/src/decorators/force-result.test.ts +133 -0
  130. package/src/decorators/force-result.ts +63 -0
  131. package/src/decorators/index.ts +13 -0
  132. package/src/decorators/invert.schema.ts +19 -0
  133. package/src/decorators/invert.test.ts +135 -0
  134. package/src/decorators/invert.ts +42 -0
  135. package/src/decorators/keep-running.schema.ts +20 -0
  136. package/src/decorators/keep-running.test.ts +105 -0
  137. package/src/decorators/keep-running.ts +49 -0
  138. package/src/decorators/precondition.schema.ts +19 -0
  139. package/src/decorators/precondition.test.ts +351 -0
  140. package/src/decorators/precondition.ts +139 -0
  141. package/src/decorators/repeat.schema.ts +21 -0
  142. package/src/decorators/repeat.test.ts +187 -0
  143. package/src/decorators/repeat.ts +94 -0
  144. package/src/decorators/run-once.schema.ts +19 -0
  145. package/src/decorators/run-once.test.ts +140 -0
  146. package/src/decorators/run-once.ts +61 -0
  147. package/src/decorators/soft-assert.schema.ts +19 -0
  148. package/src/decorators/soft-assert.test.ts +107 -0
  149. package/src/decorators/soft-assert.ts +68 -0
  150. package/src/decorators/timeout.schema.ts +21 -0
  151. package/src/decorators/timeout.test.ts +274 -0
  152. package/src/decorators/timeout.ts +159 -0
  153. package/src/errors.test.ts +63 -0
  154. package/src/errors.ts +34 -0
  155. package/src/events.test.ts +347 -0
  156. package/src/events.ts +183 -0
  157. package/src/index.ts +80 -0
  158. package/src/integrations/index.ts +30 -0
  159. package/src/integrations/integration-action.test.ts +571 -0
  160. package/src/integrations/integration-action.ts +233 -0
  161. package/src/integrations/piece-executor.ts +320 -0
  162. package/src/observability/execution-tracker.ts +320 -0
  163. package/src/observability/index.ts +23 -0
  164. package/src/observability/sinks.ts +138 -0
  165. package/src/observability/types.ts +130 -0
  166. package/src/registry-utils.ts +147 -0
  167. package/src/registry.test.ts +466 -0
  168. package/src/registry.ts +334 -0
  169. package/src/schemas/base.schema.ts +104 -0
  170. package/src/schemas/index.ts +223 -0
  171. package/src/schemas/integration.test.ts +238 -0
  172. package/src/schemas/tree-definition.schema.ts +170 -0
  173. package/src/schemas/validation.test.ts +146 -0
  174. package/src/schemas/validation.ts +122 -0
  175. package/src/scripting/index.ts +22 -0
  176. package/src/templates/template-loader.test.ts +281 -0
  177. package/src/templates/template-loader.ts +152 -0
  178. package/src/temporal-integration.test.ts +213 -0
  179. package/src/test-nodes.ts +259 -0
  180. package/src/types.ts +503 -0
  181. package/src/utilities/index.ts +17 -0
  182. package/src/utilities/log-message.test.ts +275 -0
  183. package/src/utilities/log-message.ts +134 -0
  184. package/src/utilities/regex-extract.test.ts +138 -0
  185. package/src/utilities/regex-extract.ts +108 -0
  186. package/src/utilities/variable-resolver.test.ts +416 -0
  187. package/src/utilities/variable-resolver.ts +318 -0
  188. package/src/utils/error-handler.test.ts +117 -0
  189. package/src/utils/error-handler.ts +48 -0
  190. package/src/utils/signal-check.test.ts +234 -0
  191. package/src/utils/signal-check.ts +140 -0
  192. package/src/yaml/errors.ts +143 -0
  193. package/src/yaml/index.ts +30 -0
  194. package/src/yaml/loader.ts +39 -0
  195. package/src/yaml/parser.ts +286 -0
  196. package/src/yaml/validation/semantic-validator.ts +196 -0
  197. package/templates/google-sheets/insert-row.yaml +76 -0
  198. package/templates/notification-sender.yaml +33 -0
  199. package/templates/order-validation.yaml +44 -0
  200. package/tsconfig.json +24 -0
  201. package/vitest.config.ts +25 -0
  202. package/workflows/order-processor.yaml +59 -0
  203. package/workflows/process-order-workflow.yaml +142 -0
@@ -0,0 +1,990 @@
1
+ # YAML Workflow Specification
2
+
3
+ This document provides a comprehensive reference for defining behavior tree workflows using YAML in btree.
4
+
5
+ ## Table of Contents
6
+
7
+ 1. [Overview](#overview)
8
+ 2. [Basic Structure](#basic-structure)
9
+ 3. [Node Types](#node-types)
10
+ 4. [Validation Pipeline](#validation-pipeline)
11
+ 5. [Composite Nodes](#composite-nodes)
12
+ 6. [Decorator Nodes](#decorator-nodes)
13
+ 7. [Action and Condition Nodes](#action-and-condition-nodes)
14
+ 8. [Error Handling](#error-handling)
15
+ 9. [Migration Guide](#migration-guide)
16
+
17
+ ## Overview
18
+
19
+ The YAML workflow format allows you to define behavior trees declaratively, with comprehensive validation ensuring correctness before execution. All workflows undergo a 4-stage validation pipeline:
20
+
21
+ 1. **YAML Syntax** - Validates YAML well-formedness
22
+ 2. **Tree Structure** - Ensures required fields and correct data types
23
+ 3. **Node Configuration** - Validates node-specific properties
24
+ 4. **Semantic Rules** - Checks ID uniqueness, child counts, and references
25
+
26
+ ## Basic Structure
27
+
28
+ Every workflow starts with a root node definition:
29
+
30
+ ```yaml
31
+ type: NodeType # Required: The node type (e.g., Sequence, Timeout)
32
+ id: unique-id # Optional: Unique identifier for this node
33
+ name: Display Name # Optional: Human-readable name
34
+ props: # Optional: Node-specific configuration
35
+ key: value
36
+ children: # Optional: Child nodes (for composites/decorators)
37
+ - type: ChildType
38
+ id: child-id
39
+ ```
40
+
41
+ ### Minimal Example
42
+
43
+ ```yaml
44
+ type: PrintAction
45
+ id: hello-world
46
+ props:
47
+ message: "Hello, World!"
48
+ ```
49
+
50
+ ### Complete Example
51
+
52
+ ```yaml
53
+ type: Sequence
54
+ id: user-onboarding
55
+ name: User Onboarding Flow
56
+
57
+ children:
58
+ - type: PrintAction
59
+ id: welcome-message
60
+ props:
61
+ message: "Welcome to our platform!"
62
+
63
+ - type: Timeout
64
+ id: profile-setup-timeout
65
+ props:
66
+ timeoutMs: 30000
67
+ children:
68
+ - type: Sequence
69
+ id: profile-setup
70
+ children:
71
+ - type: PrintAction
72
+ id: request-info
73
+ props:
74
+ message: "Please complete your profile..."
75
+
76
+ - type: Delay
77
+ id: wait-for-input
78
+ props:
79
+ delayMs: 1000
80
+ children:
81
+ - type: PrintAction
82
+ id: processing
83
+ props:
84
+ message: "Processing..."
85
+ ```
86
+
87
+ ## Node Types
88
+
89
+ ### Composites
90
+
91
+ Composites execute multiple children according to specific logic:
92
+
93
+ | Node Type | Children | Description |
94
+ |-----------|----------|-------------|
95
+ | `Sequence` | 1+ | Execute children in order until one fails |
96
+ | `Selector` | 1+ | Execute children in order until one succeeds |
97
+ | `Parallel` | 1+ | Execute all children concurrently |
98
+ | `ReactiveSequence` | 1+ | Like Sequence but re-ticks previous children |
99
+ | `MemorySequence` | 1+ | Like Sequence but remembers position |
100
+ | `ForEach` | 1+ | Iterate over collection, executing child for each item |
101
+ | `While` | 2 | Loop while condition succeeds, execute body |
102
+ | `Conditional` | 2-3 | If-then-else logic |
103
+ | `Recovery` | 1+ | Try children in order until one succeeds or all fail |
104
+ | `SubTree` | 0 | Reference another tree by ID |
105
+
106
+ ### Decorators
107
+
108
+ Decorators wrap a single child and modify its behavior:
109
+
110
+ | Node Type | Children | Description |
111
+ |-----------|----------|-------------|
112
+ | `Timeout` | 1 | Fail if child exceeds time limit |
113
+ | `Delay` | 1 | Wait before executing child |
114
+ | `Repeat` | 1 | Execute child N times |
115
+ | `Invert` | 1 | Flip success/failure |
116
+ | `ForceSuccess` | 1 | Always return success |
117
+ | `ForceFailure` | 1 | Always return failure |
118
+ | `RunOnce` | 1 | Execute child only once |
119
+ | `KeepRunningUntilFailure` | 1 | Keep returning RUNNING until child fails |
120
+ | `Precondition` | 1 | Check condition before executing child |
121
+ | `SoftAssert` | 1 | Like Precondition but less strict |
122
+
123
+ ### Actions and Conditions
124
+
125
+ Custom application-specific nodes defined in your registry.
126
+
127
+ ## Validation Pipeline
128
+
129
+ ### Stage 1: YAML Syntax Validation
130
+
131
+ Validates that the YAML is well-formed:
132
+
133
+ ```yaml
134
+ # Invalid: Missing colon
135
+ type Sequence
136
+
137
+ # Invalid: Incorrect indentation
138
+ type: Sequence
139
+ id: wrong-indent
140
+
141
+ # Valid
142
+ type: Sequence
143
+ id: correct
144
+ ```
145
+
146
+ **Errors:**
147
+ - `YamlSyntaxError` - Malformed YAML, incorrect indentation, invalid characters
148
+
149
+ ### Stage 2: Tree Structure Validation
150
+
151
+ Validates required fields and data types:
152
+
153
+ ```yaml
154
+ # Invalid: Missing type field
155
+ id: my-node
156
+ children: []
157
+
158
+ # Invalid: children must be an array
159
+ type: Sequence
160
+ children: "not-an-array"
161
+
162
+ # Valid
163
+ type: Sequence
164
+ id: my-sequence
165
+ children:
166
+ - type: PrintAction
167
+ id: action1
168
+ ```
169
+
170
+ **Errors:**
171
+ - `StructureValidationError` - Missing `type` field, incorrect data types, invalid structure
172
+
173
+ ### Stage 3: Node Configuration Validation
174
+
175
+ Validates node-specific properties using Zod schemas:
176
+
177
+ ```yaml
178
+ # Invalid: Negative timeout
179
+ type: Timeout
180
+ props:
181
+ timeoutMs: -100
182
+
183
+ # Invalid: Missing required property
184
+ type: ForEach
185
+ props:
186
+ itemKey: item
187
+ # Missing collectionKey
188
+
189
+ # Valid
190
+ type: Timeout
191
+ props:
192
+ timeoutMs: 5000
193
+ children:
194
+ - type: PrintAction
195
+ id: action
196
+ ```
197
+
198
+ **Errors:**
199
+ - `ConfigValidationError` - Invalid property values, missing required properties, type mismatches
200
+
201
+ ### Stage 4: Semantic Validation
202
+
203
+ Validates semantic rules and relationships:
204
+
205
+ ```yaml
206
+ # Invalid: Duplicate IDs
207
+ type: Sequence
208
+ children:
209
+ - type: PrintAction
210
+ id: duplicate
211
+ - type: PrintAction
212
+ id: duplicate # Error: ID already used
213
+
214
+ # Invalid: Decorator must have exactly 1 child
215
+ type: Timeout
216
+ props:
217
+ timeoutMs: 1000
218
+ children:
219
+ - type: PrintAction
220
+ id: action1
221
+ - type: PrintAction
222
+ id: action2 # Error: Timeout requires exactly 1 child
223
+
224
+ # Invalid: Circular SubTree reference
225
+ type: SubTree
226
+ props:
227
+ treeId: my-tree # Error: Cannot reference self or create cycle
228
+
229
+ # Valid
230
+ type: Sequence
231
+ children:
232
+ - type: PrintAction
233
+ id: unique-id-1
234
+ - type: PrintAction
235
+ id: unique-id-2
236
+ ```
237
+
238
+ **Errors:**
239
+ - `SemanticValidationError` - Duplicate IDs, wrong child count, circular references, unregistered node types
240
+
241
+ ## Composite Nodes
242
+
243
+ ### Sequence
244
+
245
+ Execute children in order until one fails or all succeed.
246
+
247
+ ```yaml
248
+ type: Sequence
249
+ id: checkout-flow
250
+ children:
251
+ - type: ValidateCart
252
+ id: validate
253
+ - type: ProcessPayment
254
+ id: payment
255
+ - type: SendConfirmation
256
+ id: confirmation
257
+ ```
258
+
259
+ **Configuration:** Base properties only
260
+
261
+ ### Selector
262
+
263
+ Execute children in order until one succeeds or all fail.
264
+
265
+ ```yaml
266
+ type: Selector
267
+ id: payment-methods
268
+ children:
269
+ - type: TryCreditCard
270
+ id: credit-card
271
+ - type: TryPayPal
272
+ id: paypal
273
+ - type: TryBankTransfer
274
+ id: bank
275
+ ```
276
+
277
+ **Configuration:** Base properties only
278
+
279
+ ### Parallel
280
+
281
+ Execute all children concurrently.
282
+
283
+ ```yaml
284
+ type: Parallel
285
+ id: parallel-tasks
286
+ props:
287
+ strategy: "strict" # "strict" | "any"
288
+ successThreshold: 2 # Optional: Number of successes needed
289
+ failureThreshold: 1 # Optional: Number of failures to abort
290
+ children:
291
+ - type: FetchUserData
292
+ id: fetch-user
293
+ - type: FetchProductData
294
+ id: fetch-product
295
+ - type: FetchInventory
296
+ id: fetch-inventory
297
+ ```
298
+
299
+ **Properties:**
300
+ - `strategy` (optional):
301
+ - `"strict"` - All children must succeed (default)
302
+ - `"any"` - At least one child must succeed
303
+ - `successThreshold` (optional): Number of children that must succeed
304
+ - `failureThreshold` (optional): Number of children that can fail before aborting
305
+
306
+ ### ForEach
307
+
308
+ Iterate over a collection, executing child for each item.
309
+
310
+ ```yaml
311
+ type: ForEach
312
+ id: process-orders
313
+ props:
314
+ collectionKey: "orders" # Required: Blackboard key with array
315
+ itemKey: "currentOrder" # Required: Blackboard key for current item
316
+ indexKey: "orderIndex" # Optional: Blackboard key for index
317
+ children:
318
+ - type: ProcessOrder
319
+ id: process-order
320
+ ```
321
+
322
+ **Properties:**
323
+ - `collectionKey` (required): Blackboard key containing the array to iterate
324
+ - `itemKey` (required): Blackboard key where current item is stored
325
+ - `indexKey` (optional): Blackboard key where current index is stored
326
+
327
+ ### While
328
+
329
+ Loop while condition succeeds, executing body.
330
+
331
+ ```yaml
332
+ type: While
333
+ id: retry-loop
334
+ props:
335
+ maxIterations: 1000 # Optional: Default 1000, prevents infinite loops
336
+ children:
337
+ - type: HasMoreItems # Condition (child 0)
338
+ id: has-more
339
+ - type: ProcessItem # Body (child 1)
340
+ id: process
341
+ ```
342
+
343
+ **Properties:**
344
+ - `maxIterations` (optional): Maximum loop iterations (default: 1000)
345
+
346
+ **Requirements:**
347
+ - Must have exactly 2 children
348
+ - First child is the condition
349
+ - Second child is the body
350
+
351
+ ### Conditional
352
+
353
+ If-then-else logic.
354
+
355
+ ```yaml
356
+ type: Conditional
357
+ id: user-check
358
+ children:
359
+ - type: IsUserLoggedIn # Condition (child 0)
360
+ id: check-login
361
+ - type: ShowDashboard # Then branch (child 1)
362
+ id: show-dashboard
363
+ - type: ShowLoginPage # Else branch (child 2, optional)
364
+ id: show-login
365
+ ```
366
+
367
+ **Configuration:** Base properties only
368
+
369
+ **Requirements:**
370
+ - Must have 2-3 children
371
+ - First child is the condition
372
+ - Second child is the "then" branch
373
+ - Third child (optional) is the "else" branch
374
+
375
+ ### ReactiveSequence
376
+
377
+ Like Sequence but re-ticks previous children on each tick.
378
+
379
+ ```yaml
380
+ type: ReactiveSequence
381
+ id: reactive-flow
382
+ children:
383
+ - type: CheckSensor
384
+ id: sensor-check
385
+ - type: ProcessData
386
+ id: process
387
+ ```
388
+
389
+ **Configuration:** Base properties only
390
+
391
+ ### MemorySequence
392
+
393
+ Like Sequence but remembers last executing child.
394
+
395
+ ```yaml
396
+ type: MemorySequence
397
+ id: memory-flow
398
+ children:
399
+ - type: Step1
400
+ id: step-1
401
+ - type: Step2
402
+ id: step-2
403
+ - type: Step3
404
+ id: step-3
405
+ ```
406
+
407
+ **Configuration:** Base properties only
408
+
409
+ ### Recovery
410
+
411
+ Try children in order until one succeeds or all fail (like Selector but for error recovery).
412
+
413
+ ```yaml
414
+ type: Recovery
415
+ id: error-recovery
416
+ children:
417
+ - type: TryPrimaryService
418
+ id: primary
419
+ - type: TryBackupService
420
+ id: backup
421
+ - type: UseCache
422
+ id: cache
423
+ ```
424
+
425
+ **Configuration:** Base properties only
426
+
427
+ ### SubTree
428
+
429
+ Reference another tree by ID.
430
+
431
+ ```yaml
432
+ type: SubTree
433
+ id: reusable-subtree
434
+ props:
435
+ treeId: "common-validation" # Required: ID of tree to reference
436
+ ```
437
+
438
+ **Properties:**
439
+ - `treeId` (required): ID of the tree to execute
440
+
441
+ **Note:** Circular references are detected and prevented.
442
+
443
+ ## Decorator Nodes
444
+
445
+ All decorators must have exactly 1 child.
446
+
447
+ ### Timeout
448
+
449
+ Fail if child exceeds time limit.
450
+
451
+ ```yaml
452
+ type: Timeout
453
+ id: api-timeout
454
+ props:
455
+ timeoutMs: 5000 # Required: Timeout in milliseconds (> 0)
456
+ children:
457
+ - type: CallExternalAPI
458
+ id: api-call
459
+ ```
460
+
461
+ **Properties:**
462
+ - `timeoutMs` (required): Timeout duration in milliseconds (must be > 0)
463
+
464
+ ### Delay
465
+
466
+ Wait before executing child.
467
+
468
+ ```yaml
469
+ type: Delay
470
+ id: wait-before-retry
471
+ props:
472
+ delayMs: 1000 # Required: Delay in milliseconds (>= 0)
473
+ children:
474
+ - type: RetryOperation
475
+ id: retry
476
+ ```
477
+
478
+ **Properties:**
479
+ - `delayMs` (required): Delay duration in milliseconds (must be >= 0)
480
+
481
+ ### Repeat
482
+
483
+ Execute child N times.
484
+
485
+ ```yaml
486
+ type: Repeat
487
+ id: retry-three-times
488
+ props:
489
+ numCycles: 3 # Required: Number of times to repeat (> 0, integer)
490
+ children:
491
+ - type: AttemptConnection
492
+ id: connect
493
+ ```
494
+
495
+ **Properties:**
496
+ - `numCycles` (required): Number of repetitions (must be > 0 and an integer)
497
+
498
+ ### Invert
499
+
500
+ Flip success/failure status of child.
501
+
502
+ ```yaml
503
+ type: Invert
504
+ id: invert-result
505
+ children:
506
+ - type: CheckCondition
507
+ id: condition
508
+ ```
509
+
510
+ **Configuration:** Base properties only
511
+
512
+ ### ForceSuccess
513
+
514
+ Always return success regardless of child result.
515
+
516
+ ```yaml
517
+ type: ForceSuccess
518
+ id: optional-step
519
+ children:
520
+ - type: OptionalOperation
521
+ id: operation
522
+ ```
523
+
524
+ **Configuration:** Base properties only
525
+
526
+ ### ForceFailure
527
+
528
+ Always return failure regardless of child result.
529
+
530
+ ```yaml
531
+ type: ForceFailure
532
+ id: force-fail
533
+ children:
534
+ - type: SomeOperation
535
+ id: operation
536
+ ```
537
+
538
+ **Configuration:** Base properties only
539
+
540
+ ### RunOnce
541
+
542
+ Execute child only once, then always return success.
543
+
544
+ ```yaml
545
+ type: RunOnce
546
+ id: initialize-once
547
+ children:
548
+ - type: InitializeSystem
549
+ id: init
550
+ ```
551
+
552
+ **Configuration:** Base properties only
553
+
554
+ ### KeepRunningUntilFailure
555
+
556
+ Keep returning RUNNING until child fails.
557
+
558
+ ```yaml
559
+ type: KeepRunningUntilFailure
560
+ id: keep-running
561
+ children:
562
+ - type: MonitorProcess
563
+ id: monitor
564
+ ```
565
+
566
+ **Configuration:** Base properties only
567
+
568
+ ### Precondition
569
+
570
+ Check condition before executing child. Fail if condition fails.
571
+
572
+ ```yaml
573
+ type: Precondition
574
+ id: check-prerequisites
575
+ children:
576
+ - type: CheckUserPermissions
577
+ id: check-perms
578
+ ```
579
+
580
+ **Configuration:** Base properties only
581
+
582
+ ### SoftAssert
583
+
584
+ Like Precondition but less strict.
585
+
586
+ ```yaml
587
+ type: SoftAssert
588
+ id: soft-check
589
+ children:
590
+ - type: OptionalCheck
591
+ id: check
592
+ ```
593
+
594
+ **Configuration:** Base properties only
595
+
596
+ ## Action and Condition Nodes
597
+
598
+ Action and condition nodes are application-specific and must be registered in your Registry before loading YAML workflows.
599
+
600
+ ```yaml
601
+ # Custom action node
602
+ type: SendEmail
603
+ id: send-notification
604
+ props:
605
+ recipient: "user@example.com"
606
+ subject: "Welcome!"
607
+ template: "welcome-email"
608
+
609
+ # Custom condition node
610
+ type: IsUserPremium
611
+ id: check-premium
612
+ props:
613
+ userId: "{{userId}}"
614
+ ```
615
+
616
+ **Requirements:**
617
+ - Node type must be registered in Registry
618
+ - Properties validated against node's schema (if defined)
619
+ - Can use blackboard variable interpolation (e.g., `"{{variableName}}"`)
620
+
621
+ ## Error Handling
622
+
623
+ ### Error Types
624
+
625
+ | Error Type | Stage | Description |
626
+ |------------|-------|-------------|
627
+ | `YamlSyntaxError` | 1 | YAML parsing failed |
628
+ | `StructureValidationError` | 2 | Invalid tree structure |
629
+ | `ConfigValidationError` | 3 | Invalid node configuration |
630
+ | `SemanticValidationError` | 4 | Semantic rule violation |
631
+
632
+ ### Error Format
633
+
634
+ All validation errors include:
635
+ - **Message**: Description of the error
636
+ - **Path**: Location in the tree (e.g., `root.children[2].props.timeoutMs`)
637
+ - **Suggestion**: How to fix the error
638
+
639
+ Example error:
640
+
641
+ ```
642
+ SemanticValidationError: Duplicate node ID 'process-payment'
643
+ Path: root.children[3].id
644
+ Previous occurrence: root.children[1].id
645
+ Suggestion: Use unique IDs for each node in the tree
646
+ ```
647
+
648
+ ### Common Errors
649
+
650
+ #### Duplicate IDs
651
+
652
+ ```yaml
653
+ # Error: Duplicate IDs
654
+ type: Sequence
655
+ children:
656
+ - type: PrintAction
657
+ id: my-action
658
+ - type: PrintAction
659
+ id: my-action # Error!
660
+ ```
661
+
662
+ **Fix:** Use unique IDs for each node.
663
+
664
+ #### Wrong Child Count
665
+
666
+ ```yaml
667
+ # Error: Decorator with multiple children
668
+ type: Timeout
669
+ props:
670
+ timeoutMs: 1000
671
+ children:
672
+ - type: Action1
673
+ id: a1
674
+ - type: Action2
675
+ id: a2 # Error: Timeout requires exactly 1 child
676
+ ```
677
+
678
+ **Fix:** Decorators must have exactly 1 child. Wrap multiple children in a Sequence.
679
+
680
+ ```yaml
681
+ # Fixed
682
+ type: Timeout
683
+ props:
684
+ timeoutMs: 1000
685
+ children:
686
+ - type: Sequence
687
+ id: actions
688
+ children:
689
+ - type: Action1
690
+ id: a1
691
+ - type: Action2
692
+ id: a2
693
+ ```
694
+
695
+ #### Invalid Property Values
696
+
697
+ ```yaml
698
+ # Error: Negative timeout
699
+ type: Timeout
700
+ props:
701
+ timeoutMs: -100 # Error: Must be > 0
702
+ ```
703
+
704
+ **Fix:** Use valid values per node schema.
705
+
706
+ ```yaml
707
+ # Fixed
708
+ type: Timeout
709
+ props:
710
+ timeoutMs: 5000
711
+ ```
712
+
713
+ #### Missing Required Properties
714
+
715
+ ```yaml
716
+ # Error: Missing required property
717
+ type: ForEach
718
+ props:
719
+ itemKey: "item"
720
+ # Missing collectionKey!
721
+ ```
722
+
723
+ **Fix:** Include all required properties.
724
+
725
+ ```yaml
726
+ # Fixed
727
+ type: ForEach
728
+ props:
729
+ collectionKey: "items"
730
+ itemKey: "item"
731
+ ```
732
+
733
+ ## Migration Guide
734
+
735
+ ### From Programmatic API to YAML
736
+
737
+ **Before (TypeScript):**
738
+
739
+ ```typescript
740
+ const tree = new Sequence({ id: "checkout" }, [
741
+ new Timeout({ id: "payment-timeout", timeoutMs: 30000 }, [
742
+ new ProcessPayment({ id: "payment" })
743
+ ]),
744
+ new SendConfirmation({ id: "confirmation" })
745
+ ]);
746
+ ```
747
+
748
+ **After (YAML):**
749
+
750
+ ```yaml
751
+ type: Sequence
752
+ id: checkout
753
+ children:
754
+ - type: Timeout
755
+ id: payment-timeout
756
+ props:
757
+ timeoutMs: 30000
758
+ children:
759
+ - type: ProcessPayment
760
+ id: payment
761
+
762
+ - type: SendConfirmation
763
+ id: confirmation
764
+ ```
765
+
766
+ ### Loading YAML Workflows
767
+
768
+ ```typescript
769
+ import {
770
+ Registry,
771
+ registerStandardNodes,
772
+ loadTreeFromYaml,
773
+ loadTreeFromFile
774
+ } from '@wayfarer-ai/btree';
775
+
776
+ // Setup registry with all 32 built-in nodes
777
+ const registry = new Registry();
778
+ registerStandardNodes(registry); // One line instead of 32!
779
+
780
+ // Register your custom nodes
781
+ registry.register('ProcessPayment', ProcessPayment, { category: 'action' });
782
+ registry.register('SendConfirmation', SendConfirmation, { category: 'action' });
783
+
784
+ // Load from string
785
+ const yamlString = `
786
+ type: Sequence
787
+ id: checkout
788
+ children:
789
+ - type: ProcessPayment
790
+ id: payment
791
+ `;
792
+
793
+ const tree = loadTreeFromYaml(yamlString, registry);
794
+
795
+ // Load from file
796
+ const tree = await loadTreeFromFile('./workflows/checkout.yaml', registry);
797
+
798
+ // Execute
799
+ const result = await tree.execute();
800
+ ```
801
+
802
+ **Built-in nodes** automatically registered by `registerStandardNodes()`:
803
+ - **10 Composites**: Sequence, Selector, Parallel, ForEach, While, Conditional, ReactiveSequence, MemorySequence, Recovery, SubTree
804
+ - **10 Decorators**: Timeout, Delay, Repeat, Invert, ForceSuccess, ForceFailure, RunOnce, KeepRunningUntilFailure, Precondition, SoftAssert
805
+ - **9 Actions/Conditions**: PrintAction, MockAction, CounterAction, CheckCondition, AlwaysCondition, WaitAction, Script, LogMessage, RegexExtract
806
+ - **3 Test Nodes**: SuccessNode, FailureNode, RunningNode
807
+
808
+ ### Validation Without Execution
809
+
810
+ ```typescript
811
+ import { validateYaml } from 'btree';
812
+
813
+ const result = validateYaml(yamlString, registry);
814
+
815
+ if (!result.valid) {
816
+ console.error('Validation errors:');
817
+ result.errors.forEach(error => {
818
+ console.error(error.format());
819
+ });
820
+ } else {
821
+ console.log('Workflow is valid!');
822
+ }
823
+ ```
824
+
825
+ ### Loading Options
826
+
827
+ ```typescript
828
+ import { loadTreeFromYaml } from 'btree';
829
+
830
+ const tree = loadTreeFromYaml(yamlString, registry, {
831
+ validate: true, // Enable validation (default: true)
832
+ failFast: false, // Collect all errors (default: true)
833
+ autoGenerateIds: true // Auto-generate missing IDs (default: true)
834
+ });
835
+ ```
836
+
837
+ ### Validation Options
838
+
839
+ ```typescript
840
+ import { validateYaml } from 'btree';
841
+
842
+ const result = validateYaml(yamlString, registry, {
843
+ collectAllErrors: true, // Collect all errors (default: false)
844
+ checkReferences: true // Check semantic rules (default: true)
845
+ });
846
+ ```
847
+
848
+ ## Best Practices
849
+
850
+ ### 1. Always Provide IDs
851
+
852
+ While IDs can be auto-generated, explicit IDs make debugging easier:
853
+
854
+ ```yaml
855
+ # Good
856
+ type: Sequence
857
+ id: user-registration
858
+ children:
859
+ - type: ValidateEmail
860
+ id: validate-email
861
+ - type: CreateAccount
862
+ id: create-account
863
+
864
+ # Avoid (auto-generated IDs are hard to track)
865
+ type: Sequence
866
+ children:
867
+ - type: ValidateEmail
868
+ - type: CreateAccount
869
+ ```
870
+
871
+ ### 2. Use Descriptive Names
872
+
873
+ Add names for better readability:
874
+
875
+ ```yaml
876
+ type: Sequence
877
+ id: checkout-flow
878
+ name: E-commerce Checkout Flow
879
+ children:
880
+ - type: ValidateCart
881
+ id: validate-cart
882
+ name: Validate Shopping Cart
883
+
884
+ - type: ProcessPayment
885
+ id: process-payment
886
+ name: Process Customer Payment
887
+ ```
888
+
889
+ ### 3. Validate Before Deployment
890
+
891
+ Always validate workflows before deploying to production:
892
+
893
+ ```typescript
894
+ const result = validateYaml(workflowYaml, registry);
895
+ if (!result.valid) {
896
+ throw new Error('Invalid workflow');
897
+ }
898
+ ```
899
+
900
+ ### 4. Use SubTrees for Reusability
901
+
902
+ Extract common patterns into reusable subtrees:
903
+
904
+ ```yaml
905
+ # common-validation.yaml
906
+ type: Sequence
907
+ id: common-validation
908
+ children:
909
+ - type: CheckAuth
910
+ id: check-auth
911
+ - type: ValidateInput
912
+ id: validate-input
913
+
914
+ # main-workflow.yaml
915
+ type: Sequence
916
+ id: api-endpoint
917
+ children:
918
+ - type: SubTree
919
+ id: validation
920
+ props:
921
+ treeId: "common-validation"
922
+
923
+ - type: ProcessRequest
924
+ id: process
925
+ ```
926
+
927
+ ### 5. Handle Timeouts Explicitly
928
+
929
+ Always set realistic timeouts for external operations:
930
+
931
+ ```yaml
932
+ type: Timeout
933
+ id: api-timeout
934
+ props:
935
+ timeoutMs: 5000 # 5 seconds for API call
936
+ children:
937
+ - type: CallExternalAPI
938
+ id: api-call
939
+ ```
940
+
941
+ ### 6. Use Recovery for Fallbacks
942
+
943
+ Implement graceful degradation with Recovery nodes:
944
+
945
+ ```yaml
946
+ type: Recovery
947
+ id: data-source
948
+ children:
949
+ - type: FetchFromDatabase
950
+ id: db-fetch
951
+
952
+ - type: FetchFromCache
953
+ id: cache-fetch
954
+
955
+ - type: UseDefaultData
956
+ id: default-data
957
+ ```
958
+
959
+ ## Examples
960
+
961
+ See the `examples/yaml-workflows/` directory for complete examples:
962
+
963
+ **Working Examples** (tested with Temporal):
964
+ - `01-simple-sequence.yaml` - Basic sequential workflow with 3 print actions
965
+ - `02-parallel-timeout.yaml` - Parallel task execution with timeout protection
966
+ - `05-order-processing.yaml` - Complex e-commerce order processing (20+ nodes, 5 levels deep)
967
+
968
+ **Reference Examples** (showcase advanced patterns):
969
+ - `03-ecommerce-checkout.yaml` - Multi-phase checkout with conditional logic
970
+ - `04-ai-agent-workflow.yaml` - AI agent with decision trees and iterative processing
971
+
972
+ To run the working examples:
973
+ ```bash
974
+ # Terminal 1: Start Temporal server
975
+ temporal server start-dev
976
+
977
+ # Terminal 2: Start worker
978
+ cd examples/temporal
979
+ npx tsx worker.ts
980
+
981
+ # Terminal 3: Execute workflows
982
+ npx tsx client.ts
983
+ ```
984
+
985
+ ## Further Reading
986
+
987
+ - [Core Concepts](./workflow-engine/01-core-concepts.md) - Behavior tree fundamentals
988
+ - [Node Reference](./workflow-engine/02-node-reference.md) - Complete node documentation
989
+ - [Schema Documentation](../src/schemas/README.md) - Zod schema reference
990
+ - [Registry Guide](./workflow-engine/03-registry.md) - Node registration and tree creation