diff --git a/src/modules/bmm/workflows/4-implementation/generate-design-system/checklist.md b/src/modules/bmm/workflows/4-implementation/generate-design-system/checklist.md
new file mode 100644
index 00000000..3b5206aa
--- /dev/null
+++ b/src/modules/bmm/workflows/4-implementation/generate-design-system/checklist.md
@@ -0,0 +1,18 @@
+# Generate Design System - Validation Checklist
+
+## Input Validation
+- [ ] ux-design-specification.md is loaded
+- [ ] architecture.md is loaded (if present)
+- [ ] KB path is accessible (resources/ui-ux-pro-max)
+
+## Processing Validation
+- [ ] Design decisions are successfully extracted
+- [ ] Missing items are replenished via KB
+- [ ] User confirms the design decision summary
+
+## Output Validation
+- [ ] design-tokens.json syntax is valid
+- [ ] theme.css syntax is valid
+- [ ] globals.css syntax is valid
+- [ ] component-specs.json syntax is valid
+- [ ] All CSS values reference design tokens
diff --git a/src/modules/bmm/workflows/4-implementation/generate-design-system/instructions.xml b/src/modules/bmm/workflows/4-implementation/generate-design-system/instructions.xml
new file mode 100644
index 00000000..0f0e5277
--- /dev/null
+++ b/src/modules/bmm/workflows/4-implementation/generate-design-system/instructions.xml
@@ -0,0 +1,1347 @@
+
+ The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml
+ You MUST have already loaded and processed: {installed_path}/workflow.yaml
+ Communicate all responses in {communication_language}, tailored to {user_skill_level}, and generate all documents in {document_output_language}
+
+ CRITICAL MISSION: You are the Design System Generator. You bridge the gap between UX Design and Implementation.
+ Your purpose is to translate human-readable UX specifications into machine-readable DEV artifacts.
+ Strictly follow the Single Source of Truth (SSOT) principle: Design Tokens drive everything.
+
+
+
+
+
+
+ Initialize missing_list to empty
+ Set domain to "ui-ux" for KB queries
+
+
+
+
+
+
+ HALT
+
+ Set ux_file_path to discovered path
+ Set ux_spec to ux_spec_content
+
+
+
+
+
+ Set arch_file_path to null
+ Set default_framework to "tailwind"
+ Set default_component_lib to "react"
+
+ Set arch_file_path to discovered path
+ Set architecture to architecture_content
+
+
+ Set kb_path to {kb_path}
+
+ Set kb_path to "{project-root}/resources/ui-ux-pro-max"
+
+
+
+
+
+
+
+
+
+
+
+ Load project context from {project_context}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Initialize extracted_tokens object with the following W3C Design Token structure:
+
+
+
+ ?? PARSE VISUAL FOUNDATION from {ux_spec}:
+
+
+ Extract Color Palette:
+ 1. Search for sections matching: "Color Palette", "Colors", "Color", "Palette"
+ 2. Identify parsing format:
+ FORMAT A - Markdown table:
+
+ ??Parse: role=first column, value=second column
+ FORMAT B - List format:
+
+ ??Parse: regex pattern `^[-*]\s*(\w+):\s*(#[0-9a-fA-F]{3,8}|hsl\([^)]+\)|rgb\([^)]+\))`
+ FORMAT C - Inline definition:
+
+ ??Parse: regex pattern `(primary|secondary|accent|neutral|success|warning|error)\s*(color)?\s*(is|:)?\s*(#[0-9a-fA-F]{3,8}|hsl\([^)]+\))`
+ 3. For each color role found (primary, secondary, accent, neutral, success, warning, error):
+ - Normalize value to HEX format if HSL/RGB provided
+ - If scale provided (50-900), store all values
+ - If only base color, store as "500" and mark 50/100/900 as MISSING
+ - Store with structure: { "value": "#...", "type": "color", "source": "ux-spec" }
+ 4. EDGE CASE: No color section found ??Add all required colors to missing_list
+
+
+ Extract Typography:
+ 1. Search for sections matching: "Typography", "Font", "Typeface"
+ 2. Parse font families:
+ - Look for: "Heading font:", "Heading typeface:", "heading:", "h1-h6"
+ - Look for: "Body font:", "Body typeface:", "body:", "paragraph"
+ - Look for: "Mono font:", "Code font:", "Monospace font:", "mono:"
+ - Extract font-stack string (e.g., "'Inter', sans-serif")
+ - Store: { "value": "'Inter', sans-serif", "type": "fontFamily", "source": "ux-spec" }
+ 3. Parse font sizes (if explicitly defined):
+ - Look for scale definitions: xs, sm, base, lg, xl, 2xl, 3xl, 4xl
+ - Accept rem, em, or px values (normalize to rem)
+ 4. Parse font weights and line heights if found
+ 5. EDGE CASE: Only "Inter" mentioned without stack ??Use "'Inter', system-ui, sans-serif"
+ 6. EDGE CASE: No typography section ??Add fontFamily.heading, fontFamily.body to missing_list
+
+
+ ?? PARSE SPACING AND LAYOUT from {ux_spec}:
+
+
+ ?? Extract Spacing Scale:
+ 1. Search for: "Spacing", "Space scale", "Layout"
+ 2. Identify base unit:
+ - Look for patterns: "4px base", "base unit: 4px", "0.25rem", "4pt grid"
+ - Default base: 4px (0.25rem) if not specified
+ 3. Parse scale values:
+ - Standard scale: 0, 1, 2, 3, 4, 6, 8, 12, 16
+ - Calculate: value * base_unit (e.g., 4 * 4px = 16px = 1rem)
+ - Store: { "value": "1rem", "type": "spacing", "source": "ux-spec" }
+ 4. EDGE CASE: No spacing defined ??Use default scale with base=4px, mark source as "default"
+
+
+ Extract Breakpoints:
+ 1. Search for: "Breakpoints", "Responsive", "Media queries"
+ 2. Parse breakpoint values:
+ - sm: usually 640px
+ - md: usually 768px
+ - lg: usually 1024px
+ - xl: usually 1280px
+ - 2xl: usually 1536px
+ 3. Store: { "value": "768px", "type": "dimension", "source": "ux-spec" }
+ 4. EDGE CASE: No breakpoints ??Use Tailwind defaults, mark source as "default"
+
+
+ Extract Border Radius:
+ 1. Search for: "Border Radius", "Radius", "Corners"
+ 2. Parse values: none, sm, md, lg, xl, full
+ 3. Accept rem, px values (normalize to rem)
+ 4. Store: { "value": "0.375rem", "type": "borderRadius", "source": "ux-spec" }
+ 5. EDGE CASE: No radius defined ??Add sm, md, lg to missing_list
+
+
+ PARSE EFFECTS AND ANIMATION from {ux_spec}:
+
+
+ ?? Extract Shadow Definitions:
+ 1. Search for: "Shadow", "Elevation", "Box shadow"
+ 2. Parse shadow levels: sm, md, lg, xl
+ 3. Extract full box-shadow syntax if provided:
+ Example: "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
+ 4. Store: { "value": "0 4px 6px -1px rgba(0, 0, 0, 0.1)", "type": "boxShadow", "source": "ux-spec" }
+ 5. EDGE CASE: No shadow defined ??Add sm, md to missing_list
+
+
+ ??Extract Animation Settings:
+ 1. Search for: "Animation", "Motion", "Transitions"
+ 2. Parse duration values:
+ - fast: typically 150ms
+ - normal: typically 300ms
+ - slow: typically 500ms
+ 3. Parse easing functions:
+ - default: cubic-bezier(0.4, 0, 0.2, 1)
+ - in, out, bounce variations
+ 4. Store duration: { "value": "150ms", "type": "duration", "source": "ux-spec" }
+ 5. Store easing: { "value": "cubic-bezier(0.4, 0, 0.2, 1)", "type": "cubicBezier", "source": "ux-spec" }
+ 6. EDGE CASE: No animation defined ??Add duration.fast, duration.normal, easing.default to missing_list
+
+
+
+ Extract Tech Stack from {architecture}:
+ 1. CSS Framework: search for "Tailwind", "CSS Modules", "Vanilla CSS", "SCSS", "styled-components"
+ 2. Component Library: search for "shadcn/ui", "Chakra", "MUI", "Radix", "Headless UI"
+ 3. Target Platform: search for "React", "Vue", "Next.js", "React Native", "Electron"
+ 4. Store tech_stack object with source: "architecture"
+
+
+
+
+
+ Set tech_stack = { framework: "tailwind", componentLib: "react", source: "default" }
+
+
+
+ FINALIZE extracted_tokens structure:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ?? VALIDATE extracted_tokens against required token checklist:
+ Initialize validation_errors = [] and missing_list = []
+
+
+ Define validation helper: isValidToken(token) =
+ - token !== null
+ - token !== undefined
+ - token.value !== null && token.value !== ""
+ - token.type exists
+ - Return true if all conditions pass
+
+
+ VALIDATE Colors (REQUIRED per spec 4.2):
+ CHECK: extracted_tokens.colors exists and is not empty object
+
+
+ For role = "primary":
+ - CHECK: colors.primary exists as object
+ - For each required scale in [50, 100, 500, 600, 700, 900]:
+ - CHECK: colors.primary.{scale} exists and isValidToken()
+ - IF MISSING: Add { category: "colors", key: "primary.{scale}", priority: "required" }
+
+
+ For each required role in [secondary, accent, neutral, success, warning, error]:
+ - CHECK: colors.{role} exists as object
+ - For each required scale in [500, 600, 700]:
+ - CHECK: colors.{role}.{scale} exists and isValidToken()
+ - IF MISSING: Add { category: "colors", key: "{role}.{scale}", priority: "required" }
+
+
+ VALIDATE Typography (REQUIRED):
+ CHECK: extracted_tokens.typography exists
+ Required checks:
+ 1. typography.fontFamily.heading:
+ - IF null/undefined/empty: Add to missing_list
+
+ 2. typography.fontFamily.body:
+ - IF null/undefined/empty: Add to missing_list
+
+ 3. typography.fontSize.base:
+ - IF null/undefined/empty: Add to missing_list
+
+
+
+ VALIDATE Spacing (REQUIRED per spec 4.2):
+ CHECK: extracted_tokens.spacing exists
+ For each required key in [0, 1, 2, 3, 4, 6, 8, 12, 16]:
+ - CHECK: spacing[key] exists and isValidToken()
+ - IF MISSING: Add { category: "spacing", key: "{key}", priority: "required" }
+
+
+ VALIDATE Border Radius (REQUIRED per spec 4.2):
+ CHECK: extracted_tokens.borderRadius exists
+ For each required key in [none, sm, md, lg, xl, full]:
+ - CHECK: borderRadius[key] exists and isValidToken()
+ - IF MISSING: Add { category: "borderRadius", key: "{key}", priority: "required" }
+
+
+ VALIDATE Shadow (REQUIRED per spec 4.2):
+ CHECK: extracted_tokens.shadow exists
+ For each required key in [sm, md, lg, xl]:
+ - CHECK: shadow[key] exists and isValidToken()
+ - CHECK: shadow[key].value contains valid box-shadow syntax
+ - IF MISSING: Add { category: "shadow", key: "{key}", priority: "required" }
+
+
+ ??VALIDATE Animation (REQUIRED):
+ CHECK: extracted_tokens.animation exists
+ Required checks:
+ 1. animation.duration.fast:
+ - CHECK: exists and value matches pattern /^\d+m?s$/
+ - IF MISSING: Add { category: "animation", key: "duration.fast", priority: "required" }
+ 2. animation.duration.normal:
+ - CHECK: exists and value matches pattern /^\d+m?s$/
+ - IF MISSING: Add { category: "animation", key: "duration.normal", priority: "required" }
+ 3. animation.easing.default:
+ - CHECK: exists and value contains "cubic-bezier" or valid keyword
+ - IF MISSING: Add { category: "animation", key: "easing.default", priority: "required" }
+
+
+ VALIDATE Breakpoints (REQUIRED per spec 4.2):
+ CHECK: extracted_tokens.breakpoints exists
+ For each required key in [sm, md, lg, xl, 2xl]:
+ - CHECK: breakpoints[key] exists and value matches /^\d+px$/
+ - IF MISSING: Add { category: "breakpoints", key: "{key}", priority: "required" }
+
+
+ ?? Generate Validation Report:
+ Set required_missing = missing_list.filter(item => item.priority === "required")
+ Set recommended_missing = missing_list.filter(item => item.priority === "recommended")
+
+
+
+ Set validation_status = "complete"
+
+
+
+
+ Set validation_status = "incomplete"
+
+
+
+
+
+
+
+ Store missing_list for Step 4 KB replenishment
+
+
+
+
+
+ Initialize replenished_items = []
+ Initialize kb_query_executed = false
+ Initialize kb_query_failed = false
+
+
+ EXTRACT STYLE KEYWORDS from {ux_spec} for KB queries:
+ 1. Search for sections: "Design Philosophy", "Design Principles", "Style", "Visual Direction"
+ 2. Extract style keywords using patterns:
+ - Look for adjectives: modern, minimalist, playful, professional, bold, elegant, etc.
+ - Look for style references: Bauhaus, Material, Apple-like, etc.
+ - Look for industry hints: SaaS, e-commerce, portfolio, dashboard, etc.
+ 3. Build {style} variable from found keywords (fallback: "modern professional")
+ 4. Store {industry} from project context or infer from ux_spec content
+ 5. Store {product_type} from project context or infer from ux_spec content
+
+
+ Set {style} = "modern professional"
+
+
+
+ Set {industry} = "general"
+
+
+
+
+
+
+
+
+ Define helper function getDefaultSuggestion(item):
+ switch(item.category):
+ case "colors": return "#0ea5e9" (or appropriate scale value for role)
+ case "typography": return "'Inter', system-ui, sans-serif"
+ case "spacing": return "{item.key * 0.25}rem" (4px base grid)
+ case "borderRadius": return sm=0.125rem, md=0.375rem, lg=0.5rem
+ case "shadow": return Tailwind default shadows
+ case "animation": return fast=150ms, normal=300ms, default easing
+ case "breakpoints": return Tailwind defaults (sm=640px, md=768px, etc.)
+ End function definition
+
+
+ Define helper function setNestedToken(obj, keyPath, tokenValue):
+ 1. Split keyPath by "." (e.g., "fontFamily.heading" ??["fontFamily", "heading"])
+ 2. Traverse obj, creating nested objects as needed
+ 3. Set final key to tokenValue
+ Example: setNestedToken(typography, "fontFamily.heading", {value, type, source})
+ ??typography.fontFamily.heading = {value, type, source}
+ End function definition
+
+
+
+ CATEGORIZE missing_list by token type:
+ - color_missing = missing_list.filter(m => m.category === "colors")
+ - typography_missing = missing_list.filter(m => m.category === "typography")
+ - spacing_missing = missing_list.filter(m => m.category === "spacing" || m.category === "borderRadius")
+ - shadow_missing = missing_list.filter(m => m.category === "shadow")
+ - animation_missing = missing_list.filter(m => m.category === "animation")
+ - breakpoints_missing = missing_list.filter(m => m.category === "breakpoints")
+
+
+
+
+ Set kb_query_executed = true
+ Execute query: python {kb_path}/scripts/search.py "{style} {industry} color palette" --domain color --json
+
+
+
+ Set kb_query_failed = true
+
+ Log error details for debugging
+ Skip KB color processing, proceed to next category
+
+
+
+ Continue without KB color suggestions
+
+
+ Parse JSON result with structure:
+
+ For each color found in KB results:
+
+ - Normalize value to HEX format:
+ If HSL: hsl(h, s%, l%) ??Convert using: R,G,B = hslToRgb(h/360, s/100, l/100), then #RRGGBB
+ If RGB: rgb(r, g, b) ??Convert to #RRGGBB using hex encoding
+ If already HEX: validate format #RGB or #RRGGBB or #RRGGBBAA
+
+ - Store with proper nesting:
+ - Ensure extracted_tokens.colors[role] exists as an object
+ If scale provided: extracted_tokens.colors[role][scaleKey] = { value, type: "color", source: "kb-suggestion" }
+ If single value: extracted_tokens.colors[role]["500"] = { value, type: "color", source: "kb-suggestion" }
+ - Remove from color_missing list
+ - Append to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+
+ Set kb_query_executed = true
+ Execute: python {kb_path}/scripts/search.py "{style} typography" --domain typography --json
+
+ Set kb_query_failed = true
+
+
+ Parse JSON result:
+
+ For each typography setting found:
+ - Store: extracted_tokens.typography.fontFamily[role] = { value, type: "fontFamily", source: "kb-suggestion" }
+ - Remove from typography_missing list
+ - Append to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+ Set kb_query_executed = true
+ Execute: python {kb_path}/scripts/search.py "{style} spacing system" --domain spacing --json
+
+ Set kb_query_failed = true
+
+
+ Parse JSON result and apply Tailwind-compatible scale if found
+ For spacing values: store with type: "spacing", source: "kb-suggestion"
+ For borderRadius values: store with type: "borderRadius", source: "kb-suggestion"
+ Remove filled items from spacing_missing list
+ Append filled spacing/radius items to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+ Set kb_query_executed = true
+ Execute: python {kb_path}/scripts/search.py "{style} elevation shadow" --domain elevation --json
+
+ Set kb_query_failed = true
+
+
+ Parse JSON result with box-shadow syntax
+ For each shadow found:
+ - Store: extracted_tokens.shadow[level] = { value: "box-shadow-syntax", type: "boxShadow", source: "kb-suggestion" }
+ - Remove from shadow_missing list
+ - Append to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+ Set kb_query_executed = true
+ Execute: python {kb_path}/scripts/search.py "{style} motion animation" --domain animation --json
+
+ Set kb_query_failed = true
+
+
+ Parse JSON result for duration and easing values
+ For duration values: store with type: "duration", source: "kb-suggestion"
+ For easing values: store with type: "cubicBezier", source: "kb-suggestion"
+ Remove filled items from animation_missing list
+ Append filled animation items to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+ Set kb_query_executed = true
+ Execute: python {kb_path}/scripts/search.py "{style} responsive breakpoints" --domain layout --json
+
+
+ Set kb_query_failed = true
+
+ Apply Tailwind default breakpoints: sm=640px, md=768px, lg=1024px, xl=1280px, 2xl=1536px
+ Mark source as "default" for these values
+
+
+ Parse JSON result for breakpoint values
+ For each breakpoint found:
+ - Validate format matches /^\d+px$/
+ - Store: extracted_tokens.breakpoints[key] = { value, type: "dimension", source: "kb-suggestion" }
+ - Remove from breakpoints_missing list
+ - Append to replenished_items with source: "kb-suggestion"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HALT
+
+
+
+
+
+ HALT
+
+
+
+
+ Initialize remaining_missing = []
+ Rebuild remaining_missing by concatenating all category lists after KB queries:
+ remaining_missing = [...color_missing, ...typography_missing, ...spacing_missing, ...shadow_missing, ...animation_missing, ...breakpoints_missing]
+ Filter remaining_missing by priority: required items first, then recommended
+
+
+
+
+
+
+ Please enter values or commands:
+
+
+ For EACH user input value, validate format:
+ COLOR validation: /^#[0-9a-fA-F]{3,8}$/ OR /^hsl\([^)]+\)$/ OR /^rgb\([^)]+\)$/
+ FONT validation: non-empty string (any font family name accepted)
+ DIMENSION validation: /^\d+(\.\d+)?(px|rem|em)$/
+ DURATION validation: /^\d+(ms|s)$/
+ EASING validation: /^cubic-bezier\([^)]+\)$/ OR keywords (ease, ease-in, ease-out, linear)
+
+
+
+
+
+
+
+ Please choose [r/d/s]:
+ Handle user choice accordingly
+
+
+
+
+ Use setNestedToken(extracted_tokens[category], key, { value: user_input, type: token_type, source: "user-input" })
+ This handles keys like "fontFamily.heading" ??typography.fontFamily.heading
+ Remove item from remaining_missing
+ Append to replenished_items with source: "user-input"
+
+
+
+ Apply default values with source: "default"
+ Default values reference:
+ - colors.primary.500: "#0ea5e9" (Sky Blue)
+ - colors.secondary.500: "#6366f1" (Indigo)
+ - colors.neutral.500: "#64748b" (Slate)
+ - typography.fontFamily.heading: "'Inter', system-ui, sans-serif"
+ - typography.fontFamily.body: "'Inter', system-ui, sans-serif"
+ - typography.fontSize.base: "1rem"
+ - spacing.{n}: "{n * 0.25}rem" (4px base)
+ - borderRadius.sm: "0.125rem", md: "0.375rem", lg: "0.5rem"
+ - shadow.sm: "0 1px 2px 0 rgba(0, 0, 0, 0.05)"
+ - shadow.md: "0 4px 6px -1px rgba(0, 0, 0, 0.1)"
+ - animation.duration.fast: "150ms", normal: "300ms", slow: "500ms"
+ - animation.easing.default: "cubic-bezier(0.4, 0, 0.2, 1)"
+ - breakpoints: sm=640px, md=768px, lg=1024px, xl=1280px
+ Append default-filled items to replenished_items with source: "default"
+
+
+
+
+
+ Confirm skip? [y/n]
+
+ If confirmed skip: mark item as skipped, proceed without value
+
+
+
+
+ CALCULATE source statistics:
+ - Count tokens where source === "ux-spec" ??store as ux_count
+ - Count tokens where source === "architecture" ??store as arch_count
+ - Count tokens where source === "kb-suggestion" ??store as kb_count
+ - Count tokens where source === "user-input" ??store as user_count
+ - Count tokens where source === "default" ??store as default_count
+ - Calculate total_count = ux_count + arch_count + kb_count + user_count + default_count
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ FINALIZE KB TRACKING STATE for Step 7 validation:
+ Set kb_query_executed = true if ANY KB query was attempted in Step 4
+ Set kb_hits_found = true if ANY KB query returned non-empty results
+ Build kb_hits_for_item = {} tracking per-item KB hit status:
+ For each item in original missing_list:
+ kb_hits_for_item[item.category + "." + item.key] = (KB had hit for this item)
+ Calculate missing_with_kb_hits = count of items where kb_hits_for_item[key] === true
+ Store these variables for Step 7 KB reference rate calculation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Proceed with file generation? [Y/n]
+
+ HALT
+
+
+
+
+
+ Build design_tokens_json from extracted_tokens using W3C Design Token format
+ Ensure "$schema" is set to "https://design-tokens.github.io/community-group/format/"
+ Preserve source field on every token (ux-spec/architecture/kb-suggestion/user-input/default)
+ Write file: {output_folder}/design-tokens.json
+
+
+ Generate theme.css from design_tokens_json
+ Map tokens to CSS Custom Properties using naming rules:
+ - colors: --color-{role}-{scale}
+ - typography: --font-family-*, --font-size-*, --font-weight-*, --line-height-*
+ - spacing: --spacing-{key}
+ - borderRadius: --radius-{key}
+ - shadow: --shadow-{key}
+ - animation: --duration-*, --easing-*
+ - breakpoints: --breakpoint-*
+ Group variables by section with readable comments
+ Add [data-theme="dark"] overrides for background/surface/text/text-muted if available
+ Write file: {output_folder}/theme.css
+
+
+ Generate globals.css with Modern Reset, Base Typography, and Layout Utilities
+ Ensure all values reference CSS variables from theme.css (SSOT)
+ Include :focus-visible and prefers-reduced-motion rules
+ Write file: {output_folder}/globals.css
+
+
+ Determine componentLibrary from tech_stack.componentLib (default: "react")
+ Determine effectsLibrary (default: "framer-motion", or "none" if not used)
+ Include "$schema" only if component-specs.schema.json is available (optional)
+ Build component-specs.json with meta and component definitions:
+ - Button: variants (primary/secondary/outline/ghost), sizes (sm/md/lg), states (disabled/loading), animation (hover/tap)
+ - Card: base + variants (elevated/outlined)
+ - Input: base + states (focus/error/disabled)
+ Write file: {output_folder}/component-specs.json
+
+
+
+
+
+ Initialize validation_report = { errors: [], warnings: [], metrics: {} }
+ Initialize format_errors = [], completeness_errors = [], kb_errors = [], consistency_errors = []
+
+
+ 📋 VALIDATE JSON SYNTAX:
+
+
+ Attempt to parse design-tokens.json as JSON:
+
+ Extract error line number and message from parse error
+ Add to format_errors:
+
+
+
+ Set design_tokens_json_valid = true
+
+
+
+
+ Attempt to parse component-specs.json as JSON:
+
+ Extract error line number and message from parse error
+ Add to format_errors:
+
+
+
+ Set component_specs_json_valid = true
+
+
+
+
+ 📋 VALIDATE CSS SYNTAX:
+
+
+ Validate theme.css CSS syntax:
+ 1. Check bracket balance: count of '{' must equal count of '}'
+ 2. Check property format: each line inside {} should match pattern /^\s*[\w-]+:\s*.+;?\s*$/ or be a comment
+ 3. Check for unclosed comments: /* must have matching */
+ 4. Check for invalid selectors: selectors should not contain unescaped special characters
+
+ Add to format_errors:
+
+
+
+ Add to format_errors:
+
+
+
+ Set theme_css_valid = true
+
+
+
+
+ Validate globals.css CSS syntax with detailed location tracking:
+ 1. Initialize globals_line_number = 0
+ 2. For each line in globals.css:
+ globals_line_number++
+ Track bracket_depth: '{' increases, '}' decreases
+ 3. Bracket balance check: if final bracket_depth != 0, report unbalanced
+ 4. Property format check: validate each property line matches /^\s*[\w-]+:\s*.+;?\s*$/
+ 5. Comment closure check: verify /* has matching */
+
+ Add to format_errors:
+
+
+
+ Add to format_errors:
+
+
+
+ Set globals_css_valid = true
+
+
+
+
+ 📋 VALIDATE COMPLETENESS (per spec 4.2):
+ Define required_tokens checklist from design-system-generator-spec.md Section 4.2:
+
+
+
+ CHECK colors completeness:
+ For primary: verify 50, 100, 500, 600, 700, 900 exist
+ For secondary, accent, neutral, success, warning, error: verify 500, 600, 700 exist
+
+ Add to completeness_errors:
+
+
+
+
+ CHECK typography completeness:
+ fontFamily: heading, body, mono
+ fontSize: xs, sm, base, lg, xl, 2xl, 3xl, 4xl
+ fontWeight: normal, medium, semibold, bold
+ lineHeight: tight, normal, relaxed
+
+ Add missing items to completeness_errors with category: "typography"
+
+
+
+ CHECK spacing completeness: 0, 1, 2, 3, 4, 6, 8, 12, 16
+
+ Add missing items to completeness_errors with category: "spacing"
+
+
+
+ CHECK borderRadius completeness: none, sm, md, lg, xl, full
+
+ Add missing items to completeness_errors with category: "borderRadius"
+
+
+
+ CHECK shadow completeness: sm, md, lg, xl
+
+ Add missing items to completeness_errors with category: "shadow"
+
+
+
+ CHECK animation completeness:
+ duration: fast, normal, slow
+ easing: default, in, out, bounce
+
+ Add missing items to completeness_errors with category: "animation"
+
+
+
+ CHECK breakpoints completeness: sm, md, lg, xl, 2xl
+
+ Add missing items to completeness_errors with category: "breakpoints"
+
+
+
+ CALCULATE completeness metrics at TOKEN-LEVEL:
+ Define total_required_tokens = 73 per spec 4.2:
+ - colors: 6 (primary) + 3*6 (secondary~error) = 24
+ - typography: 3 (fontFamily) + 8 (fontSize) + 4 (fontWeight) + 3 (lineHeight) = 18
+ - spacing: 9 (0,1,2,3,4,6,8,12,16)
+ - borderRadius: 6 (none,sm,md,lg,xl,full)
+ - shadow: 4 (sm,md,lg,xl)
+ - animation: 3 (duration) + 4 (easing) = 7
+ - breakpoints: 5 (sm,md,lg,xl,2xl)
+ Count missing_tokens_count by iterating all required token paths and checking existence
+ found_tokens = 73 - missing_tokens_count
+ completeness_rate = (found_tokens / 73) * 100
+ Store in validation_report.metrics.completeness_rate
+
+
+
+
+
+
+
+
+
+ 📋 VALIDATE KB REFERENCE (P0 Risk Control):
+
+
+ Retrieve kb_query_executed and kb_hits_found from Step 4 execution state
+ Count tokens with source === "kb-suggestion" as kb_sourced_count
+ Count tokens from missing_list that had KB hits as missing_with_kb_hits
+
+
+
+ Add to kb_errors:
+
+
+
+
+
+
+
+ No KB reference error - user-input and default sources are permitted
+
+
+
+ CALCULATE KB reference rate:
+
+ kb_reference_rate = (kb_sourced_count / missing_with_kb_hits) * 100
+ Store in validation_report.metrics.kb_reference_rate
+
+
+
+
+ Add warning to validation_report.warnings
+
+
+
+
+ Set kb_reference_rate = "N/A" in validation_report.metrics
+
+
+
+ 📋 VALIDATE CONTENT CONSISTENCY:
+
+
+ CHECK theme.css custom properties match design-tokens.json:
+ 1. Extract all CSS custom properties from theme.css (--color-*, --font-*, --spacing-*, etc.)
+ 2. For each custom property, verify corresponding token exists in design-tokens.json
+ 3. Verify values are consistent (allow for format differences like #hex vs rgb)
+
+ Add to consistency_errors:
+
+
+
+
+ CHECK design-tokens.json tokens have corresponding CSS custom properties (reverse check):
+ 1. For each token in design-tokens.json:
+ - Build expected CSS property name using naming convention:
+ * colors.{role}.{scale} -> --color-{role}-{scale}
+ * typography.fontFamily.{key} -> --font-family-{key}
+ * typography.fontSize.{key} -> --font-size-{key}
+ * spacing.{key} -> --spacing-{key}
+ * borderRadius.{key} -> --radius-{key}
+ * shadow.{key} -> --shadow-{key}
+ * animation.duration.{key} -> --duration-{key}
+ * animation.easing.{key} -> --easing-{key}
+ * breakpoints.{key} -> --breakpoint-{key}
+ 2. Verify the expected CSS property exists in theme.css
+
+ Add to consistency_errors:
+
+
+
+
+ CHECK theme.css contains dark theme variant:
+ Search for [data-theme="dark"] or .dark or @media (prefers-color-scheme: dark)
+
+ Add to consistency_errors:
+
+
+
+
+
+
+
+ CHECK globals.css contains required content:
+
+
+ 1. CSS Reset: search for "box-sizing: border-box" and "margin: 0"
+
+ Add to consistency_errors:
+
+
+
+
+ 2. Focus styles: search for ":focus-visible" or ":focus"
+
+ Add to consistency_errors:
+
+
+
+
+ 3. Reduced motion: search for "prefers-reduced-motion"
+
+ Add to consistency_errors:
+
+
+
+
+
+
+
+ CHECK component-specs.json covers core components:
+ Required components: Button, Card, Input
+
+ Add to consistency_errors:
+
+
+
+
+
+
+
+ 📋 GENERATE VALIDATION REPORT:
+
+
+ Combine all error arrays: all_errors = [...format_errors, ...completeness_errors, ...kb_errors, ...consistency_errors]
+
+
+ format_correct_count = (design_tokens_json_valid ? 1 : 0) + (component_specs_json_valid ? 1 : 0) + (theme_css_valid ? 1 : 0) + (globals_css_valid ? 1 : 0)
+ format_correctness_rate = (format_correct_count / 4) * 100
+ Store in validation_report.metrics.format_correctness_rate
+
+
+
+
+ For each error in all_errors:
+
+
+
+
+
+
+
+ ASSESS Dev Usability (composite metric):
+ 1. Output file coverage: 4/4 files generated?
+ 2. JSON/CSS lint: format_correctness_rate === 100?
+ 3. No blocking errors: format_errors.length === 0?
+
+
+
+ Set validation_report.dev_usability = "READY"
+
+
+
+ Set validation_report.dev_usability = "BLOCKED"
+
+
+
+ Set validation_report.dev_usability = "USABLE_WITH_GAPS"
+
+
+
+ Validate against checklist at {validation} using {project-root}/_bmad/core/tasks/validate-workflow.xml
+
+
+
+
+
+
+
+
+
+ Report completion
+
+
+
diff --git a/src/modules/bmm/workflows/4-implementation/generate-design-system/workflow.yaml b/src/modules/bmm/workflows/4-implementation/generate-design-system/workflow.yaml
new file mode 100644
index 00000000..04625080
--- /dev/null
+++ b/src/modules/bmm/workflows/4-implementation/generate-design-system/workflow.yaml
@@ -0,0 +1,53 @@
+id: generate-design-system
+name: generate-design-system
+description: "Generate DEV-Ready design system files from UX Design Specification"
+author: "BMad"
+version: "1.0.0"
+
+# Critical variables from config
+config_source: "{project-root}/_bmad/bmm/config.yaml"
+output_folder: "{config_source}:output_folder"
+user_name: "{config_source}:user_name"
+communication_language: "{config_source}:communication_language"
+user_skill_level: "{config_source}:user_skill_level"
+document_output_language: "{config_source}:document_output_language"
+date: system-generated
+
+# Workflow components
+installed_path: "{project-root}/_bmad/bmm/workflows/4-implementation/generate-design-system"
+instructions: "{installed_path}/instructions.xml"
+validation: "{installed_path}/checklist.md"
+
+# Project context
+project_context: "**/project-context.md"
+
+# Knowledge base path (configurable per environment)
+kb_path: "{config_source}:kb_path"
+
+# Input file patterns
+input_file_patterns:
+ ux_spec:
+ description: "UX Design Specification"
+ whole: "{output_folder}/*ux-design*.md"
+ sharded: "{output_folder}/*ux*/*.md"
+ load_strategy: "FULL_LOAD"
+ architecture:
+ description: "Architecture document for tech stack"
+ whole: "{output_folder}/*architecture*.md"
+ sharded: "{output_folder}/*architecture*/*.md"
+ load_strategy: "SELECTIVE_LOAD"
+ project_context:
+ description: "Project context for coding standards"
+ whole: "**/project-context.md"
+ load_strategy: "OPTIONAL"
+
+# Output files
+outputs:
+ - design-tokens.json
+ - theme.css
+ - globals.css
+ - component-specs.json
+
+standalone: true
+
+web_bundle: false
diff --git a/test-samples/TEST-GUIDE.md b/test-samples/TEST-GUIDE.md
new file mode 100644
index 00000000..e451734e
--- /dev/null
+++ b/test-samples/TEST-GUIDE.md
@@ -0,0 +1,121 @@
+# 整合測試操作指南 (Story 2.8)
+
+**日期:** 2025-12-23
+**目的:** 驗證 Design System Generator Workflow 端到端功能
+
+---
+
+## 測試環境
+
+| 項目 | 路徑 |
+|------|------|
+| KB 路徑 | `d:\Bmad\azuma520-BMAD-METHOD\resources\ui-ux-pro-max` |
+| Workflow | `d:\Bmad\azuma520-BMAD-METHOD\src\modules\bmm\workflows\4-implementation\generate-design-system\` |
+| 樣本 A | `d:\Bmad\work\output-bmm\test-samples\sample-a\` |
+| 樣本 B | `d:\Bmad\work\output-bmm\test-samples\sample-b\` |
+
+---
+
+## 測試流程
+
+### 步驟 1:執行樣本 A 測試
+
+**測試目標:** KB 有命中情境 — 驗證 KB 參考率 > 70%
+
+1. **開啟新 Chat 視窗** (確保乾淨的 context)
+2. **啟動 Dev Agent:**
+ ```
+ /bmad-bmm-agents-dev
+ ```
+3. **觸發 workflow:**
+ ```
+ generate-design-system
+ ```
+4. **當系統詢問 UX Spec 位置時,指定:**
+ ```
+ d:\Bmad\work\output-bmm\test-samples\sample-a\ux-design-specification.md
+ ```
+5. **記錄以下指標:**
+ - [ ] Step 4 的 Source Distribution 表格
+ - [ ] KB Reference Rate (%)
+ - [ ] Step 7 的 Completeness Rate
+ - [ ] 生成的 4 個輸出檔案
+
+---
+
+### 步驟 2:執行樣本 B 測試
+
+**測試目標:** KB 無命中情境 — 驗證 fallback 機制
+
+1. **開啟新 Chat 視窗** (確保乾淨的 context)
+2. **啟動 Dev Agent:**
+ ```
+ /bmad-bmm-agents-dev
+ ```
+3. **觸發 workflow:**
+ ```
+ generate-design-system
+ ```
+4. **當系統詢問 UX Spec 位置時,指定:**
+ ```
+ d:\Bmad\work\output-bmm\test-samples\sample-b\ux-design-specification.md
+ ```
+5. **當提示輸入缺失值時:**
+ - 輸入 `d-all` 使用全部預設值 (測試 fallback)
+ - 或依提示逐一輸入
+6. **記錄以下指標:**
+ - [ ] Step 4 的 Source Distribution 表格
+ - [ ] Fallback 觸發次數
+ - [ ] Step 7 的 Completeness Rate
+ - [ ] 生成的 4 個輸出檔案
+
+---
+
+### 步驟 3:驗證輸出檔案
+
+**在每個樣本目錄中檢查:**
+
+```
+sample-a/
+├── architecture.md (輸入)
+├── ux-design-specification.md (輸入)
+├── design-tokens.json (輸出 - 驗證)
+├── theme.css (輸出 - 驗證)
+├── globals.css (輸出 - 驗證)
+└── component-specs.json (輸出 - 驗證)
+```
+
+**驗證清單:**
+- [ ] JSON 檔案可正確解析 (無語法錯誤)
+- [ ] CSS 檔案可被瀏覽器解析
+- [ ] design-tokens.json 包含 source 欄位
+- [ ] theme.css 包含所有必要 CSS 變數
+
+---
+
+## 成功標準
+
+| 指標 | 樣本 A 目標 | 樣本 B 目標 |
+|------|------------|------------|
+| KB 參考率 | > 70% | N/A (預期無命中) |
+| 完整度 | 100% | 100% |
+| 格式正確率 | 100% | 100% |
+| 輸出檔案數 | 4 | 4 |
+
+---
+
+## 記錄測試結果
+
+測試完成後,請將結果填入:
+`d:\Bmad\work\output-bmm\test-samples\integration-test-report.md`
+
+---
+
+## 故障排除
+
+| 問題 | 解決方案 |
+|------|----------|
+| KB 找不到 | 確認路徑 `resources/ui-ux-pro-max` 存在 |
+| UX Spec 找不到 | 使用完整絕對路徑 |
+| JSON 解析失敗 | 檢查生成檔案的語法 |
+| Workflow 中斷 | 查看錯誤訊息,可能是輸入格式問題 |
diff --git a/test-samples/integration-test-report.md b/test-samples/integration-test-report.md
new file mode 100644
index 00000000..b77e4fa5
--- /dev/null
+++ b/test-samples/integration-test-report.md
@@ -0,0 +1,181 @@
+# Epic 2 Completion Report - Design System Generator
+
+**Date:** 2025-12-25
+**Tester:** Dev Agent (Codex)
+**Epic:** Epic 2 - Design System Generator Workflow
+**Purpose:** Validate complete UX → Design System Generator toolchain
+
+---
+
+## Epic 2 Summary
+
+Epic 2 delivers a **complete Design System Generator workflow** for BMAD:
+
+| Story | Title | Status |
+|-------|-------|--------|
+| 2.1 | Workflow Structure | ✅ Done |
+| 2.2 | Parse UX Specification | ✅ Done |
+| 2.3 | Token Extraction | ✅ Done |
+| 2.4 | KB Integration | ✅ Done |
+| 2.5 | Generate Output Files | ✅ Done |
+| 2.6 | KB Suggestion Enhancement | ✅ Done |
+| 2.7 | Validation Mechanism | ✅ Done |
+| 2.8 | Integration Testing | ✅ Done (Sample A) |
+
+**Deliverables:**
+- `instructions.xml` - Complete workflow implementation
+- `design-tokens.json` - Token definitions with source tracking
+- `theme.css` - CSS custom properties with dark mode support
+- `globals.css` - Base styles, reset, typography, components
+- `component-specs.json` - Component specifications for dev handoff
+
+---
+
+## Test Samples Overview
+
+| Sample | Description | UX Spec Path | Architecture Path | Status |
+|--------|-------------|--------------|-------------------|--------|
+| A | Minor missing values, KB hit expected | `test-samples/sample-a/ux-design-specification.md` | `test-samples/sample-a/architecture.md` | ✅ Executed |
+| B | Major missing values, KB no-hit, fallback expected | `test-samples/sample-b/ux-design-specification.md` | `test-samples/sample-b/architecture.md` | ⏸️ Deferred |
+
+---
+
+## Test Execution Matrix
+
+### Task 2: UX Workflow Execution
+
+| Sample | UX Workflow Status | KB References in UX Spec | Notes |
+|--------|-------------------|--------------------------|-------|
+| A | Executed | Color palette, typography, UX patterns | KB references recorded in UX spec |
+| B | Executed | Recorded (details in UX spec) | UX spec produced for fallback scenario |
+
+**Evidence:**
+- `work/output-bmm/test-samples/sample-a/ux-design-specification.md`
+- `work/output-bmm/test-samples/sample-b/ux-design-specification.md`
+
+---
+
+### Task 3: Generator Workflow Execution
+
+#### Sample A Results
+
+**Workflow:** `generate-design-system`
+**Status:** ✅ Executed (2025-12-25)
+
+| Metric | Expected | Actual | Pass/Fail |
+|--------|----------|--------|-----------|
+| KB Reference Rate (missing items) | > 70% | 65% (13/20) | ⚠️ |
+| KB Reference Rate (KB hit only) | > 70% | 100% (13/13) | ✅ PASS |
+| Completeness Rate | 100% | 100% | ✅ PASS |
+| Format Correctness Rate | 100% | 100% | ✅ PASS |
+| Output Files Generated | 4 | 4 | ✅ PASS |
+
+**Source Distribution:**
+| Source | Percentage |
+|--------|------------|
+| ux-spec | 62.3% |
+| kb-suggestion | 23.4% |
+| user-input | 0% |
+| default | 14.3% |
+
+**Output Files:**
+- [x] design-tokens.json
+- [x] theme.css
+- [x] globals.css
+- [x] component-specs.json
+
+**Notes:**
+- Missing required tokens: 20
+- KB filled: 13, Default: 5, UX spec backfill: 2
+- KB `elevation` domain query failed; fallback to `style`
+- Architecture not found; default Tailwind CSS + React used
+- JSON/CSS lint: PASS
+
+**Run Context:**
+- KB path (configured): `{project-root}/resources/ui-ux-pro-max`
+- KB repo location: `d:/Bmad/azuma520-BMAD-METHOD/resources/ui-ux-pro-max`
+- Generator version: BMAD Design System Generator v1.0
+- Output timestamp: 2025-12-25T12:44:30+08:00
+
+---
+
+#### Sample B Results
+
+**Status:** ⏸️ Deferred to backlog (scope reduced by team decision)
+
+---
+
+### Task 4: Stack Validation
+
+**KB Reference Non-Duplication Check:**
+- [x] UX Workflow 已補完的值,Generator 不應再觸發 KB 查詢
+- [x] 確認無重複查詢相同缺失值
+
+**Token Category Coverage:**
+- [x] colors (primary, secondary, accent, neutral, success, warning, error with 500/600/700)
+- [x] typography (fontFamily, fontSize, fontWeight, lineHeight)
+- [x] spacing (0/1/2/3/4/6/8/12/16)
+- [x] borderRadius (none/sm/md/lg/xl/full)
+- [x] shadow (sm/md/lg/xl)
+- [x] animation (duration, easing)
+- [x] breakpoints (sm/md/lg/xl/2xl)
+
+**Limitations:** UX spec did not provide a per-field KB list, so strict duplicate-check is limited to token source tags.
+
+---
+
+### Task 5: Real Project Import Validation
+
+| Check | Result | Notes |
+|-------|--------|-------|
+| CSS variables parsed | ✅ PASS | All `var(--*)` in demo-app exist in `theme.css` |
+| `data-theme` toggle | ⚠️ NO CHANGE | `[data-theme]` not defined in `theme.css` |
+| component-specs usable | ✅ PASS | Button/TaskCard/Toast align with specs |
+| No style conflicts | ✅ PASS | No layout breaks in demo-app |
+| Responsive breakpoints | ✅ PASS | 375/768/1024 show layout changes |
+
+**Evidence:**
+- `work/output-bmm/test-samples/sample-a/demo-app/public/theme.css`
+- `work/output-bmm/test-samples/sample-a/demo-app/public/globals.css`
+- `work/output-bmm/test-samples/sample-a/component-specs.json`
+- `work/output-bmm/test-samples/sample-a/demo-app/src`
+- Demo app running at `localhost:5173`
+
+---
+
+## Success Criteria Summary
+
+| Criteria | Target | Sample A | Overall |
+|----------|--------|----------|---------|
+| KB Reference Rate (when applicable) | > 70% | ✅ 100% (KB-hit) | PASS |
+| File Completeness | 100% | ✅ 100% | PASS |
+| Format Correctness | 100% | ✅ 100% | PASS |
+| Dev Usability | All pass | ✅ PASS | PASS |
+
+**Epic 2 Validation: ✅ PASSED**
+
+---
+
+## Issues Found
+
+| # | Severity | Description | Root Cause | Recommendation |
+|---|----------|-------------|------------|----------------|
+| 1 | P2 | `data-theme` 切換無效 | `theme.css` 未定義 `[data-theme]` 覆寫 | Define `[data-theme]` overrides or document limitation |
+| 2 | P3 | `@import` 非置頂 | `globals.css` 中 `@import` 不在頂部 | Move `@import` to top or inline fonts |
+| 3 | P3 | 全域 reset 可能覆蓋 | `globals.css` 設定全域 reset | Scope resets or document expected overrides |
+
+---
+
+## Sign-off
+
+- [x] Epic 2 Stories 2.1-2.8 completed
+- [x] Sample A integration test executed and passed
+- [x] Success criteria met
+- [x] Known limitations documented
+- [ ] Sample B deferred to backlog
+
+**Epic 2 Status: ✅ COMPLETE**
+
+---
+
+*Report generated: 2025-12-25 17:25 (Taiwan Time)*
diff --git a/test-samples/sample-a/PRD-AquaFlow-V1.0.md b/test-samples/sample-a/PRD-AquaFlow-V1.0.md
new file mode 100644
index 00000000..38a0c0a3
--- /dev/null
+++ b/test-samples/sample-a/PRD-AquaFlow-V1.0.md
@@ -0,0 +1,100 @@
+# PRD: AquaFlow SaaS - Project Management & Collaboration Platform (Sample A)
+
+## 1. Overview
+AquaFlow is a cloud-based project management and collaboration platform for small-to-mid sized teams. The product focuses on a clear drag-and-drop workflow, fast onboarding, and reliable task visibility.
+
+### 1.1 Goals
+- Provide an intuitive, low-friction task management experience.
+- Reduce time-to-adoption for non-technical teams.
+- Enable teams to track work status at a glance.
+- Offer consistent UX patterns for common actions (create, edit, assign, comment).
+
+### 1.2 Non-Goals
+- Deep enterprise portfolio management (PPM).
+- Native desktop apps in v1.
+- Complex time tracking or billing features.
+
+## 2. Target Users
+- Team leads and project managers at SMBs.
+- Cross-functional team members needing lightweight collaboration.
+- Ops and marketing teams with frequent task handoffs.
+
+## 3. Problem Statement
+Existing tools are either too complex or too lightweight. Teams need a balanced product that combines clarity, speed, and just enough structure to manage tasks without heavy process overhead.
+
+## 4. Key Use Cases
+1) Create projects and define task boards.
+2) Add tasks with priority, assignee, and due date.
+3) Drag tasks across columns to update status.
+4) Collaborate via comments and mentions.
+5) Track progress with basic metrics (task counts, completion rate).
+
+## 5. Core Features (MVP)
+### 5.1 Projects
+- Create and manage multiple projects.
+- Project members and roles (Owner, Editor, Viewer).
+
+### 5.2 Task Board (Primary)
+- Columns: Backlog, In Progress, Review, Done.
+- Drag-and-drop task movement.
+- Quick add tasks inline.
+
+### 5.3 Task Details
+- Title, description, assignee, due date, priority.
+- Comment thread with @mentions.
+- Activity log (created, moved, updated).
+
+### 5.4 Search and Filter
+- Search by title/assignee.
+- Filter by status, priority, due date.
+
+### 5.5 Notifications
+- In-app notifications for mentions and assignments.
+- Email notifications (configurable).
+
+## 6. UX Requirements
+- Clean, modern SaaS aesthetic.
+- Primary workflow centered around drag-and-drop board.
+- Clear visual hierarchy for task status.
+- Consistent button hierarchy and feedback patterns.
+- Accessibility: readable typography, keyboard focus states, sufficient contrast.
+
+## 7. Data Model (High-Level)
+- User: id, name, email, role
+- Project: id, name, members
+- Task: id, title, description, status, assignee, priority, due_date
+- Comment: id, task_id, author_id, body, created_at
+
+## 8. Metrics & Success Criteria
+- Activation: user creates first project and adds first task.
+- Engagement: weekly active users, tasks created per user.
+- Retention: 4-week retention rate.
+- Usability: time to complete a basic workflow (create -> assign -> move).
+
+## 9. Risks & Mitigations
+- Risk: onboarding friction.
+ - Mitigation: default templates and guided tips.
+- Risk: inconsistent UX patterns.
+ - Mitigation: design system and tokenized UI.
+- Risk: poor task discoverability.
+ - Mitigation: search and filters in MVP.
+
+## 10. Release Phases
+### Phase 1 (MVP)
+- Projects, task board, task details, comments, notifications.
+
+### Phase 2
+- Advanced analytics, automation rules, integrations.
+
+## 11. Out of Scope
+- Enterprise SSO (SAML) in MVP.
+- Complex dependency management.
+- Mobile native apps.
+
+## 12. Open Questions
+- Which integrations (Slack, Google Calendar) are most critical for Phase 2?
+- Should we support custom workflows in MVP?
+
+## 13. Appendix
+- Style direction: Modern Professional SaaS
+- Keywords: trust, efficiency, clarity, professional
diff --git a/test-samples/sample-a/architecture.md b/test-samples/sample-a/architecture.md
new file mode 100644
index 00000000..68dcf669
--- /dev/null
+++ b/test-samples/sample-a/architecture.md
@@ -0,0 +1,28 @@
+# Architecture Document - Sample A (Integration Test)
+
+**Project:** AquaFlow SaaS Project Management Platform
+**Date:** 2025-12-23
+**Purpose:** Integration Testing - KB Hit Scenario
+
+---
+
+## Tech Stack
+
+### Frontend
+- **Framework:** React 18
+- **UI Library:** Chakra UI v2
+- **State Management:** Zustand
+- **Drag & Drop:** @dnd-kit/core
+- **Animation:** Framer Motion
+- **Styling:** CSS-in-JS (Chakra theme)
+
+### Design System
+- **Approach:** Custom Design Tokens + Chakra Theme
+- **Output Format:** CSS Custom Properties + JSON Tokens
+
+---
+
+## Notes
+
+> This architecture document is for integration testing purposes.
+> Sample A tests the scenario where KB has matching suggestions for missing tokens.
diff --git a/test-samples/sample-a/component-specs.json b/test-samples/sample-a/component-specs.json
new file mode 100644
index 00000000..23684a32
--- /dev/null
+++ b/test-samples/sample-a/component-specs.json
@@ -0,0 +1,535 @@
+{
+ "$metadata": {
+ "generator": "BMAD Design System Generator v1.0",
+ "source": "ux-design-specification.md",
+ "project": "AquaFlow SaaS",
+ "generatedAt": "2025-12-25T12:44:30+08:00"
+ },
+ "components": {
+ "TaskCard": {
+ "name": "TaskCard",
+ "description": "看板上的可拖曳任務卡片",
+ "category": "business",
+ "status": "design-ready",
+ "props": {
+ "id": {
+ "type": "string",
+ "required": true
+ },
+ "title": {
+ "type": "string",
+ "required": true
+ },
+ "labels": {
+ "type": "Label[]",
+ "required": false,
+ "default": "[]"
+ },
+ "assignee": {
+ "type": "User | null",
+ "required": false
+ },
+ "dueDate": {
+ "type": "Date | null",
+ "required": false
+ },
+ "priority": {
+ "type": "'low' | 'medium' | 'high' | 'urgent'",
+ "required": false,
+ "default": "'medium'"
+ },
+ "isDragging": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ },
+ "isSelected": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ }
+ },
+ "states": {
+ "default": {
+ "background": "var(--bg-card)",
+ "borderRadius": "var(--radius-md)",
+ "boxShadow": "var(--shadow-sm)",
+ "padding": "var(--space-3)"
+ },
+ "hover": {
+ "background": "var(--color-neutral-50)",
+ "cursor": "pointer",
+ "transition": "background-color var(--duration-fast) var(--easing-default)"
+ },
+ "dragging": {
+ "boxShadow": "var(--shadow-lg)",
+ "transform": "rotate(3deg)",
+ "opacity": "0.9",
+ "cursor": "grabbing"
+ },
+ "selected": {
+ "outline": "2px solid var(--color-primary-500)",
+ "outlineOffset": "2px"
+ },
+ "loading": {
+ "opacity": "0.6",
+ "pointerEvents": "none"
+ }
+ },
+ "accessibility": {
+ "role": "listitem",
+ "ariaGrabbed": "boolean (when dragging)",
+ "focusRing": "var(--focus-ring-width) solid var(--focus-ring-color)",
+ "keyboardNav": "Tab to focus, Space/Enter to select, Arrow keys to move"
+ },
+ "kbReferences": [
+ "#28 Focus States",
+ "#29 Hover States",
+ "#30 Active States",
+ "#84 Truncation",
+ "#40 ARIA Labels"
+ ]
+ },
+ "KanbanColumn": {
+ "name": "KanbanColumn",
+ "description": "任務狀態欄(待辦/進行中/完成)",
+ "category": "business",
+ "status": "design-ready",
+ "props": {
+ "id": {
+ "type": "string",
+ "required": true
+ },
+ "title": {
+ "type": "string",
+ "required": true
+ },
+ "tasks": {
+ "type": "Task[]",
+ "required": true
+ },
+ "taskCount": {
+ "type": "number",
+ "required": false
+ },
+ "isDropTarget": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ },
+ "isEmpty": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ }
+ },
+ "states": {
+ "default": {
+ "background": "var(--color-neutral-100)",
+ "borderRadius": "var(--radius-lg)",
+ "padding": "var(--space-3)",
+ "minHeight": "200px"
+ },
+ "dropTargetActive": {
+ "background": "var(--color-primary-50)",
+ "outline": "2px dashed var(--color-primary-500)",
+ "outlineOffset": "-2px"
+ },
+ "empty": {
+ "display": "flex",
+ "alignItems": "center",
+ "justifyContent": "center",
+ "color": "var(--text-muted)",
+ "fontSize": "var(--font-size-sm)"
+ }
+ },
+ "emptyState": {
+ "message": "尚無任務,拖曳或點擊新增",
+ "icon": "plus-circle"
+ },
+ "accessibility": {
+ "role": "list",
+ "ariaLabel": "dynamic: {title} 欄位,共 {taskCount} 項任務"
+ },
+ "kbReferences": [
+ "#80 Empty States",
+ "#10 Loading States"
+ ]
+ },
+ "CommandPalette": {
+ "name": "CommandPalette",
+ "description": "Cmd+K 全域搜尋/快捷指令面板",
+ "category": "navigation",
+ "status": "design-ready",
+ "props": {
+ "isOpen": {
+ "type": "boolean",
+ "required": true
+ },
+ "searchQuery": {
+ "type": "string",
+ "required": false,
+ "default": "''"
+ },
+ "results": {
+ "type": "SearchResult[]",
+ "required": false,
+ "default": "[]"
+ },
+ "recentItems": {
+ "type": "SearchResult[]",
+ "required": false,
+ "default": "[]"
+ },
+ "onClose": {
+ "type": "() => void",
+ "required": true
+ },
+ "onSelect": {
+ "type": "(item: SearchResult) => void",
+ "required": true
+ }
+ },
+ "states": {
+ "open": {
+ "position": "fixed",
+ "top": "20%",
+ "left": "50%",
+ "transform": "translateX(-50%)",
+ "width": "min(600px, 90vw)",
+ "maxHeight": "400px",
+ "background": "var(--bg-card)",
+ "borderRadius": "var(--radius-lg)",
+ "boxShadow": "var(--shadow-xl)",
+ "zIndex": "9999"
+ },
+ "searching": {
+ "showSpinner": true
+ },
+ "results": {
+ "overflow": "auto"
+ },
+ "empty": {
+ "message": "找不到符合的結果",
+ "showRecentItems": true
+ }
+ },
+ "keyboard": {
+ "trigger": "Cmd+K / Ctrl+K",
+ "navigate": "Arrow Up/Down",
+ "select": "Enter",
+ "close": "Escape"
+ },
+ "accessibility": {
+ "role": "dialog",
+ "ariaModal": true,
+ "ariaLabel": "快速搜尋",
+ "focusTrap": true
+ },
+ "kbReferences": [
+ "#41 Keyboard Navigation",
+ "#28 Focus States",
+ "#89 Search Autocomplete"
+ ]
+ },
+ "ProgressRing": {
+ "name": "ProgressRing",
+ "description": "視覺化任務完成進度環",
+ "category": "feedback",
+ "status": "design-ready",
+ "props": {
+ "value": {
+ "type": "number",
+ "required": true,
+ "description": "0-100 百分比"
+ },
+ "size": {
+ "type": "'sm' | 'md' | 'lg'",
+ "required": false,
+ "default": "'md'"
+ },
+ "showLabel": {
+ "type": "boolean",
+ "required": false,
+ "default": "true"
+ },
+ "color": {
+ "type": "string",
+ "required": false,
+ "default": "var(--color-primary-500)"
+ }
+ },
+ "sizes": {
+ "sm": {
+ "diameter": "24px",
+ "strokeWidth": "3px",
+ "fontSize": "var(--font-size-xs)"
+ },
+ "md": {
+ "diameter": "32px",
+ "strokeWidth": "4px",
+ "fontSize": "var(--font-size-sm)"
+ },
+ "lg": {
+ "diameter": "48px",
+ "strokeWidth": "5px",
+ "fontSize": "var(--font-size-base)"
+ }
+ },
+ "animation": {
+ "duration": "var(--duration-normal)",
+ "easing": "var(--easing-out)",
+ "respectsReducedMotion": true
+ },
+ "accessibility": {
+ "role": "progressbar",
+ "ariaValueNow": "dynamic: {value}",
+ "ariaValueMin": "0",
+ "ariaValueMax": "100",
+ "ariaLabel": "任務完成進度"
+ },
+ "kbReferences": [
+ "#8 Duration Timing",
+ "#9 Reduced Motion"
+ ]
+ },
+ "Button": {
+ "name": "Button",
+ "description": "通用按鈕組件",
+ "category": "primitive",
+ "status": "design-ready",
+ "props": {
+ "variant": {
+ "type": "'primary' | 'secondary' | 'ghost' | 'danger'",
+ "required": false,
+ "default": "'primary'"
+ },
+ "size": {
+ "type": "'sm' | 'md' | 'lg'",
+ "required": false,
+ "default": "'md'"
+ },
+ "isLoading": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ },
+ "isDisabled": {
+ "type": "boolean",
+ "required": false,
+ "default": "false"
+ },
+ "leftIcon": {
+ "type": "ReactNode",
+ "required": false
+ },
+ "rightIcon": {
+ "type": "ReactNode",
+ "required": false
+ },
+ "children": {
+ "type": "ReactNode",
+ "required": true
+ }
+ },
+ "variants": {
+ "primary": {
+ "background": "var(--color-primary-500)",
+ "color": "white",
+ "hoverBackground": "var(--color-primary-700)"
+ },
+ "secondary": {
+ "background": "transparent",
+ "color": "var(--color-primary-500)",
+ "border": "1px solid var(--color-primary-500)",
+ "hoverBackground": "var(--color-primary-50)"
+ },
+ "ghost": {
+ "background": "transparent",
+ "color": "var(--text-secondary)",
+ "hoverBackground": "var(--color-neutral-100)"
+ },
+ "danger": {
+ "background": "var(--color-error-500)",
+ "color": "white",
+ "hoverBackground": "var(--color-error-700)"
+ }
+ },
+ "sizes": {
+ "sm": {
+ "padding": "var(--space-1) var(--space-2)",
+ "fontSize": "var(--font-size-sm)",
+ "minHeight": "32px"
+ },
+ "md": {
+ "padding": "var(--space-2) var(--space-4)",
+ "fontSize": "var(--font-size-base)",
+ "minHeight": "44px"
+ },
+ "lg": {
+ "padding": "var(--space-3) var(--space-6)",
+ "fontSize": "var(--font-size-lg)",
+ "minHeight": "52px"
+ }
+ },
+ "states": {
+ "hover": {
+ "filter": "brightness(1.1)"
+ },
+ "active": {
+ "transform": "scale(0.98)"
+ },
+ "disabled": {
+ "opacity": "0.5",
+ "cursor": "not-allowed"
+ },
+ "loading": {
+ "opacity": "0.8",
+ "cursor": "wait"
+ }
+ },
+ "accessibility": {
+ "minTouchTarget": "44x44px",
+ "focusRing": "var(--focus-ring-width) solid var(--focus-ring-color)"
+ }
+ },
+ "Toast": {
+ "name": "Toast",
+ "description": "通知訊息組件",
+ "category": "feedback",
+ "status": "design-ready",
+ "props": {
+ "type": {
+ "type": "'success' | 'error' | 'warning' | 'info'",
+ "required": true
+ },
+ "message": {
+ "type": "string",
+ "required": true
+ },
+ "duration": {
+ "type": "number",
+ "required": false,
+ "default": "3000",
+ "description": "ms, 0 for persistent"
+ },
+ "onDismiss": {
+ "type": "() => void",
+ "required": false
+ }
+ },
+ "types": {
+ "success": {
+ "icon": "check-circle",
+ "color": "var(--color-success-500)",
+ "duration": "3000"
+ },
+ "error": {
+ "icon": "x-circle",
+ "color": "var(--color-error-500)",
+ "duration": "0"
+ },
+ "warning": {
+ "icon": "alert-triangle",
+ "color": "var(--color-warning-500)",
+ "duration": "5000"
+ },
+ "info": {
+ "icon": "info",
+ "color": "var(--color-primary-500)",
+ "duration": "5000"
+ }
+ },
+ "animation": {
+ "enter": "slideIn from right",
+ "exit": "fadeOut",
+ "duration": "var(--duration-normal)"
+ },
+ "accessibility": {
+ "role": "alert",
+ "ariaLive": "polite"
+ }
+ }
+ },
+ "patterns": {
+ "interactiveElement": {
+ "description": "所有互動元素的通用狀態規範",
+ "states": {
+ "focus": "ring-2 ring-blue-500 ring-offset-2",
+ "hover": "bg-gray-50 transition-colors",
+ "active": "scale-[0.98]",
+ "disabled": "opacity-50 cursor-not-allowed"
+ },
+ "touchTarget": "min-h-[44px] min-w-[44px]",
+ "transition": "all var(--duration-normal) var(--easing-default)"
+ },
+ "formField": {
+ "description": "表單欄位通用規範",
+ "label": {
+ "position": "above",
+ "required": "標示 *",
+ "fontSize": "var(--font-size-sm)",
+ "fontWeight": "var(--font-weight-medium)"
+ },
+ "input": {
+ "minHeight": "44px",
+ "borderRadius": "var(--radius-md)",
+ "borderColor": "var(--border-color)"
+ },
+ "error": {
+ "position": "below",
+ "color": "var(--color-error-500)",
+ "fontSize": "var(--font-size-sm)"
+ },
+ "validation": "onBlur"
+ },
+ "modal": {
+ "description": "對話框通用規範",
+ "backdrop": "rgba(0, 0, 0, 0.5)",
+ "borderRadius": "var(--radius-lg)",
+ "closeOptions": [
+ "button",
+ "Esc",
+ "click outside"
+ ],
+ "focusTrap": true,
+ "animation": {
+ "enter": "fadeIn + scaleUp",
+ "exit": "fadeOut + scaleDown"
+ }
+ }
+ },
+ "implementationRoadmap": {
+ "phase1": {
+ "name": "Core Components",
+ "priority": "P0",
+ "components": [
+ "TaskCard",
+ "KanbanColumn",
+ "Button"
+ ],
+ "dependencies": [
+ "@dnd-kit/core",
+ "@dnd-kit/sortable"
+ ]
+ },
+ "phase2": {
+ "name": "Navigation & Feedback",
+ "priority": "P1",
+ "components": [
+ "CommandPalette",
+ "ProgressRing",
+ "Toast"
+ ]
+ },
+ "phase3": {
+ "name": "Extended Components",
+ "priority": "P2",
+ "components": [
+ "ActivityFeed",
+ "UserAvatar",
+ "ProjectCard"
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/test-samples/sample-a/design-tokens.json b/test-samples/sample-a/design-tokens.json
new file mode 100644
index 00000000..8a921986
--- /dev/null
+++ b/test-samples/sample-a/design-tokens.json
@@ -0,0 +1,448 @@
+{
+ "$metadata": {
+ "generator": "BMAD Design System Generator v1.0",
+ "source": "ux-design-specification.md",
+ "project": "AquaFlow SaaS",
+ "generatedAt": "2025-12-25T12:44:30+08:00"
+ },
+ "colors": {
+ "primary": {
+ "50": {
+ "value": "#EFF6FF",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "100": {
+ "value": "#DBEAFE",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "500": {
+ "value": "#2563EB",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#2563EB",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "700": {
+ "value": "#1D4ED8",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "900": {
+ "value": "#1E3A8A",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "secondary": {
+ "500": {
+ "value": "#3B82F6",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#2563EB",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#1D4ED8",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "accent": {
+ "500": {
+ "value": "#F97316",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#EA580C",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#C2410C",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "neutral": {
+ "50": {
+ "value": "#F8FAFC",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "100": {
+ "value": "#F1F5F9",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "200": {
+ "value": "#E2E8F0",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "500": {
+ "value": "#64748B",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "600": {
+ "value": "#475569",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#334155",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "800": {
+ "value": "#1E293B",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "900": {
+ "value": "#0F172A",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "success": {
+ "500": {
+ "value": "#22C55E",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#16A34A",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#15803D",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "warning": {
+ "500": {
+ "value": "#EAB308",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#CA8A04",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#A16207",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ },
+ "error": {
+ "500": {
+ "value": "#EF4444",
+ "type": "color",
+ "source": "ux-spec"
+ },
+ "600": {
+ "value": "#DC2626",
+ "type": "color",
+ "source": "kb-suggestion"
+ },
+ "700": {
+ "value": "#B91C1C",
+ "type": "color",
+ "source": "kb-suggestion"
+ }
+ }
+ },
+ "typography": {
+ "fontFamily": {
+ "heading": {
+ "value": "'Inter', system-ui, sans-serif",
+ "type": "fontFamily",
+ "source": "ux-spec"
+ },
+ "body": {
+ "value": "'Inter', system-ui, sans-serif",
+ "type": "fontFamily",
+ "source": "ux-spec"
+ },
+ "mono": {
+ "value": "'JetBrains Mono', 'Fira Code', monospace",
+ "type": "fontFamily",
+ "source": "default"
+ }
+ },
+ "fontSize": {
+ "xs": {
+ "value": "0.75rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "sm": {
+ "value": "0.875rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "base": {
+ "value": "1rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "lg": {
+ "value": "1.25rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "xl": {
+ "value": "1.5rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "2xl": {
+ "value": "2rem",
+ "type": "fontSize",
+ "source": "ux-spec"
+ },
+ "3xl": {
+ "value": "2.5rem",
+ "type": "fontSize",
+ "source": "default"
+ },
+ "4xl": {
+ "value": "3rem",
+ "type": "fontSize",
+ "source": "default"
+ }
+ },
+ "fontWeight": {
+ "normal": {
+ "value": "400",
+ "type": "fontWeight",
+ "source": "ux-spec"
+ },
+ "medium": {
+ "value": "500",
+ "type": "fontWeight",
+ "source": "ux-spec"
+ },
+ "semibold": {
+ "value": "600",
+ "type": "fontWeight",
+ "source": "ux-spec"
+ },
+ "bold": {
+ "value": "700",
+ "type": "fontWeight",
+ "source": "ux-spec"
+ }
+ },
+ "lineHeight": {
+ "tight": {
+ "value": "1.2",
+ "type": "lineHeight",
+ "source": "ux-spec"
+ },
+ "snug": {
+ "value": "1.3",
+ "type": "lineHeight",
+ "source": "ux-spec"
+ },
+ "normal": {
+ "value": "1.5",
+ "type": "lineHeight",
+ "source": "ux-spec"
+ },
+ "relaxed": {
+ "value": "1.6",
+ "type": "lineHeight",
+ "source": "default"
+ }
+ }
+ },
+ "spacing": {
+ "0": {
+ "value": "0",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "1": {
+ "value": "0.25rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "2": {
+ "value": "0.5rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "3": {
+ "value": "0.75rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "4": {
+ "value": "1rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "6": {
+ "value": "1.5rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "8": {
+ "value": "2rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "10": {
+ "value": "2.5rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "12": {
+ "value": "3rem",
+ "type": "spacing",
+ "source": "ux-spec"
+ },
+ "16": {
+ "value": "4rem",
+ "type": "spacing",
+ "source": "default"
+ }
+ },
+ "borderRadius": {
+ "none": {
+ "value": "0",
+ "type": "borderRadius",
+ "source": "default"
+ },
+ "sm": {
+ "value": "0.25rem",
+ "type": "borderRadius",
+ "source": "ux-spec"
+ },
+ "md": {
+ "value": "0.5rem",
+ "type": "borderRadius",
+ "source": "ux-spec"
+ },
+ "lg": {
+ "value": "1rem",
+ "type": "borderRadius",
+ "source": "ux-spec"
+ },
+ "xl": {
+ "value": "1.5rem",
+ "type": "borderRadius",
+ "source": "default"
+ },
+ "full": {
+ "value": "9999px",
+ "type": "borderRadius",
+ "source": "default"
+ }
+ },
+ "shadow": {
+ "sm": {
+ "value": "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
+ "type": "boxShadow",
+ "source": "kb-suggestion"
+ },
+ "md": {
+ "value": "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)",
+ "type": "boxShadow",
+ "source": "kb-suggestion"
+ },
+ "lg": {
+ "value": "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
+ "type": "boxShadow",
+ "source": "kb-suggestion"
+ },
+ "xl": {
+ "value": "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1)",
+ "type": "boxShadow",
+ "source": "kb-suggestion"
+ }
+ },
+ "animation": {
+ "duration": {
+ "fast": {
+ "value": "150ms",
+ "type": "duration",
+ "source": "default"
+ },
+ "normal": {
+ "value": "200ms",
+ "type": "duration",
+ "source": "ux-spec"
+ },
+ "slow": {
+ "value": "300ms",
+ "type": "duration",
+ "source": "default"
+ }
+ },
+ "easing": {
+ "default": {
+ "value": "cubic-bezier(0.4, 0, 0.2, 1)",
+ "type": "cubicBezier",
+ "source": "default"
+ },
+ "in": {
+ "value": "cubic-bezier(0.4, 0, 1, 1)",
+ "type": "cubicBezier",
+ "source": "default"
+ },
+ "out": {
+ "value": "cubic-bezier(0, 0, 0.2, 1)",
+ "type": "cubicBezier",
+ "source": "default"
+ },
+ "inOut": {
+ "value": "cubic-bezier(0.4, 0, 0.2, 1)",
+ "type": "cubicBezier",
+ "source": "default"
+ }
+ }
+ },
+ "breakpoints": {
+ "sm": {
+ "value": "320px",
+ "type": "dimension",
+ "source": "ux-spec"
+ },
+ "md": {
+ "value": "768px",
+ "type": "dimension",
+ "source": "ux-spec"
+ },
+ "lg": {
+ "value": "1024px",
+ "type": "dimension",
+ "source": "ux-spec"
+ },
+ "xl": {
+ "value": "1440px",
+ "type": "dimension",
+ "source": "ux-spec"
+ },
+ "2xl": {
+ "value": "1536px",
+ "type": "dimension",
+ "source": "default"
+ }
+ }
+}
\ No newline at end of file
diff --git a/test-samples/sample-a/globals.css b/test-samples/sample-a/globals.css
new file mode 100644
index 00000000..3b222496
--- /dev/null
+++ b/test-samples/sample-a/globals.css
@@ -0,0 +1,379 @@
+/**
+ * AquaFlow Design System - Global Styles
+ * Generated by BMAD Design System Generator v1.0
+ * Source: ux-design-specification.md
+ * Generated: 2025-12-25T12:44:30+08:00
+ *
+ * Usage: Import after theme.css
+ * @import './theme.css';
+ * @import './globals.css';
+ */
+
+/* ============================================
+ CSS Reset & Box Sizing
+ ============================================ */
+
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+}
+
+/* ============================================
+ Font Import (Inter from Google Fonts)
+ ============================================ */
+
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
+
+/* ============================================
+ Base HTML Elements
+ ============================================ */
+
+html {
+ font-size: 16px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+ text-rendering: optimizeLegibility;
+ scroll-behavior: smooth;
+}
+
+@media (prefers-reduced-motion: reduce) {
+ html {
+ scroll-behavior: auto;
+ }
+}
+
+body {
+ font-family: var(--font-family-body);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-normal);
+ line-height: var(--line-height-normal);
+ color: var(--text-primary);
+ background-color: var(--bg-primary);
+ min-height: 100vh;
+}
+
+/* ============================================
+ Typography
+ ============================================ */
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-family: var(--font-family-heading);
+ font-weight: var(--font-weight-bold);
+ line-height: var(--line-height-tight);
+ color: var(--text-primary);
+ margin-bottom: var(--space-4);
+}
+
+h1 {
+ font-size: var(--font-size-2xl);
+ font-weight: var(--font-weight-bold);
+ line-height: var(--line-height-tight);
+}
+
+h2 {
+ font-size: var(--font-size-xl);
+ font-weight: var(--font-weight-semibold);
+ line-height: var(--line-height-snug);
+}
+
+h3 {
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-semibold);
+ line-height: var(--line-height-snug);
+}
+
+p {
+ margin-bottom: var(--space-4);
+}
+
+small {
+ font-size: var(--font-size-sm);
+}
+
+code,
+pre {
+ font-family: var(--font-family-mono);
+}
+
+/* ============================================
+ Links
+ ============================================ */
+
+a {
+ color: var(--color-primary-500);
+ text-decoration: none;
+ transition: color var(--duration-fast) var(--easing-default);
+}
+
+a:hover {
+ color: var(--color-primary-700);
+ text-decoration: underline;
+}
+
+a:focus-visible {
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
+ outline-offset: var(--focus-ring-offset);
+ border-radius: var(--radius-sm);
+}
+
+/* ============================================
+ Buttons (Base)
+ ============================================ */
+
+button,
+.btn {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: var(--space-2);
+
+ font-family: var(--font-family-body);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-medium);
+ line-height: 1;
+
+ padding: var(--space-2) var(--space-4);
+ min-height: 44px;
+ min-width: 44px;
+
+ border: none;
+ border-radius: var(--radius-md);
+ cursor: pointer;
+
+ transition:
+ background-color var(--duration-fast) var(--easing-default),
+ transform var(--duration-fast) var(--easing-default),
+ box-shadow var(--duration-fast) var(--easing-default);
+}
+
+button:focus-visible,
+.btn:focus-visible {
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
+ outline-offset: var(--focus-ring-offset);
+}
+
+button:active,
+.btn:active {
+ transform: scale(0.98);
+}
+
+button:disabled,
+.btn:disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ transform: none;
+}
+
+/* Button Variants */
+.btn-primary {
+ background-color: var(--color-primary-500);
+ color: white;
+}
+
+.btn-primary:hover:not(:disabled) {
+ background-color: var(--color-primary-700);
+}
+
+.btn-secondary {
+ background-color: transparent;
+ color: var(--color-primary-500);
+ border: 1px solid var(--color-primary-500);
+}
+
+.btn-secondary:hover:not(:disabled) {
+ background-color: var(--color-primary-50);
+}
+
+.btn-ghost {
+ background-color: transparent;
+ color: var(--text-secondary);
+}
+
+.btn-ghost:hover:not(:disabled) {
+ background-color: var(--color-neutral-100);
+}
+
+.btn-danger {
+ background-color: var(--color-error-500);
+ color: white;
+}
+
+.btn-danger:hover:not(:disabled) {
+ background-color: var(--color-error-700);
+}
+
+/* ============================================
+ Form Elements
+ ============================================ */
+
+input,
+textarea,
+select {
+ font-family: var(--font-family-body);
+ font-size: var(--font-size-base);
+
+ padding: var(--space-2) var(--space-3);
+ min-height: 44px;
+
+ background-color: white;
+ border: 1px solid var(--border-color);
+ border-radius: var(--radius-md);
+
+ transition:
+ border-color var(--duration-fast) var(--easing-default),
+ box-shadow var(--duration-fast) var(--easing-default);
+}
+
+input:hover,
+textarea:hover,
+select:hover {
+ border-color: var(--border-hover);
+}
+
+input:focus,
+textarea:focus,
+select:focus {
+ outline: none;
+ border-color: var(--color-primary-500);
+ box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
+}
+
+input:disabled,
+textarea:disabled,
+select:disabled {
+ background-color: var(--color-neutral-100);
+ cursor: not-allowed;
+}
+
+input::placeholder,
+textarea::placeholder {
+ color: var(--text-muted);
+}
+
+label {
+ display: block;
+ font-size: var(--font-size-sm);
+ font-weight: var(--font-weight-medium);
+ color: var(--text-primary);
+ margin-bottom: var(--space-1);
+}
+
+/* ============================================
+ Cards
+ ============================================ */
+
+.card {
+ background-color: var(--bg-card);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-sm);
+ padding: var(--space-4);
+
+ transition:
+ box-shadow var(--duration-fast) var(--easing-default),
+ transform var(--duration-fast) var(--easing-default);
+}
+
+.card:hover {
+ box-shadow: var(--shadow-md);
+}
+
+.card-interactive:hover {
+ transform: translateY(-2px);
+ cursor: pointer;
+}
+
+/* ============================================
+ Utilities
+ ============================================ */
+
+/* Focus visible utility */
+.focus-visible:focus-visible {
+ outline: var(--focus-ring-width) solid var(--focus-ring-color);
+ outline-offset: var(--focus-ring-offset);
+}
+
+/* Screen reader only */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* Skip link */
+.skip-link {
+ position: absolute;
+ top: -100%;
+ left: 0;
+ z-index: 9999;
+ padding: var(--space-2) var(--space-4);
+ background-color: var(--color-primary-500);
+ color: white;
+ text-decoration: none;
+}
+
+.skip-link:focus {
+ top: 0;
+}
+
+/* Truncation */
+.truncate {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.line-clamp-2 {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+/* ============================================
+ Layout
+ ============================================ */
+
+.container {
+ max-width: var(--max-width);
+ margin: 0 auto;
+ padding: 0 var(--space-4);
+}
+
+/* ============================================
+ Responsive Breakpoints
+ ============================================ */
+
+/* Mobile first - base styles are for mobile */
+
+/* Tablet and up */
+@media (min-width: 768px) {
+ h1 {
+ font-size: calc(var(--font-size-2xl) * 1.25);
+ }
+
+ h2 {
+ font-size: calc(var(--font-size-xl) * 1.1);
+ }
+}
+
+/* Desktop and up */
+@media (min-width: 1024px) {
+ .container {
+ padding: 0 var(--space-6);
+ }
+}
\ No newline at end of file
diff --git a/test-samples/sample-a/theme.css b/test-samples/sample-a/theme.css
new file mode 100644
index 00000000..c035f05c
--- /dev/null
+++ b/test-samples/sample-a/theme.css
@@ -0,0 +1,217 @@
+/**
+ * AquaFlow Design System - Theme CSS
+ * Generated by BMAD Design System Generator v1.0
+ * Source: ux-design-specification.md
+ * Generated: 2025-12-25T12:44:30+08:00
+ *
+ * Usage: Import this file in your main CSS or component library
+ * @import './theme.css';
+ */
+
+/* ============================================
+ CSS Custom Properties (Design Tokens)
+ ============================================ */
+
+:root {
+ /* -------------------- Colors -------------------- */
+
+ /* Primary - Trust Blue */
+ --color-primary-50: #EFF6FF;
+ --color-primary-100: #DBEAFE;
+ --color-primary-500: #2563EB;
+ --color-primary-600: #2563EB;
+ --color-primary-700: #1D4ED8;
+ --color-primary-900: #1E3A8A;
+
+ /* Secondary */
+ --color-secondary-500: #3B82F6;
+ --color-secondary-600: #2563EB;
+ --color-secondary-700: #1D4ED8;
+
+ /* Accent - CTA Orange */
+ --color-accent-500: #F97316;
+ --color-accent-600: #EA580C;
+ --color-accent-700: #C2410C;
+
+ /* Neutral - Slate */
+ --color-neutral-50: #F8FAFC;
+ --color-neutral-100: #F1F5F9;
+ --color-neutral-200: #E2E8F0;
+ --color-neutral-500: #64748B;
+ --color-neutral-600: #475569;
+ --color-neutral-700: #334155;
+ --color-neutral-800: #1E293B;
+ --color-neutral-900: #0F172A;
+
+ /* Semantic Colors */
+ --color-success-500: #22C55E;
+ --color-success-600: #16A34A;
+ --color-success-700: #15803D;
+
+ --color-warning-500: #EAB308;
+ --color-warning-600: #CA8A04;
+ --color-warning-700: #A16207;
+
+ --color-error-500: #EF4444;
+ --color-error-600: #DC2626;
+ --color-error-700: #B91C1C;
+
+ /* -------------------- Typography -------------------- */
+
+ --font-family-heading: 'Inter', system-ui, sans-serif;
+ --font-family-body: 'Inter', system-ui, sans-serif;
+ --font-family-mono: 'JetBrains Mono', 'Fira Code', monospace;
+
+ --font-size-xs: 0.75rem;
+ /* 12px */
+ --font-size-sm: 0.875rem;
+ /* 14px */
+ --font-size-base: 1rem;
+ /* 16px */
+ --font-size-lg: 1.25rem;
+ /* 20px */
+ --font-size-xl: 1.5rem;
+ /* 24px */
+ --font-size-2xl: 2rem;
+ /* 32px */
+ --font-size-3xl: 2.5rem;
+ /* 40px */
+ --font-size-4xl: 3rem;
+ /* 48px */
+
+ --font-weight-normal: 400;
+ --font-weight-medium: 500;
+ --font-weight-semibold: 600;
+ --font-weight-bold: 700;
+
+ --line-height-tight: 1.2;
+ --line-height-snug: 1.3;
+ --line-height-normal: 1.5;
+ --line-height-relaxed: 1.6;
+
+ /* -------------------- Spacing -------------------- */
+
+ --space-0: 0;
+ --space-1: 0.25rem;
+ /* 4px */
+ --space-2: 0.5rem;
+ /* 8px */
+ --space-3: 0.75rem;
+ /* 12px */
+ --space-4: 1rem;
+ /* 16px */
+ --space-6: 1.5rem;
+ /* 24px */
+ --space-8: 2rem;
+ /* 32px */
+ --space-10: 2.5rem;
+ /* 40px */
+ --space-12: 3rem;
+ /* 48px */
+ --space-16: 4rem;
+ /* 64px */
+
+ /* -------------------- Border Radius -------------------- */
+
+ --radius-none: 0;
+ --radius-sm: 0.25rem;
+ /* 4px */
+ --radius-md: 0.5rem;
+ /* 8px */
+ --radius-lg: 1rem;
+ /* 16px */
+ --radius-xl: 1.5rem;
+ /* 24px */
+ --radius-full: 9999px;
+
+ /* -------------------- Shadows -------------------- */
+
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1);
+
+ /* -------------------- Animation -------------------- */
+
+ --duration-fast: 150ms;
+ --duration-normal: 200ms;
+ --duration-slow: 300ms;
+
+ --easing-default: cubic-bezier(0.4, 0, 0.2, 1);
+ --easing-in: cubic-bezier(0.4, 0, 1, 1);
+ --easing-out: cubic-bezier(0, 0, 0.2, 1);
+ --easing-in-out: cubic-bezier(0.4, 0, 0.2, 1);
+
+ /* -------------------- Breakpoints (for reference) -------------------- */
+ /* Use @media queries with these values */
+ --breakpoint-sm: 320px;
+ --breakpoint-md: 768px;
+ --breakpoint-lg: 1024px;
+ --breakpoint-xl: 1440px;
+ --breakpoint-2xl: 1536px;
+
+ /* -------------------- Layout -------------------- */
+
+ --max-width: 1280px;
+ --sidebar-width: 240px;
+ --card-padding: var(--space-4);
+ --column-gap: var(--space-4);
+}
+
+/* ============================================
+ Semantic Aliases (for convenience)
+ ============================================ */
+
+:root {
+ /* Background */
+ --bg-primary: var(--color-neutral-50);
+ --bg-secondary: var(--color-neutral-100);
+ --bg-card: white;
+ --bg-overlay: rgba(0, 0, 0, 0.5);
+
+ /* Text */
+ --text-primary: var(--color-neutral-800);
+ --text-secondary: var(--color-neutral-600);
+ --text-muted: var(--color-neutral-500);
+ --text-inverse: white;
+
+ /* Border */
+ --border-color: var(--color-neutral-200);
+ --border-hover: var(--color-neutral-500);
+
+ /* Focus */
+ --focus-ring-color: var(--color-primary-500);
+ --focus-ring-width: 2px;
+ --focus-ring-offset: 2px;
+}
+
+/* ============================================
+ Dark Mode Support (optional)
+ ============================================ */
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --bg-primary: var(--color-neutral-900);
+ --bg-secondary: var(--color-neutral-800);
+ --bg-card: var(--color-neutral-800);
+
+ --text-primary: var(--color-neutral-50);
+ --text-secondary: var(--color-neutral-200);
+ --text-muted: var(--color-neutral-500);
+
+ --border-color: var(--color-neutral-700);
+ --border-hover: var(--color-neutral-500);
+ }
+}
+
+/* ============================================
+ Reduced Motion Support
+ ============================================ */
+
+@media (prefers-reduced-motion: reduce) {
+ :root {
+ --duration-fast: 0ms;
+ --duration-normal: 0ms;
+ --duration-slow: 0ms;
+ }
+}
\ No newline at end of file
diff --git a/test-samples/sample-a/ux-design-specification.md b/test-samples/sample-a/ux-design-specification.md
new file mode 100644
index 00000000..d55db90b
--- /dev/null
+++ b/test-samples/sample-a/ux-design-specification.md
@@ -0,0 +1,759 @@
+---
+stepsCompleted: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
+inputDocuments: ['test-samples/sample-a/PRD-AquaFlow-V1.0.md']
+workflowType: 'ux-design'
+lastStep: 14
+status: 'complete'
+project_name: 'AquaFlow SaaS 專案管理協作平台'
+user_name: '東杰'
+date: '2025-12-25'
+---
+
+# UX Design Specification: AquaFlow SaaS 專案管理協作平台
+
+**Author:** 東杰
+**Date:** 2025年12月25日
+**Version:** 1.0
+
+---
+
+## 產品背景摘要
+
+**產品名稱:** AquaFlow
+**產品類型:** 雲端 SaaS 專案管理協作平台
+**目標受眾:** 中小型企業團隊領導者、專案經理、跨職能團隊成員
+
+### 解決的核心問題
+1. 現有工具太複雜或太輕量,團隊需要平衡清晰度、速度和適當結構的產品
+2. 任務狀態追蹤困難
+3. 新手上手時間過長
+
+### 核心功能模組
+- 專案管理(建立和管理多個專案)
+- 任務看板(看板拖曳、快速新增)
+- 任務詳情(指派、截止日期、優先級、評論)
+- 搜尋與篩選
+- 通知系統(應用內 + Email)
+
+### 設計風格方向
+- 關鍵字:trust、efficiency、clarity、professional
+- 風格:Modern Professional SaaS
+
+---
+
+## Executive Summary
+
+### Project Vision
+
+AquaFlow 是專為中小型企業團隊打造的雲端專案管理協作平台。我們的目標是提供比 Jira 更輕量、更直覺的體驗,同時保持專業團隊所需的核心功能。
+
+**核心價值主張:**
+- 直覺的拖曳看板,讓任務管理變得簡單
+- 清晰的團隊進度可見度,一眼掌握全局
+- 快速上手,5分鐘即可開始使用
+- 合理的價格,不需要企業級預算
+
+### Target Users
+
+**主要使用者:**
+- 團隊領導者與專案經理(有 Jira 經驗)
+- 跨職能團隊成員
+- 營運與行銷團隊
+
+**使用者特徵:**
+- 技術熟練度:中高(有專案管理與 Jira 經驗)
+- 主要設備:桌面電腦
+- 使用情境:辦公室環境,團隊協作型任務
+
+**核心痛點:**
+- Jira 成本過高
+- 現有工具過於複雜或功能不足
+
+### Key Design Challenges
+
+1. **避免「另一個 Jira」的印象** — 需要更簡潔但不失專業
+2. **傳達價值感** — UI 需要讓用戶感受到「更划算且更好用」
+3. **團隊協作可見度** — 清晰呈現「誰在做什麼、進度如何」
+
+### Design Opportunities
+
+1. **快速上手體驗** — 比 Jira 更低的學習門檻
+2. **視覺化進度** — 一眼看清團隊全局
+3. **極致拖曳體驗** — 讓核心互動成為產品亮點
+4. **輕量專業** — 保持專業外觀,去除不必要複雜度
+
+---
+
+## Core User Experience
+
+### Defining Experience
+
+**核心互動:** 新增任務 + 拖曳任務狀態
+
+這兩個動作是 AquaFlow 的靈魂。用戶每天會執行這些操作數十次,必須做到:
+- **新增任務**:10 秒內完成,只需輸入標題
+- **拖曳任務**:絲滑流暢,即時視覺回饋
+
+**差異化策略(vs Jira):**
+
+| 面向 | Jira 痛點 | AquaFlow 解法 |
+|------|-----------|---------------|
+| 新增任務 | 要填很多欄位 | 「標題即任務」— 只需標題,其他選填 |
+| 拖曳體驗 | 有時卡頓 | Spring 動畫 + 樂觀更新 |
+| 進度可見度 | 要看報表 | 欄位計數器 + 進度環 |
+| 設定複雜度 | 設定太多 | 智慧默認,開箱即用 |
+
+### Platform Strategy
+
+| 面向 | 決策 |
+|------|------|
+| **主要平台** | 響應式 Web App |
+| **互動方式** | 滑鼠/鍵盤為主 |
+| **離線功能** | V1 暫不支援(辦公室使用為主) |
+| **瀏覽器支援** | Chrome, Firefox, Safari, Edge(最新兩版) |
+
+### Effortless Interactions
+
+1. **極速新增** — 浮動按鈕 + `Cmd+K` 快捷鍵
+2. **絲滑拖曳** — Spring 動畫 + 樂觀更新
+3. **一眼進度** — 欄位計數器 + 進度環
+4. **快速搜尋** — `Cmd+K` 全域搜尋
+
+### Critical Success Moments
+
+| 時刻 | 用戶情感 | 設計策略 |
+|------|----------|----------|
+| **第一次拖曳到「完成」** | 「哇,好順!」 | 微慶祝動畫 |
+| **看到團隊進度** | 「終於不用問了」 | 進度環 + 計數器 |
+| **10秒內新增任務** | 「比 Jira 簡單」 | 快速新增流程 |
+| **找到上週任務** | 「搜尋好用!」 | `Cmd+K` 全域搜尋 |
+
+### Experience Principles
+
+1. **🚀 速度優先** — 任何操作 200ms 內有視覺回應
+2. **👁️ 資訊清晰** — 一眼看到:誰負責、何時截止、什麼狀態
+3. **🎯 專注當下** — 減少干擾,專注於當前任務
+4. **🔄 流暢過渡** — 所有狀態變化都有自然動畫
+5. **⌨️ 效率捷徑** — 為專業用戶提供鍵盤快捷鍵
+
+---
+
+## Desired Emotional Response
+
+### Primary Emotional Goals
+
+| 情感 | 觸發時機 | 設計策略 |
+|------|----------|----------|
+| **掌控感** | 看到團隊進度 | 進度環 + 清晰的狀態欄 |
+| **效率感** | 快速完成操作 | 200ms 內有回應 |
+| **輕鬆感** | 首次使用 | 智慧默認,不需要設定 |
+| **成就感** | 完成任務 | 微慶祝動畫 |
+
+### Emotional Journey Mapping
+
+| 階段 | 情感 | 設計策略 |
+|------|------|----------|
+| **發現** | 好奇 + 期待 | 清晰的價值主張,5秒內吸引注意 |
+| **註冊** | 信任 + 輕鬆 | 最少步驟,支援社群登入 |
+| **首次使用** | 自信 + 引導 | 引導式 onboarding,不壓迫 |
+| **日常使用** | 高效 + 滿足 | 流暢操作,即時回饋 |
+| **完成任務** | 成就感 | 微慶祝動畫,進度視覺化 |
+| **出錯時** | 被理解 + 有方向 | 友善錯誤訊息,明確解決方案 |
+
+### Micro-Emotions
+
+**強化的正面情感:**
+- ✅ **自信** vs ❌ 困惑 → 清晰的視覺層級
+- ✅ **信任** vs ❌ 懷疑 → 一致的互動模式
+- ✅ **成就感** vs ❌ 挫折 → 漸進式任務分解
+- ✅ **歸屬感** vs ❌ 孤立 → 團隊活動可見性
+
+**避免的負面情感:**
+- 😰 焦慮 — 避免資訊過載(vs Jira 太多欄位)
+- 😤 挫折 — 避免複雜操作流程
+- 😵 困惑 — 避免不一致的 UI 元素
+- 😒 厭煩 — 避免過多確認對話框
+
+### Emotional Design Principles
+
+1. **🏆 慶祝進步** — 每個完成的任務都值得微小的慶祝動畫
+2. **🤝 溫暖的錯誤處理** — 錯誤訊息像朋友在幫忙,不像機器在責備
+3. **✨ 驚喜時刻** — 隱藏的彩蛋讓日常使用不無聊
+4. **🧘 減少認知負擔** — 默認值聰明,讓用戶少做決定
+5. **👋 個人化觸點** — 使用者名字、偏好設定優先
+
+---
+
+## UX Pattern Analysis & Inspiration
+
+### Inspiring Products Analysis
+
+| 產品 | 優點 | 可借鑒的 UX 模式 |
+|------|------|-----------------|
+| **Trello** | 極致直覺的拖曳體驗 | 看板 + 卡片設計、封面圖片、標籤系統 |
+| **Asana** | 多視圖無縫切換 | 列表/看板/時間軸視圖、右側滑出面板 |
+| **Notion** | 鍵盤導向操作 | `Cmd+K` 萬能搜尋、斜線指令 |
+| **Linear** | 極簡專業風格 | 清晰資訊層級、快捷鍵系統 |
+
+### Transferable UX Patterns
+
+**導航模式:**
+- 側邊欄工作區切換(像 Slack 一樣快速切換)
+- 麵包屑導航(工作區 > 專案 > 任務的清晰路徑)
+- 全域搜尋 `Cmd+K`(快速找到任何東西)
+
+**互動模式:**
+- Trello 風格的流暢拖曳
+- 右側滑出詳情面板(不離開上下文)
+- @提及自動完成(自然的協作語法)
+
+### Anti-Patterns to Avoid
+
+| 反模式 | 來源 | 為什麼避免 |
+|--------|------|-----------|
+| 過度功能 | Jira | 中小企業不需要複雜設定 |
+| 資訊過載 | Monday.com | 太多欄位造成認知負擔 |
+| 強制教學 | 某些企業軟體 | 阻斷新手的探索慾望 |
+| 深層導航 | 舊版 Basecamp | 超過 3 層深度造成迷失 |
+
+### Design Inspiration Strategy
+
+**採用 (Adopt):**
+- ✅ Trello 的拖曳體驗 → 核心看板互動
+- ✅ Asana 的視圖切換 → 列表/看板無縫切換
+- ✅ Notion 的 Cmd+K → 全域快捷搜尋
+
+**改編 (Adapt):**
+- 🔄 Asana 的慶祝動畫 → 更輕量的完成微動畫
+- 🔄 Linear 的鍵盤導向 → 簡化為常用快捷鍵
+
+**避免 (Avoid):**
+- ❌ 任何需要培訓的功能 → 自助可發現
+- ❌ 深層選單 → 最多 3 層
+
+---
+
+## Design System Foundation
+
+### Design System Choice
+
+**選定方案:** Chakra UI v2 + React
+
+**技術組合:**
+- UI 框架:Chakra UI v2
+- 圖標庫:Lucide Icons
+- 拖曳:@dnd-kit/core
+- 動畫:Framer Motion(內建)
+- 表單:React Hook Form + Chakra
+
+### Rationale for Selection
+
+| 考量因素 | Chakra UI 優勢 |
+|----------|----------------|
+| **React 整合** | 原生支援,符合 PRD 技術栈 |
+| **可主題化** | 輕鬆建立 AquaFlow 品牌識別 |
+| **無障礙** | 內建 WCAG 標準支援 |
+| **開發體驗** | 清晰文件、TypeScript 支援 |
+| **拖曳支援** | 易於整合 @dnd-kit |
+
+### Implementation Approach
+
+1. **Phase 1: 基礎設定**
+ - 安裝 Chakra UI 和依賴套件
+ - 配置主題 (theme.ts)
+ - 建立設計令牌 (Design Tokens)
+
+2. **Phase 2: 基礎組件**
+ - Button, Input, Card 等基礎組件
+ - 導航組件 (Sidebar, Navbar)
+ - 版面配置組件
+
+3. **Phase 3: 業務組件**
+ - TaskCard (任務卡片)
+ - KanbanColumn (看板欄)
+ - ProjectList (專案列表)
+
+### Customization Strategy
+
+**設計令牌 (Design Tokens):**
+- 品牌色:待 Step 8 定義
+- 字型:Inter (Google Fonts)
+- 間距:4px 基礎單位
+- 圓角:sm=4px, md=8px, lg=16px
+- 陰影:使用 Chakra 默認 shadow tokens
+
+---
+
+## Visual Design Foundation
+
+### Color System
+
+**色彩來源:** UI/UX Pro Max 知識庫 (SaaS Modern Professional)
+
+| 角色 | Hex 色碼 | 用途 |
+|------|----------|------|
+| **Primary** | `#2563EB` | 主按鈕、連結、品牌識別 |
+| **Secondary** | `#3B82F6` | hover 狀態、次要強調 |
+| **CTA** | `#F97316` | 行動呼籲按鈕 |
+| **Background** | `#F8FAFC` | 頁面背景 |
+| **Text** | `#1E293B` | 主要文字 |
+| **Border** | `#E2E8F0` | 邊框、分隔線 |
+
+**語意色彩:**
+- Success: `#22C55E`
+- Warning: `#EAB308`
+- Error: `#EF4444`
+- Info: `#3B82F6`
+
+**設計理念:** Trust blue + accent contrast(信任藍 + 對比強調色)
+
+### Typography System
+
+**字型來源:** UI/UX Pro Max 知識庫 (Minimal Swiss)
+
+**主要字型:** Inter (Google Fonts)
+```css
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
+```
+
+**字級階層:**
+
+| 元素 | 大小 | 粗細 | 行高 |
+|------|------|------|------|
+| H1 | 32px | 700 | 1.2 |
+| H2 | 24px | 600 | 1.3 |
+| H3 | 20px | 600 | 1.4 |
+| Body | 16px | 400 | 1.5 |
+| Small | 14px | 400 | 1.5 |
+| Caption | 12px | 400 | 1.4 |
+
+### Spacing & Layout Foundation
+
+**基礎單位:** 4px
+
+**間距系統 (Chakra UI):**
+```
+space.1 = 4px
+space.2 = 8px ← 最小按鈕間距
+space.3 = 12px
+space.4 = 16px ← 常用內邊距
+space.6 = 24px ← 區塊間距
+space.8 = 32px
+space.10 = 40px
+space.12 = 48px
+```
+
+**版面配置:**
+- 最大寬度:1280px
+- 側邊欄寬度:240px
+- 卡片內邊距:16px
+- 欄位間距:16px
+
+### Accessibility Considerations
+
+- ✅ 色彩對比度符合 WCAG AA 標準(4.5:1)
+- ✅ 主要按鈕使用至少 44x44px 觸控區域
+- ✅ 相鄰按鈕間距至少 8px
+- ✅ Inter 字型具備優秀的可讀性
+- ✅ 支援鍵盤導航(Tab/Shift+Tab)
+
+---
+
+## Design Direction Decision
+
+### Design Directions Explored
+
+由於設計決策已在前面步驟中明確定義,跳過多變體 mockups 生成。
+
+**已確定的設計元素:**
+- 設計系統:Chakra UI v2
+- 配色:Trust Blue (#2563EB) + Orange CTA (#F97316)
+- 字型:Inter
+- 風格:Modern Professional SaaS
+
+### Chosen Direction
+
+**選定方向:Modern Professional SaaS**
+
+| 面向 | 設計決策 |
+|------|----------|
+| **布局** | 側邊欄導航 + 主內容區看板 |
+| **視覺密度** | 中等密度,留白適當 |
+| **互動風格** | 輕量動畫、Spring 拖曳 |
+| **導航模式** | 左側邊欄 + 頂部麵包屑 |
+| **卡片風格** | 白底圓角 + 輕陰影 |
+
+### Design Rationale
+
+1. **側邊欄導航** — 符合 SaaS 產品標準,用戶有 Jira 經驗
+2. **中等密度** — 平衡資訊呈現和清晰度(vs Jira 的高密度)
+3. **輕量動畫** — 支持「速度優先」原則,不影響效能
+4. **白底圓角卡片** — 現代專業感,符合 Trust + Efficiency 關鍵字
+
+### Implementation Approach
+
+1. **Chakra UI Theme** — 配置自訂顏色和字型
+2. **Layout Components** — Sidebar + Main + SlidePanel
+3. **Card Components** — TaskCard、ProjectCard
+4. **Animation Library** — Framer Motion for Spring animations
+
+---
+
+## User Journey Flows
+
+### Journey 1: 新增任務
+
+**目標:** 10 秒內建立新任務
+
+```mermaid
+flowchart TD
+ A[點擊 + 按鈕 / Cmd+K] --> B[輸入任務標題]
+ B --> C{按 Enter?}
+ C -->|是| D[任務建立成功 ✓]
+ C -->|否| E[展開詳情面板]
+ E --> F[填寫其他欄位]
+ F --> D
+ D --> G[微慶祝動畫]
+```
+
+**關鍵設計決策:**
+- 只需標題即可建立任務
+- 其他欄位皆為選填
+- 支援快捷鍵 `Cmd+K`
+
+### Journey 2: 拖曳任務狀態
+
+**目標:** 絲滑流暢的狀態切換
+
+```mermaid
+flowchart TD
+ A[抓取任務卡片] --> B[拖曳中 - 陰影提升]
+ B --> C[放置到目標欄]
+ C --> D{樂觀更新}
+ D -->|成功| E[Spring 動畫完成]
+ D -->|失敗| F[回滾位置 + 錯誤提示]
+ E --> G[欄位計數器更新]
+```
+
+**關鍵設計決策:**
+- 樂觀更新(先顯示成功,再同步後端)
+- Spring 動畫增加流暢感
+- 失敗時優雅回滾
+
+### Journey 3: 全域搜尋
+
+**目標:** 快速找到任何任務
+
+```mermaid
+flowchart TD
+ A[按 Cmd+K] --> B[搜尋框浮現]
+ B --> C[輸入關鍵字]
+ C --> D[即時顯示結果]
+ D --> E{選擇結果}
+ E -->|Enter/Click| F[跳轉到任務]
+ E -->|Esc| G[關閉搜尋]
+```
+
+**關鍵設計決策:**
+- 全域快捷鍵 `Cmd+K`
+- 即時搜尋結果
+- 支援鍵盤導航
+
+### Journey Patterns
+
+**通用模式:**
+1. **快捷鍵入口** — 所有常用功能支援 keyboard shortcut
+2. **即時回饋** — 200ms 內有視覺回應
+3. **樂觀更新** — 先顯示成功,後台同步
+4. **優雅錯誤處理** — 自動回滾 + 友善訊息
+
+### Flow Optimization Principles
+
+| 原則 | 說明 |
+|------|------|
+| **10 秒法則** | 核心操作必須在 10 秒內完成 |
+| **200ms 回應** | 任何操作有即時視覺回饋 |
+| **一鍵可及** | 最常用功能一次點擊/按鍵即可 |
+| **漸進揭露** | 進階功能隱藏,需要時才顯示 |
+
+---
+
+## Component Strategy
+
+### Design System Components (Chakra UI v2)
+
+**基礎組件(直接使用):**
+- Button, IconButton, ButtonGroup
+- Input, Select, Checkbox, Radio, Switch
+- Card, Box, Flex, Grid, Stack
+- Modal, Drawer, Popover, Tooltip
+- Alert, Toast, Progress, Spinner
+- Tabs, Breadcrumb, Menu
+
+### Custom Components
+
+#### 1. TaskCard (任務卡片)
+
+| 項目 | 規格 |
+|------|------|
+| **用途** | 看板上的可拖曳任務卡片 |
+| **內容** | 標題、標籤、負責人頭像、截止日期、優先級 |
+| **狀態** | default, hover, dragging, selected, loading |
+
+**KB 指南參考:**
+- #28 Focus States → `focus:ring-2 focus:ring-blue-500`
+- #29 Hover States → `hover:bg-gray-50 cursor-pointer`
+- #30 Active States → `active:scale-[0.99]`
+- #84 Truncation → 標題超長用 `line-clamp-2`
+- #40 ARIA Labels → 拖曳需 `aria-grabbed` 屬性
+
+#### 2. KanbanColumn (看板欄)
+
+| 項目 | 規格 |
+|------|------|
+| **用途** | 任務狀態欄(待辦/進行中/完成) |
+| **內容** | 欄標題、任務計數器、進度環、新增按鈕 |
+| **狀態** | default, drop-target-active, empty |
+
+**KB 指南參考:**
+- #80 Empty States → 空欄顯示「尚無任務,拖曳或點擊新增」
+- #10 Loading States → 載入中顯示 Skeleton
+
+#### 3. CommandPalette (快捷指令面板)
+
+| 項目 | 規格 |
+|------|------|
+| **用途** | Cmd+K 全域搜尋/快捷指令 |
+| **內容** | 搜尋框、分類結果、最近項目 |
+| **狀態** | open, searching, results, empty |
+
+**KB 指南參考:**
+- #41 Keyboard Navigation → 完整鍵盤支援(↑↓ Enter Esc)
+- #28 Focus States → 清晰的選項焦點指示
+- #89 Search Autocomplete → 即時顯示搜尋建議
+
+#### 4. ProgressRing (進度環)
+
+| 項目 | 規格 |
+|------|------|
+| **用途** | 視覺化任務完成進度 |
+| **內容** | 百分比數字、動畫環 |
+| **尺寸** | sm(24px), md(32px), lg(48px) |
+
+**KB 指南參考:**
+- #8 Duration Timing → 動畫 200ms
+- #9 Reduced Motion → 尊重 `prefers-reduced-motion`
+
+### Component Implementation Strategy
+
+**通用狀態規範(基於 KB 指南):**
+
+```css
+/* 所有互動組件必須實作 */
+.interactive {
+ /* #28 Focus States */
+ focus:ring-2 focus:ring-blue-500 focus:ring-offset-2
+
+ /* #29 Hover States */
+ hover:bg-gray-50 transition-colors
+
+ /* #30 Active States */
+ active:scale-[0.98]
+
+ /* #22 Touch Target */
+ min-h-[44px] min-w-[44px]
+}
+
+/* #8 Animation Timing */
+transition: all 200ms ease-out;
+
+/* #9 Reduced Motion */
+@media (prefers-reduced-motion: reduce) {
+ transition: none;
+}
+```
+
+### Implementation Roadmap
+
+| 階段 | 組件 | 優先級 | 依賴 |
+|------|------|--------|------|
+| **Phase 1** | TaskCard | 🔴 P0 | @dnd-kit |
+| **Phase 1** | KanbanColumn | 🔴 P0 | TaskCard |
+| **Phase 2** | CommandPalette | 🟡 P1 | - |
+| **Phase 2** | ProgressRing | 🟡 P1 | - |
+| **Phase 3** | ActivityFeed | 🟢 P2 | - |
+| **Phase 3** | UserAvatar | 🟢 P2 | - |
+
+---
+
+## UX Consistency Patterns
+
+**KB 指南參考:** #61 Submit Feedback, #4 Back Button, #43 Form Labels
+
+### Button Hierarchy
+
+| 層級 | 用途 | 樣式 | 範例 |
+|------|------|------|------|
+| **Primary** | 主要行動 | 填充藍色 `#2563EB` + 白字 | 儲存、建立、提交 |
+| **Secondary** | 次要行動 | 邊框藍色 + 藍字 | 取消、返回 |
+| **Ghost** | 低調行動 | 透明背景 + 灰字 | 更多選項、展開 |
+| **Danger** | 破壞性行動 | 紅色 `#EF4444` | 刪除(需確認對話框) |
+
+**按鈕狀態:**
+- Default → Hover (`brightness(1.1)`) → Active (`scale(0.98)`) → Disabled (`opacity-50`)
+
+### Feedback Patterns
+
+| 類型 | 觸發 | 呈現 | 持續時間 |
+|------|------|------|----------|
+| **Success** | 操作完成 | Toast 右上角 ✓ | 3 秒自動消失 |
+| **Error** | 操作失敗 | 紅色 Alert + 說明 | 用戶關閉 |
+| **Warning** | 需要注意 | 黃色 Alert | 用戶確認 |
+| **Info** | 提示資訊 | 藍色 Toast | 5 秒自動消失 |
+| **Loading** | 等待中 | Spinner 或 Skeleton | 完成後消失 |
+
+**回饋規則:**
+- 小於 300ms 的操作:無需顯示 loading
+- 300ms-1s:顯示 spinner
+- 大於 1s:顯示 skeleton 或進度條
+
+### Form Patterns
+
+**輸入欄位規範:**
+- ✅ 每個 input 都有 `