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.
Files changed (40) hide show
  1. package/.claude/commands/gaia-create-stakeholder.md +20 -0
  2. package/.claude/commands/gaia-test-gap-analysis.md +17 -0
  3. package/CLAUDE.md +87 -1
  4. package/README.md +2 -2
  5. package/_gaia/_config/global.yaml +5 -1
  6. package/_gaia/_config/lifecycle-sequence.yaml +20 -0
  7. package/_gaia/_config/skill-manifest.csv +2 -0
  8. package/_gaia/_config/workflow-manifest.csv +3 -1
  9. package/_gaia/core/engine/workflow.xml +5 -1
  10. package/_gaia/core/workflows/party-mode/steps/step-01-agent-loading.md +60 -9
  11. package/_gaia/creative/workflows/problem-solving/checklist.md +64 -14
  12. package/_gaia/creative/workflows/problem-solving/instructions.xml +367 -22
  13. package/_gaia/creative/workflows/problem-solving/workflow.yaml +31 -1
  14. package/_gaia/dev/agents/_base-dev.md +13 -2
  15. package/_gaia/dev/skills/_skill-index.yaml +15 -0
  16. package/_gaia/dev/skills/figma-integration.md +498 -0
  17. package/_gaia/lifecycle/templates/brownfield-scan-security-prompt.md +228 -0
  18. package/_gaia/lifecycle/templates/gap-entry-schema.md +39 -4
  19. package/_gaia/lifecycle/templates/story-template.md +29 -1
  20. package/_gaia/lifecycle/workflows/2-planning/create-ux-design/instructions.xml +96 -3
  21. package/_gaia/lifecycle/workflows/4-implementation/code-review/instructions.xml +10 -0
  22. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/checklist.md +25 -0
  23. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/instructions.xml +79 -0
  24. package/_gaia/lifecycle/workflows/4-implementation/create-stakeholder/workflow.yaml +22 -0
  25. package/_gaia/lifecycle/workflows/4-implementation/create-story/instructions.xml +10 -0
  26. package/_gaia/lifecycle/workflows/4-implementation/dev-story/instructions.xml +10 -0
  27. package/_gaia/lifecycle/workflows/4-implementation/retrospective/instructions.xml +3 -3
  28. package/_gaia/lifecycle/workflows/4-implementation/validate-story/instructions.xml +11 -0
  29. package/_gaia/lifecycle/workflows/anytime/brownfield-onboarding/instructions.xml +11 -7
  30. package/_gaia/testing/workflows/test-gap-analysis/checklist.md +8 -0
  31. package/_gaia/testing/workflows/test-gap-analysis/instructions.xml +53 -0
  32. package/_gaia/testing/workflows/test-gap-analysis/workflow.yaml +38 -0
  33. package/bin/gaia-framework.js +36 -2
  34. package/bin/helpers/derive-bump-label.js +41 -0
  35. package/bin/helpers/validate-bump-labels.js +38 -0
  36. package/gaia-install.sh +71 -4
  37. package/package.json +1 -1
  38. package/_gaia/_memory/tier2-results/.gitkeep +0 -0
  39. package/_gaia/_memory/tier2-results/checkpoint-resume-2026-03-24.yaml +0 -6
  40. package/_gaia/_memory/tier2-results/engine-scenarios-2026-03-22.yaml +0 -14
@@ -3,6 +3,7 @@
3
3
  > Brownfield deep analysis scan subagent. Detects security gaps in API endpoints and infrastructure security configurations.
4
4
  > Reference: Architecture ADR-021, Section 10.15.2, Section 10.15.5, ADR-022 §10.16.5
5
5
  > Infra-awareness: E12-S6 — applies infra-specific patterns when project_type is infrastructure or platform.
6
+ > Non-REST protocols: E11-S17 — GraphQL and gRPC endpoint detection and security gap scanning.
6
7
 
7
8
  ## Objective
8
9
 
@@ -51,6 +52,89 @@ Apply framework-specific patterns based on {tech_stack}:
51
52
 
52
53
  If no API endpoints are detected, output a summary note and zero gap entries for the application phase.
53
54
 
