@fluentcommerce/ai-skills 0.1.0 → 0.3.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.

Potentially problematic release.


This version of @fluentcommerce/ai-skills might be problematic. Click here for more details.

Files changed (168) hide show
  1. package/README.md +866 -622
  2. package/bin/cli.mjs +2112 -1973
  3. package/content/cli/agents/fluent-cli/agent.json +149 -149
  4. package/content/cli/agents/fluent-cli.md +132 -132
  5. package/content/cli/skills/fluent-bootstrap/SKILL.md +214 -181
  6. package/content/cli/skills/fluent-cli-index/SKILL.md +1 -1
  7. package/content/cli/skills/fluent-cli-mcp-cicd/SKILL.md +117 -1
  8. package/content/cli/skills/fluent-cli-reference/SKILL.md +1040 -1031
  9. package/content/cli/skills/fluent-cli-retailer/SKILL.md +27 -2
  10. package/content/cli/skills/fluent-cli-settings/SKILL.md +21 -1
  11. package/content/cli/skills/fluent-connect/SKILL.md +937 -886
  12. package/content/cli/skills/fluent-module-deploy/SKILL.md +63 -5
  13. package/content/cli/skills/fluent-profile/SKILL.md +73 -0
  14. package/content/cli/skills/fluent-workflow/SKILL.md +360 -310
  15. package/content/dev/agents/fluent-backend-dev/AGENT.md +58 -0
  16. package/content/dev/agents/fluent-backend-dev/agent.json +69 -0
  17. package/content/dev/agents/fluent-backend-dev.md +287 -0
  18. package/content/dev/agents/fluent-dev/AGENT.md +98 -0
  19. package/content/dev/agents/fluent-dev/agent.json +14 -2
  20. package/content/dev/agents/fluent-dev.md +194 -525
  21. package/content/dev/agents/fluent-frontend-dev/AGENT.md +63 -0
  22. package/content/dev/agents/fluent-frontend-dev/agent.json +52 -0
  23. package/content/dev/agents/fluent-frontend-dev.md +323 -0
  24. package/content/dev/skills/fluent-archive/SKILL.md +234 -0
  25. package/content/dev/skills/fluent-build/SKILL.md +312 -192
  26. package/content/dev/skills/fluent-connection-analysis/SKILL.md +422 -386
  27. package/content/dev/skills/fluent-custom-code/SKILL.md +15 -9
  28. package/content/dev/skills/fluent-data-module-scaffold/SKILL.md +19 -2
  29. package/content/dev/skills/fluent-e2e-test/SKILL.md +501 -394
  30. package/content/dev/skills/fluent-event-api/SKILL.md +962 -945
  31. package/content/dev/skills/fluent-feature-explain/SKILL.md +680 -603
  32. package/content/dev/skills/fluent-feature-plan/PLAN_TEMPLATE.md +27 -2
  33. package/content/dev/skills/fluent-feature-plan/SKILL.md +478 -227
  34. package/content/dev/skills/fluent-feature-status/SKILL.md +335 -0
  35. package/content/dev/skills/fluent-feedback/SKILL.md +221 -0
  36. package/content/dev/skills/fluent-implementation-map/SKILL.md +644 -0
  37. package/content/dev/skills/fluent-job-batch/SKILL.md +10 -0
  38. package/content/dev/skills/fluent-module-scaffold/SKILL.md +64 -2
  39. package/content/dev/skills/fluent-module-validate/SKILL.md +778 -775
  40. package/content/dev/skills/fluent-mystique-analyze/SKILL.md +817 -0
  41. package/content/dev/skills/fluent-mystique-builder/COMPONENT_TEMPLATE.md +81 -0
  42. package/content/dev/skills/fluent-mystique-builder/README.md +63 -0
  43. package/content/dev/skills/fluent-mystique-builder/SKILL.md +1294 -0
  44. package/content/dev/skills/fluent-mystique-builder/components/INDEX.md +92 -0
  45. package/content/dev/skills/fluent-mystique-builder/components/fc.accordion.md +48 -0
  46. package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.fulfilmentpack.md +20 -0
  47. package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.multiparcel.md +21 -0
  48. package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.returnitems.md +21 -0
  49. package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.wavepick.md +21 -0
  50. package/content/dev/skills/fluent-mystique-builder/components/fc.action.inline.md +24 -0
  51. package/content/dev/skills/fluent-mystique-builder/components/fc.activity.entity.md +25 -0
  52. package/content/dev/skills/fluent-mystique-builder/components/fc.analytics.viz.md +20 -0
  53. package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.column.md +111 -0
  54. package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.json.md +20 -0
  55. package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.jsoneditor.md +54 -0
  56. package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.locationId.md +51 -0
  57. package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.retailerId.md +52 -0
  58. package/content/dev/skills/fluent-mystique-builder/components/fc.button.bar.md +57 -0
  59. package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.download.md +53 -0
  60. package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.inline.compatibility.md +60 -0
  61. package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.inline.md +53 -0
  62. package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.md +24 -0
  63. package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.pick.md +61 -0
  64. package/content/dev/skills/fluent-mystique-builder/components/fc.buttons.add.reject.md +20 -0
  65. package/content/dev/skills/fluent-mystique-builder/components/fc.card.attribute.md +73 -0
  66. package/content/dev/skills/fluent-mystique-builder/components/fc.card.attributes.grid.md +40 -0
  67. package/content/dev/skills/fluent-mystique-builder/components/fc.card.image.md +37 -0
  68. package/content/dev/skills/fluent-mystique-builder/components/fc.card.map.point.md +24 -0
  69. package/content/dev/skills/fluent-mystique-builder/components/fc.card.multi.md +79 -0
  70. package/content/dev/skills/fluent-mystique-builder/components/fc.card.product.md +27 -0
  71. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.area.md +34 -0
  72. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.area.wrapper.feed.md +98 -0
  73. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.bar.md +52 -0
  74. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.bar.wrapper.source.md +104 -0
  75. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.gauge.md +28 -0
  76. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.gauge.wrapper.threshold.md +118 -0
  77. package/content/dev/skills/fluent-mystique-builder/components/fc.chart.line.md +32 -0
  78. package/content/dev/skills/fluent-mystique-builder/components/fc.conditional.md +62 -0
  79. package/content/dev/skills/fluent-mystique-builder/components/fc.dashboard.threshold.md +65 -0
  80. package/content/dev/skills/fluent-mystique-builder/components/fc.daterange.wrapper.forwarder.md +56 -0
  81. package/content/dev/skills/fluent-mystique-builder/components/fc.drawer.button.md +21 -0
  82. package/content/dev/skills/fluent-mystique-builder/components/fc.event.detail.md +20 -0
  83. package/content/dev/skills/fluent-mystique-builder/components/fc.events.search.md +21 -0
  84. package/content/dev/skills/fluent-mystique-builder/components/fc.field.daterange.md +83 -0
  85. package/content/dev/skills/fluent-mystique-builder/components/fc.field.filterComplex.md +106 -0
  86. package/content/dev/skills/fluent-mystique-builder/components/fc.field.intrange.md +82 -0
  87. package/content/dev/skills/fluent-mystique-builder/components/fc.field.multistring.md +50 -0
  88. package/content/dev/skills/fluent-mystique-builder/components/fc.filterPanel.md +53 -0
  89. package/content/dev/skills/fluent-mystique-builder/components/fc.json.editor.md +22 -0
  90. package/content/dev/skills/fluent-mystique-builder/components/fc.json.viewer.md +21 -0
  91. package/content/dev/skills/fluent-mystique-builder/components/fc.list.customAction.md +79 -0
  92. package/content/dev/skills/fluent-mystique-builder/components/fc.list.md +116 -0
  93. package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.bppmetrics.md +69 -0
  94. package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.feed.md +65 -0
  95. package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.source.md +64 -0
  96. package/content/dev/skills/fluent-mystique-builder/components/fc.modal.button.addItem.md +60 -0
  97. package/content/dev/skills/fluent-mystique-builder/components/fc.modal.button.md +21 -0
  98. package/content/dev/skills/fluent-mystique-builder/components/fc.mutation.inline.md +88 -0
  99. package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.collapsible.attributes.md +83 -0
  100. package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.collapsible.text.md +33 -0
  101. package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.link.md +30 -0
  102. package/content/dev/skills/fluent-mystique-builder/components/fc.order.itemDetails.md +20 -0
  103. package/content/dev/skills/fluent-mystique-builder/components/fc.order.shipmentDetails.md +20 -0
  104. package/content/dev/skills/fluent-mystique-builder/components/fc.page.filter.select.md +87 -0
  105. package/content/dev/skills/fluent-mystique-builder/components/fc.page.md +64 -0
  106. package/content/dev/skills/fluent-mystique-builder/components/fc.page.refresh.md +48 -0
  107. package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.column.md +71 -0
  108. package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.header.md +61 -0
  109. package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.md +59 -0
  110. package/content/dev/skills/fluent-mystique-builder/components/fc.page.wizard.md +45 -0
  111. package/content/dev/skills/fluent-mystique-builder/components/fc.page.wizard.summary.md +56 -0
  112. package/content/dev/skills/fluent-mystique-builder/components/fc.progress.circular.md +20 -0
  113. package/content/dev/skills/fluent-mystique-builder/components/fc.provider.graphql.md +71 -0
  114. package/content/dev/skills/fluent-mystique-builder/components/fc.quantity.list.md +87 -0
  115. package/content/dev/skills/fluent-mystique-builder/components/fc.repeater.md +56 -0
  116. package/content/dev/skills/fluent-mystique-builder/components/fc.reports.ipuipc.md +54 -0
  117. package/content/dev/skills/fluent-mystique-builder/components/fc.return.rowExpansion.md +19 -0
  118. package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.barcode.md +21 -0
  119. package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.barcodeFilter.md +72 -0
  120. package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.camera.md +20 -0
  121. package/content/dev/skills/fluent-mystique-builder/components/fc.settingForm.md +64 -0
  122. package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.profile.drawer.button.md +19 -0
  123. package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.profile.modal.button.md +64 -0
  124. package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.strategy.modal.button.md +20 -0
  125. package/content/dev/skills/fluent-mystique-builder/components/fc.stepper.md +20 -0
  126. package/content/dev/skills/fluent-mystique-builder/components/fc.tab.content.md +56 -0
  127. package/content/dev/skills/fluent-mystique-builder/components/fc.tabs.card.md +64 -0
  128. package/content/dev/skills/fluent-mystique-builder/components/fc.tabs.md +69 -0
  129. package/content/dev/skills/fluent-mystique-builder/components/fc.tile.metric.md +73 -0
  130. package/content/dev/skills/fluent-mystique-builder/components/fc.workflow.provider.md +77 -0
  131. package/content/dev/skills/fluent-mystique-builder/validate-docs.ps1 +260 -0
  132. package/content/dev/skills/fluent-mystique-scaffold/SKILL.md +1830 -0
  133. package/content/dev/skills/fluent-mystique-validate/SKILL.md +646 -0
  134. package/content/dev/skills/fluent-pre-deploy-check/SKILL.md +1144 -1108
  135. package/content/dev/skills/fluent-retailer-config/SKILL.md +1162 -1111
  136. package/content/dev/skills/fluent-rollback/SKILL.md +387 -0
  137. package/content/dev/skills/fluent-rule-scaffold/SKILL.md +515 -385
  138. package/content/dev/skills/fluent-scope-decompose/SKILL.md +1123 -1021
  139. package/content/dev/skills/fluent-session-audit-export/SKILL.md +880 -632
  140. package/content/dev/skills/fluent-session-summary/SKILL.md +320 -195
  141. package/content/dev/skills/fluent-settings/SKILL.md +160 -1
  142. package/content/dev/skills/fluent-source-onboard/SKILL.md +31 -3
  143. package/content/dev/skills/fluent-sourcing/SKILL.md +1185 -0
  144. package/content/dev/skills/fluent-system-monitoring/SKILL.md +771 -767
  145. package/content/dev/skills/fluent-test-data/SKILL.md +514 -513
  146. package/content/dev/skills/fluent-trace/SKILL.md +1169 -1143
  147. package/content/dev/skills/fluent-transition-api/SKILL.md +364 -346
  148. package/content/dev/skills/fluent-use-case-discover/SKILL.md +593 -0
  149. package/content/dev/skills/fluent-use-case-discover/SPEC_TEMPLATE.md +281 -0
  150. package/content/dev/skills/fluent-version-manage/SKILL.md +53 -2
  151. package/content/dev/skills/fluent-workflow-analyzer/SKILL.md +995 -959
  152. package/content/dev/skills/fluent-workflow-builder/SKILL.md +668 -319
  153. package/content/dev/skills/fluent-workflow-deploy/SKILL.md +480 -267
  154. package/content/dev/skills/fluent-workspace-tree/SKILL.md +281 -0
  155. package/content/mcp-extn/agents/fluent-mcp.md +133 -69
  156. package/content/mcp-extn/skills/fluent-mcp-tools/SKILL.md +812 -461
  157. package/content/mcp-official/agents/fluent-mcp-core.md +91 -91
  158. package/content/mcp-official/skills/fluent-mcp-core/SKILL.md +94 -94
  159. package/content/rfl/skills/fluent-rfl-assess/SKILL.md +172 -172
  160. package/docs/CAPABILITY_MAP.md +106 -77
  161. package/docs/DEPLOYMENT_PROMOTION_RUNBOOK.md +218 -0
  162. package/docs/DESIGN-implementation-map.md +698 -0
  163. package/docs/DEV_WORKFLOW.md +814 -802
  164. package/docs/FLOW_RUN.md +142 -142
  165. package/docs/GETTING_STARTED.md +427 -0
  166. package/docs/USE_CASES.md +909 -52
  167. package/metadata.json +184 -156
  168. package/package.json +3 -2
