Harness Design Mobile
Token-bound mobile component generation. Scaffold from design tokens and aesthetic intent, implement with React Native, SwiftUI, Flutter, or Compose patterns following platform-specific design rules, and verify every value references the token set with native convention compliance.
When to Use
- Generating new mobile components that must conform to the project's design system tokens
- When
on_new_feature triggers fire with mobile UI scope requiring token-bound component generation
- When
on_commit triggers fire and new mobile components contain hardcoded design values that should reference tokens
- Implementing design intent from
design-system/DESIGN.md into platform-native styling (StyleSheet, SwiftUI modifiers, Flutter ThemeData, Compose MaterialTheme)
- Ensuring components follow platform-specific guidelines (iOS Human Interface Guidelines, Material Design 3, Flutter design patterns)
- NOT for generating design tokens themselves (use harness-design-system)
- NOT for establishing aesthetic direction or anti-patterns (use harness-design)
- NOT for accessibility auditing (use harness-accessibility)
- NOT for web platform components (use harness-design-web)
Process
Phase 1: SCAFFOLD — Read Tokens, Detect Platform, Plan Structure
Read design tokens. Load design-system/tokens.json (W3C DTCG format). Extract:
- Color tokens: primary, secondary, accent, neutral ramps, semantic colors
- Typography tokens: heading and body font families, font weights, font sizes, line heights
- Spacing tokens: spacing scale values
- If
design-system/tokens.json does not exist, stop and instruct the user to run harness-design-system first.
Read design intent. Load design-system/DESIGN.md for:
- Aesthetic direction (style, tone, differentiator)
- Anti-patterns to avoid
- Platform-specific mobile notes (touch targets, native component usage, platform conventions)
- If
design-system/DESIGN.md does not exist, warn the user and proceed with tokens only.
Check harness configuration. Read harness.config.json for:
design.strictness — enforcement level. Default to standard.
design.platforms — confirm mobile is in the platforms list.
Detect mobile platform. Scan the project for:
- React Native:
package.json contains react-native or expo, .tsx files with StyleSheet or react-native imports
- SwiftUI:
.swift files with import SwiftUI, Package.swift or .xcodeproj exists
- Flutter:
pubspec.yaml exists, .dart files with import 'package:flutter/
- Compose:
build.gradle.kts with compose dependencies, .kt files with @Composable
- If the user specified
--platform, use that override.
Load platform-specific rules. Based on detected platform, read platform design guidelines from agents/skills/shared/design-knowledge/platform-rules/:
- iOS (SwiftUI/React Native on iOS): Read
ios.yaml — Human Interface Guidelines, safe area insets, navigation bar patterns, tab bar conventions, dynamic type support, SF Symbols integration
- Android (Compose/React Native on Android): Read
android.yaml — Material Design 3, elevation system, shape system, dynamic color, navigation patterns, edge-to-edge layout
- Flutter: Read
flutter.yaml — Flutter design patterns, ThemeData structure, widget composition, adaptive layouts, platform channel considerations
- React Native cross-platform: Read both
ios.yaml and android.yaml — platform-specific overrides via Platform.select, safe area handling, navigation library patterns
Load anti-pattern definitions. Read anti-pattern files from agents/skills/shared/design-knowledge/anti-patterns/:
typography.yaml — typographic anti-patterns (too many fonts, inconsistent scales)
color.yaml — color anti-patterns (hardcoded hex, insufficient contrast)
layout.yaml — layout anti-patterns (magic numbers, inconsistent spacing)
motion.yaml — motion anti-patterns (excessive animation, missing reduced-motion)
Build token-to-platform mapping. Create a lookup table mapping tokens to platform-native representations:
- React Native:
color.primary.500 maps to StyleSheet value or themed constant
- SwiftUI:
color.primary.500 maps to Color("primary500") in asset catalog or Color(hex:) extension
- Flutter:
color.primary.500 maps to Theme.of(context).colorScheme.primary or custom AppColors.primary500
- Compose:
color.primary.500 maps to MaterialTheme.colorScheme.primary or custom AppTheme.colors.primary500
Plan component structure. Define:
- Component file path(s) following platform conventions
- Props/parameters interface
- Which tokens will be consumed
- Platform-specific considerations (safe areas, touch targets, dynamic type)
- Present plan to user before proceeding.
Phase 2: IMPLEMENT — Generate Token-Bound Mobile Components
Generate platform-specific component code. Based on detected platform:
React Native (TypeScript):
- Functional component with TypeScript props interface
- All colors via themed StyleSheet or token constants (no hardcoded hex values)
- Typography via scaled text styles referencing token font families and sizes
- Spacing via token-derived constants in StyleSheet
- Platform-specific overrides via
Platform.select where iOS and Android differ
- Safe area handling via
useSafeAreaInsets for edge-to-edge content
SwiftUI:
- View struct with typed properties
- Colors from asset catalog or Color extension referencing tokens
- Typography via custom
Font extensions mapping to token values
- Spacing via token-derived constants
- Dynamic Type support via
.font(.body) or custom scaled fonts
- Safe area respect via
.safeAreaInset modifiers
- iOS Human Interface Guidelines compliance (44pt minimum touch targets)
Flutter (Dart):
- StatelessWidget or StatefulWidget with typed constructor parameters
- Colors via
Theme.of(context) or custom AppColors class referencing tokens
- Typography via
Theme.of(context).textTheme or custom AppTypography
- Spacing via token-derived constants class
- Material Design 3 compliance (elevation, shape, dynamic color)
- Adaptive layout via
LayoutBuilder or MediaQuery for responsive behavior
Compose (Kotlin):
@Composable function with typed parameters
- Colors via
MaterialTheme.colorScheme or custom theme referencing tokens
- Typography via
MaterialTheme.typography or custom type scale
- Spacing via token-derived
Dp constants
- Material Design 3 compliance (Surface, ElevatedCard, shape system)
- Modifier chains for layout following Compose conventions
Apply platform-specific rules:
- Touch targets: Minimum 44x44pt (iOS) or 48x48dp (Android/Material)
- Safe areas: All platforms handle notch/status bar/navigation bar correctly
- Typography scaling: Support dynamic type (iOS), font scale (Android), and text scale factor (Flutter)
- Elevation/shadows: Platform-appropriate (iOS shadow, Material elevation, Flutter elevation)
- Navigation patterns: Platform-native navigation (UINavigationController, NavHost, Navigator)
Add USES_TOKEN annotations. Insert platform-appropriate comments documenting token consumption:
// @design-token color.primary.500 — primary action background
// @design-token typography.heading.fontFamily — section heading
// @design-token spacing.md — card internal padding
Phase 3: VERIFY — Check Token Binding and Platform Compliance
Scan for hardcoded values. Search generated files for:
- Hardcoded color values: hex codes,
UIColor(red:green:blue:), Color(0xFF...), Color(red:green:blue:)
- Hardcoded font families: string literals for font names not referencing tokens
- Hardcoded spacing: raw numeric values in padding/margin not from the token scale
Verify token coverage. For every design value in generated components:
- Confirm it resolves to a token in
design-system/tokens.json
- Confirm the token path is valid
- Report orphan references
Check platform guideline compliance:
- iOS: Touch targets >= 44pt, safe area respected, dynamic type supported
- Android/Material: Touch targets >= 48dp, edge-to-edge layout, Material 3 components used
- Flutter: ThemeData used consistently, no hardcoded Material values
- React Native: Platform.select used for iOS/Android differences, safe area handled
Check anti-pattern compliance. Cross-reference against design-system/DESIGN.md anti-patterns and definitions in agents/skills/shared/design-knowledge/anti-patterns/.
Query the knowledge graph. If available at .harness/graph/:
- Verify
DesignToken nodes exist for all referenced tokens
- Verify
PLATFORM_BINDING edges exist for the target mobile platform
- Check
VIOLATES_DESIGN edges via DesignConstraintAdapter
Assign severity based on designStrictness:
permissive — all findings are info
standard — hardcoded values are warn, platform guideline violations are warn, accessibility violations are error
strict — hardcoded values are error (blocks), platform violations are warn, accessibility violations are error
Report verification results:
MOBILE-001 [warn] Hardcoded color Color(0xFF3B82F6) — should reference token
File: lib/widgets/action_button.dart:15
Fix: Use Theme.of(context).colorScheme.primary or AppColors.primary500
MOBILE-002 [warn] Touch target 32dp below minimum 48dp (Material Design 3)
File: lib/widgets/icon_action.dart:22
Fix: Set minimumSize to Size(48, 48) in ButtonStyle
MOBILE-003 [info] Missing dynamic type support
File: Sources/Views/ProductCard.swift:18
Fix: Use .font(.body) instead of .font(.system(size: 16))
Run harness validate. Confirm new components integrate cleanly.
Harness Integration
harness validate — Run after generating components to verify project health.
harness scan — Run after component generation to update the knowledge graph with USES_TOKEN and PLATFORM_BINDING edges.
DesignIngestor (packages/graph/src/ingest/DesignIngestor.ts) — Verifies DesignToken nodes exist for all tokens referenced by generated components.
DesignConstraintAdapter (packages/graph/src/constraints/DesignConstraintAdapter.ts) — Checks for VIOLATES_DESIGN edges during VERIFY phase. Reports constraint violations at configured strictness.
harness-design-system — Dependency. Provides design-system/tokens.json. If tokens do not exist, instruct user to run harness-design-system first.
harness-design — Dependency. Provides design-system/DESIGN.md with aesthetic intent and anti-patterns.
harness-impact-analysis — Traces token changes to affected mobile components via USES_TOKEN edges.
Graph naming convention: This skill uses PascalCase for node types (DesignToken, DesignConstraint) and UPPER_SNAKE for edge types (USES_TOKEN, PLATFORM_BINDING, VIOLATES_DESIGN) as conceptual labels. The graph schema registers these as snake_case identifiers (design_token, design_constraint, uses_token, platform_binding, violates_design). The adapter classes (DesignIngestor, DesignConstraintAdapter) handle the mapping — always use the adapters rather than constructing graph queries with raw type names.
Success Criteria
- Generated mobile components reference design tokens exclusively — no hardcoded color, font, or spacing values
- Platform detection correctly identifies React Native, SwiftUI, Flutter, or Compose projects
- Token-to-platform mapping produces correct output for each mobile platform
- Platform-specific rules are enforced (touch targets, safe areas, dynamic type, Material 3 compliance)
@design-token annotations are present for every consumed token
- Anti-pattern compliance check catches violations from
design-system/DESIGN.md
- Verification report uses severity levels matching
design.strictness configuration
harness validate passes after component generation
Examples
Example: React Native Card Component
Context: Fitness app. React Native with Expo. Tokens from harness-design-system. Design intent: expressive, warm tone.
SCAFFOLD output:
Platform detected: React Native (Expo)
Tokens loaded: 38 tokens from design-system/tokens.json
Design intent: Expressive, warm (from DESIGN.md)
Component plan: WorkoutCard with progress indicator
Token consumption: color.primary.*, color.accent.*, typography.heading, spacing.md/lg
Platform rules: iOS 44pt touch targets, Android 48dp touch targets, safe area insets
IMPLEMENT output (WorkoutCard.tsx):
// @design-token color.primary.500 — card accent
// @design-token color.neutral.50 — card background
// @design-token color.neutral.900 — primary text
// @design-token typography.heading.fontFamily — workout title
// @design-token typography.body.fontFamily — workout details
// @design-token spacing.md — card padding
// @design-token spacing.sm — content gap
import { View, Text, StyleSheet, Platform } from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { tokens } from '@/theme/tokens';
interface WorkoutCardProps {
title: string;
duration: string;
progress: number;
}
export function WorkoutCard({ title, duration, progress }: WorkoutCardProps) {
return (
<View style={styles.card}>
<Text style={styles.title}>{title}</Text>
<Text style={styles.detail}>{duration}</Text>
<View style={styles.progressTrack}>
<View style={[styles.progressFill, { width: `${progress}%` }]} />
</View>
</View>
);
}
const styles = StyleSheet.create({
card: {
backgroundColor: tokens.color.neutral[50],
borderRadius: tokens.radius.md,
padding: tokens.spacing.md,
gap: tokens.spacing.sm,
...Platform.select({
ios: {
shadowColor: tokens.color.neutral[900],
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.08,
shadowRadius: 8,
},
android: {
elevation: 2,
},
}),
},
title: {
fontFamily: tokens.typography.heading.fontFamily,
fontWeight: tokens.typography.heading.fontWeight,
fontSize: 18,
color: tokens.color.neutral[900],
},
detail: {
fontFamily: tokens.typography.body.fontFamily,
fontSize: 14,
color: tokens.color.neutral[600],
},
progressTrack: {
height: 6,
backgroundColor: tokens.color.neutral[200],
borderRadius: 3,
},
progressFill: {
height: 6,
backgroundColor: tokens.color.primary[500],
borderRadius: 3,
},
});
Example: SwiftUI List Item
IMPLEMENT output (WorkoutRow.swift):
// @design-token color.primary.500 — accent color
// @design-token color.neutral.900 — primary text
// @design-token color.neutral.600 — secondary text
// @design-token typography.heading.fontWeight — title weight
// @design-token spacing.sm — content spacing
import SwiftUI
struct WorkoutRow: View {
let title: String
let duration: String
let progress: Double
var body: some View {
VStack(alignment: .leading, spacing: AppSpacing.sm) {
Text(title)
.font(.headline)
.foregroundColor(AppColors.neutral900)
Text(duration)
.font(.subheadline)
.foregroundColor(AppColors.neutral600)
ProgressView(value: progress)
.tint(AppColors.primary500)
}
.padding(AppSpacing.md)
.accessibilityElement(children: .combine)
}
}
Rationalizations to Reject
| Rationalization |
Reality |
| "The touch target is 40pt on iOS — that's close to 44pt and the designer approved the comp, so I'll leave it." |
The 44pt iOS minimum and 48dp Android minimum are non-negotiable gates, not guidelines. Touch target violations are error severity regardless of strictness level. Designer comp approval does not override platform accessibility requirements. |
| "This is a cross-platform React Native component, so I only need to read the generic token mapping — platform-specific rules for iOS and Android are optional." |
React Native components require both ios.yaml and android.yaml rules. Platform-specific rules govern safe areas, elevation, navigation patterns, and touch targets that differ between platforms. Missing either set produces non-compliant native behavior. |
"The component uses a hardcoded shadow for iOS — shadowColor, shadowOffset, etc. Those aren't design tokens, they're platform APIs." |
Shadow colors must still reference token values. shadowColor: tokens.color.neutral[900] is the correct form. Hardcoded shadow values like #000 or rgba(0,0,0,0.2) are token binding violations the VERIFY phase will flag. |
"There's no design-system/DESIGN.md yet, but I know the aesthetic intent from our planning discussion — I'll proceed with tokens only." |
Proceeding without DESIGN.md means anti-pattern enforcement is disabled for the entire VERIFY phase. The anti-pattern check is what catches design intent violations beyond token correctness. Warn the user and recommend running harness-design first. |
| "The scaffold plan is straightforward — a simple card component. I'll skip presenting it to the user and just generate." |
The scaffold plan confirmation is when the user can catch incorrect platform assumptions (wrong StyleSheet structure, wrong platform APIs) before any code is written. Mobile components are harder to refactor than web components due to platform-specific branching. |
Gates
- No component generation without reading tokens from harness-design-system. The SCAFFOLD phase requires
design-system/tokens.json. Do not generate components with hardcoded values as a fallback.
- No hardcoded design values in generated output. Every color, font, and spacing value must reference a token.
- No platform-specific code without platform detection. The SCAFFOLD phase must detect or receive the target mobile platform before generating components.
- No generation without scaffold plan confirmation. Present the component plan to the user first.
- No iOS components without 44pt minimum touch targets. Touch target violations are
error severity regardless of strictness level.
- No Android/Material components without 48dp minimum touch targets. Same as iOS — touch targets are non-negotiable.
- No graph mutations without validating node types. Verify edge types are registered before writing.
Escalation
- When
design-system/tokens.json does not exist: Instruct the user: "Design tokens have not been generated. Run harness-design-system first, then re-run harness-design-mobile."
- When the project targets multiple mobile platforms: Generate for the primary platform first, then offer to generate platform-adapted variants. React Native projects get both iOS and Android considerations in a single pass.
- When tokens are insufficient for the requested component: Report missing tokens and instruct the user to add them via harness-design-system.
- When platform guidelines conflict with design intent: Present the conflict: "Material Design 3 recommends rounded corners for cards, but your design intent declares 'sharp edges only.' Options: (1) Follow platform guidelines for native feel, (2) Override with design intent for brand consistency."
- When the knowledge graph is unavailable: Skip graph operations. Log: "Graph not available — skipping token node verification and PLATFORM_BINDING edge creation. Run
harness scan later to populate."
1---2name: harness-design-mobile3description: Harness Design Mobile4---5# Harness Design Mobile67> Token-bound mobile component generation. Scaffold from design tokens and aesthetic intent, implement with React Native, SwiftUI, Flutter, or Compose patterns following platform-specific design rules, and verify every value references the token set with native convention compliance.89## When to Use1011- Generating new mobile components that must conform to the project's design system tokens12- When `on_new_feature` triggers fire with mobile UI scope requiring token-bound component generation13- When `on_commit` triggers fire and new mobile components contain hardcoded design values that should reference tokens14- Implementing design intent from `design-system/DESIGN.md` into platform-native styling (StyleSheet, SwiftUI modifiers, Flutter ThemeData, Compose MaterialTheme)15- Ensuring components follow platform-specific guidelines (iOS Human Interface Guidelines, Material Design 3, Flutter design patterns)16- NOT for generating design tokens themselves (use harness-design-system)17- NOT for establishing aesthetic direction or anti-patterns (use harness-design)18- NOT for accessibility auditing (use harness-accessibility)19- NOT for web platform components (use harness-design-web)2021## Process2223### Phase 1: SCAFFOLD — Read Tokens, Detect Platform, Plan Structure24251. **Read design tokens.** Load `design-system/tokens.json` (W3C DTCG format). Extract:26 - Color tokens: primary, secondary, accent, neutral ramps, semantic colors27 - Typography tokens: heading and body font families, font weights, font sizes, line heights28 - Spacing tokens: spacing scale values29 - If `design-system/tokens.json` does not exist, stop and instruct the user to run `harness-design-system` first.30312. **Read design intent.** Load `design-system/DESIGN.md` for:32 - Aesthetic direction (style, tone, differentiator)33 - Anti-patterns to avoid34 - Platform-specific mobile notes (touch targets, native component usage, platform conventions)35 - If `design-system/DESIGN.md` does not exist, warn the user and proceed with tokens only.36373. **Check harness configuration.** Read `harness.config.json` for:38 - `design.strictness` — enforcement level. Default to `standard`.39 - `design.platforms` — confirm `mobile` is in the platforms list.40414. **Detect mobile platform.** Scan the project for:42 - **React Native:** `package.json` contains `react-native` or `expo`, `.tsx` files with `StyleSheet` or `react-native` imports43 - **SwiftUI:** `.swift` files with `import SwiftUI`, `Package.swift` or `.xcodeproj` exists44 - **Flutter:** `pubspec.yaml` exists, `.dart` files with `import 'package:flutter/`45 - **Compose:** `build.gradle.kts` with `compose` dependencies, `.kt` files with `@Composable`46 - If the user specified `--platform`, use that override.47485. **Load platform-specific rules.** Based on detected platform, read platform design guidelines from `agents/skills/shared/design-knowledge/platform-rules/`:49 - **iOS (SwiftUI/React Native on iOS):** Read `ios.yaml` — Human Interface Guidelines, safe area insets, navigation bar patterns, tab bar conventions, dynamic type support, SF Symbols integration50 - **Android (Compose/React Native on Android):** Read `android.yaml` — Material Design 3, elevation system, shape system, dynamic color, navigation patterns, edge-to-edge layout51 - **Flutter:** Read `flutter.yaml` — Flutter design patterns, ThemeData structure, widget composition, adaptive layouts, platform channel considerations52 - **React Native cross-platform:** Read both `ios.yaml` and `android.yaml` — platform-specific overrides via `Platform.select`, safe area handling, navigation library patterns53546. **Load anti-pattern definitions.** Read anti-pattern files from `agents/skills/shared/design-knowledge/anti-patterns/`:55 - `typography.yaml` — typographic anti-patterns (too many fonts, inconsistent scales)56 - `color.yaml` — color anti-patterns (hardcoded hex, insufficient contrast)57 - `layout.yaml` — layout anti-patterns (magic numbers, inconsistent spacing)58 - `motion.yaml` — motion anti-patterns (excessive animation, missing reduced-motion)59607. **Build token-to-platform mapping.** Create a lookup table mapping tokens to platform-native representations:61 - **React Native:** `color.primary.500` maps to `StyleSheet` value or themed constant62 - **SwiftUI:** `color.primary.500` maps to `Color("primary500")` in asset catalog or `Color(hex:)` extension63 - **Flutter:** `color.primary.500` maps to `Theme.of(context).colorScheme.primary` or custom `AppColors.primary500`64 - **Compose:** `color.primary.500` maps to `MaterialTheme.colorScheme.primary` or custom `AppTheme.colors.primary500`65668. **Plan component structure.** Define:67 - Component file path(s) following platform conventions68 - Props/parameters interface69 - Which tokens will be consumed70 - Platform-specific considerations (safe areas, touch targets, dynamic type)71 - Present plan to user before proceeding.7273### Phase 2: IMPLEMENT — Generate Token-Bound Mobile Components74751. **Generate platform-specific component code.** Based on detected platform:7677 **React Native (TypeScript):**78 - Functional component with TypeScript props interface79 - All colors via themed StyleSheet or token constants (no hardcoded hex values)80 - Typography via scaled text styles referencing token font families and sizes81 - Spacing via token-derived constants in StyleSheet82 - Platform-specific overrides via `Platform.select` where iOS and Android differ83 - Safe area handling via `useSafeAreaInsets` for edge-to-edge content8485 **SwiftUI:**86 - View struct with typed properties87 - Colors from asset catalog or Color extension referencing tokens88 - Typography via custom `Font` extensions mapping to token values89 - Spacing via token-derived constants90 - Dynamic Type support via `.font(.body)` or custom scaled fonts91 - Safe area respect via `.safeAreaInset` modifiers92 - iOS Human Interface Guidelines compliance (44pt minimum touch targets)9394 **Flutter (Dart):**95 - StatelessWidget or StatefulWidget with typed constructor parameters96 - Colors via `Theme.of(context)` or custom `AppColors` class referencing tokens97 - Typography via `Theme.of(context).textTheme` or custom `AppTypography`98 - Spacing via token-derived constants class99 - Material Design 3 compliance (elevation, shape, dynamic color)100 - Adaptive layout via `LayoutBuilder` or `MediaQuery` for responsive behavior101102 **Compose (Kotlin):**103 - `@Composable` function with typed parameters104 - Colors via `MaterialTheme.colorScheme` or custom theme referencing tokens105 - Typography via `MaterialTheme.typography` or custom type scale106 - Spacing via token-derived `Dp` constants107 - Material Design 3 compliance (Surface, ElevatedCard, shape system)108 - Modifier chains for layout following Compose conventions1091102. **Apply platform-specific rules:**111 - **Touch targets:** Minimum 44x44pt (iOS) or 48x48dp (Android/Material)112 - **Safe areas:** All platforms handle notch/status bar/navigation bar correctly113 - **Typography scaling:** Support dynamic type (iOS), font scale (Android), and text scale factor (Flutter)114 - **Elevation/shadows:** Platform-appropriate (iOS shadow, Material elevation, Flutter elevation)115 - **Navigation patterns:** Platform-native navigation (UINavigationController, NavHost, Navigator)1161173. **Add USES_TOKEN annotations.** Insert platform-appropriate comments documenting token consumption:118 ```119 // @design-token color.primary.500 — primary action background120 // @design-token typography.heading.fontFamily — section heading121 // @design-token spacing.md — card internal padding122 ```123124### Phase 3: VERIFY — Check Token Binding and Platform Compliance1251261. **Scan for hardcoded values.** Search generated files for:127 - Hardcoded color values: hex codes, `UIColor(red:green:blue:)`, `Color(0xFF...)`, `Color(red:green:blue:)`128 - Hardcoded font families: string literals for font names not referencing tokens129 - Hardcoded spacing: raw numeric values in padding/margin not from the token scale1301312. **Verify token coverage.** For every design value in generated components:132 - Confirm it resolves to a token in `design-system/tokens.json`133 - Confirm the token path is valid134 - Report orphan references1351363. **Check platform guideline compliance:**137 - **iOS:** Touch targets >= 44pt, safe area respected, dynamic type supported138 - **Android/Material:** Touch targets >= 48dp, edge-to-edge layout, Material 3 components used139 - **Flutter:** ThemeData used consistently, no hardcoded Material values140 - **React Native:** Platform.select used for iOS/Android differences, safe area handled1411424. **Check anti-pattern compliance.** Cross-reference against `design-system/DESIGN.md` anti-patterns and definitions in `agents/skills/shared/design-knowledge/anti-patterns/`.1431445. **Query the knowledge graph.** If available at `.harness/graph/`:145 - Verify `DesignToken` nodes exist for all referenced tokens146 - Verify `PLATFORM_BINDING` edges exist for the target mobile platform147 - Check `VIOLATES_DESIGN` edges via `DesignConstraintAdapter`1481496. **Assign severity based on `designStrictness`:**150 - `permissive` — all findings are `info`151 - `standard` — hardcoded values are `warn`, platform guideline violations are `warn`, accessibility violations are `error`152 - `strict` — hardcoded values are `error` (blocks), platform violations are `warn`, accessibility violations are `error`1531547. **Report verification results:**155156 ```157 MOBILE-001 [warn] Hardcoded color Color(0xFF3B82F6) — should reference token158 File: lib/widgets/action_button.dart:15159 Fix: Use Theme.of(context).colorScheme.primary or AppColors.primary500160161 MOBILE-002 [warn] Touch target 32dp below minimum 48dp (Material Design 3)162 File: lib/widgets/icon_action.dart:22163 Fix: Set minimumSize to Size(48, 48) in ButtonStyle164165 MOBILE-003 [info] Missing dynamic type support166 File: Sources/Views/ProductCard.swift:18167 Fix: Use .font(.body) instead of .font(.system(size: 16))168 ```1691708. **Run `harness validate`.** Confirm new components integrate cleanly.171172## Harness Integration173174- **`harness validate`** — Run after generating components to verify project health.175- **`harness scan`** — Run after component generation to update the knowledge graph with `USES_TOKEN` and `PLATFORM_BINDING` edges.176- **`DesignIngestor`** (`packages/graph/src/ingest/DesignIngestor.ts`) — Verifies `DesignToken` nodes exist for all tokens referenced by generated components.177- **`DesignConstraintAdapter`** (`packages/graph/src/constraints/DesignConstraintAdapter.ts`) — Checks for `VIOLATES_DESIGN` edges during VERIFY phase. Reports constraint violations at configured strictness.178- **`harness-design-system`** — Dependency. Provides `design-system/tokens.json`. If tokens do not exist, instruct user to run harness-design-system first.179- **`harness-design`** — Dependency. Provides `design-system/DESIGN.md` with aesthetic intent and anti-patterns.180- **`harness-impact-analysis`** — Traces token changes to affected mobile components via `USES_TOKEN` edges.181182**Graph naming convention:** This skill uses PascalCase for node types (`DesignToken`, `DesignConstraint`) and UPPER_SNAKE for edge types (`USES_TOKEN`, `PLATFORM_BINDING`, `VIOLATES_DESIGN`) as conceptual labels. The graph schema registers these as snake_case identifiers (`design_token`, `design_constraint`, `uses_token`, `platform_binding`, `violates_design`). The adapter classes (`DesignIngestor`, `DesignConstraintAdapter`) handle the mapping — always use the adapters rather than constructing graph queries with raw type names.183184## Success Criteria185186- Generated mobile components reference design tokens exclusively — no hardcoded color, font, or spacing values187- Platform detection correctly identifies React Native, SwiftUI, Flutter, or Compose projects188- Token-to-platform mapping produces correct output for each mobile platform189- Platform-specific rules are enforced (touch targets, safe areas, dynamic type, Material 3 compliance)190- `@design-token` annotations are present for every consumed token191- Anti-pattern compliance check catches violations from `design-system/DESIGN.md`192- Verification report uses severity levels matching `design.strictness` configuration193- `harness validate` passes after component generation194195## Examples196197### Example: React Native Card Component198199**Context:** Fitness app. React Native with Expo. Tokens from harness-design-system. Design intent: expressive, warm tone.200201**SCAFFOLD output:**202203```204Platform detected: React Native (Expo)205Tokens loaded: 38 tokens from design-system/tokens.json206Design intent: Expressive, warm (from DESIGN.md)207Component plan: WorkoutCard with progress indicator208Token consumption: color.primary.*, color.accent.*, typography.heading, spacing.md/lg209Platform rules: iOS 44pt touch targets, Android 48dp touch targets, safe area insets210```211212**IMPLEMENT output (WorkoutCard.tsx):**213214```tsx215// @design-token color.primary.500 — card accent216// @design-token color.neutral.50 — card background217// @design-token color.neutral.900 — primary text218// @design-token typography.heading.fontFamily — workout title219// @design-token typography.body.fontFamily — workout details220// @design-token spacing.md — card padding221// @design-token spacing.sm — content gap222223import { View, Text, StyleSheet, Platform } from 'react-native';224import { useSafeAreaInsets } from 'react-native-safe-area-context';225import { tokens } from '@/theme/tokens';226227interface WorkoutCardProps {228 title: string;229 duration: string;230 progress: number;231}232233export function WorkoutCard({ title, duration, progress }: WorkoutCardProps) {234 return (235 <View style={styles.card}>236 <Text style={styles.title}>{title}</Text>237 <Text style={styles.detail}>{duration}</Text>238 <View style={styles.progressTrack}>239 <View style={[styles.progressFill, { width: `${progress}%` }]} />240 </View>241 </View>242 );243}244245const styles = StyleSheet.create({246 card: {247 backgroundColor: tokens.color.neutral[50],248 borderRadius: tokens.radius.md,249 padding: tokens.spacing.md,250 gap: tokens.spacing.sm,251 ...Platform.select({252 ios: {253 shadowColor: tokens.color.neutral[900],254 shadowOffset: { width: 0, height: 2 },255 shadowOpacity: 0.08,256 shadowRadius: 8,257 },258 android: {259 elevation: 2,260 },261 }),262 },263 title: {264 fontFamily: tokens.typography.heading.fontFamily,265 fontWeight: tokens.typography.heading.fontWeight,266 fontSize: 18,267 color: tokens.color.neutral[900],268 },269 detail: {270 fontFamily: tokens.typography.body.fontFamily,271 fontSize: 14,272 color: tokens.color.neutral[600],273 },274 progressTrack: {275 height: 6,276 backgroundColor: tokens.color.neutral[200],277 borderRadius: 3,278 },279 progressFill: {280 height: 6,281 backgroundColor: tokens.color.primary[500],282 borderRadius: 3,283 },284});285```286287### Example: SwiftUI List Item288289**IMPLEMENT output (WorkoutRow.swift):**290291```swift292// @design-token color.primary.500 — accent color293// @design-token color.neutral.900 — primary text294// @design-token color.neutral.600 — secondary text295// @design-token typography.heading.fontWeight — title weight296// @design-token spacing.sm — content spacing297298import SwiftUI299300struct WorkoutRow: View {301 let title: String302 let duration: String303 let progress: Double304305 var body: some View {306 VStack(alignment: .leading, spacing: AppSpacing.sm) {307 Text(title)308 .font(.headline)309 .foregroundColor(AppColors.neutral900)310311 Text(duration)312 .font(.subheadline)313 .foregroundColor(AppColors.neutral600)314315 ProgressView(value: progress)316 .tint(AppColors.primary500)317 }318 .padding(AppSpacing.md)319 .accessibilityElement(children: .combine)320 }321}322```323324## Rationalizations to Reject325326| Rationalization | Reality |327| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |328| "The touch target is 40pt on iOS — that's close to 44pt and the designer approved the comp, so I'll leave it." | The 44pt iOS minimum and 48dp Android minimum are non-negotiable gates, not guidelines. Touch target violations are `error` severity regardless of strictness level. Designer comp approval does not override platform accessibility requirements. |329| "This is a cross-platform React Native component, so I only need to read the generic token mapping — platform-specific rules for iOS and Android are optional." | React Native components require both `ios.yaml` and `android.yaml` rules. Platform-specific rules govern safe areas, elevation, navigation patterns, and touch targets that differ between platforms. Missing either set produces non-compliant native behavior. |330| "The component uses a hardcoded shadow for iOS — `shadowColor`, `shadowOffset`, etc. Those aren't design tokens, they're platform APIs." | Shadow colors must still reference token values. `shadowColor: tokens.color.neutral[900]` is the correct form. Hardcoded shadow values like `#000` or `rgba(0,0,0,0.2)` are token binding violations the VERIFY phase will flag. |331| "There's no `design-system/DESIGN.md` yet, but I know the aesthetic intent from our planning discussion — I'll proceed with tokens only." | Proceeding without `DESIGN.md` means anti-pattern enforcement is disabled for the entire VERIFY phase. The anti-pattern check is what catches design intent violations beyond token correctness. Warn the user and recommend running harness-design first. |332| "The scaffold plan is straightforward — a simple card component. I'll skip presenting it to the user and just generate." | The scaffold plan confirmation is when the user can catch incorrect platform assumptions (wrong StyleSheet structure, wrong platform APIs) before any code is written. Mobile components are harder to refactor than web components due to platform-specific branching. |333334## Gates335336- **No component generation without reading tokens from harness-design-system.** The SCAFFOLD phase requires `design-system/tokens.json`. Do not generate components with hardcoded values as a fallback.337- **No hardcoded design values in generated output.** Every color, font, and spacing value must reference a token.338- **No platform-specific code without platform detection.** The SCAFFOLD phase must detect or receive the target mobile platform before generating components.339- **No generation without scaffold plan confirmation.** Present the component plan to the user first.340- **No iOS components without 44pt minimum touch targets.** Touch target violations are `error` severity regardless of strictness level.341- **No Android/Material components without 48dp minimum touch targets.** Same as iOS — touch targets are non-negotiable.342- **No graph mutations without validating node types.** Verify edge types are registered before writing.343344## Escalation345346- **When `design-system/tokens.json` does not exist:** Instruct the user: "Design tokens have not been generated. Run `harness-design-system` first, then re-run `harness-design-mobile`."347- **When the project targets multiple mobile platforms:** Generate for the primary platform first, then offer to generate platform-adapted variants. React Native projects get both iOS and Android considerations in a single pass.348- **When tokens are insufficient for the requested component:** Report missing tokens and instruct the user to add them via harness-design-system.349- **When platform guidelines conflict with design intent:** Present the conflict: "Material Design 3 recommends rounded corners for cards, but your design intent declares 'sharp edges only.' Options: (1) Follow platform guidelines for native feel, (2) Override with design intent for brand consistency."350- **When the knowledge graph is unavailable:** Skip graph operations. Log: "Graph not available — skipping token node verification and PLATFORM_BINDING edge creation. Run `harness scan` later to populate."