55
+ ## Phase 1b: GraphQL Endpoint Discovery
56
+
57
+ Catalog all GraphQL endpoints. For each endpoint, record: operation type (query/mutation/subscription), resolver function, authentication directives, authorization checks.
58
+
59
+ ### Schema-First Detection Patterns
60
+
61
+ - `.graphql` and `.gql` schema files
62
+ - `type Query { ... }` and `type Mutation { ... }` blocks in schema files
63
+ - `typeDefs` variable definitions in JS/TS files (template literals with SDL)
64
+
65
+ ### Code-First Detection Patterns
66
+
67
+ - `@Resolver()` decorators (NestJS, TypeGraphQL)
68
+ - `@Query()` and `@Mutation()` decorators
69
+ - `resolvers` objects exported from modules
70
+ - Python class-based resolvers (Strawberry `@strawberry.type`, Ariadne `@query_type.field`)
71
+ - Go resolver structs (gqlgen `resolver.go` files)
72
+
73
+ ### GraphQL Framework Variants
74
+
75
+ Apply framework-specific patterns based on detected GraphQL library:
76
+
77
+ | Framework | Language | Detection Pattern |
78
+ |---|---|---|
79
+ | Apollo Server | Node/TS | `ApolloServer`, `@apollo/server`, Apollo plugins |
80
+ | GraphQL Yoga | Node/TS | `createYoga`, `@graphql-yoga/node` |
81
+ | Mercurius | Node/TS (Fastify) | `mercurius`, `app.graphql` |
82
+ | Strawberry | Python | `strawberry.Schema`, `@strawberry.type` |
83
+ | gqlgen | Go | `gqlgen.yml`, `generated.go`, resolver structs |
84
+ | Ariadne | Python | `ariadne`, `make_executable_schema` |
85
+ | NestJS GraphQL | Node/TS | `@nestjs/graphql`, `@Resolver()`, `@Query()`, `@Mutation()` |
86
+
87
+ ### GraphQL Middleware Chain Detection
88
+
89
+ - `graphql-shield` rule trees (`const permissions = shield({ ... })`)
90
+ - `@UseGuards(AuthGuard)` decorators (NestJS)
91
+ - Apollo Server plugins (`ApolloServerPlugin` implementing `requestDidStart`)
92
+ - Yoga plugins (`useAuth`, custom `envelop` plugins)
93
+ - Custom context resolvers setting `context.user` from auth headers
94
+
95
+ ### Graceful Exit — No GraphQL Endpoints
96
+
97
+ If no GraphQL schema files, resolver definitions, or GraphQL framework imports are detected, skip Phase 1b and Phase 2b entirely. Output a summary note and zero gap entries for GraphQL.
98
+
99
+ ## Phase 1c: gRPC Endpoint Discovery
100
+
101
+ Catalog all gRPC endpoints. For each endpoint, record: service name, RPC method name, request/response message types, streaming type (unary/server/client/bidirectional), interceptor chain.
102
+
103
+ ### Proto Service Parsing
104
+
105
+ - `.proto` files with `service` blocks defining `rpc` methods
106
+ - `stream` annotations on request or response types (server streaming, client streaming, bidirectional streaming)
107
+ - `package` declarations for service namespace
108
+
109
+ ### Server Interceptor Detection
110
+
111
+ | Language | Interceptor Pattern |
112
+ |---|---|
113
+ | Java | `ServerInterceptor` interface, `@GrpcService` (Spring gRPC), interceptor registry |
114
+ | Go | `grpc.UnaryInterceptor()`, `grpc.StreamInterceptor()`, `grpc.ChainUnaryInterceptor()` |
115
+ | Python | `grpc.server_interceptor`, `intercept_service()` |
116
+ | Node/TS | `addService()` calls, `@GrpcMethod` decorators (NestJS), `grpc-js` server options |
117
+
118
+ ### gRPC Middleware Chain Detection
119
+
120
+ - Interceptor chains in server setup (ordered middleware)
121
+ - `@GrpcMethod` decorators with guard annotations (NestJS)
122
+ - Metadata extractors for authentication tokens
123
+ - Health check service registration (`grpc.health.v1`)
124
+
125
+ ### Graceful Exit — No gRPC Endpoints
126
+
127
+ If no `.proto` files, gRPC server setup, or gRPC framework imports are detected, skip Phase 1c and Phase 2c entirely. Output a summary note and zero gap entries for gRPC.
128
+
129
+ ## Phase 1d: Mixed-Protocol Detection
130
+
131
+ A single codebase may expose REST + GraphQL + gRPC endpoints simultaneously. When multiple protocols are detected:
132
+
133
+ 1. Scan all three protocols independently
134
+ 2. Identify shared authentication middleware (e.g., a JWT validator used by both Express routes and Apollo context)
135
+ 3. Do not double-count shared middleware as separate gaps — if auth middleware covers both REST and GraphQL, count it once
136
+ 4. Note in findings when multiple protocols share infrastructure
137
+
54
138
  ## Phase 2: Security Gap Detection — Application Rules
55
139
 
56
140
  ### 1. Missing Authentication Middleware (AC3a)
@@ -82,6 +166,99 @@ Sensitive data exposure is `high` severity.
82
166
 
83
167
  Detect POST/PUT/PATCH/DELETE endpoints that accept a request body but have no input validation. Missing input validation is `high` severity.
84
168
 
