@fluentcommerce/ai-skills 0.1.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.
- package/LICENSE +21 -0
- package/README.md +622 -0
- package/bin/cli.mjs +1973 -0
- package/content/cli/agents/fluent-cli/agent.json +149 -0
- package/content/cli/agents/fluent-cli.md +132 -0
- package/content/cli/skills/fluent-bootstrap/SKILL.md +181 -0
- package/content/cli/skills/fluent-cli-index/SKILL.md +63 -0
- package/content/cli/skills/fluent-cli-mcp-cicd/SKILL.md +77 -0
- package/content/cli/skills/fluent-cli-reference/SKILL.md +1031 -0
- package/content/cli/skills/fluent-cli-retailer/SKILL.md +85 -0
- package/content/cli/skills/fluent-cli-settings/SKILL.md +106 -0
- package/content/cli/skills/fluent-connect/SKILL.md +886 -0
- package/content/cli/skills/fluent-module-deploy/SKILL.md +349 -0
- package/content/cli/skills/fluent-profile/SKILL.md +180 -0
- package/content/cli/skills/fluent-workflow/SKILL.md +310 -0
- package/content/dev/agents/fluent-dev/agent.json +88 -0
- package/content/dev/agents/fluent-dev.md +525 -0
- package/content/dev/reference-modules/catalog.json +4754 -0
- package/content/dev/skills/fluent-build/SKILL.md +192 -0
- package/content/dev/skills/fluent-connection-analysis/SKILL.md +386 -0
- package/content/dev/skills/fluent-custom-code/SKILL.md +895 -0
- package/content/dev/skills/fluent-data-module-scaffold/SKILL.md +714 -0
- package/content/dev/skills/fluent-e2e-test/SKILL.md +394 -0
- package/content/dev/skills/fluent-event-api/SKILL.md +945 -0
- package/content/dev/skills/fluent-feature-explain/SKILL.md +603 -0
- package/content/dev/skills/fluent-feature-plan/PLAN_TEMPLATE.md +695 -0
- package/content/dev/skills/fluent-feature-plan/SKILL.md +227 -0
- package/content/dev/skills/fluent-job-batch/SKILL.md +138 -0
- package/content/dev/skills/fluent-mermaid-validate/SKILL.md +86 -0
- package/content/dev/skills/fluent-module-scaffold/SKILL.md +1928 -0
- package/content/dev/skills/fluent-module-validate/SKILL.md +775 -0
- package/content/dev/skills/fluent-pre-deploy-check/SKILL.md +1108 -0
- package/content/dev/skills/fluent-retailer-config/SKILL.md +1111 -0
- package/content/dev/skills/fluent-rule-scaffold/SKILL.md +385 -0
- package/content/dev/skills/fluent-scope-decompose/SKILL.md +1021 -0
- package/content/dev/skills/fluent-session-audit-export/SKILL.md +632 -0
- package/content/dev/skills/fluent-session-summary/SKILL.md +195 -0
- package/content/dev/skills/fluent-settings/SKILL.md +1058 -0
- package/content/dev/skills/fluent-source-onboard/SKILL.md +632 -0
- package/content/dev/skills/fluent-system-monitoring/SKILL.md +767 -0
- package/content/dev/skills/fluent-test-data/SKILL.md +513 -0
- package/content/dev/skills/fluent-trace/SKILL.md +1143 -0
- package/content/dev/skills/fluent-transition-api/SKILL.md +346 -0
- package/content/dev/skills/fluent-version-manage/SKILL.md +744 -0
- package/content/dev/skills/fluent-workflow-analyzer/SKILL.md +959 -0
- package/content/dev/skills/fluent-workflow-builder/SKILL.md +319 -0
- package/content/dev/skills/fluent-workflow-deploy/SKILL.md +267 -0
- package/content/mcp-extn/agents/fluent-mcp.md +69 -0
- package/content/mcp-extn/skills/fluent-mcp-tools/SKILL.md +461 -0
- package/content/mcp-official/agents/fluent-mcp-core.md +91 -0
- package/content/mcp-official/skills/fluent-mcp-core/SKILL.md +94 -0
- package/content/rfl/agents/fluent-rfl.md +56 -0
- package/content/rfl/skills/fluent-rfl-assess/SKILL.md +172 -0
- package/docs/CAPABILITY_MAP.md +77 -0
- package/docs/CLI_COVERAGE.md +47 -0
- package/docs/DEV_WORKFLOW.md +802 -0
- package/docs/FLOW_RUN.md +142 -0
- package/docs/USE_CASES.md +404 -0
- package/metadata.json +156 -0
- package/package.json +51 -0
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fluent-e2e-test
|
|
3
|
+
description: Run end-to-end test sequences for Fluent Commerce workflows. Discover environment, create entities dynamically, fire events, poll statuses, assert state transitions, and report results. Triggers on "run e2e test", "test order flow", "test workflow", "e2e test", "integration test".
|
|
4
|
+
user-invocable: true
|
|
5
|
+
allowed-tools: Bash, Read, Write, Edit, Glob, Grep
|
|
6
|
+
argument-hint: [scenario-name] [--order-ref <ref>] [--entity-type ORDER|FULFILMENT]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# End-to-End Test Runner
|
|
10
|
+
|
|
11
|
+
Run automated test sequences against Fluent Commerce workflows. Discover environment configuration, create entities with real refs, fire events in sequence, poll for state transitions, and report pass/fail results.
|
|
12
|
+
|
|
13
|
+
## Ownership Boundary
|
|
14
|
+
|
|
15
|
+
This skill owns test scenario choreography, polling strategy, and pass/fail reporting.
|
|
16
|
+
|
|
17
|
+
Environment discovery and entity creation payloads are owned by `/fluent-test-data`.
|
|
18
|
+
Canonical MCP extension tool syntax/limits are owned by `/fluent-mcp-tools`.
|
|
19
|
+
Event model/filter semantics and causality patterns are owned by `/fluent-event-api`.
|
|
20
|
+
|
|
21
|
+
## Pre-Check: Load Source Analysis
|
|
22
|
+
|
|
23
|
+
Before testing, check if `/fluent-custom-code` analysis artifacts exist:
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
accounts/<PROFILE>/analysis/custom-code/source-map.json
|
|
27
|
+
accounts/<PROFILE>/analysis/custom-code/constraints.json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If found, use them to:
|
|
31
|
+
- `source-map.json` → `modules[].rules[].parameters` — know what attributes events need
|
|
32
|
+
- `source-map.json` → `modules[].rules[].entityTypes` — validate entity type coverage
|
|
33
|
+
- `constraints.json` → `risks[]` — focus tests on high-risk areas
|
|
34
|
+
|
|
35
|
+
If not found, rely on workflow JSON and runtime discovery only. Treat artifact-gate failures as "not found" (for example missing required files, missing hashes, or blocking `missingSources` in `constraints.json`).
|
|
36
|
+
|
|
37
|
+
## When to Use
|
|
38
|
+
|
|
39
|
+
- Verifying a workflow works end-to-end after changes
|
|
40
|
+
- Testing a specific path (HD delivery, CC pickup, cancellation, short pick)
|
|
41
|
+
- Regression testing after deploying a new module version
|
|
42
|
+
- Validating event processing and state transitions
|
|
43
|
+
- Confirming external system integration points (webhooks fire correctly)
|
|
44
|
+
|
|
45
|
+
## Test Execution Framework
|
|
46
|
+
|
|
47
|
+
Every E2E test follows this pattern:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
0. DISCOVER environment (via /fluent-test-data)
|
|
51
|
+
1. CREATE entity using discovered refs (via /fluent-test-data)
|
|
52
|
+
2. For each step:
|
|
53
|
+
a. SEND event (via MCP event.send)
|
|
54
|
+
b. WAIT for async processing (poll with timeout)
|
|
55
|
+
c. VERIFY entity state (via MCP graphql.query)
|
|
56
|
+
d. Record PASS or FAIL
|
|
57
|
+
3. REPORT results
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Key MCP Tools Used
|
|
61
|
+
|
|
62
|
+
| Operation | MCP Tool | Server |
|
|
63
|
+
|-----------|----------|--------|
|
|
64
|
+
| Discover environment | `graphql.query` | fluent-mcp-extn |
|
|
65
|
+
| Create entity | `graphql.query` (mutation) | fluent-mcp-extn |
|
|
66
|
+
| Discover available actions | `workflow.transitions` | fluent-mcp-extn |
|
|
67
|
+
| Send event | `event.send` | fluent-mcp-extn |
|
|
68
|
+
| Check event status | `event.list` | fluent-mcp-extn |
|
|
69
|
+
| Query entity state | `graphql.query` | fluent-mcp-extn |
|
|
70
|
+
| Introspect schema | `graphql.introspect` | fluent-mcp-extn |
|
|
71
|
+
|
|
72
|
+
## Phase 0: Environment Discovery (mandatory)
|
|
73
|
+
|
|
74
|
+
**Before creating any entity**, run the `/fluent-test-data` discovery sequence to obtain:
|
|
75
|
+
|
|
76
|
+
- Retailer ID and ref
|
|
77
|
+
- Active warehouse ref (for HD) and store ref (for CC)
|
|
78
|
+
- Product catalogue ref and at least one product ref with inventory
|
|
79
|
+
- Customer ID (create if none exist)
|
|
80
|
+
- Consignment prefix (from settings, or default `A_`)
|
|
81
|
+
|
|
82
|
+
**Never hardcode refs.** Different retailers have different catalogues, locations, and products. Always query the live environment.
|
|
83
|
+
|
|
84
|
+
## Dynamic Transition Discovery
|
|
85
|
+
|
|
86
|
+
Instead of hardcoding event sequences, use `workflow.transitions` to dynamically discover available actions at each state:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
1. Create entity using discovered refs (via /fluent-test-data)
|
|
90
|
+
2. workflow.transitions → get available actions at current status
|
|
91
|
+
3. For each action:
|
|
92
|
+
a. event.send with eventName and required attributes from response
|
|
93
|
+
b. Poll entity status until transition completes
|
|
94
|
+
c. workflow.transitions → get next available actions
|
|
95
|
+
4. Repeat until no more userActions
|
|
96
|
+
|
|
97
|
+
If `userActions` is empty, do **not** assume terminal immediately:
|
|
98
|
+
- It can also mean a system-managed/gated status.
|
|
99
|
+
- Verify entity status and recent events before concluding terminal.
|
|
100
|
+
- If status is non-terminal, continue via workflow/event-driven progression and trace checks.
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Benefits:**
|
|
104
|
+
- Test sequences adapt automatically when workflows change
|
|
105
|
+
- Discovers required attributes for each event (avoids missing-attribute errors)
|
|
106
|
+
- Validates that expected user actions are available after deployment
|
|
107
|
+
|
|
108
|
+
**Example — discover actions at current status:**
|
|
109
|
+
```
|
|
110
|
+
workflow.transitions({
|
|
111
|
+
triggers: [{
|
|
112
|
+
type: "ORDER",
|
|
113
|
+
subtype: "HD",
|
|
114
|
+
status: "<current_status>",
|
|
115
|
+
retailerId: "<discovered.retailerId>",
|
|
116
|
+
flexType: "ORDER::HD"
|
|
117
|
+
}]
|
|
118
|
+
})
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The response `userActions[].eventName` maps directly to `event.send`'s `name` parameter.
|
|
122
|
+
The response `userActions[].attributes` tells you what to include in `event.send`'s `attributes`.
|
|
123
|
+
|
|
124
|
+
## Poll-and-Assert Pattern
|
|
125
|
+
|
|
126
|
+
After sending an event, the entity status changes asynchronously. Use this pattern to wait:
|
|
127
|
+
|
|
128
|
+
### Poll entity status until expected state (or timeout)
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
1. Send event via event.send (mode: "async")
|
|
132
|
+
2. Wait 3 seconds (initial processing time)
|
|
133
|
+
3. Query entity status via graphql.query
|
|
134
|
+
4. If status matches expected → PASS
|
|
135
|
+
5. If status doesn't match → wait 5 more seconds, retry (up to 12 retries = 60s total)
|
|
136
|
+
6. If timeout → FAIL with "Expected <EXPECTED>, got <ACTUAL> after 60s"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Composite workflow note (ORDER::MULTI and similar):**
|
|
140
|
+
- After `ConfirmValidation`, use a longer wait window (20-30s) before first assertion.
|
|
141
|
+
- Fulfilment creation and aggregate gates can complete asynchronously in several hops.
|
|
142
|
+
|
|
143
|
+
### Poll event status until processed
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
1. After event.send, note the event details
|
|
147
|
+
2. event.list filtered by entityRef + name + recent time window
|
|
148
|
+
3. Check eventStatus: SUCCESS = processed, FAILED = error, PENDING = still processing
|
|
149
|
+
4. If PENDING → wait 5s and retry
|
|
150
|
+
5. If FAILED → report error details from event.get
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Test Scenarios
|
|
154
|
+
|
|
155
|
+
### Scenario: ORDER HD (Home Delivery) — Full Lifecycle
|
|
156
|
+
|
|
157
|
+
**Pre-requisite:** Run `/fluent-test-data` discovery. Need: retailerId, warehouseRef, productRef, catalogueRef, customerId, consignmentPrefix.
|
|
158
|
+
|
|
159
|
+
**Entities created:** 1 ORDER with 1 HD fulfilment choice (all refs from discovery)
|
|
160
|
+
|
|
161
|
+
**Steps:**
|
|
162
|
+
|
|
163
|
+
| # | Action | Event | Expected Order Status | Expected Fulfilment Status |
|
|
164
|
+
|---|--------|-------|----------------------|---------------------------|
|
|
165
|
+
| 1 | Create order | *(via /fluent-test-data)* | CREATED → ON_VALIDATION | — |
|
|
166
|
+
| 2 | Confirm validation | `ConfirmValidation` on ORDER | ORDER_SPLIT → IN_PROGRESS | CREATED |
|
|
167
|
+
| 3 | Confirm allocation | `ConfirmAllocation` on FULFILMENT | IN_PROGRESS | RECEIVED |
|
|
168
|
+
| 4 | Create invoice | `CreateInvoice` on FULFILMENT | IN_PROGRESS | INVOICED |
|
|
169
|
+
| 5 | Confirm pick | `ConfirmPick` on FULFILMENT | IN_PROGRESS | PICKPACK → *(auto)* |
|
|
170
|
+
| 6 | Confirm shipment | `ConfirmShipment` on FULFILMENT | SHIPPED | SHIPPED |
|
|
171
|
+
| 7 | Confirm delivery | `ConfirmDelivery` on FULFILMENT | COMPLETED | DELIVERED |
|
|
172
|
+
|
|
173
|
+
**Step 1 — Create Order:**
|
|
174
|
+
|
|
175
|
+
Run `/fluent-test-data` to generate the `createOrder` mutation with discovered refs. The skill queries locations, products, catalogues, and customers — then builds the mutation payload dynamically. See `/fluent-test-data` for the full discovery and creation flow.
|
|
176
|
+
|
|
177
|
+
**Step 2 — ConfirmValidation (triggers full cascade):**
|
|
178
|
+
```
|
|
179
|
+
event.send({
|
|
180
|
+
name: "ConfirmValidation",
|
|
181
|
+
entityRef: "<order_ref>",
|
|
182
|
+
entityType: "ORDER",
|
|
183
|
+
retailerId: "<discovered.retailerId>"
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
After this event, the async cascade runs automatically:
|
|
188
|
+
- ProcessOrder → ORDER_SPLIT
|
|
189
|
+
- RouteFulfilmentChoice → ProcessHDFulfilmentChoice
|
|
190
|
+
- CreateFulfilmentFromSourcingLocation → creates FULFILMENT
|
|
191
|
+
- NotifyFCComplete → SourceOrder → IN_PROGRESS
|
|
192
|
+
|
|
193
|
+
**Wait 15 seconds**, then verify:
|
|
194
|
+
- Order status = `IN_PROGRESS`
|
|
195
|
+
- Fulfilment exists with status = `CREATED`
|
|
196
|
+
- Query fulfilment ref for subsequent events
|
|
197
|
+
|
|
198
|
+
If fulfilment is not found, run fallback lookup sequence before failing:
|
|
199
|
+
1. Query fulfilment from the order edge (`order.fulfilments`).
|
|
200
|
+
2. Query fulfilment by order ID (`fulfilments(orderId: [...])`) if supported.
|
|
201
|
+
3. Check event history for `FAILED` or `PENDING` events.
|
|
202
|
+
4. Query `ORCHESTRATION_AUDIT` (`category=exception`) for rule-level errors.
|
|
203
|
+
|
|
204
|
+
**Steps 3-7 — Fulfilment events:**
|
|
205
|
+
|
|
206
|
+
Each fulfilment event follows the same pattern:
|
|
207
|
+
```
|
|
208
|
+
event.send({
|
|
209
|
+
name: "<EVENT_NAME>",
|
|
210
|
+
entityRef: "<fulfilment_ref>",
|
|
211
|
+
entityType: "FULFILMENT",
|
|
212
|
+
retailerId: "<discovered.retailerId>",
|
|
213
|
+
attributes: { ... }
|
|
214
|
+
})
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Use `workflow.transitions` at each step to confirm what attributes are required. Common patterns:
|
|
218
|
+
|
|
219
|
+
| Event | Typical Attributes |
|
|
220
|
+
|-------|-------------------|
|
|
221
|
+
| `ConfirmAllocation` | *(check transitions response — often none)* |
|
|
222
|
+
| `CreateInvoice` | *(check transitions response — often none)* |
|
|
223
|
+
| `ConfirmPick` | `pickedAt` (ISO datetime), `pickedItems` (array of `{ ref, filledQuantity }` from discovered product refs) |
|
|
224
|
+
| `ConfirmShipment` | `trackingNumber` (generate: `E2E-TRACK-<TIMESTAMP>`), `carrierRef` (generate: `E2E-CARRIER`), `shippedAt` (ISO now) |
|
|
225
|
+
| `ConfirmDelivery` | `deliveredAt` (ISO now) |
|
|
226
|
+
|
|
227
|
+
### Scenario: ORDER CC (Click & Collect)
|
|
228
|
+
|
|
229
|
+
**Pre-requisite:** Same as HD, but also need a store location (type=STORE) from discovery.
|
|
230
|
+
|
|
231
|
+
Same as HD through step 5 (ConfirmPick), then diverges:
|
|
232
|
+
|
|
233
|
+
| # | Event | Expected Fulfilment Status |
|
|
234
|
+
|---|-------|---------------------------|
|
|
235
|
+
| 6 | *(auto after pick)* | READY_FOR_PICKUP |
|
|
236
|
+
| 7 | `ConfirmCollection` on FULFILMENT | COLLECTED |
|
|
237
|
+
| — | *(auto)* | ORDER → COMPLETED |
|
|
238
|
+
|
|
239
|
+
### Scenario: Cancel Order
|
|
240
|
+
|
|
241
|
+
| # | Action | Event | Expected Status |
|
|
242
|
+
|---|--------|-------|----------------|
|
|
243
|
+
| 1 | Create order | *(via /fluent-test-data)* | ON_VALIDATION |
|
|
244
|
+
| 2 | Cancel | `CancelOrder` on ORDER | CANCELLED |
|
|
245
|
+
|
|
246
|
+
### Scenario: Short Pick
|
|
247
|
+
|
|
248
|
+
| # | Action | Expected Fulfilment Status |
|
|
249
|
+
|---|--------|---------------------------|
|
|
250
|
+
| 1-4 | Normal flow through INVOICED | INVOICED |
|
|
251
|
+
| 5 | `ConfirmPick` with `pickedItems` where `filledQuantity < requestedQuantity` | PARTIAL |
|
|
252
|
+
|
|
253
|
+
### Scenario: Dynamic (Workflow-Driven)
|
|
254
|
+
|
|
255
|
+
For custom or unknown workflows, use fully dynamic discovery:
|
|
256
|
+
|
|
257
|
+
```
|
|
258
|
+
1. Run /fluent-test-data discovery
|
|
259
|
+
2. Create entity using discovered refs
|
|
260
|
+
3. Loop:
|
|
261
|
+
a. workflow.transitions for current entity state
|
|
262
|
+
b. If no userActions:
|
|
263
|
+
- verify status category and recent events first
|
|
264
|
+
- stop only when entity is confirmed terminal
|
|
265
|
+
c. Pick first userAction (or specific one by label)
|
|
266
|
+
d. event.send with eventName + required attributes from response
|
|
267
|
+
e. Poll until entity transitions
|
|
268
|
+
f. Go to (a)
|
|
269
|
+
4. Report all transitions walked
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
This approach works for ANY workflow without knowing the state machine in advance.
|
|
273
|
+
|
|
274
|
+
## Test Report Format
|
|
275
|
+
|
|
276
|
+
After running a scenario, output a structured report:
|
|
277
|
+
|
|
278
|
+
```
|
|
279
|
+
=== E2E Test Report ===
|
|
280
|
+
Scenario: ORDER HD Full Lifecycle
|
|
281
|
+
Order Ref: <generated_ref>
|
|
282
|
+
Retailer: <discovered.retailerRef> (ID: <discovered.retailerId>)
|
|
283
|
+
Start Time: <ISO timestamp>
|
|
284
|
+
|
|
285
|
+
Discovery:
|
|
286
|
+
Warehouse: <discovered.warehouseRef>
|
|
287
|
+
Product: <discovered.productRef> (catalogue: <discovered.catalogueRef>)
|
|
288
|
+
Customer: <discovered.customerId>
|
|
289
|
+
|
|
290
|
+
Step 1: Create Order
|
|
291
|
+
Action: createOrder mutation (refs from live discovery)
|
|
292
|
+
Result: PASS — Order created, ID=<id>, status=CREATED
|
|
293
|
+
Duration: <N>s
|
|
294
|
+
|
|
295
|
+
Step 2: ConfirmValidation → IN_PROGRESS
|
|
296
|
+
Action: event.send ConfirmValidation
|
|
297
|
+
Expected: Order=IN_PROGRESS, Fulfilment=CREATED
|
|
298
|
+
Actual: Order=IN_PROGRESS, Fulfilment=CREATED (ref: <fulfilment_ref>)
|
|
299
|
+
Result: PASS
|
|
300
|
+
Duration: <N>s (async cascade)
|
|
301
|
+
|
|
302
|
+
...
|
|
303
|
+
|
|
304
|
+
=== Summary ===
|
|
305
|
+
Steps: N/N passed
|
|
306
|
+
Total Duration: <N>s
|
|
307
|
+
Result: ALL PASSED
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Post-Test Event Analysis
|
|
311
|
+
|
|
312
|
+
After a test scenario completes (pass or fail), extract detailed execution data from the event audit trail for comprehensive validation. This supplements the poll-and-assert pattern with full execution evidence.
|
|
313
|
+
|
|
314
|
+
> **Preferred: compact flowInspect first.** After test completion, call `event.flowInspect` with the order ref as `rootEntityRef` using default compact mode (~2-3k tokens). The compact summary includes status flow, anomaly findings, failed webhooks, and slowest rulesets — sufficient for most test reports. Only add targeted flags (`includeRuleDetails`, `includeCustomLogs`) if the compact summary reveals issues that need drill-down. **NEVER use `compact: false`** — it returns ~30k tokens and fills context. Use the manual patterns below only when you need extraction beyond what flowInspect provides.
|
|
315
|
+
|
|
316
|
+
### Snapshot Verification
|
|
317
|
+
|
|
318
|
+
Use entity snapshots from ORCHESTRATION_AUDIT events to verify entity state at each transition without additional GraphQL queries:
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
event.list({
|
|
322
|
+
"eventType": "ORCHESTRATION_AUDIT",
|
|
323
|
+
"context.rootEntityRef": "<ORDER_REF>",
|
|
324
|
+
"count": 200
|
|
325
|
+
})
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Filter by `category == "snapshot"` to get the full entity state at each orchestration step. Each snapshot contains the complete entity (status, items, attributes, relationships) at the moment before rules executed.
|
|
329
|
+
|
|
330
|
+
**Verification pattern:**
|
|
331
|
+
```
|
|
332
|
+
For each test step that passed:
|
|
333
|
+
1. Find the snapshot event for that entity at the expected status
|
|
334
|
+
2. Verify key fields:
|
|
335
|
+
- Items count and quantities match expected
|
|
336
|
+
- Attributes set by previous steps are present (e.g., trackingNumber after ConfirmShipment)
|
|
337
|
+
- Customer/address data is correctly attached
|
|
338
|
+
- Child entity refs (fulfilmentChoice, fulfilment) are populated
|
|
339
|
+
3. If a step failed, compare the snapshot against expected to identify what was different
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Mutation Verification
|
|
343
|
+
|
|
344
|
+
Extract all mutations executed during the test to verify the workflow made the correct GraphQL calls:
|
|
345
|
+
|
|
346
|
+
Filter ORCHESTRATION_AUDIT events where `name` is null and `attributes` contains `request.queryString`. Each mutation event shows the exact GraphQL mutation and input variables.
|
|
347
|
+
|
|
348
|
+
This catches issues where:
|
|
349
|
+
- A rule set the wrong status (mutation input has unexpected status value)
|
|
350
|
+
- A rule updated the wrong entity (mutation targets a different entity ID)
|
|
351
|
+
- Expected attribute updates were not made (mutation input missing expected fields)
|
|
352
|
+
|
|
353
|
+
### Webhook Delivery Verification
|
|
354
|
+
|
|
355
|
+
After test completion, verify all expected webhooks were delivered:
|
|
356
|
+
|
|
357
|
+
Filter ORCHESTRATION_AUDIT events where `name == "Send Webhook"`. Check `Response code` for each:
|
|
358
|
+
- `200` = delivered successfully
|
|
359
|
+
- `404` = endpoint not found (check setting)
|
|
360
|
+
- `0` = connection timeout (check endpoint availability)
|
|
361
|
+
|
|
362
|
+
Include webhook delivery results in the test report as an additional validation layer.
|
|
363
|
+
|
|
364
|
+
### Enhanced Test Report (with event analysis)
|
|
365
|
+
|
|
366
|
+
After the standard test report, append an event analysis section:
|
|
367
|
+
|
|
368
|
+
```
|
|
369
|
+
=== Event Analysis ===
|
|
370
|
+
|
|
371
|
+
Mutations: 7 total (all successful)
|
|
372
|
+
Webhooks: 4 sent (3 delivered, 1 failed — webhook.fulfilment.shipped → 404)
|
|
373
|
+
Snapshots: 3 captured (ORDER@CREATED, FULFILMENT@CREATED, FULFILMENT@PICKPACK)
|
|
374
|
+
Scheduled Events: 1 (ValidationGraceExpired, 30s delay, pre-empted by ConfirmValidation)
|
|
375
|
+
NO_MATCH Events: 1 (ValidationGraceExpired → expected, timer pre-empted)
|
|
376
|
+
Custom Logs: 4 entries (3 INFO, 1 WARN)
|
|
377
|
+
|
|
378
|
+
Recommendation: Fix webhook setting "webhook.fulfilment.shipped" before go-live
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
## Tips
|
|
382
|
+
|
|
383
|
+
- **Always run /fluent-test-data discovery first** — Never assume refs exist
|
|
384
|
+
- **Use unique refs per test run** — Include timestamp or counter to avoid collisions
|
|
385
|
+
- **Wait 15s after ConfirmValidation** — The async cascade creates FC → fulfilment → gates, all in sequence
|
|
386
|
+
- **For composite workflows, poll up to 60s** — CREATE/validation cascades can take longer than single-entity flows
|
|
387
|
+
- **Wait 5-10s between fulfilment events** — Async processing needs time
|
|
388
|
+
- **Always query fulfilment ref** after step 2 — The ref is generated by the workflow (pattern varies by implementation)
|
|
389
|
+
- **Check event.list if a step fails** — Filter by entityRef + eventStatus=FAILED to see error details
|
|
390
|
+
- **Query ORCHESTRATION_AUDIT events on failure** — When a step fails, query audit events for the failing entity to see exactly what happened: `event.list({ eventType: "ORCHESTRATION_AUDIT", "context.entityRef": "<REF>", from: "<recent>", count: 50 })`. Look for `category=exception` events for stack traces, `category=ACTION` for what rules executed, and `category=ruleSet` for timing.
|
|
391
|
+
- **If `workflow.transitions` returns empty `userActions` on non-terminal statuses** — continue with workflow/event-driven progression and trace checks; do not stop early
|
|
392
|
+
- **On FAIL, hand off to /fluent-trace** — Pass entityRef, entityType, eventId (if known), expected status, and actual status; avoid duplicating trace decision-tree logic in this skill
|
|
393
|
+
- **Use event.send with mode: "async"** — Synchronous mode is not recommended for workflow events
|
|
394
|
+
- **Use `workflow.transitions`** to discover required attributes at each step instead of guessing
|