@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
@@ -0,0 +1,646 @@
1
+ ---
2
+ name: fluent-mystique-validate
3
+ description: Validate Mystique manifest JSON against the v2.0 schema, lint component configurations, and cross-reference aliases, data sources, and i18n keys. Triggers on "validate manifest", "check mystique", "lint manifest", "validate component", "mystique issues".
4
+ user-invocable: true
5
+ allowed-tools: Bash, Read, Write, Edit, Glob, Grep
6
+ argument-hint: <manifest-file-or-directory> [--strict] [--fix-suggestions] [--component <alias>]
7
+ ---
8
+
9
+ # Mystique Manifest Validator
10
+
11
+ Validate Fluent Commerce Mystique manifest JSON files against the v2.0 schema, lint component configurations, cross-reference aliases against the known component registry, validate data sources and GraphQL queries, check template string syntax, and verify i18n key usage.
12
+
13
+ This is a **frontend/UI validation** skill. Mystique manifests are JSON configuration files deployed to Fluent UX Apps that define the entire UI layout, data binding, and component composition. They are separate from backend workflow definitions.
14
+
15
+ ## Ownership Boundary
16
+
17
+ This skill owns manifest schema validation, component prop type checking, cross-reference resolution, template string syntax, and i18n key completeness checking.
18
+
19
+ Other skills own:
20
+ - Manifest creation and editing: `/fluent-mystique-builder`
21
+ - SDK component project structure: `/fluent-mystique-scaffold`
22
+ - Deployed manifest analysis and metrics: `/fluent-mystique-analyze`
23
+ - GraphQL query execution against live API: MCP tools (`graphql.query`)
24
+ - Workflow validation: `/fluent-workflow-analyzer`
25
+ - Settings management and manifest deployment: `/fluent-settings`
26
+
27
+ ## When to Use
28
+
29
+ - Before deploying a manifest to a Fluent environment
30
+ - After editing manifest JSON to catch structural errors before runtime
31
+ - When inheriting an unfamiliar manifest to assess its structural health
32
+ - After `/fluent-mystique-builder` generates or modifies manifest JSON (always run as post-build hook)
33
+ - To validate a single component's configuration within a manifest (`--component` flag)
34
+ - To get actionable fix suggestions for identified issues (`--fix-suggestions` flag)
35
+
36
+ ## Required Inputs
37
+
38
+ - **Manifest file or directory**: Path to a `.json` manifest file, or a directory containing manifest files
39
+ - If a directory, validate all `.json` files that contain `"manifestVersion": "2.0"`
40
+ - Search recursively; skip `node_modules/`, `dist/`, `.git/`
41
+ - **Flags**:
42
+ - `--strict`: Treat MEDIUM and LOW issues as errors (default: only CRITICAL and HIGH are errors)
43
+ - `--fix-suggestions`: Include suggested JSON patches for each issue
44
+ - `--component <alias>`: Validate only instances of the specified component alias
45
+
46
+ ## Mystique Architecture Context
47
+
48
+ ### What is Mystique?
49
+
50
+ Mystique is Fluent Commerce's declarative UI framework. Instead of writing React code for every screen, implementers define **manifest JSON** files that describe:
51
+
52
+ - **Routes**: URL paths organized into sections and pages
53
+ - **Pages**: Top-level containers with GraphQL data queries
54
+ - **Components**: Nested tree of UI building blocks (lists, cards, charts, forms)
55
+ - **Data binding**: JSONPath-based `dataSource` scoping from page query results to components
56
+ - **Template strings**: Handlebars expressions for dynamic values (`{{ref}}`, `{{currency amount code}}`)
57
+ - **Role-based visibility**: Component/page/section access control via `roles[]`
58
+ - **Fragments**: Reusable manifest snippets loaded via setting references
59
+
60
+ ### Manifest v2.0 Schema
61
+
62
+ ```
63
+ MystiqueManifest
64
+ manifestVersion: "2.0" # REQUIRED, must be exactly "2.0"
65
+ name: string # REQUIRED, app identifier (no spaces)
66
+ title: string # REQUIRED, display name (supports i18n: prefix)
67
+ icon?: string # Material icon name
68
+ context?: { level, role? } # account | retailer | location
69
+ orchestrationAlias?: string # entity type alias mapping
70
+ plugins?: MystiquePlugin[] # external component bundles
71
+ homePath: string # REQUIRED, landing route path
72
+ routes: MystiqueManifestRoute[] # REQUIRED, non-empty array
73
+ ```
74
+
75
+ ### Plugin and Custom Component Model
76
+
77
+ Fluent UX Apps render built-in components from the core registry. Custom components are **React bundles** (`bundle.js`) built with the OMX Component SDK, registered via `ComponentRegistry.register()`, and hosted externally.
78
+
79
+ - **Development**: Custom bundles served from `localhost` (e.g., `http://localhost:3001/bundle.js`)
80
+ - **Production**: Custom bundles hosted on CDN/Vercel/S3 (e.g., `https://cdn.example.com/plugins/bundle.abc123.js`)
81
+ - **Fluent does NOT host custom component bundles** -- they must be self-hosted
82
+ - **Plugins array**: Manifest references bundles via `plugins: [{ type: "url", src: "https://..." }]` or `plugins: [{ type: "setting", setting: "settingName" }]`
83
+
84
+ ### Component Instance Structure
85
+
86
+ Every UI element in a manifest is a `MystiqueComponentInstance`:
87
+
88
+ ```
89
+ MystiqueComponentInstance
90
+ component: string # REQUIRED, registry alias (e.g., "fc.list")
91
+ dataSource?: string # JSONPath scoping data context
92
+ props?: Record<string,any> # Component-specific configuration
93
+ descendants?: Instance[] # Nested child components
94
+ roles?: string[] # Role-based visibility
95
+ ```
96
+
97
+ ---
98
+
99
+ ## Component Alias Registry
100
+
101
+ The following table lists all **verified** component aliases extracted from the official OMX Mystique component documentation and source code. The validator uses this registry to resolve `component` field values.
102
+
103
+ ### Layout and Container Components
104
+
105
+ | Alias | Legacy Alias | Category | Expects dataSource | Expects descendants | Key Props |
106
+ |-------|-------------|----------|-------------------|--------------------|----|
107
+ | `fc.page` | `shared.components.material.DynamicPage` | page | No (uses page `data`) | Yes | `title` (recommended) |
108
+ | `fc.page.wizard` | -- | page | No | Yes | `steps[]`, `title` |
109
+ | `fc.page.wizard.summary` | -- | page | No | No | `width`, `noCard`, `sticky` |
110
+ | `fc.page.section` | -- | layout | Optional | Yes | `title`, `icon` |
111
+ | `fc.page.section.column` | -- | layout | No | Yes | `width` (CardWidth), `height` (`start`/`stretch`) |
112
+ | `fc.page.section.header` | -- | layout | No | Yes | `title`, `icon` |
113
+ | `fc.page.refresh` | -- | layout | No | Yes | `interval` |
114
+ | `fc.conditional` | -- | layout | No | Yes | **`value`** (required), **`matches`** (required) |
115
+ | `fc.repeater` | -- | layout | **Yes** (required) | Yes | `dataSource` (path to array/connection) |
116
+ | `fc.provider.graphql` | -- | layout | No | Yes | **`query`** (required), `variables`, **`path`** (required), `max`, `loadingBehavior` |
117
+ | `fc.workflow.provider` | -- | layout | No | Yes | (no props — fetches workflow data via REST) |
118
+ | `fc.tabs` | `shared.components.material.MaterialTabsSet` | layout | No | Yes | **`layouts[]`** (required), `urlKey` |
119
+ | `fc.tabs.card` | -- | layout | No | Yes | **`tabs[]`** (required), `width`, `urlKey` |
120
+ | `fc.tab.content` | `shared.components.material.SubLayoutContent` | layout | No | Yes | (pass-through wrapper) |
121
+ | `fc.accordion` | -- | content | No | Optional | `summary`, `details`, `expandIcon`, `expanded`, `defaultExpanded`, `disabled`, `indent` |
122
+ | `fc.filterPanel` | -- | layout | No | Yes | filter configuration |
123
+
124
+ ### Content and Display Components
125
+
126
+ | Alias | Legacy Alias | Category | Expects dataSource | Expects descendants | Key Props |
127
+ |-------|-------------|----------|-------------------|--------------------|----|
128
+ | `fc.list` | `shared.components.material.DynamicList` | content | **Yes** (required) | Optional (row expansion) | **`attributes[]`** (required), **`defaultPageSize`** (required), `title`, `rowLink`, `filter`, `actions[]`, `density`, `responsiveness`, `vAlign`, `rowComponent`, `rowsPerPageOptions[]`, `loading` |
129
+ | `fc.card.attribute` | `shared.components.material.DynamicCard` | content | Optional | No | **`attributes[]`** (required), `title`, `highlight`, `width`, `cardImage` |
130
+ | `fc.card.image` | -- | content | No | Optional | **`image`** (required, `{imageUrl, width?, height?}`), `width`, `indent`, `descendantSpacing`, `descendantDirection` |
131
+ | `fc.card.product` | -- | content | Optional | Optional | `title`, `width`, `image`, `attributes[]` |
132
+ | `fc.card.multi` | -- | content | Optional | Yes | `title`, `width` |
133
+ | `fc.card.attributes.grid` | -- | content | **Yes** (required) | No | `exclude[]` |
134
+ | `fc.card.map.point` | -- | content | Optional | No | map configuration |
135
+ | `fc.tile.metric` | -- | content | No | No | **`label`** (required), **`value`** (required), `options[]`, `variant`, `width`, `link` |
136
+ | `fc.attribute.json` | -- | content | Optional | No | JSON display |
137
+ | `fc.attribute.column` | -- | content | Optional | No | column attribute display |
138
+ | `fc.attribute.locationId` | -- | content | No | No | location display |
139
+ | `fc.attribute.retailerId` | -- | content | No | No | retailer display |
140
+ | `fc.mystique.collapsible.text` | -- | content | No | No | **`text`** (required), **`charCutoff`** (required) |
141
+ | `fc.mystique.collapsible.attributes` | -- | content | Optional | No | collapsible attribute list |
142
+ | `fc.mystique.link` | -- | content | No | No | `label`, `link` |
143
+ | `fc.progress.circular` | -- | content | No | No | progress indicator |
144
+ | `fc.dashboard.threshold` | -- | content | Optional | No | dashboard threshold config |
145
+ | `fc.stepper` | -- | content | No | No | step progress indicator |
146
+ | `fc.json.viewer` | -- | content | Optional | No | read-only JSON display |
147
+ | `fc.json.editor` | -- | content | Optional | No | editable JSON with validation |
148
+ | `fc.quantity.list` | -- | content | **Yes** (required) | No | `attributes[]`, `defaultPageSize`, `quantitySelectorProps` |
149
+ | `fc.scanner.barcode` | -- | content | No | No | USB barcode scanner input |
150
+ | `fc.scanner.camera` | -- | content | No | No | camera barcode scanner |
151
+ | `fc.scanner.barcodeFilter` | -- | content | No | No | barcode filter bar |
152
+ | `fc.settingForm` | -- | content | No | No | `setting`, `context`, `contextId` |
153
+ | `fc.action.inline` | -- | content | Optional | No | inline user action |
154
+ | `fc.mutation.inline` | -- | content | No | No | `mutation` (config), `title`, `width` |
155
+ | `fc.list.customAction` | -- | content | **Yes** (required) | No | `attributes[]`, `action` (callback config) |
156
+
157
+ ### Chart Components
158
+
159
+ | Alias | Category | Expects dataSource | Key Props |
160
+ |-------|----------|-------------------|-----------|
161
+ | `fc.chart.area` | content | Yes | chart data config |
162
+ | `fc.chart.area.wrapper.feed` | content | Yes | feed-based area chart |
163
+ | `fc.chart.bar` | content | Yes | chart data config |
164
+ | `fc.chart.bar.wrapper.source` | content | Yes | source-based bar chart |
165
+ | `fc.chart.line` | content | Yes | chart data config |
166
+ | `fc.chart.gauge` | content | Yes | chart data config |
167
+ | `fc.chart.gauge.wrapper.threshold` | content | Yes | threshold-based gauge |
168
+
169
+ ### List Wrapper Components
170
+
171
+ | Alias | Category | Expects dataSource | Key Props |
172
+ |-------|----------|-------------------|-----------|
173
+ | `fc.list.wrapper.feed` | content | Yes | feed-based list |
174
+ | `fc.list.wrapper.source` | content | Yes | source-based list |
175
+ | `fc.list.wrapper.bppmetrics` | content | Yes | BPP metrics list |
176
+
177
+ ### Action and Button Components
178
+
179
+ | Alias | Category | Key Props |
180
+ |-------|----------|----|
181
+ | `fc.button.print` | action | `label`, print configuration |
182
+ | `fc.button.print.pick` | action | `label`, pick-specific print |
183
+ | `fc.button.print.inline` | action | `label`, inline print |
184
+ | `fc.button.print.inline.compatibility` | action | legacy inline print |
185
+ | `fc.button.print.download` | action | `label`, download print |
186
+ | `fc.modal.button` | action | modal trigger button |
187
+ | `fc.modal.button.addItem` | action | add item modal trigger |
188
+ | `fc.drawer.button` | action | drawer trigger button |
189
+ | `fc.buttons.add.reject` | action | add/reject action buttons |
190
+ | `fc.button.bar` | action | grouped action button bar |
191
+ | `fc.sourcing.profile.drawer.button` | action | sourcing profile drawer trigger |
192
+ | `fc.sourcing.profile.modal.button` | action | sourcing profile modal trigger |
193
+ | `fc.sourcing.strategy.modal.button` | action | sourcing strategy modal trigger |
194
+
195
+ ### Form and Field Components
196
+
197
+ | Alias | Category | Key Props |
198
+ |-------|----------|----|
199
+ | `select` | field | query/setting/manifest options |
200
+ | `retailer` | field | retailer selector |
201
+ | `fc.field.daterange` / `daterange` | field | date range filter |
202
+ | `fc.field.intrange` / `intrange` | field | number range filter |
203
+ | `fc.field.filterComplex` | field | complex filter |
204
+ | `fc.field.multistring` | field | multi-value search |
205
+ | `fc.page.filter.select` | field | page-level filter select |
206
+ | `fc.attribute.jsoneditor` | field | JSON editor |
207
+ | `AttributeInput.list` | field | attribute input list |
208
+ | `ExtendedAddressInput` | field | address input |
209
+ | `fc.scanner.barcode` / `fc.barcode.scanner` | field | USB barcode scanner (see also Content section) |
210
+ | `fc.action.field.wavepick` | field | wave pick list |
211
+ | `fc.action.field.fulfilmentpack` / `FULFILMENT_PACK` | field | fulfilment pack field |
212
+ | `fc.action.field.multiparcel` / `MULTI_PARCEL_FIELD` | field | multi-parcel field |
213
+ | `fc.action.field.returnitems` / `RETURN_ITEMS` | field | return items field |
214
+ | `FULFILMENT_IDS` | field | wave create details |
215
+ | `fc.daterange.wrapper.forwarder` | field | date range forwarding |
216
+
217
+ ### OMS-Specific Components
218
+
219
+ | Alias | Category | Key Props |
220
+ |-------|----------|----|
221
+ | `fc.events.search` | content | event search component |
222
+ | `fc.event.detail` | content | event detail drawer |
223
+ | `fc.activity.entity` | content | entity activity timeline |
224
+ | `fc.order.itemDetails` | content | order item details drawer |
225
+ | `fc.order.shipmentDetails` | content | shipment details drawer |
226
+ | `fc.return.rowExpansion` | content | return row expansion |
227
+ | `fc.reports.ipuipc` | content | IPU/IPC report |
228
+
229
+ ### Analytics Components
230
+
231
+ | Alias | Category | Key Props |
232
+ |-------|----------|----|
233
+ | `fc.analytics.viz` | content | Looker visualization |
234
+
235
+ ### Custom Components
236
+
237
+ Custom component aliases are registered via `ComponentRegistry.register()` in SDK plugin bundles. They follow the pattern:
238
+ - `custom.<name>` -- common custom prefix
239
+ - `<project>.<name>` -- project-scoped prefix
240
+
241
+ Custom aliases are NOT in this registry. The validator flags them as **INFO** (not errors) with a suggestion to verify the component is registered in a loaded plugin.
242
+
243
+ ---
244
+
245
+ ## Validation Rules
246
+
247
+ ### Phase 1: Schema Compliance
248
+
249
+ | ID | Rule | Severity | Description |
250
+ |----|------|----------|-------------|
251
+ | S01 | `manifestVersion` required | CRITICAL | Must be exactly `"2.0"`. Missing or wrong version means the manifest will not load. |
252
+ | S02 | `name` required | CRITICAL | Non-empty string, no spaces. Used for logging and user action filtering. |
253
+ | S03 | `homePath` required | CRITICAL | Must be a non-empty string matching a defined route path. |
254
+ | S04 | `routes` non-empty | CRITICAL | At least one route must be defined. |
255
+ | S05 | `title` required | HIGH | Non-empty string. Displayed in app header and browser title bar. Supports `i18n:` prefix. |
256
+ | S06 | `context.level` enum | HIGH | If `context` is present, `level` must be `account`, `retailer`, or `location`. |
257
+ | S07 | Route `type` enum | HIGH | Every route must have `type` set to `section`, `page`, or `reference`. |
258
+ | S08 | Page `path` required | HIGH | Every page must have a non-empty `path` string. |
259
+ | S09 | Page `component` required | HIGH | Every page must have a `component` field. Typically `fc.page` or `fc.page.wizard`. |
260
+ | S10 | Section must have `pages` | MEDIUM | Sections must contain a non-empty `pages` array. |
261
+ | S11 | Section must have `nav` | MEDIUM | Sections need `nav.label` and `nav.icon` for sidebar rendering. |
262
+ | S12 | Reference must have `settingName` | HIGH | Fragment references require a non-empty `settingName`. |
263
+ | S13 | Plugin structure valid | MEDIUM | Each plugin must be `{ type: "url", src: "<url>" }` or `{ type: "setting", setting: "<name>" }`. |
264
+ | S14 | `descendants` must be array | MEDIUM | If present, must be an array of component instances. |
265
+ | S15 | Fragment `manifestVersion` | HIGH | Manifest fragments must also declare `manifestVersion: "2.0"`. |
266
+
267
+ ### Phase 2: Component Resolution
268
+
269
+ | ID | Rule | Severity | Description |
270
+ |----|------|----------|-------------|
271
+ | C01 | Component alias exists | HIGH | Every `component` field must resolve to a known alias from the registry above, a legacy alias, or be flagged as a custom component (prefixed or plugin-registered). |
272
+ | C02 | No duplicate route paths | HIGH | Two pages must not share the same `path` pattern within the same manifest. |
273
+ | C03 | `homePath` resolves | CRITICAL | The `homePath` value must match an existing route's `path` field. |
274
+ | C04 | Fragment `settingName` convention | MEDIUM | Fragment references should follow `fc.mystique.manifest.*` naming pattern. |
275
+ | C05 | Plugin name uniqueness | MEDIUM | No duplicate `name` values in the `plugins` array. |
276
+ | C06 | Nesting depth limit | LOW | Warn if component descendants are nested more than 8 levels deep. Deep nesting impacts rendering performance. |
277
+ | C07 | Role string format | LOW | Warn on role strings that do not match common patterns (e.g., `ADMIN`, `FULFILLMENT_ADMIN`, uppercase with underscores). |
278
+
279
+ ### Phase 3: Data and Query Validation
280
+
281
+ | ID | Rule | Severity | Description |
282
+ |----|------|----------|-------------|
283
+ | D01 | `data.query` is valid GraphQL | HIGH | The `query` string in page `data` must be syntactically valid GraphQL. Check for balanced braces, valid field names, proper variable declarations. |
284
+ | D02 | `dataSource` path format | MEDIUM | Must be valid dot-notation JSONPath (e.g., `orderById.items.edges`). No leading dots, no trailing dots, no double dots. |
285
+ | D03 | `dataSource` references page data | MEDIUM | The root segment of a `dataSource` path should correspond to a top-level field in the nearest ancestor page or provider query. |
286
+ | D04 | Query variables referenced | LOW | Variables declared in `data.variables` should appear as `$varName` in the query string. Unused variables are likely copy-paste errors. |
287
+ | D05 | No query without consumer | LOW | If a page defines `data.query` but has no descendants that use `dataSource` or template strings referencing the data, the query is wasted. |
288
+ | D06 | Provider `query` required | HIGH | `fc.provider.graphql` components must have `props.query` defined. |
289
+
290
+ ### Phase 4: Template String Validation
291
+
292
+ | ID | Rule | Severity | Description |
293
+ |----|------|----------|-------------|
294
+ | T01 | Handlebars syntax balanced | MEDIUM | All `{{` must have matching `}}`. Unbalanced delimiters cause runtime rendering failures. |
295
+ | T02 | Known template helpers | LOW | Warn on helper function names that are not in the standard set. **Comparison:** `eq`, `ne`, `gt`, `lt`, `gte`, `lte`. **Logic:** `and`, `or`, `not`, `if`, `unless`, `in`, `switch`, `hasRole`, `firstDefinedValue`, `anyMatch`. **Iteration:** `each`, `with`, `lookup`. **String:** `capitalise`/`capitalize`, `humanify`, `toLowerCase`, `toUpperCase`, `concat`, `stringify`, `substring`, `replace`, `split`, `join`, `includes`, `startsWith`, `endsWith`, `preserveWhitespace`, `partialStringMatch`, `decodeUrlParams`, `currentUrlParams`. **Placeholder:** `placeholderText`, `placeholderDate`, `placeholderArray`. **Date:** `dateFormat`, `dateStringFormatter`, `dateTimeFormatter`, `dateAdd`, `dateSubtract`, `dateRelative`, `dateFormatByLocale`. **Number:** `currency`, `formatNumber`, `add`, `subtract`, `multiply`, `divide`, `pow`, `math`. **Array:** `len`, `arraySum`, `length`, `pluralize`. **Special:** `barcode`, `json`, `i18n`. |
296
+ | T03 | `i18n:` prefix format | MEDIUM | Strings prefixed with `i18n:` should follow the key convention pattern (e.g., `i18n:fc.om.orders.detail.title`). Warn on keys with spaces or special characters. |
297
+ | T04 | `rowLink` template produces URL | MEDIUM | `rowLink` values must produce valid relative URL paths. They should start with `/` or use template expressions that resolve to paths (e.g., `/orders/{{node.id}}`). |
298
+ | T05 | `_locale='en'` on backend date queries | HIGH | When `dateFormat` or `dateStringFormatter` is used inside `data.variables` (query variable values), warn if `_locale='en'` is missing. User locale can produce non-ASCII digits (Arabic, Thai) that break backend date parsing. |
299
+ | T06 | Triple-brace for unescaped output | LOW | `{{{helper}}}` (triple-brace) outputs unescaped HTML. Warn when used outside URL construction patterns — unescaped output can create XSS risks. `{{{currentUrlParams}}}` in `href`/`link` is acceptable. |
300
+
301
+ ### Phase 5: Component Props Validation
302
+
303
+ | ID | Rule | Severity | Description |
304
+ |----|------|----------|-------------|
305
+ | P01 | `fc.list` requires `attributes` | HIGH | The list component must have `props.attributes` as a non-empty array of column definitions. |
306
+ | P02 | `fc.list` requires `defaultPageSize` | MEDIUM | Should have `props.defaultPageSize` set. Defaults to 10 if missing but explicit is preferred. |
307
+ | P03 | `fc.list` attribute needs `label` | MEDIUM | Each attribute in a list should have a `label` (or i18n key) for the column header. |
308
+ | P04 | `fc.list` needs `dataSource` | HIGH | List components must have a `dataSource` pointing to a connection or array. |
309
+ | P05 | `fc.card.attribute` requires `attributes` | HIGH | Attribute card must have `props.attributes` as a non-empty array. |
310
+ | P06 | `fc.conditional` requires `value` and `matches` | HIGH | Must have both `props.value` (template string) and `props.matches` (string or string array). |
311
+ | P07 | `fc.repeater` requires `dataSource` | HIGH | Repeater component must have `dataSource` set to an array or connection path. |
312
+ | P08 | `fc.repeater` requires `descendants` | HIGH | Repeater must have at least one descendant to repeat. |
313
+ | P09 | `fc.provider.graphql` requires `query` | HIGH | Data provider must have `props.query` with a valid GraphQL query string. |
314
+ | P10 | `fc.tabs.card` requires `tabs` | HIGH | Tab card must have `props.tabs` as a non-empty array of tab definitions with `label`. |
315
+ | P11 | `fc.tabs.card` tabs-descendants count match | MEDIUM | Number of `tabs` entries should match number of `descendants`. Mismatches cause empty or unreachable tabs. |
316
+ | P12 | `fc.tile.metric` requires `label` and `value` | HIGH | Tile metric must have both `props.label` and `props.value`. |
317
+ | P13 | `fc.mystique.collapsible.text` requires `text` and `charCutoff` | HIGH | Collapsible text must have both `props.text` (string) and `props.charCutoff` (number). |
318
+ | P14 | `fc.card.image` requires `image` | HIGH | Image card must have `props.image` with at least `imageUrl`. |
319
+ | P15 | `fc.page` title recommended | LOW | Pages should have `props.title` for header rendering. Missing titles result in blank page headers. |
320
+ | P16 | `fc.page` recommended component | LOW | Page `component` field should typically be `fc.page` or `fc.page.wizard`. Other values may indicate misconfiguration. |
321
+ | P17 | `width` prop valid CardWidth | LOW | When present, `width` should be a valid CardWidth: `"quarter"`, `"third"`, `"half"`, `"two-thirds"`, `"full"`, or a number 1-12. |
322
+ | P18 | `fc.settingForm` requires setting reference | MEDIUM | Setting form component needs a setting name or reference to render. |
323
+ | P19 | Dynamic attribute `type` valid | MEDIUM | Attribute `type` if present must be `"image"` or `"component"`. Unknown types render nothing. |
324
+ | P20 | Image attribute needs `value` URL | MEDIUM | Attributes with `type: "image"` must have `value` (image URL template) and optionally `options.width`/`options.height`. |
325
+ | P21 | Component attribute needs `options.component` | HIGH | Attributes with `type: "component"` must have `options.component` pointing to a known alias. |
326
+ | P22 | Icon name has library prefix | LOW | Icon names in `options.styles[].icon.name` should include library prefix (`Md*` for Material Design, `Fa*` for Font Awesome). `"CheckCircle"` is wrong — use `"MdCheckCircle"`. |
327
+ | P23 | `enableCopyIcon` valid value | LOW | If present, `enableCopyIcon` must be `"displayAlways"` or `"displayOnHover"`. |
328
+
329
+ ### Phase 6: Cross-Manifest and Plugin Validation
330
+
331
+ | ID | Rule | Severity | Description |
332
+ |----|------|----------|-------------|
333
+ | X01 | Fragment references resolve | HIGH | When `--strict` is set and other manifests/settings are available, verify that `settingName` in `type: "reference"` routes points to a known setting. |
334
+ | X02 | Plugin URL format | MEDIUM | Plugin `src` must be a valid URL (starts with `http://` or `https://`). |
335
+ | X03 | Plugin URL localhost warning | LOW | Warn if plugin `src` contains `localhost` or `127.0.0.1` -- this indicates a development configuration that will fail in production. |
336
+ | X04 | Plugin URL HTTPS for production | LOW | Warn if plugin `src` uses `http://` instead of `https://` (excluding localhost for dev). Production environments should use HTTPS. |
337
+ | X05 | Shared alias consistency | LOW | If validating a directory of manifests, flag cases where the same custom component alias has different prop patterns across manifests. |
338
+
339
+ ---
340
+
341
+ ## Execution Flow
342
+
343
+ ### Step 1: Discover and Load Manifests
344
+
345
+ ```
346
+ 1. Resolve input path:
347
+ - If file: load single manifest JSON
348
+ - If directory: recursively find all .json files containing "manifestVersion": "2.0"
349
+ - Skip: node_modules/, dist/, .git/, build/
350
+
351
+ 2. Parse each manifest:
352
+ - Validate JSON syntax (report parse errors immediately)
353
+ - Detect manifest vs fragment (presence of "name" + "homePath" = full manifest)
354
+ - Record file path, size, route count for summary
355
+ ```
356
+
357
+ ### Step 2: Schema Compliance (Phase 1)
358
+
359
+ ```
360
+ For each manifest:
361
+ 1. Check required top-level fields (S01-S04)
362
+ 2. Check recommended fields (S05)
363
+ 3. Validate context, plugins, routes structure (S06-S15)
364
+ 4. Record all issues with JSON path locations
365
+ ```
366
+
367
+ ### Step 3: Component Tree Walk (Phase 2 + Phase 5)
368
+
369
+ ```
370
+ For each manifest:
371
+ 1. Walk all routes recursively:
372
+ - Sections: validate nav, walk pages
373
+ - Pages: validate path/component, walk descendants
374
+ - References: validate settingName
375
+ 2. For each component instance encountered:
376
+ a. Resolve alias against registry (C01)
377
+ b. Track nesting depth (C06)
378
+ c. Validate component-specific required props (P01-P18)
379
+ d. Validate dataSource format (D02-D03)
380
+ e. Validate template strings in props (T01-T04)
381
+ 3. Check route path uniqueness (C02)
382
+ 4. Verify homePath resolves (C03)
383
+ ```
384
+
385
+ ### Step 4: Data and Query Validation (Phase 3)
386
+
387
+ ```
388
+ For each page with data.query:
389
+ 1. Validate GraphQL syntax (D01):
390
+ - Balanced braces and parentheses
391
+ - Valid query/mutation keyword
392
+ - Variable declarations match usage
393
+ 2. Cross-reference variables (D04)
394
+ 3. Check data consumption by descendants (D05)
395
+
396
+ For each fc.provider.graphql:
397
+ 1. Validate props.query exists and is syntactically valid (D06)
398
+ ```
399
+
400
+ ### Step 5: Cross-Manifest Checks (Phase 6)
401
+
402
+ ```
403
+ If validating multiple manifests:
404
+ 1. Check fragment reference resolution (X01)
405
+ 2. Validate plugin URLs (X02-X04)
406
+ 3. Check cross-manifest alias consistency (X05)
407
+ ```
408
+
409
+ ### Step 6: Generate Report
410
+
411
+ ```
412
+ 1. Aggregate all issues by severity
413
+ 2. Sort: CRITICAL first, then HIGH, MEDIUM, LOW
414
+ 3. Generate summary statistics
415
+ 4. If --fix-suggestions: include suggested JSON patches
416
+ 5. Output report to console and optionally to file
417
+ ```
418
+
419
+ ---
420
+
421
+ ## Output Format
422
+
423
+ ### Summary Banner
424
+
425
+ ```
426
+ +----------------------------------------------------------+
427
+ | Mystique Manifest Validation Report |
428
+ +----------------------------------------------------------+
429
+ | File: admin-manifest.json |
430
+ | Version: 2.0 |
431
+ | Type: Full Manifest |
432
+ | Routes: 4 sections, 12 pages, 1 fragment reference |
433
+ | Components: 87 instances (22 unique aliases) |
434
+ | Plugins: 2 (1 URL, 1 setting) |
435
+ +----------------------------------------------------------+
436
+ | CRITICAL: 0 | HIGH: 2 | MEDIUM: 3 | LOW: 1 |
437
+ +----------------------------------------------------------+
438
+ ```
439
+
440
+ ### Issue Detail Format
441
+
442
+ Each issue is reported with:
443
+
444
+ ```
445
+ <SEVERITY> [<RULE_ID>] <description>
446
+ at <json-path>
447
+ > <suggested fix or context>
448
+ ```
449
+
450
+ ### Example Issues
451
+
452
+ ```
453
+ CRITICAL [S01] Missing required field "manifestVersion"
454
+ at (root)
455
+ > Add "manifestVersion": "2.0" to the manifest root
456
+
457
+ HIGH [C01] Unknown component alias "fc.card.detail" at routes[0].pages[2].descendants[0]
458
+ > Did you mean "fc.card.attribute"? Check ComponentRegistry for registered aliases.
459
+
460
+ HIGH [P01] fc.list missing required "attributes" prop at routes[1].pages[0].descendants[0]
461
+ > Add "attributes": [...] array with column definitions: { "label": "...", "template": "{{...}}" }
462
+
463
+ HIGH [P06] fc.conditional missing required "value" and "matches" props at routes[0].pages[1].descendants[3]
464
+ > Add "value": "{{templateExpression}}" and "matches": "expectedValue" to props
465
+
466
+ MEDIUM [D02] Invalid dataSource path "orders..edges" (double dot) at routes[0].pages[0].descendants[1]
467
+ > Fix path to "orders.edges" -- remove duplicate dot separator
468
+
469
+ MEDIUM [T01] Unbalanced template delimiters "{{ref}" at routes[0].pages[1].descendants[0].props.title
470
+ > Fix closing delimiter: "{{ref}}"
471
+
472
+ MEDIUM [T03] i18n key "i18n:my custom label" contains spaces at routes[0].pages[0].descendants[0].props.title
473
+ > Use dot-separated key format: "i18n:fc.app.myCustomLabel"
474
+
475
+ LOW [C06] Component nesting depth is 9 levels at routes[2].pages[0].descendants[0]...descendants[0]
476
+ > Consider flattening the component tree. Deep nesting impacts rendering performance.
477
+
478
+ LOW [X03] Plugin src contains "localhost": "http://localhost:3001/bundle.js" at plugins[0]
479
+ > Development URL detected. Replace with production CDN URL before deploying.
480
+ ```
481
+
482
+ ### Pass/Fail Summary
483
+
484
+ ```
485
+ RESULT: FAIL (2 HIGH issues must be resolved before deployment)
486
+
487
+ Fix the HIGH and CRITICAL issues above, then re-run validation.
488
+ MEDIUM and LOW issues are recommendations (enforce with --strict).
489
+ ```
490
+
491
+ Or on success:
492
+
493
+ ```
494
+ RESULT: PASS (0 CRITICAL, 0 HIGH issues)
495
+
496
+ Manifest is structurally valid and ready for deployment.
497
+ 3 MEDIUM and 1 LOW recommendations noted above.
498
+
499
+ Next steps:
500
+ - Deploy manifest as a Fluent setting via /fluent-settings
501
+ - Or run /fluent-mystique-analyze for deeper usage analysis
502
+ ```
503
+
504
+ ---
505
+
506
+ ## Fix Suggestions (--fix-suggestions)
507
+
508
+ When enabled, each issue includes a concrete JSON patch suggestion:
509
+
510
+ ```
511
+ HIGH [P01] fc.list missing required "attributes" prop
512
+ at routes[0].pages[0].descendants[2]
513
+
514
+ Suggested fix -- add to props:
515
+ "attributes": [
516
+ {
517
+ "label": "Reference",
518
+ "template": "{{node.ref}}"
519
+ },
520
+ {
521
+ "label": "Status",
522
+ "template": "{{node.status}}"
523
+ }
524
+ ]
525
+ ```
526
+
527
+ ```
528
+ HIGH [P06] fc.conditional missing required props
529
+ at routes[1].pages[0].descendants[0]
530
+
531
+ Suggested fix -- add to props:
532
+ "value": "{{status}}",
533
+ "matches": ["ACTIVE", "APPROVED"]
534
+ ```
535
+
536
+ ---
537
+
538
+ ## Template String Reference
539
+
540
+ ### Supported Handlebars Helpers
541
+
542
+ The Mystique template renderer supports these built-in helpers. **Only use documented helpers — guessing undocumented helpers produces broken manifests.**
543
+
544
+ **Comparison:** `eq`, `ne`, `gt`, `lt`, `gte`, `lte`
545
+ **Logic:** `and`, `or`, `not`, `if`, `unless`, `in`, `switch`, `hasRole`, `firstDefinedValue`, `anyMatch`
546
+ **Iteration:** `each`, `with`, `lookup`
547
+ **String:** `capitalise`/`capitalize`, `humanify`, `toLowerCase`, `toUpperCase`, `concat`, `stringify`, `substring`, `replace`, `split`, `join`, `includes`, `startsWith`, `endsWith`, `preserveWhitespace`, `partialStringMatch`, `decodeUrlParams`, `currentUrlParams`
548
+ **Placeholder:** `placeholderText`, `placeholderDate`, `placeholderArray`
549
+ **Date:** `dateFormat`, `dateStringFormatter`, `dateTimeFormatter`, `dateAdd`, `dateSubtract`, `dateRelative`, `dateFormatByLocale`
550
+ **Number:** `currency`, `formatNumber`, `add`, `subtract`, `multiply`, `divide`, `pow`, `math`
551
+ **Array:** `len`, `arraySum`, `length`, `pluralize`
552
+ **Special:** `barcode`, `json`, `i18n`
553
+
554
+ **CRITICAL: Always use `_locale='en'` for dates in query variables.** Without it, user locale may produce non-ASCII digits that break backend queries.
555
+
556
+ ### Context Variables
557
+
558
+ | Expression | Purpose |
559
+ |-----------|---------|
560
+ | `{{activeUser.username}}` | Current user's username |
561
+ | `{{activeUser.firstName}}` | Current user's first name |
562
+ | `{{activeUser.timezone}}` | Current user's timezone |
563
+ | `{{activeContext.id}}` | Current context ID |
564
+ | `{{activeRetailer.id}}` | Current retailer ID |
565
+ | `{{activeRetailer.ref}}` | Current retailer ref |
566
+ | `{{activeLocation.id}}` | Current location ID |
567
+ | `{{params.id}}` | Route parameter access |
568
+
569
+ ### Template Expression Patterns
570
+
571
+ ```
572
+ {{fieldName}} -- simple field access
573
+ {{node.ref}} -- nested field access (list rows)
574
+ {{attributes.byName.X}} -- attribute by name shorthand
575
+ {{edges.length}} -- connection count
576
+ {{capitalise status}} -- helper with argument
577
+ {{currency node.totalPrice node.currency}} -- helper with multiple args
578
+ {{dateFormat createdOn 'MMM DD, YYYY'}} -- date formatting
579
+ {{dateFormat (dateAdd day=-1) 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' true _locale='en'}} -- backend-safe date
580
+ {{eq status "ACTIVE"}} -- comparison (returns boolean)
581
+ {{i18n "fc.om.orders.title"}} -- i18n helper form
582
+ i18n:fc.om.orders.title -- i18n prefix form (in string props)
583
+ {{barcode fulfilmentById.ref}} -- barcode SVG generation
584
+ {{{currentUrlParams}}} -- triple-brace for unescaped output
585
+ ```
586
+
587
+ ---
588
+
589
+ ## Validation Against Single Component (--component)
590
+
591
+ When `--component <alias>` is specified, the validator focuses on all instances of that component:
592
+
593
+ ```
594
+ $ /fluent-mystique-validate manifest.json --component fc.list
595
+
596
+ Validating all fc.list instances in manifest.json...
597
+
598
+ Instance 1: routes[0].pages[0].descendants[0]
599
+ PASS [P01] attributes present (5 columns)
600
+ PASS [P02] defaultPageSize set (20)
601
+ PASS [P04] dataSource present ("orders")
602
+ PASS attributes have labels
603
+ INFO rowLink uses template: "/orders/{{node.id}}"
604
+
605
+ Instance 2: routes[1].pages[2].descendants[1].descendants[0]
606
+ FAIL [P01] attributes missing
607
+ PASS [P04] dataSource present ("fulfilments")
608
+ WARN [P02] defaultPageSize not set (will default to 10)
609
+
610
+ Summary: 2 instances found, 1 FAIL, 1 PASS
611
+ ```
612
+
613
+ ---
614
+
615
+ ## Integration with Other Skills
616
+
617
+ ### Post-Build Validation
618
+
619
+ After `/fluent-mystique-builder` creates or modifies a manifest:
620
+ 1. Builder outputs `READY: <manifest-path>`
621
+ 2. **Always run** `/fluent-mystique-validate <manifest-path>` as next step
622
+ 3. If validation fails: `BLOCKED: <count> issues` -- return to builder for fixes
623
+ 4. If validation passes: `READY: 0 CRITICAL, 0 HIGH` -- proceed to deployment
624
+
625
+ ### Pre-Deploy Check Integration
626
+
627
+ `/fluent-pre-deploy-check` should invoke this validator if manifest artifacts are found in the deployment scope. This catches manifest issues before they reach a live environment.
628
+
629
+ ### Handoff Signals
630
+
631
+ | Signal | Meaning |
632
+ |--------|---------|
633
+ | `READY: 0 CRITICAL, 0 HIGH` | Manifest passes validation, safe to deploy via `/fluent-settings` |
634
+ | `BLOCKED: N CRITICAL/HIGH issues` | Manifest has structural problems, return to `/fluent-mystique-builder` to fix |
635
+ | `REVIEW: validation-report.md` | Report generated for user review |
636
+ | `NEXT: /fluent-settings` | After passing validation, deploy manifest as a Fluent setting |
637
+ | `NEXT: /fluent-mystique-analyze` | Optional deeper analysis after validation passes |
638
+
639
+ ### Error Format
640
+
641
+ Report errors following the cross-skill convention:
642
+
643
+ - **Skill:** fluent-mystique-validate
644
+ - **Phase:** Schema / Component / Data / Template / Props / CrossManifest
645
+ - **Severity:** CRITICAL / HIGH / MEDIUM / LOW
646
+ - **Recovery:** Specific fix instructions with JSON path