gaia-framework 1.66.0 → 1.87.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/gaia-create-stakeholder.md +20 -0
- package/.claude/commands/gaia-test-gap-analysis.md +17 -0
- package/CLAUDE.md +87 -1
- package/README.md +2 -2
- package/_gaia/_config/global.yaml +5 -1
- package/_gaia/_config/lifecycle-sequence.yaml +20 -0
- package/_gaia/_config/skill-manifest.csv +2 -0
- package/_gaia/_config/workflow-manifest.csv +3 -1
- package/_gaia/core/engine/workflow.xml +5 -1
- package/_gaia/core/workflows/party-mode/steps/step-01-agent-loading.md +60 -9
- package/_gaia/creative/workflows/problem-solving/checklist.md +64 -14
- package/_gaia/creative/workflows/problem-solving/instructions.xml +367 -22
- package/_gaia/creative/workflows/problem-solving/workflow.yaml +31 -1
- package/_gaia/dev/agents/_base-dev.md +13 -2
- package/_gaia/dev/skills/_skill-index.yaml +15 -0
- package/_gaia/dev/skills/figma-integration.md +498 -0
- package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +228 -0
- package/_gaia/lifecycle/templates/gap-entry-schema.md +39 -4
- package/_gaia/lifecycle/templates/story-template.md +29 -1
- package/_gaia/lifecycle/workflows/2-planning/create-ux-design/instructions.xml +96 -3
- package/_gaia/lifecycle/workflows/4-implementation/code-review/instructions.xml +10 -0
- package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/checklist.md +25 -0
- package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/instructions.xml +79 -0
- package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/workflow.yaml +22 -0
- package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +10 -0
- package/_gaia/lifecycle/workflows/4-implementation/dev-story/instructions.xml +10 -0
- package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +3 -3
- package/_gaia/lifecycle/workflows/4-implementation/validate-story/instructions.xml +11 -0
- package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +11 -7
- package/_gaia/testing/workflows/test-gap-analysis/checklist.md +8 -0
- package/_gaia/testing/workflows/test-gap-analysis/instructions.xml +53 -0
- package/_gaia/testing/workflows/test-gap-analysis/workflow.yaml +38 -0
- package/bin/gaia-framework.js +36 -2
- package/bin/helpers/derive-bump-label.js +41 -0
- package/bin/helpers/validate-bump-labels.js +38 -0
- package/gaia-install.sh +71 -4
- package/package.json +1 -1
- package/_gaia/_memory/tier2-results/.gitkeep +0 -0
- package/_gaia/_memory/tier2-results/checkpoint-resume-2026-03-24.yaml +0 -6
- package/_gaia/_memory/tier2-results/engine-scenarios-2026-03-22.yaml +0 -14
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: figma-integration
|
|
3
|
+
version: '1.0'
|
|
4
|
+
requires_mcp: design-tool
|
|
5
|
+
applicable_agents: [typescript-dev, angular-dev, flutter-dev, java-dev, python-dev, mobile-dev]
|
|
6
|
+
test_scenarios:
|
|
7
|
+
- scenario: Figma MCP server available and healthy
|
|
8
|
+
expected: Mode selection (Generate/Import/Skip) presented to user
|
|
9
|
+
- scenario: Figma MCP server not installed
|
|
10
|
+
expected: Silent fallback to markdown-only, no error or warning
|
|
11
|
+
- scenario: Figma MCP server not running
|
|
12
|
+
expected: Silent fallback to markdown-only, no error or warning
|
|
13
|
+
- scenario: Figma API token expired
|
|
14
|
+
expected: Warning displayed, fallback to markdown-only
|
|
15
|
+
- scenario: Rate limited (429)
|
|
16
|
+
expected: Single retry after delay, fallback with warning if retry fails
|
|
17
|
+
- scenario: Timeout exceeding 5 seconds
|
|
18
|
+
expected: Fallback with warning, continue markdown-only
|
|
19
|
+
- scenario: Design tool detection via MCP probe
|
|
20
|
+
expected: Correct adapter selected based on available MCP tool prefix
|
|
21
|
+
- scenario: Token extraction produces W3C DTCG format
|
|
22
|
+
expected: design-tokens.json contains $type/$value structure with semantic aliases
|
|
23
|
+
- scenario: Component spec extraction
|
|
24
|
+
expected: component-specs.yaml contains typed props, abstract layout, and states
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
**DesignToolProvider Interface** — abstract interface for design tool integrations. Adapters implement these 5 operations:
|
|
28
|
+
|
|
29
|
+
| Operation | Description | Returns |
|
|
30
|
+
|-----------|-------------|---------|
|
|
31
|
+
| `detect()` | Probe MCP tools to identify available design tool | Adapter instance or null |
|
|
32
|
+
| `getTokens()` | Extract design tokens from the design file | W3C DTCG JSON (`design-tokens.json`) |
|
|
33
|
+
| `getComponents()` | Extract component specifications | YAML spec (`component-specs.yaml`) |
|
|
34
|
+
| `getFrames()` | Generate UI kit frames across viewports | Frame metadata for UI kit page |
|
|
35
|
+
| `exportAssets()` | Export images and icons at required densities | Asset files in `assets/` directory |
|
|
36
|
+
|
|
37
|
+
**Adapter Implementations:**
|
|
38
|
+
- **FigmaAdapter** (active) — wraps `figma_*` / `figma/` MCP tools (e.g., `figma/get_file`, `figma/get_styles`, `figma/get_components`). Detected when MCP tools matching prefix `figma` are available.
|
|
39
|
+
- **PenpotAdapter** (planned) — will wrap `penpot_*` MCP tools. Detected via `penpot_` prefix. Not yet implemented.
|
|
40
|
+
- **SketchAdapter** (planned) — will wrap `sketch_*` MCP tools. Detected via `sketch_` prefix. Not yet implemented.
|
|
41
|
+
|
|
42
|
+
**Selection logic:** probe MCP tool list for known prefixes in order: `figma_` / `figma/` → `penpot_` → `sketch_`. Use the first match. If none found, report "No design tool MCP server detected."
|
|
43
|
+
|
|
44
|
+
**Zero-change path:** When no `figma:` metadata block is present in the story file or ux-design.md, all Figma-related operations are skipped — the dev agent reads ux-design.md text as-is (no MCP calls, no cache reads, no design system files generated). **MCP constraint (FR-140):** operations are read-heavy/write-light; most interactions read design data (tokens, components, styles). Write operations are limited to frame generation and are documented per section.
|
|
45
|
+
|
|
46
|
+
**Response Cache and Offline Fallback (NFR-028):** MCP responses are cached in `{project-path}/.figma-cache/` (gitignored) with composite key `{file_key}:{page_id}:{design_version_hash}`, where the version hash derives from the Figma file's `lastModified` timestamp. The version hash is the primary invalidation signal — a changed design always triggers a fresh MCP call. A 1-hour TTL serves as secondary expiry when version metadata cannot be fetched. When the MCP server is unreachable and the cache TTL has expired, the skill continues with last-known-good files from `.figma-cache/`, emitting an `[OFFLINE]` warning logged in the story's dev record — stale design data is preferable to blocking implementation.
|
|
47
|
+
|
|
48
|
+
<!-- SECTION: detection -->
|
|
49
|
+
## Detection Probe
|
|
50
|
+
|
|
51
|
+
Detect Figma MCP server availability using a lightweight, read-only probe call.
|
|
52
|
+
This section is consumed by `/gaia-create-ux` at workflow start.
|
|
53
|
+
|
|
54
|
+
> **Security mandate:** NEVER persist Figma API tokens in any GAIA file — checkpoints, sidecars, logs, or artifacts. MCP auth is handled by the MCP server process; GAIA does not touch tokens.
|
|
55
|
+
|
|
56
|
+
> **Detection-only mandate:** GAIA MUST never install, configure, or modify the MCP server. Detection is read-only — probe for availability via `figma/get_user_info` or tool listing, nothing more.
|
|
57
|
+
|
|
58
|
+
### Probe Call
|
|
59
|
+
|
|
60
|
+
Use `figma/get_user_info` as the detection probe:
|
|
61
|
+
- Read-only, lightweight, validates both connectivity and token validity
|
|
62
|
+
- 5-second hard timeout (NFR-026 compliance)
|
|
63
|
+
- Zero added latency when MCP is not available (silent skip)
|
|
64
|
+
|
|
65
|
+
### Detection Flow
|
|
66
|
+
|
|
67
|
+
1. **Attempt probe:** call `figma/get_user_info` with a 5-second hard timeout
|
|
68
|
+
2. **On success:** set `figma_mcp_available = true`, proceed to mode selection
|
|
69
|
+
3. **On failure:** classify the failure and handle per the failure mode table below
|
|
70
|
+
|
|
71
|
+
### Failure Mode Handling
|
|
72
|
+
|
|
73
|
+
| Failure | Detection Signal | Behavior |
|
|
74
|
+
|---------|-----------------|----------|
|
|
75
|
+
| **Not installed** (AC5) | Tool not found / tool not available | Silent fallback to markdown-only mode — no error, no warning, no prompt |
|
|
76
|
+
| **Not running** (AC6) | Connection refused / connection error | Silent fallback to markdown-only mode — no error, no warning, no prompt |
|
|
77
|
+
| **Token expired** (AC7) | 401 or 403 response from `figma/get_user_info` | Warn: "Figma token expired — falling back to markdown" then continue markdown-only |
|
|
78
|
+
| **Rate limited** (AC8) | 429 response | Retry once after `Retry-After` header delay (default: 2 seconds). If retry also fails, warn and fallback to markdown-only |
|
|
79
|
+
| **Timeout** (AC9) | No response within 5-second hard timeout | Warn: "Figma MCP did not respond within 5 seconds — falling back to markdown" then continue markdown-only |
|
|
80
|
+
| **Malformed response** | Unexpected or partial data | Treat as unavailable — silent fallback to markdown-only |
|
|
81
|
+
|
|
82
|
+
### Mode Selection (on success)
|
|
83
|
+
|
|
84
|
+
When `figma_mcp_available == true`, present the user with:
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Figma MCP detected. Select UX design mode:
|
|
88
|
+
[g] Generate — AI-generated UX with Figma export
|
|
89
|
+
[i] Import — Import existing Figma designs into GAIA
|
|
90
|
+
[s] Skip — Proceed with markdown-only (ignore Figma)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Minimum API Scopes
|
|
94
|
+
|
|
95
|
+
The Figma API token used by the MCP server requires these minimum scopes:
|
|
96
|
+
|
|
97
|
+
| Scope | Required For | Mode |
|
|
98
|
+
|-------|-------------|------|
|
|
99
|
+
| `files:read` | Reading design files, styles, components | Default (all modes) |
|
|
100
|
+
| `file_content:read` | Reading file content, nodes, images | Default (all modes) |
|
|
101
|
+
| `files:write` | Creating frames, writing to design files | Generate mode only |
|
|
102
|
+
|
|
103
|
+
Scope enforcement is the MCP server's responsibility — GAIA documents scope expectations only and does not validate or request token scopes.
|
|
104
|
+
|
|
105
|
+
### Error Sanitization Rules
|
|
106
|
+
|
|
107
|
+
All error messages from MCP operations MUST follow this safe error format:
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
Figma MCP error: {status_code} — {generic_description}. Falling back to markdown-only workflow.
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Disallowed content in error messages:** Figma file URLs, file keys, node IDs, design data, access tokens, or any dynamic content from the Figma API response.
|
|
114
|
+
|
|
115
|
+
| Status Code | Generic Description |
|
|
116
|
+
|-------------|-------------------|
|
|
117
|
+
| 401 | Authentication failed |
|
|
118
|
+
| 403 | Access denied |
|
|
119
|
+
| 404 | Resource not found |
|
|
120
|
+
| 429 | Rate limit exceeded — retry once, then fallback |
|
|
121
|
+
| 500 | Server error |
|
|
122
|
+
|
|
123
|
+
### Security Boundary
|
|
124
|
+
|
|
125
|
+
- The Figma API token lives exclusively in the MCP server configuration (ADR-024)
|
|
126
|
+
- GAIA files must NEVER contain or log Figma tokens, API keys, or credentials
|
|
127
|
+
- Detection probe interacts through MCP tool abstraction only — no direct HTTP calls
|
|
128
|
+
|
|
129
|
+
### Traceability
|
|
130
|
+
|
|
131
|
+
- FR-132: Figma MCP detection probe requirement
|
|
132
|
+
- FR-143: Graceful MCP failure handling
|
|
133
|
+
- NFR-026: MCP detection latency < 5 seconds
|
|
134
|
+
- ADR-024: Figma MCP integration via shared skill
|
|
135
|
+
|
|
136
|
+
<!-- SECTION: tokens -->
|
|
137
|
+
## Design Token Extraction
|
|
138
|
+
|
|
139
|
+
> **Security mandate:** MCP auth is handled by the MCP server — NEVER persist or reference Figma API tokens in extraction outputs, logs, or GAIA files.
|
|
140
|
+
|
|
141
|
+
Extract design tokens from the connected design tool and output in W3C DTCG format.
|
|
142
|
+
|
|
143
|
+
### Extraction Steps
|
|
144
|
+
|
|
145
|
+
1. **Fetch styles** — call `figma/get_styles` to retrieve all published styles (colors, typography, effects, grids)
|
|
146
|
+
2. **Map to W3C DTCG** — transform each style into the W3C Design Tokens Community Group draft format:
|
|
147
|
+
```json
|
|
148
|
+
{
|
|
149
|
+
"color": {
|
|
150
|
+
"primary": { "$type": "color", "$value": "#3B82F6", "$description": "Brand primary" }
|
|
151
|
+
},
|
|
152
|
+
"spacing": {
|
|
153
|
+
"sm": { "$type": "dimension", "$value": "8px" }
|
|
154
|
+
},
|
|
155
|
+
"typography": {
|
|
156
|
+
"heading-1": {
|
|
157
|
+
"$type": "typography",
|
|
158
|
+
"$value": { "fontFamily": "Inter", "fontSize": "32px", "fontWeight": 700, "lineHeight": 1.2 }
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
3. **Include semantic aliases** — map raw tokens to semantic names (e.g., `color.surface.primary` → `color.blue.500`)
|
|
164
|
+
4. **Add composite tokens** — typography composites, shadow composites, border-radius scales
|
|
165
|
+
5. **Write output** — save to `{planning_artifacts}/design-system/design-tokens.json` with `"schema_version": "1.0"`
|
|
166
|
+
|
|
167
|
+
<!-- SECTION: components -->
|
|
168
|
+
## Component Spec Extraction
|
|
169
|
+
|
|
170
|
+
> **Security mandate:** MCP auth is handled by the MCP server — NEVER include Figma API tokens in component specs, logs, or any GAIA output files.
|
|
171
|
+
|
|
172
|
+
Extract component specifications into a tech-agnostic intermediate format.
|
|
173
|
+
|
|
174
|
+
### Extraction Steps
|
|
175
|
+
|
|
176
|
+
1. **Fetch components** — call `figma/get_components` to list all published components and variants
|
|
177
|
+
2. **For each component**, extract:
|
|
178
|
+
- **name** — component name (PascalCase)
|
|
179
|
+
- **props** — typed properties: `{ name: string, type: "string"|"number"|"boolean"|"enum", values?: string[] }`
|
|
180
|
+
- **layout** — abstract layout type: `row | column | stack | grid` with spacing via token references (`{spacing.sm}`)
|
|
181
|
+
- **states** — `[default, hover, active, disabled, focus]` with visual diff per state
|
|
182
|
+
- **children** — nested component references with slot definitions
|
|
183
|
+
- **variants** — named variants with their property overrides
|
|
184
|
+
- **responsive** — breakpoint behavior at 375px, 768px, 1280px
|
|
185
|
+
- **a11y** — role, aria-label pattern, description, keyboard interaction
|
|
186
|
+
3. **Write output** — save to `{planning_artifacts}/design-system/component-specs.yaml` with `schema_version: "1.0"`
|
|
187
|
+
|
|
188
|
+
### Output Schema
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
schema_version: "1.0"
|
|
192
|
+
components:
|
|
193
|
+
- name: Button
|
|
194
|
+
props:
|
|
195
|
+
- { name: label, type: string }
|
|
196
|
+
- { name: variant, type: enum, values: [primary, secondary, ghost] }
|
|
197
|
+
- { name: disabled, type: boolean }
|
|
198
|
+
layout: { type: row, gap: "{spacing.sm}" }
|
|
199
|
+
states: [default, hover, active, disabled, focus]
|
|
200
|
+
a11y: { role: button, label: "{props.label}" }
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
<!-- SECTION: frames -->
|
|
204
|
+
## Frame Generation
|
|
205
|
+
|
|
206
|
+
> **Security mandate:** MCP auth is handled by the MCP server — NEVER persist Figma API tokens in frame metadata, logs, or any GAIA output files.
|
|
207
|
+
|
|
208
|
+
Create UI kit frames in the design tool across standard viewports.
|
|
209
|
+
|
|
210
|
+
### Generation Steps
|
|
211
|
+
|
|
212
|
+
1. **Create UI Kit page** — create a dedicated page named "UI Kit — Generated" in the design file
|
|
213
|
+
2. **For each screen** defined in the UX design:
|
|
214
|
+
- Create 3 viewport frames: mobile (375px), tablet (768px), desktop (1280px)
|
|
215
|
+
- Apply auto-layout with responsive constraints from component specs
|
|
216
|
+
- Place components using the extracted component specs and token values
|
|
217
|
+
3. **Add prototype flows** — link frames with interaction flows matching the UX navigation spec
|
|
218
|
+
4. **Label frames** — use naming convention: `{ScreenName}/{Viewport}` (e.g., `Dashboard/Desktop`)
|
|
219
|
+
|
|
220
|
+
### Output
|
|
221
|
+
|
|
222
|
+
Frame metadata logged for verification. No file output — frames are created directly in the design tool via MCP calls (`figma/create_frame`, `figma/create_component_instance`).
|
|
223
|
+
|
|
224
|
+
<!-- SECTION: assets -->
|
|
225
|
+
## Asset Export
|
|
226
|
+
|
|
227
|
+
> **Security mandate:** MCP auth is handled by the MCP server — NEVER include Figma API tokens in asset manifests, export logs, or any GAIA output files.
|
|
228
|
+
|
|
229
|
+
Export raster and vector assets from the design tool at required densities.
|
|
230
|
+
|
|
231
|
+
### Export Steps
|
|
232
|
+
|
|
233
|
+
1. **Identify exportable nodes** — scan the design file for nodes marked as exportable (icons, images, illustrations)
|
|
234
|
+
2. **Export icons** as SVG — call `figma/get_images` with `format: svg` for all icon nodes
|
|
235
|
+
3. **Export images** as PNG at 3 densities — call `figma/get_images` with `format: png` and `scale: 1`, `scale: 2`, `scale: 3` for image nodes
|
|
236
|
+
4. **Organize output** into directory structure:
|
|
237
|
+
```
|
|
238
|
+
{planning_artifacts}/design-system/assets/
|
|
239
|
+
├── icons/ # SVG icons
|
|
240
|
+
│ ├── icon-name.svg
|
|
241
|
+
├── images/ # PNG images at 1x/2x/3x
|
|
242
|
+
│ ├── image-name@1x.png
|
|
243
|
+
│ ├── image-name@2x.png
|
|
244
|
+
│ └── image-name@3x.png
|
|
245
|
+
```
|
|
246
|
+
5. **Generate asset manifest** — list all exported assets with dimensions and file sizes
|
|
247
|
+
|
|
248
|
+
<!-- SECTION: export -->
|
|
249
|
+
## Per-Stack Token Resolution
|
|
250
|
+
|
|
251
|
+
> **Security mandate:** MCP auth is handled by the MCP server — NEVER embed Figma API tokens in generated token files, stack outputs, or any GAIA output files.
|
|
252
|
+
|
|
253
|
+
Maps abstract design tokens to framework-specific implementations. Each dev agent uses this table to generate native code from `design-tokens.json`.
|
|
254
|
+
|
|
255
|
+
| Agent | Stack | Token Format | Example |
|
|
256
|
+
|-------|-------|-------------|---------|
|
|
257
|
+
| Cleo | TypeScript/React | CSS custom properties | `--color-primary: #3B82F6;` in `:root {}` |
|
|
258
|
+
| Lena | Angular | SCSS variables + CSS custom properties | `$color-primary: #3B82F6;` in `_tokens.scss` |
|
|
259
|
+
| Freya | Flutter/Dart | ThemeData extensions | `ThemeData(primaryColor: Color(0xFF3B82F6))` |
|
|
260
|
+
| Hugo | Java/Spring | Spring properties + Java constants | `design.color.primary=#3B82F6` in `application.properties` |
|
|
261
|
+
| Ravi | Python | Python dict constants | `TOKENS = {"color": {"primary": "#3B82F6"}}` in `design_tokens.py` |
|
|
262
|
+
| Talia | Mobile (RN/Swift/Compose) | RN StyleSheet / Swift extensions / Compose theme | `StyleSheet.create({primary: '#3B82F6'})` or `extension UIColor { static let primary = UIColor(hex: "3B82F6") }` or `val Primary = Color(0xFF3B82F6)` |
|
|
263
|
+
|
|
264
|
+
### Resolution Process
|
|
265
|
+
|
|
266
|
+
1. Read `design-tokens.json` (W3C DTCG format) from `{planning_artifacts}/design-system/`
|
|
267
|
+
2. Read `component-specs.yaml` from the same directory for component definitions and widget hints
|
|
268
|
+
3. Identify the active dev agent's stack from the agent persona
|
|
269
|
+
4. For each token, generate the stack-native representation using the table above
|
|
270
|
+
5. For each component, use the `widget_hints` field to guide framework-specific widget/component tree generation
|
|
271
|
+
6. Output token files to the project's design system directory (stack-specific path)
|
|
272
|
+
|
|
273
|
+
### Token Path Resolution Rules
|
|
274
|
+
|
|
275
|
+
Token paths use `{group.token}` syntax. The resolution pattern per stack:
|
|
276
|
+
|
|
277
|
+
| Stack | Pattern | Example Path | Resolved Output |
|
|
278
|
+
|-------|---------|-------------|-----------------|
|
|
279
|
+
| TypeScript/React | `--{group}-{token}` | `{color.blue-500}` | `var(--color-blue-500)` |
|
|
280
|
+
| Angular | `${group}-{token}` | `{spacing.4}` | `$spacing-4` |
|
|
281
|
+
| Flutter/Dart | `AppTokens.{group}.{token}` | `{typography.body}` | `AppTokens.typography.body` |
|
|
282
|
+
| Java/Spring | `design.{group}.{token}` | `{color.interactive-primary}` | `design.color.interactive-primary` |
|
|
283
|
+
| Python | `TOKENS['{group}']['{token}']` | `{shadow.md}` | `TOKENS['shadow']['md']` |
|
|
284
|
+
| Mobile (RN) | `tokens.{group}.{token}` | `{borderRadius.md}` | `tokens.borderRadius.md` |
|
|
285
|
+
| Mobile (Swift) | `DesignTokens.{group}.{token}` | `{color.blue-500}` | `DesignTokens.color.blue500` |
|
|
286
|
+
| Mobile (Compose) | `AppTheme.{group}.{token}` | `{spacing.2}` | `AppTheme.spacing.s2` |
|
|
287
|
+
|
|
288
|
+
### Semantic Alias Resolution
|
|
289
|
+
|
|
290
|
+
Semantic tokens reference primitives via `{group.token}` syntax in their `$value` field. When generating stack-specific code, resolve the alias chain to produce the final value. Example:
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
"interactive-primary": { "$type": "color", "$value": "{color.blue-500}" }
|
|
294
|
+
→ resolves to → #3B82F6
|
|
295
|
+
→ CSS: --color-interactive-primary: #3B82F6;
|
|
296
|
+
→ SCSS: $color-interactive-primary: #3B82F6;
|
|
297
|
+
→ Dart: static const interactivePrimary = Color(0xFF3B82F6);
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
<!-- SECTION: import-detection -->
|
|
301
|
+
## Import Mode — Detection and Entry Point
|
|
302
|
+
|
|
303
|
+
Import mode reverses the Generate flow: reads existing Figma designs INTO GAIA (Figma → ux-design.md) instead of generating Figma frames FROM GAIA. Uses only read operations from the DesignToolProvider interface: `detect()`, `getTokens()`, `getComponents()`, `getFrames()`. No `exportAssets()` needed.
|
|
304
|
+
|
|
305
|
+
### Import Entry Point
|
|
306
|
+
|
|
307
|
+
The detection probe mode selection menu (from E13-S1) presents three options: **Generate** | **Import** | **Skip**. When the user selects Import mode:
|
|
308
|
+
|
|
309
|
+
1. **Accept input** — prompt for Figma file URL or raw file key
|
|
310
|
+
2. **Parse URL** — extract file key from `https://www.figma.com/file/{key}/...` format, or accept raw key directly
|
|
311
|
+
3. **Validate file key** — issue a lightweight `figma/get_file` MCP call with `depth=1` (metadata only) to confirm the file exists and is accessible
|
|
312
|
+
4. **Handle errors:**
|
|
313
|
+
- Invalid key format → client-side rejection, no MCP call
|
|
314
|
+
- 404 not found → "Figma file not found. Verify the file key or URL."
|
|
315
|
+
- 403 permission denied → "Access denied. Ensure the file is shared with your Figma account."
|
|
316
|
+
- 429 rate limited → single retry after 1-second delay; if retry fails, abort gracefully
|
|
317
|
+
- 5-second timeout → "MCP server unresponsive. Import aborted." (per E13-S1 hard limit)
|
|
318
|
+
|
|
319
|
+
### API Scopes
|
|
320
|
+
|
|
321
|
+
Import mode uses only read scopes: `files:read` and `file_content:read`. No write operations are performed on the Figma file — import is strictly read-only.
|
|
322
|
+
|
|
323
|
+
<!-- SECTION: import-discovery -->
|
|
324
|
+
## Import Mode — Page and Frame Discovery
|
|
325
|
+
|
|
326
|
+
Enumerate all pages and top-level frames from the Figma file to build a complete document tree.
|
|
327
|
+
|
|
328
|
+
### Discovery Steps
|
|
329
|
+
|
|
330
|
+
1. **Fetch full document tree** — call `figma/get_file` with full depth to retrieve the complete document tree
|
|
331
|
+
2. **Extract pages** — parse response for top-level CANVAS nodes (Figma's page type)
|
|
332
|
+
3. **Extract frames** — within each CANVAS, collect FRAME nodes with metadata: name, nodeId, absoluteBoundingBox (x, y, width, height)
|
|
333
|
+
4. **Build Page → Frames hierarchy** — structure: `{ page: { name, nodeId, frames: [{ name, nodeId, width, height }] } }`
|
|
334
|
+
5. **Classify frames by viewport** — based on absoluteBoundingBox width:
|
|
335
|
+
- Mobile: width ≤ 480px
|
|
336
|
+
- Tablet: width 481–1024px
|
|
337
|
+
- Desktop: width > 1024px
|
|
338
|
+
6. **Cache response** — store in `{project-path}/.figma-cache/` with 1-hour TTL per ADR-024
|
|
339
|
+
|
|
340
|
+
### Partial Access Handling
|
|
341
|
+
|
|
342
|
+
If some pages or frames are inaccessible (permission restricted), generate a partial ux-design.md with `[PARTIAL]` warnings for inaccessible pages. Do not abort the entire import.
|
|
343
|
+
|
|
344
|
+
### Empty File Handling
|
|
345
|
+
|
|
346
|
+
If the Figma file contains no frames (empty file), generate a minimal ux-design.md with empty screen sections and a note: "No frames found in Figma file."
|
|
347
|
+
|
|
348
|
+
<!-- SECTION: import-tokens -->
|
|
349
|
+
## Import Mode — Design Token Extraction
|
|
350
|
+
|
|
351
|
+
Extract design tokens from an existing Figma file and write them in W3C DTCG format. This reverses the generate flow — reading tokens FROM Figma rather than pushing tokens TO Figma.
|
|
352
|
+
|
|
353
|
+
### Extraction Steps
|
|
354
|
+
|
|
355
|
+
1. **Extract color styles** — read the file's `styles` and `document` nodes. Resolve fill and stroke references to RGBA values. Map named styles to semantic token names using naming pattern: `Primary/500` → `color.primary.500`
|
|
356
|
+
2. **Extract typography styles** — resolve font family, font size, font weight, line height, letter spacing from text style nodes
|
|
357
|
+
3. **Extract effect styles** — resolve drop-shadow and inner-shadow parameters (offsetX, offsetY, blur, spread, color). Also extract blur effect parameters
|
|
358
|
+
4. **Extract spacing from auto-layout** — read auto-layout frame properties: itemSpacing, paddingLeft, paddingRight, paddingTop, paddingBottom
|
|
359
|
+
5. **Map to W3C DTCG format** — each token gets `$type`, `$value`, and optional `$description` per the W3C Design Tokens Community Group draft specification. Composite tokens (typography) use nested structure
|
|
360
|
+
6. **Resolve semantic aliases** — match Figma style names to conventional naming patterns and create alias references (e.g., `color.surface.primary` → `{color.white}`)
|
|
361
|
+
7. **Write output** — save design-tokens.json to `{planning_artifacts}/design-system/` with `schema_version` field
|
|
362
|
+
|
|
363
|
+
### Error messages
|
|
364
|
+
|
|
365
|
+
Log error messages with status codes only — no URLs, file keys, or design data in log output (per E13-S6 / FR-143).
|
|
366
|
+
|
|
367
|
+
<!-- SECTION: import-screens -->
|
|
368
|
+
## Import Mode — Screen Inventory
|
|
369
|
+
|
|
370
|
+
Build a complete screen-to-frame mapping from the discovered page and frame hierarchy.
|
|
371
|
+
|
|
372
|
+
### Screen Inventory Steps
|
|
373
|
+
|
|
374
|
+
1. **Group frames by page** — organize the frame list from import-discovery into page groups
|
|
375
|
+
2. **Build per-frame metadata** — for each frame: name, nodeId, width, height, viewport classification (mobile/tablet/desktop)
|
|
376
|
+
3. **Extract component instances** — for each frame, enumerate component instances used within it. Map to component-specs.yaml format: name, props, layout type
|
|
377
|
+
4. **Generate screen-to-frame mapping** — produce a structured mapping:
|
|
378
|
+
```yaml
|
|
379
|
+
screens:
|
|
380
|
+
- page: "Home"
|
|
381
|
+
frames:
|
|
382
|
+
- name: "Home/Desktop"
|
|
383
|
+
nodeId: "123:456"
|
|
384
|
+
width: 1280
|
|
385
|
+
height: 800
|
|
386
|
+
viewport: desktop
|
|
387
|
+
components: [Button, Card, TextInput]
|
|
388
|
+
```
|
|
389
|
+
5. **Track all node IDs** — every Figma node referenced must include its nodeId for downstream dev agent consumption (E13-S5)
|
|
390
|
+
|
|
391
|
+
<!-- SECTION: import-generate -->
|
|
392
|
+
## Import Mode — Generate ux-design.md
|
|
393
|
+
|
|
394
|
+
Assemble the extracted data into a complete ux-design.md document with Figma metadata frontmatter.
|
|
395
|
+
|
|
396
|
+
### Generation Steps
|
|
397
|
+
|
|
398
|
+
1. **Write `figma:` YAML frontmatter** — include:
|
|
399
|
+
```yaml
|
|
400
|
+
figma:
|
|
401
|
+
file_key: "{extracted_file_key}"
|
|
402
|
+
pages: ["Page 1", "Page 2"]
|
|
403
|
+
node_ids: ["0:1", "123:456", "789:012"]
|
|
404
|
+
imported_at: "{ISO 8601 timestamp}"
|
|
405
|
+
import_mode: true
|
|
406
|
+
```
|
|
407
|
+
2. **Write Design Tokens section** — reference token paths from design-tokens.json (e.g., `{color.primary}`, `{spacing.4}`)
|
|
408
|
+
3. **Write Component Inventory section** — list all components discovered from frame extraction with props and variants
|
|
409
|
+
4. **Write Screen Descriptions** — for each screen: frame name, node ID, viewport classification, component list, and layout description
|
|
410
|
+
5. **Preserve read-only guarantee** — the entire generation step produces only local files. Zero write operations to Figma via MCP. Only `get_file`, `get_file_nodes`, and `get_image` calls are used throughout the import flow
|
|
411
|
+
|
|
412
|
+
### Output Files
|
|
413
|
+
|
|
414
|
+
- `{planning_artifacts}/ux-design.md` — enhanced with `figma:` frontmatter
|
|
415
|
+
- `{planning_artifacts}/design-system/design-tokens.json` — W3C DTCG format
|
|
416
|
+
- `{planning_artifacts}/design-system/component-specs.yaml` — component specs (updated with import data)
|
|
417
|
+
|
|
418
|
+
**Shared formats:** Import mode writes the same intermediate files as Generate mode (design-tokens.json, component-specs.yaml) using identical schemas from E13-S3. This ensures downstream dev agents consume imported designs identically to generated ones.
|
|
419
|
+
|
|
420
|
+
<!-- SECTION: fidelity -->
|
|
421
|
+
## Design-to-Implementation Fidelity Gate
|
|
422
|
+
|
|
423
|
+
Post-implementation verification layer that compares token values in generated code against the approved `design-tokens.json` to detect and measure drift between design intent and implementation. Addresses FR-171 and ADR-024. Consumed by `/gaia-code-review` as a conditional step when the story has a `figma:` frontmatter block.
|
|
424
|
+
|
|
425
|
+
### Token Extraction from Generated Code
|
|
426
|
+
|
|
427
|
+
Scan generated code files for token references using platform-specific patterns:
|
|
428
|
+
|
|
429
|
+
- **CSS custom properties:** `var(--color-primary-500)` maps to `color.primary.500`
|
|
430
|
+
- **SCSS variables:** `$color-primary-500` maps to `color.primary.500`
|
|
431
|
+
- **Flutter ThemeData:** `AppTokens.color.primary500` maps to `color.primary.500`
|
|
432
|
+
- **Spring properties:** `design.tokens.color.primary.500`
|
|
433
|
+
- **Python dict:** `TOKENS['color']['primary.500']`
|
|
434
|
+
- **React Native / Swift / Compose:** platform-specific mappings per the export section resolution table
|
|
435
|
+
|
|
436
|
+
Use the per-stack token resolution table from the `export` section above to reverse-map platform-specific references back to canonical W3C DTCG paths before comparison.
|
|
437
|
+
|
|
438
|
+
### Deep Comparison Engine
|
|
439
|
+
|
|
440
|
+
For each token reference extracted from code:
|
|
441
|
+
|
|
442
|
+
1. Look up the canonical W3C DTCG path in `{planning_artifacts}/design-system/design-tokens.json`
|
|
443
|
+
2. Compare the value used in code against the approved value in design-tokens.json
|
|
444
|
+
3. Classify each token as:
|
|
445
|
+
- **matched** — value in code exactly matches design-tokens.json
|
|
446
|
+
- **drifted** — token exists in design-tokens.json but value differs
|
|
447
|
+
- **missing** — token referenced in code but absent from design-tokens.json
|
|
448
|
+
|
|
449
|
+
### Per-Category Drift Reporting
|
|
450
|
+
|
|
451
|
+
Group all compared tokens by W3C DTCG top-level category:
|
|
452
|
+
|
|
453
|
+
- `color.*` — color palette, semantic colors, surface colors
|
|
454
|
+
- `typography.*` — font families, sizes, weights, line heights
|
|
455
|
+
- `spacing.*` — margins, paddings, gaps
|
|
456
|
+
- `border.*` / `radius.*` — border widths, styles, border-radius values
|
|
457
|
+
|
|
458
|
+
Calculate drift percentage per category using the formula: `drift_pct = (drifted + missing) / total × 100`
|
|
459
|
+
|
|
460
|
+
Generate a structured fidelity report with a per-category breakdown table:
|
|
461
|
+
|
|
462
|
+
| Category | Total | Matched | Drifted | Missing | Drift % | Status |
|
|
463
|
+
|----------|-------|---------|---------|---------|---------|--------|
|
|
464
|
+
| color.* | 20 | 18 | 1 | 1 | 10% | WARN |
|
|
465
|
+
|
|
466
|
+
### Threshold-Based Gating
|
|
467
|
+
|
|
468
|
+
Two configurable thresholds (defaults from FR-171):
|
|
469
|
+
|
|
470
|
+
- **10% WARNING** — drift exceeds 10% in any category: raise a WARNING. Story may continue but issue is flagged.
|
|
471
|
+
- **25% BLOCK** — drift exceeds 25% in any category: story completion is BLOCKED and re-review is required.
|
|
472
|
+
|
|
473
|
+
**Edge case handling:**
|
|
474
|
+
|
|
475
|
+
- **Empty categories** — if a category has zero tokens referenced, skip it (do not report 0/0 as drift)
|
|
476
|
+
- **N=1 single-token categories** — if a category has only one token and it is drifted, flag with a note "Single-token category — flagged but not auto-blocked (N=1 exception)" instead of blocking. Prevents a single mismatched border-radius from blocking an entire story.
|
|
477
|
+
- **Missing design-tokens.json** — if `design-tokens.json` does not exist at the expected path, skip the fidelity check gracefully with a note: "Fidelity check skipped — design-tokens.json not found at {path}." No crash, no block.
|
|
478
|
+
- **Zero tokens consumed** — if generated code references zero tokens (no `figma:` block consumed or no token patterns found), report "N/A — no tokens consumed" and skip the fidelity check.
|
|
479
|
+
|
|
480
|
+
### Report Persistence
|
|
481
|
+
|
|
482
|
+
Save the fidelity report to `{implementation_artifacts}/reviews/{story_key}/fidelity-report.md`. The report includes:
|
|
483
|
+
|
|
484
|
+
- **Timestamp** — ISO 8601 date of the fidelity check
|
|
485
|
+
- **Story key** — the story_key being checked
|
|
486
|
+
- **Token source file path** — path to the design-tokens.json used as baseline
|
|
487
|
+
- **Per-category breakdown table** (as shown above)
|
|
488
|
+
- **Overall drift percentage** — weighted average across all categories
|
|
489
|
+
- **Verdict** — PASS / WARNING / BLOCKED
|
|
490
|
+
|
|
491
|
+
After saving the report, write the overall drift percentage to the story file YAML frontmatter:
|
|
492
|
+
|
|
493
|
+
```yaml
|
|
494
|
+
figma:
|
|
495
|
+
fidelity_drift_pct: 8.5
|
|
496
|
+
```
|
|
497
|
+
|
|
498
|
+
The `figma.fidelity_drift_pct` value is the weighted overall drift across all categories.
|