xcomponent-ai 0.4.2 → 0.5.0

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 (109) hide show
  1. package/CONTRIBUTING.md +5 -5
  2. package/EVENT-ACCUMULATION-GUIDE.md +93 -75
  3. package/EXTERNAL-API.md +1 -1
  4. package/LLM-GUIDE.md +129 -103
  5. package/QUICKSTART.md +18 -1
  6. package/README.md +154 -79
  7. package/SCALABILITY.md +1 -1
  8. package/dist/agents.js +3 -3
  9. package/dist/agents.js.map +1 -1
  10. package/dist/api.d.ts.map +1 -1
  11. package/dist/api.js +81 -1
  12. package/dist/api.js.map +1 -1
  13. package/dist/cli.js +56 -13
  14. package/dist/cli.js.map +1 -1
  15. package/dist/component-registry.d.ts.map +1 -1
  16. package/dist/component-registry.js +0 -1
  17. package/dist/component-registry.js.map +1 -1
  18. package/dist/dashboard-server.d.ts +75 -0
  19. package/dist/dashboard-server.d.ts.map +1 -0
  20. package/dist/dashboard-server.js +793 -0
  21. package/dist/dashboard-server.js.map +1 -0
  22. package/dist/external-broker-api.d.ts +90 -4
  23. package/dist/external-broker-api.d.ts.map +1 -1
  24. package/dist/external-broker-api.js +90 -4
  25. package/dist/external-broker-api.js.map +1 -1
  26. package/dist/fsm-runtime.d.ts +44 -2
  27. package/dist/fsm-runtime.d.ts.map +1 -1
  28. package/dist/fsm-runtime.js +354 -44
  29. package/dist/fsm-runtime.js.map +1 -1
  30. package/dist/index.d.ts +5 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +19 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/mermaid-generator.d.ts +9 -0
  35. package/dist/mermaid-generator.d.ts.map +1 -1
  36. package/dist/mermaid-generator.js +72 -29
  37. package/dist/mermaid-generator.js.map +1 -1
  38. package/dist/message-broker.d.ts +63 -6
  39. package/dist/message-broker.d.ts.map +1 -1
  40. package/dist/message-broker.js +257 -28
  41. package/dist/message-broker.js.map +1 -1
  42. package/dist/monitoring.js +1 -1
  43. package/dist/monitoring.js.map +1 -1
  44. package/dist/persistence.d.ts +1 -1
  45. package/dist/persistence.d.ts.map +1 -1
  46. package/dist/persistence.js +4 -2
  47. package/dist/persistence.js.map +1 -1
  48. package/dist/postgres-persistence.d.ts +114 -0
  49. package/dist/postgres-persistence.d.ts.map +1 -0
  50. package/dist/postgres-persistence.js +438 -0
  51. package/dist/postgres-persistence.js.map +1 -0
  52. package/dist/redis-persistence.d.ts +87 -0
  53. package/dist/redis-persistence.d.ts.map +1 -0
  54. package/dist/redis-persistence.js +279 -0
  55. package/dist/redis-persistence.js.map +1 -0
  56. package/dist/runtime-broadcaster.d.ts +67 -0
  57. package/dist/runtime-broadcaster.d.ts.map +1 -0
  58. package/dist/runtime-broadcaster.js +427 -0
  59. package/dist/runtime-broadcaster.js.map +1 -0
  60. package/dist/swagger-spec.js +1 -1
  61. package/dist/swagger-spec.js.map +1 -1
  62. package/dist/types.d.ts +106 -13
  63. package/dist/types.d.ts.map +1 -1
  64. package/dist/types.js +3 -1
  65. package/dist/types.js.map +1 -1
  66. package/dist/websockets.d.ts +9 -0
  67. package/dist/websockets.d.ts.map +1 -1
  68. package/dist/websockets.js +22 -3
  69. package/dist/websockets.js.map +1 -1
  70. package/examples/advanced-patterns-demo.yaml +2 -132
  71. package/examples/complete-workflow-all-features.yaml +0 -9
  72. package/examples/cross-component-demo.yaml +3 -0
  73. package/examples/distributed/Dockerfile.dashboard +27 -0
  74. package/examples/distributed/Dockerfile.runtime +28 -0
  75. package/examples/distributed/README.md +349 -0
  76. package/examples/distributed/docker-compose.yml +103 -0
  77. package/examples/distributed/e2e-test.js +468 -0
  78. package/examples/distributed/init-db.sql +104 -0
  79. package/examples/distributed/order-component.yaml +97 -0
  80. package/examples/distributed/payment-component.yaml +96 -0
  81. package/examples/distributed/runtime.js +182 -0
  82. package/examples/distributed-redis/Dockerfile.dashboard +27 -0
  83. package/examples/distributed-redis/Dockerfile.runtime +28 -0
  84. package/examples/distributed-redis/docker-compose.yml +97 -0
  85. package/examples/distributed-redis/e2e-test.js +448 -0
  86. package/examples/distributed-redis/init-db.sql +104 -0
  87. package/examples/distributed-redis/order-component.yaml +97 -0
  88. package/examples/distributed-redis/payment-component.yaml +96 -0
  89. package/examples/distributed-redis/runtime.js +182 -0
  90. package/examples/event-accumulation-demo.yaml +2 -54
  91. package/examples/explicit-transitions-demo.yaml +2 -93
  92. package/examples/full-project-structure.md +0 -14
  93. package/examples/kyc.yaml +0 -16
  94. package/examples/monolith-postgres/Dockerfile +28 -0
  95. package/examples/monolith-postgres/docker-compose.yml +42 -0
  96. package/examples/monolith-postgres/e2e-test.js +428 -0
  97. package/examples/monolith-postgres/runtime.js +200 -0
  98. package/examples/order-processing-xcomponent.yaml +0 -13
  99. package/examples/payment.yaml +0 -20
  100. package/examples/simple-xcomponent-demo.yaml +94 -0
  101. package/examples/trading-complete.yaml +0 -8
  102. package/examples/trading-with-schema.yaml +0 -6
  103. package/examples/trading.yaml +0 -8
  104. package/package.json +14 -4
  105. package/public/dashboard-old.html +1299 -0
  106. package/public/dashboard.html +3115 -1152
  107. package/examples/distributed-demo/README.md +0 -234
  108. package/examples/distributed-demo/order.yaml +0 -71
  109. package/examples/distributed-demo/payment.yaml +0 -60
