Refactor layout and style extraction workflows for multi-selection capabilities

- Updated `layout-extract` command to support user multi-selection of layout concepts, allowing for multiple layout templates to be generated based on user preferences.
- Revised argument hints and output structures to reflect changes in selection handling and output file formats.
- Enhanced user interaction by enabling multi-select options in both layout and style extraction phases.
- Streamlined the generation of layout templates and design systems to accommodate multiple selected variants, improving flexibility and user experience.
- Adjusted validation and output verification processes to ensure consistency with new multi-selection features.
This commit is contained in:
catlog22
2025-11-08 23:23:06 +08:00
parent 7269f20f57
commit d213885f52
6 changed files with 392 additions and 418 deletions

View File

@@ -70,31 +70,24 @@ IF exists({base_path}/.intermediates/style-analysis/design-space-analysis.json):
**Output**: `design_tokens_valid`, `design_space_analysis` **Output**: `design_tokens_valid`, `design_space_analysis`
### Step 3: Gather Layout Inspiration (Reuse or Create) ### Step 3: Gather Layout Inspiration (Direct MCP Search)
```bash ```bash
# Check if layout inspirations already exist from layout-extract phase # Gather layout inspiration via MCP for each target
inspiration_source = "{base_path}/.intermediates/layout-analysis/inspirations" layout_inspiration_map = {}
FOR target IN target_list: FOR target IN target_list:
# Priority 1: Reuse existing inspiration from layout-extract
IF exists({inspiration_source}/{target}-layout-ideas.txt):
# Reuse existing inspiration (no action needed)
REPORT: "Using existing layout inspiration for {target}"
ELSE:
# Priority 2: Generate new inspiration via MCP
bash(mkdir -p {inspiration_source})
search_query = "{target} {target_type} layout patterns variations" search_query = "{target} {target_type} layout patterns variations"
mcp__exa__web_search_exa(query=search_query, numResults=5) search_results = mcp__exa__web_search_exa(query=search_query, numResults=5)
# Extract context from prompt for this target # Extract context from prompt for this target
target_requirements = extract_relevant_context_from_prompt(prompt_text, target) target_requirements = extract_relevant_context_from_prompt(prompt_text, target)
# Write inspiration file to centralized location # Store inspiration in memory (no file write needed)
Write({inspiration_source}/{target}-layout-ideas.txt, inspiration_content) layout_inspiration_map[target] = format_inspiration_from_search(search_results, target_requirements)
REPORT: "Created new layout inspiration for {target}" REPORT: "Gathered layout inspiration for {target}"
``` ```
**Output**: `T` inspiration text files (reused or created in `.intermediates/layout-analysis/inspirations/`) **Output**: `layout_inspiration_map` (in-memory, passed to agents)
## Phase 2: Target-Style-Centric Batch Generation (Agent) ## Phase 2: Target-Style-Centric Batch Generation (Agent)
@@ -132,7 +125,7 @@ Task(ui-design-agent): `
${design_attributes ? "DESIGN_ATTRIBUTES: " + JSON.stringify(design_attributes) : ""} ${design_attributes ? "DESIGN_ATTRIBUTES: " + JSON.stringify(design_attributes) : ""}
## Reference ## Reference
- Layout inspiration: Read("{base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt") - Layout inspiration: {layout_inspiration_map[target]}
- Design tokens: Read("{base_path}/style-extraction/style-{style_id}/design-tokens.json") - Design tokens: Read("{base_path}/style-extraction/style-{style_id}/design-tokens.json")
Parse ALL token values including: Parse ALL token values including:
* colors, typography (with combinations), spacing, opacity * colors, typography (with combinations), spacing, opacity
@@ -315,8 +308,6 @@ bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes")
{base_path}/ {base_path}/
├── .intermediates/ ├── .intermediates/
│ └── layout-analysis/ │ └── layout-analysis/
│ └── inspirations/
│ └── {target}-layout-ideas.txt # Layout inspiration (reused or created)
├── prototypes/ ├── prototypes/
│ ├── {target}-style-{s}-layout-{l}.html # Final prototypes │ ├── {target}-style-{s}-layout-{l}.html # Final prototypes
│ ├── {target}-style-{s}-layout-{l}.css │ ├── {target}-style-{s}-layout-{l}.css

View File

@@ -207,7 +207,8 @@ run_id = "run-$(date +%Y%m%d)-$RANDOM"
relative_base_path = --session ? ".workflow/WFS-{session}/design-${run_id}" : ".workflow/.design/design-${run_id}" relative_base_path = --session ? ".workflow/WFS-{session}/design-${run_id}" : ".workflow/.design/design-${run_id}"
# Create directory and convert to absolute path # Create directory and convert to absolute path
Bash(mkdir -p "${relative_base_path}/{style-extraction,prototypes}") Bash(mkdir -p "${relative_base_path}/style-extraction")
Bash(mkdir -p "${relative_base_path}/prototypes")
base_path=$(cd "${relative_base_path}" && pwd) base_path=$(cd "${relative_base_path}" && pwd)
Write({base_path}/.run-metadata.json): { Write({base_path}/.run-metadata.json): {
@@ -315,7 +316,8 @@ IF design_source IN ["code_only", "hybrid"]:
# Check file existence and assess completeness # Check file existence and assess completeness
style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json") style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json")
animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json") animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json")
layout_exists = exists("{base_path}/layout-extraction/layout-templates.json") layout_count = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | wc -l)
layout_exists = (layout_count > 0)
style_complete = false style_complete = false
animation_complete = false animation_complete = false
@@ -351,14 +353,16 @@ IF design_source IN ["code_only", "hybrid"]:
# Layout completeness check # Layout completeness check
IF layout_exists: IF layout_exists:
layouts = Read("{base_path}/layout-extraction/layout-templates.json") # Read first layout file to verify structure
first_layout = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | head -1)
layout_data = Read(first_layout)
layout_complete = ( layout_complete = (
layouts.layout_templates?.length >= 3 && layout_count >= 1 &&
layouts.extraction_metadata?.layout_system?.type && layout_data.template?.dom_structure &&
layouts.extraction_metadata?.responsive?.breakpoints layout_data.template?.css_layout_rules
) )
IF NOT layout_complete AND layouts.extraction_metadata?.completeness?.missing_items: IF NOT layout_complete:
missing_categories.extend(layouts.extraction_metadata.completeness.missing_items) missing_categories.push("complete layout structure")
ELSE: ELSE:
missing_categories.push("layout templates") missing_categories.push("layout templates")
@@ -386,7 +390,7 @@ IF design_source == "visual_only" OR needs_visual_supplement:
command = "/workflow:ui-design:style-extract --base-path \"{base_path}\" " + command = "/workflow:ui-design:style-extract --base-path \"{base_path}\" " +
(--images ? "--images \"{images}\" " : "") + (--images ? "--images \"{images}\" " : "") +
(--prompt ? "--prompt \"{prompt}\" " : "") + (--prompt ? "--prompt \"{prompt}\" " : "") +
"--mode explore --variants {style_variants}" "--variants {style_variants}"
SlashCommand(command) SlashCommand(command)
ELSE: ELSE:
REPORT: "✅ Phase 1: Style (Using Code Import)" REPORT: "✅ Phase 1: Style (Using Code Import)"
@@ -415,7 +419,7 @@ IF (design_source == "visual_only" OR needs_visual_supplement) OR (NOT layout_co
command = "/workflow:ui-design:layout-extract --base-path \"{base_path}\" " + command = "/workflow:ui-design:layout-extract --base-path \"{base_path}\" " +
(--images ? "--images \"{images}\" " : "") + (--images ? "--images \"{images}\" " : "") +
(--prompt ? "--prompt \"{prompt}\" " : "") + (--prompt ? "--prompt \"{prompt}\" " : "") +
"--targets \"{targets_string}\" --mode explore --variants {layout_variants} --device-type \"{device_type}\"" "--targets \"{targets_string}\" --variants {layout_variants} --device-type \"{device_type}\""
SlashCommand(command) SlashCommand(command)
ELSE: ELSE:
REPORT: "✅ Phase 2.5: Layout (Using Code Import)" REPORT: "✅ Phase 2.5: Layout (Using Code Import)"
@@ -549,10 +553,11 @@ Architecture: Style-Centric Batch Generation
Run ID: {run_id} | Session: {session_id or "standalone"} Run ID: {run_id} | Session: {session_id or "standalone"}
Type: {icon} {target_type} | Device: {device_type} | Matrix: {s}×{l}×{n} = {total} prototypes Type: {icon} {target_type} | Device: {device_type} | Matrix: {s}×{l}×{n} = {total} prototypes
Phase 1: {s} complete design systems (style-extract) Phase 1: {s} complete design systems (style-extract with multi-select)
Phase 2: {n×l} layout templates (layout-extract explore mode) Phase 2: {n×l} layout templates (layout-extract with multi-select)
- Device: {device_type} layouts - Device: {device_type} layouts
- {n} targets × {l} layout variants = {n×l} structural templates - {n} targets × {l} layout variants = {n×l} structural templates
- User-selected concepts generated in parallel
Phase 3: UI Assembly (generate) Phase 3: UI Assembly (generate)
- Pure assembly: layout templates + design tokens - Pure assembly: layout templates + design tokens
- {s}×{l}×{n} = {total} final prototypes - {s}×{l}×{n} = {total} final prototypes
@@ -562,21 +567,22 @@ Phase 4: Brainstorming artifacts updated
Assembly Process: Assembly Process:
✅ Separation of Concerns: Layout (structure) + Style (tokens) kept separate ✅ Separation of Concerns: Layout (structure) + Style (tokens) kept separate
✅ Layout Extraction: {n×l} reusable structural templates ✅ Layout Extraction: {n×l} reusable structural templates
✅ Multi-Selection Workflow: User selects multiple variants from generated options
✅ Pure Assembly: No design decisions in generate phase ✅ Pure Assembly: No design decisions in generate phase
✅ Device-Optimized: Layouts designed for {device_type} ✅ Device-Optimized: Layouts designed for {device_type}
Design Quality: Design Quality:
✅ Token-Driven Styling: 100% var() usage ✅ Token-Driven Styling: 100% var() usage
✅ Structural Variety: {l} distinct layouts per target ✅ Structural Variety: {l} distinct layouts per target (user-selected)
✅ Style Variety: {s} independent design systems ✅ Style Variety: {s} independent design systems (user-selected)
✅ Device-Optimized: Layouts designed for {device_type} ✅ Device-Optimized: Layouts designed for {device_type}
📂 {base_path}/ 📂 {base_path}/
├── .intermediates/ (Intermediate analysis files) ├── .intermediates/ (Intermediate analysis files)
│ ├── style-analysis/ (computed-styles.json, design-space-analysis.json) │ ├── style-analysis/ (computed-styles.json, design-space-analysis.json)
│ └── layout-analysis/ (dom-structure-*.json, inspirations/*.txt) │ └── layout-analysis/ (analysis-options.json, user-selection.json, dom-structure-*.json)
├── style-extraction/ ({s} complete design systems) ├── style-extraction/ ({s} complete design systems)
├── layout-extraction/ ({n×l} layout templates + layout-space-analysis.json) ├── layout-extraction/ ({n×l} layout template files: layout-{target}-{variant}.json)
├── prototypes/ ({total} assembled prototypes) ├── prototypes/ ({total} assembled prototypes)
└── .run-metadata.json (includes device type) └── .run-metadata.json (includes device type)

View File

@@ -225,8 +225,8 @@ IF design_source == "hybrid":
REPORT: " → Source: {code_base_path}" REPORT: " → Source: {code_base_path}"
REPORT: " → Mode: Hybrid (Web + Code)" REPORT: " → Mode: Hybrid (Web + Code)"
command = "/workflow:ui-design:import-from-code --base-path \"{base_path}\" " + command = "/workflow:ui-design:import-from-code --output-path \"{base_path}\" " +
"--base-path \"{code_base_path}\"" "--source-path \"{code_base_path}\""
TRY: TRY:
SlashCommand(command) SlashCommand(command)
@@ -239,7 +239,8 @@ IF design_source == "hybrid":
# Check file existence and assess completeness # Check file existence and assess completeness
style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json") style_exists = exists("{base_path}/style-extraction/style-1/design-tokens.json")
animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json") animation_exists = exists("{base_path}/animation-extraction/animation-tokens.json")
layout_exists = exists("{base_path}/layout-extraction/layout-templates.json") layout_count = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | wc -l)
layout_exists = (layout_count > 0)
style_complete = false style_complete = false
animation_complete = false animation_complete = false
@@ -275,14 +276,16 @@ IF design_source == "hybrid":
# Layout completeness check # Layout completeness check
IF layout_exists: IF layout_exists:
layouts = Read("{base_path}/layout-extraction/layout-templates.json") # Read first layout file to verify structure
first_layout = bash(ls {base_path}/layout-extraction/layout-*.json 2>/dev/null | head -1)
layout_data = Read(first_layout)
layout_complete = ( layout_complete = (
layouts.layout_templates?.length >= 3 && layout_count >= 1 &&
layouts.extraction_metadata?.layout_system?.type && layout_data.template?.dom_structure &&
layouts.extraction_metadata?.responsive?.breakpoints layout_data.template?.css_layout_rules
) )
IF NOT layout_complete AND layouts.extraction_metadata?.completeness?.missing_items: IF NOT layout_complete:
missing_categories.extend(layouts.extraction_metadata.completeness.missing_items) missing_categories.push("complete layout structure")
ELSE: ELSE:
missing_categories.push("layout templates") missing_categories.push("layout templates")
@@ -405,7 +408,7 @@ ELSE:
extraction_prompt = f"Extract visual style tokens from '{primary_target}' with consistency across all pages." extraction_prompt = f"Extract visual style tokens from '{primary_target}' with consistency across all pages."
url_map_for_extract = ",".join([f"{name}:{url}" for name, url in url_map.items()]) url_map_for_extract = ",".join([f"{name}:{url}" for name, url in url_map.items()])
extract_command = f"/workflow:ui-design:style-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_extract}\" --prompt \"{extraction_prompt}\" --mode imitate" extract_command = f"/workflow:ui-design:style-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_extract}\" --prompt \"{extraction_prompt}\" --variants 1"
SlashCommand(extract_command) SlashCommand(extract_command)
TodoWrite(mark_completed: "Extract style", mark_in_progress: "Extract animation") TodoWrite(mark_completed: "Extract style", mark_in_progress: "Extract animation")
@@ -436,7 +439,7 @@ IF skip_layout:
ELSE: ELSE:
REPORT: "🚀 Phase 2.5: Layout Extraction" REPORT: "🚀 Phase 2.5: Layout Extraction"
url_map_for_layout = ",".join([f"{target}:{url}" for target, url in url_map.items()]) url_map_for_layout = ",".join([f"{target}:{url}" for target, url in url_map.items()])
layout_extract_command = f"/workflow:ui-design:layout-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_layout}\" --targets \"{','.join(target_names)}\" --mode imitate" layout_extract_command = f"/workflow:ui-design:layout-extract --base-path \"{base_path}\" --images \"{images_glob}\" --urls \"{url_map_for_layout}\" --targets \"{','.join(target_names)}\" --variants 1"
SlashCommand(layout_extract_command) SlashCommand(layout_extract_command)
TodoWrite(mark_completed: "Extract layout", mark_in_progress: "Assemble UI") TodoWrite(mark_completed: "Extract layout", mark_in_progress: "Assemble UI")
@@ -546,7 +549,7 @@ ELSE:
│ ├── animation-tokens.json │ ├── animation-tokens.json
│ └── animation-guide.md │ └── animation-guide.md
├── layout-extraction/ # Structure templates ├── layout-extraction/ # Structure templates
│ └── layout-templates.json │ └── layout-{target}-1.json # One file per target
└── prototypes/ # {generated_count} HTML/CSS files └── prototypes/ # {generated_count} HTML/CSS files
├── {target1}-style-1-layout-1.html + .css ├── {target1}-style-1-layout-1.html + .css
├── {target2}-style-1-layout-1.html + .css ├── {target2}-style-1-layout-1.html + .css

View File

@@ -1,7 +1,7 @@
--- ---
name: workflow:ui-design:import-from-code name: workflow:ui-design:import-from-code
description: Import design system from code files (CSS/JS/HTML/SCSS) using parallel agent analysis with final synthesis description: Import design system from code files (CSS/JS/HTML/SCSS) using parallel agent analysis with final synthesis
argument-hint: "[--base-path <path>] [--css \"<glob>\"] [--js \"<glob>\"] [--scss \"<glob>\"] [--html \"<glob>\"] [--style-files \"<glob>\"] [--session <id>]" argument-hint: "[--source-path <path>] [--output-path <path>] [--css \"<glob>\"] [--js \"<glob>\"] [--scss \"<glob>\"] [--html \"<glob>\"] [--style-files \"<glob>\"] [--session <id>]"
allowed-tools: Read,Write,Bash,Glob,Grep,Task,TodoWrite allowed-tools: Read,Write,Bash,Glob,Grep,Task,TodoWrite
auto-continue: true auto-continue: true
--- ---
@@ -34,7 +34,8 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using
/workflow:ui-design:import-from-code [FLAGS] /workflow:ui-design:import-from-code [FLAGS]
# Flags # Flags
--base-path <path> Base directory for analysis (default: current directory) --source-path <path> Source code directory to analyze (default: current directory)
--output-path <path> Output directory for extracted design tokens (default: current directory)
--css "<glob>" CSS file glob pattern (e.g., "theme/*.css") --css "<glob>" CSS file glob pattern (e.g., "theme/*.css")
--scss "<glob>" SCSS file glob pattern (e.g., "styles/*.scss") --scss "<glob>" SCSS file glob pattern (e.g., "styles/*.scss")
--js "<glob>" JavaScript file glob pattern (e.g., "theme/*.js") --js "<glob>" JavaScript file glob pattern (e.g., "theme/*.js")
@@ -47,19 +48,19 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using
```bash ```bash
# Basic usage - auto-discover all files # Basic usage - auto-discover all files
/workflow:ui-design:import-from-code --base-path ./ /workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system
# Target specific directories # Target specific directories
/workflow:ui-design:import-from-code --base-path ./src --css "theme/*.css" --js "theme/*.js" /workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --css "theme/*.css" --js "theme/*.js"
# Tailwind config only # Tailwind config only (output to current directory)
/workflow:ui-design:import-from-code --js "tailwind.config.js" /workflow:ui-design:import-from-code --source-path ./ --js "tailwind.config.js"
# CSS framework import # CSS framework import
/workflow:ui-design:import-from-code --css "styles/**/*.scss" --html "components/**/*.html" /workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --css "styles/**/*.scss" --html "components/**/*.html"
# Universal style files # Universal style files
/workflow:ui-design:import-from-code --style-files "**/theme.*" /workflow:ui-design:import-from-code --source-path ./src --output-path ./design-system --style-files "**/theme.*"
``` ```
--- ---
@@ -74,11 +75,12 @@ Extract design system tokens from source code files (CSS/SCSS/JS/TS/HTML) using
```bash ```bash
# 1. Initialize directories # 1. Initialize directories
base_path="${base_path:-.}" source_path="${source_path:-.}"
intermediates_dir="${base_path}/.intermediates/import-analysis" output_path="${output_path:-.}"
intermediates_dir="${output_path}/.intermediates/import-analysis"
mkdir -p "$intermediates_dir" mkdir -p "$intermediates_dir"
echo "[Phase 0] File Discovery Started" echo "[Phase 0] File Discovery Started (source: $source_path, output: $output_path)"
``` ```
<!-- TodoWrite: Initialize todo list --> <!-- TodoWrite: Initialize todo list -->
@@ -95,7 +97,7 @@ echo "[Phase 0] File Discovery Started"
```bash ```bash
# 2. Discover files by type # 2. Discover files by type
cd "$base_path" || exit 1 cd "$source_path" || exit 1
# CSS files # CSS files
if [ -n "$css" ]; then if [ -n "$css" ]; then
@@ -181,7 +183,7 @@ Task(ui-design-agent): `
[STYLE_TOKENS_EXTRACTION] [STYLE_TOKENS_EXTRACTION]
Extract visual design tokens (colors, typography, spacing, shadows, borders) from ALL file types Extract visual design tokens (colors, typography, spacing, shadows, borders) from ALL file types
MODE: style-extraction | BASE_PATH: ${base_path} MODE: style-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path}
## Input Files (Can reference ANY file type) ## Input Files (Can reference ANY file type)
@@ -208,7 +210,7 @@ Task(ui-design-agent): `
## Output Requirements ## Output Requirements
Generate 2 files in ${base_path}/style-extraction/style-1/: Generate 2 files in ${output_path}/style-extraction/style-1/:
1. design-tokens.json (production-ready design tokens) 1. design-tokens.json (production-ready design tokens)
2. style-guide.md (design philosophy and usage guide) 2. style-guide.md (design philosophy and usage guide)
@@ -357,13 +359,13 @@ Task(ui-design-agent): `
## Critical Requirements ## Critical Requirements
- ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - not restricted to CSS only - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - not restricted to CSS only
- ✅ Use Read() tool for each file you want to analyze - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path})
- ✅ Cross-reference between file types for better extraction - ✅ Cross-reference between file types for better extraction
- ✅ Extract all visual token types systematically - ✅ Extract all visual token types systematically
- ✅ Create style-extraction/style-1/ directory first: Bash(mkdir -p "${base_path}/style-extraction/style-1") - ✅ Create style-extraction/style-1/ directory first: Bash(mkdir -p "${output_path}/style-extraction/style-1")
- ✅ Use Write() to save both files: - ✅ Use Write() to save both files:
- ${base_path}/style-extraction/style-1/design-tokens.json - ${output_path}/style-extraction/style-1/design-tokens.json
- ${base_path}/style-extraction/style-1/style-guide.md - ${output_path}/style-extraction/style-1/style-guide.md
- ✅ Include _metadata.completeness field to track missing content - ✅ Include _metadata.completeness field to track missing content
- ❌ NO external research or MCP calls - ❌ NO external research or MCP calls
` `
@@ -378,7 +380,7 @@ Task(ui-design-agent): `
[ANIMATION_TOKENS_EXTRACTION] [ANIMATION_TOKENS_EXTRACTION]
Extract animation/transition tokens from ALL file types Extract animation/transition tokens from ALL file types
MODE: animation-extraction | BASE_PATH: ${base_path} MODE: animation-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path}
## Input Files (Can reference ANY file type) ## Input Files (Can reference ANY file type)
@@ -405,7 +407,7 @@ Task(ui-design-agent): `
## Output Requirements ## Output Requirements
Generate 2 files in ${base_path}/animation-extraction/: Generate 2 files in ${output_path}/animation-extraction/:
1. animation-tokens.json (production-ready animation tokens) 1. animation-tokens.json (production-ready animation tokens)
2. animation-guide.md (animation usage guide) 2. animation-guide.md (animation usage guide)
@@ -530,13 +532,13 @@ Task(ui-design-agent): `
## Critical Requirements ## Critical Requirements
- ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML)
- ✅ Use Read() tool for each file you want to analyze - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path})
- ✅ Detect animation framework if used - ✅ Detect animation framework if used
- ✅ Extract all animation-related tokens - ✅ Extract all animation-related tokens
- ✅ Create animation-extraction/ directory first: Bash(mkdir -p "${base_path}/animation-extraction") - ✅ Create animation-extraction/ directory first: Bash(mkdir -p "${output_path}/animation-extraction")
- ✅ Use Write() to save both files: - ✅ Use Write() to save both files:
- ${base_path}/animation-extraction/animation-tokens.json - ${output_path}/animation-extraction/animation-tokens.json
- ${base_path}/animation-extraction/animation-guide.md - ${output_path}/animation-extraction/animation-guide.md
- ✅ Include _metadata.completeness field to track missing content - ✅ Include _metadata.completeness field to track missing content
- ❌ NO external research or MCP calls - ❌ NO external research or MCP calls
` `
@@ -551,7 +553,7 @@ Task(ui-design-agent): `
[LAYOUT_PATTERNS_EXTRACTION] [LAYOUT_PATTERNS_EXTRACTION]
Extract layout patterns and component structures from ALL file types Extract layout patterns and component structures from ALL file types
MODE: layout-extraction | BASE_PATH: ${base_path} MODE: layout-extraction | SOURCE_PATH: ${source_path} | OUTPUT_PATH: ${output_path}
## Input Files (Can reference ANY file type) ## Input Files (Can reference ANY file type)
@@ -578,7 +580,7 @@ Task(ui-design-agent): `
## Output Requirements ## Output Requirements
Generate 1 file: ${base_path}/layout-extraction/layout-templates.json Generate 1 file: ${output_path}/layout-extraction/layout-templates.json
### layout-templates.json Structure: ### layout-templates.json Structure:
{ {
@@ -675,11 +677,11 @@ Task(ui-design-agent): `
## Critical Requirements ## Critical Requirements
- ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML) - ✅ Can read ANY file type (CSS/SCSS/JS/TS/HTML)
- ✅ Use Read() tool for each file you want to analyze - ✅ Use Read() tool for each file you want to analyze (files are in SOURCE_PATH: ${source_path})
- ✅ Identify naming conventions and layout systems - ✅ Identify naming conventions and layout systems
- ✅ Extract component patterns with variants and states - ✅ Extract component patterns with variants and states
- ✅ Create layout-extraction/ directory first: Bash(mkdir -p "${base_path}/layout-extraction") - ✅ Create layout-extraction/ directory first: Bash(mkdir -p "${output_path}/layout-extraction")
- ✅ Use Write() to save: ${base_path}/layout-extraction/layout-templates.json - ✅ Use Write() to save: ${output_path}/layout-extraction/layout-templates.json
- ✅ Include extraction_metadata.completeness field to track missing content - ✅ Include extraction_metadata.completeness field to track missing content
- ❌ NO external research or MCP calls - ❌ NO external research or MCP calls
` `
@@ -710,11 +712,11 @@ echo "[Phase 1] Parallel agent analysis complete"
### Generated Files ### Generated Files
**Location**: `${base_path}/` **Location**: `${output_path}/`
**Directory Structure**: **Directory Structure**:
``` ```
${base_path}/ ${output_path}/
├── style-extraction/ ├── style-extraction/
│ └── style-1/ │ └── style-1/
│ ├── design-tokens.json # Production-ready design tokens │ ├── design-tokens.json # Production-ready design tokens
@@ -769,7 +771,7 @@ ${base_path}/
| Error | Cause | Resolution | | Error | Cause | Resolution |
|-------|-------|------------| |-------|-------|------------|
| No files discovered | Glob patterns too restrictive or wrong base-path | Check glob patterns and base-path, verify file locations | | No files discovered | Glob patterns too restrictive or wrong source-path | Check glob patterns and source-path, verify file locations |
| Agent reports "failed" status | No tokens found in any file | Review file content, check if files contain design tokens | | Agent reports "failed" status | No tokens found in any file | Review file content, check if files contain design tokens |
| Empty completeness reports | Files exist but contain no extractable tokens | Manually verify token definitions in source files | | Empty completeness reports | Files exist but contain no extractable tokens | Manually verify token definitions in source files |
| Missing file type | Specific file type not discovered | Use explicit glob flags (--css, --js, --html, --scss) | | Missing file type | Specific file type not discovered | Use explicit glob flags (--css, --js, --html, --scss) |
@@ -779,7 +781,8 @@ ${base_path}/
## Best Practices ## Best Practices
1. **Use auto-discovery for full projects**: Omit glob flags to discover all files automatically 1. **Use auto-discovery for full projects**: Omit glob flags to discover all files automatically
2. **Target specific directories for speed**: Use `--base-path` + specific globs for focused analysis 2. **Target specific directories for speed**: Use `--source-path` to target source code and `--output-path` for extracted tokens, combined with specific globs for focused analysis
3. **Cross-reference agent reports**: Compare all three completeness reports to identify gaps 3. **Separate source and output**: Always use distinct `--source-path` (where source code lives) and `--output-path` (where design tokens are generated) to avoid polluting source code directory
4. **Review missing content**: Check `missing` field in reports for actionable improvements 4. **Cross-reference agent reports**: Compare all three completeness reports to identify gaps
5. **Verify file discovery**: Check `.intermediates/import-analysis/*-files.txt` if agents report no data 5. **Review missing content**: Check `missing` field in reports for actionable improvements
6. **Verify file discovery**: Check `${output_path}/.intermediates/import-analysis/*-files.txt` if agents report no data