169
+ ## Phase 2b: GraphQL Security Gap Detection
170
+
171
+ ### 1. Queries/Mutations Missing Auth Directives
172
+
173
+ Detect GraphQL operations missing authentication. Look for:
174
+ - Resolvers without `@auth`, `@authenticated`, `@HasPermission`, or `@UseGuards(AuthGuard)` directives
175
+ - Schema types without `@auth` directive when other types have it (inconsistent protection)
176
+ - Mutation resolvers with no authorization checks are `critical` severity
177
+ - Query resolvers returning non-public data without auth are `high` severity
178
+
179
+ ### 2. Introspection Enabled in Production
180
+
181
+ Detect GraphQL introspection configuration that may leak schema in production:
182
+ - `introspection: true` in Apollo Server config without `NODE_ENV` conditional
183
+ - Missing introspection disable in production configuration
184
+ - Yoga/Mercurius default introspection without explicit disable
185
+
186
+ Introspection in production is `medium` severity.
187
+
188
+ ### 3. Mutations Without Authorization Checks
189
+
190
+ Detect mutation resolvers that lack authorization logic:
191
+ - Mutation handlers with no permission checks, guard decorators, or authorization middleware
192
+ - `graphql-shield` rules that allow mutations without role checks
193
+ - NestJS mutations without `@UseGuards()` when other mutations have guards
194
+
195
+ Missing mutation authorization is `critical` severity.
196
+
197
+ ### 4. Field-Level Authorization Gaps
198
+
199
+ Detect sensitive fields exposed without field-level auth controls:
200
+ - Fields named `email`, `password`, `ssn`, `token`, `secret`, `creditCard` without `@Authorized` or field-level resolvers
201
+ - Resolver types exposing sensitive nested objects without per-field permission checks
202
+ - User types exposing admin-only fields to all authenticated users
203
+
204
+ Field-level authorization gaps are `high` severity.
205
+
206
+ ### 5. GraphQL Federation and Schema Stitching
207
+
208
+ When Apollo Federation or schema stitching is detected:
209
+ - Note gateway-level auth that may mask per-service gaps
210
+ - Flag subgraph services that rely solely on gateway auth without their own validation
211
+ - Detect `@external` fields without authorization in the owning subgraph
212
+
213
+ Federation auth gaps are `medium` severity with a note about gateway-level coverage.
214
+
215
+ ## Phase 2c: gRPC Security Gap Detection
216
+
217
+ ### 1. Services Missing Auth Interceptors
218
+
219
+ Detect gRPC server setup without authentication interceptors:
220
+ - Server initialization without `AuthInterceptor` or equivalent in the interceptor chain
221
+ - Services registered via `addService` with no auth middleware applied
222
+ - Spring gRPC services without `@GrpcService` security configuration
223
+
224
+ Missing auth interceptor is `critical` severity.
225
+
226
+ ### 2. Unary RPCs Without Authorization Metadata
227
+
228
+ Detect unary RPC methods that do not validate authorization metadata:
229
+ - `rpc` method handlers that do not extract or validate `metadata` authorization headers
230
+ - Handler functions that skip token/credential validation from gRPC metadata
231
+ - Methods that do not check caller identity or roles from request context
232
+
233
+ Missing unary authorization is `high` severity.
234
+
235
+ ### 3. Streaming RPCs Without Per-Message Auth
236
+
237
+ Detect bidirectional and server streaming RPCs without per-message authentication:
238
+ - Stream handlers that authenticate only at connection start but not per-message
239
+ - Bidirectional streams without per-message auth validation
240
+ - Server streaming RPCs that do not re-validate authorization on long-lived connections
241
+
242
+ Missing stream auth is `high` severity.
243
+
244
+ ### 4. TLS Configuration Gaps
245
+
246
+ Detect insecure gRPC transport configuration:
247
+ - `grpc.insecure_port` usage in non-development configuration
248
+ - `ServerCredentials.createInsecure()` in production server setup
249
+ - Missing TLS certificate configuration in production gRPC servers
250
+ - Plaintext gRPC channels in production client configuration
251
+
252
+ Insecure TLS is `critical` severity.
253
+
254
+ ### 5. gRPC Reflection Enabled in Production
255
+
256
+ Detect gRPC reflection service that may expose service definitions:
257
+ - `grpc.reflection.v1alpha` or `grpc.reflection.v1` service registered without environment guard
258
+ - Reflection service enabled unconditionally (similar risk to GraphQL introspection)
259
+
260
+ Reflection in production is `medium` severity.
261
+
85
262
  ## Phase 3: False-Positive Mitigation — Inherited Auth
86
263
 
87
264
  Before flagging an endpoint as "missing authentication middleware," trace the middleware chain upward:
@@ -106,6 +283,18 @@ Before flagging an endpoint as "missing authentication middleware," trace the mi
106
283
  - `r.Use(JWTAuth())` — app-level
107
284
  - `group := r.Group("/api"); group.Use(AuthMiddleware())` — group-level
108
285
 
286
+ #### GraphQL Inherited Auth
287
+ - Apollo Server `context` function that validates JWT and sets `context.user` — app-level
288
+ - `graphql-shield` rule tree applied via `applyMiddleware` — schema-level
289
+ - NestJS `@UseGuards(AuthGuard)` on resolver class — class-level
290
+ - Apollo Federation gateway-level auth that validates before routing to subgraphs — gateway-level
291
+
292
+ #### gRPC Inherited Auth
293
+ - Global auth interceptor registered via `grpc.UnaryInterceptor(authInterceptor)` — server-level
294
+ - `ServerInterceptor` added to server builder interceptor chain — server-level
295
+ - Per-service interceptor applied at `addService` — service-level
296
+ - TLS mutual authentication (mTLS) at transport level — transport-level
297
+
109
298
  ## Phase 4: Infrastructure Security Patterns (E12-S6)
110
299
 
111
300
  **Apply ONLY when {project_type} is `infrastructure` or `platform`.**
@@ -180,11 +369,50 @@ gap:
180
369
  evidence:
181
370
  file: "relative/path/to/file"
182
371
  line: 42
372
+ protocol: "rest"
183
373
  recommendation: "Actionable fix — add middleware, validate input, filter response"
184
374
  verified_by: "machine-detected"
185
375
  confidence: "{high|medium|low}"