@@ -1,394 +1,501 @@
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: PASSOrder 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
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/code/source-map.json
27
+ accounts/<PROFILE>/analysis/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
+ ## Progress
73
+
74
+ Emit this block at each phase transition to show progress:
75
+
76
+ ```
77
+ ▸ /fluent-e2e-test [1/6]
78
+ Environment discovery → Plan-driven test discovery
79
+ Create test entity ○ Execute test steps
80
+ Assert & report ○ Post-test analysis
81
+ ```
82
+
83
+ Update the block as each phase completes — mark completed phases with `✓`, the active phase with `→`, and remaining phases with `○`. Replace `[1/6]` with the current phase number.
84
+
85
+ ## Phase 0: Environment Discovery (mandatory)
86
+
87
+ **Before creating any entity**, run the `/fluent-test-data` discovery sequence to obtain:
88
+
89
+ - Retailer ID and ref
90
+ - Active warehouse ref (for HD) and store ref (for CC)
91
+ - Product catalogue ref and at least one product ref with inventory
92
+ - Customer ID (create if none exist)
93
+ - Consignment prefix (from settings, or default `A_`)
94
+
95
+ **Never hardcode refs.** Different retailers have different catalogues, locations, and products. Always query the live environment.
96
+
97
+ ## Phase 0.5: Plan-Driven Test Discovery
98
+
99
+ When a feature plan exists, use its Test Plan section (§16) as the primary source for test scenarios instead of manually constructing them.
100
+
101
+ ### Detection
102
+ 1. Check `accounts/<PROFILE>/features/*/status.json` for features with `plan: "APPROVED"` and `status` of `IN_PROGRESS` or `APPROVED`
103
+ 2. If found, read the corresponding `plan.md`
104
+ 3. Parse the `## Test Plan` or `## §16 Test Plan` section
105
+
106
+ ### What to Extract from §16
107
+
108
+ | Plan Field | Maps to E2E |
109
+ |------------|-------------|
110
+ | Scenario name | Test suite label |
111
+ | Preconditions | Phase 0 entity setup requirements |
112
+ | Event sequence | Phase 1+ SEND steps (ordered) |
113
+ | Expected status at each step | VERIFY assertions |
114
+ | Expected webhook fires | Additional assertions (check `event.list` for webhook events) |
115
+ | Edge cases / negative paths | Separate test scenarios |
116
+
117
+ ### Auto-Generation Protocol
118
+
119
+ For each scenario in §16:
120
+ 1. **Parse preconditions** → determine entity type, required attributes, location/product refs
121
+ 2. **Parse event sequence** build ordered list of `event.send` calls with expected status transitions
122
+ 3. **Parse assertions** → build `test.assert` calls for each status checkpoint
123
+ 4. **Parse edge cases** → create separate negative test scenarios
124
+
125
+ ### Example Mapping
126
+
127
+ Plan §16 entry:
128
+ ```
129
+ | Scenario | Preconditions | Events | Expected |
130
+ |----------|--------------|--------|----------|
131
+ | HD Happy Path | ORDER at CREATED, warehouse W1 active | SendToFulfilment → Confirm → Complete | COMPLETE |
132
+ ```
133
+
134
+ Maps to E2E steps:
135
+ ```
136
+ 1. CREATE ORDER with ref TEST-HD-<timestamp>
137
+ 2. SEND SendToFulfilment → VERIFY status=AWAITING_FULFILMENT
138
+ 3. SEND Confirm → VERIFY status=CONFIRMED
139
+ 4. SEND Complete VERIFY status=COMPLETE
140
+ ```
141
+
142
+ ### Fallback
143
+ If no plan exists or §16 is missing, fall back to the existing manual test construction flow (Phase 1+).
144
+
145
+ ### Handoff
146
+ ```
147
+ -> READY: Loaded N test scenarios from plan §16 for feature '<slug>'
148
+ ```
149
+ Or:
150
+ ```
151
+ -> SKIP: No plan §16 found — using manual test construction
152
+ ```
153
+
154
+ ## Dynamic Transition Discovery
155
+
156
+ Instead of hardcoding event sequences, use `workflow.transitions` to dynamically discover available actions at each state:
157
+
158
+ ```
159
+ 1. Create entity using discovered refs (via /fluent-test-data)
160
+ 2. workflow.transitions → get available actions at current status
161
+ 3. For each action:
162
+ a. event.send with eventName and required attributes from response
163
+ b. Poll entity status until transition completes
164
+ c. workflow.transitions → get next available actions
165
+ 4. Repeat until no more userActions
166
+
167
+ If `userActions` is empty, do **not** assume terminal immediately:
168
+ - It can also mean a system-managed/gated status.
169
+ - Verify entity status and recent events before concluding terminal.
170
+ - If status is non-terminal, continue via workflow/event-driven progression and trace checks.
171
+ ```
172
+
173
+ **Benefits:**
174
+ - Test sequences adapt automatically when workflows change
175
+ - Discovers required attributes for each event (avoids missing-attribute errors)
176
+ - Validates that expected user actions are available after deployment
177
+
178
+ **Example — discover actions at current status:**
179
+ ```
180
+ workflow.transitions({
181
+ triggers: [{
182
+ type: "ORDER",
183
+ subtype: "HD",
184
+ status: "<current_status>",
185
+ retailerId: "<discovered.retailerId>",
186
+ flexType: "ORDER::HD"
187
+ }]
188
+ })
189
+ ```
190
+
191
+ The response `userActions[].eventName` maps directly to `event.send`'s `name` parameter.
192
+ The response `userActions[].attributes` tells you what to include in `event.send`'s `attributes`.
193
+
194
+ ### Strict User Action Contract (Execution Guardrails)
195
+
196
+ Use this contract whenever tests rely on `workflow.transitions`:
197
+
198
+ 1. Treat `workflow.transitions` as the executable action contract for the current state.
199
+ 2. Send the event name exactly as returned in `userActions[].eventName` (never infer from labels).
200
+ 3. Send only `userActions[].attributes` with exact `name` and expected shape; do not invent keys.
201
+ 4. Keep trigger scope aligned: `type`, `subtype`, and `flexType` must match the entity and workflow branch.
202
+ 5. If an expected action is missing, retry with `module: "all"` to rule out module-visibility filters.
203
+ 6. If it appears under `module: "all"` but not under the target module, fix `context[].modules` and `fc.mystique.apps`.
204
+ 7. If `userActions` is still empty on a non-terminal status, verify workflow JSON has ruleset-level `userActions` with explicit `eventName`.
205
+
206
+ For canonical schema and diagnostics, cross-check `/fluent-workflow-builder` and `/fluent-transition-api`.
207
+
208
+ ## Poll-and-Assert Pattern
209
+
210
+ After sending an event, the entity status changes asynchronously. Use this pattern to wait:
211
+
212
+ ### Poll entity status until expected state (or timeout)
213
+
214
+ ```
215
+ 1. Send event via event.send (mode: "async")
216
+ 2. Wait 3 seconds (initial processing time)
217
+ 3. Query entity status via graphql.query
218
+ 4. If status matches expected → PASS
219
+ 5. If status doesn't match → wait 5 more seconds, retry (up to 12 retries = 60s total)
220
+ 6. If timeout → FAIL with "Expected <EXPECTED>, got <ACTUAL> after 60s"
221
+ ```
222
+
223
+ **Composite workflow note (ORDER::MULTI and similar):**
224
+ - After `ConfirmValidation`, use a longer wait window (20-30s) before first assertion.
225
+ - Fulfilment creation and aggregate gates can complete asynchronously in several hops.
226
+
227
+ ### Poll event status until processed
228
+
229
+ > For the complete event model, filter syntax, and execution semantics, see `/fluent-event-api`. This skill focuses on test choreography and assertion patterns.
230
+
231
+ ```
232
+ 1. After event.send, note the event details
233
+ 2. event.list filtered by entityRef + name + recent time window
234
+ 3. Check eventStatus: SUCCESS = processed, FAILED = error, PENDING = still processing
235
+ 4. If PENDING wait 5s and retry
236
+ 5. If FAILED report error details from event.get
237
+ ```
238
+
239
+ > **Canonical reference:** See `/fluent-event-api` for complete event status values, filter syntax, and query patterns.
240
+
241
+ ## Test Scenarios
242
+
243
+ ### Scenario: ORDER HD (Home Delivery) Full Lifecycle
244
+
245
+ **Pre-requisite:** Run `/fluent-test-data` discovery. Need: retailerId, warehouseRef, productRef, catalogueRef, customerId, consignmentPrefix.
246
+
247
+ **Entities created:** 1 ORDER with 1 HD fulfilment choice (all refs from discovery)
248
+
249
+ **Steps:**
250
+
251
+ | # | Action | Event | Expected Order Status | Expected Fulfilment Status |
252
+ |---|--------|-------|----------------------|---------------------------|
253
+ | 1 | Create order | *(via /fluent-test-data)* | CREATED → ON_VALIDATION | — |
254
+ | 2 | Confirm validation | `ConfirmValidation` on ORDER | ORDER_SPLIT → IN_PROGRESS | CREATED |
255
+ | 3 | Confirm allocation | `ConfirmAllocation` on FULFILMENT | IN_PROGRESS | RECEIVED |
256
+ | 4 | Create invoice | `CreateInvoice` on FULFILMENT | IN_PROGRESS | INVOICED |
257
+ | 5 | Confirm pick | `ConfirmPick` on FULFILMENT | IN_PROGRESS | PICKPACK → *(auto)* |
258
+ | 6 | Confirm shipment | `ConfirmShipment` on FULFILMENT | SHIPPED | SHIPPED |
259
+ | 7 | Confirm delivery | `ConfirmDelivery` on FULFILMENT | COMPLETED | DELIVERED |
260
+
261
+ **Step 1 Create Order:**
262
+
263
+ 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.
264
+
265
+ **Step 2 ConfirmValidation (triggers full cascade):**
266
+ ```
267
+ event.send({
268
+ name: "ConfirmValidation",
269
+ entityRef: "<order_ref>",
270
+ entityType: "ORDER",
271
+ retailerId: "<discovered.retailerId>"
272
+ })
273
+ ```
274
+
275
+ After this event, the async cascade runs automatically:
276
+ - ProcessOrder ORDER_SPLIT
277
+ - RouteFulfilmentChoice → ProcessHDFulfilmentChoice
278
+ - CreateFulfilmentFromSourcingLocation → creates FULFILMENT
279
+ - NotifyFCComplete SourceOrder → IN_PROGRESS
280
+
281
+ **Wait 15 seconds**, then verify:
282
+ - Order status = `IN_PROGRESS`
283
+ - Fulfilment exists with status = `CREATED`
284
+ - Query fulfilment ref for subsequent events
285
+
286
+ If fulfilment is not found, run fallback lookup sequence before failing:
287
+ 1. Query fulfilment from the order edge (`order.fulfilments`).
288
+ 2. Query fulfilment by order ID (`fulfilments(orderId: [...])`) if supported.
289
+ 3. Check event history for `FAILED` or `PENDING` events.
290
+ 4. Query `ORCHESTRATION_AUDIT` (`category=exception`) for rule-level errors.
291
+
292
+ **Steps 3-7Fulfilment events:**
293
+
294
+ Each fulfilment event follows the same pattern:
295
+ ```
296
+ event.send({
297
+ name: "<EVENT_NAME>",
298
+ entityRef: "<fulfilment_ref>",
299
+ entityType: "FULFILMENT",
300
+ retailerId: "<discovered.retailerId>",
301
+ attributes: { ... }
302
+ })
303
+ ```
304
+
305
+ Use `workflow.transitions` at each step to confirm what attributes are required. Common patterns:
306
+
307
+ | Event | Typical Attributes |
308
+ |-------|-------------------|
309
+ | `ConfirmAllocation` | *(check transitions response — often none)* |
310
+ | `CreateInvoice` | *(check transitions response — often none)* |
311
+ | `ConfirmPick` | `pickedAt` (ISO datetime), `pickedItems` (array of `{ ref, filledQuantity }` from discovered product refs) |
312
+ | `ConfirmShipment` | `trackingNumber` (generate: `E2E-TRACK-<TIMESTAMP>`), `carrierRef` (generate: `E2E-CARRIER`), `shippedAt` (ISO now) |
313
+ | `ConfirmDelivery` | `deliveredAt` (ISO now) |
314
+
315
+ ### Scenario: ORDER CC (Click & Collect)
316
+
317
+ **Pre-requisite:** Same as HD, but also need a store location (type=STORE) from discovery.
318
+
319
+ Same as HD through step 5 (ConfirmPick), then diverges:
320
+
321
+ | # | Event | Expected Fulfilment Status |
322
+ |---|-------|---------------------------|
323
+ | 6 | *(auto after pick)* | READY_FOR_PICKUP |
324
+ | 7 | `ConfirmCollection` on FULFILMENT | COLLECTED |
325
+ | — | *(auto)* | ORDER → COMPLETED |
326
+
327
+ ### Scenario: Cancel Order
328
+
329
+ | # | Action | Event | Expected Status |
330
+ |---|--------|-------|----------------|
331
+ | 1 | Create order | *(via /fluent-test-data)* | ON_VALIDATION |
332
+ | 2 | Cancel | `CancelOrder` on ORDER | CANCELLED |
333
+
334
+ ### Scenario: Short Pick
335
+
336
+ | # | Action | Expected Fulfilment Status |
337
+ |---|--------|---------------------------|
338
+ | 1-4 | Normal flow through INVOICED | INVOICED |
339
+ | 5 | `ConfirmPick` with `pickedItems` where `filledQuantity < requestedQuantity` | PARTIAL |
340
+
341
+ ### Scenario: Dynamic (Workflow-Driven)
342
+
343
+ For custom or unknown workflows, use fully dynamic discovery:
344
+
345
+ ```
346
+ 1. Run /fluent-test-data discovery
347
+ 2. Create entity using discovered refs
348
+ 3. Loop:
349
+ a. workflow.transitions for current entity state
350
+ b. If no userActions:
351
+ - verify status category and recent events first
352
+ - stop only when entity is confirmed terminal
353
+ c. Pick first userAction (or specific one by label)
354
+ d. event.send with eventName + required attributes from response
355
+ e. Poll until entity transitions
356
+ f. Go to (a)
357
+ 4. Report all transitions walked
358
+ ```
359
+
360
+ This approach works for ANY workflow without knowing the state machine in advance.
361
+
362
+ ## Test Report Format
363
+
364
+ After running a scenario, output a structured report:
365
+
366
+ ```
367
+ === E2E Test Report ===
368
+ Scenario: ORDER HD Full Lifecycle
369
+ Order Ref: <generated_ref>
370
+ Retailer: <discovered.retailerRef> (ID: <discovered.retailerId>)
371
+ Start Time: <ISO timestamp>
372
+
373
+ Discovery:
374
+ Warehouse: <discovered.warehouseRef>
375
+ Product: <discovered.productRef> (catalogue: <discovered.catalogueRef>)
376
+ Customer: <discovered.customerId>
377
+
378
+ Step 1: Create Order
379
+ Action: createOrder mutation (refs from live discovery)
380
+ Result: PASS — Order created, ID=<id>, status=CREATED
381
+ Duration: <N>s
382
+
383
+ Step 2: ConfirmValidation IN_PROGRESS
384
+ Action: event.send ConfirmValidation
385
+ Expected: Order=IN_PROGRESS, Fulfilment=CREATED
386
+ Actual: Order=IN_PROGRESS, Fulfilment=CREATED (ref: <fulfilment_ref>)
387
+ Result: PASS
388
+ Duration: <N>s (async cascade)
389
+
390
+ ...
391
+
392
+ === Summary ===
393
+ Steps: N/N passed
394
+ Total Duration: <N>s
395
+ Result: ALL PASSED
396
+ ```
397
+
398
+ ## Post-Test Event Analysis
399
+
400
+ 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.
401
+
402
+ > **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.
403
+
404
+ ### Snapshot Verification
405
+
406
+ Use entity snapshots from ORCHESTRATION_AUDIT events to verify entity state at each transition without additional GraphQL queries:
407
+
408
+ > **Event filter reference:** For complete filter syntax, see `/fluent-event-api`.
409
+
410
+ ```
411
+ event.list({
412
+ "eventType": "ORCHESTRATION_AUDIT",
413
+ "context.rootEntityRef": "<ORDER_REF>",
414
+ "count": 200
415
+ })
416
+ ```
417
+
418
+ 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.
419
+
420
+ **Verification pattern:**
421
+ ```
422
+ For each test step that passed:
423
+ 1. Find the snapshot event for that entity at the expected status
424
+ 2. Verify key fields:
425
+ - Items count and quantities match expected
426
+ - Attributes set by previous steps are present (e.g., trackingNumber after ConfirmShipment)
427
+ - Customer/address data is correctly attached
428
+ - Child entity refs (fulfilmentChoice, fulfilment) are populated
429
+ 3. If a step failed, compare the snapshot against expected to identify what was different
430
+ ```
431
+
432
+ ### Mutation Verification
433
+
434
+ Extract all mutations executed during the test to verify the workflow made the correct GraphQL calls:
435
+
436
+ Filter ORCHESTRATION_AUDIT events where `name` is null and `attributes` contains `request.queryString`. Each mutation event shows the exact GraphQL mutation and input variables.
437
+
438
+ This catches issues where:
439
+ - A rule set the wrong status (mutation input has unexpected status value)
440
+ - A rule updated the wrong entity (mutation targets a different entity ID)
441
+ - Expected attribute updates were not made (mutation input missing expected fields)
442
+
443
+ ### Webhook Delivery Verification
444
+
445
+ After test completion, verify all expected webhooks were delivered:
446
+
447
+ Filter ORCHESTRATION_AUDIT events where `name == "Send Webhook"`. Check `Response code` for each:
448
+ - `200` = delivered successfully
449
+ - `404` = endpoint not found (check setting)
450
+ - `0` = connection timeout (check endpoint availability)
451
+
452
+ Include webhook delivery results in the test report as an additional validation layer.
453
+
454
+ ### Enhanced Test Report (with event analysis)
455
+
456
+ After the standard test report, append an event analysis section:
457
+
458
+ ```
459
+ === Event Analysis ===
460
+
461
+ Mutations: 7 total (all successful)
462
+ Webhooks: 4 sent (3 delivered, 1 failed — webhook.fulfilment.shipped → 404)
463
+ Snapshots: 3 captured (ORDER@CREATED, FULFILMENT@CREATED, FULFILMENT@PICKPACK)
464
+ Scheduled Events: 1 (ValidationGraceExpired, 30s delay, pre-empted by ConfirmValidation)
465
+ NO_MATCH Events: 1 (ValidationGraceExpired → expected, timer pre-empted)
466
+ Custom Logs: 4 entries (3 INFO, 1 WARN)
467
+
468
+ Recommendation: Fix webhook setting "webhook.fulfilment.shipped" before go-live
469
+ ```
470
+
471
+ ## Session Tracking
472
+
473
+ When invoked, log the following to the session tracking protocol (consumed by `/fluent-session-summary` and `/fluent-session-audit-export`):
474
+
475
+ **On entry:**
476
+ ```json
477
+ { "skill": "<this-skill-name>", "timestamp": "<ISO-8601>", "arguments": { "<key>": "<value>", "...": "..." } }
478
+ ```
479
+
480
+ **On exit:**
481
+ ```json
482
+ { "skill": "<this-skill-name>", "outcome": "<completed|failed|skipped>", "changesProduced": ["<seq-numbers>"], "toolCallsProduced": ["<seq-numbers>"], "nextRecommended": "<from-handoff-section>" }
483
+ ```
484
+
485
+ All MCP tool calls made during execution should include `"skill": "<this-skill-name>"` in their tracking record for attribution. The `arguments` object should capture the key parameters actually passed (profile, retailer, entity type, etc.) — not a fixed schema. The `nextRecommended` value comes from the Handoff section below.
486
+
487
+ ## Tips
488
+
489
+ - **Always run /fluent-test-data discovery first** — Never assume refs exist
490
+ - **Use unique refs per test run** — Include timestamp or counter to avoid collisions
491
+ - **Wait 15s after ConfirmValidation** — The async cascade creates FC → fulfilment → gates, all in sequence
492
+ - **For composite workflows, poll up to 60s** — CREATE/validation cascades can take longer than single-entity flows
493
+ - **Wait 5-10s between fulfilment events** — Async processing needs time
494
+ - **Always query fulfilment ref** after step 2 — The ref is generated by the workflow (pattern varies by implementation)
495
+ - **Check event.list if a step fails** — Filter by entityRef + eventStatus=FAILED to see error details
496
+ - **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.
497
+ - **If `workflow.transitions` returns empty `userActions` on non-terminal statuses** — run strict diagnostics first (subtype/flexType alignment, `module: "all"` retry, explicit `eventName` and valid `context[].modules`), then continue workflow/event-driven progression and trace checks; do not stop early
498
+ - **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
499
+ - **If tests fail post-deployment, consider `/fluent-rollback`** — Revert to the previous known-good state while investigating root cause. This is especially useful when a deployment introduced a regression and you need to restore service quickly
500
+ - **Use event.send with mode: "async"** — Synchronous mode is not recommended for workflow events
501
+ - **Use `workflow.transitions`** to discover required attributes at each step instead of guessing