View File

@@ -1,7 +1,7 @@
--- ---
name: layout-extract name: layout-extract
description: Extract structural layout information from reference images, URLs, or text prompts using Claude analysis description: Extract structural layout information from reference images, URLs, or text prompts using Claude analysis
argument-hint: [--base-path <path>] [--session <id>] [--images "<glob>"] [--urls "<list>"] [--prompt "<desc>"] [--targets "<list>"] [--mode <imitate|explore>] [--variants <count>] [--device-type <desktop|mobile|tablet|responsive>] argument-hint: [--base-path <path>] [--session <id>] [--images "<glob>"] [--urls "<list>"] [--prompt "<desc>"] [--targets "<list>"] [--variants <count>] [--device-type <desktop|mobile|tablet|responsive>]
allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), Task(ui-design-agent), mcp__exa__web_search_exa(*) allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), Task(ui-design-agent), mcp__exa__web_search_exa(*)
--- ---
@@ -14,10 +14,8 @@ Extract structural layout information from reference images, URLs, or text promp
**Strategy**: AI-Driven Structural Analysis **Strategy**: AI-Driven Structural Analysis
- **Agent-Powered**: Uses `ui-design-agent` for deep structural analysis - **Agent-Powered**: Uses `ui-design-agent` for deep structural analysis
- **Dual-Mode**: - **Behavior**: Generate N layout concepts → User multi-select → Generate selected templates
- `imitate`: High-fidelity replication of single layout structure - **Output**: `layout-templates.json` with DOM structure, component hierarchy, and CSS layout rules
- `explore`: Multiple structurally distinct layout variations
- **Single Output**: `layout-templates.json` with DOM structure, component hierarchy, and CSS layout rules
- **Device-Aware**: Optimized for specific device types (desktop, mobile, tablet, responsive) - **Device-Aware**: Optimized for specific device types (desktop, mobile, tablet, responsive)
- **Token-Based**: CSS uses `var()` placeholders for spacing and breakpoints - **Token-Based**: CSS uses `var()` placeholders for spacing and breakpoints
@@ -45,14 +43,9 @@ ELSE:
has_urls = false has_urls = false
url_list = [] url_list = []
# Determine extraction mode # Set variants count (default: 3, range: 1-5)
extraction_mode = --mode OR "imitate" # "imitate" or "explore" # Behavior: Generate N layout concepts per target → User multi-select → Generate selected templates
variants_count = --variants OR 3
# Set variants count based on mode
IF extraction_mode == "imitate":
variants_count = 1 # Force single variant (ignore --variants)
ELSE IF extraction_mode == "explore":
variants_count = --variants OR 3 # Default to 3
VALIDATE: 1 <= variants_count <= 5 VALIDATE: 1 <= variants_count <= 5
# Resolve targets # Resolve targets
@@ -62,6 +55,9 @@ IF --targets:
ELSE IF has_urls: ELSE IF has_urls:
targets = [url_info.target for url_info in url_list] targets = [url_info.target for url_info in url_list]
ELSE IF --prompt: ELSE IF --prompt:
# Extract targets from prompt using pattern matching
# Looks for keywords: "page names", target descriptors (login, dashboard, etc.)
# Returns lowercase, hyphenated strings (e.g., ["login", "dashboard"])
targets = extract_from_prompt(--prompt) targets = extract_from_prompt(--prompt)
ELSE: ELSE:
targets = ["page"] targets = ["page"]
@@ -190,36 +186,17 @@ IF result.exploration?.triggered:
IF session_has_inputs: SKIP Step 2 file reading IF session_has_inputs: SKIP Step 2 file reading
# 2. Check if output already exists # 2. Check if output already exists
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists") bash(find {base_path}/layout-extraction -name "layout-*.json" -print -quit | grep -q . && echo "exists")
IF exists: SKIP to completion IF exists: SKIP to completion
``` ```
--- ---
**Phase 0 Output**: `input_mode`, `base_path`, `extraction_mode`, `variants_count`, `targets[]`, `device_type`, loaded inputs **Phase 0 Output**: `input_mode`, `base_path`, `variants_count`, `targets[]`, `device_type`, loaded inputs
## Phase 1: Layout Concept Generation (Explore Mode Only) ## Phase 1: Layout Concept Generation
### Step 1: Check Extraction Mode ### Step 1: Generate Layout Concept Options (Agent Task 1)
```bash
# extraction_mode == "imitate" → skip this phase
# extraction_mode == "explore" → execute this phase
```
**If imitate mode**: Skip to Phase 2
### Step 2: Gather Layout Inspiration (Explore Mode)
```bash
bash(mkdir -p {base_path}/.intermediates/layout-analysis/inspirations)
# For each target: Research via MCP
# mcp__exa__web_search_exa(query="{target} layout patterns {device_type}", numResults=5)
# Write inspiration file
Write({base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt, inspiration_content)
```
### Step 3: Generate Layout Concept Options (Agent Task 1)
**Executor**: `Task(ui-design-agent)` **Executor**: `Task(ui-design-agent)`
Launch agent to generate `variants_count` layout concept options for each target: Launch agent to generate `variants_count` layout concept options for each target:
@@ -235,7 +212,6 @@ Task(ui-design-agent): `
## Input Analysis ## Input Analysis
- Targets: {targets.join(", ")} - Targets: {targets.join(", ")}
- Device type: {device_type} - Device type: {device_type}
- Layout inspiration: Read inspirations from {base_path}/.intermediates/layout-analysis/inspirations/
- Visual references: {loaded_images if available} - Visual references: {loaded_images if available}
${dom_structure_available ? "- DOM Structure: Read from .intermediates/layout-analysis/dom-structure-*.json" : ""} ${dom_structure_available ? "- DOM Structure: Read from .intermediates/layout-analysis/dom-structure-*.json" : ""}
@@ -272,7 +248,7 @@ Task(ui-design-agent): `
` `
``` ```
### Step 4: Verify Options File Created ### Step 2: Verify Options File Created
```bash ```bash
bash(test -f {base_path}/.intermediates/layout-analysis/analysis-options.json && echo "created") bash(test -f {base_path}/.intermediates/layout-analysis/analysis-options.json && echo "created")
@@ -333,13 +309,13 @@ Please select your preferred concept for this target.
### Step 3: Capture User Selection (Per Target) ### Step 3: Capture User Selection (Per Target)
```javascript ```javascript
// Use AskUserQuestion tool for each target // Use AskUserQuestion tool for each target (multi-select enabled)
FOR each target: FOR each target:
AskUserQuestion({ AskUserQuestion({
questions: [{ questions: [{
question: "Which layout concept do you prefer for '{target}'?", question: "Which layout concept(s) do you prefer for '{target}'?",
header: "Layout for " + target, header: "Layout for " + target,
multiSelect: false, multiSelect: true, // Multi-selection enabled (default behavior)
options: [ options: [
{FOR each concept in layout_concepts[target]: {FOR each concept in layout_concepts[target]:
label: "Concept {concept.index}: {concept.concept_name}", label: "Concept {concept.index}: {concept.concept_name}",
@@ -349,39 +325,47 @@ FOR each target:
}] }]
}) })
// Parse user response // Parse user response (array of selections)
selected_option_text = user_answer selected_options = user_answer
// Check for user cancellation // Check for user cancellation
IF selected_option_text == null OR selected_option_text == "": IF selected_options == null OR selected_options.length == 0:
REPORT: "⚠️ User canceled selection. Workflow terminated." REPORT: "⚠️ User canceled selection. Workflow terminated."
EXIT workflow EXIT workflow
// Extract concept index from response format "Concept N: Name" // Extract concept indices from array
selected_indices = []
FOR each selected_option_text IN selected_options:
match = selected_option_text.match(/Concept (\d+):/) match = selected_option_text.match(/Concept (\d+):/)
IF match: IF match:
selected_index = parseInt(match[1]) selected_indices.push(parseInt(match[1]))
ELSE: ELSE:
ERROR: "Invalid selection format. Expected 'Concept N: ...' format" ERROR: "Invalid selection format. Expected 'Concept N: ...' format"
EXIT workflow EXIT workflow
// Store selection for this target // Store selections for this target (array of indices)
selections[target] = { selections[target] = {
selected_index: selected_index, selected_indices: selected_indices, // Array of selected indices
concept_name: layout_concepts[target][selected_index-1].concept_name concept_names: selected_indices.map(i => layout_concepts[target][i-1].concept_name)
} }
REPORT: "✅ Selected {selected_indices.length} layout(s) for {target}"
``` ```
### Step 4: Write User Selection File ### Step 4: Write User Selection File
```bash ```bash
# Calculate total selections across all targets
total_selections = sum([len(selections[t].selected_indices) for t in targets])
# Create user selection JSON # Create user selection JSON
selection_data = { selection_data = {
"metadata": { "metadata": {
"selected_at": "{current_timestamp}", "selected_at": "{current_timestamp}",
"selection_type": "per_target", "selection_type": "per_target_multi",
"session_id": "{session_id}" "session_id": "{session_id}",
"total_selections": total_selections
}, },
"selections": selections // {target: {selected_index, concept_name}} "selections": selections // {target: {selected_indices: [...], concept_names: [...]}}
} }
# Write to file # Write to file
@@ -393,85 +377,88 @@ bash(test -f {base_path}/.intermediates/layout-analysis/user-selection.json && e
### Step 5: Confirmation Message ### Step 5: Confirmation Message
``` ```
✅ Selections recorded! ✅ Selections recorded! Total: {total_selections} layout(s)
{FOR each target, selection in selections: {FOR each target, selection in selections:
• {target}: Concept {selection.selected_index} - {selection.concept_name} • {target}: {selection.selected_indices.length} layout(s) selected
{FOR each index IN selection.selected_indices:
- Concept {index}: {layout_concepts[target][index-1].concept_name}
}
} }
Proceeding to generate detailed layout templates based on your selections... Proceeding to generate {total_selections} detailed layout template(s)...
``` ```
**Output**: `user-selection.json` with user's choices for all targets **Output**: `user-selection.json` with user's multi-selections for all targets
## Phase 2: Layout Template Generation (Agent Task 2) ## Phase 2: Layout Template Generation (Agent Task 2)
**Executor**: `Task(ui-design-agent)` for selected concept(s) **Executor**: `Task(ui-design-agent)` × `Total_Selected_Templates` in **parallel**
### Step 1: Load User Selection (Explore Mode) ### Step 1: Load User Selections and Build Task List
```bash ```bash
# For explore mode, read user selection # Read user selections
IF extraction_mode == "explore":
selection = Read({base_path}/.intermediates/layout-analysis/user-selection.json) selection = Read({base_path}/.intermediates/layout-analysis/user-selection.json)
selections_per_target = selection.selections selections_per_target = selection.selections
# Also read the selected concept details from options # Read concept details
options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json) options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json)
layout_concepts = options.layout_concepts layout_concepts = options.layout_concepts
# Build selected concepts map # Build task list for all selected concepts across all targets
selected_concepts = {} task_list = []
FOR each target in targets: FOR each target in targets:
selected_index = selections_per_target[target].selected_index selected_indices = selections_per_target[target].selected_indices # Array
selected_concepts[target] = layout_concepts[target][selected_index-1] # 0-indexed concept_names = selections_per_target[target].concept_names # Array
ELSE:
# Imitate mode - no selection needed FOR i in range(len(selected_indices)):
selected_concepts = null idx = selected_indices[i]
concept = layout_concepts[target][idx - 1] # 0-indexed array
variant_id = i + 1 # 1-based variant numbering
task_list.push({
target: target,
variant_id: variant_id,
concept: concept,
output_file: "{base_path}/layout-extraction/layout-{target}-{variant_id}.json"
})
total_tasks = task_list.length
REPORT: "Generating {total_tasks} layout templates across {targets.length} targets"
``` ```
### Step 2: Launch Agent Task ### Step 2: Launch Parallel Agent Tasks
Generate layout templates for selected concepts: Generate layout templates for ALL selected concepts in parallel:
```javascript ```javascript
FOR each task in task_list:
Task(ui-design-agent): ` Task(ui-design-agent): `
[LAYOUT_TEMPLATE_GENERATION_TASK] [LAYOUT_TEMPLATE_GENERATION_TASK #{task.variant_id} for {task.target}]
Generate detailed layout templates based on user-selected concepts. Generate detailed layout template based on user-selected concept.
Focus ONLY on structure and layout. DO NOT concern with visual style (colors, fonts, etc.). Focus ONLY on structure and layout. DO NOT concern with visual style (colors, fonts, etc.).
SESSION: {session_id} | MODE: {extraction_mode} | BASE_PATH: {base_path} SESSION: {session_id} | BASE_PATH: {base_path}
TARGET: {task.target} | VARIANT: {task.variant_id}
DEVICE_TYPE: {device_type} DEVICE_TYPE: {device_type}
${extraction_mode == "explore" ? ` USER SELECTION:
USER SELECTIONS: - Selected Concept: {task.concept.concept_name}
${targets.map(target => ` - Philosophy: {task.concept.design_philosophy}
Target: ${target} - Pattern: {task.concept.layout_pattern}
- Selected Concept: ${selected_concepts[target].concept_name} - Key Components: {task.concept.key_components.join(", ")}
- Philosophy: ${selected_concepts[target].design_philosophy} - Structural Features: {task.concept.structural_features.join(", ")}
- Pattern: ${selected_concepts[target].layout_pattern}
- Key Components: ${selected_concepts[target].key_components.join(", ")}
- Structural Features: ${selected_concepts[target].structural_features.join(", ")}
`).join("\n")}
` : `
MODE: Imitate - High-fidelity replication of reference layout structure
TARGETS: ${targets.join(", ")}
`}
## Input Analysis ## Input Analysis
- Targets: {targets.join(", ")} - Target: {task.target}
- Device type: {device_type} - Device type: {device_type}
- Visual references: {loaded_images if available} - Visual references: {loaded_images if available}
${dom_structure_available ? "- DOM Structure Data: Read from .intermediates/layout-analysis/dom-structure-*.json - USE THIS for accurate layout properties" : ""} ${dom_structure_available ? "- DOM Structure Data: Read from .intermediates/layout-analysis/dom-structure-{task.target}.json - USE THIS for accurate layout properties" : ""}
## Generation Rules ## Generation Rules
${extraction_mode == "explore" ? ` - Develop the user-selected layout concept into a detailed template
- **Explore Mode**: Develop each user-selected layout concept into a detailed template
- Use the selected concept's key_components as foundation - Use the selected concept's key_components as foundation
- Apply the selected layout_pattern (grid-3col, flex-row, etc.) - Apply the selected layout_pattern (grid-3col, flex-row, etc.)
- Honor the structural_features defined in the concept - Honor the structural_features defined in the concept
- Expand the concept with complete DOM structure and CSS layout rules - Expand the concept with complete DOM structure and CSS layout rules
` : `
- **Imitate Mode**: High-fidelity replication of reference layout structure
${dom_structure_available ? "- Use DOM structure data as ground truth" : "- Use visual inference"}
`}
${dom_structure_available ? ` ${dom_structure_available ? `
- IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties - IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties
- Use DOM data as primary source for layout properties - Use DOM data as primary source for layout properties
@@ -480,62 +467,65 @@ Task(ui-design-agent): `
- Preserve identified patterns from DOM structure - Preserve identified patterns from DOM structure
` : ""} ` : ""}
## Generate for EACH Target ## Template Generation
For target in {targets}:
${extraction_mode == "explore" ? "Based on user-selected concept:" : "Based on reference:"}
1. **DOM Structure**: 1. **DOM Structure**:
- Semantic HTML5 tags: <header>, <nav>, <main>, <aside>, <section>, <footer> - Semantic HTML5 tags: <header>, <nav>, <main>, <aside>, <section>, <footer>
- ARIA roles and accessibility attributes - ARIA roles and accessibility attributes
${extraction_mode == "explore" ? "- Use key_components from selected concept" : ""} - Use key_components from selected concept
${dom_structure_available ? "- Base on extracted DOM tree from .intermediates" : "- Infer from visual analysis"} ${dom_structure_available ? "- Base on extracted DOM tree from .intermediates" : "- Infer from visual analysis"}
- Device-specific optimizations for {device_type} - Device-specific optimizations for {device_type}
2. **Component Hierarchy**: 2. **Component Hierarchy**:
- Array of main layout regions - Array of main layout regions
${extraction_mode == "explore" ? "- Derived from selected concept's key_components" : ""} - Derived from selected concept's key_components
3. **CSS Layout Rules**: 3. **CSS Layout Rules**:
${extraction_mode == "explore" ? "- Implement selected layout_pattern" : ""} - Implement selected layout_pattern
${dom_structure_available ? "- Use real layout properties from DOM structure data" : "- Focus on Grid, Flexbox, position, alignment"} ${dom_structure_available ? "- Use real layout properties from DOM structure data" : "- Focus on Grid, Flexbox, position, alignment"}
- Use CSS Custom Properties: var(--spacing-*), var(--breakpoint-*) - Use CSS Custom Properties: var(--spacing-*), var(--breakpoint-*)
- Device-specific styles (mobile-first @media for responsive) - Device-specific styles (mobile-first @media for responsive)
- NO colors, NO fonts, NO shadows - layout structure only - NO colors, NO fonts, NO shadows - layout structure only
## Output Format ## Output Format
Write complete layout-templates.json with layout_templates array. Write single-template JSON object with:
Each template must include: - target: "{task.target}"
- target (string) - variant_id: "layout-{task.variant_id}"
- variant_id: "layout-1" (always 1 since only selected concept is generated)
- source_image_path (string): Reference image path - source_image_path (string): Reference image path
- device_type (string) - device_type: "{device_type}"
- design_philosophy (string ${extraction_mode == "explore" ? "- from selected concept" : ""}) - design_philosophy (string from selected concept)
- dom_structure (JSON object) - dom_structure (JSON object)
- component_hierarchy (array of strings) - component_hierarchy (array of strings)
- css_layout_rules (string) - css_layout_rules (string)
## Critical Requirements ## Critical Requirements
- ✅ Use Write() tool for layout-templates.json - ✅ Use Write() tool for {task.output_file}
-One template per target (only selected concept) -Single template for {task.target} variant {task.variant_id}
- ✅ Structure only, no visual styling - ✅ Structure only, no visual styling
- ✅ Token-based CSS (var()) - ✅ Token-based CSS (var())
${extraction_mode == "explore" ? "- ✅ Maintain consistency with selected concepts" : ""} - ✅ Maintain consistency with selected concept
` `
``` ```
**Output**: Agent generates `layout-templates.json` with one template per target **Output**: Agent generates multiple layout template files (one per selected concept)
### Step 2: Write Output File ### Step 3: Verify Output Files
```bash ```bash
# Take JSON output from agent # Count generated files
bash(echo '{agent_json_output}' > {base_path}/layout-extraction/layout-templates.json) expected_count = total_tasks
actual_count = bash(ls {base_path}/layout-extraction/layout-*.json | wc -l)
# Verify output # Verify all files were created
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists") IF actual_count == expected_count:
bash(cat {base_path}/layout-extraction/layout-templates.json | grep -q "layout_templates" && echo "valid") REPORT: "✓ All {expected_count} layout template files generated"
ELSE:
ERROR: "Expected {expected_count} files, found {actual_count}"
# Verify file structure (sample check)
bash(cat {base_path}/layout-extraction/layout-{first_target}-1.json | grep -q "variant_id" && echo "valid structure")
``` ```
**Output**: `layout-templates.json` created and verified **Output**: All layout template files created and verified (one file per selected concept)
## Completion ## Completion
@@ -543,9 +533,10 @@ bash(cat {base_path}/layout-extraction/layout-templates.json | grep -q "layout_t
```javascript ```javascript
TodoWrite({todos: [ TodoWrite({todos: [
{content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"}, {content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"},
{content: "Layout research (explore mode)", status: "completed", activeForm: "Researching layout patterns"}, {content: "Layout concept analysis (agent)", status: "completed", activeForm: "Analyzing layout patterns"},
{content: "Layout analysis and synthesis (agent)", status: "completed", activeForm: "Generating layout templates"}, {content: "User selection confirmation", status: "completed", activeForm: "Confirming selections"},
{content: "Write layout-templates.json", status: "completed", activeForm: "Saving templates"} {content: "Generate layout templates (parallel)", status: "completed", activeForm: "Generating templates"},
{content: "Verify output files", status: "completed", activeForm: "Verifying files"}
]}); ]});
``` ```
@@ -555,11 +546,9 @@ TodoWrite({todos: [
Configuration: Configuration:
- Session: {session_id} - Session: {session_id}
- Extraction Mode: {extraction_mode} (imitate/explore)
- Device Type: {device_type} - Device Type: {device_type}
- Targets: {targets} - Targets: {targets.join(", ")}
- Variants per Target: {variants_count} - Total Templates: {total_tasks} ({targets.length} targets with multi-selection)
- Total Templates: {targets.length × variants_count}
{IF has_urls AND dom_structure_available: {IF has_urls AND dom_structure_available:
- 🔍 URL Mode: DOM structure extracted from {len(url_list)} URL(s) - 🔍 URL Mode: DOM structure extracted from {len(url_list)} URL(s)
- Accuracy: Real flex/grid properties from live pages - Accuracy: Real flex/grid properties from live pages
@@ -568,22 +557,28 @@ Configuration:
- ⚠️ URL Mode: Chrome DevTools unavailable, used visual analysis fallback - ⚠️ URL Mode: Chrome DevTools unavailable, used visual analysis fallback
} }
{IF extraction_mode == "explore": User Selections:
Layout Research: {FOR each target in targets:
- {targets.length} inspiration files generated - {target}: {selections_per_target[target].concept_names.join(", ")} ({selections_per_target[target].selected_indices.length} variants)
- Pattern search focused on {device_type} layouts
} }
Generated Templates: Generated Templates:
{FOR each template: - Target: {template.target} | Variant: {template.variant_id} | Philosophy: {template.design_philosophy}} {base_path}/layout-extraction/
{FOR each target in targets:
Output File: {FOR each variant_id in range(1, selections_per_target[target].selected_indices.length + 1):
- {base_path}/layout-extraction/layout-templates.json ├── layout-{target}-{variant_id}.json
{IF dom_structure_available: }
- {base_path}/.intermediates/layout-analysis/dom-structure-*.json ({len(url_list)} files)
} }
Next: /workflow:ui-design:generate will combine these structural templates with style systems to produce final prototypes. Intermediate Files:
- {base_path}/.intermediates/layout-analysis/
├── analysis-options.json (concept proposals)
├── user-selection.json (multi-selections per target)
{IF dom_structure_available:
├── dom-structure-*.json ({len(url_list)} DOM extracts)
}
Next: /workflow:ui-design:generate or /workflow:ui-design:batch-generate will combine these structural templates with design systems to produce final prototypes.
``` ```
## Simple Bash Commands ## Simple Bash Commands
@@ -595,19 +590,18 @@ bash(find .workflow -type d -name "design-run-*" | head -1)
# Create output directories # Create output directories
bash(mkdir -p {base_path}/layout-extraction) bash(mkdir -p {base_path}/layout-extraction)
bash(mkdir -p {base_path}/.intermediates/layout-analysis/inspirations) # explore mode only
``` ```
### Validation Commands ### Validation Commands
```bash ```bash
# Check if already extracted # Check if already extracted
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists") bash(find {base_path}/layout-extraction -name "layout-*.json" -print -quit | grep -q . && echo "exists")
# Validate JSON structure # Count generated files
bash(cat layout-templates.json | grep -q "layout_templates" && echo "valid") bash(ls {base_path}/layout-extraction/layout-*.json | wc -l)
# Count templates # Validate JSON structure (sample check)
bash(cat layout-templates.json | grep -c "\"target\":") bash(cat {base_path}/layout-extraction/layout-{first_target}-1.json | grep -q "variant_id" && echo "valid")
``` ```
### File Operations ### File Operations
@@ -616,9 +610,6 @@ bash(cat layout-templates.json | grep -c "\"target\":")
bash(ls {images_pattern}) bash(ls {images_pattern})
Read({image_path}) Read({image_path})
# Write inspiration files (explore mode)
Write({base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt, content)
# Write layout templates # Write layout templates
bash(echo '{json}' > {base_path}/layout-extraction/layout-templates.json) bash(echo '{json}' > {base_path}/layout-extraction/layout-templates.json)
``` ```
@@ -629,28 +620,28 @@ bash(echo '{json}' > {base_path}/layout-extraction/layout-templates.json)
{base_path}/ {base_path}/
├── .intermediates/ # Intermediate analysis files ├── .intermediates/ # Intermediate analysis files
│ └── layout-analysis/ │ └── layout-analysis/
│ ├── dom-structure-{target}.json # Extracted DOM structure (URL mode only) │ ├── analysis-options.json # Generated layout concepts
── inspirations/ # Explore mode only ── user-selection.json # User's multi-selections per target
└── {target}-layout-ideas.txt # Layout inspiration research └── dom-structure-{target}.json # Extracted DOM structure (URL mode only)
└── layout-extraction/ # Final layout templates └── layout-extraction/ # Final layout templates
── layout-templates.json # Structural layout templates ── layout-{target}-{variant}.json # Structural layout templates (one per selected concept)
└── layout-space-analysis.json # Layout directions (explore mode only)
``` ```
## layout-templates.json Format ## Layout Template File Format
Each `layout-{target}-{variant}.json` file contains a single template:
```json ```json
{ {
"extraction_metadata": { "extraction_metadata": {
"session_id": "...", "session_id": "...",
"input_mode": "image|url|prompt|hybrid", "input_mode": "image|url|prompt|hybrid",
"extraction_mode": "imitate|explore",
"device_type": "desktop|mobile|tablet|responsive", "device_type": "desktop|mobile|tablet|responsive",
"timestamp": "...", "timestamp": "...",
"variants_count": 3, "target": "home",
"targets": ["home", "dashboard"] "variant_id": "layout-1"
}, },
"layout_templates": [ "template":
{ {
"target": "home", "target": "home",
"variant_id": "layout-1", "variant_id": "layout-1",
@@ -705,8 +696,8 @@ ERROR: Invalid target name
ERROR: Agent task failed ERROR: Agent task failed
→ Check agent output, retry with simplified prompt → Check agent output, retry with simplified prompt
ERROR: MCP search failed (explore mode) ERROR: MCP search failed
→ Check network, retry → Check network connection, retry command
``` ```
### Recovery Strategies ### Recovery Strategies
@@ -720,11 +711,12 @@ ERROR: MCP search failed (explore mode)
- **Hybrid Extraction Strategy** - Combines real DOM structure data with AI visual analysis - **Hybrid Extraction Strategy** - Combines real DOM structure data with AI visual analysis
- **Accurate Layout Properties** - Chrome DevTools extracts real flex/grid configurations, bounds, and hierarchy - **Accurate Layout Properties** - Chrome DevTools extracts real flex/grid configurations, bounds, and hierarchy
- **Separation of Concerns** - Decouples layout (structure) from style (visuals) - **Separation of Concerns** - Decouples layout (structure) from style (visuals)
- **Structural Exploration** - Explore mode enables A/B testing of different layouts - **Multi-Selection Workflow** - Generate N concepts → User selects multiple → Parallel template generation
- **Structural Exploration** - Enables A/B testing of different layouts through multi-selection
- **Token-Based Layout** - CSS uses `var()` placeholders for instant design system adaptation - **Token-Based Layout** - CSS uses `var()` placeholders for instant design system adaptation
- **Device-Specific** - Tailored structures for different screen sizes - **Device-Specific** - Tailored structures for different screen sizes
- **Graceful Fallback** - Falls back to visual analysis if Chrome DevTools unavailable - **Graceful Fallback** - Falls back to visual analysis if Chrome DevTools unavailable
- **Foundation for Assembly** - Provides structural blueprint for refactored `generate` command - **Foundation for Assembly** - Provides structural blueprint for prototype generation
- **Agent-Powered** - Deep structural analysis with AI - **Agent-Powered** - Deep structural analysis with AI
## Integration ## Integration
@@ -732,17 +724,17 @@ ERROR: MCP search failed (explore mode)
**Workflow Position**: Between style extraction and prototype generation **Workflow Position**: Between style extraction and prototype generation
**New Workflow**: **New Workflow**:
1. `/workflow:ui-design:style-extract` → `design-tokens.json` + `style-guide.md` (Complete design systems) 1. `/workflow:ui-design:style-extract` → Multiple `style-N/design-tokens.json` files (Complete design systems)
2. `/workflow:ui-design:layout-extract` → `layout-templates.json` (Structural templates) 2. `/workflow:ui-design:layout-extract` → Multiple `layout-{target}-{variant}.json` files (Structural templates)
3. `/workflow:ui-design:generate` (Pure assembler): 3. `/workflow:ui-design:generate` or `/workflow:ui-design:batch-generate` (Assembler):
- **Reads**: `design-tokens.json` + `layout-templates.json` - **Reads**: All `design-tokens.json` files + all `layout-{target}-{variant}.json` files
- **Action**: For each style × layout combination: - **Action**: For each style × layout combination:
1. Build HTML from `dom_structure` 1. Build HTML from `dom_structure`
2. Create layout CSS from `css_layout_rules` 2. Create layout CSS from `css_layout_rules`
3. Link design tokens CSS 3. Apply design tokens to CSS
4. Inject placeholder content 4. Generate complete prototypes
- **Output**: Complete token-driven HTML/CSS prototypes - **Output**: Complete token-driven HTML/CSS prototypes
**Input**: Reference images, URLs, or text prompts **Input**: Reference images, URLs, or text prompts
**Output**: `layout-templates.json` for `/workflow:ui-design:generate` **Output**: `layout-{target}-{variant}.json` files for downstream generation commands
**Next**: `/workflow:ui-design:generate --session {session_id}` **Next**: `/workflow:ui-design:generate` or `/workflow:ui-design:batch-generate`

View File

@@ -1,7 +1,7 @@
--- ---
name: style-extract name: style-extract
description: Extract design style from reference images or text prompts using Claude analysis with variant generation description: Extract design style from reference images or text prompts using Claude analysis with variant generation
argument-hint: "[--base-path <path>] [--session <id>] [--images "<glob>"] [--urls "<list>"] [--prompt "<desc>"] [--mode <imitate|explore>] [--variants <count>]" argument-hint: "[--base-path <path>] [--session <id>] [--images "<glob>"] [--urls "<list>"] [--prompt "<desc>"] [--variants <count>]"
allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), mcp__chrome-devtools__navigate_page(*), mcp__chrome-devtools__evaluate_script(*) allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), mcp__chrome-devtools__navigate_page(*), mcp__chrome-devtools__evaluate_script(*)
--- ---
@@ -40,15 +40,9 @@ IF --urls:
ELSE: ELSE:
has_urls = false has_urls = false
# Determine extraction mode # Set variants count (default: 3, range: 1-5)
# Priority: --mode parameter → default "imitate" # Behavior: Generate N design directions → User multi-select → Generate selected variants
extraction_mode = --mode OR "imitate" # "imitate" or "explore" variants_count = --variants OR 3
# Set variants count based on mode
IF extraction_mode == "imitate":
variants_count = 1 # Force single variant for imitate mode (ignore --variants)
ELSE IF extraction_mode == "explore":
variants_count = --variants OR 3 # Default to 3 for explore mode
VALIDATE: 1 <= variants_count <= 5 VALIDATE: 1 <= variants_count <= 5
# Determine base path (auto-detect and convert to absolute) # Determine base path (auto-detect and convert to absolute)
@@ -142,24 +136,15 @@ IF exists: SKIP to completion
**Phase 0 Output**: `input_mode`, `base_path`, `extraction_mode`, `variants_count`, `loaded_images[]` or `prompt_guidance`, `has_urls`, `url_list[]`, `computed_styles_available` **Phase 0 Output**: `input_mode`, `base_path`, `extraction_mode`, `variants_count`, `loaded_images[]` or `prompt_guidance`, `has_urls`, `url_list[]`, `computed_styles_available`
## Phase 1: Design Direction Generation (Explore Mode Only) ## Phase 1: Design Direction Generation
### Step 1: Check Extraction Mode ### Step 1: Load Project Context
```bash
# Check extraction mode
# extraction_mode == "imitate" → skip this phase
# extraction_mode == "explore" → execute this phase
```
**If imitate mode**: Skip to Phase 2
### Step 2: Load Project Context (Explore Mode)
```bash ```bash
# Load brainstorming context if available # Load brainstorming context if available
bash(test -f {base_path}/.brainstorming/role analysis documents && cat it) bash(test -f {base_path}/.brainstorming/role analysis documents && cat it)
``` ```
### Step 3: Generate Design Direction Options (Agent Task 1) ### Step 2: Generate Design Direction Options (Agent Task 1)
**Executor**: `Task(ui-design-agent)` **Executor**: `Task(ui-design-agent)`
Launch agent to generate `variants_count` design direction options with previews: Launch agent to generate `variants_count` design direction options with previews:
@@ -207,7 +192,7 @@ Task(ui-design-agent): `
` `
``` ```
### Step 4: Verify Options File Created ### Step 3: Verify Options File Created
```bash ```bash
bash(test -f {base_path}/.intermediates/style-analysis/analysis-options.json && echo "created") bash(test -f {base_path}/.intermediates/style-analysis/analysis-options.json && echo "created")
@@ -267,12 +252,12 @@ Please select the direction(s) you'd like to develop into complete design system
### Step 3: Capture User Selection ### Step 3: Capture User Selection
```javascript ```javascript
// Use AskUserQuestion tool for selection // Use AskUserQuestion tool for multi-selection
AskUserQuestion({ AskUserQuestion({
questions: [{ questions: [{
question: "Which design direction would you like to develop into a complete design system?", question: "Which design direction(s) would you like to develop into complete design systems?",
header: "Style Choice", header: "Style Choice",
multiSelect: false, // Single selection for Phase 1 multiSelect: true, // Multi-selection enabled (default behavior)
options: [ options: [
{FOR each direction: {FOR each direction:
label: "Option {direction.index}: {direction.philosophy_name}", label: "Option {direction.index}: {direction.philosophy_name}",
@@ -282,21 +267,25 @@ AskUserQuestion({
}] }]
}) })
// Parse user response (e.g., "Option 1: Minimalist & Airy") // Parse user response (array of selections, e.g., ["Option 1: ...", "Option 3: ..."])
selected_option_text = user_answer selected_options = user_answer
// Check for user cancellation // Check for user cancellation
IF selected_option_text == null OR selected_option_text == "": IF selected_options == null OR selected_options.length == 0:
REPORT: "⚠️ User canceled selection. Workflow terminated." REPORT: "⚠️ User canceled selection. Workflow terminated."
EXIT workflow EXIT workflow
// Extract option index from response format "Option N: Name" // Extract option indices from array
selected_indices = []
FOR each selected_option_text IN selected_options:
match = selected_option_text.match(/Option (\d+):/) match = selected_option_text.match(/Option (\d+):/)
IF match: IF match:
selected_index = parseInt(match[1]) selected_indices.push(parseInt(match[1]))
ELSE: ELSE:
ERROR: "Invalid selection format. Expected 'Option N: ...' format" ERROR: "Invalid selection format. Expected 'Option N: ...' format"
EXIT workflow EXIT workflow
REPORT: "✅ Selected {selected_indices.length} design direction(s)"
``` ```
### Step 4: Write User Selection File ### Step 4: Write User Selection File
@@ -305,10 +294,11 @@ ELSE:
selection_data = { selection_data = {
"metadata": { "metadata": {
"selected_at": "{current_timestamp}", "selected_at": "{current_timestamp}",
"selection_type": "single", "selection_type": "multi",
"session_id": "{session_id}" "session_id": "{session_id}",
"selection_count": selected_indices.length
}, },
"selected_indices": [selected_index], "selected_indices": selected_indices, // Array of selected indices
"refinements": { "refinements": {
"enabled": false "enabled": false
} }
@@ -325,54 +315,55 @@ bash(test -f {base_path}/.intermediates/style-analysis/user-selection.json && ec
``` ```
✅ Selection recorded! ✅ Selection recorded!
You selected: Option {selected_index} - {selected_direction.philosophy_name} You selected {selected_indices.length} design direction(s):
{FOR each index IN selected_indices:
• Option {index} - {design_directions[index-1].philosophy_name}
}
Proceeding to generate complete design system based on your selection... Proceeding to generate {selected_indices.length} complete design system(s)...
``` ```
**Output**: `user-selection.json` with user's choice **Output**: `user-selection.json` with user's multi-selection
## Phase 2: Design System Generation (Agent Task 2) ## Phase 2: Design System Generation (Agent Task 2)
**Executor**: `Task(ui-design-agent)` for selected variant(s) **Executor**: `Task(ui-design-agent)` for selected variant(s)
### Step 1: Load User Selection (Explore Mode) ### Step 1: Load User Selection
```bash ```bash
# For explore mode, read user selection # Read user selection
IF extraction_mode == "explore":
selection = Read({base_path}/.intermediates/style-analysis/user-selection.json) selection = Read({base_path}/.intermediates/style-analysis/user-selection.json)
selected_indices = selection.selected_indices selected_indices = selection.selected_indices # Array of selected indices
refinements = selection.refinements
# Also read the selected direction details from options # Read the selected direction details from options
options = Read({base_path}/.intermediates/style-analysis/analysis-options.json) options = Read({base_path}/.intermediates/style-analysis/analysis-options.json)
selected_directions = [options.design_directions[i-1] for i in selected_indices] # 0-indexed selected_directions = [options.design_directions[i-1] for i in selected_indices] # 0-indexed array
# For Phase 1, we only allow single selection actual_variants_count = selected_indices.length
selected_direction = selected_directions[0] REPORT: "📦 Generating {actual_variants_count} design system(s)..."
actual_variants_count = 1
ELSE:
# Imitate mode - generate single variant without selection
selected_direction = null
actual_variants_count = 1
``` ```
### Step 2: Create Output Directory ### Step 2: Create Output Directories
```bash ```bash
# Create directory for selected variant only # Create directories for each selected variant
bash(mkdir -p {base_path}/style-extraction/style-1) FOR index IN 1..actual_variants_count:
bash(mkdir -p {base_path}/style-extraction/style-{index})
``` ```
### Step 3: Launch Agent Task ### Step 3: Launch Agent Tasks (Parallel)
Generate design system for selected direction: Generate design systems for ALL selected directions in parallel (max 5 concurrent):
```javascript ```javascript
// Launch parallel tasks, one for each selected direction
FOR variant_index IN 1..actual_variants_count:
selected_direction = selected_directions[variant_index - 1] // 0-indexed
Task(ui-design-agent): ` Task(ui-design-agent): `
[DESIGN_SYSTEM_GENERATION_TASK] [DESIGN_SYSTEM_GENERATION_TASK #{variant_index}/{actual_variants_count}]
Generate production-ready design system based on user-selected direction Generate production-ready design system based on user-selected direction
SESSION: {session_id} | MODE: {extraction_mode} | BASE_PATH: {base_path} SESSION: {session_id} | VARIANT: {variant_index}/{actual_variants_count} | BASE_PATH: {base_path}
${extraction_mode == "explore" ? `
USER SELECTION: USER SELECTION:
- Selected Direction: ${selected_direction.philosophy_name} - Selected Direction: ${selected_direction.philosophy_name}
- Design Attributes: ${JSON.stringify(selected_direction.design_attributes)} - Design Attributes: ${JSON.stringify(selected_direction.design_attributes)}
@@ -383,22 +374,13 @@ Task(ui-design-agent): `
- Preview Typography: Heading=${selected_direction.preview.font_family_heading}, Body=${selected_direction.preview.font_family_body} - Preview Typography: Heading=${selected_direction.preview.font_family_heading}, Body=${selected_direction.preview.font_family_body}
- Preview Border Radius: ${selected_direction.preview.border_radius_base} - Preview Border Radius: ${selected_direction.preview.border_radius_base}
${refinements.enabled ? `
USER REFINEMENTS:
${refinements.primary_color ? "- Primary Color Override: " + refinements.primary_color : ""}
${refinements.font_family_heading ? "- Heading Font Override: " + refinements.font_family_heading : ""}
${refinements.font_family_body ? "- Body Font Override: " + refinements.font_family_body : ""}
` : ""}
` : ""}
## Input Analysis ## Input Analysis
- Input mode: {input_mode} (image/text/hybrid${has_urls ? "/url" : ""}) - Input mode: {input_mode} (image/text/hybrid${has_urls ? "/url" : ""})
- Visual references: {loaded_images OR prompt_guidance} - Visual references: {loaded_images OR prompt_guidance}
${computed_styles_available ? "- Computed styles: Use as ground truth (Read from .intermediates/style-analysis/computed-styles.json)" : ""} ${computed_styles_available ? "- Computed styles: Use as ground truth (Read from .intermediates/style-analysis/computed-styles.json)" : ""}
## Generation Rules ## Generation Rules
${extraction_mode == "explore" ? ` - Develop the selected design direction into a complete design system
- **Explore Mode**: Develop the selected design direction into a complete design system
- Use preview elements as foundation and expand with full token coverage - Use preview elements as foundation and expand with full token coverage
- Apply design_attributes to all token values: - Apply design_attributes to all token values:
* color_saturation → OKLCH chroma values * color_saturation → OKLCH chroma values
@@ -409,15 +391,11 @@ Task(ui-design-agent): `
* innovation → token naming, experimental values * innovation → token naming, experimental values
- Honor search_keywords for design inspiration - Honor search_keywords for design inspiration
- Avoid anti_keywords patterns - Avoid anti_keywords patterns
` : `
- **Imitate Mode**: High-fidelity replication of reference design
${computed_styles_available ? "- Use computed styles as ground truth for all measurements" : "- Use visual inference for measurements"}
`}
- All colors in OKLCH format ${computed_styles_available ? "(convert from computed RGB)" : ""} - All colors in OKLCH format ${computed_styles_available ? "(convert from computed RGB)" : ""}
- WCAG AA compliance: 4.5:1 text contrast, 3:1 UI contrast - WCAG AA compliance: 4.5:1 text contrast, 3:1 UI contrast
## Generate ## Generate
Create complete design system in {base_path}/style-extraction/style-1/ Create complete design system in {base_path}/style-extraction/style-{variant_index}/
1. **design-tokens.json**: 1. **design-tokens.json**:
- Complete token structure with ALL fields: - Complete token structure with ALL fields:
@@ -450,14 +428,13 @@ Task(ui-design-agent): `
## Critical Requirements ## Critical Requirements
- ✅ Use Write() tool immediately for each file - ✅ Use Write() tool immediately for each file
- ✅ Write to style-1/ directory (single output) - ✅ Write to style-{variant_index}/ directory
- ❌ NO external research or MCP calls (pure AI generation) - ❌ NO external research or MCP calls (pure AI generation)
- ✅ Maintain consistency with user-selected direction - ✅ Maintain consistency with user-selected direction
${refinements.enabled ? "- ✅ Apply user refinements precisely" : ""}
` `
``` ```
**Output**: Agent generates 2 files (design-tokens.json, style-guide.md) for selected direction **Output**: {actual_variants_count} parallel agent tasks generate 2 files each (design-tokens.json, style-guide.md)
## Phase 3: Verify Output ## Phase 3: Verify Output
@@ -561,8 +538,10 @@ bash(cat {base_path}/style-extraction/style-1/design-tokens.json | grep -q "colo
# Load brainstorming context # Load brainstorming context
bash(test -f .brainstorming/role analysis documents && cat it) bash(test -f .brainstorming/role analysis documents && cat it)
# Create directories # Create directories (example for multiple variants)
bash(mkdir -p {base_path}/style-extraction/style-{{1..3}}) bash(mkdir -p {base_path}/style-extraction/style-1)
bash(mkdir -p {base_path}/style-extraction/style-2)
bash(mkdir -p {base_path}/style-extraction/style-3)
# Verify output # Verify output
bash(ls {base_path}/style-extraction/style-1/) bash(ls {base_path}/style-extraction/style-1/)