186
376
  ```
187
377
 
378
+ **Protocol field:** Every gap entry MUST include a `protocol` field in the evidence section indicating which API protocol the finding applies to: `rest`, `graphql`, or `grpc`. This enables downstream consumers to filter and route findings by protocol.
379
+
380
+ #### GraphQL Gap Example
381
+
382
+ ```yaml
383
+ gap:
384
+ id: "GAP-SECURITY-015"
385
+ category: "security-endpoint"
386
+ severity: "critical"
387
+ title: "Mutation resolver missing authorization checks"
388
+ description: "createUser mutation has no @auth directive or guard. Any authenticated user can create accounts."
389
+ evidence:
390
+ file: "src/graphql/resolvers/user.resolver.ts"
391
+ line: 42
392
+ protocol: "graphql"
393
+ recommendation: "Add @UseGuards(AuthGuard, RolesGuard) or @auth directive to the createUser mutation."
394
+ verified_by: "machine-detected"
395
+ confidence: "high"
396
+ ```
397
+
398
+ #### gRPC Gap Example
399
+
400
+ ```yaml
401
+ gap:
402
+ id: "GAP-SECURITY-022"
403
+ category: "security-endpoint"
404
+ severity: "critical"
405
+ title: "gRPC server missing auth interceptor in production config"
406
+ description: "Server setup uses grpc.insecure_port without TLS. No auth interceptor in interceptor chain."
407
+ evidence:
408
+ file: "cmd/server/main.go"
409
+ line: 58
410
+ protocol: "grpc"
411
+ recommendation: "Add TLS credentials and an auth interceptor to the gRPC server configuration."
412
+ verified_by: "machine-detected"
413
+ confidence: "high"
414
+ ```
415
+
188
416
  ### Confidence Classification
189
417
 
190
418
  - **high** — exact pattern match (e.g., no auth decorator/annotation on a `@PostMapping` handler)
@@ -1,7 +1,7 @@
1
1
  # Gap Entry Schema
2
2
 
3
- > **Version:** 1.1.0
4
- > **Story:** E11-S1, E12-S5
3
+ > **Version:** 1.2.0
4
+ > **Story:** E11-S1, E12-S5, E11-S18
5
5
  > **Traces to:** FR-111, FR-123, US-38, ADR-021, ADR-022
6
6
  >
7
7
  > Standardized output schema for brownfield scan subagents (E11).
@@ -22,6 +22,7 @@ description: "<string>"
22
22
  evidence:
23
23
  file: "<relative-path>"
24
24
  line: <number-or-range>
25
+ protocol: "<string>" # Optional
25
26
  recommendation: "<string>"
26
27
  verified_by: "<agent-id>"
27
28
  confidence: "<enum>"
@@ -36,7 +37,7 @@ confidence: "<enum>"
36
37
  | `severity` | enum | yes | Impact level — must be one of the 5 allowed values (see Severity Enum) |
37
38
  | `title` | string | yes | Short summary of the gap (max 80 characters) |
38
39
  | `description` | string | yes | Detailed explanation of the gap, what it means, and why it matters |
39
- | `evidence` | object | yes | Source code evidence (see Evidence Object) |
40
+ | `evidence` | object | yes | Source code evidence with required `file` and `line` sub-fields, plus optional `protocol` sub-field (see Evidence Object) |
40
41
  | `recommendation` | string | yes | Actionable fix or remediation guidance |
41
42
  | `verified_by` | string | yes | ID of the scan agent that produced this finding (e.g., `dead-code-analyzer`, `config-scanner`) |
42
43
  | `confidence` | enum | yes | Agent's confidence in the finding accuracy (see Confidence Enum) |
@@ -95,6 +96,7 @@ The `evidence` field is a composite object grouping source location data:
95
96
  evidence:
96
97
  file: "src/services/auth.ts" # Relative path from project root (non-empty string)
97
98
  line: 42 # Single line number
99
+ protocol: "rest" # Optional. Protocol type
98
100
  ```
99
101
 
100
102
  Or with a line range:
@@ -105,10 +107,19 @@ evidence:
105
107
  line: "15-28" # Line range (start-end)
106
108
  ```
107
109
 
110
+ Or without the optional protocol field (backward compatible):
111
+
112
+ ```yaml
113
+ evidence:
114
+ file: "src/utils/helper.ts"
115
+ line: 10
116
+ ```
117
+
108
118
  | Sub-field | Type | Required | Constraints |
109
119
  |-----------|------|----------|-------------|
110
120
  | `file` | string | yes | Relative path from project root. Must be non-empty. |
111
121
  | `line` | number or string | yes | Single line number (integer) or range as `"start-end"` string |
122
+ | `protocol` | string | no | Optional. One of `rest`, `graphql`, `grpc`, `websocket`, or any custom string. Omit if not applicable. When present, must be a non-empty string. |
112
123
 
113
124
  ## ID Format
114
125
 
@@ -138,10 +149,17 @@ All fields listed in the Field Reference are **required** — a gap entry with a
138
149
  - `evidence.line` must be a positive integer or a range string matching `^\d+-\d+$`
139
150
  - `title` should not exceed 80 characters
140
151
  - `verified_by` must be a non-empty string identifying the scan agent
152
+ - `evidence.protocol` when present, must be a non-empty string
141
153
 
142
154
  ### Required vs Optional
143
155
 
144
- All 9 fields (`id`, `category`, `severity`, `title`, `description`, `evidence`, `recommendation`, `verified_by`, `confidence`) are **required**. There are no optional fields in the base schema.
156
+ All 9 top-level fields (`id`, `category`, `severity`, `title`, `description`, `evidence`, `recommendation`, `verified_by`, `confidence`) are **required**. There are no optional top-level fields in the base schema.
157
+
158
+ The `evidence` object contains one optional sub-field: `protocol`. This is the first optional sub-field in the schema. Existing gap entries that omit `protocol` remain fully valid.
159
+
160
+ ### Optional Field Validation
161
+
162
+ The `protocol` sub-field of the `evidence` object is not enum-validated. It accepts any non-empty string when present. Recommended canonical values are `rest`, `graphql`, `grpc`, and `websocket`, but custom strings (e.g., `mqtt`, `soap`, `amqp`) are also accepted without schema changes. When `protocol` is omitted entirely, the gap entry remains valid (backward compatible). When present, an empty string is invalid.
145
163
 
146
164
  ## Budget Control
147
165
 
@@ -174,6 +192,23 @@ verified_by: "config-scanner"
174
192
  confidence: "high"
175
193
  ```
176
194
 
