@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,319 +1,668 @@
1
- ---
2
- name: fluent-workflow-builder
3
- description: Create and edit Fluent Commerce workflow JSON definitions. Build rulesets, states, transitions, and triggers. Validate structure before upload. Triggers on "build workflow", "create workflow", "add ruleset", "edit workflow", "workflow json".
4
- user-invocable: true
5
- allowed-tools: Bash, Read, Write, Edit, Glob, Grep
6
- argument-hint: <operation> [workflow-name]
7
- ---
8
-
9
- # Workflow Builder
10
-
11
- Create, edit, and validate Fluent Commerce workflow JSON definitions.
12
-
13
- ## Planning Gate
14
-
15
- **Before creating or modifying any workflow, write a plan using the template from `PLAN_TEMPLATE.md` in the `fluent-feature-plan` skill.** Every table row must carry a Source column (NEW/EXISTING/MODIFIED/REUSED/OOTB).
16
-
17
- **If this workflow change is part of a larger feature** (rules + settings + webhooks), use `/fluent-feature-plan` first. Then reference the approved plan during implementation.
18
-
19
- **Workflow-builder specific emphasis ensure these are covered:**
20
-
21
- 1. **Business Context (§1)**what business flow this workflow enables or modifies
22
- 2. **State machine (§3.1)** — Mermaid `stateDiagram-v2` with ALL statuses; annotate `:::added`, `:::removed`, `:::modified`. Validate syntax per `/fluent-mermaid-validate`
23
- 3. **Cross-entity flow (§3.2)** — Mermaid `sequenceDiagram` for cross-entity event chains, webhooks, external systems. Validate syntax per `/fluent-mermaid-validate`
24
- 4. **Before/After diff (§3.4)** — if modifying, show changes (or use `workflow.diff`)
25
- 5. **Workflows (§4)** — every workflow created or modified with Source column and current version
26
- 6. **Statuses (§5)** — new/modified statuses with Source column, entity type, which ruleset adds them
27
- 7. **Rulesets (§6)** — rulesets with Source column, trigger event, from/to status, ordered rule list with NEW/OOTB/EXISTING annotations
28
- 8. **Rules Inventory (§7)** — all rules with Source classification
29
- 9. **Settings (§9)** settings with Source column, context, value type, JSON example for NEW
30
- 10. **Webhooks (§10)**setting name, method, payload shape, trigger rule
31
- 11. **Scheduled Events11)** event name, delay, purpose
32
- 12. **GraphQL Operations (§12)** queries/mutations marked as NEW or REUSED pattern
33
- 13. **Deployment Sequence (§17)** — modules before workflows that reference new rules
34
-
35
- **Write the plan to:** `accounts/<PROFILE>/plans/<YYYY-MM-DD>-workflow-builder-<slug>.md`. Set `Status: PENDING`.
36
-
37
- Present the full plan content to the user and wait for approval before writing any workflow JSON. On approval, update the file to `Status: APPROVED`. If the user says "just do it", proceed directly (still write the file for audit trail).
38
-
39
- ## Ownership Boundary
40
-
41
- This skill owns workflow structure/design guidance and validation checklists.
42
-
43
- Operational workflow commands are owned by `/fluent-workflow`:
44
-
45
- - `workflow list`
46
- - `workflow download`
47
- - `workflow merge`
48
- - `workflowlog` operations
49
-
50
- ## Pre-Check: Load Source Analysis
51
-
52
- Before adding custom rules to a workflow, check if `/fluent-custom-code` analysis artifacts exist:
53
-
54
- ```
55
- accounts/<PROFILE>/analysis/custom-code/workflow-rule-map.json
56
- accounts/<PROFILE>/analysis/custom-code/source-map.json
57
- accounts/<PROFILE>/analysis/custom-code/constraints.json
58
- ```
59
-
60
- If found, use them to:
61
- - `source-map.json` `modules[].rules[]` available custom rules, their parameters, and entity types
62
- - `workflow-rule-map.json` existing rule-to-workflow bindings (avoid duplicates)
63
- - `constraints.json` extension constraints and risks
64
-
65
- If not found, fall back to workflow JSON analysis only. Treat artifact-gate failures the same as "not found" (for example missing required files, missing hashes, or blocking `missingSources` in `constraints.json`). Suggest running `/fluent-custom-code <PROFILE>` first when adding custom rules.
66
-
67
- ## When to Use
68
-
69
- - Creating a new workflow from scratch
70
- - Adding rulesets or states to an existing workflow
71
- - Editing triggers, rules, or gate conditions
72
- - Validating workflow JSON before upload
73
- - Generating workflow fragments for merge operations
74
-
75
- ## Workflow JSON Structure
76
-
77
- Every Fluent workflow follows this schema:
78
-
79
- ```json
80
- {
81
- "retailerId": "<retailer-id>",
82
- "version": "<semver>",
83
- "entityType": "ORDER | FULFILMENT | RETURN_ORDER | ARTICLE | WAVE | ...",
84
- "entitySubtype": "<subtype matching workflow name after ::>",
85
- "name": "<ENTITY_TYPE>::<SUBTYPE>",
86
- "description": "<human-readable description>",
87
- "versionComment": "<what changed in this version>",
88
- "createdBy": "<retailer-ref>",
89
- "rulesets": [ ... ],
90
- "statuses": [ ... ]
91
- }
92
- ```
93
-
94
- ### Ruleset Structure
95
-
96
- ```json
97
- {
98
- "name": "<RulesetName>",
99
- "description": "[<ENTITY_TYPE>] What this ruleset does",
100
- "type": "<ENTITY_TYPE>",
101
- "eventType": "NORMAL",
102
- "rules": [
103
- {
104
- "name": "<ACCOUNT>.<MODULE>.<RuleName>",
105
- "props": {
106
- "key": "value"
107
- }
108
- }
109
- ],
110
- "triggers": [
111
- { "status": "<STATUS>" }
112
- ],
113
- "userActions": []
114
- }
115
- ```
116
-
117
- ### Trigger Types
118
-
119
- Rulesets are triggered by one of:
120
-
121
- | Trigger | When it fires |
122
- |---------|---------------|
123
- | `{ "status": "CREATED" }` | Entity enters CREATED status (platform CREATE event) |
124
- | `{ "status": "ON_VALIDATION" }` | Entity enters ON_VALIDATION status |
125
- | No status trigger | Ruleset is triggered by a named event matching the ruleset name |
126
-
127
- **Convention:** If a ruleset has no `status` trigger, it fires when an event with `name` matching the ruleset name arrives. For example, ruleset `ConfirmValidation` fires on event `ConfirmValidation`.
128
-
129
- ### Statuses Array
130
-
131
- ```json
132
- {
133
- "statuses": [
134
- { "name": "CREATED", "category": "BOOKING", "entityType": "ORDER" },
135
- { "name": "ON_VALIDATION", "category": "BOOKING", "entityType": "ORDER" },
136
- { "name": "COMPLETE", "category": "DONE", "entityType": "ORDER" }
137
- ]
138
- }
139
- ```
140
-
141
- Categories: `BOOKING`, `FULFILMENT`, `DONE`, `PAYMENT`
142
-
143
- ## Common Rule Patterns
144
-
145
- ### Core Rules (provided by Fluent platform)
146
-
147
- | Rule | Props | Purpose |
148
- |------|-------|---------|
149
- | `<ACCOUNT>.core.SetState` | `status` | Transition entity to new status |
150
- | `<ACCOUNT>.core.SendEvent` | `eventName` | Fire a named event on current entity |
151
- | `<ACCOUNT>.core.SendEventOnVerifyingEntityStatus` | `eventName`, `statuses` (comma-separated) | Fire event only if entity is in one of the listed statuses |
152
- | `<ACCOUNT>.core.SendEventOnVerifyingAllFcStatus` | `eventName`, `statuses` (comma-separated) | Gate: fire event when ALL fulfilment choices reach one of the listed statuses |
153
- | `<ACCOUNT>.core.ScheduleEvent` | `eventName`, `delay` (seconds) | Schedule a delayed event |
154
- | `<ACCOUNT>.core.IfEventAttributeValueIsEqual` | `eventAttributeName`, `eventAttributeValue`, `eventName` | Conditional: fire event if attribute matches |
155
-
156
- ### Extension Rules (from custom extension module)
157
-
158
- | Rule | Key Props | Purpose |
159
- |------|-----------|---------|
160
- | `<ACCOUNT>.<MODULE>.UpdateStatusHistory` | `toStatus` | Track status transition in attribute |
161
- | `<ACCOUNT>.<MODULE>.SendWebhookWithDynamicAttributes` | `setting` | Send webhook with config from Setting |
162
- | `<ACCOUNT>.<MODULE>.UpdateEntityFromSetting` | `setting` | Batch-update entity from event data via Setting |
163
- | `<ACCOUNT>.<MODULE>.CreateFulfilmentFromSourcingLocation` | *(from event attrs)* | Create fulfilment from sourcing data |
164
- | `<ACCOUNT>.<MODULE>.UpsertAttribute` | `attributeName`, `attributeType`, `attributeValue` | Set entity attribute |
165
- | `<ACCOUNT>.<MODULE>.UpsertAttributeFromPath` | `jsonpath`, `attributeName`, `attributeType` | Extract value via JSON path and set as attribute |
166
-
167
- ## Plan Before Building
168
-
169
- **Before creating or editing any workflow, present an implementation plan to the user.** The plan should include:
170
-
171
- 1. **State machine design** — All statuses and transitions, shown as a Mermaid `stateDiagram-v2`
172
- 2. **Ruleset inventory** Every ruleset with its trigger condition, rules, and purpose
173
- 3. **Settings dependencies** — Any settings referenced by rules (webhook URLs, thresholds, feature flags)
174
- 4. **Custom rule requirements** — Any new Java rules needed (entity type, parameters, behavior)
175
- 5. **Cross-entity interactions** — How this workflow interacts with other entity workflows (e.g., ORDER → FULFILMENT)
176
- 6. **Deployment sequence** — What gets deployed in what order
177
-
178
- For workflow edits, additionally show:
179
- - **Before/after diff** — What rulesets are being added, removed, or modified
180
- - **Before/after Mermaid diagrams** — Visual comparison of the state machine changes
181
- - **Risk assessment** — Impact of changes on existing live entities
182
-
183
- **Wait for user approval before making any changes to workflow JSON files.**
184
-
185
- ## Building a New Workflow
186
-
187
- ### Step 1: Determine entity type and subtype
188
-
189
- ```
190
- Workflow name = <ENTITY_TYPE>::<SUBTYPE>
191
- Example: ORDER::HD, FULFILMENT::DEFAULT, RETURN_ORDER::DEFAULT
192
- ```
193
-
194
- ### Step 2: Design the state machine
195
-
196
- List all statuses and the events/rules that transition between them. Example:
197
-
198
- ```
199
- CREATED [CREATE ruleset] ON_VALIDATION
200
- ON_VALIDATION → [ConfirmValidation event] → IN_PROGRESS
201
- IN_PROGRESS [ConfirmShipment event] SHIPPED
202
- SHIPPED → [ConfirmDelivery event] → COMPLETE
203
- ```
204
-
205
- ### Step 3: Build each ruleset
206
-
207
- For each transition, create a ruleset with:
208
- 1. The rules to execute (in order — rules run sequentially)
209
- 2. A trigger (status trigger for the first ruleset, event-name trigger for the rest)
210
-
211
- ### Step 4: Add gate rulesets (if needed)
212
-
213
- Gates check child entity statuses before advancing parent. Example:
214
-
215
- ```json
216
- {
217
- "name": "NotifyFCComplete",
218
- "description": "Gate: advance order when all FCs reach terminal status",
219
- "type": "ORDER",
220
- "eventType": "NORMAL",
221
- "rules": [
222
- {
223
- "name": "ACCT.core.SendEventOnVerifyingAllFcStatus",
224
- "props": {
225
- "eventName": "SourceOrder",
226
- "statuses": "ASSIGNED,CANCELLED,ESCALATED"
227
- }
228
- }
229
- ],
230
- "triggers": [],
231
- "userActions": []
232
- }
233
- ```
234
-
235
- ### Step 5: Validate structure
236
-
237
- Before uploading, verify:
238
- - [ ] Every status referenced in triggers exists in the `statuses` array
239
- - [ ] Every `SetState` target status exists in the `statuses` array
240
- - [ ] Every `SendEvent` target has a matching ruleset name (or is handled elsewhere)
241
- - [ ] Rule names follow `<ACCOUNT>.<MODULE>.<RuleName>` format
242
- - [ ] No duplicate ruleset names
243
- - [ ] Version is bumped from previous
244
-
245
- ## Editing an Existing Workflow
246
-
247
- ### Get current workflow first
248
-
249
- Use `/fluent-workflow` for download/list operations, then apply this skill's structure and validation patterns.
250
-
251
- ### Make changes
252
-
253
- Edit the JSON directly. Common operations:
254
-
255
- **Add a new ruleset:**
256
- ```json
257
- {
258
- "name": "NewRulesetName",
259
- "description": "[ORDER] What it does",
260
- "type": "ORDER",
261
- "eventType": "NORMAL",
262
- "rules": [ ... ],
263
- "triggers": [ { "status": "IN_PROGRESS" } ],
264
- "userActions": []
265
- }
266
- ```
267
-
268
- **Add a rule to existing ruleset:**
269
- Find the ruleset in the `rulesets` array, append to its `rules` array.
270
-
271
- **Change a gate condition:**
272
- Find the gate ruleset, update the `statuses` prop value.
273
-
274
- ### Upload/merge
275
-
276
- Use `/fluent-workflow-deploy` for uploading workflows to environments (MCP tool primary, REST API fallback). Use `/fluent-workflow` for listing, downloading, and merging workflows. Use `/fluent-module-deploy` for deploying full module bundles (JAR + settings + workflows together).
277
-
278
- **Important:** If the workflow references new custom rules, deploy the module first via `/fluent-module-deploy` before uploading the workflow. Unregistered rules cause NO_MATCH events at runtime.
279
-
280
- ## Workflow Fragments
281
-
282
- Fragments are partial workflow definitions used with `fluent workflow merge`:
283
-
284
- ```json
285
- {
286
- "name": "my-customization",
287
- "description": "Add custom validation step",
288
- "rulesets": [
289
- {
290
- "name": "CustomValidation",
291
- "description": "Custom validation ruleset",
292
- "type": "ORDER",
293
- "eventType": "NORMAL",
294
- "rules": [ ... ],
295
- "triggers": [ ... ],
296
- "userActions": []
297
- }
298
- ],
299
- "statuses": [
300
- { "name": "CUSTOM_VALIDATING", "category": "BOOKING", "entityType": "ORDER" }
301
- ]
302
- }
303
- ```
304
-
305
- Merge adds the fragment's rulesets and statuses to the base workflow. Use this for modular customizations.
306
-
307
- ## Validation Checklist
308
-
309
- Run through this before uploading any workflow:
310
-
311
- 1. **JSON syntax** Valid JSON (no trailing commas, correct brackets)
312
- 2. **Required fields** `retailerId`, `version`, `entityType`, `entitySubtype`, `name`, `rulesets`
313
- 3. **Status coverage** Every SetState target exists in `statuses`
314
- 4. **Event coverage** Every SendEvent target has a matching ruleset (or is expected inbound)
315
- 5. **Trigger consistency** Only one ruleset per status trigger (avoid conflicts)
316
- 6. **Rule naming** `<ACCOUNT>.<MODULE>.<RuleName>` format, all referenced rules exist in platform
317
- 7. **Gate logic** Gate statuses include all terminal states for child entities
318
- 8. **Version bump** Version is higher than currently deployed version
319
- 9. **Description** — `versionComment` describes what changed
1
+ ---
2
+ name: fluent-workflow-builder
3
+ description: Create and edit Fluent Commerce workflow JSON definitions. Build rulesets, states, transitions, and triggers. Validate structure before upload. Triggers on "build workflow", "create workflow", "add ruleset", "edit workflow", "workflow json".
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
6
+ argument-hint: <operation> [workflow-name]
7
+ ---
8
+
9
+ # Workflow Builder
10
+
11
+ Create, edit, and validate Fluent Commerce workflow JSON definitions.
12
+
13
+ ## Pre-flight: Feedback Check
14
+
15
+ Before starting, check for past learnings from this skill:
16
+
17
+ 1. Check if `accounts/<PROFILE>/feedback/fluent-workflow-builder.jsonl` exists
18
+ 2. If yes, read last 20 records
19
+ 3. Filter to: same entity type/subtype if known, FAILURE or USER_CORRECTED outcomes, confidence = CONFIRMED or PROMOTED
20
+ 4. Extract top 3 relevant learnings — use as internal "WATCH OUT" guidance during execution
21
+ 5. Do NOT show raw feedback to the user silently adjust approach based on past issues
22
+
23
+ ## Planning Gate
24
+
25
+ ### Pre-flight: Plan Verification
26
+
27
+ Before proceeding, check for an existing approved plan:
28
+
29
+ 1. **Search** `accounts/<PROFILE>/features/*/status.json` for an entry with `plan: "APPROVED"` that covers this workflow, OR check `accounts/<PROFILE>/tasks/` for a task plan with `Status: APPROVED`
30
+ 2. **If multi-artifact work** (workflow + rules + settings): STOP. Invoke `/fluent-feature-plan` first this skill cannot be used for multi-artifact work without a feature plan
31
+ 3. **If approved plan found:** Skip to implementation, referencing the plan's §4 (Workflows), §5 (Statuses), and §6 (Rulesets) sections
32
+ 4. **If single-workflow-only work with no plan:** Continue to the Planning Gate below to write a plan for this skill
33
+
34
+ **Before creating or modifying any workflow, write a plan using the template from `PLAN_TEMPLATE.md` in the `fluent-feature-plan` skill.** Every table row must carry a Source column (NEW/EXISTING/MODIFIED/REUSED/OOTB).
35
+
36
+ **If this workflow change is part of a larger feature** (rules + settings + webhooks), use `/fluent-feature-plan` first. Then reference the approved plan during implementation.
37
+
38
+ **Workflow-builder specific emphasis — ensure these are covered:**
39
+
40
+ 1. **Business Context (§1)** — what business flow this workflow enables or modifies
41
+ 2. **State machine (§3.1)** Mermaid `stateDiagram-v2` with ALL statuses; annotate `:::added`, `:::removed`, `:::modified`. Validate syntax per `/fluent-mermaid-validate`
42
+ 3. **Cross-entity flow (§3.2)** — Mermaid `sequenceDiagram` for cross-entity event chains, webhooks, external systems. Validate syntax per `/fluent-mermaid-validate`
43
+ 4. **Before/After diff (§3.4)** if modifying, show changes (or use `workflow.diff`)
44
+ 5. **Workflows (§4)** — every workflow created or modified with Source column and current version
45
+ 6. **Statuses (§5)** — new/modified statuses with Source column, entity type, which ruleset adds them
46
+ 7. **Rulesets (§6)** — rulesets with Source column, trigger event, from/to status, ordered rule list with NEW/OOTB/EXISTING annotations
47
+ 8. **Rules Inventory (§7)** — all rules with Source classification
48
+ 9. **Settings (§9)** — settings with Source column, context, value type, JSON example for NEW
49
+ 10. **Webhooks (§10)** — setting name, method, payload shape, trigger rule
50
+ 11. **Scheduled Events (§11)** — event name, delay, purpose
51
+ 12. **GraphQL Operations (§12)** — queries/mutations marked as NEW or REUSED pattern
52
+ 13. **Deployment Sequence (§17)** modules before workflows that reference new rules
53
+
54
+ **Write the plan to:** `accounts/<PROFILE>/tasks/<YYYY-MM-DD>-workflow-builder-<slug>.md`. Set `Status: PENDING`.
55
+
56
+ Present the full plan content to the user and wait for approval before writing any workflow JSON. On approval, update the file to `Status: APPROVED`. If the user says "just do it", proceed directly (still write the file for audit trail).
57
+
58
+ ## Post-Build: Workflow Validation
59
+
60
+ After building or modifying any workflow JSON, **always recommend running `/fluent-workflow-analyzer`** to validate for:
61
+ - Orphaned rulesets (triggers that can never fire)
62
+ - Trigger conflicts (duplicate event+status combinations)
63
+ - Missing rule references (rules not in `plugin.list`)
64
+ - Structural issues (statuses without transitions, unreachable states)
65
+
66
+ If the user skips this step, `/fluent-pre-deploy-check` will enforce it before deployment. But catching issues early avoids wasted deploy cycles.
67
+
68
+ ## Ownership Boundary
69
+
70
+ This skill owns workflow structure/design guidance and validation checklists.
71
+
72
+ Operational workflow commands are owned by `/fluent-workflow`:
73
+
74
+ - `workflow list`
75
+ - `workflow download`
76
+ - `workflow merge`
77
+ - `workflowlog` operations
78
+
79
+ ## Pre-flight: Custom Rule Availability
80
+
81
+ Before building or modifying a workflow that references custom rules, verify those rules are deployed:
82
+
83
+ 1. **Identify custom rules** in the plan's §7 (Rules Inventory) any rule with Source = NEW, MODIFIED, or EXISTING that is NOT `FLUENTRETAIL.*`
84
+ 2. **For each custom rule**, query: `plugin.list({ name: "<RuleName>" })`
85
+ 3. **If ALL custom rules found:** Proceed — rules are registered and available.
86
+ 4. **If ANY custom rule is MISSING:** **STOP.** Inform the user: *"Custom rule `<RuleName>` is not registered. Deploy the module first via `/fluent-build` → `/fluent-module-deploy`, then resume workflow editing."*
87
+ 5. **Exception:** If the workflow is being built as part of a feature plan where module deployment comes later (§17 Deployment Sequence), note the dependency and proceed — but add a `DEPLOYMENT_ORDER_WARNING` comment in the plan.
88
+
89
+ This check prevents deploying workflows that reference unregistered rules, which causes runtime `NO_MATCH` failures.
90
+
91
+ ## Pre-Check: Load Source Analysis
92
+
93
+ Before adding custom rules to a workflow, check if `/fluent-custom-code` analysis artifacts exist:
94
+
95
+ ```
96
+ accounts/<PROFILE>/analysis/code/workflow-rule-map.json
97
+ accounts/<PROFILE>/analysis/code/source-map.json
98
+ accounts/<PROFILE>/analysis/code/constraints.json
99
+ ```
100
+
101
+ If found, use them to:
102
+ - `source-map.json` → `modules[].rules[]` — available custom rules, their parameters, and entity types
103
+ - `workflow-rule-map.json` → existing rule-to-workflow bindings (avoid duplicates)
104
+ - `constraints.json` → extension constraints and risks
105
+
106
+ If not found, fall back to workflow JSON analysis only. Treat artifact-gate failures the same as "not found" (for example missing required files, missing hashes, or blocking `missingSources` in `constraints.json`). Suggest running `/fluent-custom-code <PROFILE>` first when adding custom rules.
107
+
108
+ ## Handoff Protocol
109
+
110
+ ### Signals emitted by this skill
111
+
112
+ | Signal | Condition | Example |
113
+ |--------|-----------|---------|
114
+ | `-> READY: <path>` | Workflow JSON created/modified | `-> READY: accounts/HMDEV/workflows/HM_TEST/ORDER__HD.json` |
115
+ | `-> NEXT: /fluent-<skill>` | Always validate after build | `-> NEXT: /fluent-workflow-analyzer` |
116
+ | `-> BLOCKED: <reason>` | Prerequisite missing | `-> BLOCKED: PREREQ_MISSING — Custom rule CancelOrderRule not registered. Run /fluent-build + /fluent-module-deploy` |
117
+ | `-> SKIP: <reason>` | No workflow changes needed | `-> SKIP: No workflow changes in this feature plan` |
118
+
119
+ ### Error codes
120
+
121
+ | Code | Condition | Recovery |
122
+ |------|-----------|----------|
123
+ | `PLAN_REQUIRED` | Multi-artifact work attempted without approved plan | Run `/fluent-feature-plan` first |
124
+ | `PREREQ_MISSING` | Custom rules not deployed or source analysis missing | Deploy module first via `/fluent-build` + `/fluent-module-deploy` |
125
+ | `VALIDATION_FAILED` | Workflow JSON structure invalid | Fix JSON structure per validation checklist |
126
+
127
+ ## When to Use
128
+
129
+ - Creating a new workflow from scratch
130
+ - Adding rulesets or states to an existing workflow
131
+ - Editing triggers, rules, or gate conditions
132
+ - Validating workflow JSON before upload
133
+ - Generating workflow fragments for merge operations
134
+
135
+ ## Progress
136
+
137
+ Emit this block at each phase transition to show progress:
138
+
139
+ ```
140
+ ▸ /fluent-workflow-builder [1/5]
141
+ Entity type & subtype → Design state machine
142
+ ○ Build rulesets ○ Add gate rulesets
143
+ Validate structure
144
+ ```
145
+
146
+ Update the block as each phase completes — mark completed phases with `✓`, the active phase with `→`, and remaining phases with `○`. Replace `[1/5]` with the current phase number.
147
+
148
+ ## Workflow JSON Structure
149
+
150
+ Every Fluent workflow follows this schema:
151
+
152
+ ```json
153
+ {
154
+ "retailerId": "<retailer-id>",
155
+ "version": "<semver>",
156
+ "entityType": "ORDER | FULFILMENT | RETURN_ORDER | ARTICLE | WAVE | ...",
157
+ "entitySubtype": "<subtype matching workflow name after ::>",
158
+ "name": "<ENTITY_TYPE>::<SUBTYPE>",
159
+ "description": "<human-readable description>",
160
+ "versionComment": "<what changed in this version>",
161
+ "createdBy": "<retailer-ref>",
162
+ "rulesets": [ ... ],
163
+ "statuses": [ ... ]
164
+ }
165
+ ```
166
+
167
+ ### Ruleset Structure
168
+
169
+ ```json
170
+ {
171
+ "name": "<RulesetName>",
172
+ "description": "[<ENTITY_TYPE>] What this ruleset does",
173
+ "type": "<ENTITY_TYPE>",
174
+ "subtype": "<ENTITY_SUBTYPE>",
175
+ "eventType": "NORMAL",
176
+ "rules": [
177
+ {
178
+ "name": "<ACCOUNT>.<MODULE>.<RuleName>",
179
+ "props": {
180
+ "key": "value"
181
+ }
182
+ }
183
+ ],
184
+ "triggers": [
185
+ { "status": "<STATUS>" }
186
+ ],
187
+ "userActions": []
188
+ }
189
+ ```
190
+
191
+ ### Trigger Types
192
+
193
+ Rulesets are triggered by one of:
194
+
195
+ | Trigger | When it fires |
196
+ |---------|---------------|
197
+ | `{ "status": "CREATED" }` | Entity enters CREATED status (platform CREATE event) |
198
+ | `{ "status": "ON_VALIDATION" }` | Entity enters ON_VALIDATION status |
199
+ | No status trigger | Ruleset is triggered by a named event matching the ruleset name |
200
+
201
+ **Convention:** If a ruleset has no `status` trigger, it fires when an event with `name` matching the ruleset name arrives. For example, ruleset `ConfirmValidation` fires on event `ConfirmValidation`.
202
+
203
+ ### User Actions
204
+
205
+ User actions link UI buttons to workflow rulesets. When a user clicks the button, an event is sent via `/event/sync` to trigger the ruleset.
206
+
207
+ **Schema:**
208
+
209
+ ```json
210
+ {
211
+ "userActions": [
212
+ {
213
+ "eventName": "<EventName>",
214
+ "context": [
215
+ {
216
+ "label": "<Button Label>",
217
+ "type": "PRIMARY",
218
+ "modules": ["adminconsole"],
219
+ "confirm": true
220
+ }
221
+ ],
222
+ "attributes": []
223
+ }
224
+ ]
225
+ }
226
+ ```
227
+
228
+ **Field reference:**
229
+
230
+ | Field | Type | Required | Description |
231
+ |-------|------|----------|-------------|
232
+ | `eventName` | String | No | Event name sent when button is clicked. If omitted, defaults to the **ruleset name**. Strict recommendation: set it explicitly for every user action and keep it aligned with the ruleset name unless intentionally different. |
233
+ | `context` | Array | Yes | Where and how the button appears. At least one entry required. |
234
+ | `context[].label` | String | Yes | Button text shown in the UI |
235
+ | `context[].type` | String | Yes | `"PRIMARY"` (prominent) or `"SECONDARY"` (overflow menu / ellipsis) |
236
+ | `context[].modules` | Array | Yes | Which UI apps show the button: `"adminconsole"` (OMS), `"store"` (Store App), `"servicepoint"` (Service Point), or any custom manifest app name (the suffix after `fc.mystique.manifest.`) |
237
+ | `context[].confirm` | Boolean | Yes | Whether the UI shows a confirmation dialog before sending the event |
238
+ | `attributes` | Array | No | Attributes collected via the confirmation dialog. Empty array if no input needed. |
239
+
240
+ ### Strict User Action Contract (Non-Negotiable)
241
+
242
+ Use these guardrails to prevent configuration drift and hallucinated schema fields.
243
+
244
+ 1. `userActions` MUST be inside the ruleset object (never at workflow root).
245
+ 2. Ruleset MUST include `subtype`, and it MUST match workflow `entitySubtype` for UI actions to appear.
246
+ 3. Set `userActions[].eventName` explicitly and keep it equal to the ruleset `name` unless a deliberate alternate routing is required.
247
+ 4. Each `context[]` object MUST include: `label`, `type`, `modules`, `confirm`.
248
+ 5. `context[].modules` values MUST be valid app names: `adminconsole`, `store`, `servicepoint`, or known custom manifest app suffixes from `fc.mystique.apps`.
249
+ 6. `attributes` is optional; when present, each attribute MUST include `name`, `label`, `type`, and `mandatory`.
250
+ 7. Do NOT invent undocumented keys (for example: `actionLabel`, `moduleName`, `requiresConfirmation`, `buttonType`).
251
+ 8. User actions are sync UI transitions (`/event/sync`). Keep payloads minimal and schema-accurate.
252
+
253
+ **Attribute schema** (when confirmation collects user input):
254
+
255
+ ```json
256
+ {
257
+ "attributes": [
258
+ {
259
+ "name": "controlValue",
260
+ "label": "Control Value",
261
+ "type": "INTEGER",
262
+ "source": "",
263
+ "defaultValue": 0,
264
+ "mandatory": true
265
+ }
266
+ ]
267
+ }
268
+ ```
269
+
270
+ | Field | Type | Description |
271
+ |-------|------|-------------|
272
+ | `name` | String | Attribute key passed in the event payload |
273
+ | `label` | String | Label shown in the confirmation dialog |
274
+ | `type` | String | `STRING`, `INTEGER`, `BOOLEAN`, `FLOAT` |
275
+ | `source` | String | Setting key to populate dropdown options (e.g., `"settings.cancellationReasons"`). Empty string for free-text input. |
276
+ | `defaultValue` | Any | Pre-filled value in the dialog |
277
+ | `mandatory` | Boolean | Whether the field must be filled before confirming |
278
+
279
+ **Key rules:**
280
+
281
+ - The ruleset MUST have a `subtype` (matching the workflow's entity subtype) for the user action to display in the UI.
282
+ - `eventName` is optional -- if omitted, the event name defaults to the ruleset name. Set it explicitly only when the event name differs.
283
+ - A ruleset can be both event-triggered AND have user actions (dual classification). For example, `CancelOrder` can be triggered by a user action button AND by an automated event from another ruleset.
284
+ - `modules` values map to Mystique manifest app names. The `fc.mystique.apps` account-level setting controls which apps are available for selection. To add a user action to `fc.mystique.manifest.custom`, use `"custom"` in the modules array.
285
+ - User actions send events via the synchronous endpoint (`/event/sync`), not the async endpoint. This means the UI blocks until the event is processed.
286
+
287
+ #### User Action Validation Checklist (MANDATORY)
288
+
289
+ **Before outputting ANY ruleset with `userActions`, run every check. If any fails, fix before presenting.**
290
+
291
+ | # | Check | Fail = | Common mistake |
292
+ |---|-------|--------|----------------|
293
+ | UA01 | Ruleset has `subtype` matching workflow entity subtype | Button invisible in UI | Forgetting `"subtype": "HD"` — #1 cause of missing buttons |
294
+ | UA02 | `context` is an **array** (not object) | Runtime error | `"context": {...}` instead of `"context": [{...}]` |
295
+ | UA03 | Every context entry has ALL 4 fields: `label`, `type`, `modules`, `confirm` | Invisible / broken | Omitting `confirm` or `modules` |
296
+ | UA04 | `type` is exactly `"PRIMARY"` or `"SECONDARY"` (uppercase) | Button invisible | `"primary"`, `"default"`, `"action"` — none valid |
297
+ | UA05 | `modules` is **non-empty array** of valid app names | Button invisible | Empty `[]` or wrong name |
298
+ | UA06 | Module values: `"adminconsole"` (OMS), `"store"` (Store), `"servicepoint"` (SP), or custom manifest suffix | Wrong app | `"oms"`, `"fluent-oms"`, `"console"` — not valid |
299
+ | UA07 | `confirm` is **boolean** (`true`/`false`), not string | Dialog broken | `"confirm": "true"` |
300
+ | UA08 | If `attributes` has entries, each has `name`, `label`, `type` | Dialog broken | Missing `name` = no key in event payload |
301
+ | UA09 | Attribute `type`: `STRING`, `INTEGER`, `BOOLEAN`, `FLOAT` (uppercase) | Wrong input | `"string"`, `"text"`, `"number"` — not valid |
302
+ | UA10 | Attribute `source`: empty `""` for free-text, `"settings.<key>"` for dropdown | Dropdown empty | Missing `settings.` prefix |
303
+ | UA11 | `userActions` is array at **ruleset top level** | Silently ignored | Inside `props` or `rules` — wrong |
304
+ | UA12 | `eventName` matches ruleset `name` OR explicitly set to different event | Wrong event | Typo sends event no ruleset catches |
305
+
306
+ **Hard-forbidden patterns (never generate):**
307
+
308
+ ```
309
+ WRONG: "modules": ["oms"] → RIGHT: "modules": ["adminconsole"]
310
+ WRONG: "modules": ["fluent-store"] → RIGHT: "modules": ["store"]
311
+ WRONG: "type": "primary" → RIGHT: "type": "PRIMARY"
312
+ WRONG: "type": "button" → RIGHT: "type": "PRIMARY" or "SECONDARY"
313
+ WRONG: "confirm": "true" → RIGHT: "confirm": true
314
+ WRONG: "context": { ... } → RIGHT: "context": [{ ... }]
315
+ WRONG: attribute "type": "string" → RIGHT: attribute "type": "STRING"
316
+ WRONG: "source": "cancellationReasons" → RIGHT: "source": "settings.cancellationReasons"
317
+ WRONG: userActions inside "rules" → RIGHT: userActions at ruleset top level
318
+ WRONG: ruleset without "subtype" → RIGHT: always include "subtype" matching workflow
319
+ ```
320
+
321
+ **Post-output verification:** After generating a user action, verify: (1) Does this ruleset have `subtype`? (2) Does `modules` use the correct app name? (3) Is `context` an array with all 4 fields? If any answer is no, fix before presenting.
322
+
323
+ **Troubleshooting:** When a user action fires, the browser sends a `POST /api/v4.1/event/sync` call. Use browser DevTools (Network tab) to inspect the request payload, bearer token, and response `eventStatus`. The token is the logged-in user's token -- useful for debugging permission issues.
324
+
325
+ **When to use user actions:**
326
+ - Manual workflow transitions that require human decision (cancel, reject, approve, confirm)
327
+ - Collecting information from the user at transition time (cancellation reason, tracking number)
328
+ - Actions that should appear as buttons in Fluent OMS or Store apps
329
+
330
+ **When NOT to use:**
331
+ - Automated status transitions -- use `triggers` with status-based firing
332
+ - System-to-system integrations -- use `SendEvent` rules or the async event API
333
+ - Scheduled/delayed actions -- use `ScheduleEvent` rule
334
+ - Transitions that happen without user involvement (e.g., all fulfilments complete → advance order)
335
+
336
+ **Common user action patterns:**
337
+
338
+ | Pattern | eventName | modules | confirm | Typical attributes |
339
+ |---------|-----------|---------|---------|-------------------|
340
+ | Cancel order | `CancelOrder` | `["adminconsole"]` | true | cancellationReason (DROPDOWN from settings) |
341
+ | Confirm order | `ConfirmOrder` | `["adminconsole"]` | true | none |
342
+ | Reject fulfilment | `RejectFulfilment` | `["store"]` | true | rejectionReason (DROPDOWN) |
343
+ | Pick item | `PickItem` | `["store"]` | false | none |
344
+ | Pack fulfilment | `PackFulfilment` | `["store"]` | false | none |
345
+ | Dispatch fulfilment | `DispatchFulfilment` | `["store"]` | true | trackingNumber (STRING), carrier (DROPDOWN) |
346
+ | Approve return | `ApproveReturn` | `["adminconsole"]` | true | none |
347
+
348
+ **Complete example -- Cancel Order with reason collection:**
349
+
350
+ ```json
351
+ {
352
+ "name": "CancelOrder",
353
+ "description": "[ORDER] Cancel order from OMS with reason",
354
+ "type": "ORDER",
355
+ "subtype": "HD",
356
+ "eventType": "NORMAL",
357
+ "rules": [
358
+ {
359
+ "name": "<ACCOUNT>.core.SetState",
360
+ "props": { "status": "CANCELLED" }
361
+ }
362
+ ],
363
+ "triggers": [],
364
+ "userActions": [
365
+ {
366
+ "eventName": "CancelOrder",
367
+ "context": [
368
+ {
369
+ "label": "Cancel Order",
370
+ "type": "PRIMARY",
371
+ "modules": ["adminconsole"],
372
+ "confirm": true
373
+ }
374
+ ],
375
+ "attributes": [
376
+ {
377
+ "name": "cancellationReason",
378
+ "label": "Cancellation Reason",
379
+ "type": "STRING",
380
+ "source": "settings.cancellationReasons",
381
+ "defaultValue": "",
382
+ "mandatory": true
383
+ },
384
+ {
385
+ "name": "cancellationNote",
386
+ "label": "Notes",
387
+ "type": "STRING",
388
+ "source": "",
389
+ "defaultValue": "",
390
+ "mandatory": false
391
+ }
392
+ ]
393
+ }
394
+ ]
395
+ }
396
+ ```
397
+
398
+ **Verifying user actions after deployment:**
399
+
400
+ 1. Query the Transition API for the entity status where the button should appear:
401
+ ```
402
+ workflow.transitions entityType=ORDER subtype=HD status=BOOKED retailerId=2
403
+ ```
404
+ Response `userActions[]` should contain the configured action with `eventName`, `context`, and `attributes`.
405
+
406
+ 2. If `userActions` is empty: check `subtype` on the ruleset (most common cause), verify `modules` matches the manifest app name, confirm the entity is in the correct status.
407
+
408
+ **Strict validation checklist (run before upload):**
409
+
410
+ 1. Confirm each ruleset with `userActions` has `type` + `subtype`, and `subtype` equals workflow `entitySubtype`.
411
+ 2. Confirm `userActions[].eventName` is explicitly set and aligns to ruleset `name` (unless intentionally different).
412
+ 3. Confirm every `context[].modules` value is valid for the target UI app.
413
+ 4. Run `workflow.transitions` twice:
414
+ - once with `module: "all"` (truth-source view),
415
+ - once with the target module (visibility check).
416
+ 5. Trigger from UI and inspect `POST /api/v4.1/event/sync` in browser DevTools (payload + response `eventStatus`).
417
+
418
+ ### Statuses Array
419
+
420
+ ```json
421
+ {
422
+ "statuses": [
423
+ { "name": "CREATED", "category": "BOOKING", "entityType": "ORDER" },
424
+ { "name": "ON_VALIDATION", "category": "BOOKING", "entityType": "ORDER" },
425
+ { "name": "COMPLETE", "category": "DONE", "entityType": "ORDER" }
426
+ ]
427
+ }
428
+ ```
429
+
430
+ Categories: `BOOKING`, `FULFILMENT`, `DONE`, `PAYMENT`
431
+
432
+ ## Common Rule Patterns
433
+
434
+ ### Core Rules (provided by Fluent platform)
435
+
436
+ | Rule | Props | Purpose |
437
+ |------|-------|---------|
438
+ | `<ACCOUNT>.core.SetState` | `status` | Transition entity to new status |
439
+ | `<ACCOUNT>.core.SendEvent` | `eventName` | Fire a named event on current entity |
440
+ | `<ACCOUNT>.core.SendEventOnVerifyingEntityStatus` | `eventName`, `statuses` (comma-separated) | Fire event only if entity is in one of the listed statuses |
441
+ | `<ACCOUNT>.core.SendEventOnVerifyingAllFcStatus` | `eventName`, `statuses` (comma-separated) | Gate: fire event when ALL fulfilment choices reach one of the listed statuses |
442
+ | `<ACCOUNT>.core.ScheduleEvent` | `eventName`, `delay` (seconds) | Schedule a delayed event |
443
+ | `<ACCOUNT>.core.IfEventAttributeValueIsEqual` | `eventAttributeName`, `eventAttributeValue`, `eventName` | Conditional: fire event if attribute matches |
444
+
445
+ ### Extension Rules (from custom extension module)
446
+
447
+ | Rule | Key Props | Purpose |
448
+ |------|-----------|---------|
449
+ | `<ACCOUNT>.<MODULE>.UpdateStatusHistory` | `toStatus` | Track status transition in attribute |
450
+ | `<ACCOUNT>.<MODULE>.SendWebhookWithDynamicAttributes` | `setting` | Send webhook with config from Setting |
451
+ | `<ACCOUNT>.<MODULE>.UpdateEntityFromSetting` | `setting` | Batch-update entity from event data via Setting |
452
+ | `<ACCOUNT>.<MODULE>.CreateFulfilmentFromSourcingLocation` | *(from event attrs)* | Create fulfilment from sourcing data |
453
+ | `<ACCOUNT>.<MODULE>.UpsertAttribute` | `attributeName`, `attributeType`, `attributeValue` | Set entity attribute |
454
+ | `<ACCOUNT>.<MODULE>.UpsertAttributeFromPath` | `jsonpath`, `attributeName`, `attributeType` | Extract value via JSON path and set as attribute |
455
+
456
+ ## Plan Before Building
457
+
458
+ **Before creating or editing any workflow, present an implementation plan to the user.** The plan should include:
459
+
460
+ 1. **State machine design** — All statuses and transitions, shown as a Mermaid `stateDiagram-v2`
461
+ 2. **Ruleset inventory** — Every ruleset with its trigger condition, rules, and purpose
462
+ 3. **Settings dependencies** — Any settings referenced by rules (webhook URLs, thresholds, feature flags)
463
+ 4. **Custom rule requirements** — Any new Java rules needed (entity type, parameters, behavior)
464
+ 5. **Cross-entity interactions** — How this workflow interacts with other entity workflows (e.g., ORDER → FULFILMENT)
465
+ 6. **Deployment sequence** — What gets deployed in what order
466
+
467
+ For workflow edits, additionally show:
468
+ - **Before/after diff** — What rulesets are being added, removed, or modified
469
+ - **Before/after Mermaid diagrams** — Visual comparison of the state machine changes
470
+ - **Risk assessment** — Impact of changes on existing live entities
471
+
472
+ **Wait for user approval before making any changes to workflow JSON files.**
473
+
474
+ ## Building a New Workflow
475
+
476
+ ### Step 1: Determine entity type and subtype
477
+
478
+ ```
479
+ Workflow name = <ENTITY_TYPE>::<SUBTYPE>
480
+ Example: ORDER::HD, FULFILMENT::DEFAULT, RETURN_ORDER::DEFAULT
481
+ ```
482
+
483
+ ### Step 2: Design the state machine
484
+
485
+ List all statuses and the events/rules that transition between them. Example:
486
+
487
+ ```
488
+ CREATED → [CREATE ruleset] → ON_VALIDATION
489
+ ON_VALIDATION → [ConfirmValidation event] → IN_PROGRESS
490
+ IN_PROGRESS → [ConfirmShipment event] → SHIPPED
491
+ SHIPPED → [ConfirmDelivery event] → COMPLETE
492
+ ```
493
+
494
+ ### Step 3: Build each ruleset
495
+
496
+ For each transition, create a ruleset with:
497
+ 1. The rules to execute (in order — rules run sequentially)
498
+ 2. A trigger (status trigger for the first ruleset, event-name trigger for the rest)
499
+
500
+ ### Step 4: Add gate rulesets (if needed)
501
+
502
+ Gates check child entity statuses before advancing parent. Example:
503
+
504
+ ```json
505
+ {
506
+ "name": "NotifyFCComplete",
507
+ "description": "Gate: advance order when all FCs reach terminal status",
508
+ "type": "ORDER",
509
+ "eventType": "NORMAL",
510
+ "rules": [
511
+ {
512
+ "name": "ACCT.core.SendEventOnVerifyingAllFcStatus",
513
+ "props": {
514
+ "eventName": "SourceOrder",
515
+ "statuses": "ASSIGNED,CANCELLED,ESCALATED"
516
+ }
517
+ }
518
+ ],
519
+ "triggers": [],
520
+ "userActions": []
521
+ }
522
+ ```
523
+
524
+ ### Step 5: Validate structure
525
+
526
+ Before uploading, verify:
527
+ - [ ] Every status referenced in triggers exists in the `statuses` array
528
+ - [ ] Every `SetState` target status exists in the `statuses` array
529
+ - [ ] Every `SendEvent` target has a matching ruleset name (or is handled elsewhere)
530
+ - [ ] Rule names follow `<ACCOUNT>.<MODULE>.<RuleName>` format
531
+ - [ ] No duplicate ruleset names
532
+ - [ ] Version is bumped from previous
533
+
534
+ ## Editing an Existing Workflow
535
+
536
+ ### Get current workflow first
537
+
538
+ Use `/fluent-workflow` for download/list operations, then apply this skill's structure and validation patterns.
539
+
540
+ ### Make changes
541
+
542
+ Edit the JSON directly. Common operations:
543
+
544
+ **Add a new ruleset:**
545
+ ```json
546
+ {
547
+ "name": "NewRulesetName",
548
+ "description": "[ORDER] What it does",
549
+ "type": "ORDER",
550
+ "eventType": "NORMAL",
551
+ "rules": [ ... ],
552
+ "triggers": [ { "status": "IN_PROGRESS" } ],
553
+ "userActions": []
554
+ }
555
+ ```
556
+
557
+ **Add a rule to existing ruleset:**
558
+ Find the ruleset in the `rulesets` array, append to its `rules` array.
559
+
560
+ **Change a gate condition:**
561
+ Find the gate ruleset, update the `statuses` prop value.
562
+
563
+ ### Upload/merge
564
+
565
+ Use `/fluent-workflow-deploy` for uploading workflows to environments (MCP tool primary, REST API fallback). Use `/fluent-workflow` for listing, downloading, and merging workflows. Use `/fluent-module-deploy` for deploying full module bundles (JAR + settings + workflows together).
566
+
567
+ **Important:** If the workflow references new custom rules, deploy the module first via `/fluent-module-deploy` before uploading the workflow. Unregistered rules cause NO_MATCH events at runtime.
568
+
569
+ ## Workflow Fragments
570
+
571
+ Fragments are partial workflow definitions used with `fluent workflow merge`:
572
+
573
+ ```json
574
+ {
575
+ "name": "my-customization",
576
+ "description": "Add custom validation step",
577
+ "rulesets": [
578
+ {
579
+ "name": "CustomValidation",
580
+ "description": "Custom validation ruleset",
581
+ "type": "ORDER",
582
+ "eventType": "NORMAL",
583
+ "rules": [ ... ],
584
+ "triggers": [ ... ],
585
+ "userActions": []
586
+ }
587
+ ],
588
+ "statuses": [
589
+ { "name": "CUSTOM_VALIDATING", "category": "BOOKING", "entityType": "ORDER" }
590
+ ]
591
+ }
592
+ ```
593
+
594
+ Merge adds the fragment's rulesets and statuses to the base workflow. Use this for modular customizations.
595
+
596
+ ## Session Tracking
597
+
598
+ When invoked, log the following to the session tracking protocol (consumed by `/fluent-session-summary` and `/fluent-session-audit-export`):
599
+
600
+ **On entry:**
601
+ ```json
602
+ { "skill": "<this-skill-name>", "timestamp": "<ISO-8601>", "arguments": { "<key>": "<value>", "...": "..." } }
603
+ ```
604
+
605
+ **On exit:**
606
+ ```json
607
+ { "skill": "<this-skill-name>", "outcome": "<completed|failed|skipped>", "changesProduced": ["<seq-numbers>"], "toolCallsProduced": ["<seq-numbers>"], "nextRecommended": "<from-handoff-section>" }
608
+ ```
609
+
610
+ 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.
611
+
612
+ ## Handoff
613
+
614
+ | Output Artifact | Consumed By | Path |
615
+ |----------------|-------------|------|
616
+ | Workflow JSON file | `/fluent-workflow-analyzer` (validation) | `accounts/<PROFILE>/workflows/<RETAILER_REF>/<ENTITY_TYPE>__<SUBTYPE>.json` |
617
+ | Workflow JSON file | `/fluent-workflow-deploy` (deployment) | `accounts/<PROFILE>/workflows/<RETAILER_REF>/<ENTITY_TYPE>__<SUBTYPE>.json` |
618
+ | Workflow JSON file | `/fluent-pre-deploy-check` (gate check) | `accounts/<PROFILE>/workflows/<RETAILER_REF>/<ENTITY_TYPE>__<SUBTYPE>.json` |
619
+
620
+ ## Error Reporting
621
+
622
+ Errors from this skill follow the standard format:
623
+
624
+ | Field | Description |
625
+ |-------|-------------|
626
+ | `phase` | Skill phase where error occurred (e.g., `pre-flight`, `design`, `generation`, `validation`) |
627
+ | `severity` | `CRITICAL` (blocks downstream), `HIGH` (needs fix), `MEDIUM` (advisory), `LOW` (informational) |
628
+ | `message` | Human-readable error description |
629
+ | `resolution` | Suggested fix or downstream skill to invoke |
630
+
631
+ ## Validation Checklist
632
+
633
+ Run through this before uploading any workflow:
634
+
635
+ 1. **JSON syntax** — Valid JSON (no trailing commas, correct brackets)
636
+ 2. **Required fields** — `retailerId`, `version`, `entityType`, `entitySubtype`, `name`, `rulesets`
637
+ 3. **Status coverage** — Every SetState target exists in `statuses`
638
+ 4. **Event coverage** — Every SendEvent target has a matching ruleset (or is expected inbound)
639
+ 5. **Trigger consistency** — Only one ruleset per status trigger (avoid conflicts)
640
+ 6. **Rule naming** — `<ACCOUNT>.<MODULE>.<RuleName>` format, all referenced rules exist in platform
641
+ 7. **Gate logic** — Gate statuses include all terminal states for child entities
642
+ 8. **Version bump** — Version is higher than currently deployed version
643
+ 9. **Description** — `versionComment` describes what changed
644
+
645
+ ## Post-Execution: Feedback Capture
646
+
647
+ After completing this skill (whether success or failure), write a feedback record:
648
+
649
+ 1. **Classify outcome:** `SUCCESS` (clean build), `PARTIAL_SUCCESS` (built after fixing issues), `FAILURE` (could not complete), `BLOCKED` (prereq missing), `USER_CORRECTED` (user overrode approach)
650
+ 2. **Build record:** Create a `feedback-record-v1` JSON object with:
651
+ - `skill`: `"fluent-workflow-builder"`
652
+ - `feature`: feature slug if working within a feature, null otherwise
653
+ - `entityType` / `entitySubtype`: from the workflow being built (e.g., `ORDER`, `HD`)
654
+ - `phases`: trace of each phase (pre-flight, plan, build-rulesets, build-statuses, validate, etc.) with PASS/FAIL/SKIP
655
+ - `learnings`: any gotchas discovered during execution
656
+ - `userCorrections`: any corrections the user provided
657
+ 3. **Redact secrets:** Strip tokens, passwords, API keys. Keep business identifiers.
658
+ 4. **Append** one JSON line to `accounts/<PROFILE>/feedback/fluent-workflow-builder.jsonl`
659
+ 5. **Update** `accounts/<PROFILE>/feedback/index.json` counters (create file and directory with `mkdir -p` if missing)
660
+
661
+ **Skip capture if:** The execution was trivially simple (e.g., user just asked a question about workflows, no actual build/edit happened).
662
+
663
+ ## Known Pitfalls
664
+ <!-- feedback-promoted: managed section, updated by feedback loop -->
665
+
666
+ _(No promoted learnings yet.)_
667
+
668
+ <!-- end feedback-promoted -->