@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.
- package/README.md +866 -622
- package/bin/cli.mjs +2112 -1973
- package/content/cli/agents/fluent-cli/agent.json +149 -149
- package/content/cli/agents/fluent-cli.md +132 -132
- package/content/cli/skills/fluent-bootstrap/SKILL.md +214 -181
- package/content/cli/skills/fluent-cli-index/SKILL.md +1 -1
- package/content/cli/skills/fluent-cli-mcp-cicd/SKILL.md +117 -1
- package/content/cli/skills/fluent-cli-reference/SKILL.md +1040 -1031
- package/content/cli/skills/fluent-cli-retailer/SKILL.md +27 -2
- package/content/cli/skills/fluent-cli-settings/SKILL.md +21 -1
- package/content/cli/skills/fluent-connect/SKILL.md +937 -886
- package/content/cli/skills/fluent-module-deploy/SKILL.md +63 -5
- package/content/cli/skills/fluent-profile/SKILL.md +73 -0
- package/content/cli/skills/fluent-workflow/SKILL.md +360 -310
- package/content/dev/agents/fluent-backend-dev/AGENT.md +58 -0
- package/content/dev/agents/fluent-backend-dev/agent.json +69 -0
- package/content/dev/agents/fluent-backend-dev.md +287 -0
- package/content/dev/agents/fluent-dev/AGENT.md +98 -0
- package/content/dev/agents/fluent-dev/agent.json +14 -2
- package/content/dev/agents/fluent-dev.md +194 -525
- package/content/dev/agents/fluent-frontend-dev/AGENT.md +63 -0
- package/content/dev/agents/fluent-frontend-dev/agent.json +52 -0
- package/content/dev/agents/fluent-frontend-dev.md +323 -0
- package/content/dev/skills/fluent-archive/SKILL.md +234 -0
- package/content/dev/skills/fluent-build/SKILL.md +312 -192
- package/content/dev/skills/fluent-connection-analysis/SKILL.md +422 -386
- package/content/dev/skills/fluent-custom-code/SKILL.md +15 -9
- package/content/dev/skills/fluent-data-module-scaffold/SKILL.md +19 -2
- package/content/dev/skills/fluent-e2e-test/SKILL.md +501 -394
- package/content/dev/skills/fluent-event-api/SKILL.md +962 -945
- package/content/dev/skills/fluent-feature-explain/SKILL.md +680 -603
- package/content/dev/skills/fluent-feature-plan/PLAN_TEMPLATE.md +27 -2
- package/content/dev/skills/fluent-feature-plan/SKILL.md +478 -227
- package/content/dev/skills/fluent-feature-status/SKILL.md +335 -0
- package/content/dev/skills/fluent-feedback/SKILL.md +221 -0
- package/content/dev/skills/fluent-implementation-map/SKILL.md +644 -0
- package/content/dev/skills/fluent-job-batch/SKILL.md +10 -0
- package/content/dev/skills/fluent-module-scaffold/SKILL.md +64 -2
- package/content/dev/skills/fluent-module-validate/SKILL.md +778 -775
- package/content/dev/skills/fluent-mystique-analyze/SKILL.md +817 -0
- package/content/dev/skills/fluent-mystique-builder/COMPONENT_TEMPLATE.md +81 -0
- package/content/dev/skills/fluent-mystique-builder/README.md +63 -0
- package/content/dev/skills/fluent-mystique-builder/SKILL.md +1294 -0
- package/content/dev/skills/fluent-mystique-builder/components/INDEX.md +92 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.accordion.md +48 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.fulfilmentpack.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.multiparcel.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.returnitems.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.action.field.wavepick.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.action.inline.md +24 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.activity.entity.md +25 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.analytics.viz.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.column.md +111 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.json.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.jsoneditor.md +54 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.locationId.md +51 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.attribute.retailerId.md +52 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.bar.md +57 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.download.md +53 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.inline.compatibility.md +60 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.inline.md +53 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.md +24 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.button.print.pick.md +61 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.buttons.add.reject.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.attribute.md +73 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.attributes.grid.md +40 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.image.md +37 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.map.point.md +24 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.multi.md +79 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.card.product.md +27 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.area.md +34 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.area.wrapper.feed.md +98 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.bar.md +52 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.bar.wrapper.source.md +104 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.gauge.md +28 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.gauge.wrapper.threshold.md +118 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.chart.line.md +32 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.conditional.md +62 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.dashboard.threshold.md +65 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.daterange.wrapper.forwarder.md +56 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.drawer.button.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.event.detail.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.events.search.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.field.daterange.md +83 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.field.filterComplex.md +106 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.field.intrange.md +82 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.field.multistring.md +50 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.filterPanel.md +53 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.json.editor.md +22 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.json.viewer.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.list.customAction.md +79 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.list.md +116 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.bppmetrics.md +69 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.feed.md +65 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.list.wrapper.source.md +64 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.modal.button.addItem.md +60 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.modal.button.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.mutation.inline.md +88 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.collapsible.attributes.md +83 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.collapsible.text.md +33 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.mystique.link.md +30 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.order.itemDetails.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.order.shipmentDetails.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.filter.select.md +87 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.md +64 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.refresh.md +48 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.column.md +71 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.header.md +61 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.section.md +59 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.wizard.md +45 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.page.wizard.summary.md +56 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.progress.circular.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.provider.graphql.md +71 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.quantity.list.md +87 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.repeater.md +56 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.reports.ipuipc.md +54 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.return.rowExpansion.md +19 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.barcode.md +21 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.barcodeFilter.md +72 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.scanner.camera.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.settingForm.md +64 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.profile.drawer.button.md +19 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.profile.modal.button.md +64 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.sourcing.strategy.modal.button.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.stepper.md +20 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.tab.content.md +56 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.tabs.card.md +64 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.tabs.md +69 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.tile.metric.md +73 -0
- package/content/dev/skills/fluent-mystique-builder/components/fc.workflow.provider.md +77 -0
- package/content/dev/skills/fluent-mystique-builder/validate-docs.ps1 +260 -0
- package/content/dev/skills/fluent-mystique-scaffold/SKILL.md +1830 -0
- package/content/dev/skills/fluent-mystique-validate/SKILL.md +646 -0
- package/content/dev/skills/fluent-pre-deploy-check/SKILL.md +1144 -1108
- package/content/dev/skills/fluent-retailer-config/SKILL.md +1162 -1111
- package/content/dev/skills/fluent-rollback/SKILL.md +387 -0
- package/content/dev/skills/fluent-rule-scaffold/SKILL.md +515 -385
- package/content/dev/skills/fluent-scope-decompose/SKILL.md +1123 -1021
- package/content/dev/skills/fluent-session-audit-export/SKILL.md +880 -632
- package/content/dev/skills/fluent-session-summary/SKILL.md +320 -195
- package/content/dev/skills/fluent-settings/SKILL.md +160 -1
- package/content/dev/skills/fluent-source-onboard/SKILL.md +31 -3
- package/content/dev/skills/fluent-sourcing/SKILL.md +1185 -0
- package/content/dev/skills/fluent-system-monitoring/SKILL.md +771 -767
- package/content/dev/skills/fluent-test-data/SKILL.md +514 -513
- package/content/dev/skills/fluent-trace/SKILL.md +1169 -1143
- package/content/dev/skills/fluent-transition-api/SKILL.md +364 -346
- package/content/dev/skills/fluent-use-case-discover/SKILL.md +593 -0
- package/content/dev/skills/fluent-use-case-discover/SPEC_TEMPLATE.md +281 -0
- package/content/dev/skills/fluent-version-manage/SKILL.md +53 -2
- package/content/dev/skills/fluent-workflow-analyzer/SKILL.md +995 -959
- package/content/dev/skills/fluent-workflow-builder/SKILL.md +668 -319
- package/content/dev/skills/fluent-workflow-deploy/SKILL.md +480 -267
- package/content/dev/skills/fluent-workspace-tree/SKILL.md +281 -0
- package/content/mcp-extn/agents/fluent-mcp.md +133 -69
- package/content/mcp-extn/skills/fluent-mcp-tools/SKILL.md +812 -461
- package/content/mcp-official/agents/fluent-mcp-core.md +91 -91
- package/content/mcp-official/skills/fluent-mcp-core/SKILL.md +94 -94
- package/content/rfl/skills/fluent-rfl-assess/SKILL.md +172 -172
- package/docs/CAPABILITY_MAP.md +106 -77
- package/docs/DEPLOYMENT_PROMOTION_RUNBOOK.md +218 -0
- package/docs/DESIGN-implementation-map.md +698 -0
- package/docs/DEV_WORKFLOW.md +814 -802
- package/docs/FLOW_RUN.md +142 -142
- package/docs/GETTING_STARTED.md +427 -0
- package/docs/USE_CASES.md +909 -52
- package/metadata.json +184 -156
- 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
|