mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-12 02:37:45 +08:00
feat: 增强 command-guide skill 支持深度命令分析和 CLI 辅助查询
新增 Mode 6: 深度命令分析 - 创建 reference 备份目录(80个文档:11 agents + 69 commands) - 支持简单查询(直接文件查找)和复杂查询(CLI 辅助分析) - 集成 gemini/qwen 进行跨命令对比、最佳实践、工作流分析 - 添加查询复杂度自动分类和降级策略 更新文档 - SKILL.md: 添加 Mode 6 说明和 Reference Documentation 章节 - implementation-details.md: 添加完整的 Mode 6 实现逻辑 - 版本更新至 v1.3.0 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,911 @@
|
||||
---
|
||||
name: animation-extract
|
||||
description: Extract animation and transition patterns from URLs, CSS, or interactive questioning for design system documentation
|
||||
argument-hint: "[--base-path <path>] [--session <id>] [--urls "<list>"] [--mode <auto|interactive>] [--focus "<types>"]"
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), Task(ui-design-agent), mcp__chrome-devtools__navigate_page(*), mcp__chrome-devtools__evaluate_script(*)
|
||||
---
|
||||
|
||||
# Animation Extraction Command
|
||||
|
||||
## Overview
|
||||
|
||||
Extract animation and transition patterns from web pages using CSS extraction, visual analysis, or interactive questioning. This command generates production-ready animation tokens and guidelines that integrate with design systems.
|
||||
|
||||
**Strategy**: Hybrid Extraction with Interactive Fallback
|
||||
|
||||
- **Auto Mode (Priority 1)**: Extract from CSS via Chrome DevTools when URLs provided
|
||||
- **Visual Mode (Priority 2)**: Analyze screenshots for motion cues (blur, position changes)
|
||||
- **Interactive Mode (Priority 3)**: Guided questioning when extraction insufficient
|
||||
- **Output**: `animation-tokens.json` + `animation-guide.md`
|
||||
|
||||
## Phase 0: Setup & Input Validation
|
||||
|
||||
### Step 1: Detect Input Mode & Base Path
|
||||
|
||||
```bash
|
||||
# Detect input source
|
||||
# Priority: --urls → url mode | --mode interactive → question mode
|
||||
|
||||
# Parse URLs if provided (format: "target:url,target:url,...")
|
||||
IF --urls:
|
||||
url_list = []
|
||||
FOR pair IN split(--urls, ","):
|
||||
IF ":" IN pair:
|
||||
target, url = pair.split(":", 1)
|
||||
url_list.append({target: target.strip(), url: url.strip()})
|
||||
ELSE:
|
||||
url_list.append({target: "page", url: pair.strip()})
|
||||
|
||||
has_urls = true
|
||||
primary_url = url_list[0].url
|
||||
ELSE:
|
||||
has_urls = false
|
||||
|
||||
# Determine extraction mode
|
||||
extraction_mode = --mode OR (has_urls ? "auto" : "interactive")
|
||||
|
||||
# Parse animation focus (if provided)
|
||||
IF --focus:
|
||||
focus_types = split(--focus, ",") # e.g., "transitions,hover,scroll"
|
||||
ELSE:
|
||||
focus_types = ["all"] # Extract all animation types
|
||||
|
||||
# Determine base path
|
||||
bash(find .workflow -type d -name "design-*" | head -1) # Auto-detect
|
||||
# OR use --base-path / --session parameters
|
||||
```
|
||||
|
||||
### Step 2: Load Design Tokens Context
|
||||
|
||||
```bash
|
||||
# Load existing design tokens for duration/easing alignment
|
||||
IF exists({base_path}/style-extraction/style-1/design-tokens.json):
|
||||
design_tokens = Read({base_path}/style-extraction/style-1/design-tokens.json)
|
||||
has_design_context = true
|
||||
ELSE:
|
||||
has_design_context = false
|
||||
WARN: "⚠️ No design tokens found - animation tokens will use standalone values"
|
||||
|
||||
# Create output directory
|
||||
bash(mkdir -p {base_path}/animation-extraction)
|
||||
bash(mkdir -p {base_path}/.intermediates/animation-analysis)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Phase 0 Output**: `extraction_mode`, `base_path`, `has_urls`, `url_list[]`, `focus_types[]`, `has_design_context`
|
||||
|
||||
## Phase 1: CSS Animation Extraction (Auto Mode - URL Required)
|
||||
|
||||
### Step 1: Check Extraction Mode
|
||||
|
||||
```bash
|
||||
# extraction_mode == "interactive" → skip to Phase 2
|
||||
# extraction_mode == "auto" AND has_urls → execute this phase
|
||||
```
|
||||
|
||||
**If interactive mode**: Skip to Phase 2
|
||||
|
||||
### Step 2: Extract Computed Animations (Auto-Trigger)
|
||||
|
||||
```bash
|
||||
# AUTO-TRIGGER: If URLs are available, automatically extract CSS animations/transitions
|
||||
|
||||
IF has_urls AND mcp_chrome_devtools_available:
|
||||
REPORT: "🔍 Auto-triggering URL mode: Extracting CSS animations and transitions"
|
||||
|
||||
# Read extraction script
|
||||
script_content = Read(~/.claude/scripts/extract-animations.js)
|
||||
|
||||
# For each URL:
|
||||
FOR url_info IN url_list:
|
||||
target = url_info.target
|
||||
url = url_info.url
|
||||
|
||||
REPORT: " Processing: {target} ({url})"
|
||||
|
||||
# Open page in Chrome DevTools
|
||||
mcp__chrome-devtools__navigate_page(url=url)
|
||||
|
||||
# Wait for page to fully load and animations to initialize
|
||||
bash(sleep 2)
|
||||
|
||||
# Execute extraction script
|
||||
result = mcp__chrome-devtools__evaluate_script(function=script_content)
|
||||
|
||||
# Save raw animation data
|
||||
Write({base_path}/.intermediates/animation-analysis/animations-{target}.json, result)
|
||||
|
||||
REPORT: " ✅ Extracted: {result.summary.total_animations} animations, {result.summary.total_transitions} transitions"
|
||||
|
||||
animations_extracted = true
|
||||
REPORT: " ✅ CSS animation extraction complete"
|
||||
ELSE IF has_urls AND NOT mcp_chrome_devtools_available:
|
||||
animations_extracted = false
|
||||
REPORT: "⚠️ Chrome DevTools MCP not available"
|
||||
REPORT: " Falling back to interactive mode for animation guidance"
|
||||
ELSE:
|
||||
animations_extracted = false
|
||||
```
|
||||
|
||||
**Extraction Script Reference**: `~/.claude/scripts/extract-animations.js`
|
||||
|
||||
**Usage**: Read the script file and use content directly in `mcp__chrome-devtools__evaluate_script()`
|
||||
|
||||
**Script returns**:
|
||||
- `metadata`: Extraction timestamp, URL, method
|
||||
- `transitions`: Array of transition definitions (property, duration, easing, delay)
|
||||
- `animations`: Array of keyframe animations (name, duration, easing, keyframes)
|
||||
- `transforms`: Common transform patterns
|
||||
- `summary`: Statistics (total_animations, total_transitions, unique_easings)
|
||||
|
||||
**Benefits**:
|
||||
- ✅ Real animation values from production sites
|
||||
- ✅ Captures all CSS transitions and @keyframes rules
|
||||
- ✅ Identifies common easing functions and durations
|
||||
- ✅ Maps animations to element selectors
|
||||
|
||||
---
|
||||
|
||||
**Phase 1 Output**: `animations-{target}.json` (intermediate files)
|
||||
|
||||
## Phase 2: Interactive Animation Specification (Interactive/Fallback Mode)
|
||||
|
||||
### Step 1: Check if Extraction Sufficient
|
||||
|
||||
```bash
|
||||
# If animations extracted from CSS, check coverage
|
||||
IF animations_extracted:
|
||||
total_animations = sum([data.summary.total_animations for data in all_extracted])
|
||||
total_transitions = sum([data.summary.total_transitions for data in all_extracted])
|
||||
|
||||
# If sufficient data found, skip interactive mode
|
||||
IF total_animations >= 3 OR total_transitions >= 5:
|
||||
REPORT: "✅ Sufficient animation data extracted from CSS"
|
||||
SKIP to Phase 3
|
||||
ELSE:
|
||||
REPORT: "⚠️ Limited animation data found - launching interactive mode"
|
||||
extraction_insufficient = true
|
||||
ELSE:
|
||||
extraction_insufficient = true
|
||||
```
|
||||
|
||||
### Step 2: Generate Animation Questions (Main Flow)
|
||||
|
||||
```bash
|
||||
# If extraction failed or insufficient, use interactive questioning
|
||||
IF extraction_insufficient OR extraction_mode == "interactive":
|
||||
REPORT: "🤔 Interactive animation specification mode"
|
||||
REPORT: " Context: {has_design_context ? 'Aligning with design tokens' : 'Standalone animation system'}"
|
||||
REPORT: " Focus: {focus_types}"
|
||||
|
||||
# Determine question categories based on focus_types
|
||||
question_categories = []
|
||||
IF "all" IN focus_types OR "transitions" IN focus_types:
|
||||
question_categories.append("timing_scale")
|
||||
question_categories.append("easing_philosophy")
|
||||
|
||||
IF "all" IN focus_types OR "interactions" IN focus_types OR "hover" IN focus_types:
|
||||
question_categories.append("button_interactions")
|
||||
question_categories.append("card_interactions")
|
||||
question_categories.append("input_interactions")
|
||||
|
||||
IF "all" IN focus_types OR "page" IN focus_types:
|
||||
question_categories.append("page_transitions")
|
||||
|
||||
IF "all" IN focus_types OR "loading" IN focus_types:
|
||||
question_categories.append("loading_states")
|
||||
|
||||
IF "all" IN focus_types OR "scroll" IN focus_types:
|
||||
question_categories.append("scroll_animations")
|
||||
```
|
||||
|
||||
### Step 3: Output Questions in Text Format (Main Flow)
|
||||
|
||||
```markdown
|
||||
# Generate and output structured questions
|
||||
REPORT: ""
|
||||
REPORT: "===== 动画规格交互式配置 ====="
|
||||
REPORT: ""
|
||||
|
||||
question_number = 1
|
||||
questions_output = []
|
||||
|
||||
# Q1: Timing Scale (if included)
|
||||
IF "timing_scale" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 时间尺度】您的设计需要什么样的过渡速度?"
|
||||
REPORT: "a) 快速敏捷"
|
||||
REPORT: " 说明:100-200ms 过渡,适合工具型应用和即时反馈场景"
|
||||
REPORT: "b) 平衡适中"
|
||||
REPORT: " 说明:200-400ms 过渡,通用选择,符合多数用户预期"
|
||||
REPORT: "c) 流畅舒缓"
|
||||
REPORT: " 说明:400-600ms 过渡,适合品牌展示和沉浸式体验"
|
||||
REPORT: "d) 自定义"
|
||||
REPORT: " 说明:需要指定具体数值和使用场景"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "timing_scale", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
# Q2: Easing Philosophy (if included)
|
||||
IF "easing_philosophy" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 缓动风格】哪种缓动曲线符合您的品牌调性?"
|
||||
REPORT: "a) 线性匀速"
|
||||
REPORT: " 说明:恒定速度,技术感和精确性,适合数据可视化"
|
||||
REPORT: "b) 快入慢出"
|
||||
REPORT: " 说明:快速启动自然减速,最接近物理世界,通用推荐"
|
||||
REPORT: "c) 慢入慢出"
|
||||
REPORT: " 说明:平滑对称,精致优雅,适合高端品牌"
|
||||
REPORT: "d) 弹性效果"
|
||||
REPORT: " 说明:Spring/Bounce 回弹,活泼现代,适合互动性强的应用"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "easing_philosophy", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
# Q3-5: Interaction Animations (button, card, input - if included)
|
||||
IF "button_interactions" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 按钮交互】按钮悬停/点击时如何反馈?"
|
||||
REPORT: "a) 微妙变化"
|
||||
REPORT: " 说明:仅颜色/透明度变化,适合简约设计"
|
||||
REPORT: "b) 抬升效果"
|
||||
REPORT: " 说明:轻微缩放+阴影加深,增强物理感知"
|
||||
REPORT: "c) 滑动移位"
|
||||
REPORT: " 说明:Transform translateY,视觉引导明显"
|
||||
REPORT: "d) 无动画"
|
||||
REPORT: " 说明:静态交互,性能优先或特定品牌要求"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "button_interactions", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
IF "card_interactions" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 卡片交互】卡片悬停时的动画效果?"
|
||||
REPORT: "a) 阴影加深"
|
||||
REPORT: " 说明:Box-shadow 变化,层次感增强"
|
||||
REPORT: "b) 上浮效果"
|
||||
REPORT: " 说明:Transform translateY(-4px),明显的空间层次"
|
||||
REPORT: "c) 缩放放大"
|
||||
REPORT: " 说明:Scale(1.02),突出焦点内容"
|
||||
REPORT: "d) 无动画"
|
||||
REPORT: " 说明:静态卡片,性能或设计考量"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "card_interactions", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
IF "input_interactions" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 表单交互】输入框是否需要微交互反馈?"
|
||||
REPORT: "a) 聚焦动画"
|
||||
REPORT: " 说明:边框/阴影过渡,清晰的状态指示"
|
||||
REPORT: "b) 错误抖动"
|
||||
REPORT: " 说明:水平shake动画,错误提示更明显"
|
||||
REPORT: "c) 成功勾选"
|
||||
REPORT: " 说明:Checkmark 动画,完成反馈"
|
||||
REPORT: "d) 全部包含"
|
||||
REPORT: " 说明:聚焦+错误+成功的完整反馈体系"
|
||||
REPORT: "e) 无微交互"
|
||||
REPORT: " 说明:标准表单,无额外动画"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "input_interactions", options: ["a", "b", "c", "d", "e"]})
|
||||
question_number += 1
|
||||
|
||||
# Q6: Page Transitions (if included)
|
||||
IF "page_transitions" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 页面过渡】页面/路由切换是否需要过渡动画?"
|
||||
REPORT: "a) 淡入淡出"
|
||||
REPORT: " 说明:Crossfade 效果,平滑过渡不突兀"
|
||||
REPORT: "b) 滑动切换"
|
||||
REPORT: " 说明:Swipe left/right,方向性导航"
|
||||
REPORT: "c) 缩放过渡"
|
||||
REPORT: " 说明:Scale in/out,空间层次感"
|
||||
REPORT: "d) 无过渡"
|
||||
REPORT: " 说明:即时切换,性能优先"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "page_transitions", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
# Q7: Loading States (if included)
|
||||
IF "loading_states" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 加载状态】加载时使用何种动画风格?"
|
||||
REPORT: "a) 旋转加载器"
|
||||
REPORT: " 说明:Spinner 圆形旋转,通用加载指示"
|
||||
REPORT: "b) 脉冲闪烁"
|
||||
REPORT: " 说明:Opacity pulse,轻量级反馈"
|
||||
REPORT: "c) 骨架屏"
|
||||
REPORT: " 说明:Shimmer effect,内容占位预览"
|
||||
REPORT: "d) 进度条"
|
||||
REPORT: " 说明:Linear fill,进度量化展示"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "loading_states", options: ["a", "b", "c", "d"]})
|
||||
question_number += 1
|
||||
|
||||
# Q8: Scroll Animations (if included)
|
||||
IF "scroll_animations" IN question_categories:
|
||||
REPORT: "【问题{question_number} - 滚动动画】元素是否在滚动时触发动画?"
|
||||
REPORT: "a) 淡入出现"
|
||||
REPORT: " 说明:Opacity 0→1,渐进式内容呈现"
|
||||
REPORT: "b) 上滑出现"
|
||||
REPORT: " 说明:TranslateY + fade,方向性引导"
|
||||
REPORT: "c) 缩放淡入"
|
||||
REPORT: " 说明:Scale 0.9→1 + fade,聚焦效果"
|
||||
REPORT: "d) 交错延迟"
|
||||
REPORT: " 说明:Stagger 序列动画,列表渐次呈现"
|
||||
REPORT: "e) 无滚动动画"
|
||||
REPORT: " 说明:静态内容,性能或可访问性考量"
|
||||
REPORT: ""
|
||||
questions_output.append({id: question_number, category: "scroll_animations", options: ["a", "b", "c", "d", "e"]})
|
||||
question_number += 1
|
||||
|
||||
REPORT: "支持格式:"
|
||||
REPORT: "- 空格分隔:1a 2b 3c"
|
||||
REPORT: "- 逗号分隔:1a,2b,3c"
|
||||
REPORT: "- 自由组合:1a 2b,3c"
|
||||
REPORT: ""
|
||||
REPORT: "请输入您的选择:"
|
||||
```
|
||||
|
||||
### Step 4: Wait for User Input (Main Flow)
|
||||
|
||||
```javascript
|
||||
# Wait for user input
|
||||
user_raw_input = WAIT_FOR_USER_INPUT()
|
||||
|
||||
# Store raw input for debugging
|
||||
REPORT: "收到输入: {user_raw_input}"
|
||||
```
|
||||
|
||||
### Step 5: Parse User Answers (Main Flow)
|
||||
|
||||
```javascript
|
||||
# Intelligent input parsing (support multiple formats)
|
||||
answers = {}
|
||||
|
||||
# Parse input using intelligent matching
|
||||
# Support formats: "1a 2b 3c", "1a,2b,3c", "1a 2b,3c"
|
||||
parsed_responses = PARSE_USER_INPUT(user_raw_input, questions_output)
|
||||
|
||||
# Validate parsing
|
||||
IF parsed_responses.is_valid:
|
||||
# Map question numbers to categories
|
||||
FOR response IN parsed_responses.answers:
|
||||
question_id = response.question_id
|
||||
selected_option = response.option
|
||||
|
||||
# Find category for this question
|
||||
FOR question IN questions_output:
|
||||
IF question.id == question_id:
|
||||
category = question.category
|
||||
answers[category] = selected_option
|
||||
REPORT: "✅ 问题{question_id} ({category}): 选择 {selected_option}"
|
||||
break
|
||||
ELSE:
|
||||
REPORT: "❌ 输入格式无法识别,请参考格式示例重新输入:"
|
||||
REPORT: " 示例:1a 2b 3c 4d"
|
||||
# Return to Step 3 for re-input
|
||||
GOTO Step 3
|
||||
```
|
||||
|
||||
### Step 6: Write Animation Specification (Main Flow)
|
||||
|
||||
```javascript
|
||||
# Map user choices to specification structure
|
||||
specification = {
|
||||
"metadata": {
|
||||
"source": "interactive",
|
||||
"timestamp": NOW(),
|
||||
"focus_types": focus_types,
|
||||
"has_design_context": has_design_context
|
||||
},
|
||||
"timing_scale": MAP_TIMING_SCALE(answers.timing_scale),
|
||||
"easing_philosophy": MAP_EASING_PHILOSOPHY(answers.easing_philosophy),
|
||||
"interactions": {
|
||||
"button": MAP_BUTTON_INTERACTION(answers.button_interactions),
|
||||
"card": MAP_CARD_INTERACTION(answers.card_interactions),
|
||||
"input": MAP_INPUT_INTERACTION(answers.input_interactions)
|
||||
},
|
||||
"page_transitions": MAP_PAGE_TRANSITIONS(answers.page_transitions),
|
||||
"loading_animations": MAP_LOADING_STATES(answers.loading_states),
|
||||
"scroll_animations": MAP_SCROLL_ANIMATIONS(answers.scroll_animations)
|
||||
}
|
||||
|
||||
# Mapping functions (inline logic)
|
||||
FUNCTION MAP_TIMING_SCALE(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {scale: "fast", base_duration: "150ms", range: "100-200ms"}
|
||||
CASE "b": RETURN {scale: "balanced", base_duration: "300ms", range: "200-400ms"}
|
||||
CASE "c": RETURN {scale: "smooth", base_duration: "500ms", range: "400-600ms"}
|
||||
CASE "d": RETURN {scale: "custom", base_duration: "300ms", note: "User to provide values"}
|
||||
|
||||
FUNCTION MAP_EASING_PHILOSOPHY(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {style: "linear", curve: "linear"}
|
||||
CASE "b": RETURN {style: "ease-out", curve: "cubic-bezier(0, 0, 0.2, 1)"}
|
||||
CASE "c": RETURN {style: "ease-in-out", curve: "cubic-bezier(0.4, 0, 0.2, 1)"}
|
||||
CASE "d": RETURN {style: "spring", curve: "cubic-bezier(0.34, 1.56, 0.64, 1)"}
|
||||
|
||||
FUNCTION MAP_BUTTON_INTERACTION(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {type: "subtle", properties: ["color", "background-color", "opacity"]}
|
||||
CASE "b": RETURN {type: "lift", properties: ["transform", "box-shadow"], transform: "scale(1.02)"}
|
||||
CASE "c": RETURN {type: "slide", properties: ["transform"], transform: "translateY(-2px)"}
|
||||
CASE "d": RETURN {type: "none", properties: []}
|
||||
|
||||
FUNCTION MAP_CARD_INTERACTION(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {type: "shadow", properties: ["box-shadow"]}
|
||||
CASE "b": RETURN {type: "float", properties: ["transform", "box-shadow"], transform: "translateY(-4px)"}
|
||||
CASE "c": RETURN {type: "scale", properties: ["transform"], transform: "scale(1.02)"}
|
||||
CASE "d": RETURN {type: "none", properties: []}
|
||||
|
||||
FUNCTION MAP_INPUT_INTERACTION(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {enabled: ["focus"], focus: {properties: ["border-color", "box-shadow"]}}
|
||||
CASE "b": RETURN {enabled: ["error"], error: {animation: "shake", keyframes: "translateX"}}
|
||||
CASE "c": RETURN {enabled: ["success"], success: {animation: "checkmark", keyframes: "draw"}}
|
||||
CASE "d": RETURN {enabled: ["focus", "error", "success"]}
|
||||
CASE "e": RETURN {enabled: []}
|
||||
|
||||
FUNCTION MAP_PAGE_TRANSITIONS(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {enabled: true, style: "fade", animation: "fadeIn/fadeOut"}
|
||||
CASE "b": RETURN {enabled: true, style: "slide", animation: "slideLeft/slideRight"}
|
||||
CASE "c": RETURN {enabled: true, style: "zoom", animation: "zoomIn/zoomOut"}
|
||||
CASE "d": RETURN {enabled: false}
|
||||
|
||||
FUNCTION MAP_LOADING_STATES(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {style: "spinner", animation: "rotate", keyframes: "360deg"}
|
||||
CASE "b": RETURN {style: "pulse", animation: "pulse", keyframes: "opacity"}
|
||||
CASE "c": RETURN {style: "skeleton", animation: "shimmer", keyframes: "gradient-shift"}
|
||||
CASE "d": RETURN {style: "progress", animation: "fill", keyframes: "width"}
|
||||
|
||||
FUNCTION MAP_SCROLL_ANIMATIONS(option):
|
||||
SWITCH option:
|
||||
CASE "a": RETURN {enabled: true, style: "fade", animation: "fadeIn"}
|
||||
CASE "b": RETURN {enabled: true, style: "slideUp", animation: "slideUp", transform: "translateY(20px)"}
|
||||
CASE "c": RETURN {enabled: true, style: "scaleIn", animation: "scaleIn", transform: "scale(0.9)"}
|
||||
CASE "d": RETURN {enabled: true, style: "stagger", animation: "fadeIn", stagger_delay: "100ms"}
|
||||
CASE "e": RETURN {enabled: false}
|
||||
|
||||
# Write specification file
|
||||
output_path = "{base_path}/.intermediates/animation-analysis/animation-specification.json"
|
||||
Write(output_path, JSON.stringify(specification, indent=2))
|
||||
|
||||
REPORT: "✅ Animation specification saved to {output_path}"
|
||||
REPORT: " Proceeding to token synthesis..."
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Phase 2 Output**: `animation-specification.json` (user preferences)
|
||||
|
||||
## Phase 3: Animation Token Synthesis (Agent - No User Interaction)
|
||||
|
||||
**Executor**: `Task(ui-design-agent)` for token generation
|
||||
|
||||
**⚠️ CRITICAL**: This phase has NO user interaction. Agent only reads existing data and generates tokens.
|
||||
|
||||
### Step 1: Load All Input Sources
|
||||
|
||||
```bash
|
||||
# Gather all available animation data
|
||||
extracted_animations = []
|
||||
IF animations_extracted:
|
||||
FOR target IN target_list:
|
||||
IF exists({base_path}/.intermediates/animation-analysis/animations-{target}.json):
|
||||
extracted_animations.append(Read(file))
|
||||
|
||||
user_specification = null
|
||||
IF exists({base_path}/.intermediates/animation-analysis/animation-specification.json):
|
||||
user_specification = Read(file)
|
||||
REPORT: "✅ Loaded user specification from Phase 2"
|
||||
ELSE:
|
||||
REPORT: "⚠️ No user specification found - using extracted CSS only"
|
||||
|
||||
design_tokens = null
|
||||
IF has_design_context:
|
||||
design_tokens = Read({base_path}/style-extraction/style-1/design-tokens.json)
|
||||
```
|
||||
|
||||
### Step 2: Launch Token Generation Task (Pure Synthesis)
|
||||
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[ANIMATION_TOKEN_GENERATION_TASK]
|
||||
Synthesize animation data into production-ready tokens - NO user interaction
|
||||
|
||||
SESSION: {session_id} | BASE_PATH: {base_path}
|
||||
|
||||
## ⚠️ CRITICAL: Pure Synthesis Task
|
||||
- NO user questions or interaction
|
||||
- READ existing specification files ONLY
|
||||
- Generate tokens based on available data
|
||||
|
||||
## Input Sources (Read-Only)
|
||||
1. **Extracted CSS Animations** (if available):
|
||||
${extracted_animations.length > 0 ? JSON.stringify(extracted_animations) : "None - skip CSS data"}
|
||||
|
||||
2. **User Specification** (REQUIRED if Phase 2 ran):
|
||||
File: {base_path}/.intermediates/animation-analysis/animation-specification.json
|
||||
${user_specification ? "Status: ✅ Found - READ this file for user choices" : "Status: ⚠️ Not found - use CSS extraction only"}
|
||||
|
||||
3. **Design Tokens Context** (for alignment):
|
||||
${design_tokens ? JSON.stringify(design_tokens) : "None - standalone animation system"}
|
||||
|
||||
## Synthesis Rules
|
||||
|
||||
### Priority System
|
||||
1. User specification from animation-specification.json (highest priority)
|
||||
2. Extracted CSS values from animations-*.json (medium priority)
|
||||
3. Industry best practices (fallback)
|
||||
|
||||
### Duration Normalization
|
||||
- IF user_specification.timing_scale EXISTS:
|
||||
Use user's chosen scale (fast/balanced/smooth/custom)
|
||||
- ELSE IF extracted CSS durations available:
|
||||
Cluster extracted durations into 3-5 semantic scales
|
||||
- ELSE:
|
||||
Use standard scale (instant:0ms, fast:150ms, normal:300ms, slow:500ms, very-slow:800ms)
|
||||
- Align with design token spacing scale if available
|
||||
|
||||
### Easing Standardization
|
||||
- IF user_specification.easing_philosophy EXISTS:
|
||||
Use user's chosen philosophy (linear/ease-out/ease-in-out/spring)
|
||||
- ELSE IF extracted CSS easings available:
|
||||
Identify common easing functions from CSS
|
||||
- ELSE:
|
||||
Use standard easings
|
||||
- Map to semantic names and convert to cubic-bezier format
|
||||
|
||||
### Animation Categorization
|
||||
Organize into:
|
||||
- **duration**: Timing scale (instant, fast, normal, slow, very-slow)
|
||||
- **easing**: Easing functions (linear, ease-in, ease-out, ease-in-out, spring)
|
||||
- **transitions**: Property-specific transitions (color, transform, opacity, etc.)
|
||||
- **keyframes**: Named @keyframe animations (fadeIn, slideInUp, pulse, etc.)
|
||||
- **interactions**: Interaction-specific presets (button-hover, card-hover, input-focus, etc.)
|
||||
- **page_transitions**: Route/view change animations (if user enabled)
|
||||
- **scroll_animations**: Scroll-triggered animations (if user enabled)
|
||||
|
||||
### User Specification Integration
|
||||
IF user_specification EXISTS:
|
||||
- Map user choices to token values:
|
||||
* timing_scale → duration values
|
||||
* easing_philosophy → easing curves
|
||||
* interactions.button → interactions.button-hover token
|
||||
* interactions.card → interactions.card-hover token
|
||||
* interactions.input → micro-interaction tokens
|
||||
* page_transitions → page_transitions tokens
|
||||
* loading_animations → loading state tokens
|
||||
* scroll_animations → scroll_animations tokens
|
||||
|
||||
## Generate Files
|
||||
|
||||
### 1. animation-tokens.json
|
||||
Complete animation token structure using var() references:
|
||||
|
||||
{
|
||||
"duration": {
|
||||
"instant": "0ms",
|
||||
"fast": "150ms", # Adjust based on user_specification.timing_scale
|
||||
"normal": "300ms",
|
||||
"slow": "500ms",
|
||||
"very-slow": "800ms"
|
||||
},
|
||||
"easing": {
|
||||
"linear": "linear",
|
||||
"ease-in": "cubic-bezier(0.4, 0, 1, 1)",
|
||||
"ease-out": "cubic-bezier(0, 0, 0.2, 1)", # Adjust based on user_specification.easing_philosophy
|
||||
"ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
|
||||
"spring": "cubic-bezier(0.34, 1.56, 0.64, 1)"
|
||||
},
|
||||
"transitions": {
|
||||
"color": {
|
||||
"property": "color, background-color, border-color",
|
||||
"duration": "var(--duration-fast)",
|
||||
"easing": "var(--easing-ease-out)"
|
||||
},
|
||||
"transform": {
|
||||
"property": "transform",
|
||||
"duration": "var(--duration-normal)",
|
||||
"easing": "var(--easing-ease-out)"
|
||||
},
|
||||
"opacity": {
|
||||
"property": "opacity",
|
||||
"duration": "var(--duration-normal)",
|
||||
"easing": "var(--easing-ease-in-out)"
|
||||
}
|
||||
},
|
||||
"keyframes": {
|
||||
"fadeIn": {"0%": {"opacity": "0"}, "100%": {"opacity": "1"}},
|
||||
"slideInUp": {"0%": {"transform": "translateY(20px)", "opacity": "0"}, "100%": {"transform": "translateY(0)", "opacity": "1"}},
|
||||
"pulse": {"0%, 100%": {"opacity": "1"}, "50%": {"opacity": "0.7"}},
|
||||
# Add more keyframes based on user_specification choices
|
||||
},
|
||||
"interactions": {
|
||||
"button-hover": {
|
||||
# Map from user_specification.interactions.button
|
||||
"properties": ["background-color", "transform"],
|
||||
"duration": "var(--duration-fast)",
|
||||
"easing": "var(--easing-ease-out)",
|
||||
"transform": "scale(1.02)"
|
||||
},
|
||||
"card-hover": {
|
||||
# Map from user_specification.interactions.card
|
||||
"properties": ["box-shadow", "transform"],
|
||||
"duration": "var(--duration-normal)",
|
||||
"easing": "var(--easing-ease-out)",
|
||||
"transform": "translateY(-4px)"
|
||||
}
|
||||
# Add input-focus, modal-open, dropdown-toggle based on user choices
|
||||
},
|
||||
"page_transitions": {
|
||||
# IF user_specification.page_transitions.enabled == true
|
||||
"fade": {
|
||||
"duration": "var(--duration-normal)",
|
||||
"enter": "fadeIn",
|
||||
"exit": "fadeOut"
|
||||
}
|
||||
# Add slide, zoom based on user_specification.page_transitions.style
|
||||
},
|
||||
"scroll_animations": {
|
||||
# IF user_specification.scroll_animations.enabled == true
|
||||
"default": {
|
||||
"animation": "fadeIn", # From user_specification.scroll_animations.style
|
||||
"duration": "var(--duration-slow)",
|
||||
"easing": "var(--easing-ease-out)",
|
||||
"threshold": "0.1",
|
||||
"stagger_delay": "100ms" # From user_specification if stagger chosen
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### 2. animation-guide.md
|
||||
Comprehensive usage guide with sections:
|
||||
- **Animation Philosophy**: Rationale from user choices and CSS analysis
|
||||
- **Duration Scale**: Explanation of timing values and usage contexts
|
||||
- **Easing Functions**: When to use each easing curve
|
||||
- **Transition Presets**: Property-specific transition guidelines
|
||||
- **Keyframe Animations**: Available animations and use cases
|
||||
- **Interaction Patterns**: Button, card, input animation examples
|
||||
- **Page Transitions**: Route change animation implementation (if enabled)
|
||||
- **Scroll Animations**: Scroll-trigger setup and configuration (if enabled)
|
||||
- **Implementation Examples**: CSS and JavaScript code samples
|
||||
- **Accessibility**: prefers-reduced-motion media query setup
|
||||
- **Performance Best Practices**: Hardware acceleration, will-change usage
|
||||
|
||||
## Output File Paths
|
||||
- animation-tokens.json: {base_path}/animation-extraction/animation-tokens.json
|
||||
- animation-guide.md: {base_path}/animation-extraction/animation-guide.md
|
||||
|
||||
## Critical Requirements
|
||||
- ✅ READ animation-specification.json if it exists (from Phase 2)
|
||||
- ✅ Use Write() tool immediately for both files
|
||||
- ✅ All tokens use CSS Custom Property format: var(--duration-fast)
|
||||
- ✅ Include prefers-reduced-motion media query guidance
|
||||
- ✅ Validate all cubic-bezier values are valid (4 numbers between 0-1)
|
||||
- ❌ NO user questions or interaction in this phase
|
||||
- ❌ NO external research or MCP calls
|
||||
`
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Phase 3 Output**: `animation-tokens.json` + `animation-guide.md`
|
||||
|
||||
## Phase 4: Verify Output
|
||||
|
||||
### Step 1: Check Files Created
|
||||
|
||||
```bash
|
||||
# Verify animation tokens created
|
||||
bash(test -f {base_path}/animation-extraction/animation-tokens.json && echo "exists")
|
||||
bash(test -f {base_path}/animation-extraction/animation-guide.md && echo "exists")
|
||||
|
||||
# Validate structure
|
||||
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "duration" && echo "valid")
|
||||
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "easing" && echo "valid")
|
||||
```
|
||||
|
||||
### Step 2: Verify File Sizes
|
||||
|
||||
```bash
|
||||
bash(ls -lh {base_path}/animation-extraction/)
|
||||
```
|
||||
|
||||
**Output**: 2 files verified (animation-tokens.json, animation-guide.md)
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"},
|
||||
{content: "CSS animation extraction (auto mode)", status: "completed", activeForm: "Extracting from CSS"},
|
||||
{content: "Interactive specification (main flow)", status: "completed", activeForm: "Collecting user input in main flow"},
|
||||
{content: "Animation token synthesis (agent - no interaction)", status: "completed", activeForm: "Generating tokens via agent"},
|
||||
{content: "Verify output files", status: "completed", activeForm: "Verifying files"}
|
||||
]});
|
||||
```
|
||||
|
||||
### Output Message
|
||||
|
||||
```
|
||||
✅ Animation extraction complete!
|
||||
|
||||
Configuration:
|
||||
- Session: {session_id}
|
||||
- Extraction Mode: {extraction_mode} (auto/interactive)
|
||||
- Input Sources:
|
||||
{IF animations_extracted:
|
||||
- ✅ CSS extracted from {len(url_list)} URL(s)
|
||||
}
|
||||
{IF user_specification:
|
||||
- ✅ User specification via interactive mode (main flow)
|
||||
}
|
||||
{IF has_design_context:
|
||||
- ✅ Aligned with existing design tokens
|
||||
}
|
||||
|
||||
Generated Files:
|
||||
{base_path}/animation-extraction/
|
||||
├── animation-tokens.json # Production-ready animation tokens
|
||||
└── animation-guide.md # Usage guidelines and examples
|
||||
|
||||
{IF animations_extracted:
|
||||
Intermediate Analysis:
|
||||
{base_path}/.intermediates/animation-analysis/
|
||||
├── animations-*.json # Extracted CSS data ({len(url_list)} files)
|
||||
}
|
||||
{IF user_specification:
|
||||
└── animation-specification.json # User preferences
|
||||
}
|
||||
|
||||
Extracted Data Summary:
|
||||
- Duration scales: {duration_count} values
|
||||
- Easing functions: {easing_count} types
|
||||
- Interaction presets: {interaction_count} patterns
|
||||
- Keyframe animations: {keyframe_count} animations
|
||||
|
||||
Next: Animation tokens ready for integration
|
||||
• style-extract/layout-extract can reference animation tokens
|
||||
• generate command will include animation CSS
|
||||
• Tokens use var() format for easy customization
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1)
|
||||
|
||||
# Create output directories
|
||||
bash(mkdir -p {base_path}/animation-extraction)
|
||||
bash(mkdir -p {base_path}/.intermediates/animation-analysis)
|
||||
```
|
||||
|
||||
### Validation Commands
|
||||
|
||||
```bash
|
||||
# Check if already extracted
|
||||
bash(test -f {base_path}/animation-extraction/animation-tokens.json && echo "exists")
|
||||
|
||||
# Validate JSON structure
|
||||
bash(cat {base_path}/animation-extraction/animation-tokens.json | grep -q "duration" && echo "valid")
|
||||
|
||||
# Count animation types
|
||||
bash(cat animation-tokens.json | grep -c "\"keyframes\":")
|
||||
```
|
||||
|
||||
### File Operations
|
||||
|
||||
```bash
|
||||
# Load design tokens context
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && cat it)
|
||||
|
||||
# Verify output
|
||||
bash(ls {base_path}/animation-extraction/)
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
├── .intermediates/ # Intermediate analysis files
|
||||
│ └── animation-analysis/
|
||||
│ ├── animations-{target}.json # Extracted CSS (auto mode)
|
||||
│ └── animation-specification.json # User input (interactive mode)
|
||||
└── animation-extraction/ # Final animation tokens
|
||||
├── animation-tokens.json # Production-ready animation tokens
|
||||
└── animation-guide.md # Usage guide and examples
|
||||
```
|
||||
|
||||
## animation-tokens.json Format
|
||||
|
||||
```json
|
||||
{
|
||||
"duration": {
|
||||
"instant": "0ms",
|
||||
"fast": "150ms",
|
||||
"normal": "300ms",
|
||||
"slow": "500ms",
|
||||
"very-slow": "800ms"
|
||||
},
|
||||
"easing": {
|
||||
"linear": "linear",
|
||||
"ease-in": "cubic-bezier(0.4, 0, 1, 1)",
|
||||
"ease-out": "cubic-bezier(0, 0, 0.2, 1)",
|
||||
"ease-in-out": "cubic-bezier(0.4, 0, 0.2, 1)",
|
||||
"spring": "cubic-bezier(0.34, 1.56, 0.64, 1)"
|
||||
},
|
||||
"transitions": {
|
||||
"color": {"property": "...", "duration": "var(--duration-fast)", "easing": "..."},
|
||||
"transform": {"property": "...", "duration": "...", "easing": "..."}
|
||||
},
|
||||
"keyframes": {
|
||||
"fadeIn": {"0%": {...}, "100%": {...}},
|
||||
"slideInUp": {...}
|
||||
},
|
||||
"interactions": {
|
||||
"button-hover": {"properties": [...], "duration": "...", "transform": "..."},
|
||||
"card-hover": {...}
|
||||
},
|
||||
"page_transitions": {...},
|
||||
"scroll_animations": {...}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**: CSS var() format, valid cubic-bezier values, prefers-reduced-motion support
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
|
||||
```
|
||||
ERROR: No URL or interactive mode specified
|
||||
→ Provide --urls for auto mode or use --mode interactive
|
||||
|
||||
ERROR: Chrome DevTools unavailable
|
||||
→ Automatically falls back to interactive mode
|
||||
|
||||
ERROR: Insufficient animation data extracted
|
||||
→ Launches interactive mode for supplemental input
|
||||
|
||||
ERROR: Invalid cubic-bezier values
|
||||
→ Validates and corrects to nearest standard easing
|
||||
```
|
||||
|
||||
### Recovery Strategies
|
||||
|
||||
- **CSS extraction failure**: Falls back to interactive mode
|
||||
- **Partial extraction**: Supplements with interactive questioning
|
||||
- **Invalid data**: Validates and uses fallback values
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Auto-Trigger CSS Extraction** - Automatically extracts animations when --urls provided
|
||||
- **Hybrid Strategy** - Combines CSS extraction with interactive specification
|
||||
- **Main Flow Interaction** - User questions in main flow, agent only for token synthesis
|
||||
- **Intelligent Fallback** - Gracefully handles extraction failures
|
||||
- **Context-Aware** - Aligns with existing design tokens
|
||||
- **Production-Ready** - CSS var() format, accessibility support
|
||||
- **Comprehensive Coverage** - Transitions, keyframes, interactions, scroll animations
|
||||
- **Separated Concerns** - User decisions (Phase 2 main flow) → Token generation (Phase 3 agent)
|
||||
|
||||
## Integration
|
||||
|
||||
**Workflow Position**: Between style extraction and layout extraction (or parallel)
|
||||
|
||||
**New Workflow**:
|
||||
1. `/workflow:ui-design:style-extract` → `design-tokens.json` + `style-guide.md`
|
||||
2. **`/workflow:ui-design:animation-extract`** → `animation-tokens.json` + `animation-guide.md` (NEW)
|
||||
3. `/workflow:ui-design:layout-extract` → `layout-templates.json`
|
||||
4. `/workflow:ui-design:generate`:
|
||||
- Reads: design-tokens.json + animation-tokens.json + layout-templates.json
|
||||
- Generates: Prototypes with animation CSS included
|
||||
|
||||
**Input**: URLs (auto mode) or interactive questioning
|
||||
**Output**: `animation-tokens.json` + `animation-guide.md`
|
||||
**Next**: `/workflow:ui-design:layout-extract` OR `/workflow:ui-design:generate`
|
||||
|
||||
**Note**: This command extracts motion design patterns (animations, transitions) to complement visual style tokens. Can run in parallel with layout-extract.
|
||||
@@ -0,0 +1,480 @@
|
||||
---
|
||||
name: batch-generate
|
||||
description: Prompt-driven batch UI generation using target-style-centric parallel execution with design token application
|
||||
argument-hint: [--targets "<list>"] [--target-type "page|component"] [--device-type "desktop|mobile|tablet|responsive"] [--base-path <path>] [--session <id>] [--style-variants <count>] [--layout-variants <count>]
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Task(ui-design-agent), Bash(*), mcp__exa__web_search_exa(*)
|
||||
---
|
||||
|
||||
# Batch Generate UI Prototypes (/workflow:ui-design:batch-generate)
|
||||
|
||||
## Overview
|
||||
Prompt-driven UI generation with intelligent target extraction and **target-style-centric batch execution**. Each agent handles all layouts for one target × style combination.
|
||||
|
||||
**Strategy**: Prompt → Targets → Batched Generation
|
||||
- **Prompt-driven**: Describe what to build, command extracts targets
|
||||
- **Agent scope**: Each of `T × S` agents generates `L` layouts
|
||||
- **Parallel batching**: Max 6 concurrent agents for optimal throughput
|
||||
- **Component isolation**: Complete task independence
|
||||
- **Style-aware**: HTML adapts to design_attributes
|
||||
- **Self-contained CSS**: Direct token values (no var() refs)
|
||||
|
||||
**Supports**: Pages (full layouts) and components (isolated elements)
|
||||
|
||||
## Phase 1: Setup & Validation
|
||||
|
||||
### Step 1: Parse Prompt & Resolve Configuration
|
||||
```bash
|
||||
# Parse required parameters
|
||||
prompt_text = --prompt
|
||||
device_type = --device-type OR "responsive"
|
||||
|
||||
# Extract targets from prompt
|
||||
IF --targets:
|
||||
target_list = split_and_clean(--targets)
|
||||
ELSE:
|
||||
target_list = extract_targets_from_prompt(prompt_text) # See helpers
|
||||
IF NOT target_list: target_list = ["home"] # Fallback
|
||||
|
||||
# Detect target type
|
||||
target_type = --target-type OR detect_target_type(target_list)
|
||||
|
||||
# Resolve base path
|
||||
IF --base-path:
|
||||
base_path = --base-path
|
||||
ELSE IF --session:
|
||||
bash(find .workflow/WFS-{session} -type d -name "design-*" -printf "%T@ %p\n" | sort -nr | head -1 | cut -d' ' -f2)
|
||||
ELSE:
|
||||
bash(find .workflow -type d -name "design-*" -printf "%T@ %p\n" | sort -nr | head -1 | cut -d' ' -f2)
|
||||
|
||||
# Get variant counts
|
||||
style_variants = --style-variants OR bash(ls {base_path}/style-extraction/style-* -d | wc -l)
|
||||
layout_variants = --layout-variants OR 3
|
||||
```
|
||||
|
||||
**Output**: `base_path`, `target_list[]`, `target_type`, `device_type`, `style_variants`, `layout_variants`
|
||||
|
||||
### Step 2: Validate Design Tokens
|
||||
```bash
|
||||
# Check design tokens exist
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "valid")
|
||||
|
||||
# Load design space analysis (optional, from intermediates)
|
||||
IF exists({base_path}/.intermediates/style-analysis/design-space-analysis.json):
|
||||
design_space_analysis = Read({base_path}/.intermediates/style-analysis/design-space-analysis.json)
|
||||
```
|
||||
|
||||
**Output**: `design_tokens_valid`, `design_space_analysis`
|
||||
|
||||
### Step 3: Gather Layout Inspiration (Reuse or Create)
|
||||
```bash
|
||||
# Check if layout inspirations already exist from layout-extract phase
|
||||
inspiration_source = "{base_path}/.intermediates/layout-analysis/inspirations"
|
||||
|
||||
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"
|
||||
mcp__exa__web_search_exa(query=search_query, numResults=5)
|
||||
|
||||
# Extract context from prompt for this target
|
||||
target_requirements = extract_relevant_context_from_prompt(prompt_text, target)
|
||||
|
||||
# Write inspiration file to centralized location
|
||||
Write({inspiration_source}/{target}-layout-ideas.txt, inspiration_content)
|
||||
REPORT: "Created new layout inspiration for {target}"
|
||||
```
|
||||
|
||||
**Output**: `T` inspiration text files (reused or created in `.intermediates/layout-analysis/inspirations/`)
|
||||
|
||||
## Phase 2: Target-Style-Centric Batch Generation (Agent)
|
||||
|
||||
**Executor**: `Task(ui-design-agent)` × `T × S` tasks in **batched parallel** (max 6 concurrent)
|
||||
|
||||
### Step 1: Calculate Batch Execution Plan
|
||||
```bash
|
||||
bash(mkdir -p {base_path}/prototypes)
|
||||
|
||||
# Build task list: T × S combinations
|
||||
MAX_PARALLEL = 6
|
||||
total_tasks = T × S
|
||||
total_batches = ceil(total_tasks / MAX_PARALLEL)
|
||||
|
||||
# Initialize batch tracking
|
||||
TodoWrite({todos: [
|
||||
{content: "Batch 1/{batches}: Generate 6 tasks", status: "in_progress"},
|
||||
{content: "Batch 2/{batches}: Generate 6 tasks", status: "pending"},
|
||||
...
|
||||
]})
|
||||
```
|
||||
|
||||
### Step 2: Launch Batched Agent Tasks
|
||||
For each batch (up to 6 parallel tasks):
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[TARGET_STYLE_UI_GENERATION_FROM_PROMPT]
|
||||
🎯 ONE component: {target} × Style-{style_id} ({philosophy_name})
|
||||
Generate: {layout_variants} × 2 files (HTML + CSS per layout)
|
||||
|
||||
PROMPT CONTEXT: {target_requirements} # Extracted from original prompt
|
||||
TARGET: {target} | TYPE: {target_type} | STYLE: {style_id}/{style_variants}
|
||||
BASE_PATH: {base_path}
|
||||
DEVICE: {device_type}
|
||||
${design_attributes ? "DESIGN_ATTRIBUTES: " + JSON.stringify(design_attributes) : ""}
|
||||
|
||||
## Reference
|
||||
- Layout inspiration: Read("{base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt")
|
||||
- Design tokens: Read("{base_path}/style-extraction/style-{style_id}/design-tokens.json")
|
||||
Parse ALL token values including:
|
||||
* colors, typography (with combinations), spacing, opacity
|
||||
* border_radius, shadows, breakpoints
|
||||
* component_styles (button, card, input variants)
|
||||
${design_attributes ? "- Adapt DOM to: density, visual_weight, formality, organic_vs_geometric" : ""}
|
||||
|
||||
## Generation
|
||||
For EACH layout (1 to {layout_variants}):
|
||||
|
||||
1. HTML: {base_path}/prototypes/{target}-style-{style_id}-layout-N.html
|
||||
- Complete HTML5: <!DOCTYPE>, <head>, <body>
|
||||
- CSS ref: <link href="{target}-style-{style_id}-layout-N.css">
|
||||
- Semantic: <header>, <nav>, <main>, <footer>
|
||||
- A11y: ARIA labels, landmarks, responsive meta
|
||||
- Viewport: <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
- Follow user requirements from prompt
|
||||
${design_attributes ? `
|
||||
- DOM adaptation:
|
||||
* density='spacious' → flatter hierarchy
|
||||
* density='compact' → deeper nesting
|
||||
* visual_weight='heavy' → extra wrappers
|
||||
* visual_weight='minimal' → direct structure` : ""}
|
||||
- Device-specific: Optimize for {device_type}
|
||||
|
||||
2. CSS: {base_path}/prototypes/{target}-style-{style_id}-layout-N.css
|
||||
- Self-contained: Direct token VALUES (no var())
|
||||
- Use tokens: colors, fonts, spacing, opacity, borders, shadows
|
||||
- IF tokens.component_styles exists: Use component presets for buttons, cards, inputs
|
||||
- IF tokens.typography.combinations exists: Use typography presets for headings and body text
|
||||
- Device-optimized: {device_type} styles
|
||||
${device_type === 'responsive' ? '- Responsive: Mobile-first @media' : '- Fixed: ' + device_type}
|
||||
${design_attributes ? `
|
||||
- Token selection: density → spacing, visual_weight → shadows` : ""}
|
||||
|
||||
## Notes
|
||||
- ✅ Token VALUES directly from design-tokens.json (with typography.combinations, opacity, component_styles support)
|
||||
- ✅ Follow prompt requirements for {target}
|
||||
- ✅ Optimize for {device_type}
|
||||
- ❌ NO var() refs, NO external deps
|
||||
- Layouts structurally DISTINCT
|
||||
- Write files IMMEDIATELY (per layout)
|
||||
- CSS filename MUST match HTML <link href>
|
||||
`
|
||||
|
||||
# After each batch completes
|
||||
TodoWrite: Mark batch completed, next batch in_progress
|
||||
```
|
||||
|
||||
## Phase 3: Verify & Generate Previews
|
||||
|
||||
### Step 1: Verify Generated Files
|
||||
```bash
|
||||
# Count expected vs found
|
||||
bash(ls {base_path}/prototypes/{target}-style-*-layout-*.html | wc -l)
|
||||
# Expected: S × L × T × 2
|
||||
|
||||
# Validate samples
|
||||
Read({base_path}/prototypes/{target}-style-{style_id}-layout-{layout_id}.html)
|
||||
# Check: <!DOCTYPE html>, correct CSS href, sufficient CSS length
|
||||
```
|
||||
|
||||
**Output**: `S × L × T × 2` files verified
|
||||
|
||||
### Step 2: Run Preview Generation Script
|
||||
```bash
|
||||
bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes")
|
||||
```
|
||||
|
||||
**Script generates**:
|
||||
- `compare.html` (interactive matrix)
|
||||
- `index.html` (navigation)
|
||||
- `PREVIEW.md` (instructions)
|
||||
|
||||
### Step 3: Verify Preview Files
|
||||
```bash
|
||||
bash(ls {base_path}/prototypes/compare.html {base_path}/prototypes/index.html {base_path}/prototypes/PREVIEW.md)
|
||||
```
|
||||
|
||||
**Output**: 3 preview files
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Setup and parse prompt", status: "completed", activeForm: "Parsing prompt"},
|
||||
{content: "Detect token sources", status: "completed", activeForm: "Loading design systems"},
|
||||
{content: "Gather layout inspiration", status: "completed", activeForm: "Researching layouts"},
|
||||
{content: "Batch 1/{batches}: Generate 6 tasks", status: "completed", activeForm: "Generating batch 1"},
|
||||
... (all batches completed)
|
||||
{content: "Verify files & generate previews", status: "completed", activeForm: "Creating previews"}
|
||||
]});
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ Prompt-driven batch UI generation complete!
|
||||
|
||||
Prompt: {prompt_text}
|
||||
|
||||
Configuration:
|
||||
- Style Variants: {style_variants}
|
||||
- Layout Variants: {layout_variants}
|
||||
- Target Type: {target_type}
|
||||
- Device Type: {device_type}
|
||||
- Targets: {target_list} ({T} targets)
|
||||
- Total Prototypes: {S × L × T}
|
||||
|
||||
Batch Execution:
|
||||
- Total tasks: {T × S} (targets × styles)
|
||||
- Batches: {batches} (max 6 parallel per batch)
|
||||
- Agent scope: {L} layouts per target×style
|
||||
- Component isolation: Complete task independence
|
||||
- Device-specific: All layouts optimized for {device_type}
|
||||
|
||||
Quality:
|
||||
- Style-aware: {design_space_analysis ? 'HTML adapts to design_attributes' : 'Standard structure'}
|
||||
- CSS: Self-contained (direct token values, no var())
|
||||
- Device-optimized: {device_type} layouts
|
||||
- Tokens: Production-ready (WCAG AA compliant)
|
||||
|
||||
Generated Files:
|
||||
{base_path}/prototypes/
|
||||
├── {target}-style-{s}-layout-{l}.html ({S×L×T} prototypes)
|
||||
├── {target}-style-{s}-layout-{l}.css
|
||||
├── compare.html (interactive matrix)
|
||||
├── index.html (navigation)
|
||||
└── PREVIEW.md (instructions)
|
||||
|
||||
Layout Inspirations:
|
||||
{base_path}/.intermediates/layout-analysis/inspirations/ ({T} text files, reused or created)
|
||||
|
||||
Preview:
|
||||
1. Open compare.html (recommended)
|
||||
2. Open index.html
|
||||
3. Read PREVIEW.md
|
||||
|
||||
Next: /workflow:ui-design:update
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" -printf "%T@ %p\n" | sort -nr | head -1 | cut -d' ' -f2)
|
||||
|
||||
# Count style variants
|
||||
bash(ls {base_path}/style-extraction/style-* -d | wc -l)
|
||||
|
||||
# Check design tokens exist
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "valid")
|
||||
```
|
||||
|
||||
### Validation Commands
|
||||
```bash
|
||||
# Count generated files
|
||||
bash(ls {base_path}/prototypes/{target}-style-*-layout-*.html | wc -l)
|
||||
|
||||
# Verify preview
|
||||
bash(test -f {base_path}/prototypes/compare.html && echo "exists")
|
||||
```
|
||||
|
||||
### File Operations
|
||||
```bash
|
||||
# Create prototypes directory
|
||||
bash(mkdir -p {base_path}/prototypes)
|
||||
|
||||
# Create inspirations directory (if needed)
|
||||
bash(mkdir -p {base_path}/.intermediates/layout-analysis/inspirations)
|
||||
|
||||
# Run preview script
|
||||
bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes")
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
├── .intermediates/
|
||||
│ └── layout-analysis/
|
||||
│ └── inspirations/
|
||||
│ └── {target}-layout-ideas.txt # Layout inspiration (reused or created)
|
||||
├── prototypes/
|
||||
│ ├── {target}-style-{s}-layout-{l}.html # Final prototypes
|
||||
│ ├── {target}-style-{s}-layout-{l}.css
|
||||
│ ├── compare.html
|
||||
│ ├── index.html
|
||||
│ └── PREVIEW.md
|
||||
└── style-extraction/
|
||||
└── style-{s}/
|
||||
├── design-tokens.json
|
||||
└── style-guide.md
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: No design tokens found
|
||||
→ Run /workflow:ui-design:style-extract first
|
||||
|
||||
ERROR: No targets extracted from prompt
|
||||
→ Use --targets explicitly or rephrase prompt
|
||||
|
||||
ERROR: MCP search failed
|
||||
→ Check network, retry
|
||||
|
||||
ERROR: Batch {N} agent tasks failed
|
||||
→ Check agent output, retry specific target×style combinations
|
||||
|
||||
ERROR: Script permission denied
|
||||
→ chmod +x ~/.claude/scripts/ui-generate-preview.sh
|
||||
```
|
||||
|
||||
### Recovery Strategies
|
||||
- **Partial success**: Keep successful target×style combinations
|
||||
- **Missing design_attributes**: Works without (less style-aware)
|
||||
- **Invalid tokens**: Validate design-tokens.json structure
|
||||
- **Failed batch**: Re-run command, only failed combinations will retry
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] Prompt clearly describes targets
|
||||
- [ ] CSS uses direct token values (no var())
|
||||
- [ ] HTML adapts to design_attributes (if available)
|
||||
- [ ] Semantic HTML5 structure
|
||||
- [ ] ARIA attributes present
|
||||
- [ ] Device-optimized layouts
|
||||
- [ ] Layouts structurally distinct
|
||||
- [ ] compare.html works
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Prompt-Driven**: Describe what to build, command extracts targets
|
||||
- **Target-Style-Centric**: `T×S` agents, each handles `L` layouts
|
||||
- **Parallel Batching**: Max 6 concurrent agents with progress tracking
|
||||
- **Component Isolation**: Complete task independence
|
||||
- **Style-Aware**: HTML adapts to design_attributes
|
||||
- **Self-Contained CSS**: Direct token values (no var())
|
||||
- **Device-Specific**: Optimized for desktop/mobile/tablet/responsive
|
||||
- **Inspiration-Based**: MCP-powered layout research
|
||||
- **Production-Ready**: Semantic, accessible, responsive
|
||||
|
||||
## Integration
|
||||
|
||||
**Input**:
|
||||
- Required: Prompt, design-tokens.json
|
||||
- Optional: design-space-analysis.json (from `.intermediates/style-analysis/`)
|
||||
- Reuses: Layout inspirations from `.intermediates/layout-analysis/inspirations/` (if available from layout-extract)
|
||||
|
||||
**Output**: S×L×T prototypes for `/workflow:ui-design:update`
|
||||
**Compatible**: style-extract, explore-auto, imitate-auto outputs
|
||||
**Optimization**: Reuses layout inspirations from layout-extract phase, avoiding duplicate MCP searches
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic: Auto-detection
|
||||
```bash
|
||||
/workflow:ui-design:batch-generate \
|
||||
--prompt "Dashboard with metric cards and charts"
|
||||
|
||||
# Auto: latest design run, extracts "dashboard" target
|
||||
# Output: S × L × 1 prototypes
|
||||
```
|
||||
|
||||
### With Session
|
||||
```bash
|
||||
/workflow:ui-design:batch-generate \
|
||||
--prompt "Auth pages: login, signup, password reset" \
|
||||
--session WFS-auth
|
||||
|
||||
# Uses WFS-auth's design run
|
||||
# Extracts: ["login", "signup", "password-reset"]
|
||||
# Batches: 2 (if S=3: 9 tasks = 6+3)
|
||||
# Output: S × L × 3 prototypes
|
||||
```
|
||||
|
||||
### Components with Device Type
|
||||
```bash
|
||||
/workflow:ui-design:batch-generate \
|
||||
--prompt "Mobile UI components: navbar, card, footer" \
|
||||
--target-type component \
|
||||
--device-type mobile
|
||||
|
||||
# Mobile-optimized component generation
|
||||
# Output: S × L × 3 prototypes
|
||||
```
|
||||
|
||||
### Large Scale (Multi-batch)
|
||||
```bash
|
||||
/workflow:ui-design:batch-generate \
|
||||
--prompt "E-commerce site" \
|
||||
--targets "home,shop,product,cart,checkout" \
|
||||
--style-variants 4 \
|
||||
--layout-variants 2
|
||||
|
||||
# Tasks: 5 × 4 = 20 (4 batches: 6+6+6+2)
|
||||
# Output: 4 × 2 × 5 = 40 prototypes
|
||||
```
|
||||
|
||||
## Helper Functions Reference
|
||||
|
||||
### Target Extraction
|
||||
```python
|
||||
# extract_targets_from_prompt(prompt_text)
|
||||
# Patterns: "Create X and Y", "Generate X, Y, Z pages", "Build X"
|
||||
# Returns: ["x", "y", "z"] (normalized lowercase with hyphens)
|
||||
|
||||
# detect_target_type(target_list)
|
||||
# Keywords: page (home, dashboard, login) vs component (navbar, card, button)
|
||||
# Returns: "page" or "component"
|
||||
|
||||
# extract_relevant_context_from_prompt(prompt_text, target)
|
||||
# Extracts sentences mentioning specific target
|
||||
# Returns: Relevant context string
|
||||
```
|
||||
|
||||
## Batch Execution Details
|
||||
|
||||
### Parallel Control
|
||||
- **Max concurrent**: 6 agents per batch
|
||||
- **Task distribution**: T × S tasks = ceil(T×S/6) batches
|
||||
- **Progress tracking**: TodoWrite per-batch status
|
||||
- **Examples**:
|
||||
- 3 tasks → 1 batch
|
||||
- 9 tasks → 2 batches (6+3)
|
||||
- 20 tasks → 4 batches (6+6+6+2)
|
||||
|
||||
### Performance
|
||||
| Tasks | Batches | Est. Time | Efficiency |
|
||||
|-------|---------|-----------|------------|
|
||||
| 1-6 | 1 | 3-5 min | 100% |
|
||||
| 7-12 | 2 | 6-10 min | ~85% |
|
||||
| 13-18 | 3 | 9-15 min | ~80% |
|
||||
| 19-30 | 4-5 | 12-25 min | ~75% |
|
||||
|
||||
### Optimization Tips
|
||||
1. **Reduce tasks**: Fewer targets or styles
|
||||
2. **Adjust layouts**: L=2 instead of L=3 for faster iteration
|
||||
3. **Stage generation**: Core pages first, secondary pages later
|
||||
|
||||
## Notes
|
||||
|
||||
- **Prompt quality**: Clear descriptions improve target extraction
|
||||
- **Token sources**: Consolidated (production) or proposed (fast-track)
|
||||
- **Batch parallelism**: Max 6 concurrent for stability
|
||||
- **Scalability**: Tested up to 30+ tasks (5+ batches)
|
||||
- **Dependencies**: MCP web search, ui-generate-preview.sh script
|
||||
@@ -0,0 +1,361 @@
|
||||
---
|
||||
name: capture
|
||||
description: Batch screenshot capture for UI design workflows using MCP puppeteer or local fallback with URL mapping
|
||||
argument-hint: --url-map "target:url,..." [--base-path path] [--session id]
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Bash(*), Glob(*), ListMcpResourcesTool(*), mcp__chrome-devtools__*, mcp__playwright__*
|
||||
---
|
||||
|
||||
# Batch Screenshot Capture (/workflow:ui-design:capture)
|
||||
|
||||
## Overview
|
||||
Batch screenshot tool with MCP-first strategy and multi-tier fallback. Processes multiple URLs in parallel.
|
||||
|
||||
**Strategy**: MCP → Playwright → Chrome → Manual
|
||||
**Output**: Flat structure `screenshots/{target}.png`
|
||||
|
||||
## Phase 1: Initialize & Parse
|
||||
|
||||
### Step 1: Determine Base Path
|
||||
```bash
|
||||
# Priority: --base-path > session > standalone
|
||||
bash(if [ -n "$BASE_PATH" ]; then
|
||||
echo "$BASE_PATH"
|
||||
elif [ -n "$SESSION_ID" ]; then
|
||||
find .workflow/WFS-$SESSION_ID/design-* -type d | head -1 || \
|
||||
echo ".workflow/WFS-$SESSION_ID/design-run-$(date +%Y%m%d-%H%M%S)"
|
||||
else
|
||||
echo ".workflow/.design/run-$(date +%Y%m%d-%H%M%S)"
|
||||
fi)
|
||||
|
||||
bash(mkdir -p $BASE_PATH/screenshots)
|
||||
```
|
||||
|
||||
### Step 2: Parse URL Map
|
||||
```javascript
|
||||
// Input: "home:https://linear.app, pricing:https://linear.app/pricing"
|
||||
url_entries = []
|
||||
|
||||
FOR pair IN split(params["--url-map"], ","):
|
||||
parts = pair.split(":", 1)
|
||||
|
||||
IF len(parts) != 2:
|
||||
ERROR: "Invalid format: {pair}. Expected: 'target:url'"
|
||||
EXIT 1
|
||||
|
||||
target = parts[0].strip().lower().replace(" ", "-")
|
||||
url = parts[1].strip()
|
||||
|
||||
// Validate target name
|
||||
IF NOT regex_match(target, r"^[a-z0-9][a-z0-9_-]*$"):
|
||||
ERROR: "Invalid target: {target}"
|
||||
EXIT 1
|
||||
|
||||
// Add https:// if missing
|
||||
IF NOT url.startswith("http"):
|
||||
url = f"https://{url}"
|
||||
|
||||
url_entries.append({target, url})
|
||||
```
|
||||
|
||||
**Output**: `base_path`, `url_entries[]`
|
||||
|
||||
### Step 3: Initialize Todos
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Parse url-map", status: "completed", activeForm: "Parsing"},
|
||||
{content: "Detect MCP tools", status: "in_progress", activeForm: "Detecting"},
|
||||
{content: "Capture screenshots", status: "pending", activeForm: "Capturing"},
|
||||
{content: "Verify results", status: "pending", activeForm: "Verifying"}
|
||||
]})
|
||||
```
|
||||
|
||||
## Phase 2: Detect Screenshot Tools
|
||||
|
||||
### Step 1: Check MCP Availability
|
||||
```javascript
|
||||
// List available MCP servers
|
||||
all_resources = ListMcpResourcesTool()
|
||||
available_servers = unique([r.server for r in all_resources])
|
||||
|
||||
// Check Chrome DevTools MCP
|
||||
chrome_devtools = "chrome-devtools" IN available_servers
|
||||
chrome_screenshot = check_tool_exists("mcp__chrome-devtools__take_screenshot")
|
||||
|
||||
// Check Playwright MCP
|
||||
playwright_mcp = "playwright" IN available_servers
|
||||
playwright_screenshot = check_tool_exists("mcp__playwright__screenshot")
|
||||
|
||||
// Determine primary tool
|
||||
IF chrome_devtools AND chrome_screenshot:
|
||||
tool = "chrome-devtools"
|
||||
ELSE IF playwright_mcp AND playwright_screenshot:
|
||||
tool = "playwright"
|
||||
ELSE:
|
||||
tool = null
|
||||
```
|
||||
|
||||
**Output**: `tool` (chrome-devtools | playwright | null)
|
||||
|
||||
### Step 2: Check Local Fallback
|
||||
```bash
|
||||
# Only if MCP unavailable
|
||||
bash(which playwright 2>/dev/null || echo "")
|
||||
bash(which google-chrome || which chrome || which chromium 2>/dev/null || echo "")
|
||||
```
|
||||
|
||||
**Output**: `local_tools[]`
|
||||
|
||||
## Phase 3: Capture Screenshots
|
||||
|
||||
### Screenshot Format Options
|
||||
|
||||
**PNG Format** (default, lossless):
|
||||
- **Pros**: Lossless quality, best for detailed UI screenshots
|
||||
- **Cons**: Larger file sizes (typically 200-500 KB per screenshot)
|
||||
- **Parameters**: `format: "png"` (no quality parameter)
|
||||
- **Use case**: High-fidelity UI replication, design system extraction
|
||||
|
||||
**WebP Format** (optional, lossy/lossless):
|
||||
- **Pros**: Smaller file sizes with good quality (50-70% smaller than PNG)
|
||||
- **Cons**: Requires quality parameter, slight quality loss at high compression
|
||||
- **Parameters**: `format: "webp", quality: 90` (80-100 recommended)
|
||||
- **Use case**: Batch captures, network-constrained environments
|
||||
|
||||
**JPEG Format** (optional, lossy):
|
||||
- **Pros**: Smallest file sizes
|
||||
- **Cons**: Lossy compression, not recommended for UI screenshots
|
||||
- **Parameters**: `format: "jpeg", quality: 90`
|
||||
- **Use case**: Photo-heavy pages, not recommended for UI design
|
||||
|
||||
### Step 1: MCP Capture (If Available)
|
||||
```javascript
|
||||
IF tool == "chrome-devtools":
|
||||
// Get or create page
|
||||
pages = mcp__chrome-devtools__list_pages()
|
||||
|
||||
IF pages.length == 0:
|
||||
mcp__chrome-devtools__new_page({url: url_entries[0].url})
|
||||
page_idx = 0
|
||||
ELSE:
|
||||
page_idx = 0
|
||||
|
||||
mcp__chrome-devtools__select_page({pageIdx: page_idx})
|
||||
|
||||
// Capture each URL
|
||||
FOR entry IN url_entries:
|
||||
mcp__chrome-devtools__navigate_page({url: entry.url, timeout: 30000})
|
||||
bash(sleep 2)
|
||||
|
||||
// PNG format doesn't support quality parameter
|
||||
// Use PNG for lossless quality (larger files)
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
fullPage: true,
|
||||
format: "png",
|
||||
filePath: f"{base_path}/screenshots/{entry.target}.png"
|
||||
})
|
||||
|
||||
// Alternative: Use WebP with quality for smaller files
|
||||
// mcp__chrome-devtools__take_screenshot({
|
||||
// fullPage: true,
|
||||
// format: "webp",
|
||||
// quality: 90,
|
||||
// filePath: f"{base_path}/screenshots/{entry.target}.webp"
|
||||
// })
|
||||
|
||||
ELSE IF tool == "playwright":
|
||||
FOR entry IN url_entries:
|
||||
mcp__playwright__screenshot({
|
||||
url: entry.url,
|
||||
output_path: f"{base_path}/screenshots/{entry.target}.png",
|
||||
full_page: true,
|
||||
timeout: 30000
|
||||
})
|
||||
```
|
||||
|
||||
### Step 2: Local Fallback (If MCP Failed)
|
||||
```bash
|
||||
# Try Playwright CLI
|
||||
bash(playwright screenshot "$url" "$output_file" --full-page --timeout 30000)
|
||||
|
||||
# Try Chrome headless
|
||||
bash($chrome --headless --screenshot="$output_file" --window-size=1920,1080 "$url")
|
||||
```
|
||||
|
||||
### Step 3: Manual Mode (If All Failed)
|
||||
```
|
||||
⚠️ Manual Screenshot Required
|
||||
|
||||
Failed URLs:
|
||||
home: https://linear.app
|
||||
Save to: .workflow/.design/run-20250110/screenshots/home.png
|
||||
|
||||
Steps:
|
||||
1. Visit URL in browser
|
||||
2. Take full-page screenshot
|
||||
3. Save to path above
|
||||
4. Type 'ready' to continue
|
||||
|
||||
Options: ready | skip | abort
|
||||
```
|
||||
|
||||
## Phase 4: Verification
|
||||
|
||||
### Step 1: Scan Captured Files
|
||||
```bash
|
||||
bash(ls -1 $base_path/screenshots/*.{png,jpg,jpeg,webp} 2>/dev/null)
|
||||
bash(du -h $base_path/screenshots/*.png 2>/dev/null)
|
||||
```
|
||||
|
||||
### Step 2: Generate Metadata
|
||||
```javascript
|
||||
captured_files = Glob(f"{base_path}/screenshots/*.{{png,jpg,jpeg,webp}}")
|
||||
captured_targets = [basename_no_ext(f) for f in captured_files]
|
||||
|
||||
metadata = {
|
||||
"timestamp": current_timestamp(),
|
||||
"total_requested": len(url_entries),
|
||||
"total_captured": len(captured_targets),
|
||||
"screenshots": []
|
||||
}
|
||||
|
||||
FOR entry IN url_entries:
|
||||
is_captured = entry.target IN captured_targets
|
||||
|
||||
metadata.screenshots.append({
|
||||
"target": entry.target,
|
||||
"url": entry.url,
|
||||
"captured": is_captured,
|
||||
"path": f"{base_path}/screenshots/{entry.target}.png" IF is_captured ELSE null,
|
||||
"size_kb": file_size_kb IF is_captured ELSE null
|
||||
})
|
||||
|
||||
Write(f"{base_path}/screenshots/capture-metadata.json", JSON.stringify(metadata))
|
||||
```
|
||||
|
||||
**Output**: `capture-metadata.json`
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Parse url-map", status: "completed", activeForm: "Parsing"},
|
||||
{content: "Detect MCP tools", status: "completed", activeForm: "Detecting"},
|
||||
{content: "Capture screenshots", status: "completed", activeForm: "Capturing"},
|
||||
{content: "Verify results", status: "completed", activeForm: "Verifying"}
|
||||
]})
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ Batch screenshot capture complete!
|
||||
|
||||
Summary:
|
||||
- Requested: {total_requested}
|
||||
- Captured: {total_captured}
|
||||
- Success rate: {success_rate}%
|
||||
- Method: {tool || "Local fallback"}
|
||||
|
||||
Output:
|
||||
{base_path}/screenshots/
|
||||
├── home.png (245.3 KB)
|
||||
├── pricing.png (198.7 KB)
|
||||
└── capture-metadata.json
|
||||
|
||||
Next: /workflow:ui-design:extract --images "screenshots/*.png"
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1)
|
||||
|
||||
# Create screenshot directory
|
||||
bash(mkdir -p $BASE_PATH/screenshots)
|
||||
```
|
||||
|
||||
### Tool Detection
|
||||
```bash
|
||||
# Check MCP
|
||||
all_resources = ListMcpResourcesTool()
|
||||
|
||||
# Check local tools
|
||||
bash(which playwright 2>/dev/null)
|
||||
bash(which google-chrome 2>/dev/null)
|
||||
```
|
||||
|
||||
### Verification
|
||||
```bash
|
||||
# List captures
|
||||
bash(ls -1 $base_path/screenshots/*.png 2>/dev/null)
|
||||
|
||||
# File sizes
|
||||
bash(du -h $base_path/screenshots/*.png)
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
└── screenshots/
|
||||
├── home.png
|
||||
├── pricing.png
|
||||
├── about.png
|
||||
└── capture-metadata.json
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: Invalid url-map format
|
||||
→ Use: "target:url, target2:url2"
|
||||
|
||||
ERROR: png screenshots do not support 'quality'
|
||||
→ PNG format is lossless, no quality parameter needed
|
||||
→ Remove quality parameter OR switch to webp/jpeg format
|
||||
|
||||
ERROR: MCP unavailable
|
||||
→ Using local fallback
|
||||
|
||||
ERROR: All tools failed
|
||||
→ Manual mode activated
|
||||
```
|
||||
|
||||
### Format-Specific Errors
|
||||
```
|
||||
❌ Wrong: format: "png", quality: 90
|
||||
✅ Right: format: "png"
|
||||
|
||||
✅ Or use: format: "webp", quality: 90
|
||||
✅ Or use: format: "jpeg", quality: 90
|
||||
```
|
||||
|
||||
### Recovery
|
||||
- **Partial success**: Keep successful captures
|
||||
- **Retry**: Re-run with failed targets only
|
||||
- **Manual**: Follow interactive guidance
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] All requested URLs processed
|
||||
- [ ] File sizes > 1KB (valid images)
|
||||
- [ ] Metadata JSON generated
|
||||
- [ ] No missing targets (or documented)
|
||||
|
||||
## Key Features
|
||||
|
||||
- **MCP-first**: Prioritize managed tools
|
||||
- **Multi-tier fallback**: 4 layers (MCP → Local → Manual)
|
||||
- **Batch processing**: Parallel capture
|
||||
- **Error tolerance**: Partial failures handled
|
||||
- **Structured output**: Flat, predictable
|
||||
|
||||
## Integration
|
||||
|
||||
**Input**: `--url-map` (multiple target:url pairs)
|
||||
**Output**: `screenshots/*.png` + `capture-metadata.json`
|
||||
**Called by**: `/workflow:ui-design:imitate-auto`, `/workflow:ui-design:explore-auto`
|
||||
**Next**: `/workflow:ui-design:extract` or `/workflow:ui-design:explore-layers`
|
||||
@@ -0,0 +1,494 @@
|
||||
---
|
||||
name: explore-auto
|
||||
description: Exploratory UI design workflow with style-centric batch generation, creates design variants from prompts/images with parallel execution
|
||||
argument-hint: "[--prompt "<desc>"] [--images "<glob>"] [--targets "<list>"] [--target-type "page|component"] [--session <id>] [--style-variants <count>] [--layout-variants <count>] [--batch-plan]""
|
||||
allowed-tools: SlashCommand(*), TodoWrite(*), Read(*), Bash(*), Glob(*), Write(*), Task(conceptual-planning-agent)
|
||||
---
|
||||
|
||||
# UI Design Auto Workflow Command
|
||||
|
||||
## Overview & Execution Model
|
||||
|
||||
**Fully autonomous orchestrator**: Executes all design phases sequentially from style extraction to design integration, with optional batch planning.
|
||||
|
||||
**Unified Target System**: Generates `style_variants × layout_variants × targets` prototypes, where targets can be:
|
||||
- **Pages** (full-page layouts): home, dashboard, settings, etc.
|
||||
- **Components** (isolated UI elements): navbar, card, hero, form, etc.
|
||||
- **Mixed**: Can combine both in a single workflow
|
||||
|
||||
**Autonomous Flow** (⚠️ CONTINUOUS EXECUTION - DO NOT STOP):
|
||||
1. User triggers: `/workflow:ui-design:explore-auto [params]`
|
||||
2. Phase 0c: Target confirmation → User confirms → **IMMEDIATELY triggers Phase 1**
|
||||
3. Phase 1 (style-extract) → **WAIT for completion** → Auto-continues
|
||||
4. Phase 2.3 (animation-extract, optional) → **WAIT for completion** → Auto-continues
|
||||
5. Phase 2.5 (layout-extract) → **WAIT for completion** → Auto-continues
|
||||
6. **Phase 3 (ui-assembly)** → **WAIT for completion** → Auto-continues
|
||||
7. Phase 4 (design-update) → **WAIT for completion** → Auto-continues
|
||||
8. Phase 5 (batch-plan, optional) → Reports completion
|
||||
|
||||
**Phase Transition Mechanism**:
|
||||
- **Phase 0c (User Interaction)**: User confirms targets → IMMEDIATELY triggers Phase 1
|
||||
- **Phase 1-5 (Autonomous)**: `SlashCommand` is BLOCKING - execution pauses until completion
|
||||
- Upon each phase completion: Automatically process output and execute next phase
|
||||
- No additional user interaction after Phase 0c confirmation
|
||||
|
||||
**Auto-Continue Mechanism**: TodoWrite tracks phase status. Upon each phase completion, you MUST immediately construct and execute the next phase command. No user intervention required. The workflow is NOT complete until reaching Phase 4 (or Phase 5 if --batch-plan).
|
||||
|
||||
**Target Type Detection**: Automatically inferred from prompt/targets, or explicitly set via `--target-type`.
|
||||
|
||||
## Core Rules
|
||||
|
||||
1. **Start Immediately**: TodoWrite initialization → Phase 1 execution
|
||||
2. **No Preliminary Validation**: Sub-commands handle their own validation
|
||||
3. **Parse & Pass**: Extract data from each output for next phase
|
||||
4. **Default to All**: When selecting variants/prototypes, use ALL generated items
|
||||
5. **Track Progress**: Update TodoWrite after each phase
|
||||
6. **⚠️ CRITICAL: DO NOT STOP** - This is a continuous multi-phase workflow. After each SlashCommand completes, you MUST wait for completion, then immediately execute the next phase. Workflow is NOT complete until Phase 4 (or Phase 5 if --batch-plan).
|
||||
|
||||
## Parameter Requirements
|
||||
|
||||
**Optional Parameters** (all have smart defaults):
|
||||
- `--targets "<list>"`: Comma-separated targets (pages/components) to generate (inferred from prompt/session if omitted)
|
||||
- `--target-type "page|component|auto"`: Explicitly set target type (default: `auto` - intelligent detection)
|
||||
- `--device-type "desktop|mobile|tablet|responsive|auto"`: Device type for layout optimization (default: `auto` - intelligent detection)
|
||||
- **Desktop**: 1920×1080px - Mouse-driven, spacious layouts
|
||||
- **Mobile**: 375×812px - Touch-friendly, compact layouts
|
||||
- **Tablet**: 768×1024px - Hybrid touch/mouse layouts
|
||||
- **Responsive**: 1920×1080px base with mobile-first breakpoints
|
||||
- `--session <id>`: Workflow session ID (standalone mode if omitted)
|
||||
- `--images "<glob>"`: Reference image paths (default: `design-refs/*`)
|
||||
- `--prompt "<description>"`: Design style and target description
|
||||
- `--style-variants <count>`: Style variants (default: inferred from prompt or 3, range: 1-5)
|
||||
- `--layout-variants <count>`: Layout variants per style (default: inferred or 3, range: 1-5)
|
||||
- `--batch-plan`: Auto-generate implementation tasks after design-update
|
||||
|
||||
**Legacy Parameters** (maintained for backward compatibility):
|
||||
- `--pages "<list>"`: Alias for `--targets` with `--target-type page`
|
||||
- `--components "<list>"`: Alias for `--targets` with `--target-type component`
|
||||
|
||||
**Input Rules**:
|
||||
- Must provide at least one: `--images` or `--prompt` or `--targets`
|
||||
- Multiple parameters can be combined for guided analysis
|
||||
- If `--targets` not provided, intelligently inferred from prompt/session
|
||||
|
||||
**Supported Target Types**:
|
||||
- **Pages** (full layouts): home, dashboard, settings, profile, login, etc.
|
||||
- **Components** (UI elements):
|
||||
- Navigation: navbar, header, menu, breadcrumb, tabs, sidebar
|
||||
- Content: hero, card, list, table, grid, timeline
|
||||
- Input: form, search, filter, input-group
|
||||
- Feedback: modal, alert, toast, badge, progress
|
||||
- Media: gallery, carousel, video-player, image-card
|
||||
- Other: footer, pagination, dropdown, tooltip, avatar
|
||||
|
||||
**Intelligent Prompt Parsing**: Extracts variant counts from natural language:
|
||||
- "Generate **3 style variants**" → `--style-variants 3`
|
||||
- "**2 layout options**" → `--layout-variants 2`
|
||||
- "Create **4 styles** with **2 layouts each**" → `--style-variants 4 --layout-variants 2`
|
||||
- Explicit flags override prompt inference
|
||||
|
||||
## Execution Modes
|
||||
|
||||
**Matrix Mode** (style-centric):
|
||||
- Generates `style_variants × layout_variants × targets` prototypes
|
||||
- **Phase 1**: `style_variants` complete design systems (extract)
|
||||
- **Phase 2**: Layout templates extraction (layout-extract)
|
||||
- **Phase 3**: Style-centric batch generation (generate)
|
||||
- Sub-phase 1: `targets × layout_variants` target-specific layout plans
|
||||
- **Sub-phase 2**: `S` style-centric agents (each handles `L×T` combinations)
|
||||
- Sub-phase 3: `style_variants × layout_variants × targets` final prototypes
|
||||
- Performance: Efficient parallel execution with S agents
|
||||
- Quality: HTML structure adapts to design_attributes
|
||||
- Pages: Full-page layouts with complete structure
|
||||
- Components: Isolated elements with minimal wrapper
|
||||
|
||||
**Integrated vs. Standalone**:
|
||||
- `--session` flag determines session integration or standalone execution
|
||||
|
||||
## 6-Phase Execution
|
||||
|
||||
### Phase 0a: Intelligent Prompt Parsing
|
||||
```bash
|
||||
# Parse variant counts from prompt or use explicit/default values
|
||||
IF --prompt AND (NOT --style-variants OR NOT --layout-variants):
|
||||
style_variants = regex_extract(prompt, r"(\d+)\s*style") OR --style-variants OR 3
|
||||
layout_variants = regex_extract(prompt, r"(\d+)\s*layout") OR --layout-variants OR 3
|
||||
ELSE:
|
||||
style_variants = --style-variants OR 3
|
||||
layout_variants = --layout-variants OR 3
|
||||
|
||||
VALIDATE: 1 <= style_variants <= 5, 1 <= layout_variants <= 5
|
||||
```
|
||||
|
||||
### Phase 0a-2: Device Type Inference
|
||||
```bash
|
||||
# Device type inference
|
||||
device_type = "auto"
|
||||
|
||||
# Step 1: Explicit parameter (highest priority)
|
||||
IF --device-type AND --device-type != "auto":
|
||||
device_type = --device-type
|
||||
device_source = "explicit"
|
||||
ELSE:
|
||||
# Step 2: Prompt analysis
|
||||
IF --prompt:
|
||||
device_keywords = {
|
||||
"desktop": ["desktop", "web", "laptop", "widescreen", "large screen"],
|
||||
"mobile": ["mobile", "phone", "smartphone", "ios", "android"],
|
||||
"tablet": ["tablet", "ipad", "medium screen"],
|
||||
"responsive": ["responsive", "adaptive", "multi-device", "cross-platform"]
|
||||
}
|
||||
detected_device = detect_device_from_prompt(--prompt, device_keywords)
|
||||
IF detected_device:
|
||||
device_type = detected_device
|
||||
device_source = "prompt_inference"
|
||||
|
||||
# Step 3: Target type inference
|
||||
IF device_type == "auto":
|
||||
# Components are typically desktop-first, pages can vary
|
||||
device_type = target_type == "component" ? "desktop" : "responsive"
|
||||
device_source = "target_type_inference"
|
||||
|
||||
STORE: device_type, device_source
|
||||
```
|
||||
|
||||
**Device Type Presets**:
|
||||
- **Desktop**: 1920×1080px - Mouse-driven, spacious layouts
|
||||
- **Mobile**: 375×812px - Touch-friendly, compact layouts
|
||||
- **Tablet**: 768×1024px - Hybrid touch/mouse layouts
|
||||
- **Responsive**: 1920×1080px base with mobile-first breakpoints
|
||||
|
||||
**Detection Keywords**:
|
||||
- Prompt contains "mobile", "phone", "smartphone" → mobile
|
||||
- Prompt contains "tablet", "ipad" → tablet
|
||||
- Prompt contains "desktop", "web", "laptop" → desktop
|
||||
- Prompt contains "responsive", "adaptive" → responsive
|
||||
- Otherwise: Inferred from target type (components→desktop, pages→responsive)
|
||||
|
||||
### Phase 0b: Run Initialization & Directory Setup
|
||||
```bash
|
||||
run_id = "run-$(date +%Y%m%d-%H%M%S)"
|
||||
base_path = --session ? ".workflow/WFS-{session}/design-${run_id}" : ".workflow/.design/${run_id}"
|
||||
|
||||
Bash(mkdir -p "${base_path}/{style-extraction,style-consolidation,prototypes}")
|
||||
|
||||
Write({base_path}/.run-metadata.json): {
|
||||
"run_id": "${run_id}", "session_id": "${session_id}", "timestamp": "...",
|
||||
"workflow": "ui-design:auto",
|
||||
"architecture": "style-centric-batch-generation",
|
||||
"parameters": { "style_variants": ${style_variants}, "layout_variants": ${layout_variants},
|
||||
"targets": "${inferred_target_list}", "target_type": "${target_type}",
|
||||
"prompt": "${prompt_text}", "images": "${images_pattern}",
|
||||
"device_type": "${device_type}", "device_source": "${device_source}" },
|
||||
"status": "in_progress",
|
||||
"performance_mode": "optimized"
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 0c: Unified Target Inference with Intelligent Type Detection
|
||||
```bash
|
||||
# Priority: --pages/--components (legacy) → --targets → --prompt analysis → synthesis → default
|
||||
target_list = []; target_type = "auto"; target_source = "none"
|
||||
|
||||
# Step 1-2: Explicit parameters (legacy or unified)
|
||||
IF --pages: target_list = split(--pages); target_type = "page"; target_source = "explicit_legacy"
|
||||
ELSE IF --components: target_list = split(--components); target_type = "component"; target_source = "explicit_legacy"
|
||||
ELSE IF --targets:
|
||||
target_list = split(--targets); target_source = "explicit"
|
||||
target_type = --target-type != "auto" ? --target-type : detect_target_type(target_list)
|
||||
|
||||
# Step 3: Prompt analysis (Claude internal analysis)
|
||||
ELSE IF --prompt:
|
||||
analysis_result = analyze_prompt("{prompt_text}") # Extract targets, types, purpose
|
||||
target_list = analysis_result.targets
|
||||
target_type = analysis_result.primary_type OR detect_target_type(target_list)
|
||||
target_source = "prompt_analysis"
|
||||
|
||||
# Step 4: Session synthesis
|
||||
ELSE IF --session AND exists(role analysis documents):
|
||||
target_list = extract_targets_from_synthesis(); target_type = "page"; target_source = "synthesis"
|
||||
|
||||
# Step 5: Fallback
|
||||
IF NOT target_list: target_list = ["home"]; target_type = "page"; target_source = "default"
|
||||
|
||||
# Validate and clean
|
||||
validated_targets = [normalize(t) for t in target_list if is_valid(t)]
|
||||
IF NOT validated_targets: validated_targets = ["home"]; target_type = "page"
|
||||
IF --target-type != "auto": target_type = --target-type
|
||||
|
||||
# Interactive confirmation
|
||||
DISPLAY_CONFIRMATION(target_type, target_source, validated_targets, device_type, device_source):
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
"{emoji} {LABEL} CONFIRMATION (Style-Centric)"
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
"Type: {target_type} | Source: {target_source}"
|
||||
"Targets ({count}): {', '.join(validated_targets)}"
|
||||
"Device: {device_type} | Source: {device_source}"
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
"Performance: {style_variants} agent calls"
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
"Modification Options:"
|
||||
" • 'continue/yes/ok' - Proceed with current configuration"
|
||||
" • 'targets: a,b,c' - Replace target list"
|
||||
" • 'skip: x,y' - Remove specific targets"
|
||||
" • 'add: z' - Add new targets"
|
||||
" • 'type: page|component' - Change target type"
|
||||
" • 'device: desktop|mobile|tablet|responsive' - Change device type"
|
||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
user_input = WAIT_FOR_USER_INPUT()
|
||||
|
||||
# Process user modifications
|
||||
MATCH user_input:
|
||||
"continue|yes|ok" → proceed
|
||||
"targets: ..." → validated_targets = parse_new_list()
|
||||
"skip: ..." → validated_targets = remove_items()
|
||||
"add: ..." → validated_targets = add_items()
|
||||
"type: ..." → target_type = extract_type()
|
||||
"device: ..." → device_type = extract_device()
|
||||
default → proceed with current list
|
||||
|
||||
STORE: inferred_target_list, target_type, target_inference_source
|
||||
|
||||
# ⚠️ CRITICAL: User confirmation complete, IMMEDIATELY initialize TodoWrite and execute Phase 1
|
||||
# This is the only user interaction point in the workflow
|
||||
# After this point, all subsequent phases execute automatically without user intervention
|
||||
```
|
||||
|
||||
**Helper Function: detect_target_type()**
|
||||
```bash
|
||||
detect_target_type(target_list):
|
||||
page_keywords = ["home", "dashboard", "settings", "profile", "login", "signup", "auth", ...]
|
||||
component_keywords = ["navbar", "header", "footer", "hero", "card", "button", "form", ...]
|
||||
|
||||
page_matches = count_matches(target_list, page_keywords + ["page", "screen", "view"])
|
||||
component_matches = count_matches(target_list, component_keywords + ["component", "widget"])
|
||||
|
||||
RETURN "component" IF component_matches > page_matches ELSE "page"
|
||||
```
|
||||
|
||||
### Phase 1: Style Extraction
|
||||
```bash
|
||||
command = "/workflow:ui-design:style-extract --base-path \"{base_path}\" " +
|
||||
(--images ? "--images \"{images}\" " : "") +
|
||||
(--prompt ? "--prompt \"{prompt}\" " : "") +
|
||||
"--mode explore --variants {style_variants}"
|
||||
SlashCommand(command)
|
||||
|
||||
# Output: {style_variants} style cards with design_attributes
|
||||
# SlashCommand blocks until phase complete
|
||||
# Upon completion, IMMEDIATELY execute Phase 2.3 (auto-continue)
|
||||
```
|
||||
|
||||
### Phase 2.3: Animation Extraction (Optional - Interactive Mode)
|
||||
```bash
|
||||
# Animation extraction for motion design patterns
|
||||
REPORT: "🚀 Phase 2.3: Animation Extraction (interactive mode)"
|
||||
REPORT: " → Mode: Interactive specification"
|
||||
REPORT: " → Purpose: Define motion design patterns"
|
||||
|
||||
command = "/workflow:ui-design:animation-extract --base-path \"{base_path}\" --mode interactive"
|
||||
|
||||
SlashCommand(command)
|
||||
|
||||
# Output: animation-tokens.json + animation-guide.md
|
||||
# SlashCommand blocks until phase complete
|
||||
# Upon completion, IMMEDIATELY execute Phase 2.5 (auto-continue)
|
||||
```
|
||||
|
||||
### Phase 2.5: Layout Extraction
|
||||
```bash
|
||||
targets_string = ",".join(inferred_target_list)
|
||||
command = "/workflow:ui-design:layout-extract --base-path \"{base_path}\" " +
|
||||
(--images ? "--images \"{images}\" " : "") +
|
||||
(--prompt ? "--prompt \"{prompt}\" " : "") +
|
||||
"--targets \"{targets_string}\" " +
|
||||
"--mode explore --variants {layout_variants} " +
|
||||
"--device-type \"{device_type}\""
|
||||
|
||||
REPORT: "🚀 Phase 2.5: Layout Extraction (explore mode)"
|
||||
REPORT: " → Targets: {targets_string}"
|
||||
REPORT: " → Layout variants: {layout_variants}"
|
||||
REPORT: " → Device: {device_type}"
|
||||
|
||||
SlashCommand(command)
|
||||
|
||||
# Output: layout-templates.json with {targets × layout_variants} layout structures
|
||||
# SlashCommand blocks until phase complete
|
||||
# Upon completion, IMMEDIATELY execute Phase 3 (auto-continue)
|
||||
```
|
||||
|
||||
### Phase 3: UI Assembly
|
||||
```bash
|
||||
command = "/workflow:ui-design:generate --base-path \"{base_path}\" " +
|
||||
"--style-variants {style_variants} --layout-variants {layout_variants}"
|
||||
|
||||
total = style_variants × layout_variants × len(inferred_target_list)
|
||||
|
||||
REPORT: "🚀 Phase 3: UI Assembly | Matrix: {s}×{l}×{n} = {total} prototypes"
|
||||
REPORT: " → Pure assembly: Combining layout templates + design tokens"
|
||||
REPORT: " → Device: {device_type} (from layout templates)"
|
||||
REPORT: " → Assembly tasks: {total} combinations"
|
||||
|
||||
SlashCommand(command)
|
||||
|
||||
# SlashCommand blocks until phase complete
|
||||
# Upon completion, IMMEDIATELY execute Phase 4 (auto-continue)
|
||||
# Output:
|
||||
# - {target}-style-{s}-layout-{l}.html (assembled prototypes)
|
||||
# - {target}-style-{s}-layout-{l}.css
|
||||
# - compare.html (interactive matrix view)
|
||||
# - PREVIEW.md (usage instructions)
|
||||
```
|
||||
|
||||
### Phase 4: Design System Integration
|
||||
```bash
|
||||
command = "/workflow:ui-design:update" + (--session ? " --session {session_id}" : "")
|
||||
SlashCommand(command)
|
||||
|
||||
# SlashCommand blocks until phase complete
|
||||
# Upon completion:
|
||||
# - If --batch-plan flag present: IMMEDIATELY execute Phase 5 (auto-continue)
|
||||
# - If no --batch-plan: Workflow complete, display final report
|
||||
```
|
||||
|
||||
### Phase 5: Batch Task Generation (Optional)
|
||||
```bash
|
||||
IF --batch-plan:
|
||||
FOR target IN inferred_target_list:
|
||||
task_desc = "Implement {target} {target_type} based on design system"
|
||||
SlashCommand("/workflow:plan --agent \"{task_desc}\"")
|
||||
```
|
||||
|
||||
## TodoWrite Pattern
|
||||
```javascript
|
||||
// Initialize IMMEDIATELY after Phase 0c user confirmation to track multi-phase execution
|
||||
TodoWrite({todos: [
|
||||
{"content": "Execute style extraction", "status": "in_progress", "activeForm": "Executing..."},
|
||||
{"content": "Execute layout extraction", "status": "pending", "activeForm": "Executing..."},
|
||||
{"content": "Execute UI assembly", "status": "pending", "activeForm": "Executing..."},
|
||||
{"content": "Execute design integration", "status": "pending", "activeForm": "Executing..."}
|
||||
]})
|
||||
|
||||
// ⚠️ CRITICAL: After EACH SlashCommand completion (Phase 1-5), you MUST:
|
||||
// 1. SlashCommand blocks and returns when phase is complete
|
||||
// 2. Update current phase: status → "completed"
|
||||
// 3. Update next phase: status → "in_progress"
|
||||
// 4. IMMEDIATELY execute next phase SlashCommand (auto-continue)
|
||||
// This ensures continuous workflow tracking and prevents premature stopping
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
- **🚀 Performance**: Style-centric batch generation with S agent calls
|
||||
- **🎨 Style-Aware**: HTML structure adapts to design_attributes
|
||||
- **✅ Perfect Consistency**: Each style by single agent
|
||||
- **📦 Autonomous**: No user intervention required between phases
|
||||
- **🧠 Intelligent**: Parses natural language, infers targets/types
|
||||
- **🔄 Reproducible**: Deterministic flow with isolated run directories
|
||||
- **🎯 Flexible**: Supports pages, components, or mixed targets
|
||||
|
||||
## Examples
|
||||
|
||||
### 1. Page Mode (Prompt Inference)
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --prompt "Modern blog: home, article, author"
|
||||
# Result: 27 prototypes (3×3×3) - responsive layouts (default)
|
||||
```
|
||||
|
||||
### 2. Mobile-First Design
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --prompt "Mobile shopping app: home, product, cart" --device-type mobile
|
||||
# Result: 27 prototypes (3×3×3) - mobile layouts (375×812px)
|
||||
```
|
||||
|
||||
### 3. Desktop Application
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --targets "dashboard,analytics,settings" --device-type desktop --style-variants 2 --layout-variants 2
|
||||
# Result: 12 prototypes (2×2×3) - desktop layouts (1920×1080px)
|
||||
```
|
||||
|
||||
### 4. Tablet Interface
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --prompt "Educational app for tablets" --device-type tablet --targets "courses,lessons,profile"
|
||||
# Result: 27 prototypes (3×3×3) - tablet layouts (768×1024px)
|
||||
```
|
||||
|
||||
### 5. Custom Matrix with Session
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --session WFS-ecommerce --images "refs/*.png" --style-variants 2 --layout-variants 2
|
||||
# Result: 2×2×N prototypes - device type inferred from session
|
||||
```
|
||||
|
||||
### 6. Component Mode (Desktop)
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --targets "navbar,hero" --target-type "component" --device-type desktop --style-variants 3 --layout-variants 2
|
||||
# Result: 12 prototypes (3×2×2) - desktop components
|
||||
```
|
||||
|
||||
### 7. Intelligent Parsing + Batch Planning
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --prompt "Create 4 styles with 2 layouts for mobile dashboard and settings" --batch-plan
|
||||
# Result: 16 prototypes (4×2×2) + auto-generated tasks - mobile-optimized (inferred from prompt)
|
||||
```
|
||||
|
||||
### 8. Large Scale Responsive
|
||||
```bash
|
||||
/workflow:ui-design:explore-auto --targets "home,dashboard,settings,profile" --device-type responsive --style-variants 3 --layout-variants 3
|
||||
# Result: 36 prototypes (3×3×4) - responsive layouts
|
||||
```
|
||||
|
||||
## Completion Output
|
||||
```
|
||||
✅ UI Design Explore-Auto Workflow Complete!
|
||||
|
||||
Architecture: Style-Centric Batch Generation
|
||||
Run ID: {run_id} | Session: {session_id or "standalone"}
|
||||
Type: {icon} {target_type} | Device: {device_type} | Matrix: {s}×{l}×{n} = {total} prototypes
|
||||
|
||||
Phase 1: {s} complete design systems (style-extract)
|
||||
Phase 2: {n×l} layout templates (layout-extract explore mode)
|
||||
- Device: {device_type} layouts
|
||||
- {n} targets × {l} layout variants = {n×l} structural templates
|
||||
Phase 3: UI Assembly (generate)
|
||||
- Pure assembly: layout templates + design tokens
|
||||
- {s}×{l}×{n} = {total} final prototypes
|
||||
Phase 4: Brainstorming artifacts updated
|
||||
[Phase 5: {n} implementation tasks created] # if --batch-plan
|
||||
|
||||
Assembly Process:
|
||||
✅ Separation of Concerns: Layout (structure) + Style (tokens) kept separate
|
||||
✅ Layout Extraction: {n×l} reusable structural templates
|
||||
✅ Pure Assembly: No design decisions in generate phase
|
||||
✅ Device-Optimized: Layouts designed for {device_type}
|
||||
|
||||
Design Quality:
|
||||
✅ Token-Driven Styling: 100% var() usage
|
||||
✅ Structural Variety: {l} distinct layouts per target
|
||||
✅ Style Variety: {s} independent design systems
|
||||
✅ Device-Optimized: Layouts designed for {device_type}
|
||||
|
||||
📂 {base_path}/
|
||||
├── .intermediates/ (Intermediate analysis files)
|
||||
│ ├── style-analysis/ (computed-styles.json, design-space-analysis.json)
|
||||
│ └── layout-analysis/ (dom-structure-*.json, inspirations/*.txt)
|
||||
├── style-extraction/ ({s} complete design systems)
|
||||
├── layout-extraction/ ({n×l} layout templates + layout-space-analysis.json)
|
||||
├── prototypes/ ({total} assembled prototypes)
|
||||
└── .run-metadata.json (includes device type)
|
||||
|
||||
🌐 Preview: {base_path}/prototypes/compare.html
|
||||
- Interactive {s}×{l} matrix view
|
||||
- Side-by-side comparison
|
||||
- Target-specific layouts with style-aware structure
|
||||
- Toggle between {n} targets
|
||||
|
||||
{icon} Targets: {', '.join(targets)} (type: {target_type})
|
||||
- Each target has {l} custom-designed layouts
|
||||
- Each style × target × layout has unique HTML structure (not just CSS!)
|
||||
- Layout plans stored as structured JSON
|
||||
- Optimized for {device_type} viewing
|
||||
|
||||
Next: [/workflow:execute] OR [Open compare.html → Select → /workflow:plan]
|
||||
```
|
||||
|
||||
@@ -0,0 +1,589 @@
|
||||
---
|
||||
name: explore-layers
|
||||
description: Interactive deep UI capture with depth-controlled layer exploration using MCP puppeteer
|
||||
argument-hint: --url <url> --depth <1-5> [--session id] [--base-path path]
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Bash(*), Glob(*), mcp__chrome-devtools__*
|
||||
---
|
||||
|
||||
# Interactive Layer Exploration (/workflow:ui-design:explore-layers)
|
||||
|
||||
## Overview
|
||||
Single-URL depth-controlled interactive capture. Progressively explores UI layers from pages to Shadow DOM.
|
||||
|
||||
**Depth Levels**:
|
||||
- `1` = Page (full-page screenshot)
|
||||
- `2` = Elements (key components)
|
||||
- `3` = Interactions (modals, dropdowns)
|
||||
- `4` = Embedded (iframes, widgets)
|
||||
- `5` = Shadow DOM (web components)
|
||||
|
||||
**Requirements**: Chrome DevTools MCP
|
||||
|
||||
## Phase 1: Setup & Validation
|
||||
|
||||
### Step 1: Parse Parameters
|
||||
```javascript
|
||||
url = params["--url"]
|
||||
depth = int(params["--depth"])
|
||||
|
||||
// Validate URL
|
||||
IF NOT url.startswith("http"):
|
||||
url = f"https://{url}"
|
||||
|
||||
// Validate depth
|
||||
IF depth NOT IN [1, 2, 3, 4, 5]:
|
||||
ERROR: "Invalid depth: {depth}. Use 1-5"
|
||||
EXIT 1
|
||||
```
|
||||
|
||||
### Step 2: Determine Base Path
|
||||
```bash
|
||||
bash(if [ -n "$BASE_PATH" ]; then
|
||||
echo "$BASE_PATH"
|
||||
elif [ -n "$SESSION_ID" ]; then
|
||||
find .workflow/WFS-$SESSION_ID/design-* -type d | head -1 || \
|
||||
echo ".workflow/WFS-$SESSION_ID/design-layers-$(date +%Y%m%d-%H%M%S)"
|
||||
else
|
||||
echo ".workflow/.design/layers-$(date +%Y%m%d-%H%M%S)"
|
||||
fi)
|
||||
|
||||
# Create depth directories
|
||||
bash(for i in $(seq 1 $depth); do mkdir -p $BASE_PATH/screenshots/depth-$i; done)
|
||||
```
|
||||
|
||||
**Output**: `url`, `depth`, `base_path`
|
||||
|
||||
### Step 3: Validate MCP Availability
|
||||
```javascript
|
||||
all_resources = ListMcpResourcesTool()
|
||||
chrome_devtools = "chrome-devtools" IN [r.server for r in all_resources]
|
||||
|
||||
IF NOT chrome_devtools:
|
||||
ERROR: "explore-layers requires Chrome DevTools MCP"
|
||||
ERROR: "Install: npm i -g @modelcontextprotocol/server-chrome-devtools"
|
||||
EXIT 1
|
||||
```
|
||||
|
||||
### Step 4: Initialize Todos
|
||||
```javascript
|
||||
todos = [
|
||||
{content: "Setup and validation", status: "completed", activeForm: "Setting up"}
|
||||
]
|
||||
|
||||
FOR level IN range(1, depth + 1):
|
||||
todos.append({
|
||||
content: f"Depth {level}: {DEPTH_NAMES[level]}",
|
||||
status: "pending",
|
||||
activeForm: f"Capturing depth {level}"
|
||||
})
|
||||
|
||||
todos.append({content: "Generate layer map", status: "pending", activeForm: "Mapping"})
|
||||
|
||||
TodoWrite({todos})
|
||||
```
|
||||
|
||||
## Phase 2: Navigate & Load Page
|
||||
|
||||
### Step 1: Get or Create Browser Page
|
||||
```javascript
|
||||
pages = mcp__chrome-devtools__list_pages()
|
||||
|
||||
IF pages.length == 0:
|
||||
mcp__chrome-devtools__new_page({url: url, timeout: 30000})
|
||||
page_idx = 0
|
||||
ELSE:
|
||||
page_idx = 0
|
||||
mcp__chrome-devtools__select_page({pageIdx: page_idx})
|
||||
mcp__chrome-devtools__navigate_page({url: url, timeout: 30000})
|
||||
|
||||
bash(sleep 3) // Wait for page load
|
||||
```
|
||||
|
||||
**Output**: `page_idx`
|
||||
|
||||
## Phase 3: Depth 1 - Page Level
|
||||
|
||||
### Step 1: Capture Full Page
|
||||
```javascript
|
||||
TodoWrite(mark_in_progress: "Depth 1: Page")
|
||||
|
||||
output_file = f"{base_path}/screenshots/depth-1/full-page.png"
|
||||
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
fullPage: true,
|
||||
format: "png",
|
||||
quality: 90,
|
||||
filePath: output_file
|
||||
})
|
||||
|
||||
layer_map = {
|
||||
"url": url,
|
||||
"depth": depth,
|
||||
"layers": {
|
||||
"depth-1": {
|
||||
"type": "page",
|
||||
"captures": [{
|
||||
"name": "full-page",
|
||||
"path": output_file,
|
||||
"size_kb": file_size_kb(output_file)
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TodoWrite(mark_completed: "Depth 1: Page")
|
||||
```
|
||||
|
||||
**Output**: `depth-1/full-page.png`
|
||||
|
||||
## Phase 4: Depth 2 - Element Level (If depth >= 2)
|
||||
|
||||
### Step 1: Analyze Page Structure
|
||||
```javascript
|
||||
IF depth < 2: SKIP
|
||||
|
||||
TodoWrite(mark_in_progress: "Depth 2: Elements")
|
||||
|
||||
snapshot = mcp__chrome-devtools__take_snapshot()
|
||||
|
||||
// Filter key elements
|
||||
key_types = ["nav", "header", "footer", "aside", "button", "form", "article"]
|
||||
key_elements = [
|
||||
el for el in snapshot.interactiveElements
|
||||
if el.type IN key_types OR el.role IN ["navigation", "banner", "main"]
|
||||
][:10] // Limit to top 10
|
||||
```
|
||||
|
||||
### Step 2: Capture Element Screenshots
|
||||
```javascript
|
||||
depth_2_captures = []
|
||||
|
||||
FOR idx, element IN enumerate(key_elements):
|
||||
element_name = sanitize(element.text[:20] or element.type) or f"element-{idx}"
|
||||
output_file = f"{base_path}/screenshots/depth-2/{element_name}.png"
|
||||
|
||||
TRY:
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
uid: element.uid,
|
||||
format: "png",
|
||||
quality: 85,
|
||||
filePath: output_file
|
||||
})
|
||||
|
||||
depth_2_captures.append({
|
||||
"name": element_name,
|
||||
"type": element.type,
|
||||
"path": output_file,
|
||||
"size_kb": file_size_kb(output_file)
|
||||
})
|
||||
CATCH error:
|
||||
REPORT: f"Skip {element_name}: {error}"
|
||||
|
||||
layer_map.layers["depth-2"] = {
|
||||
"type": "elements",
|
||||
"captures": depth_2_captures
|
||||
}
|
||||
|
||||
TodoWrite(mark_completed: "Depth 2: Elements")
|
||||
```
|
||||
|
||||
**Output**: `depth-2/{element}.png` × N
|
||||
|
||||
## Phase 5: Depth 3 - Interaction Level (If depth >= 3)
|
||||
|
||||
### Step 1: Analyze Interactive Triggers
|
||||
```javascript
|
||||
IF depth < 3: SKIP
|
||||
|
||||
TodoWrite(mark_in_progress: "Depth 3: Interactions")
|
||||
|
||||
// Detect structure
|
||||
structure = mcp__chrome-devtools__evaluate_script({
|
||||
function: `() => ({
|
||||
modals: document.querySelectorAll('[role="dialog"], .modal').length,
|
||||
dropdowns: document.querySelectorAll('[role="menu"], .dropdown').length,
|
||||
tooltips: document.querySelectorAll('[role="tooltip"], [title]').length
|
||||
})`
|
||||
})
|
||||
|
||||
// Identify triggers
|
||||
triggers = []
|
||||
FOR element IN snapshot.interactiveElements:
|
||||
IF element.attributes CONTAINS ("data-toggle", "aria-haspopup"):
|
||||
triggers.append({
|
||||
uid: element.uid,
|
||||
type: "modal" IF "modal" IN element.classes ELSE "dropdown",
|
||||
trigger: "click",
|
||||
text: element.text
|
||||
})
|
||||
ELSE IF element.attributes CONTAINS ("title", "data-tooltip"):
|
||||
triggers.append({
|
||||
uid: element.uid,
|
||||
type: "tooltip",
|
||||
trigger: "hover",
|
||||
text: element.text
|
||||
})
|
||||
|
||||
triggers = triggers[:10] // Limit
|
||||
```
|
||||
|
||||
### Step 2: Trigger Interactions & Capture
|
||||
```javascript
|
||||
depth_3_captures = []
|
||||
|
||||
FOR idx, trigger IN enumerate(triggers):
|
||||
layer_name = f"{trigger.type}-{sanitize(trigger.text[:15]) or idx}"
|
||||
output_file = f"{base_path}/screenshots/depth-3/{layer_name}.png"
|
||||
|
||||
TRY:
|
||||
// Trigger interaction
|
||||
IF trigger.trigger == "click":
|
||||
mcp__chrome-devtools__click({uid: trigger.uid})
|
||||
ELSE:
|
||||
mcp__chrome-devtools__hover({uid: trigger.uid})
|
||||
|
||||
bash(sleep 1)
|
||||
|
||||
// Capture
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
fullPage: false, // Viewport only
|
||||
format: "png",
|
||||
quality: 90,
|
||||
filePath: output_file
|
||||
})
|
||||
|
||||
depth_3_captures.append({
|
||||
"name": layer_name,
|
||||
"type": trigger.type,
|
||||
"trigger_method": trigger.trigger,
|
||||
"path": output_file,
|
||||
"size_kb": file_size_kb(output_file)
|
||||
})
|
||||
|
||||
// Dismiss (ESC key)
|
||||
mcp__chrome-devtools__evaluate_script({
|
||||
function: `() => {
|
||||
document.dispatchEvent(new KeyboardEvent('keydown', {key: 'Escape'}));
|
||||
}`
|
||||
})
|
||||
bash(sleep 0.5)
|
||||
|
||||
CATCH error:
|
||||
REPORT: f"Skip {layer_name}: {error}"
|
||||
|
||||
layer_map.layers["depth-3"] = {
|
||||
"type": "interactions",
|
||||
"triggers": structure,
|
||||
"captures": depth_3_captures
|
||||
}
|
||||
|
||||
TodoWrite(mark_completed: "Depth 3: Interactions")
|
||||
```
|
||||
|
||||
**Output**: `depth-3/{interaction}.png` × N
|
||||
|
||||
## Phase 6: Depth 4 - Embedded Level (If depth >= 4)
|
||||
|
||||
### Step 1: Detect Iframes
|
||||
```javascript
|
||||
IF depth < 4: SKIP
|
||||
|
||||
TodoWrite(mark_in_progress: "Depth 4: Embedded")
|
||||
|
||||
iframes = mcp__chrome-devtools__evaluate_script({
|
||||
function: `() => {
|
||||
return Array.from(document.querySelectorAll('iframe')).map(iframe => ({
|
||||
src: iframe.src,
|
||||
id: iframe.id || 'iframe',
|
||||
title: iframe.title || 'untitled'
|
||||
})).filter(i => i.src && i.src.startsWith('http'));
|
||||
}`
|
||||
})
|
||||
```
|
||||
|
||||
### Step 2: Capture Iframe Content
|
||||
```javascript
|
||||
depth_4_captures = []
|
||||
|
||||
FOR idx, iframe IN enumerate(iframes):
|
||||
iframe_name = f"iframe-{sanitize(iframe.title or iframe.id)}-{idx}"
|
||||
output_file = f"{base_path}/screenshots/depth-4/{iframe_name}.png"
|
||||
|
||||
TRY:
|
||||
// Navigate to iframe URL in new tab
|
||||
mcp__chrome-devtools__new_page({url: iframe.src, timeout: 30000})
|
||||
bash(sleep 2)
|
||||
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
fullPage: true,
|
||||
format: "png",
|
||||
quality: 90,
|
||||
filePath: output_file
|
||||
})
|
||||
|
||||
depth_4_captures.append({
|
||||
"name": iframe_name,
|
||||
"url": iframe.src,
|
||||
"path": output_file,
|
||||
"size_kb": file_size_kb(output_file)
|
||||
})
|
||||
|
||||
// Close iframe tab
|
||||
current_pages = mcp__chrome-devtools__list_pages()
|
||||
mcp__chrome-devtools__close_page({pageIdx: current_pages.length - 1})
|
||||
|
||||
CATCH error:
|
||||
REPORT: f"Skip {iframe_name}: {error}"
|
||||
|
||||
layer_map.layers["depth-4"] = {
|
||||
"type": "embedded",
|
||||
"captures": depth_4_captures
|
||||
}
|
||||
|
||||
TodoWrite(mark_completed: "Depth 4: Embedded")
|
||||
```
|
||||
|
||||
**Output**: `depth-4/iframe-*.png` × N
|
||||
|
||||
## Phase 7: Depth 5 - Shadow DOM (If depth = 5)
|
||||
|
||||
### Step 1: Detect Shadow Roots
|
||||
```javascript
|
||||
IF depth < 5: SKIP
|
||||
|
||||
TodoWrite(mark_in_progress: "Depth 5: Shadow DOM")
|
||||
|
||||
shadow_elements = mcp__chrome-devtools__evaluate_script({
|
||||
function: `() => {
|
||||
const elements = Array.from(document.querySelectorAll('*'));
|
||||
return elements
|
||||
.filter(el => el.shadowRoot)
|
||||
.map((el, idx) => ({
|
||||
tag: el.tagName.toLowerCase(),
|
||||
id: el.id || \`shadow-\${idx}\`,
|
||||
innerHTML: el.shadowRoot.innerHTML.substring(0, 100)
|
||||
}));
|
||||
}`
|
||||
})
|
||||
```
|
||||
|
||||
### Step 2: Capture Shadow DOM Components
|
||||
```javascript
|
||||
depth_5_captures = []
|
||||
|
||||
FOR idx, shadow IN enumerate(shadow_elements):
|
||||
shadow_name = f"shadow-{sanitize(shadow.id)}"
|
||||
output_file = f"{base_path}/screenshots/depth-5/{shadow_name}.png"
|
||||
|
||||
TRY:
|
||||
// Inject highlight script
|
||||
mcp__chrome-devtools__evaluate_script({
|
||||
function: `() => {
|
||||
const el = document.querySelector('${shadow.tag}${shadow.id ? "#" + shadow.id : ""}');
|
||||
if (el) {
|
||||
el.scrollIntoView({behavior: 'smooth', block: 'center'});
|
||||
el.style.outline = '3px solid red';
|
||||
}
|
||||
}`
|
||||
})
|
||||
|
||||
bash(sleep 0.5)
|
||||
|
||||
// Full-page screenshot (component highlighted)
|
||||
mcp__chrome-devtools__take_screenshot({
|
||||
fullPage: false,
|
||||
format: "png",
|
||||
quality: 90,
|
||||
filePath: output_file
|
||||
})
|
||||
|
||||
depth_5_captures.append({
|
||||
"name": shadow_name,
|
||||
"tag": shadow.tag,
|
||||
"path": output_file,
|
||||
"size_kb": file_size_kb(output_file)
|
||||
})
|
||||
|
||||
CATCH error:
|
||||
REPORT: f"Skip {shadow_name}: {error}"
|
||||
|
||||
layer_map.layers["depth-5"] = {
|
||||
"type": "shadow-dom",
|
||||
"captures": depth_5_captures
|
||||
}
|
||||
|
||||
TodoWrite(mark_completed: "Depth 5: Shadow DOM")
|
||||
```
|
||||
|
||||
**Output**: `depth-5/shadow-*.png` × N
|
||||
|
||||
## Phase 8: Generate Layer Map
|
||||
|
||||
### Step 1: Compile Metadata
|
||||
```javascript
|
||||
TodoWrite(mark_in_progress: "Generate layer map")
|
||||
|
||||
// Calculate totals
|
||||
total_captures = sum(len(layer.captures) for layer in layer_map.layers.values())
|
||||
total_size_kb = sum(
|
||||
sum(c.size_kb for c in layer.captures)
|
||||
for layer in layer_map.layers.values()
|
||||
)
|
||||
|
||||
layer_map["summary"] = {
|
||||
"timestamp": current_timestamp(),
|
||||
"total_depth": depth,
|
||||
"total_captures": total_captures,
|
||||
"total_size_kb": total_size_kb
|
||||
}
|
||||
|
||||
Write(f"{base_path}/screenshots/layer-map.json", JSON.stringify(layer_map, indent=2))
|
||||
|
||||
TodoWrite(mark_completed: "Generate layer map")
|
||||
```
|
||||
|
||||
**Output**: `layer-map.json`
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
all_todos_completed = true
|
||||
TodoWrite({todos: all_completed_todos})
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ Interactive layer exploration complete!
|
||||
|
||||
Configuration:
|
||||
- URL: {url}
|
||||
- Max depth: {depth}
|
||||
- Layers explored: {len(layer_map.layers)}
|
||||
|
||||
Capture Summary:
|
||||
Depth 1 (Page): {depth_1_count} screenshot(s)
|
||||
Depth 2 (Elements): {depth_2_count} screenshot(s)
|
||||
Depth 3 (Interactions): {depth_3_count} screenshot(s)
|
||||
Depth 4 (Embedded): {depth_4_count} screenshot(s)
|
||||
Depth 5 (Shadow DOM): {depth_5_count} screenshot(s)
|
||||
|
||||
Total: {total_captures} captures ({total_size_kb:.1f} KB)
|
||||
|
||||
Output Structure:
|
||||
{base_path}/screenshots/
|
||||
├── depth-1/
|
||||
│ └── full-page.png
|
||||
├── depth-2/
|
||||
│ ├── navbar.png
|
||||
│ └── footer.png
|
||||
├── depth-3/
|
||||
│ ├── modal-login.png
|
||||
│ └── dropdown-menu.png
|
||||
├── depth-4/
|
||||
│ └── iframe-analytics.png
|
||||
├── depth-5/
|
||||
│ └── shadow-button.png
|
||||
└── layer-map.json
|
||||
|
||||
Next: /workflow:ui-design:extract --images "screenshots/**/*.png"
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Directory Setup
|
||||
```bash
|
||||
# Create depth directories
|
||||
bash(for i in $(seq 1 $depth); do mkdir -p $BASE_PATH/screenshots/depth-$i; done)
|
||||
```
|
||||
|
||||
### Validation
|
||||
```bash
|
||||
# Check MCP
|
||||
all_resources = ListMcpResourcesTool()
|
||||
|
||||
# Count captures per depth
|
||||
bash(ls $base_path/screenshots/depth-{1..5}/*.png 2>/dev/null | wc -l)
|
||||
```
|
||||
|
||||
### File Operations
|
||||
```bash
|
||||
# List all captures
|
||||
bash(find $base_path/screenshots -name "*.png" -type f)
|
||||
|
||||
# Total size
|
||||
bash(du -sh $base_path/screenshots)
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/screenshots/
|
||||
├── depth-1/
|
||||
│ └── full-page.png
|
||||
├── depth-2/
|
||||
│ ├── {element}.png
|
||||
│ └── ...
|
||||
├── depth-3/
|
||||
│ ├── {interaction}.png
|
||||
│ └── ...
|
||||
├── depth-4/
|
||||
│ ├── iframe-*.png
|
||||
│ └── ...
|
||||
├── depth-5/
|
||||
│ ├── shadow-*.png
|
||||
│ └── ...
|
||||
└── layer-map.json
|
||||
```
|
||||
|
||||
## Depth Level Details
|
||||
|
||||
| Depth | Name | Captures | Time | Use Case |
|
||||
|-------|------|----------|------|----------|
|
||||
| 1 | Page | Full page | 30s | Quick preview |
|
||||
| 2 | Elements | Key components | 1-2min | Component library |
|
||||
| 3 | Interactions | Modals, dropdowns | 2-4min | UI flows |
|
||||
| 4 | Embedded | Iframes | 3-6min | Complete context |
|
||||
| 5 | Shadow DOM | Web components | 4-8min | Full coverage |
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: Chrome DevTools MCP required
|
||||
→ Install: npm i -g @modelcontextprotocol/server-chrome-devtools
|
||||
|
||||
ERROR: Invalid depth
|
||||
→ Use: 1-5
|
||||
|
||||
ERROR: Interaction trigger failed
|
||||
→ Some modals may be skipped, check layer-map.json
|
||||
```
|
||||
|
||||
### Recovery
|
||||
- **Partial success**: Lower depth captures preserved
|
||||
- **Trigger failures**: Interaction layer may be incomplete
|
||||
- **Iframe restrictions**: Cross-origin iframes skipped
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] All depths up to specified level captured
|
||||
- [ ] layer-map.json generated with metadata
|
||||
- [ ] File sizes valid (> 500 bytes)
|
||||
- [ ] Interaction triggers executed
|
||||
- [ ] Shadow DOM elements highlighted
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Depth-controlled**: Progressive capture 1-5 levels
|
||||
- **Interactive triggers**: Click/hover for hidden layers
|
||||
- **Iframe support**: Embedded content captured
|
||||
- **Shadow DOM**: Web component internals
|
||||
- **Structured output**: Organized by depth
|
||||
|
||||
## Integration
|
||||
|
||||
**Input**: Single URL + depth level (1-5)
|
||||
**Output**: Hierarchical screenshots + layer-map.json
|
||||
**Complements**: `/workflow:ui-design:capture` (multi-URL batch)
|
||||
**Next**: `/workflow:ui-design:extract` for design analysis
|
||||
@@ -0,0 +1,363 @@
|
||||
---
|
||||
name: generate
|
||||
description: Assemble UI prototypes by combining layout templates with design tokens, pure assembler without new content generation
|
||||
argument-hint: [--base-path <path>] [--session <id>] [--style-variants <count>] [--layout-variants <count>]
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Task(ui-design-agent), Bash(*)
|
||||
---
|
||||
|
||||
# Generate UI Prototypes (/workflow:ui-design:generate)
|
||||
|
||||
## Overview
|
||||
Pure assembler that combines pre-extracted layout templates with design tokens to generate UI prototypes (`style × layout × targets`). No layout design logic - purely combines existing components.
|
||||
|
||||
**Strategy**: Pure Assembly
|
||||
- **Input**: `layout-templates.json` + `design-tokens.json` (+ reference images if available)
|
||||
- **Process**: Combine structure (DOM) with style (tokens)
|
||||
- **Output**: Complete HTML/CSS prototypes
|
||||
- **No Design Logic**: All layout and style decisions already made
|
||||
- **Automatic Image Reference**: If source images exist in layout templates, they're automatically used for visual context
|
||||
|
||||
**Prerequisite Commands**:
|
||||
- `/workflow:ui-design:style-extract` → Complete design systems (design-tokens.json + style-guide.md)
|
||||
- `/workflow:ui-design:layout-extract` → Layout structure
|
||||
|
||||
## Phase 1: Setup & Validation
|
||||
|
||||
### Step 1: Resolve Base Path & Parse Configuration
|
||||
```bash
|
||||
# Determine working directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1) # Auto-detect
|
||||
|
||||
# Get style count
|
||||
bash(ls {base_path}/style-extraction/style-* -d | wc -l)
|
||||
|
||||
# Image reference auto-detected from layout template source_image_path
|
||||
```
|
||||
|
||||
### Step 2: Load Layout Templates
|
||||
```bash
|
||||
# Check layout templates exist
|
||||
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists")
|
||||
|
||||
# Load layout templates
|
||||
Read({base_path}/layout-extraction/layout-templates.json)
|
||||
# Extract: targets, layout_variants count, device_type, template structures
|
||||
```
|
||||
|
||||
**Output**: `base_path`, `style_variants`, `layout_templates[]`, `targets[]`, `device_type`
|
||||
|
||||
### Step 3: Validate Design Tokens
|
||||
```bash
|
||||
# Check design tokens exist for all styles
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "valid")
|
||||
|
||||
# For each style variant: Load design tokens
|
||||
Read({base_path}/style-extraction/style-{id}/design-tokens.json)
|
||||
```
|
||||
|
||||
**Output**: `design_tokens[]` for all style variants
|
||||
|
||||
### Step 4: Load Animation Tokens (Optional)
|
||||
```bash
|
||||
# Check if animation tokens exist
|
||||
bash(test -f {base_path}/animation-extraction/animation-tokens.json && echo "exists")
|
||||
|
||||
# Load animation tokens if available
|
||||
IF exists({base_path}/animation-extraction/animation-tokens.json):
|
||||
animation_tokens = Read({base_path}/animation-extraction/animation-tokens.json)
|
||||
has_animations = true
|
||||
ELSE:
|
||||
has_animations = false
|
||||
```
|
||||
|
||||
**Output**: `animation_tokens` (optional), `has_animations` flag
|
||||
|
||||
## Phase 2: Assembly (Agent)
|
||||
|
||||
**Executor**: `Task(ui-design-agent)` × `T × S × L` tasks (can be batched)
|
||||
|
||||
### Step 1: Launch Assembly Tasks
|
||||
```bash
|
||||
bash(mkdir -p {base_path}/prototypes)
|
||||
```
|
||||
|
||||
For each `target × style_id × layout_id`:
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[LAYOUT_STYLE_ASSEMBLY]
|
||||
🎯 Assembly task: {target} × Style-{style_id} × Layout-{layout_id}
|
||||
Combine: Pre-extracted layout structure + design tokens → Final HTML/CSS
|
||||
|
||||
TARGET: {target} | STYLE: {style_id} | LAYOUT: {layout_id}
|
||||
BASE_PATH: {base_path}
|
||||
|
||||
## Inputs (READ ONLY - NO DESIGN DECISIONS)
|
||||
1. Layout Template:
|
||||
Read("{base_path}/layout-extraction/layout-templates.json")
|
||||
Find template where: target={target} AND variant_id="layout-{layout_id}"
|
||||
Extract: dom_structure, css_layout_rules, device_type, source_image_path
|
||||
|
||||
2. Design Tokens:
|
||||
Read("{base_path}/style-extraction/style-{style_id}/design-tokens.json")
|
||||
Extract: ALL token values including:
|
||||
* colors, typography (with combinations), spacing, opacity
|
||||
* border_radius, shadows, breakpoints
|
||||
* component_styles (button, card, input variants)
|
||||
Note: typography.combinations, opacity, and component_styles fields contain preset configurations using var() references
|
||||
|
||||
3. Animation Tokens (OPTIONAL):
|
||||
IF exists("{base_path}/animation-extraction/animation-tokens.json"):
|
||||
Read("{base_path}/animation-extraction/animation-tokens.json")
|
||||
Extract: duration, easing, transitions, keyframes, interactions
|
||||
has_animations = true
|
||||
ELSE:
|
||||
has_animations = false
|
||||
|
||||
4. Reference Image (AUTO-DETECTED):
|
||||
IF template.source_image_path exists:
|
||||
Read(template.source_image_path)
|
||||
Purpose: Additional visual context for better placeholder content generation
|
||||
Note: This is for reference only - layout and style decisions already made
|
||||
ELSE:
|
||||
Use generic placeholder content
|
||||
|
||||
## Assembly Process
|
||||
1. Build HTML: {base_path}/prototypes/{target}-style-{style_id}-layout-{layout_id}.html
|
||||
- Recursively build from template.dom_structure
|
||||
- Add: <!DOCTYPE html>, <head>, <meta viewport>
|
||||
- CSS link: <link href="{target}-style-{style_id}-layout-{layout_id}.css">
|
||||
- Inject placeholder content:
|
||||
* Default: Use Lorem ipsum, generic sample data
|
||||
* If reference image available: Generate more contextually appropriate placeholders
|
||||
(e.g., realistic headings, meaningful text snippets that match the visual context)
|
||||
- Preserve all attributes from dom_structure
|
||||
|
||||
2. Build CSS: {base_path}/prototypes/{target}-style-{style_id}-layout-{layout_id}.css
|
||||
- Start with template.css_layout_rules
|
||||
- Replace ALL var(--*) with actual token values from design-tokens.json
|
||||
Example: var(--spacing-4) → 1rem (from tokens.spacing.4)
|
||||
Example: var(--breakpoint-md) → 768px (from tokens.breakpoints.md)
|
||||
Example: var(--opacity-80) → 0.8 (from tokens.opacity.80)
|
||||
- Add visual styling using design tokens:
|
||||
* Colors: tokens.colors.*
|
||||
* Typography: tokens.typography.* (including combinations)
|
||||
* Opacity: tokens.opacity.*
|
||||
* Shadows: tokens.shadows.*
|
||||
* Border radius: tokens.border_radius.*
|
||||
- IF tokens.component_styles exists: Add component style classes
|
||||
* Generate classes for button variants (.btn-primary, .btn-secondary)
|
||||
* Generate classes for card variants (.card-default, .card-interactive)
|
||||
* Generate classes for input variants (.input-default, .input-focus, .input-error)
|
||||
* Use var() references that resolve to actual token values
|
||||
- IF tokens.typography.combinations exists: Add typography preset classes
|
||||
* Generate classes for typography presets (.text-heading-primary, .text-body-regular, .text-caption)
|
||||
* Use var() references for family, size, weight, line-height, letter-spacing
|
||||
- IF has_animations == true: Inject animation tokens
|
||||
* Add CSS Custom Properties for animations at :root level:
|
||||
--duration-instant, --duration-fast, --duration-normal, etc.
|
||||
--easing-linear, --easing-ease-out, etc.
|
||||
* Add @keyframes rules from animation_tokens.keyframes
|
||||
* Add interaction classes (.button-hover, .card-hover) from animation_tokens.interactions
|
||||
* Add utility classes (.transition-color, .transition-transform) from animation_tokens.transitions
|
||||
* Include prefers-reduced-motion media query for accessibility
|
||||
- Device-optimized for template.device_type
|
||||
|
||||
## Assembly Rules
|
||||
- ✅ Pure assembly: Combine existing structure + existing style
|
||||
- ❌ NO layout design decisions (structure pre-defined)
|
||||
- ❌ NO style design decisions (tokens pre-defined)
|
||||
- ✅ Replace var() with actual values
|
||||
- ✅ Add placeholder content only
|
||||
- Write files IMMEDIATELY
|
||||
- CSS filename MUST match HTML <link href="...">
|
||||
`
|
||||
```
|
||||
|
||||
### Step 2: Verify Generated Files
|
||||
```bash
|
||||
# Count expected vs found
|
||||
bash(ls {base_path}/prototypes/{target}-style-*-layout-*.html | wc -l)
|
||||
|
||||
# Validate samples
|
||||
Read({base_path}/prototypes/{target}-style-{style_id}-layout-{layout_id}.html)
|
||||
# Check: <!DOCTYPE html>, correct CSS href, sufficient CSS length
|
||||
```
|
||||
|
||||
**Output**: `S × L × T × 2` files verified
|
||||
|
||||
## Phase 3: Generate Preview Files
|
||||
|
||||
### Step 1: Run Preview Generation Script
|
||||
```bash
|
||||
bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes")
|
||||
```
|
||||
|
||||
**Script generates**:
|
||||
- `compare.html` (interactive matrix)
|
||||
- `index.html` (navigation)
|
||||
- `PREVIEW.md` (instructions)
|
||||
|
||||
### Step 2: Verify Preview Files
|
||||
```bash
|
||||
bash(ls {base_path}/prototypes/compare.html {base_path}/prototypes/index.html {base_path}/prototypes/PREVIEW.md)
|
||||
```
|
||||
|
||||
**Output**: 3 preview files
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Setup and validation", status: "completed", activeForm: "Loading design systems"},
|
||||
{content: "Load layout templates", status: "completed", activeForm: "Reading layout templates"},
|
||||
{content: "Assembly (agent)", status: "completed", activeForm: "Assembling prototypes"},
|
||||
{content: "Verify files", status: "completed", activeForm: "Validating output"},
|
||||
{content: "Generate previews", status: "completed", activeForm: "Creating preview files"}
|
||||
]});
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ UI prototype assembly complete!
|
||||
|
||||
Configuration:
|
||||
- Style Variants: {style_variants}
|
||||
- Layout Variants: {layout_variants} (from layout-templates.json)
|
||||
- Device Type: {device_type}
|
||||
- Targets: {targets}
|
||||
- Total Prototypes: {S × L × T}
|
||||
- Image Reference: Auto-detected (uses source images when available in layout templates)
|
||||
|
||||
Assembly Process:
|
||||
- Pure assembly: Combined pre-extracted layouts + design tokens
|
||||
- No design decisions: All structure and style pre-defined
|
||||
- Assembly tasks: T×S×L = {T}×{S}×{L} = {T×S×L} combinations
|
||||
|
||||
Quality:
|
||||
- Structure: From layout-extract (DOM, CSS layout rules)
|
||||
- Style: From style-extract (design tokens)
|
||||
- CSS: Token values directly applied (var() replaced)
|
||||
- Device-optimized: Layouts match device_type from templates
|
||||
|
||||
Generated Files:
|
||||
{base_path}/prototypes/
|
||||
├── _templates/
|
||||
│ └── layout-templates.json (input, pre-extracted)
|
||||
├── {target}-style-{s}-layout-{l}.html ({S×L×T} prototypes)
|
||||
├── {target}-style-{s}-layout-{l}.css
|
||||
├── compare.html (interactive matrix)
|
||||
├── index.html (navigation)
|
||||
└── PREVIEW.md (instructions)
|
||||
|
||||
Preview:
|
||||
1. Open compare.html (recommended)
|
||||
2. Open index.html
|
||||
3. Read PREVIEW.md
|
||||
|
||||
Next: /workflow:ui-design:update
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1)
|
||||
|
||||
# Count style variants
|
||||
bash(ls {base_path}/style-extraction/style-* -d | wc -l)
|
||||
```
|
||||
|
||||
### Validation Commands
|
||||
```bash
|
||||
# Check layout templates exist
|
||||
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists")
|
||||
|
||||
# Check design tokens exist
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "valid")
|
||||
|
||||
# Count generated files
|
||||
bash(ls {base_path}/prototypes/{target}-style-*-layout-*.html | wc -l)
|
||||
|
||||
# Verify preview
|
||||
bash(test -f {base_path}/prototypes/compare.html && echo "exists")
|
||||
```
|
||||
|
||||
### File Operations
|
||||
```bash
|
||||
# Create directories
|
||||
bash(mkdir -p {base_path}/prototypes)
|
||||
|
||||
# Run preview script
|
||||
bash(~/.claude/scripts/ui-generate-preview.sh "{base_path}/prototypes")
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
├── layout-extraction/
|
||||
│ └── layout-templates.json # Input (from layout-extract)
|
||||
├── style-extraction/
|
||||
│ └── style-{s}/
|
||||
│ ├── design-tokens.json # Input (from style-extract)
|
||||
│ └── style-guide.md
|
||||
└── prototypes/
|
||||
├── {target}-style-{s}-layout-{l}.html # Assembled prototypes
|
||||
├── {target}-style-{s}-layout-{l}.css
|
||||
├── compare.html
|
||||
├── index.html
|
||||
└── PREVIEW.md
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: Layout templates not found
|
||||
→ Run /workflow:ui-design:layout-extract first
|
||||
|
||||
ERROR: Design tokens not found
|
||||
→ Run /workflow:ui-design:style-extract first
|
||||
|
||||
ERROR: Agent assembly failed
|
||||
→ Check inputs exist, validate JSON structure
|
||||
|
||||
ERROR: Script permission denied
|
||||
→ chmod +x ~/.claude/scripts/ui-generate-preview.sh
|
||||
```
|
||||
|
||||
### Recovery Strategies
|
||||
- **Partial success**: Keep successful assembly combinations
|
||||
- **Invalid template structure**: Validate layout-templates.json
|
||||
- **Invalid tokens**: Validate design-tokens.json structure
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- [ ] CSS uses direct token values (var() replaced)
|
||||
- [ ] HTML structure matches layout template exactly
|
||||
- [ ] Semantic HTML5 structure preserved
|
||||
- [ ] ARIA attributes from template present
|
||||
- [ ] Device-specific optimizations applied
|
||||
- [ ] All token references resolved
|
||||
- [ ] compare.html works
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Pure Assembly**: No design decisions, only combination
|
||||
- **Separation of Concerns**: Layout (structure) + Style (tokens) kept separate until final assembly
|
||||
- **Token Resolution**: var() placeholders replaced with actual values
|
||||
- **Pre-validated**: Inputs already validated by extract/consolidate
|
||||
- **Efficient**: Simple assembly vs complex generation
|
||||
- **Production-Ready**: Semantic, accessible, token-driven
|
||||
|
||||
## Integration
|
||||
|
||||
**Prerequisites**:
|
||||
- `/workflow:ui-design:style-extract` → `design-tokens.json` + `style-guide.md`
|
||||
- `/workflow:ui-design:layout-extract` → `layout-templates.json`
|
||||
|
||||
**Input**: `layout-templates.json` + `design-tokens.json`
|
||||
**Output**: S×L×T prototypes for `/workflow:ui-design:update`
|
||||
**Called by**: `/workflow:ui-design:explore-auto`, `/workflow:ui-design:imitate-auto`
|
||||
@@ -0,0 +1,682 @@
|
||||
---
|
||||
name: imitate-auto
|
||||
description: High-speed multi-page UI replication with batch screenshot capture and design token extraction
|
||||
argument-hint: --url-map "<map>" [--capture-mode <batch|deep>] [--depth <1-5>] [--session <id>] [--prompt "<desc>"]
|
||||
allowed-tools: SlashCommand(*), TodoWrite(*), Read(*), Write(*), Bash(*)
|
||||
---
|
||||
|
||||
# UI Design Imitate-Auto Workflow Command
|
||||
|
||||
## Overview & Execution Model
|
||||
|
||||
**Fully autonomous replication orchestrator**: Efficiently replicate multiple web pages through sequential execution from screenshot capture to design integration.
|
||||
|
||||
**Dual Capture Strategy**: Supports two capture modes for different use cases:
|
||||
- **Batch Mode** (default): Fast multi-URL screenshot capture via `/workflow:ui-design:capture`
|
||||
- **Deep Mode**: Interactive layer exploration for single URL via `/workflow:ui-design:explore-layers`
|
||||
|
||||
**Autonomous Flow** (⚠️ CONTINUOUS EXECUTION - DO NOT STOP):
|
||||
1. User triggers: `/workflow:ui-design:imitate-auto --url-map "..."`
|
||||
2. Phase 0: Initialize and parse parameters
|
||||
3. Phase 1: Screenshot capture (batch or deep mode) → **WAIT for completion** → Auto-continues
|
||||
4. Phase 2: Style extraction (complete design systems) → **WAIT for completion** → Auto-continues
|
||||
5. Phase 2.3: Animation extraction (CSS auto mode) → **WAIT for completion** → Auto-continues
|
||||
6. Phase 2.5: Layout extraction (structure templates) → **WAIT for completion** → Auto-continues
|
||||
7. Phase 3: Batch UI assembly → **WAIT for completion** → Auto-continues
|
||||
8. Phase 4: Design system integration → Reports completion
|
||||
|
||||
**Phase Transition Mechanism**:
|
||||
- `SlashCommand` is BLOCKING - execution pauses until completion
|
||||
- Upon each phase completion: Automatically process output and execute next phase
|
||||
- No user interaction required after initial parameter parsing
|
||||
|
||||
**Auto-Continue Mechanism**: TodoWrite tracks phase status. Upon each phase completion, you MUST immediately construct and execute the next phase command. No user intervention required. The workflow is NOT complete until reaching Phase 5.
|
||||
|
||||
## Core Rules
|
||||
|
||||
1. **Start Immediately**: TodoWrite initialization → Phase 1 execution
|
||||
2. **No Preliminary Validation**: Sub-commands handle their own validation
|
||||
3. **Parse & Pass**: Extract data from each output for next phase
|
||||
4. **Track Progress**: Update TodoWrite after each phase
|
||||
5. **⚠️ CRITICAL: DO NOT STOP** - This is a continuous multi-phase workflow. After each SlashCommand completes, you MUST wait for completion, then immediately execute the next phase. Workflow is NOT complete until Phase 5.
|
||||
|
||||
## Parameter Requirements
|
||||
|
||||
**Required Parameters**:
|
||||
- `--url-map "<map>"`: Target page mapping
|
||||
- Format: `"target1:url1, target2:url2, ..."`
|
||||
- Example: `"home:https://linear.app, pricing:https://linear.app/pricing"`
|
||||
- First target serves as primary style source
|
||||
|
||||
**Optional Parameters**:
|
||||
- `--capture-mode <batch|deep>` (Optional, default: batch): Screenshot capture strategy
|
||||
- `batch` (default): Multi-URL fast batch capture via `/workflow:ui-design:capture`
|
||||
- `deep`: Single-URL interactive depth exploration via `/workflow:ui-design:explore-layers`
|
||||
- **Note**: `deep` mode only uses first URL from url-map
|
||||
|
||||
- `--depth <1-5>` (Optional, default: 3): Capture depth for deep mode
|
||||
- `1`: Page level (full-page screenshot)
|
||||
- `2`: Element level (+ key components)
|
||||
- `3`: Interaction level (+ modals, dropdowns)
|
||||
- `4`: Embedded level (+ iframes)
|
||||
- `5`: Shadow DOM (+ web components)
|
||||
- **Only applies when** `--capture-mode deep`
|
||||
|
||||
- `--session <id>` (Optional): Workflow session ID
|
||||
- Integrate into existing session (`.workflow/WFS-{session}/`)
|
||||
- Enable automatic design system integration (Phase 5)
|
||||
- If not provided: standalone mode (`.workflow/.design/`)
|
||||
|
||||
- `--prompt "<desc>"` (Optional): Style extraction guidance
|
||||
- Influences extract command analysis focus
|
||||
- Example: `"Focus on dark mode"`, `"Emphasize minimalist design"`
|
||||
- **Note**: Design systems are now production-ready by default (no separate consolidate step)
|
||||
|
||||
## Execution Modes
|
||||
|
||||
**Capture Modes**:
|
||||
- **Batch Mode** (default): Multi-URL screenshot capture for fast replication
|
||||
- Uses `/workflow:ui-design:capture` for parallel screenshot capture
|
||||
- Optimized for replicating multiple pages efficiently
|
||||
- **Deep Mode**: Single-URL layer exploration for detailed analysis
|
||||
- Uses `/workflow:ui-design:explore-layers` for interactive depth traversal
|
||||
- Captures page layers at different depths (1-5)
|
||||
- Only processes first URL from url-map
|
||||
|
||||
**Token Processing**:
|
||||
- **Direct Generation**: Complete design systems generated in style-extract phase
|
||||
- Production-ready design-tokens.json with WCAG compliance
|
||||
- Complete style-guide.md documentation
|
||||
- No separate consolidation step required (~30-60s faster)
|
||||
|
||||
**Session Integration**:
|
||||
- `--session` flag determines session integration or standalone execution
|
||||
- Integrated: Design system automatically added to session artifacts
|
||||
- Standalone: Output in `.workflow/.design/{run_id}/`
|
||||
|
||||
## 6-Phase Execution
|
||||
|
||||
### Phase 0: Initialization and Target Parsing
|
||||
|
||||
```bash
|
||||
# Generate run ID
|
||||
run_id = "run-$(date +%Y%m%d-%H%M%S)"
|
||||
|
||||
# Determine base path and session mode
|
||||
IF --session:
|
||||
session_id = {provided_session}
|
||||
base_path = ".workflow/WFS-{session_id}/design-{run_id}"
|
||||
session_mode = "integrated"
|
||||
ELSE:
|
||||
session_id = null
|
||||
base_path = ".workflow/.design/{run_id}"
|
||||
session_mode = "standalone"
|
||||
|
||||
# Create base directory
|
||||
Bash(mkdir -p "{base_path}")
|
||||
|
||||
# Parse url-map
|
||||
url_map_string = {--url-map}
|
||||
VALIDATE: url_map_string is not empty, "--url-map parameter is required"
|
||||
|
||||
# Parse target:url pairs
|
||||
url_map = {} # {target_name: url}
|
||||
target_names = []
|
||||
|
||||
FOR pair IN split(url_map_string, ","):
|
||||
pair = pair.strip()
|
||||
|
||||
IF ":" NOT IN pair:
|
||||
ERROR: "Invalid url-map format: '{pair}'"
|
||||
ERROR: "Expected format: 'target:url'"
|
||||
ERROR: "Example: 'home:https://example.com, pricing:https://example.com/pricing'"
|
||||
EXIT 1
|
||||
|
||||
target, url = pair.split(":", 1)
|
||||
target = target.strip().lower().replace(" ", "-")
|
||||
url = url.strip()
|
||||
|
||||
url_map[target] = url
|
||||
target_names.append(target)
|
||||
|
||||
VALIDATE: len(target_names) > 0, "url-map must contain at least one target:url pair"
|
||||
|
||||
primary_target = target_names[0] # First target as primary style source
|
||||
|
||||
# Parse capture mode
|
||||
capture_mode = --capture-mode OR "batch"
|
||||
depth = int(--depth OR 3)
|
||||
|
||||
# Validate capture mode
|
||||
IF capture_mode NOT IN ["batch", "deep"]:
|
||||
ERROR: "Invalid --capture-mode: {capture_mode}"
|
||||
ERROR: "Valid options: batch, deep"
|
||||
EXIT 1
|
||||
|
||||
# Validate depth (only for deep mode)
|
||||
IF capture_mode == "deep":
|
||||
IF depth NOT IN [1, 2, 3, 4, 5]:
|
||||
ERROR: "Invalid --depth: {depth}"
|
||||
ERROR: "Valid range: 1-5"
|
||||
EXIT 1
|
||||
|
||||
# Warn if multiple URLs in deep mode
|
||||
IF len(target_names) > 1:
|
||||
WARN: "⚠️ Deep mode only uses first URL: '{primary_target}'"
|
||||
WARN: " Other URLs will be ignored: {', '.join(target_names[1:])}"
|
||||
WARN: " For multi-URL, use --capture-mode batch"
|
||||
|
||||
# Write metadata
|
||||
metadata = {
|
||||
"workflow": "imitate-auto",
|
||||
"run_id": run_id,
|
||||
"session_id": session_id,
|
||||
"timestamp": current_timestamp(),
|
||||
"parameters": {
|
||||
"url_map": url_map,
|
||||
"capture_mode": capture_mode,
|
||||
"depth": depth IF capture_mode == "deep" ELSE null,
|
||||
"prompt": --prompt OR null
|
||||
},
|
||||
"targets": target_names,
|
||||
"status": "in_progress"
|
||||
}
|
||||
|
||||
Write("{base_path}/.run-metadata.json", JSON.stringify(metadata, null, 2))
|
||||
|
||||
# Initialize TodoWrite
|
||||
TodoWrite({todos: [
|
||||
{content: "Initialize and parse url-map", status: "completed", activeForm: "Initializing"},
|
||||
{content: capture_mode == "batch" ? f"Batch screenshot capture ({len(target_names)} targets)" : f"Deep exploration (depth {depth})", status: "pending", activeForm: "Capturing screenshots"},
|
||||
{content: "Extract style (complete design systems)", status: "pending", activeForm: "Extracting style"},
|
||||
{content: "Extract animation (CSS auto mode)", status: "pending", activeForm: "Extracting animation"},
|
||||
{content: "Extract layout (structure templates)", status: "pending", activeForm: "Extracting layout"},
|
||||
{content: f"Assemble UI for {len(target_names)} targets", status: "pending", activeForm: "Assembling UI"},
|
||||
{content: session_id ? "Integrate design system" : "Standalone completion", status: "pending", activeForm: "Completing"}
|
||||
]})
|
||||
```
|
||||
|
||||
### Phase 1: Screenshot Capture (Dual Mode)
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 1: Screenshot Capture"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
IF capture_mode == "batch":
|
||||
# Mode A: Batch Multi-URL Capture
|
||||
url_map_command_string = ",".join([f"{name}:{url}" for name, url in url_map.items()])
|
||||
capture_command = f"/workflow:ui-design:capture --base-path \"{base_path}\" --url-map \"{url_map_command_string}\""
|
||||
|
||||
TRY:
|
||||
SlashCommand(capture_command)
|
||||
CATCH error:
|
||||
ERROR: "Batch capture failed: {error}"
|
||||
ERROR: "Cannot proceed without screenshots"
|
||||
EXIT 1
|
||||
|
||||
# Verify batch capture results
|
||||
screenshot_metadata_path = "{base_path}/screenshots/capture-metadata.json"
|
||||
|
||||
IF NOT exists(screenshot_metadata_path):
|
||||
ERROR: "capture command did not generate metadata file"
|
||||
ERROR: "Expected: {screenshot_metadata_path}"
|
||||
EXIT 1
|
||||
|
||||
screenshot_metadata = Read(screenshot_metadata_path)
|
||||
captured_count = screenshot_metadata.total_captured
|
||||
total_requested = screenshot_metadata.total_requested
|
||||
missing_count = total_requested - captured_count
|
||||
|
||||
IF missing_count > 0:
|
||||
missing_targets = [s.target for s in screenshot_metadata.screenshots if not s.captured]
|
||||
WARN: "⚠️ Missing {missing_count} screenshots: {', '.join(missing_targets)}"
|
||||
|
||||
IF captured_count == 0:
|
||||
ERROR: "No screenshots captured - cannot proceed"
|
||||
EXIT 1
|
||||
|
||||
ELSE: # capture_mode == "deep"
|
||||
# Mode B: Deep Interactive Layer Exploration
|
||||
primary_url = url_map[primary_target]
|
||||
explore_command = f"/workflow:ui-design:explore-layers --url \"{primary_url}\" --depth {depth} --base-path \"{base_path}\""
|
||||
|
||||
TRY:
|
||||
SlashCommand(explore_command)
|
||||
CATCH error:
|
||||
ERROR: "Deep exploration failed: {error}"
|
||||
ERROR: "Cannot proceed without screenshots"
|
||||
EXIT 1
|
||||
|
||||
# Verify deep exploration results
|
||||
layer_map_path = "{base_path}/screenshots/layer-map.json"
|
||||
|
||||
IF NOT exists(layer_map_path):
|
||||
ERROR: "explore-layers did not generate layer-map.json"
|
||||
ERROR: "Expected: {layer_map_path}"
|
||||
EXIT 1
|
||||
|
||||
layer_map = Read(layer_map_path)
|
||||
captured_count = layer_map.summary.total_captures
|
||||
total_requested = captured_count # For consistency with batch mode
|
||||
|
||||
TodoWrite(mark_completed: f"Batch screenshot capture ({len(target_names)} targets)" IF capture_mode == "batch" ELSE f"Deep exploration (depth {depth})",
|
||||
mark_in_progress: "Extract style (visual tokens)")
|
||||
```
|
||||
|
||||
### Phase 2: Style Extraction (Visual Tokens)
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 2: Style Extraction"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Use all screenshots as input to extract single design system
|
||||
IF capture_mode == "batch":
|
||||
images_glob = f"{base_path}/screenshots/*.{{png,jpg,jpeg,webp}}"
|
||||
ELSE: # deep mode
|
||||
images_glob = f"{base_path}/screenshots/**/*.{{png,jpg,jpeg,webp}}"
|
||||
|
||||
# Build extraction prompt
|
||||
IF --prompt:
|
||||
user_guidance = {--prompt}
|
||||
extraction_prompt = f"Extract visual style tokens from '{primary_target}'. User guidance: {user_guidance}"
|
||||
ELSE:
|
||||
extraction_prompt = f"Extract visual style tokens from '{primary_target}' with consistency across all pages."
|
||||
|
||||
# Build url-map string for style-extract (enables computed styles extraction)
|
||||
url_map_for_extract = ",".join([f"{name}:{url}" for name, url in url_map.items()])
|
||||
|
||||
# Call style-extract command (imitate mode, automatically uses single variant)
|
||||
# Pass --urls to enable auto-trigger of computed styles extraction
|
||||
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"
|
||||
|
||||
TRY:
|
||||
SlashCommand(extract_command)
|
||||
CATCH error:
|
||||
ERROR: "Style extraction failed: {error}"
|
||||
ERROR: "Cannot proceed without visual tokens"
|
||||
EXIT 1
|
||||
|
||||
# Verify extraction results
|
||||
design_tokens_path = "{base_path}/style-extraction/style-1/design-tokens.json"
|
||||
style_guide_path = "{base_path}/style-extraction/style-1/style-guide.md"
|
||||
|
||||
IF NOT exists(design_tokens_path) OR NOT exists(style_guide_path):
|
||||
ERROR: "style-extract did not generate required files"
|
||||
EXIT 1
|
||||
|
||||
TodoWrite(mark_completed: "Extract style (complete design systems)",
|
||||
mark_in_progress: "Extract animation (CSS auto mode)")
|
||||
```
|
||||
|
||||
### Phase 2.3: Animation Extraction (CSS Auto Mode)
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 2.3: Animation Extraction"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Build URL list for animation-extract (auto mode for CSS extraction)
|
||||
url_map_for_animation = ",".join([f"{target}:{url}" for target, url in url_map.items()])
|
||||
|
||||
# Call animation-extract command (auto mode for CSS animation extraction)
|
||||
# Pass --urls to auto-trigger CSS animation/transition extraction via Chrome DevTools
|
||||
animation_extract_command = f"/workflow:ui-design:animation-extract --base-path \"{base_path}\" --urls \"{url_map_for_animation}\" --mode auto"
|
||||
|
||||
TRY:
|
||||
SlashCommand(animation_extract_command)
|
||||
CATCH error:
|
||||
ERROR: "Animation extraction failed: {error}"
|
||||
ERROR: "Cannot proceed without animation tokens"
|
||||
EXIT 1
|
||||
|
||||
# Verify animation extraction results
|
||||
animation_tokens_path = "{base_path}/animation-extraction/animation-tokens.json"
|
||||
animation_guide_path = "{base_path}/animation-extraction/animation-guide.md"
|
||||
|
||||
IF NOT exists(animation_tokens_path) OR NOT exists(animation_guide_path):
|
||||
ERROR: "animation-extract did not generate required files"
|
||||
EXIT 1
|
||||
|
||||
TodoWrite(mark_completed: "Extract animation (CSS auto mode)",
|
||||
mark_in_progress: "Extract layout (structure templates)")
|
||||
```
|
||||
|
||||
### Phase 2.5: Layout Extraction (Structure Templates)
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 2.5: Layout Extraction"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Build URL map for layout-extract
|
||||
url_map_for_layout = ",".join([f"{target}:{url}" for target, url in url_map.items()])
|
||||
|
||||
# Call layout-extract command (imitate mode for structure replication)
|
||||
# Pass --urls to enable auto-trigger of DOM structure extraction
|
||||
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"
|
||||
|
||||
TRY:
|
||||
SlashCommand(layout_extract_command)
|
||||
CATCH error:
|
||||
ERROR: "Layout extraction failed: {error}"
|
||||
ERROR: "Cannot proceed without layout templates"
|
||||
EXIT 1
|
||||
|
||||
# Verify layout extraction results
|
||||
layout_templates_path = "{base_path}/layout-extraction/layout-templates.json"
|
||||
|
||||
IF NOT exists(layout_templates_path):
|
||||
ERROR: "layout-extract did not generate layout-templates.json"
|
||||
EXIT 1
|
||||
|
||||
TodoWrite(mark_completed: "Extract layout (structure templates)",
|
||||
mark_in_progress: f"Assemble UI for {len(target_names)} targets")
|
||||
```
|
||||
|
||||
### Phase 3: Batch UI Assembly
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 3: UI Assembly"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
# Call generate command (pure assembler - combines layout templates + design tokens)
|
||||
generate_command = f"/workflow:ui-design:generate --base-path \"{base_path}\" --style-variants 1 --layout-variants 1"
|
||||
|
||||
TRY:
|
||||
SlashCommand(generate_command)
|
||||
CATCH error:
|
||||
ERROR: "UI assembly failed: {error}"
|
||||
ERROR: "Layout templates or design tokens may be invalid"
|
||||
EXIT 1
|
||||
|
||||
# Verify assembly results
|
||||
prototypes_dir = "{base_path}/prototypes"
|
||||
generated_html_files = Glob(f"{prototypes_dir}/*-style-1-layout-1.html")
|
||||
generated_count = len(generated_html_files)
|
||||
|
||||
IF generated_count < len(target_names):
|
||||
WARN: "⚠️ Expected {len(target_names)} prototypes, assembled {generated_count}"
|
||||
|
||||
TodoWrite(mark_completed: f"Assemble UI for {len(target_names)} targets",
|
||||
mark_in_progress: session_id ? "Integrate design system" : "Standalone completion")
|
||||
```
|
||||
|
||||
### Phase 4: Design System Integration
|
||||
|
||||
```bash
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
REPORT: "🚀 Phase 4: Design System Integration"
|
||||
REPORT: "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
|
||||
IF session_id:
|
||||
update_command = f"/workflow:ui-design:update --session {session_id}"
|
||||
|
||||
TRY:
|
||||
SlashCommand(update_command)
|
||||
CATCH error:
|
||||
WARN: "⚠️ Design system integration failed: {error}"
|
||||
WARN: "Prototypes available at {base_path}/prototypes/"
|
||||
|
||||
# Update metadata
|
||||
metadata = Read("{base_path}/.run-metadata.json")
|
||||
metadata.status = "completed"
|
||||
metadata.completion_time = current_timestamp()
|
||||
metadata.outputs = {
|
||||
"screenshots": f"{base_path}/screenshots/",
|
||||
"style_system": f"{base_path}/style-extraction/style-1/",
|
||||
"prototypes": f"{base_path}/prototypes/",
|
||||
"captured_count": captured_count,
|
||||
"generated_count": generated_count
|
||||
}
|
||||
Write("{base_path}/.run-metadata.json", JSON.stringify(metadata, null, 2))
|
||||
|
||||
TodoWrite(mark_completed: session_id ? "Integrate design system" : "Standalone completion")
|
||||
|
||||
# Mark all phases complete
|
||||
TodoWrite({todos: [
|
||||
{content: "Initialize and parse url-map", status: "completed", activeForm: "Initializing"},
|
||||
{content: capture_mode == "batch" ? f"Batch screenshot capture ({len(target_names)} targets)" : f"Deep exploration (depth {depth})", status: "completed", activeForm: "Capturing"},
|
||||
{content: "Extract style (complete design systems)", status: "completed", activeForm: "Extracting"},
|
||||
{content: "Extract animation (CSS auto mode)", status: "completed", activeForm: "Extracting animation"},
|
||||
{content: "Extract layout (structure templates)", status: "completed", activeForm: "Extracting layout"},
|
||||
{content: f"Assemble UI for {len(target_names)} targets", status: "completed", activeForm: "Assembling"},
|
||||
{content: session_id ? "Integrate design system" : "Standalone completion", status: "completed", activeForm: "Completing"}
|
||||
]})
|
||||
```
|
||||
|
||||
### Phase 6: Completion Report
|
||||
|
||||
**Completion Message**:
|
||||
```
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ UI Design Imitate-Auto Complete!
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
━━━ 📊 Workflow Summary ━━━
|
||||
|
||||
Mode: {capture_mode == "batch" ? "Batch Multi-Page Replication" : f"Deep Interactive Exploration (depth {depth})"}
|
||||
Session: {session_id or "standalone"}
|
||||
Run ID: {run_id}
|
||||
|
||||
Phase 1 - Screenshot Capture: ✅ {IF capture_mode == "batch": f"{captured_count}/{total_requested} screenshots" ELSE: f"{captured_count} screenshots ({total_layers} layers)"}
|
||||
{IF capture_mode == "batch" AND captured_count < total_requested: f"⚠️ {total_requested - captured_count} missing" ELSE: "All targets captured"}
|
||||
|
||||
Phase 2 - Style Extraction: ✅ Production-ready design systems
|
||||
Output: style-extraction/style-1/ (design-tokens.json + style-guide.md)
|
||||
Quality: WCAG AA compliant, OKLCH colors
|
||||
|
||||
Phase 2.3 - Animation Extraction: ✅ CSS animations and transitions
|
||||
Output: animation-extraction/ (animation-tokens.json + animation-guide.md)
|
||||
Method: Auto-extracted from live URLs via Chrome DevTools
|
||||
|
||||
Phase 2.5 - Layout Extraction: ✅ Structure templates
|
||||
Templates: {template_count} layout structures
|
||||
|
||||
Phase 3 - UI Assembly: ✅ {generated_count} pages assembled
|
||||
Targets: {', '.join(target_names)}
|
||||
Configuration: 1 style × 1 layout × {generated_count} pages
|
||||
|
||||
Phase 4 - Integration: {IF session_id: "✅ Integrated into session" ELSE: "⏭️ Standalone mode"}
|
||||
|
||||
━━━ 📂 Output Structure ━━━
|
||||
|
||||
{base_path}/
|
||||
├── screenshots/ # {captured_count} screenshots
|
||||
{IF capture_mode == "batch":
|
||||
│ ├── {target1}.png
|
||||
│ ├── {target2}.png
|
||||
│ └── capture-metadata.json
|
||||
ELSE:
|
||||
│ ├── depth-1/
|
||||
│ │ └── full-page.png
|
||||
│ ├── depth-2/
|
||||
│ │ └── {elements}.png
|
||||
│ ├── depth-{depth}/
|
||||
│ │ └── {layers}.png
|
||||
│ └── layer-map.json
|
||||
}
|
||||
├── style-extraction/ # Production-ready design systems
|
||||
│ └── style-1/
|
||||
│ ├── design-tokens.json
|
||||
│ └── style-guide.md
|
||||
├── animation-extraction/ # CSS animations and transitions
|
||||
│ ├── animation-tokens.json
|
||||
│ └── animation-guide.md
|
||||
├── layout-extraction/ # Structure templates
|
||||
│ └── layout-templates.json
|
||||
└── prototypes/ # {generated_count} HTML/CSS files
|
||||
├── {target1}-style-1-layout-1.html + .css
|
||||
├── {target2}-style-1-layout-1.html + .css
|
||||
├── compare.html # Interactive preview
|
||||
└── index.html # Quick navigation
|
||||
|
||||
━━━ ⚡ Performance ━━━
|
||||
|
||||
Total workflow time: ~{estimate_total_time()} minutes
|
||||
Screenshot capture: ~{capture_time}
|
||||
Style extraction: ~{extract_time}
|
||||
Token processing: ~{token_processing_time}
|
||||
UI generation: ~{generate_time}
|
||||
|
||||
━━━ 🌐 Next Steps ━━━
|
||||
|
||||
1. Preview prototypes:
|
||||
• Interactive matrix: Open {base_path}/prototypes/compare.html
|
||||
• Quick navigation: Open {base_path}/prototypes/index.html
|
||||
|
||||
{IF session_id:
|
||||
2. Create implementation tasks:
|
||||
/workflow:plan --session {session_id}
|
||||
|
||||
3. Generate tests (if needed):
|
||||
/workflow:test-gen {session_id}
|
||||
ELSE:
|
||||
2. To integrate into a workflow session:
|
||||
• Create session: /workflow:session:start
|
||||
• Copy design-tokens.json to session artifacts
|
||||
|
||||
3. Explore prototypes in {base_path}/prototypes/ directory
|
||||
}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
```
|
||||
|
||||
## TodoWrite Pattern
|
||||
|
||||
```javascript
|
||||
// Initialize IMMEDIATELY at start of Phase 0 to track multi-phase execution
|
||||
TodoWrite({todos: [
|
||||
{content: "Initialize and parse url-map", status: "in_progress", activeForm: "Initializing"},
|
||||
{content: "Batch screenshot capture", status: "pending", activeForm: "Capturing screenshots"},
|
||||
{content: "Extract style (complete design systems)", status: "pending", activeForm: "Extracting style"},
|
||||
{content: "Extract layout (structure templates)", status: "pending", activeForm: "Extracting layout"},
|
||||
{content: "Assemble UI for all targets", status: "pending", activeForm: "Assembling UI"},
|
||||
{content: "Integrate design system", status: "pending", activeForm: "Integrating"}
|
||||
]})
|
||||
|
||||
// ⚠️ CRITICAL: After EACH SlashCommand completion (Phase 1-5), you MUST:
|
||||
// 1. SlashCommand blocks and returns when phase is complete
|
||||
// 2. Update current phase: status → "completed"
|
||||
// 3. Update next phase: status → "in_progress"
|
||||
// 4. IMMEDIATELY execute next phase SlashCommand (auto-continue)
|
||||
// This ensures continuous workflow tracking and prevents premature stopping
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Pre-execution Checks
|
||||
- **url-map format validation**: Clear error message with format example
|
||||
- **Empty url-map**: Error and exit
|
||||
- **Invalid target names**: Regex validation with suggestions
|
||||
|
||||
### Phase-Specific Errors
|
||||
- **Screenshot capture failure (Phase 1)**:
|
||||
- If total_captured == 0: Terminate workflow
|
||||
- If partial failure: Warn but continue with available screenshots
|
||||
|
||||
- **Style extraction failure (Phase 2)**:
|
||||
- If extract fails: Terminate with clear error
|
||||
- If style-cards.json missing: Terminate with debugging info
|
||||
|
||||
- **Token processing failure (Phase 3)**:
|
||||
- Consolidate mode: Terminate if consolidate fails
|
||||
- Fast mode: Validate proposed_tokens exist before copying
|
||||
|
||||
- **UI generation failure (Phase 4)**:
|
||||
- If generate fails: Terminate with error
|
||||
- If generated_count < target_count: Warn but proceed
|
||||
|
||||
- **Integration failure (Phase 5)**:
|
||||
- Non-blocking: Warn but don't terminate
|
||||
- Prototypes already available
|
||||
|
||||
### Recovery Strategies
|
||||
- **Partial screenshot failure**: Continue with available screenshots, list missing in warning
|
||||
- **Generate failure**: Report specific target failures, user can re-generate individually
|
||||
- **Integration failure**: Prototypes still usable, can integrate manually
|
||||
|
||||
|
||||
## Key Features
|
||||
|
||||
- **🚀 Dual Capture**: Batch mode for speed, deep mode for detail
|
||||
- **⚡ Production-Ready**: Complete design systems generated directly (~30-60s faster)
|
||||
- **🎨 High-Fidelity**: Single unified design system from primary target
|
||||
- **📦 Autonomous**: No user intervention required between phases
|
||||
- **🔄 Reproducible**: Deterministic flow with isolated run directories
|
||||
- **🎯 Flexible**: Standalone or session-integrated modes
|
||||
|
||||
## Examples
|
||||
|
||||
### 1. Basic Multi-Page Replication
|
||||
```bash
|
||||
/workflow:ui-design:imitate-auto --url-map "home:https://linear.app, features:https://linear.app/features"
|
||||
# Result: 2 prototypes with fast-track tokens
|
||||
```
|
||||
|
||||
### 2. Session Integration
|
||||
```bash
|
||||
/workflow:ui-design:imitate-auto --session WFS-payment --url-map "pricing:https://stripe.com/pricing"
|
||||
# Result: 1 prototype with production-ready design system, integrated into session
|
||||
```
|
||||
|
||||
### 3. Deep Exploration Mode
|
||||
```bash
|
||||
/workflow:ui-design:imitate-auto --url-map "app:https://app.com" --capture-mode deep --depth 3
|
||||
# Result: Interactive layer capture + prototype
|
||||
```
|
||||
|
||||
### 4. Guided Style Extraction
|
||||
```bash
|
||||
/workflow:ui-design:imitate-auto --url-map "home:https://example.com, about:https://example.com/about" --prompt "Focus on minimalist design"
|
||||
# Result: 2 prototypes with minimalist style focus
|
||||
```
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **Input**: `--url-map` (multiple target:url pairs) + optional `--capture-mode`, `--depth`, `--session`, `--prompt`
|
||||
- **Output**: Complete design system in `{base_path}/` (screenshots, style-extraction, layout-extraction, prototypes)
|
||||
- **Sub-commands Called**:
|
||||
1. Phase 1 (conditional):
|
||||
- `--capture-mode batch`: `/workflow:ui-design:capture` (multi-URL batch)
|
||||
- `--capture-mode deep`: `/workflow:ui-design:explore-layers` (single-URL depth exploration)
|
||||
2. `/workflow:ui-design:style-extract` (Phase 2 - complete design systems)
|
||||
3. `/workflow:ui-design:animation-extract` (Phase 2.3 - CSS animations and transitions)
|
||||
4. `/workflow:ui-design:layout-extract` (Phase 2.5 - structure templates)
|
||||
5. `/workflow:ui-design:generate` (Phase 3 - pure assembly)
|
||||
6. `/workflow:ui-design:update` (Phase 4, if --session)
|
||||
|
||||
## Completion Output
|
||||
|
||||
```
|
||||
✅ UI Design Imitate-Auto Workflow Complete!
|
||||
|
||||
Mode: {capture_mode} | Session: {session_id or "standalone"}
|
||||
Run ID: {run_id}
|
||||
|
||||
Phase 1 - Screenshot Capture: ✅ {captured_count} screenshots
|
||||
Phase 2 - Style Extraction: ✅ Production-ready design systems
|
||||
Phase 2.5 - Layout Extraction: ✅ Structure templates
|
||||
Phase 3 - UI Assembly: ✅ {generated_count} pages assembled
|
||||
Phase 4 - Integration: {IF session_id: "✅ Integrated" ELSE: "⏭️ Standalone"}
|
||||
|
||||
Design Quality:
|
||||
✅ High-Fidelity Replication: Accurate style from primary target
|
||||
✅ Token-Driven Styling: 100% var() usage
|
||||
✅ Production-Ready: WCAG AA compliant, OKLCH colors
|
||||
|
||||
📂 {base_path}/
|
||||
├── screenshots/ # {captured_count} screenshots
|
||||
├── style-extraction/style-1/ # Production-ready design system
|
||||
├── layout-extraction/ # Structure templates
|
||||
└── prototypes/ # {generated_count} HTML/CSS files
|
||||
|
||||
🌐 Preview: {base_path}/prototypes/compare.html
|
||||
- Interactive preview
|
||||
- Side-by-side comparison
|
||||
- {generated_count} replicated pages
|
||||
|
||||
Next: [/workflow:execute] OR [Open compare.html → /workflow:plan]
|
||||
```
|
||||
@@ -0,0 +1,746 @@
|
||||
---
|
||||
name: layout-extract
|
||||
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>]
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), Bash(*), Task(ui-design-agent), mcp__exa__web_search_exa(*)
|
||||
---
|
||||
|
||||
# Layout Extraction Command
|
||||
|
||||
## Overview
|
||||
|
||||
Extract structural layout information from reference images, URLs, or text prompts using AI analysis. This command separates the "scaffolding" (HTML structure and CSS layout) from the "paint" (visual tokens handled by `style-extract`).
|
||||
|
||||
**Strategy**: AI-Driven Structural Analysis
|
||||
|
||||
- **Agent-Powered**: Uses `ui-design-agent` for deep structural analysis
|
||||
- **Dual-Mode**:
|
||||
- `imitate`: High-fidelity replication of single layout structure
|
||||
- `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)
|
||||
- **Token-Based**: CSS uses `var()` placeholders for spacing and breakpoints
|
||||
|
||||
## Phase 0: Setup & Input Validation
|
||||
|
||||
### Step 1: Detect Input, Mode & Targets
|
||||
|
||||
```bash
|
||||
# Detect input source
|
||||
# Priority: --urls + --images → hybrid | --urls → url | --images → image | --prompt → text
|
||||
|
||||
# Parse URLs if provided (format: "target:url,target:url,...")
|
||||
IF --urls:
|
||||
url_list = []
|
||||
FOR pair IN split(--urls, ","):
|
||||
IF ":" IN pair:
|
||||
target, url = pair.split(":", 1)
|
||||
url_list.append({target: target.strip(), url: url.strip()})
|
||||
ELSE:
|
||||
# Single URL without target
|
||||
url_list.append({target: "page", url: pair.strip()})
|
||||
|
||||
has_urls = true
|
||||
ELSE:
|
||||
has_urls = false
|
||||
url_list = []
|
||||
|
||||
# Determine extraction mode
|
||||
extraction_mode = --mode OR "imitate" # "imitate" or "explore"
|
||||
|
||||
# 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
|
||||
|
||||
# Resolve targets
|
||||
# Priority: --targets → url_list targets → prompt analysis → default ["page"]
|
||||
IF --targets:
|
||||
targets = split(--targets, ",")
|
||||
ELSE IF has_urls:
|
||||
targets = [url_info.target for url_info in url_list]
|
||||
ELSE IF --prompt:
|
||||
targets = extract_from_prompt(--prompt)
|
||||
ELSE:
|
||||
targets = ["page"]
|
||||
|
||||
# Resolve device type
|
||||
device_type = --device-type OR "responsive" # desktop|mobile|tablet|responsive
|
||||
|
||||
# Determine base path
|
||||
bash(find .workflow -type d -name "design-*" | head -1) # Auto-detect
|
||||
# OR use --base-path / --session parameters
|
||||
```
|
||||
|
||||
### Step 2: Load Inputs & Create Directories
|
||||
```bash
|
||||
# For image mode
|
||||
bash(ls {images_pattern}) # Expand glob pattern
|
||||
Read({image_path}) # Load each image
|
||||
|
||||
# For URL mode
|
||||
# Parse URL list format: "target:url,target:url"
|
||||
# Validate URLs are accessible
|
||||
|
||||
# For text mode
|
||||
# Validate --prompt is non-empty
|
||||
|
||||
# Create output directory
|
||||
bash(mkdir -p {base_path}/layout-extraction)
|
||||
```
|
||||
|
||||
### Step 2.5: Extract DOM Structure (URL Mode - Auto-Trigger)
|
||||
```bash
|
||||
# AUTO-TRIGGER: If URLs are available (from --urls parameter), automatically extract real DOM structure
|
||||
# This provides accurate layout data to supplement visual analysis
|
||||
|
||||
# Check if URLs provided via --urls parameter
|
||||
IF --urls AND url_list:
|
||||
REPORT: "🔍 Auto-triggering URL mode: Extracting DOM structure"
|
||||
|
||||
bash(mkdir -p {base_path}/.intermediates/layout-analysis)
|
||||
|
||||
# For each URL in url_list:
|
||||
FOR url_info IN url_list:
|
||||
target = url_info.target
|
||||
url = url_info.url
|
||||
|
||||
IF mcp_chrome_devtools_available:
|
||||
REPORT: " Processing: {target} ({url})"
|
||||
|
||||
# Read extraction script
|
||||
script_content = Read(~/.claude/scripts/extract-layout-structure.js)
|
||||
|
||||
# Open page in Chrome DevTools
|
||||
mcp__chrome-devtools__navigate_page(url=url)
|
||||
|
||||
# Execute layout extraction script
|
||||
result = mcp__chrome-devtools__evaluate_script(function=script_content)
|
||||
|
||||
# Save DOM structure for this target (intermediate file)
|
||||
Write({base_path}/.intermediates/layout-analysis/dom-structure-{target}.json, result)
|
||||
|
||||
REPORT: " ✅ DOM structure extracted for '{target}'"
|
||||
ELSE:
|
||||
REPORT: " ⚠️ Chrome DevTools MCP not available, falling back to visual analysis"
|
||||
BREAK
|
||||
|
||||
dom_structure_available = mcp_chrome_devtools_available
|
||||
ELSE:
|
||||
dom_structure_available = false
|
||||
```
|
||||
|
||||
**Extraction Script Reference**: `~/.claude/scripts/extract-layout-structure.js`
|
||||
|
||||
**Usage**: Read the script file and use content directly in `mcp__chrome-devtools__evaluate_script()`
|
||||
|
||||
**Script returns**:
|
||||
- `metadata`: Extraction timestamp, URL, method, version
|
||||
- `patterns`: Layout pattern statistics (flexColumn, flexRow, grid counts)
|
||||
- `structure`: Hierarchical DOM tree with layout properties
|
||||
- `exploration`: (Optional) Progressive exploration results when standard selectors fail
|
||||
|
||||
**Benefits**:
|
||||
- ✅ Real flex/grid configuration (justifyContent, alignItems, gap, etc.)
|
||||
- ✅ Accurate element bounds (x, y, width, height)
|
||||
- ✅ Structural hierarchy with depth control
|
||||
- ✅ Layout pattern identification (flex-row, flex-column, grid-NCol)
|
||||
- ✅ Progressive exploration: Auto-discovers missing selectors
|
||||
|
||||
**Progressive Exploration Strategy** (v2.2.0+):
|
||||
|
||||
When script finds <3 main containers, it automatically:
|
||||
1. **Scans** all large visible containers (≥500×300px)
|
||||
2. **Extracts** class patterns matching: `main|content|wrapper|container|page|layout|app`
|
||||
3. **Suggests** new selectors to add to script
|
||||
4. **Returns** exploration data in `result.exploration`:
|
||||
```json
|
||||
{
|
||||
"triggered": true,
|
||||
"discoveredCandidates": [{classes, bounds, display}],
|
||||
"suggestedSelectors": [".wrapper", ".page-index"],
|
||||
"recommendation": ".wrapper, .page-index, .app-container"
|
||||
}
|
||||
```
|
||||
|
||||
**Using Exploration Results**:
|
||||
```javascript
|
||||
// After extraction, check for suggestions
|
||||
IF result.exploration?.triggered:
|
||||
REPORT: result.exploration.warning
|
||||
REPORT: "Suggested selectors: " + result.exploration.recommendation
|
||||
|
||||
// Update script by adding to commonClassSelectors array
|
||||
// Then re-run extraction for better coverage
|
||||
```
|
||||
|
||||
**Selector Update Workflow**:
|
||||
1. Run extraction on unfamiliar site
|
||||
2. Check `result.exploration.suggestedSelectors`
|
||||
3. Add relevant selectors to script's `commonClassSelectors`
|
||||
4. Re-run extraction → improved container detection
|
||||
|
||||
### Step 3: Memory Check
|
||||
```bash
|
||||
# 1. Check if inputs cached in session memory
|
||||
IF session_has_inputs: SKIP Step 2 file reading
|
||||
|
||||
# 2. Check if output already exists
|
||||
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists")
|
||||
IF exists: SKIP to completion
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Phase 0 Output**: `input_mode`, `base_path`, `extraction_mode`, `variants_count`, `targets[]`, `device_type`, loaded inputs
|
||||
|
||||
## Phase 1: Layout Concept Generation (Explore Mode Only)
|
||||
|
||||
### Step 1: Check Extraction Mode
|
||||
```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)`
|
||||
|
||||
Launch agent to generate `variants_count` layout concept options for each target:
|
||||
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[LAYOUT_CONCEPT_GENERATION_TASK]
|
||||
Generate {variants_count} structurally distinct layout concepts for each target
|
||||
|
||||
SESSION: {session_id} | MODE: explore | BASE_PATH: {base_path}
|
||||
TARGETS: {targets} | DEVICE_TYPE: {device_type}
|
||||
|
||||
## Input Analysis
|
||||
- Targets: {targets.join(", ")}
|
||||
- Device type: {device_type}
|
||||
- Layout inspiration: Read inspirations from {base_path}/.intermediates/layout-analysis/inspirations/
|
||||
- Visual references: {loaded_images if available}
|
||||
${dom_structure_available ? "- DOM Structure: Read from .intermediates/layout-analysis/dom-structure-*.json" : ""}
|
||||
|
||||
## Analysis Rules
|
||||
- For EACH target, generate {variants_count} structurally DIFFERENT layout concepts
|
||||
- Concepts must differ in: grid structure, component arrangement, visual hierarchy
|
||||
- Each concept should have distinct navigation pattern, content flow, and responsive behavior
|
||||
|
||||
## Generate for EACH Target
|
||||
For target in {targets}:
|
||||
For concept_index in 1..{variants_count}:
|
||||
1. **Concept Definition**:
|
||||
- concept_name (descriptive, e.g., "Classic Three-Column Holy Grail")
|
||||
- design_philosophy (1-2 sentences explaining the structural approach)
|
||||
- layout_pattern (e.g., "grid-3col", "flex-row", "single-column", "asymmetric-grid")
|
||||
- key_components (array of main layout regions)
|
||||
- structural_features (list of distinguishing characteristics)
|
||||
|
||||
2. **Wireframe Preview** (simple text representation):
|
||||
- ascii_art (simple ASCII box diagram showing layout structure)
|
||||
- Example:
|
||||
┌─────────────────┐
|
||||
│ HEADER │
|
||||
├──┬─────────┬────┤
|
||||
│ L│ MAIN │ R │
|
||||
└──┴─────────┴────┘
|
||||
|
||||
## Output
|
||||
Write single JSON file: {base_path}/.intermediates/layout-analysis/analysis-options.json
|
||||
|
||||
Use schema from INTERACTIVE-DATA-SPEC.md (Layout Extract: analysis-options.json)
|
||||
|
||||
CRITICAL: Use Write() tool immediately after generating complete JSON
|
||||
`
|
||||
```
|
||||
|
||||
### Step 4: Verify Options File Created
|
||||
```bash
|
||||
bash(test -f {base_path}/.intermediates/layout-analysis/analysis-options.json && echo "created")
|
||||
|
||||
# Quick validation
|
||||
bash(cat {base_path}/.intermediates/layout-analysis/analysis-options.json | grep -q "layout_concepts" && echo "valid")
|
||||
```
|
||||
|
||||
**Output**: `analysis-options.json` with layout concept options for all targets
|
||||
|
||||
---
|
||||
|
||||
## Phase 1.5: User Confirmation (Explore Mode Only - INTERACTIVE)
|
||||
|
||||
**Purpose**: Allow user to select preferred layout concept(s) for each target before generating detailed templates
|
||||
|
||||
### Step 1: Load and Present Options
|
||||
```bash
|
||||
# Read options file
|
||||
options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json)
|
||||
|
||||
# Parse layout concepts
|
||||
layout_concepts = options.layout_concepts
|
||||
```
|
||||
|
||||
### Step 2: Present Options to User (Per Target)
|
||||
For each target, present layout concept options and capture selection:
|
||||
|
||||
```
|
||||
📋 Layout Concept Options for Target: {target}
|
||||
|
||||
We've generated {variants_count} structurally different layout concepts for review.
|
||||
Please select your preferred concept for this target.
|
||||
|
||||
{FOR each concept in layout_concepts[target]:
|
||||
═══════════════════════════════════════════════════
|
||||
Concept {concept.index}: {concept.concept_name}
|
||||
═══════════════════════════════════════════════════
|
||||
|
||||
Philosophy: {concept.design_philosophy}
|
||||
Pattern: {concept.layout_pattern}
|
||||
|
||||
Components:
|
||||
{FOR each component in concept.key_components:
|
||||
• {component}
|
||||
}
|
||||
|
||||
Features:
|
||||
{FOR each feature in concept.structural_features:
|
||||
• {feature}
|
||||
}
|
||||
|
||||
Wireframe:
|
||||
{concept.wireframe_preview.ascii_art}
|
||||
|
||||
═══════════════════════════════════════════════════
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: Capture User Selection (Per Target)
|
||||
```javascript
|
||||
// Use AskUserQuestion tool for each target
|
||||
FOR each target:
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "Which layout concept do you prefer for '{target}'?",
|
||||
header: "Layout for " + target,
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{FOR each concept in layout_concepts[target]:
|
||||
label: "Concept {concept.index}: {concept.concept_name}",
|
||||
description: "{concept.design_philosophy}"
|
||||
}
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
// Parse user response
|
||||
selected_option_text = user_answer
|
||||
|
||||
// Check for user cancellation
|
||||
IF selected_option_text == null OR selected_option_text == "":
|
||||
REPORT: "⚠️ User canceled selection. Workflow terminated."
|
||||
EXIT workflow
|
||||
|
||||
// Extract concept index from response format "Concept N: Name"
|
||||
match = selected_option_text.match(/Concept (\d+):/)
|
||||
IF match:
|
||||
selected_index = parseInt(match[1])
|
||||
ELSE:
|
||||
ERROR: "Invalid selection format. Expected 'Concept N: ...' format"
|
||||
EXIT workflow
|
||||
|
||||
// Store selection for this target
|
||||
selections[target] = {
|
||||
selected_index: selected_index,
|
||||
concept_name: layout_concepts[target][selected_index-1].concept_name
|
||||
}
|
||||
```
|
||||
|
||||
### Step 4: Write User Selection File
|
||||
```bash
|
||||
# Create user selection JSON
|
||||
selection_data = {
|
||||
"metadata": {
|
||||
"selected_at": "{current_timestamp}",
|
||||
"selection_type": "per_target",
|
||||
"session_id": "{session_id}"
|
||||
},
|
||||
"selections": selections // {target: {selected_index, concept_name}}
|
||||
}
|
||||
|
||||
# Write to file
|
||||
bash(echo '{selection_data}' > {base_path}/.intermediates/layout-analysis/user-selection.json)
|
||||
|
||||
# Verify
|
||||
bash(test -f {base_path}/.intermediates/layout-analysis/user-selection.json && echo "saved")
|
||||
```
|
||||
|
||||
### Step 5: Confirmation Message
|
||||
```
|
||||
✅ Selections recorded!
|
||||
|
||||
{FOR each target, selection in selections:
|
||||
• {target}: Concept {selection.selected_index} - {selection.concept_name}
|
||||
}
|
||||
|
||||
Proceeding to generate detailed layout templates based on your selections...
|
||||
```
|
||||
|
||||
**Output**: `user-selection.json` with user's choices for all targets
|
||||
|
||||
## Phase 2: Layout Template Generation (Agent Task 2)
|
||||
|
||||
**Executor**: `Task(ui-design-agent)` for selected concept(s)
|
||||
|
||||
### Step 1: Load User Selection (Explore Mode)
|
||||
```bash
|
||||
# For explore mode, read user selection
|
||||
IF extraction_mode == "explore":
|
||||
selection = Read({base_path}/.intermediates/layout-analysis/user-selection.json)
|
||||
selections_per_target = selection.selections
|
||||
|
||||
# Also read the selected concept details from options
|
||||
options = Read({base_path}/.intermediates/layout-analysis/analysis-options.json)
|
||||
layout_concepts = options.layout_concepts
|
||||
|
||||
# Build selected concepts map
|
||||
selected_concepts = {}
|
||||
FOR each target in targets:
|
||||
selected_index = selections_per_target[target].selected_index
|
||||
selected_concepts[target] = layout_concepts[target][selected_index-1] # 0-indexed
|
||||
ELSE:
|
||||
# Imitate mode - no selection needed
|
||||
selected_concepts = null
|
||||
```
|
||||
|
||||
### Step 2: Launch Agent Task
|
||||
Generate layout templates for selected concepts:
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[LAYOUT_TEMPLATE_GENERATION_TASK]
|
||||
Generate detailed layout templates based on user-selected concepts.
|
||||
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}
|
||||
DEVICE_TYPE: {device_type}
|
||||
|
||||
${extraction_mode == "explore" ? `
|
||||
USER SELECTIONS:
|
||||
${targets.map(target => `
|
||||
Target: ${target}
|
||||
- Selected Concept: ${selected_concepts[target].concept_name}
|
||||
- Philosophy: ${selected_concepts[target].design_philosophy}
|
||||
- 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
|
||||
- Targets: {targets.join(", ")}
|
||||
- Device type: {device_type}
|
||||
- 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" : ""}
|
||||
|
||||
## Generation Rules
|
||||
${extraction_mode == "explore" ? `
|
||||
- **Explore Mode**: Develop each user-selected layout concept into a detailed template
|
||||
- Use the selected concept's key_components as foundation
|
||||
- Apply the selected layout_pattern (grid-3col, flex-row, etc.)
|
||||
- Honor the structural_features defined in the concept
|
||||
- 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 ? `
|
||||
- IMPORTANT: You have access to real DOM structure data with accurate flex/grid properties
|
||||
- Use DOM data as primary source for layout properties
|
||||
- Extract real flex/grid configurations (display, flexDirection, justifyContent, alignItems, gap)
|
||||
- Use actual element bounds for responsive breakpoint decisions
|
||||
- Preserve identified patterns from DOM structure
|
||||
` : ""}
|
||||
|
||||
## Generate for EACH Target
|
||||
For target in {targets}:
|
||||
${extraction_mode == "explore" ? "Based on user-selected concept:" : "Based on reference:"}
|
||||
|
||||
1. **DOM Structure**:
|
||||
- Semantic HTML5 tags: <header>, <nav>, <main>, <aside>, <section>, <footer>
|
||||
- ARIA roles and accessibility attributes
|
||||
${extraction_mode == "explore" ? "- Use key_components from selected concept" : ""}
|
||||
${dom_structure_available ? "- Base on extracted DOM tree from .intermediates" : "- Infer from visual analysis"}
|
||||
- Device-specific optimizations for {device_type}
|
||||
|
||||
2. **Component Hierarchy**:
|
||||
- Array of main layout regions
|
||||
${extraction_mode == "explore" ? "- Derived from selected concept's key_components" : ""}
|
||||
|
||||
3. **CSS Layout Rules**:
|
||||
${extraction_mode == "explore" ? "- Implement selected layout_pattern" : ""}
|
||||
${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-*)
|
||||
- Device-specific styles (mobile-first @media for responsive)
|
||||
- NO colors, NO fonts, NO shadows - layout structure only
|
||||
|
||||
## Output Format
|
||||
Write complete layout-templates.json with layout_templates array.
|
||||
Each template must include:
|
||||
- target (string)
|
||||
- variant_id: "layout-1" (always 1 since only selected concept is generated)
|
||||
- source_image_path (string): Reference image path
|
||||
- device_type (string)
|
||||
- design_philosophy (string ${extraction_mode == "explore" ? "- from selected concept" : ""})
|
||||
- dom_structure (JSON object)
|
||||
- component_hierarchy (array of strings)
|
||||
- css_layout_rules (string)
|
||||
|
||||
## Critical Requirements
|
||||
- ✅ Use Write() tool for layout-templates.json
|
||||
- ✅ One template per target (only selected concept)
|
||||
- ✅ Structure only, no visual styling
|
||||
- ✅ Token-based CSS (var())
|
||||
${extraction_mode == "explore" ? "- ✅ Maintain consistency with selected concepts" : ""}
|
||||
`
|
||||
```
|
||||
|
||||
**Output**: Agent generates `layout-templates.json` with one template per target
|
||||
|
||||
### Step 2: Write Output File
|
||||
```bash
|
||||
# Take JSON output from agent
|
||||
bash(echo '{agent_json_output}' > {base_path}/layout-extraction/layout-templates.json)
|
||||
|
||||
# Verify output
|
||||
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists")
|
||||
bash(cat {base_path}/layout-extraction/layout-templates.json | grep -q "layout_templates" && echo "valid")
|
||||
```
|
||||
|
||||
**Output**: `layout-templates.json` created and verified
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"},
|
||||
{content: "Layout research (explore mode)", status: "completed", activeForm: "Researching layout patterns"},
|
||||
{content: "Layout analysis and synthesis (agent)", status: "completed", activeForm: "Generating layout templates"},
|
||||
{content: "Write layout-templates.json", status: "completed", activeForm: "Saving templates"}
|
||||
]});
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ Layout extraction complete!
|
||||
|
||||
Configuration:
|
||||
- Session: {session_id}
|
||||
- Extraction Mode: {extraction_mode} (imitate/explore)
|
||||
- Device Type: {device_type}
|
||||
- Targets: {targets}
|
||||
- Variants per Target: {variants_count}
|
||||
- Total Templates: {targets.length × variants_count}
|
||||
{IF has_urls AND dom_structure_available:
|
||||
- 🔍 URL Mode: DOM structure extracted from {len(url_list)} URL(s)
|
||||
- Accuracy: Real flex/grid properties from live pages
|
||||
}
|
||||
{IF has_urls AND NOT dom_structure_available:
|
||||
- ⚠️ URL Mode: Chrome DevTools unavailable, used visual analysis fallback
|
||||
}
|
||||
|
||||
{IF extraction_mode == "explore":
|
||||
Layout Research:
|
||||
- {targets.length} inspiration files generated
|
||||
- Pattern search focused on {device_type} layouts
|
||||
}
|
||||
|
||||
Generated Templates:
|
||||
{FOR each template: - Target: {template.target} | Variant: {template.variant_id} | Philosophy: {template.design_philosophy}}
|
||||
|
||||
Output File:
|
||||
- {base_path}/layout-extraction/layout-templates.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.
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1)
|
||||
|
||||
# Create output directories
|
||||
bash(mkdir -p {base_path}/layout-extraction)
|
||||
bash(mkdir -p {base_path}/.intermediates/layout-analysis/inspirations) # explore mode only
|
||||
```
|
||||
|
||||
### Validation Commands
|
||||
```bash
|
||||
# Check if already extracted
|
||||
bash(test -f {base_path}/layout-extraction/layout-templates.json && echo "exists")
|
||||
|
||||
# Validate JSON structure
|
||||
bash(cat layout-templates.json | grep -q "layout_templates" && echo "valid")
|
||||
|
||||
# Count templates
|
||||
bash(cat layout-templates.json | grep -c "\"target\":")
|
||||
```
|
||||
|
||||
### File Operations
|
||||
```bash
|
||||
# Load image references
|
||||
bash(ls {images_pattern})
|
||||
Read({image_path})
|
||||
|
||||
# Write inspiration files (explore mode)
|
||||
Write({base_path}/.intermediates/layout-analysis/inspirations/{target}-layout-ideas.txt, content)
|
||||
|
||||
# Write layout templates
|
||||
bash(echo '{json}' > {base_path}/layout-extraction/layout-templates.json)
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
├── .intermediates/ # Intermediate analysis files
|
||||
│ └── layout-analysis/
|
||||
│ ├── dom-structure-{target}.json # Extracted DOM structure (URL mode only)
|
||||
│ └── inspirations/ # Explore mode only
|
||||
│ └── {target}-layout-ideas.txt # Layout inspiration research
|
||||
└── layout-extraction/ # Final layout templates
|
||||
├── layout-templates.json # Structural layout templates
|
||||
└── layout-space-analysis.json # Layout directions (explore mode only)
|
||||
```
|
||||
|
||||
## layout-templates.json Format
|
||||
|
||||
```json
|
||||
{
|
||||
"extraction_metadata": {
|
||||
"session_id": "...",
|
||||
"input_mode": "image|url|prompt|hybrid",
|
||||
"extraction_mode": "imitate|explore",
|
||||
"device_type": "desktop|mobile|tablet|responsive",
|
||||
"timestamp": "...",
|
||||
"variants_count": 3,
|
||||
"targets": ["home", "dashboard"]
|
||||
},
|
||||
"layout_templates": [
|
||||
{
|
||||
"target": "home",
|
||||
"variant_id": "layout-1",
|
||||
"source_image_path": "{base_path}/screenshots/home.png",
|
||||
"device_type": "responsive",
|
||||
"design_philosophy": "Responsive 3-column holy grail layout with fixed header and footer",
|
||||
"dom_structure": {
|
||||
"tag": "body",
|
||||
"children": [
|
||||
{
|
||||
"tag": "header",
|
||||
"attributes": {"class": "layout-header"},
|
||||
"children": [{"tag": "nav"}]
|
||||
},
|
||||
{
|
||||
"tag": "div",
|
||||
"attributes": {"class": "layout-main-wrapper"},
|
||||
"children": [
|
||||
{"tag": "main", "attributes": {"class": "layout-main-content"}},
|
||||
{"tag": "aside", "attributes": {"class": "layout-sidebar-left"}},
|
||||
{"tag": "aside", "attributes": {"class": "layout-sidebar-right"}}
|
||||
]
|
||||
},
|
||||
{"tag": "footer", "attributes": {"class": "layout-footer"}}
|
||||
]
|
||||
},
|
||||
"component_hierarchy": [
|
||||
"header",
|
||||
"main-content",
|
||||
"sidebar-left",
|
||||
"sidebar-right",
|
||||
"footer"
|
||||
],
|
||||
"css_layout_rules": ".layout-main-wrapper { display: grid; grid-template-columns: 1fr 3fr 1fr; gap: var(--spacing-6); } @media (max-width: var(--breakpoint-md)) { .layout-main-wrapper { grid-template-columns: 1fr; } }"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**: Token-based CSS (var()), semantic HTML5, device-specific structure, accessibility attributes
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: No inputs provided
|
||||
→ Provide --images, --urls, or --prompt
|
||||
|
||||
ERROR: Invalid target name
|
||||
→ Use lowercase, alphanumeric, hyphens only
|
||||
|
||||
ERROR: Agent task failed
|
||||
→ Check agent output, retry with simplified prompt
|
||||
|
||||
ERROR: MCP search failed (explore mode)
|
||||
→ Check network, retry
|
||||
```
|
||||
|
||||
### Recovery Strategies
|
||||
- **Partial success**: Keep successfully extracted templates
|
||||
- **Invalid JSON**: Retry with stricter format requirements
|
||||
- **Missing inspiration**: Works without (less informed exploration)
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Auto-Trigger URL Mode** - Automatically extracts DOM structure when --urls provided (no manual flag needed)
|
||||
- **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
|
||||
- **Separation of Concerns** - Decouples layout (structure) from style (visuals)
|
||||
- **Structural Exploration** - Explore mode enables A/B testing of different layouts
|
||||
- **Token-Based Layout** - CSS uses `var()` placeholders for instant design system adaptation
|
||||
- **Device-Specific** - Tailored structures for different screen sizes
|
||||
- **Graceful Fallback** - Falls back to visual analysis if Chrome DevTools unavailable
|
||||
- **Foundation for Assembly** - Provides structural blueprint for refactored `generate` command
|
||||
- **Agent-Powered** - Deep structural analysis with AI
|
||||
|
||||
## Integration
|
||||
|
||||
**Workflow Position**: Between style extraction and prototype generation
|
||||
|
||||
**New Workflow**:
|
||||
1. `/workflow:ui-design:style-extract` → `design-tokens.json` + `style-guide.md` (Complete design systems)
|
||||
2. `/workflow:ui-design:layout-extract` → `layout-templates.json` (Structural templates)
|
||||
3. `/workflow:ui-design:generate` (Pure assembler):
|
||||
- **Reads**: `design-tokens.json` + `layout-templates.json`
|
||||
- **Action**: For each style × layout combination:
|
||||
1. Build HTML from `dom_structure`
|
||||
2. Create layout CSS from `css_layout_rules`
|
||||
3. Link design tokens CSS
|
||||
4. Inject placeholder content
|
||||
- **Output**: Complete token-driven HTML/CSS prototypes
|
||||
|
||||
**Input**: Reference images, URLs, or text prompts
|
||||
**Output**: `layout-templates.json` for `/workflow:ui-design:generate`
|
||||
**Next**: `/workflow:ui-design:generate --session {session_id}`
|
||||
@@ -0,0 +1,671 @@
|
||||
---
|
||||
name: style-extract
|
||||
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>]"
|
||||
allowed-tools: TodoWrite(*), Read(*), Write(*), Glob(*), mcp__chrome-devtools__navigate_page(*), mcp__chrome-devtools__evaluate_script(*)
|
||||
---
|
||||
|
||||
# Style Extraction Command
|
||||
|
||||
## Overview
|
||||
Extract design style from reference images or text prompts using Claude's built-in analysis. Directly generates production-ready design systems with complete `design-tokens.json` and `style-guide.md` for each variant.
|
||||
|
||||
**Strategy**: AI-Driven Design Space Exploration
|
||||
- **Claude-Native**: 100% Claude analysis, no external tools
|
||||
- **Direct Output**: Complete design systems (design-tokens.json + style-guide.md)
|
||||
- **Flexible Input**: Images, text prompts, or both (hybrid mode)
|
||||
- **Maximum Contrast**: AI generates maximally divergent design directions
|
||||
- **Production-Ready**: WCAG AA compliant, OKLCH colors, semantic naming
|
||||
|
||||
## Phase 0: Setup & Input Validation
|
||||
|
||||
### Step 1: Detect Input Mode, Extraction Mode & Base Path
|
||||
```bash
|
||||
# Detect input source
|
||||
# Priority: --urls + --images + --prompt → hybrid-url | --urls + --images → url-image | --urls → url | --images + --prompt → hybrid | --images → image | --prompt → text
|
||||
|
||||
# Parse URLs if provided (format: "target:url,target:url,...")
|
||||
IF --urls:
|
||||
url_list = []
|
||||
FOR pair IN split(--urls, ","):
|
||||
IF ":" IN pair:
|
||||
target, url = pair.split(":", 1)
|
||||
url_list.append({target: target.strip(), url: url.strip()})
|
||||
ELSE:
|
||||
# Single URL without target
|
||||
url_list.append({target: "page", url: pair.strip()})
|
||||
|
||||
has_urls = true
|
||||
primary_url = url_list[0].url # First URL as primary source
|
||||
ELSE:
|
||||
has_urls = false
|
||||
|
||||
# Determine extraction mode
|
||||
# Priority: --mode parameter → default "imitate"
|
||||
extraction_mode = --mode OR "imitate" # "imitate" or "explore"
|
||||
|
||||
# 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
|
||||
|
||||
# Determine base path
|
||||
bash(find .workflow -type d -name "design-*" | head -1) # Auto-detect
|
||||
# OR use --base-path / --session parameters
|
||||
```
|
||||
|
||||
### Step 2: Extract Computed Styles (URL Mode - Auto-Trigger)
|
||||
```bash
|
||||
# AUTO-TRIGGER: If URLs are available (from --urls parameter or capture metadata), automatically extract real CSS values
|
||||
# This provides accurate design tokens to supplement visual analysis
|
||||
|
||||
# Priority 1: Check for --urls parameter
|
||||
IF has_urls:
|
||||
url_to_extract = primary_url
|
||||
url_source = "--urls parameter"
|
||||
|
||||
# Priority 2: Check for URL metadata from capture phase
|
||||
ELSE IF exists({base_path}/.metadata/capture-urls.json):
|
||||
capture_urls = Read({base_path}/.metadata/capture-urls.json)
|
||||
url_to_extract = capture_urls[0] # Use first URL
|
||||
url_source = "capture metadata"
|
||||
ELSE:
|
||||
url_to_extract = null
|
||||
|
||||
# Execute extraction if URL available
|
||||
IF url_to_extract AND mcp_chrome_devtools_available:
|
||||
REPORT: "🔍 Auto-triggering URL mode: Extracting computed styles from {url_source}"
|
||||
REPORT: " URL: {url_to_extract}"
|
||||
|
||||
# Read extraction script
|
||||
script_content = Read(~/.claude/scripts/extract-computed-styles.js)
|
||||
|
||||
# Open page in Chrome DevTools
|
||||
mcp__chrome-devtools__navigate_page(url=url_to_extract)
|
||||
|
||||
# Execute extraction script directly
|
||||
result = mcp__chrome-devtools__evaluate_script(function=script_content)
|
||||
|
||||
# Save computed styles to intermediates directory
|
||||
bash(mkdir -p {base_path}/.intermediates/style-analysis)
|
||||
Write({base_path}/.intermediates/style-analysis/computed-styles.json, result)
|
||||
|
||||
computed_styles_available = true
|
||||
REPORT: " ✅ Computed styles extracted and saved"
|
||||
ELSE:
|
||||
computed_styles_available = false
|
||||
IF url_to_extract:
|
||||
REPORT: "⚠️ Chrome DevTools MCP not available, falling back to visual analysis"
|
||||
```
|
||||
|
||||
**Extraction Script Reference**: `~/.claude/scripts/extract-computed-styles.js`
|
||||
|
||||
**Usage**: Read the script file and use content directly in `mcp__chrome-devtools__evaluate_script()`
|
||||
|
||||
**Script returns**:
|
||||
- `metadata`: Extraction timestamp, URL, method
|
||||
- `tokens`: Organized design tokens (colors, borderRadii, shadows, fontSizes, fontWeights, spacing)
|
||||
|
||||
**Benefits**:
|
||||
- ✅ Pixel-perfect accuracy for border-radius, box-shadow, padding, etc.
|
||||
- ✅ Eliminates guessing from visual analysis
|
||||
- ✅ Provides ground truth for design tokens
|
||||
|
||||
### Step 3: Load Inputs
|
||||
```bash
|
||||
# For image mode
|
||||
bash(ls {images_pattern}) # Expand glob pattern
|
||||
Read({image_path}) # Load each image
|
||||
|
||||
# For text mode
|
||||
# Validate --prompt is non-empty
|
||||
|
||||
# Create output directory
|
||||
bash(mkdir -p {base_path}/style-extraction/)
|
||||
```
|
||||
|
||||
### Step 3: Memory Check
|
||||
```bash
|
||||
# 1. Check if inputs cached in session memory
|
||||
IF session_has_inputs: SKIP Step 2 file reading
|
||||
|
||||
# 2. Check if output already exists
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "exists")
|
||||
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 1: Design Direction Generation (Explore Mode Only)
|
||||
|
||||
### Step 1: Check Extraction Mode
|
||||
```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
|
||||
# Load brainstorming context if available
|
||||
bash(test -f {base_path}/.brainstorming/role analysis documents && cat it)
|
||||
```
|
||||
|
||||
### Step 3: Generate Design Direction Options (Agent Task 1)
|
||||
**Executor**: `Task(ui-design-agent)`
|
||||
|
||||
Launch agent to generate `variants_count` design direction options with previews:
|
||||
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[DESIGN_DIRECTION_GENERATION_TASK]
|
||||
Generate {variants_count} maximally contrasting design directions with visual previews
|
||||
|
||||
SESSION: {session_id} | MODE: explore | BASE_PATH: {base_path}
|
||||
|
||||
## Input Analysis
|
||||
- User prompt: {prompt_guidance}
|
||||
- Visual references: {loaded_images if available}
|
||||
- Project context: {brainstorming_context if available}
|
||||
|
||||
## Analysis Rules
|
||||
- Analyze 6D attribute space: color saturation, visual weight, formality, organic/geometric, innovation, density
|
||||
- Generate {variants_count} directions with MAXIMUM contrast
|
||||
- Each direction must be distinctly different (min distance score: 0.7)
|
||||
|
||||
## Generate for EACH Direction
|
||||
1. **Core Philosophy**:
|
||||
- philosophy_name (2-3 words, e.g., "Minimalist & Airy")
|
||||
- design_attributes (6D scores 0-1)
|
||||
- search_keywords (3-5 keywords)
|
||||
- anti_keywords (2-3 keywords to avoid)
|
||||
- rationale (why this is distinct from others)
|
||||
|
||||
2. **Visual Preview Elements**:
|
||||
- primary_color (OKLCH format)
|
||||
- secondary_color (OKLCH format)
|
||||
- accent_color (OKLCH format)
|
||||
- font_family_heading (specific font name)
|
||||
- font_family_body (specific font name)
|
||||
- border_radius_base (e.g., "0.5rem")
|
||||
- mood_description (1-2 sentences describing the feel)
|
||||
|
||||
## Output
|
||||
Write single JSON file: {base_path}/.intermediates/style-analysis/analysis-options.json
|
||||
|
||||
Use schema from INTERACTIVE-DATA-SPEC.md (Style Extract: analysis-options.json)
|
||||
|
||||
CRITICAL: Use Write() tool immediately after generating complete JSON
|
||||
`
|
||||
```
|
||||
|
||||
### Step 4: Verify Options File Created
|
||||
```bash
|
||||
bash(test -f {base_path}/.intermediates/style-analysis/analysis-options.json && echo "created")
|
||||
|
||||
# Quick validation
|
||||
bash(cat {base_path}/.intermediates/style-analysis/analysis-options.json | grep -q "design_directions" && echo "valid")
|
||||
```
|
||||
|
||||
**Output**: `analysis-options.json` with design direction options
|
||||
|
||||
---
|
||||
|
||||
## Phase 1.5: User Confirmation (Explore Mode Only - INTERACTIVE)
|
||||
|
||||
**Purpose**: Allow user to select preferred design direction(s) before generating full design systems
|
||||
|
||||
### Step 1: Load and Present Options
|
||||
```bash
|
||||
# Read options file
|
||||
options = Read({base_path}/.intermediates/style-analysis/analysis-options.json)
|
||||
|
||||
# Parse design directions
|
||||
design_directions = options.design_directions
|
||||
```
|
||||
|
||||
### Step 2: Present Options to User
|
||||
```
|
||||
📋 Design Direction Options
|
||||
|
||||
We've generated {variants_count} contrasting design directions for your review.
|
||||
Please select the direction(s) you'd like to develop into complete design systems.
|
||||
|
||||
{FOR each direction in design_directions:
|
||||
═══════════════════════════════════════════════════
|
||||
Option {direction.index}: {direction.philosophy_name}
|
||||
═══════════════════════════════════════════════════
|
||||
|
||||
Philosophy: {direction.rationale}
|
||||
|
||||
Visual Preview:
|
||||
• Colors: {direction.preview.primary_color} (primary), {direction.preview.accent_color} (accent)
|
||||
• Typography: {direction.preview.font_family_heading} (headings), {direction.preview.font_family_body} (body)
|
||||
• Border Radius: {direction.preview.border_radius_base}
|
||||
• Mood: {direction.preview.mood_description}
|
||||
|
||||
Design Attributes:
|
||||
• Color Saturation: {direction.design_attributes.color_saturation * 100}%
|
||||
• Visual Weight: {direction.design_attributes.visual_weight * 100}%
|
||||
• Formality: {direction.design_attributes.formality * 100}%
|
||||
• Innovation: {direction.design_attributes.innovation * 100}%
|
||||
|
||||
Keywords: {join(direction.search_keywords, ", ")}
|
||||
Avoiding: {join(direction.anti_keywords, ", ")}
|
||||
}
|
||||
|
||||
═══════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
### Step 3: Capture User Selection
|
||||
```javascript
|
||||
// Use AskUserQuestion tool for selection
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: "Which design direction would you like to develop into a complete design system?",
|
||||
header: "Style Choice",
|
||||
multiSelect: false, // Single selection for Phase 1
|
||||
options: [
|
||||
{FOR each direction:
|
||||
label: "Option {direction.index}: {direction.philosophy_name}",
|
||||
description: "{direction.mood_description}"
|
||||
}
|
||||
]
|
||||
}]
|
||||
})
|
||||
|
||||
// Parse user response (e.g., "Option 1: Minimalist & Airy")
|
||||
selected_option_text = user_answer
|
||||
|
||||
// Check for user cancellation
|
||||
IF selected_option_text == null OR selected_option_text == "":
|
||||
REPORT: "⚠️ User canceled selection. Workflow terminated."
|
||||
EXIT workflow
|
||||
|
||||
// Extract option index from response format "Option N: Name"
|
||||
match = selected_option_text.match(/Option (\d+):/)
|
||||
IF match:
|
||||
selected_index = parseInt(match[1])
|
||||
ELSE:
|
||||
ERROR: "Invalid selection format. Expected 'Option N: ...' format"
|
||||
EXIT workflow
|
||||
```
|
||||
|
||||
### Step 4: Write User Selection File
|
||||
```bash
|
||||
# Create user selection JSON
|
||||
selection_data = {
|
||||
"metadata": {
|
||||
"selected_at": "{current_timestamp}",
|
||||
"selection_type": "single",
|
||||
"session_id": "{session_id}"
|
||||
},
|
||||
"selected_indices": [selected_index],
|
||||
"refinements": {
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
|
||||
# Write to file
|
||||
bash(echo '{selection_data}' > {base_path}/.intermediates/style-analysis/user-selection.json)
|
||||
|
||||
# Verify
|
||||
bash(test -f {base_path}/.intermediates/style-analysis/user-selection.json && echo "saved")
|
||||
```
|
||||
|
||||
### Step 5: Confirmation Message
|
||||
```
|
||||
✅ Selection recorded!
|
||||
|
||||
You selected: Option {selected_index} - {selected_direction.philosophy_name}
|
||||
|
||||
Proceeding to generate complete design system based on your selection...
|
||||
```
|
||||
|
||||
**Output**: `user-selection.json` with user's choice
|
||||
|
||||
## Phase 2: Design System Generation (Agent Task 2)
|
||||
|
||||
**Executor**: `Task(ui-design-agent)` for selected variant(s)
|
||||
|
||||
### Step 1: Load User Selection (Explore Mode)
|
||||
```bash
|
||||
# For explore mode, read user selection
|
||||
IF extraction_mode == "explore":
|
||||
selection = Read({base_path}/.intermediates/style-analysis/user-selection.json)
|
||||
selected_indices = selection.selected_indices
|
||||
refinements = selection.refinements
|
||||
|
||||
# Also read the selected direction details from options
|
||||
options = Read({base_path}/.intermediates/style-analysis/analysis-options.json)
|
||||
selected_directions = [options.design_directions[i-1] for i in selected_indices] # 0-indexed
|
||||
|
||||
# For Phase 1, we only allow single selection
|
||||
selected_direction = selected_directions[0]
|
||||
actual_variants_count = 1
|
||||
ELSE:
|
||||
# Imitate mode - generate single variant without selection
|
||||
selected_direction = null
|
||||
actual_variants_count = 1
|
||||
```
|
||||
|
||||
### Step 2: Create Output Directory
|
||||
```bash
|
||||
# Create directory for selected variant only
|
||||
bash(mkdir -p {base_path}/style-extraction/style-1)
|
||||
```
|
||||
|
||||
### Step 3: Launch Agent Task
|
||||
Generate design system for selected direction:
|
||||
```javascript
|
||||
Task(ui-design-agent): `
|
||||
[DESIGN_SYSTEM_GENERATION_TASK]
|
||||
Generate production-ready design system based on user-selected direction
|
||||
|
||||
SESSION: {session_id} | MODE: {extraction_mode} | BASE_PATH: {base_path}
|
||||
|
||||
${extraction_mode == "explore" ? `
|
||||
USER SELECTION:
|
||||
- Selected Direction: ${selected_direction.philosophy_name}
|
||||
- Design Attributes: ${JSON.stringify(selected_direction.design_attributes)}
|
||||
- Search Keywords: ${selected_direction.search_keywords.join(", ")}
|
||||
- Anti-keywords: ${selected_direction.anti_keywords.join(", ")}
|
||||
- Rationale: ${selected_direction.rationale}
|
||||
- Preview Colors: Primary=${selected_direction.preview.primary_color}, Accent=${selected_direction.preview.accent_color}
|
||||
- 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}
|
||||
|
||||
${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 mode: {input_mode} (image/text/hybrid${has_urls ? "/url" : ""})
|
||||
- Visual references: {loaded_images OR prompt_guidance}
|
||||
${computed_styles_available ? "- Computed styles: Use as ground truth (Read from .intermediates/style-analysis/computed-styles.json)" : ""}
|
||||
|
||||
## Generation Rules
|
||||
${extraction_mode == "explore" ? `
|
||||
- **Explore Mode**: Develop the selected design direction into a complete design system
|
||||
- Use preview elements as foundation and expand with full token coverage
|
||||
- Apply design_attributes to all token values:
|
||||
* color_saturation → OKLCH chroma values
|
||||
* visual_weight → font weights, shadow depths
|
||||
* density → spacing scale compression/expansion
|
||||
* formality → typography choices, border radius
|
||||
* organic_geometric → border radius, shape patterns
|
||||
* innovation → token naming, experimental values
|
||||
- Honor search_keywords for design inspiration
|
||||
- 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)" : ""}
|
||||
- WCAG AA compliance: 4.5:1 text contrast, 3:1 UI contrast
|
||||
|
||||
## Generate
|
||||
Create complete design system in {base_path}/style-extraction/style-1/
|
||||
|
||||
1. **design-tokens.json**:
|
||||
- Complete token structure with ALL fields:
|
||||
* colors (brand, surface, semantic, text, border) - OKLCH format
|
||||
* typography (families, sizes, weights, line heights, letter spacing, combinations)
|
||||
* typography.combinations: Predefined typography presets (heading-primary, heading-secondary, body-regular, body-emphasis, caption, label) using var() references
|
||||
* spacing (0-24 scale)
|
||||
* opacity (0, 10, 20, 40, 60, 80, 90, 100)
|
||||
* border_radius (none to full)
|
||||
* shadows (sm to xl)
|
||||
* component_styles (button, card, input variants) - component presets using var() references
|
||||
* breakpoints (sm to 2xl)
|
||||
- All colors in OKLCH format
|
||||
${extraction_mode == "explore" ? "- Start from preview colors and expand to full palette" : ""}
|
||||
${extraction_mode == "explore" && refinements.enabled ? "- Apply user refinements where specified" : ""}
|
||||
- Common Tailwind CSS usage patterns in project (if extracting from existing project)
|
||||
|
||||
2. **style-guide.md**:
|
||||
- Design philosophy (${extraction_mode == "explore" ? "expand on: " + selected_direction.philosophy_name : "describe the reference design"})
|
||||
- Complete color system documentation with accessibility notes
|
||||
- Typography scale and usage guidelines
|
||||
- Typography Combinations section: Document each preset (heading-primary, heading-secondary, body-regular, body-emphasis, caption, label) with usage context and code examples
|
||||
- Spacing system explanation
|
||||
- Opacity & Transparency section: Opacity scale usage, common use cases (disabled states, overlays, hover effects), accessibility considerations
|
||||
- Shadows & Elevation section: Shadow hierarchy and semantic usage
|
||||
- Component Styles section: Document button, card, and input variants with code examples and visual descriptions
|
||||
- Border Radius system and semantic usage
|
||||
- Component examples and usage patterns
|
||||
- Common Tailwind CSS patterns (if applicable)
|
||||
|
||||
## Critical Requirements
|
||||
- ✅ Use Write() tool immediately for each file
|
||||
- ✅ Write to style-1/ directory (single output)
|
||||
- ❌ NO external research or MCP calls (pure AI generation)
|
||||
- ✅ 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
|
||||
|
||||
## Phase 3: Verify Output
|
||||
|
||||
### Step 1: Check Files Created
|
||||
```bash
|
||||
# Verify all design systems created
|
||||
bash(ls {base_path}/style-extraction/style-*/design-tokens.json | wc -l)
|
||||
|
||||
# Validate structure
|
||||
bash(cat {base_path}/style-extraction/style-1/design-tokens.json | grep -q "colors" && echo "valid")
|
||||
```
|
||||
|
||||
### Step 2: Verify File Sizes
|
||||
```bash
|
||||
bash(ls -lh {base_path}/style-extraction/style-1/)
|
||||
```
|
||||
|
||||
**Output**: `variants_count × 2` files verified
|
||||
|
||||
## Completion
|
||||
|
||||
### Todo Update
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Setup and input validation", status: "completed", activeForm: "Validating inputs"},
|
||||
{content: "Design space analysis (explore mode)", status: "completed", activeForm: "Analyzing design space"},
|
||||
{content: "Design system generation (agent)", status: "completed", activeForm: "Generating design systems"},
|
||||
{content: "Verify output files", status: "completed", activeForm: "Verifying files"}
|
||||
]});
|
||||
```
|
||||
|
||||
### Output Message
|
||||
```
|
||||
✅ Style extraction complete!
|
||||
|
||||
Configuration:
|
||||
- Session: {session_id}
|
||||
- Extraction Mode: {extraction_mode} (imitate/explore)
|
||||
- Input Mode: {input_mode} (image/text/hybrid{"/url" if has_urls else ""})
|
||||
- Variants: {variants_count}
|
||||
- Production-Ready: Complete design systems generated
|
||||
{IF has_urls AND computed_styles_available:
|
||||
- 🔍 URL Mode: Computed styles extracted from {len(url_list)} URL(s)
|
||||
- Accuracy: Pixel-perfect design tokens from DOM
|
||||
}
|
||||
{IF has_urls AND NOT computed_styles_available:
|
||||
- ⚠️ URL Mode: Chrome DevTools unavailable, used visual analysis fallback
|
||||
}
|
||||
|
||||
{IF extraction_mode == "explore":
|
||||
Design Direction Selection:
|
||||
- You selected: Option {selected_index} - {selected_direction.philosophy_name}
|
||||
- Generated from {variants_count} contrasting design direction options
|
||||
}
|
||||
|
||||
Generated Files:
|
||||
{base_path}/style-extraction/
|
||||
└── style-1/ (design-tokens.json, style-guide.md)
|
||||
|
||||
{IF computed_styles_available:
|
||||
Intermediate Analysis:
|
||||
{base_path}/.intermediates/style-analysis/computed-styles.json (extracted from {primary_url})
|
||||
}
|
||||
{IF extraction_mode == "explore":
|
||||
{base_path}/.intermediates/style-analysis/analysis-options.json (design direction options)
|
||||
{base_path}/.intermediates/style-analysis/user-selection.json (your selection)
|
||||
}
|
||||
|
||||
Next: /workflow:ui-design:layout-extract --session {session_id} --targets "..."
|
||||
OR: /workflow:ui-design:generate --session {session_id}
|
||||
```
|
||||
|
||||
## Simple Bash Commands
|
||||
|
||||
### Path Operations
|
||||
```bash
|
||||
# Find design directory
|
||||
bash(find .workflow -type d -name "design-*" | head -1)
|
||||
|
||||
# Expand image pattern
|
||||
bash(ls {images_pattern})
|
||||
|
||||
# Create output directory
|
||||
bash(mkdir -p {base_path}/style-extraction/)
|
||||
```
|
||||
|
||||
### Validation Commands
|
||||
```bash
|
||||
# Check if already extracted
|
||||
bash(test -f {base_path}/style-extraction/style-1/design-tokens.json && echo "exists")
|
||||
|
||||
# Count variants
|
||||
bash(ls {base_path}/style-extraction/style-* -d | wc -l)
|
||||
|
||||
# Validate JSON structure
|
||||
bash(cat {base_path}/style-extraction/style-1/design-tokens.json | grep -q "colors" && echo "valid")
|
||||
```
|
||||
|
||||
### File Operations
|
||||
```bash
|
||||
# Load brainstorming context
|
||||
bash(test -f .brainstorming/role analysis documents && cat it)
|
||||
|
||||
# Create directories
|
||||
bash(mkdir -p {base_path}/style-extraction/style-{{1..3}})
|
||||
|
||||
# Verify output
|
||||
bash(ls {base_path}/style-extraction/style-1/)
|
||||
bash(test -f {base_path}/.intermediates/style-analysis/analysis-options.json && echo "saved")
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
```
|
||||
{base_path}/
|
||||
├── .intermediates/ # Intermediate analysis files
|
||||
│ └── style-analysis/
|
||||
│ ├── computed-styles.json # Extracted CSS values from DOM (if URL available)
|
||||
│ ├── analysis-options.json # Design direction options (explore mode only)
|
||||
│ └── user-selection.json # User's selected direction (explore mode only)
|
||||
└── style-extraction/ # Final design system
|
||||
└── style-1/
|
||||
├── design-tokens.json # Production-ready design tokens
|
||||
└── style-guide.md # Design philosophy and usage guide
|
||||
```
|
||||
|
||||
## design-tokens.json Format
|
||||
|
||||
```json
|
||||
{
|
||||
"colors": {
|
||||
"brand": {"primary": "oklch(...)", "secondary": "oklch(...)", "accent": "oklch(...)"},
|
||||
"surface": {"background": "oklch(...)", "elevated": "oklch(...)", "overlay": "oklch(...)"},
|
||||
"semantic": {"success": "oklch(...)", "warning": "oklch(...)", "error": "oklch(...)", "info": "oklch(...)"},
|
||||
"text": {"primary": "oklch(...)", "secondary": "oklch(...)", "tertiary": "oklch(...)", "inverse": "oklch(...)"},
|
||||
"border": {"default": "oklch(...)", "strong": "oklch(...)", "subtle": "oklch(...)"}
|
||||
},
|
||||
"typography": {
|
||||
"font_family": {...},
|
||||
"font_size": {...},
|
||||
"font_weight": {...},
|
||||
"line_height": {...},
|
||||
"letter_spacing": {...},
|
||||
"combinations": {
|
||||
"heading-primary": {"family": "var(--font-family-heading)", "size": "var(--font-size-3xl)", "weight": "var(--font-weight-bold)", "line_height": "var(--line-height-tight)", "letter_spacing": "var(--letter-spacing-tight)"},
|
||||
"heading-secondary": {...},
|
||||
"body-regular": {...},
|
||||
"body-emphasis": {...},
|
||||
"caption": {...},
|
||||
"label": {...}
|
||||
}
|
||||
},
|
||||
"spacing": {"0": "0", "1": "0.25rem", ..., "24": "6rem"},
|
||||
"opacity": {"0": "0", "10": "0.1", "20": "0.2", "40": "0.4", "60": "0.6", "80": "0.8", "90": "0.9", "100": "1"},
|
||||
"border_radius": {"none": "0", "sm": "0.25rem", ..., "full": "9999px"},
|
||||
"shadows": {"sm": "...", "md": "...", "lg": "...", "xl": "..."},
|
||||
"component_styles": {
|
||||
"button": {
|
||||
"primary": {"background": "var(--color-brand-primary)", "color": "var(--color-text-inverse)", "padding": "var(--spacing-3) var(--spacing-6)", "border_radius": "var(--border-radius-md)", "font_weight": "var(--font-weight-semibold)"},
|
||||
"secondary": {...},
|
||||
"tertiary": {...}
|
||||
},
|
||||
"card": {
|
||||
"default": {"background": "var(--color-surface-elevated)", "padding": "var(--spacing-6)", "border_radius": "var(--border-radius-lg)", "shadow": "var(--shadow-md)"},
|
||||
"interactive": {...}
|
||||
},
|
||||
"input": {
|
||||
"default": {"border": "1px solid var(--color-border-default)", "padding": "var(--spacing-3)", "border_radius": "var(--border-radius-md)", "background": "var(--color-surface-background)"},
|
||||
"focus": {...},
|
||||
"error": {...}
|
||||
}
|
||||
},
|
||||
"breakpoints": {"sm": "640px", ..., "2xl": "1536px"}
|
||||
}
|
||||
```
|
||||
|
||||
**Requirements**: OKLCH colors, complete coverage, semantic naming, WCAG AA compliance, typography combinations, component style presets, opacity scale
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Errors
|
||||
```
|
||||
ERROR: No images found
|
||||
→ Check glob pattern
|
||||
|
||||
ERROR: Invalid prompt
|
||||
→ Provide non-empty string
|
||||
|
||||
ERROR: Claude JSON parsing error
|
||||
→ Retry with stricter format
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Auto-Trigger URL Mode** - Automatically extracts computed styles when --urls provided (no manual flag needed)
|
||||
- **Direct Design System Generation** - Complete design-tokens.json + style-guide.md in one step
|
||||
- **Hybrid Extraction Strategy** - Combines computed CSS values (ground truth) with AI visual analysis
|
||||
- **Pixel-Perfect Accuracy** - Chrome DevTools extracts exact border-radius, shadows, spacing values
|
||||
- **AI-Driven Design Space Exploration** - 6D attribute space analysis for maximum contrast
|
||||
- **Variant-Specific Directions** - Each variant has unique philosophy, keywords, anti-patterns
|
||||
- **Maximum Contrast Guarantee** - Variants maximally distant in attribute space
|
||||
- **Flexible Input** - Images, text, URLs, or hybrid mode
|
||||
- **Graceful Fallback** - Falls back to pure visual inference if Chrome DevTools unavailable
|
||||
- **Production-Ready** - OKLCH colors, WCAG AA compliance, semantic naming
|
||||
- **Agent-Driven** - Autonomous multi-file generation with ui-design-agent
|
||||
|
||||
## Integration
|
||||
|
||||
**Input**: Reference images or text prompts
|
||||
**Output**: `style-extraction/style-{N}/` with design-tokens.json + style-guide.md
|
||||
**Next**: `/workflow:ui-design:layout-extract --session {session_id}` OR `/workflow:ui-design:generate --session {session_id}`
|
||||
|
||||
**Note**: This command extracts visual style (colors, typography, spacing) and generates production-ready design systems. For layout structure extraction, use `/workflow:ui-design:layout-extract`.
|
||||
@@ -0,0 +1,363 @@
|
||||
---
|
||||
name: update
|
||||
description: Update brainstorming artifacts with finalized design system references from selected prototypes
|
||||
argument-hint: --session <session_id> [--selected-prototypes "<list>"]
|
||||
allowed-tools: Read(*), Write(*), Edit(*), TodoWrite(*), Glob(*), Bash(*)
|
||||
---
|
||||
|
||||
# Design Update Command
|
||||
|
||||
## Overview
|
||||
|
||||
Synchronize finalized design system references to brainstorming artifacts, preparing them for `/workflow:plan` consumption. This command updates **references only** (via @ notation), not content duplication.
|
||||
|
||||
## Core Philosophy
|
||||
|
||||
- **Reference-Only Updates**: Use @ references, no content duplication
|
||||
- **Main Claude Execution**: Direct updates by main Claude (no Agent handoff)
|
||||
- **Synthesis Alignment**: Update role analysis documents UI/UX Guidelines section
|
||||
- **Plan-Ready Output**: Ensure design artifacts discoverable by task-generate
|
||||
- **Minimal Reading**: Verify file existence, don't read design content
|
||||
|
||||
## Execution Protocol
|
||||
|
||||
### Phase 1: Session & Artifact Validation
|
||||
|
||||
```bash
|
||||
# Validate session
|
||||
CHECK: .workflow/.active-* marker files; VALIDATE: session_id matches active session
|
||||
|
||||
# Verify design artifacts in latest design run
|
||||
latest_design = find_latest_path_matching(".workflow/WFS-{session}/design-*")
|
||||
|
||||
# Detect design system structure
|
||||
IF exists({latest_design}/style-extraction/style-1/design-tokens.json):
|
||||
design_system_mode = "separate"; design_tokens_path = "style-extraction/style-1/design-tokens.json"; style_guide_path = "style-extraction/style-1/style-guide.md"
|
||||
ELSE:
|
||||
ERROR: "No design tokens found. Run /workflow:ui-design:style-extract first"
|
||||
|
||||
VERIFY: {latest_design}/{design_tokens_path}, {latest_design}/{style_guide_path}, {latest_design}/prototypes/*.html
|
||||
|
||||
REPORT: "📋 Design system mode: {design_system_mode} | Tokens: {design_tokens_path}"
|
||||
|
||||
# Prototype selection
|
||||
selected_list = --selected-prototypes ? parse_comma_separated(--selected-prototypes) : Glob({latest_design}/prototypes/*.html)
|
||||
VALIDATE: Specified prototypes exist IF --selected-prototypes
|
||||
|
||||
REPORT: "Found {count} design artifacts, {prototype_count} prototypes"
|
||||
```
|
||||
|
||||
### Phase 1.1: Memory Check (Skip if Already Updated)
|
||||
|
||||
```bash
|
||||
# Check if role analysis documents contains current design run reference
|
||||
synthesis_spec_path = ".workflow/WFS-{session}/.brainstorming/role analysis documents"
|
||||
current_design_run = basename(latest_design) # e.g., "design-run-20250109-143022"
|
||||
|
||||
IF exists(synthesis_spec_path):
|
||||
synthesis_content = Read(synthesis_spec_path)
|
||||
IF "## UI/UX Guidelines" in synthesis_content AND current_design_run in synthesis_content:
|
||||
REPORT: "✅ Design system references already updated (found in memory)"
|
||||
REPORT: " Skipping: Phase 2-5 (Load Target Artifacts, Update Synthesis, Update UI Designer Guide, Completion)"
|
||||
EXIT 0
|
||||
```
|
||||
|
||||
### Phase 2: Load Target Artifacts Only
|
||||
|
||||
**What to Load**: Only the files we need to **update**, not the design files we're referencing.
|
||||
|
||||
```bash
|
||||
# Load target brainstorming artifacts (files to be updated)
|
||||
Read(.workflow/WFS-{session}/.brainstorming/role analysis documents)
|
||||
IF exists(.workflow/WFS-{session}/.brainstorming/ui-designer/analysis.md): Read(analysis.md)
|
||||
|
||||
# Optional: Read prototype notes for descriptions (minimal context)
|
||||
FOR each selected_prototype IN selected_list:
|
||||
Read({latest_design}/prototypes/{selected_prototype}-notes.md) # Extract: layout_strategy, page_name only
|
||||
|
||||
# Note: Do NOT read design-tokens.json, style-guide.md, or prototype HTML. Only verify existence and generate @ references.
|
||||
```
|
||||
|
||||
### Phase 3: Update Synthesis Specification
|
||||
|
||||
Update `.brainstorming/role analysis documents` with design system references.
|
||||
|
||||
**Target Section**: `## UI/UX Guidelines`
|
||||
|
||||
**Content Template**:
|
||||
```markdown
|
||||
## UI/UX Guidelines
|
||||
|
||||
### Design System Reference
|
||||
**Finalized Design Tokens**: @../design-{run_id}/{design_tokens_path}
|
||||
**Style Guide**: @../design-{run_id}/{style_guide_path}
|
||||
**Design System Mode**: {design_system_mode}
|
||||
|
||||
### Implementation Requirements
|
||||
**Token Adherence**: All UI implementations MUST use design token CSS custom properties
|
||||
**Accessibility**: WCAG AA compliance validated in design-tokens.json
|
||||
**Responsive**: Mobile-first design using token-based breakpoints
|
||||
**Component Patterns**: Follow patterns documented in style-guide.md
|
||||
|
||||
### Reference Prototypes
|
||||
{FOR each selected_prototype:
|
||||
- **{page_name}**: @../design-{run_id}/prototypes/{prototype}.html | Layout: {layout_strategy from notes}
|
||||
}
|
||||
|
||||
### Design System Assets
|
||||
```json
|
||||
{"design_tokens": "design-{run_id}/{design_tokens_path}", "style_guide": "design-{run_id}/{style_guide_path}", "design_system_mode": "{design_system_mode}", "prototypes": [{FOR each: "design-{run_id}/prototypes/{prototype}.html"}]}
|
||||
```
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
```bash
|
||||
# Option 1: Edit existing section
|
||||
Edit(file_path=".workflow/WFS-{session}/.brainstorming/role analysis documents",
|
||||
old_string="## UI/UX Guidelines\n[existing content]",
|
||||
new_string="## UI/UX Guidelines\n\n[new design reference content]")
|
||||
|
||||
# Option 2: Append if section doesn't exist
|
||||
IF section not found:
|
||||
Edit(file_path="...", old_string="[end of document]", new_string="\n\n## UI/UX Guidelines\n\n[new design reference content]")
|
||||
```
|
||||
|
||||
### Phase 4A: Update Relevant Role Analysis Documents
|
||||
|
||||
**Discovery**: Find role analysis.md files affected by design outputs
|
||||
|
||||
```bash
|
||||
# Always update ui-designer
|
||||
ui_designer_files = Glob(".workflow/WFS-{session}/.brainstorming/ui-designer/analysis*.md")
|
||||
|
||||
# Conditionally update other roles
|
||||
has_animations = exists({latest_design}/animation-extraction/animation-tokens.json)
|
||||
has_layouts = exists({latest_design}/layout-extraction/layout-templates.json)
|
||||
|
||||
IF has_animations: ux_expert_files = Glob(".workflow/WFS-{session}/.brainstorming/ux-expert/analysis*.md")
|
||||
IF has_layouts: architect_files = Glob(".workflow/WFS-{session}/.brainstorming/system-architect/analysis*.md")
|
||||
IF selected_list: pm_files = Glob(".workflow/WFS-{session}/.brainstorming/product-manager/analysis*.md")
|
||||
```
|
||||
|
||||
**Content Templates**:
|
||||
|
||||
**ui-designer/analysis.md** (append if not exists):
|
||||
```markdown
|
||||
## Design System Implementation Reference
|
||||
|
||||
**Design Tokens**: @../../design-{run_id}/{design_tokens_path}
|
||||
**Style Guide**: @../../design-{run_id}/{style_guide_path}
|
||||
**Prototypes**: {FOR each: @../../design-{run_id}/prototypes/{prototype}.html}
|
||||
|
||||
*Reference added by /workflow:ui-design:update*
|
||||
```
|
||||
|
||||
**ux-expert/analysis.md** (if animations):
|
||||
```markdown
|
||||
## Animation & Interaction Reference
|
||||
|
||||
**Animations**: @../../design-{run_id}/animation-extraction/animation-tokens.json
|
||||
**Prototypes**: {FOR each: @../../design-{run_id}/prototypes/{prototype}.html}
|
||||
|
||||
*Reference added by /workflow:ui-design:update*
|
||||
```
|
||||
|
||||
**system-architect/analysis.md** (if layouts):
|
||||
```markdown
|
||||
## Layout Structure Reference
|
||||
|
||||
**Layout Templates**: @../../design-{run_id}/layout-extraction/layout-templates.json
|
||||
|
||||
*Reference added by /workflow:ui-design:update*
|
||||
```
|
||||
|
||||
**product-manager/analysis.md** (if prototypes):
|
||||
```markdown
|
||||
## Prototype Validation Reference
|
||||
|
||||
**Prototypes**: {FOR each: @../../design-{run_id}/prototypes/{prototype}.html}
|
||||
|
||||
*Reference added by /workflow:ui-design:update*
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
```bash
|
||||
FOR file IN [ui_designer_files, ux_expert_files, architect_files, pm_files]:
|
||||
IF file exists AND section_not_exists(file):
|
||||
Edit(file, old_string="[end of document]", new_string="\n\n{role-specific section}")
|
||||
```
|
||||
|
||||
### Phase 4B: Create UI Designer Design System Reference
|
||||
|
||||
Create or update `.brainstorming/ui-designer/design-system-reference.md`:
|
||||
|
||||
```markdown
|
||||
# UI Designer Design System Reference
|
||||
|
||||
## Design System Integration
|
||||
This style guide references the finalized design system from the design refinement phase.
|
||||
|
||||
**Design Tokens**: @../../design-{run_id}/{design_tokens_path}
|
||||
**Style Guide**: @../../design-{run_id}/{style_guide_path}
|
||||
**Design System Mode**: {design_system_mode}
|
||||
|
||||
## Implementation Guidelines
|
||||
1. **Use CSS Custom Properties**: All styles reference design tokens
|
||||
2. **Follow Semantic HTML**: Use HTML5 semantic elements
|
||||
3. **Maintain Accessibility**: WCAG AA compliance required
|
||||
4. **Responsive Design**: Mobile-first with token-based breakpoints
|
||||
|
||||
## Reference Prototypes
|
||||
{FOR each selected_prototype:
|
||||
- **{page_name}**: @../../design-{run_id}/prototypes/{prototype}.html
|
||||
}
|
||||
|
||||
## Token System
|
||||
For complete token definitions and usage examples, see:
|
||||
- Design Tokens: @../../design-{run_id}/{design_tokens_path}
|
||||
- Style Guide: @../../design-{run_id}/{style_guide_path}
|
||||
|
||||
---
|
||||
*Auto-generated by /workflow:ui-design:update | Last updated: {timestamp}*
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
```bash
|
||||
Write(file_path=".workflow/WFS-{session}/.brainstorming/ui-designer/design-system-reference.md",
|
||||
content="[generated content with @ references]")
|
||||
```
|
||||
|
||||
### Phase 5: Completion
|
||||
|
||||
```javascript
|
||||
TodoWrite({todos: [
|
||||
{content: "Validate session and design system artifacts", status: "completed", activeForm: "Validating artifacts"},
|
||||
{content: "Load target brainstorming artifacts", status: "completed", activeForm: "Loading target files"},
|
||||
{content: "Update role analysis documents with design references", status: "completed", activeForm: "Updating synthesis spec"},
|
||||
{content: "Update relevant role analysis.md documents", status: "completed", activeForm: "Updating role analysis files"},
|
||||
{content: "Create/update ui-designer/design-system-reference.md", status: "completed", activeForm: "Creating design system reference"}
|
||||
]});
|
||||
```
|
||||
|
||||
**Completion Message**:
|
||||
```
|
||||
✅ Design system references updated for session: WFS-{session}
|
||||
|
||||
Updated artifacts:
|
||||
✓ role analysis documents - UI/UX Guidelines section with @ references
|
||||
✓ {role_count} role analysis.md files - Design system references
|
||||
✓ ui-designer/design-system-reference.md - Design system reference guide
|
||||
|
||||
Design system assets ready for /workflow:plan:
|
||||
- design-tokens.json | style-guide.md | {prototype_count} reference prototypes
|
||||
|
||||
Next: /workflow:plan [--agent] "<task description>"
|
||||
The plan phase will automatically discover and utilize the design system.
|
||||
```
|
||||
|
||||
## Output Structure
|
||||
|
||||
**Updated Files**:
|
||||
```
|
||||
.workflow/WFS-{session}/.brainstorming/
|
||||
├── role analysis documents # Updated with UI/UX Guidelines section
|
||||
├── ui-designer/
|
||||
│ ├── analysis*.md # Updated with design system references
|
||||
│ └── design-system-reference.md # New or updated design reference guide
|
||||
├── ux-expert/analysis*.md # Updated if animations exist
|
||||
├── product-manager/analysis*.md # Updated if prototypes exist
|
||||
└── system-architect/analysis*.md # Updated if layouts exist
|
||||
```
|
||||
|
||||
**@ Reference Format** (role analysis documents):
|
||||
```
|
||||
@../design-{run_id}/style-extraction/style-1/design-tokens.json
|
||||
@../design-{run_id}/style-extraction/style-1/style-guide.md
|
||||
@../design-{run_id}/prototypes/{prototype}.html
|
||||
```
|
||||
|
||||
**@ Reference Format** (ui-designer/design-system-reference.md):
|
||||
```
|
||||
@../../design-{run_id}/style-extraction/style-1/design-tokens.json
|
||||
@../../design-{run_id}/style-extraction/style-1/style-guide.md
|
||||
@../../design-{run_id}/prototypes/{prototype}.html
|
||||
```
|
||||
|
||||
**@ Reference Format** (role analysis.md files):
|
||||
```
|
||||
@../../design-{run_id}/style-extraction/style-1/design-tokens.json
|
||||
@../../design-{run_id}/animation-extraction/animation-tokens.json
|
||||
@../../design-{run_id}/layout-extraction/layout-templates.json
|
||||
@../../design-{run_id}/prototypes/{prototype}.html
|
||||
```
|
||||
|
||||
## Integration with /workflow:plan
|
||||
|
||||
After this update, `/workflow:plan` will discover design assets through:
|
||||
|
||||
**Phase 3: Intelligent Analysis** (`/workflow:tools:concept-enhanced`)
|
||||
- Reads role analysis documents → Discovers @ references → Includes design system context in ANALYSIS_RESULTS.md
|
||||
|
||||
**Phase 4: Task Generation** (`/workflow:tools:task-generate`)
|
||||
- Reads ANALYSIS_RESULTS.md → Discovers design assets → Includes design system paths in task JSON files
|
||||
|
||||
**Example Task JSON** (generated by task-generate):
|
||||
```json
|
||||
{
|
||||
"task_id": "IMPL-001",
|
||||
"context": {
|
||||
"design_system": {
|
||||
"tokens": "design-{run_id}/style-extraction/style-1/design-tokens.json",
|
||||
"style_guide": "design-{run_id}/style-extraction/style-1/style-guide.md",
|
||||
"prototypes": ["design-{run_id}/prototypes/dashboard-variant-1.html"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
- **Missing design artifacts**: Error with message "Run /workflow:ui-design:style-extract and /workflow:ui-design:generate first"
|
||||
- **role analysis documents not found**: Warning, create minimal version with just UI/UX Guidelines
|
||||
- **ui-designer/ directory missing**: Create directory and file
|
||||
- **Edit conflicts**: Preserve existing content, append or replace only UI/UX Guidelines section
|
||||
- **Invalid prototype names**: Skip invalid entries, continue with valid ones
|
||||
|
||||
## Validation Checks
|
||||
|
||||
After update, verify:
|
||||
- [ ] role analysis documents contains UI/UX Guidelines section
|
||||
- [ ] UI/UX Guidelines include @ references (not content duplication)
|
||||
- [ ] ui-designer/analysis*.md updated with design system references
|
||||
- [ ] ui-designer/design-system-reference.md created or updated
|
||||
- [ ] Relevant role analysis.md files updated (ux-expert, product-manager, system-architect)
|
||||
- [ ] All @ referenced files exist and are accessible
|
||||
- [ ] @ reference paths are relative and correct
|
||||
|
||||
## Key Features
|
||||
|
||||
1. **Reference-Only Updates**: Uses @ notation for file references, no content duplication, lightweight and maintainable
|
||||
2. **Main Claude Direct Execution**: No Agent handoff (preserves context), simple reference generation, reliable path resolution
|
||||
3. **Plan-Ready Output**: `/workflow:plan` Phase 3 can discover design system, task generation includes design asset paths, clear integration points
|
||||
4. **Minimal Reading**: Only reads target files to update, verifies design file existence (no content reading), optional prototype notes for descriptions
|
||||
5. **Flexible Prototype Selection**: Auto-select all prototypes (default), manual selection via --selected-prototypes parameter, validates existence
|
||||
|
||||
## Integration Points
|
||||
|
||||
- **Input**: Design system artifacts from `/workflow:ui-design:style-extract` and `/workflow:ui-design:generate`
|
||||
- **Output**: Updated role analysis documents, role analysis.md files, ui-designer/design-system-reference.md with @ references
|
||||
- **Next Phase**: `/workflow:plan` discovers and utilizes design system through @ references
|
||||
- **Auto Integration**: Automatically triggered by `/workflow:ui-design:auto` workflow
|
||||
|
||||
## Why Main Claude Execution?
|
||||
|
||||
This command is executed directly by main Claude (not delegated to an Agent) because:
|
||||
|
||||
1. **Simple Reference Generation**: Only generating file paths, not complex synthesis
|
||||
2. **Context Preservation**: Main Claude has full session and conversation context
|
||||
3. **Minimal Transformation**: Primarily updating references, not analyzing content
|
||||
4. **Path Resolution**: Requires precise relative path calculation
|
||||
5. **Edit Operations**: Better error recovery for Edit conflicts
|
||||
6. **Synthesis Pattern**: Follows same direct-execution pattern as other reference updates
|
||||
|
||||
This ensures reliable, lightweight integration without Agent handoff overhead.
|
||||
Reference in New Issue
Block a user