195
+ ### Application Category Example with Protocol
196
+
197
+ ```yaml
198
+ id: "GAP-security-endpoint-001"
199
+ category: "security-endpoint"
200
+ severity: "high"
201
+ title: "Unprotected admin route exposes user management API"
202
+ description: "The /api/admin/users endpoint has no authentication middleware applied."
203
+ evidence:
204
+ file: "src/routes/admin.ts"
205
+ line: 15
206
+ protocol: "rest"
207
+ recommendation: "Add authentication middleware to all /api/admin/* routes."
208
+ verified_by: "security-scanner"
209
+ confidence: "high"
210
+ ```
211
+
177
212
  ### Infrastructure Category Examples
178
213
 
179
214
  ```yaml
@@ -12,11 +12,20 @@ points: "{story_points}"
12
12
  risk: "{high/medium/low}"
13
13
  sprint_id: null
14
14
  priority_flag: null
15
+ origin: null
16
+ origin_ref: null
15
17
  depends_on: []
16
18
  blocks: []
17
19
  traces_to: []
18
20
  date: "{creation_date}"
19
21
  author: "{agent_name}"
22
+ # Optional: Figma design metadata — enables dev agents to extract design tokens and component specs via MCP.
23
+ # Omit this block entirely if the story does not reference Figma designs.
24
+ # figma:
25
+ # file_key: "{figma_file_key}" # Figma file identifier (from URL)
26
+ # pages: ["{page_name}"] # List of page names to extract from
27
+ # node_ids: ["{node_id}"] # List of specific Figma node IDs
28
+ # design_version: null # Populated by dev agent after first consumption (lastModified hash)
20
29
  ---
21
30
 
22
31
  # Story: {story_title}
@@ -116,4 +125,23 @@ As a {role}, I want to {action}, so that {benefit}.
116
125
 
117
126
  ## Definition of Done
118
127
 
119
- - [ ] Define all the Definition of Done
128
+ ### Acceptance
129
+
130
+ - [ ] All acceptance criteria verified and checked off
131
+ - [ ] All subtasks marked complete
132
+
133
+ ### Testing
134
+
135
+ - [ ] All tests pass (unit, integration, e2e as applicable)
136
+ - [ ] No linting or formatting errors
137
+
138
+ ### Code Quality & CI
139
+
140
+ - [ ] Code compiles / builds without errors
141
+ - [ ] Code follows project conventions
142
+ - [ ] No hardcoded secrets or credentials
143
+ - [ ] PR merged to staging with all CI checks passing
144
+
145
+ ### Documentation
146
+
147
+ - [ ] Documentation updated (if applicable)
@@ -32,12 +32,105 @@
32
32
  <action>Plan keyboard navigation, screen reader support</action>
33
33
  <action>Define color contrast and text sizing standards</action>
34
34
  </step>
35
- <step n="7" title="Generate Output">
35
+ <step n="7" title="Figma MCP Detection and Mode Selection">
36
+ <action>Probe for available Figma MCP server. Load figma-integration.md detection section JIT to determine if a design tool adapter is available.</action>
37
+ <action if="figma_mcp_available">Present mode selection to user: [Generate] Create Figma frames alongside ux-design.md | [Import] Import existing Figma designs (read-only) | [Skip] Text-only UX spec, no Figma integration</action>
38
+ <action if="not figma_mcp_available">Skip Figma integration — proceed with text-only UX design output. Log: "No Figma MCP server detected. Generating markdown-only ux-design.md."</action>
39
+ </step>
40
+ <step n="8" title="Generate Mode — UI Kit Page Creation" if="figma_mcp_available AND user_selected_generate">
41
+ <critical>
42
+ <mandate>Generate mode is the ONLY mode that performs write operations to Figma (FR-140). All other modes are read-only. Write operations: create pages, create frames, create component instances. Minimum required Figma API scopes: files:read + file_content:read + files:write.</mandate>
43
+ </critical>
44
+ <action>Load figma-integration.md frames section JIT from _gaia/dev/skills/figma-integration.md</action>
45
+ <action>Create a UI Kit page named "UI Kit — Generated" in the Figma design file via MCP</action>
46
+ <action>Extract design tokens from {planning_artifacts}/design-system/design-tokens.json (W3C DTCG format)</action>
47
+ <action>Create color styles with semantic aliases from token definitions (e.g., color.surface.primary, color.text.primary)</action>
48
+ <action>Create typography styles from composite token specs (heading-1, heading-2, body, caption)</action>
49
+ <action>Create spacing grid tokens and base components with state variants (default, hover, active, disabled, focus)</action>
50
+ <action>Error handling: on HTTP 429 rate limit, perform a single retry after backoff. If 429 persists, graceful fallback to markdown-only flow — log warning and skip remaining Figma operations.</action>
51
+ </step>
52
+ <step n="9" title="Generate Mode — Per-Screen Frame Generation" if="figma_mcp_available AND user_selected_generate">
53
+ <action>Parse PRD user journeys to determine screens needing frames</action>
54
+ <action>For each screen, generate frames at 6 viewports: 280px (foldable inner, FR-174), 375px (mobile), 600px (foldable outer, FR-174), 768px (tablet portrait), 1024px (tablet landscape, FR-174), 1280px (desktop)</action>
55
+ <action>Compose frames using UI Kit components from the previous step — apply auto-layout with responsive constraints from component specs</action>
56
+ <action>Label frames using naming convention: {ScreenName}/{Viewport} (e.g., Dashboard/Desktop, Login/Mobile)</action>
57
+ <action>Collect all generated Figma node IDs for downstream recording in ux-design.md</action>
58
+ </step>
59
+ <step n="10" title="Generate Mode — Prototype Flow Setup" if="figma_mcp_available AND user_selected_generate">
60
+ <action>Map PRD user journey steps to the generated screen frames</action>
61
+ <action>Create prototype flow connections between frames via Figma MCP, linking screens in the order defined by each user journey</action>
62
+ <action>Validate flow completeness: every user journey step must map to a generated frame. Flag any unmapped journey steps as warnings.</action>
63
+ </step>
64
+ <step n="11" title="Generate Mode — Asset Export Configuration" if="figma_mcp_available AND user_selected_generate">
65
+ <action>Configure PNG export at 1x, 2x, 3x densities for raster assets (images, illustrations)</action>
66
+ <action>Configure SVG export for icon components</action>
67
+ <action>Generate platform-specific asset catalogs per FR-175: iOS .xcassets catalog structure with Contents.json manifests, Android drawable-mdpi/drawable-hdpi/drawable-xhdpi/drawable-xxhdpi/drawable-xxxhdpi directories</action>
68
+ <action>Write export configuration and asset manifest to {planning_artifacts}/design-system/assets/ directory</action>
69
+ <action>Check {project-path}/.figma-cache/ for cached responses (1h TTL) before making MCP read calls — use cached data if fresh, fetch and cache if stale or missing</action>
70
+ </step>
71
+ <step n="12" title="Generate Mode — Record Figma Node IDs and Enhance ux-design.md" if="figma_mcp_available AND user_selected_generate">
72
+ <action>Build Screen-to-Frame mapping table from all generated Figma node IDs: columns Screen Name | Viewport | Figma Node ID | Page</action>
73
+ <action>Add figma: YAML frontmatter block to ux-design.md containing: file_key, pages array with node IDs for each generated page, and last_synced ISO 8601 timestamp</action>
74
+ <action>Add Design Tokens reference section linking to {planning_artifacts}/design-system/design-tokens.json with token category summary</action>
75
+ <action>Add Component Inventory section listing all generated UI Kit components with their Figma node IDs, variant counts, and state definitions</action>
76
+ <action>Add Screen-to-Frame mapping table with all generated frames across all viewports</action>
77
+ <action>Ensure backward compatibility: existing text-only ux-design.md content is preserved. Figma sections are additive — they appear after the standard UX design sections.</action>
78
+ </step>
79
+ <step n="13" title="Import Mode — File Key Entry and Validation" if="figma_mcp_available AND user_selected_import">
80
+ <critical>
81
+ <mandate>Import mode is strictly READ-ONLY. Only get_file, get_file_nodes, and get_image MCP calls are permitted. Zero write operations to Figma. Minimum required Figma API scopes: files:read + file_content:read.</mandate>
82
+ </critical>
83
+ <action>JIT-load figma-integration:import-detection section from _gaia/dev/skills/figma-integration.md</action>
84
+ <ask>Enter the Figma file URL (e.g., https://www.figma.com/file/abc123/Design-Name) or raw file key:</ask>
85
+ <action>Parse input: extract file key from URL format, or accept raw key directly</action>
86
+ <action>Validate key via lightweight figma/get_file MCP call with depth=1 (metadata only)</action>
87
+ <action>Handle errors: invalid key format (client-side rejection), 404 not found, 403 permission denied, 429 rate limited (single retry after 1s delay), 5-second timeout (abort gracefully per E13-S1)</action>
88
+ </step>
89
+ <step n="14" title="Import Mode — Page and Frame Discovery" if="figma_mcp_available AND user_selected_import">
90
+ <action>JIT-load figma-integration:import-discovery section</action>
91
+ <action>Call figma/get_file with full depth to retrieve the complete document tree</action>
92
+ <action>Parse response: extract pages (top-level CANVAS nodes) and frames (FRAME nodes within each page)</action>
93
+ <action>Build Page → Frames hierarchy with metadata (name, nodeId, absoluteBoundingBox dimensions)</action>
94
+ <action>Classify frames by viewport width: mobile (≤480px), tablet (481–1024px), desktop (>1024px)</action>
95
+ <action>Cache response in {project-path}/.figma-cache/ with 1-hour TTL per ADR-024</action>
96
+ <action>Handle partial access: if some pages/frames are inaccessible, continue with warnings and proceed with accessible content</action>
97
+ </step>
98
+ <step n="15" title="Import Mode — Design Token Extraction" if="figma_mcp_available AND user_selected_import">
99
+ <action>JIT-load figma-integration:import-tokens section</action>
100
+ <action>Extract color styles from file's styles and document nodes, resolving fill/stroke references to RGBA values</action>
101
+ <action>Extract typography styles: font family, size, weight, line height, letter spacing</action>
102
+ <action>Extract effect styles: drop-shadow and inner-shadow parameters</action>
103
+ <action>Extract spacing values from auto-layout frames: itemSpacing, paddingLeft/Right/Top/Bottom</action>
104
+ <action>Map all extracted tokens to W3C DTCG format with semantic alias support (e.g., Primary/500 → color.primary.500)</action>
105
+ <action>Write design-tokens.json to {planning_artifacts}/design-system/ with schema_version field</action>
106
+ </step>
107
+ <step n="16" title="Import Mode — Screen Inventory" if="figma_mcp_available AND user_selected_import">
108
+ <action>JIT-load figma-integration:import-screens section</action>
109
+ <action>Group frames by page from the discovered hierarchy</action>
110
+ <action>Build per-frame metadata: name, nodeId, width, height, viewport classification</action>
111
+ <action>Extract component instances used in each frame — map to component-specs.yaml format (name, props, layout type)</action>
112
+ <action>Generate structured screen-to-frame mapping with tracked nodeIds for downstream dev agent consumption (E13-S5)</action>
113
+ <action>Write component-specs.yaml to {planning_artifacts}/design-system/</action>
114
+ </step>
115
+ <step n="17" title="Import Mode — Generate ux-design.md Content" if="figma_mcp_available AND user_selected_import">
116
+ <action>JIT-load figma-integration:import-generate section</action>
117
+ <action>Prepare figma: YAML frontmatter block containing: file_key, pages array, node_ids array, imported_at ISO 8601 timestamp, import_mode: true</action>
118
+ <action>Prepare Design Tokens section with token path references (e.g., {color.primary}, {spacing.4})</action>
119
+ <action>Prepare Component Inventory section listing all components discovered from frame extraction with props and variants</action>
120
+ <action>Prepare Screen Descriptions section with per-screen: frame name, node ID, viewport classification, component list, layout description</action>
121
+ <action>Verify read-only guarantee: audit all MCP calls made during steps 13-17 — confirm only get_file, get_file_nodes, and get_image were used. Zero write operations. Abort and report if any write operation is detected.</action>
122
+ </step>
123
+ <step n="18" title="Generate Output">
36
124
  <template-output file="{planning_artifacts}/ux-design.md">
37
- Generate UX design document with: personas, information architecture, wireframe descriptions, interaction patterns, component specifications, accessibility plan, and FR-to-Screen Mapping table (FR ID | Screen/Page | Wireframe Section).
125
+ Generate UX design document with: personas, information architecture, wireframe descriptions, interaction patterns, component specifications, accessibility plan, FR-to-Screen Mapping table (FR ID | Screen/Page | Wireframe Section). If Generate mode was active: include figma: frontmatter block, Design Tokens section, Component Inventory with Figma node IDs, and Screen-to-Frame mapping table. If Import mode was active: include figma: frontmatter block (file_key, pages, node_ids, imported_at, import_mode: true), Design Tokens section with token references, Component Inventory, and Screen Descriptions.
38
126
  </template-output>
39
127
  </step>
40
- <step n="8" title="Optional: Accessibility Review">
128
+ <step n="19" title="FR-140 Compliance Check" if="figma_mcp_available AND user_selected_generate">
129
+ <action>Audit all MCP calls executed during Generate mode: classify each as READ (get_file, get_styles, get_components, get_images, get_frames) or WRITE (create_frame, create_component_instance, create_page)</action>
130
+ <action>Verify FR-140 constraint: write operations only occurred during Generate mode steps (8–12). Import mode and Skip mode must have zero write calls.</action>
131
+ <action>Document minimum required Figma API scopes: files:read + file_content:read (default for all modes), files:write (Generate mode only)</action>
132
+ </step>
133
+ <step n="20" title="Optional: Accessibility Review">
41
134
  <ask>Would you like to review the UX design for WCAG 2.1 accessibility compliance? This spawns a subagent in a separate context. Recommended for user-facing applications. (yes / skip)</ask>
42
135
  <action>If yes: spawn a subagent using the Agent tool: "Load {project-root}/_gaia/core/tasks/review-accessibility.xml. Read its entire contents. Target: {planning_artifacts}/ux-design.md. Follow the flow steps EXACTLY. Generate accessibility findings report."</action>
43
136
  <action>If skip: accessibility review can be run anytime later with /gaia-review-a11y</action>
@@ -25,6 +25,16 @@
25
25
  </action>
26
26
  <action>Include an "Architecture Conformance" section in findings with PASS/FAIL per check</action>
27
27
  </step>
28
+ <step n="3c" title="Design Fidelity Check">
29
+ <action>Read story file YAML frontmatter — check if a `figma:` block exists</action>
30
+ <action if="story_has_figma_block">Load the `figma-integration:fidelity` section JIT from `_gaia/dev/skills/figma-integration.md`</action>
31
+ <action if="story_has_figma_block">Run the fidelity comparison: extract token references from changed code files, compare against `{planning_artifacts}/design-system/design-tokens.json`, classify as matched/drifted/missing</action>
32
+ <action if="story_has_figma_block">Calculate per-category drift percentages (color, typography, spacing, borders)</action>
33
+ <action if="story_has_figma_block">Save fidelity report to `{implementation_artifacts}/reviews/{story_key}/fidelity-report.md`</action>
34
+ <action if="story_has_figma_block">Write `figma.fidelity_drift_pct` to story file frontmatter</action>
35
+ <action if="story_has_figma_block">Include fidelity results in code review findings: PASS (0% drift), WARNING (any category exceeds 10%), or BLOCKED (any category exceeds 25%)</action>
36
+ <action if="no figma block">Skip fidelity check — story does not use Figma design tokens</action>
37
+ </step>
28
38
  <step n="4" title="Generate Findings">
29
39
  <action>List issues by severity: critical, warning, suggestion</action>
30
40
  </step>
@@ -0,0 +1,25 @@
1
+ ---
2
+ title: 'Create Stakeholder Validation'
3
+ validation-target: 'Stakeholder file'
4
+ ---
5
+ ## Structure
6
+ - [ ] workflow.yaml present with agent: orchestrator
7
+ - [ ] instructions.xml present with sequential steps
8
+ - [ ] checklist.md present
9
+ - [ ] Registered in workflow-manifest.csv
10
+ - [ ] Slash command file exists at .claude/commands/gaia-create-stakeholder.md
11
+ ## Input Collection
12
+ - [ ] Required fields prompted: name, role, expertise, personality
13
+ - [ ] Optional fields prompted: perspective, tags
14
+ - [ ] Required field validation (non-empty check)
15
+ ## Validation Guards
16
+ - [ ] 50-file cap enforced before file creation
17
+ - [ ] Case-insensitive duplicate name detection against existing stakeholder name frontmatter
18
+ - [ ] custom/stakeholders/ directory auto-created if missing
19
+ ## Output
20
+ - [ ] Filename is kebab-case slug of name with .md extension
21
+ - [ ] File written to custom/stakeholders/{slug}.md
22
+ - [ ] YAML frontmatter includes all required fields
23
+ - [ ] Optional fields included only when provided
24
+ - [ ] Markdown body with ## Background section
25
+ - [ ] File does not exceed 100 lines
@@ -0,0 +1,79 @@
1
+ <workflow name="create-stakeholder">
2
+ <critical>
3
+ <mandate>Stakeholder files are written to custom/stakeholders/ — never to _gaia/</mandate>
4
+ <mandate>The 50-file cap and 100-line limit are hard gates (FR-164)</mandate>
5
+ <mandate>Duplicate name detection is case-insensitive against the name frontmatter field (FR-157)</mandate>
6
+ </critical>
7
+
8
+ <step n="1" title="Ensure Directory Exists">
9
+ <action>Check if {project-root}/custom/stakeholders/ directory exists</action>
10
+ <action if="directory does not exist">Create {project-root}/custom/stakeholders/ directory (and {project-root}/custom/ if needed)</action>
11
+ <action>Confirm directory is ready for writing</action>
12
+ </step>
13
+
14
+ <step n="2" title="Collect Required Inputs">
15
+ <ask>Provide the following required fields for the new stakeholder:
16
+
17
+ **Name** (display name, e.g., "Maria Santos"):
18
+ **Role** (title/function, e.g., "Housekeeper Manager"):
19
+ **Expertise** (domain skills, e.g., "Room turnover logistics"):
20
+ **Personality** (traits, e.g., "Pragmatic, detail-oriented"):
21
+ </ask>
22
+ <check if="any required field is empty">HALT: All four fields (name, role, expertise, personality) are required. Please provide all values.</check>
23
+ </step>
24
+
25
+ <step n="3" title="Collect Optional Inputs">
26
+ <ask>Optionally provide these additional fields (press Enter to skip):
27
+
28
+ **Perspective** (viewpoint/biases, e.g., "Focuses on operational efficiency"):
29
+ **Tags** (comma-separated, e.g., "operations, hospitality"):
30
+ </ask>
31
+ </step>
32
+
33
+ <step n="4" title="Validate Against Cap and Duplicates">
34
+ <action>Count existing .md files in {project-root}/custom/stakeholders/ directory</action>
35
+ <check if="count >= 50">HALT: The 50-file cap has been reached in custom/stakeholders/ (FR-164). There are already {count} stakeholder files. Remove unused stakeholders before creating new ones.</check>
36
+ <action>Scan all existing stakeholder files in custom/stakeholders/*.md — read the name field from each file's YAML frontmatter</action>
37
+ <action>Compare each existing name against the new stakeholder name using case-insensitive comparison</action>
38
+ <check if="duplicate name found (case-insensitive match)">HALT: A stakeholder with the name "{existing_name}" already exists at custom/stakeholders/{existing_file}. Name collision detected (case-insensitive). Choose a different name.</check>
39
+ </step>
40
+
41
+ <step n="5" title="Generate Filename Slug">
42
+ <action>Convert the stakeholder name to a kebab-case slug:
43
+ 1. Convert to lowercase
44
+ 2. Replace spaces with hyphens
45
+ 3. Strip all characters that are not alphanumeric or hyphens
46
+ 4. Collapse multiple consecutive hyphens into a single hyphen
47
+ 5. Trim leading/trailing hyphens
48
+ 6. Append .md extension
49
+ </action>
50
+ <action>Example: "Maria Santos" → "maria-santos.md", "Jean-Pierre O'Brien III" → "jean-pierre-obrien-iii.md"</action>
51
+ <action>Set output path: {project-root}/custom/stakeholders/{slug}.md</action>
52
+ <check if="file already exists at output path">HALT: File custom/stakeholders/{slug}.md already exists. This may indicate a slug collision from a different display name. Choose a different name or remove the existing file.</check>
53
+ </step>
54
+
55
+ <step n="6" title="Generate and Write Stakeholder File">
56
+ <action>Generate the stakeholder file with YAML frontmatter and Markdown body:
57
+
58
+ ```
59
+ ---
60
+ name: "{name}"
61
+ role: "{role}"
62
+ expertise: "{expertise}"
63
+ personality: "{personality}"
64
+ perspective: "{perspective}" # Only include if provided
65
+ tags: [{tags_as_yaml_array}] # Only include if provided
66
+ ---
67
+
68
+ ## Background
69
+
70
+ {A 2-3 sentence description synthesized from the provided fields, describing this stakeholder's viewpoint and discussion style.}
71
+ ```
72
+ </action>
73
+ <action>Verify the generated file does not exceed 100 lines. If it does, trim the Background section to fit within the limit.</action>
74
+ <action>Write the file to {project-root}/custom/stakeholders/{slug}.md</action>
75
+ <template-output file="{project-root}/custom/stakeholders/{slug}.md">
76
+ Stakeholder file with YAML frontmatter (name, role, expertise, personality, and optionally perspective and tags) plus a Markdown Background section.
77
+ </template-output>
78
+ </step>
79
+ </workflow>