package/CONTRIBUTING.md CHANGED
@@ -10,7 +10,7 @@ By participating in this project, you agree to maintain a respectful and inclusi
10
10
 
11
11
  ### Reporting Bugs
12
12
 
13
- 1. Check if the bug has already been reported in [Issues](https://github.com/fredericcarre/mayele-ai/issues)
13
+ 1. Check if the bug has already been reported in [Issues](https://github.com/fredericcarre/xcomponent-ai/issues)
14
14
  2. If not, create a new issue with:
15
15
  - Clear, descriptive title
16
16
  - Steps to reproduce
@@ -20,7 +20,7 @@ By participating in this project, you agree to maintain a respectful and inclusi
20
20
 
21
21
  ### Suggesting Features
22
22
 
23
- 1. Check existing [Discussions](https://github.com/fredericcarre/mayele-ai/discussions) and Issues
23
+ 1. Check existing [Discussions](https://github.com/fredericcarre/xcomponent-ai/discussions) and Issues
24
24
  2. Create a new discussion with:
25
25
  - Use case description
26
26
  - Proposed solution
@@ -31,8 +31,8 @@ By participating in this project, you agree to maintain a respectful and inclusi
31
31
 
32
32
  1. **Fork and Clone**
33
33
  ```bash
34
- git clone https://github.com/YOUR_USERNAME/mayele-ai.git
35
- cd mayele-ai
34
+ git clone https://github.com/YOUR_USERNAME/xcomponent-ai.git
35
+ cd xcomponent-ai
36
36
  npm install
37
37
  ```
38
38
 
@@ -186,7 +186,7 @@ npm run cli -- load examples/trading.yaml
186
186
 
187
187
  ## Questions?
188
188
 
189
- - Open a [Discussion](https://github.com/fredericcarre/mayele-ai/discussions)
189
+ - Open a [Discussion](https://github.com/fredericcarre/xcomponent-ai/discussions)
190
190
  - Join our community chat (coming soon)
191
191
  - Email: contributors@xcomponent.com
192
192
 
@@ -53,46 +53,59 @@ stateMachines:
53
53
 
54
54
  ### Step 2: Create Accumulation Method with Explicit Control
55
55
 
56
+ **YAML** -- declare the method name on the transition:
57
+
56
58
  ```yaml
57
- triggeredMethods:
58
- accumulateExecution: |
59
- async function(event, context, sender) {
60
- // Initialize counters
61
- if (!context.executedQuantity) {
62
- context.executedQuantity = 0;
63
- }
64
- if (!context.executions) {
65
- context.executions = [];
66
- }
67
-
68
- // Accumulate quantity from event
69
- const qty = event.payload.quantity || 0;
70
- context.executedQuantity += qty;
71
-
72
- // Track individual executions
73
- context.executions.push({
74
- quantity: qty,
75
- price: event.payload.price,
76
- executionId: event.payload.executionId,
77
- timestamp: event.timestamp
78
- });
59
+ transitions:
60
+ - from: PartiallyExecuted
61
+ to: PartiallyExecuted
62
+ event: EXECUTION_NOTIFICATION
63
+ type: triggerable
64
+ triggeredMethod: accumulateExecution
65
+ ```
79
66
 
80
- console.log(`Executed: ${context.executedQuantity}/${context.totalQuantity}`);
81
-
82
- // EXPLICIT CONTROL: Decide when to transition
83
- if (context.executedQuantity >= context.totalQuantity) {
84
- // Send event to self to trigger completion
85
- await sender.sendToSelf({
86
- type: 'FULLY_EXECUTED',
87
- payload: {
88
- totalExecuted: context.executedQuantity,
89
- executionCount: context.executions.length,
90
- averagePrice: context.executions.reduce((sum, e) => sum + e.price, 0) / context.executions.length
91
- },
92
- timestamp: Date.now()
93
- });
94
- }
67
+ **TypeScript** -- implement the handler:
68
+
69
+ ```typescript
70
+ runtime.on('triggered_method', async ({ method, event, context, sender }) => {
71
+ if (method === 'accumulateExecution') {
72
+ // Initialize counters
73
+ if (!context.executedQuantity) {
74
+ context.executedQuantity = 0;
75
+ }
76
+ if (!context.executions) {
77
+ context.executions = [];
95
78
  }
79
+
80
+ // Accumulate quantity from event
81
+ const qty = event.payload.quantity || 0;
82
+ context.executedQuantity += qty;
83
+
84
+ // Track individual executions
85
+ context.executions.push({
86
+ quantity: qty,
87
+ price: event.payload.price,
88
+ executionId: event.payload.executionId,
89
+ timestamp: event.timestamp
90
+ });
91
+
92
+ console.log(`Executed: ${context.executedQuantity}/${context.totalQuantity}`);
93
+
94
+ // EXPLICIT CONTROL: Decide when to transition
95
+ if (context.executedQuantity >= context.totalQuantity) {
96
+ // Send event to self to trigger completion
97
+ await sender.sendToSelf({
98
+ type: 'FULLY_EXECUTED',
99
+ payload: {
100
+ totalExecuted: context.executedQuantity,
101
+ executionCount: context.executions.length,
102
+ averagePrice: context.executions.reduce((sum, e) => sum + e.price, 0) / context.executions.length
103
+ },
104
+ timestamp: Date.now()
105
+ });
106
+ }
107
+ }
108
+ });
96
109
  ```
97
110
 
98
111
  **Key Points:**
@@ -146,48 +159,12 @@ transitions:
146
159
 
147
160
  ## 📝 Complete Example
148
161
 
162
+ **YAML** (`trading.yaml`):
163
+
149
164
  ```yaml
150
165
  name: TradingComponent
151
166
  version: 1.0.0
152
167
 
153
- triggeredMethods:
154
- accumulateExecution: |
155
- async function(event, context, sender) {
156
- if (!context.executedQuantity) context.executedQuantity = 0;
157
- if (!context.executions) context.executions = [];
158
-
159
- const qty = event.payload.quantity || 0;
160
- context.executedQuantity += qty;
161
- context.executions.push({
162
- quantity: qty,
163
- price: event.payload.price,
164
- executionId: event.payload.executionId,
165
- timestamp: event.timestamp
166
- });
167
-
168
- console.log(`Executed: ${context.executedQuantity}/${context.totalQuantity}`);
169
-
170
- // EXPLICIT CONTROL
171
- if (context.executedQuantity >= context.totalQuantity) {
172
- await sender.sendToSelf({
173
- type: 'FULLY_EXECUTED',
174
- payload: {
175
- totalExecuted: context.executedQuantity,
176
- executionCount: context.executions.length
177
- },
178
- timestamp: Date.now()
179
- });
180
- }
181
- }
182
-
183
- handleCompletion: |
184
- async function(event, context, sender) {
185
- console.log(`Order completed!`);
186
- console.log(` Total: ${event.payload.totalExecuted}`);
187
- console.log(` Executions: ${event.payload.executionCount}`);
188
- context.stats = event.payload;
189
- }
190
-
191
168
  stateMachines:
192
169
  - name: TradingOrder
193
170
  initialState: Created
@@ -242,6 +219,47 @@ stateMachines:
242
219
  type: triggerable
243
220
  ```
244
221
 
222
+ **TypeScript** -- implement the handlers:
223
+
224
+ ```typescript
225
+ runtime.on('triggered_method', async ({ method, event, context, sender }) => {
226
+ if (method === 'accumulateExecution') {
227
+ if (!context.executedQuantity) context.executedQuantity = 0;
228
+ if (!context.executions) context.executions = [];
229
+
230
+ const qty = event.payload.quantity || 0;
231
+ context.executedQuantity += qty;
232
+ context.executions.push({
233
+ quantity: qty,
234
+ price: event.payload.price,
235
+ executionId: event.payload.executionId,
236
+ timestamp: event.timestamp
237
+ });
238
+
239
+ console.log(`Executed: ${context.executedQuantity}/${context.totalQuantity}`);
240
+
241
+ // EXPLICIT CONTROL
242
+ if (context.executedQuantity >= context.totalQuantity) {
243
+ await sender.sendToSelf({
244
+ type: 'FULLY_EXECUTED',
245
+ payload: {
246
+ totalExecuted: context.executedQuantity,
247
+ executionCount: context.executions.length
248
+ },
249
+ timestamp: Date.now()
250
+ });
251
+ }
252
+ }
253
+
254
+ if (method === 'handleCompletion') {
255
+ console.log(`Order completed!`);
256
+ console.log(` Total: ${event.payload.totalExecuted}`);
257
+ console.log(` Executions: ${event.payload.executionCount}`);
258
+ context.stats = event.payload;
259
+ }
260
+ });
261
+ ```
262
+
245
263
  ---
246
264
 
247
265
  ## 🧪 Testing
package/EXTERNAL-API.md CHANGED
@@ -714,6 +714,6 @@ public void onOrderValidated(String orderId) {
714
714
 
715
715
  - See [SCALABILITY.md](./SCALABILITY.md) for production deployment
716
716
  - See [LLM-GUIDE.md](./LLM-GUIDE.md) for YAML FSM design patterns
717
- - See `examples/distributed-demo/` for working examples
717
+ - See `examples/distributed/` (RabbitMQ) or `examples/distributed-redis/` (Redis) for working examples
718
718
 
719
719
  **Built for interoperability.** Any language, any platform. 🌍
package/LLM-GUIDE.md CHANGED
@@ -50,8 +50,6 @@ stateMachines:
50
50
  to: Validated
51
51
  event: VALIDATE
52
52
  type: triggerable
53
- guards:
54
- - keys: [orderId, amount]
55
53
  - from: Validated
56
54
  to: Executed
57
55
  event: EXECUTE
@@ -197,7 +195,7 @@ GET /api/components/:componentName/diagrams/:machineName
197
195
 
198
196
  Returns Mermaid `stateDiagram-v2` syntax with:
199
197
  - State styling (entry/orange, final/green, error/red)
200
- - Transitions with guards
198
+ - Transitions with event labels
201
199
  - State descriptions as notes
202
200
 
203
201
  ### 6. Distributed Mode (Multi-Process)
@@ -233,97 +231,153 @@ states:
233
231
 
234
232
  When Order transitions to "Validated" in Process 1, Redis automatically delivers the PROCESS event to PaymentComponent in Process 2.
235
233
 
236
- See: `examples/distributed-demo/` for complete working example.
234
+ See: `examples/distributed/` (RabbitMQ) or `examples/distributed-redis/` (Redis) for complete working examples.
237
235
 
238
- ### 7. Broadcast with Property Filters (from Triggered Methods)
236
+ ### 6b. Entry Point Modes (Singleton vs Multiple)
239
237
 
240
- Triggered methods can send events to **specific instances** using property filters:
238
+ **Entry point machines** can operate in two modes, controlling how instances are created:
239
+
240
+ #### Configuration Options
241
241
 
242
242
  ```yaml
243
- triggeredMethods:
244
- notifyRiskMonitors: |
245
- async function(event, context, sender) {
246
- // Update local context
247
- context.executedQuantity += event.payload.quantity;
248
-
249
- // BROADCAST to risk monitors for THIS CUSTOMER ONLY
250
- const count = await sender.broadcast(
251
- 'RiskMonitor', // Target machine
252
- 'Monitoring', // Target state
253
- {
254
- type: 'ORDER_UPDATE',
255
- payload: {
256
- orderId: context.orderId,
257
- executedQuantity: context.executedQuantity
258
- },
259
- timestamp: Date.now()
260
- },
261
- [
262
- // FILTERS: Property-based targeting
263
- { property: 'customerId', value: context.customerId },
264
- { property: 'assetClass', operator: '===', value: 'EQUITY' }
265
- ]
266
- );
267
-
268
- console.log(`Notified ${count} risk monitor(s)`);
269
- }
243
+ name: OrderComponent
244
+ entryMachine: Order # Which machine is the entry point
245
+ entryMachineMode: multiple # 'singleton' or 'multiple' (default: 'singleton')
246
+ autoCreateEntryPoint: false # Auto-create instance on startup? (default: true for singleton, false for multiple)
247
+
248
+ stateMachines:
249
+ - name: Order
250
+ initialState: Created
251
+ # ...
270
252
  ```
271
253
 
272
- **Available sender methods:**
273
- - `sender.sendTo(instanceId, event)` - Send to specific instance
274
- - `sender.broadcast(machine, state, event, filters?)` - Broadcast with optional filters
275
- - `sender.broadcastToComponent(component, machine, state, event, filters?)` - Cross-component broadcast
276
- - `sender.createInstance(machine, context)` - Create new instance
254
+ #### Singleton Mode (Default)
277
255
 
278
- **Filter operators:** `===`, `!==`, `>`, `<`, `>=`, `<=`, `contains`, `in`
256
+ Best for: Monitors, supervisors, background processors
279
257
 
280
- **Multiple filters = AND logic** (all must match).
258
+ ```yaml
259
+ name: MonitoringComponent
260
+ entryMachine: SystemMonitor
261
+ entryMachineMode: singleton # Only ONE instance allowed
262
+ autoCreateEntryPoint: true # Created automatically on startup
281
263
 
282
- See: `examples/advanced-patterns-demo.yaml`
264
+ stateMachines:
265
+ - name: SystemMonitor
266
+ initialState: Idle
267
+ ```
268
+
269
+ **Behavior:**
270
+ - ✅ Runtime auto-creates the instance on startup
271
+ - ❌ API calls to create additional instances are rejected
272
+ - ✅ Instance recreated automatically if component restarts
273
+
274
+ #### Multiple Mode
275
+
276
+ Best for: Orders, payments, user workflows - entities created by users
277
+
278
+ ```yaml
279
+ name: OrderComponent
280
+ entryMachine: Order
281
+ entryMachineMode: multiple # Multiple instances allowed
282
+ autoCreateEntryPoint: false # Don't auto-create (user creates via API)
283
+
284
+ stateMachines:
285
+ - name: Order
286
+ initialState: Created
287
+ ```
288
+
289
+ **Behavior:**
290
+ - ❌ No instance created on startup (unless autoCreateEntryPoint: true)
291
+ - ✅ Create instances via API: `POST /api/components/OrderComponent/instances`
292
+ - ✅ Dashboard "New Instance" button available for manual creation
293
+
294
+ #### Creating Instances via API
295
+
296
+ For **multiple mode** components, create instances programmatically:
283
297
 
284
- ### 8. Multiple Transitions with Guards (First Matching Wins)
298
+ ```bash
299
+ # Create Order instance with context
300
+ curl -X POST http://localhost:3000/api/components/OrderComponent/instances \
301
+ -H "Content-Type: application/json" \
302
+ -d '{
303
+ "machineName": "Order",
304
+ "context": {
305
+ "orderId": "ORD-123",
306
+ "amount": 99.99,
307
+ "customerId": "CUST-456"
308
+ }
309
+ }'
310
+ ```
311
+
312
+ Or via the dashboard UI: Click the **"+ New"** button in the Instances sidebar.
285
313
 
286
- When multiple transitions from the same state use the same event, **guards differentiate them**.
314
+ #### Summary Table
287
315
 
288
- The **first transition with passing guards wins**:
316
+ | Mode | autoCreateEntryPoint | Behavior |
317
+ |------|---------------------|----------|
318
+ | `singleton` | `true` (default) | One instance auto-created, API rejects new ones |
319
+ | `singleton` | `false` | One instance allowed, created via API |
320
+ | `multiple` | `true` | One instance auto-created, more via API |
321
+ | `multiple` | `false` (default) | No auto-create, all via API or dashboard |
322
+
323
+ ### 7. Broadcast with Property Filters (from Triggered Methods)
324
+
325
+ Triggered methods can send events to **specific instances** using property filters:
326
+
327
+ **YAML** — declare the method name on the transition:
289
328
 
290
329
  ```yaml
291
330
  transitions:
292
- # TRANSITION 1: Stay in PartiallyExecuted
293
331
  - from: PartiallyExecuted
294
332
  to: PartiallyExecuted
295
333
  event: EXECUTION_NOTIFICATION
296
- triggeredMethod: accumulateExecution
297
- guards:
298
- - type: custom
299
- condition: "context.executedQuantity < context.totalQuantity"
334
+ type: triggerable
335
+ triggeredMethod: notifyRiskMonitors
336
+ ```
300
337
 
301
- # TRANSITION 2: Move to FullyExecuted
302
- - from: PartiallyExecuted
303
- to: FullyExecuted
304
- event: EXECUTION_NOTIFICATION
305
- triggeredMethod: accumulateExecution
306
- guards:
307
- - type: context
308
- property: executedQuantity
309
- operator: ">="
310
- value: "{{totalQuantity}}"
338
+ **TypeScript** implement the handler:
339
+
340
+ ```typescript
341
+ runtime.on('triggered_method', async ({ method, event, context, sender }) => {
342
+ if (method === 'notifyRiskMonitors') {
343
+ // Update local context
344
+ context.executedQuantity += event.payload.quantity;
345
+
346
+ // BROADCAST to risk monitors for THIS CUSTOMER ONLY
347
+ const count = await sender.broadcast(
348
+ 'RiskMonitor', // Target machine
349
+ {
350
+ type: 'ORDER_UPDATE',
351
+ payload: {
352
+ orderId: context.orderId,
353
+ executedQuantity: context.executedQuantity
354
+ },
355
+ timestamp: Date.now()
356
+ },
357
+ [
358
+ // FILTERS: Property-based targeting
359
+ { property: 'customerId', value: context.customerId },
360
+ { property: 'assetClass', operator: '===', value: 'EQUITY' }
361
+ ],
362
+ 'Monitoring' // Target state (optional)
363
+ );
364
+
365
+ console.log(`Notified ${count} risk monitor(s)`);
366
+ }
367
+ });
311
368
  ```
312
369
 
313
- **Execution order:**
314
- 1. Event arrives
315
- 2. Triggered method runs **once** (updates context)
316
- 3. Guards evaluated **in YAML order**
317
- 4. First matching guard transition fires
318
- 5. Other transitions skipped
370
+ **Available sender methods:**
371
+ - `sender.sendToSelf(event)` - Send event to current instance
372
+ - `sender.sendTo(instanceId, event)` - Send to specific instance
373
+ - `sender.sendToComponent(componentName, instanceId, event)` - Cross-component to specific instance
374
+ - `sender.broadcast(machineName, event, currentState?, componentName?)` - Broadcast to instances
375
+ - `sender.createInstance(machineName, context)` - Create new instance
376
+ - `sender.createInstanceInComponent(componentName, machineName, context)` - Cross-component instance creation
319
377
 
320
- **Key points:**
321
- - Triggered method runs **before** guards (can update context)
322
- - Transitions defined in YAML are evaluated in order
323
- - First match wins - other transitions not tried
324
- - Useful for accumulation patterns (partial vs. full execution)
378
+ Instance filtering is done via `matchingRules` on the target transition in YAML, not in the sender call.
325
379
 
326
- See: `EVENT-ACCUMULATION-GUIDE.md` for complete guide.
380
+ See: `examples/advanced-patterns-demo.yaml`
327
381
 
328
382
  ---
329
383
 
@@ -379,20 +433,6 @@ stateMachines:
379
433
  xcomponent-ai serve order.yaml payment.yaml
380
434
  ```
381
435
 
382
- ### Guards
383
-
384
- Conditional transitions:
385
-
386
- ```yaml
387
- transitions:
388
- - from: Pending
389
- to: Approved
390
- event: APPROVE
391
- guards:
392
- - keys: [amount, clientId] # Required fields
393
- - customFunction: "event.payload.amount <= 100000" # Max limit
394
- ```
395
-
396
436
  ### Payload Templating
397
437
 
398
438
  Pass context data between machines:
@@ -444,20 +484,7 @@ states:
444
484
  address: "{{shippingAddress}}"
445
485
  ```
446
486
 
447
- ### Pattern 3: Compliance with Guards
448
-
449
- ```yaml
450
- transitions:
451
- - from: Submitted
452
- to: Approved
453
- event: APPROVE
454
- guards:
455
- - keys: [complianceCheck, riskScore]
456
- - customFunction: "event.payload.riskScore < 70"
457
- - customFunction: "event.payload.complianceCheck === 'PASSED'"
458
- ```
459
-
460
- ### Pattern 4: Timeout Transitions
487
+ ### Pattern 3: Timeout Transitions
461
488
 
462
489
  ```yaml
463
490
  transitions:
@@ -538,10 +565,9 @@ describe('OrderEntry FSM', () => {
538
565
  1. **Start with YAML** - Define FSM first, code second
539
566
  2. **Use contextSchema** - Let dashboard generate forms automatically
540
567
  3. **Leverage cascadingRules** - Reduce orchestration code
541
- 4. **Add guards** - Encode business rules in YAML
542
- 5. **Test FSM** - Write tests for state transitions
543
- 6. **Use serve for demos** - Quick prototypes with dashboard
544
- 7. **Use programmatic mode for production** - More control, better scaling
568
+ 4. **Test FSM** - Write tests for state transitions
569
+ 5. **Use serve for demos** - Quick prototypes with dashboard
570
+ 6. **Use programmatic mode for production** - More control, better scaling
545
571
 
546
572
  ---
547
573
 
package/QUICKSTART.md CHANGED
@@ -199,12 +199,29 @@ xcomponent-ai init loan-approval
199
199
  cd loan-approval
200
200
 
201
201
  # Edit fsm/LoanApprovalComponent.yaml
202
- # (Add your states, transitions, guards)
202
+ # (Add your states, transitions)
203
203
 
204
204
  # Test your FSM
205
205
  xcomponent-ai serve fsm/LoanApprovalComponent.yaml
206
206
  ```
207
207
 
208
+ ## 🏗️ XComponent Pattern (Advanced)
209
+
210
+ For orchestrating multiple state machines with automatic instance creation:
211
+
212
+ ```bash
213
+ # Use the XComponent pattern demo
214
+ xcomponent-ai serve examples/xcomponent-pattern-demo.yaml
215
+ ```
216
+
217
+ This demonstrates:
218
+ - **Entry Point** auto-created on startup (⭐ OrderManager)
219
+ - **Inter-machine transitions** creating new instances (green arrows in dashboard)
220
+ - **Auto-deallocation** of completed instances
221
+ - **Component View** showing all machines and their connections
222
+
223
+ See [XCOMPONENT-PATTERN.md](./XCOMPONENT-PATTERN.md) for complete guide.
224
+
208
225
  ## 🎓 Next Steps
209
226
 
210
227
  - 📖 Read the [Framework Guide](./LLM_FRAMEWORK_GUIDE.md) to understand concepts