feat: add team-frontend skill with ui-ux-pro-max integration

5-role frontend dev team (coordinator/analyst/architect/developer/qa)
- analyst: Skill-based ui-ux-pro-max integration for design intelligence
- architect: data-driven design tokens from design-intelligence.json
- developer: token-aware code generation with anti-pattern constraints
- qa: 5-dimension audit (code/a11y/design/ux/pre-delivery)
- 3 pipelines: page(CP-1), feature(CP-1+CP-2+CP-8), system(CP-9 dual-track)
This commit is contained in:
catlog22
2026-02-17 21:40:33 +08:00
parent 5a937732f4
commit d47b194df7
9 changed files with 2703 additions and 0 deletions

View File

@@ -0,0 +1,433 @@
---
name: team-frontend
description: Unified team skill for frontend development team. All roles invoke this skill with --role arg. Built-in ui-ux-pro-max design intelligence. Triggers on "team frontend".
allowed-tools: TeamCreate(*), TeamDelete(*), SendMessage(*), TaskCreate(*), TaskUpdate(*), TaskList(*), TaskGet(*), Task(*), AskUserQuestion(*), TodoWrite(*), Read(*), Write(*), Edit(*), Bash(*), Glob(*), Grep(*), WebFetch(*), WebSearch(*)
---
# Team Frontend Development
全栈前端开发团队,内置 ui-ux-pro-max 设计智能。具备需求分析、设计系统生成、前端实现、质量保证的完整能力。All team members invoke this skill with `--role=xxx` to route to role-specific execution.
## Architecture Overview
```
┌──────────────────────────────────────────────────┐
│ Skill(skill="team-frontend", args="--role=xxx") │
└───────────────────┬──────────────────────────────┘
│ Role Router
┌───────┬───────┼───────┬───────┐
↓ ↓ ↓ ↓ ↓
┌──────────┐┌──────────┐┌──────────┐┌──────────┐┌──────────┐
│coordinator││ analyst ││ architect││ developer││ qa │
│ roles/ ││ roles/ ││ roles/ ││ roles/ ││ roles/ │
└──────────┘└──────────┘└──────────┘└──────────┘└──────────┘
```
## Command Architecture
Each role is organized as a folder with a `role.md` orchestrator and optional `commands/` for delegation:
```
roles/
├── coordinator/
│ ├── role.md
│ └── commands/
├── analyst/
│ ├── role.md
│ └── commands/
│ └── design-intelligence.md
├── architect/
│ ├── role.md
│ └── commands/
├── developer/
│ ├── role.md
│ └── commands/
└── qa/
├── role.md
└── commands/
└── pre-delivery-checklist.md
```
## Role Router
### Input Parsing
Parse `$ARGUMENTS` to extract `--role`:
```javascript
const args = "$ARGUMENTS"
const roleMatch = args.match(/--role[=\s]+(\w+)/)
if (!roleMatch) {
throw new Error("Missing --role argument. Available roles: coordinator, analyst, architect, developer, qa")
}
const role = roleMatch[1]
const teamName = args.match(/--team[=\s]+([\w-]+)/)?.[1] || "frontend"
```
### Role Dispatch
```javascript
const VALID_ROLES = {
"coordinator": { file: "roles/coordinator/role.md", prefix: null },
"analyst": { file: "roles/analyst/role.md", prefix: "ANALYZE" },
"architect": { file: "roles/architect/role.md", prefix: "ARCH" },
"developer": { file: "roles/developer/role.md", prefix: "DEV" },
"qa": { file: "roles/qa/role.md", prefix: "QA" }
}
if (!VALID_ROLES[role]) {
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(VALID_ROLES).join(', ')}`)
}
// Read and execute role-specific logic
Read(VALID_ROLES[role].file)
// → Execute the 5-phase process defined in that file
```
### Available Roles
| Role | Task Prefix | Responsibility | Role File |
|------|-------------|----------------|-----------|
| `coordinator` | N/A | 需求澄清、行业识别、流水线编排、进度监控、GC循环控制 | [roles/coordinator/role.md](roles/coordinator/role.md) |
| `analyst` | ANALYZE-* | 需求分析、调用 ui-ux-pro-max 获取设计智能、行业推理规则匹配 | [roles/analyst/role.md](roles/analyst/role.md) |
| `architect` | ARCH-* | 消费设计智能、定义设计令牌系统、组件架构、技术选型 | [roles/architect/role.md](roles/architect/role.md) |
| `developer` | DEV-* | 消费架构产出、实现前端组件/页面代码 | [roles/developer/role.md](roles/developer/role.md) |
| `qa` | QA-* | 代码审查、可访问性检查、行业反模式检查、Pre-Delivery验证 | [roles/qa/role.md](roles/qa/role.md) |
## Shared Infrastructure
### Role Isolation Rules
**核心原则**: 每个角色仅能执行自己职责范围内的工作。
#### Output Tagging强制
所有角色的输出必须带 `[role_name]` 标识前缀:
```javascript
SendMessage({
content: `## [${role}] ...`,
summary: `[${role}] ...`
})
mcp__ccw-tools__team_msg({
summary: `[${role}] ...`
})
```
#### Coordinator 隔离
| 允许 | 禁止 |
|------|------|
| 需求澄清 (AskUserQuestion) | ❌ 直接编写/修改代码 |
| 创建任务链 (TaskCreate) | ❌ 调用实现类 subagent |
| 分发任务给 worker | ❌ 直接执行分析/测试/审查 |
| 监控进度 (消息总线) | ❌ 绕过 worker 自行完成任务 |
| 汇报结果给用户 | ❌ 修改源代码或产物文件 |
#### Worker 隔离
| 允许 | 禁止 |
|------|------|
| 处理自己前缀的任务 | ❌ 处理其他角色前缀的任务 |
| SendMessage 给 coordinator | ❌ 直接与其他 worker 通信 |
| 使用 Toolbox 中声明的工具 | ❌ 为其他角色创建任务 (TaskCreate) |
### Message Bus (All Roles)
Every SendMessage **before**, must call `mcp__ccw-tools__team_msg` to log:
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: role,
to: "coordinator",
type: "<type>",
summary: `[${role}] <summary>`,
ref: "<file_path>"
})
```
**Message types by role**:
| Role | Types |
|------|-------|
| coordinator | `task_unblocked`, `sync_checkpoint`, `fix_required`, `error`, `shutdown` |
| analyst | `analyze_ready`, `analyze_progress`, `error` |
| architect | `arch_ready`, `arch_revision`, `arch_progress`, `error` |
| developer | `dev_complete`, `dev_progress`, `error` |
| qa | `qa_passed`, `qa_result`, `fix_required`, `error` |
### CLI Fallback
`mcp__ccw-tools__team_msg` MCP 不可用时:
```javascript
Bash(`ccw team log --team "${teamName}" --from "${role}" --to "coordinator" --type "<type>" --summary "<summary>" --json`)
```
### Task Lifecycle (All Worker Roles)
```javascript
// Standard task lifecycle every worker role follows
// Phase 1: Discovery
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith(`${VALID_ROLES[role].prefix}-`) &&
t.owner === role &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
// Phase 2-4: Role-specific (see roles/{role}/role.md)
// Phase 5: Report + Loop — 所有输出必须带 [role] 标识
mcp__ccw-tools__team_msg({ operation: "log", team: teamName, from: role, to: "coordinator", type: "...", summary: `[${role}] ...` })
SendMessage({ type: "message", recipient: "coordinator", content: `## [${role}] ...`, summary: `[${role}] ...` })
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task → back to Phase 1
```
## Pipeline Architecture
### Three Pipeline Modes
```
page (单页面 - CP-1 线性):
ANALYZE-001 → ARCH-001 → DEV-001 → QA-001
feature (多组件特性 - CP-1 + CP-2 + CP-8):
ANALYZE-001 → ARCH-001(tokens+structure) → QA-001(architecture-review)
→ DEV-001(components) → QA-002(code-review)
system (完整前端系统 - CP-1 + CP-2 + CP-8 + CP-9 双轨):
ANALYZE-001 → ARCH-001(tokens) → QA-001(token-review)
→ [ARCH-002(components) ∥ DEV-001(tokens)](并行, blockedBy QA-001)
→ QA-002(component-review) → DEV-002(components) → QA-003(final)
```
### Generator-Critic Loop (CP-2)
developer ↔ qa 循环,确保代码质量和设计合规:
```
┌──────────┐ DEV artifact ┌──────────┐
│ developer│ ──────────────────────→ │ qa │
│(Generator)│ │ (Critic) │
│ │ ←────────────────────── │ │
└──────────┘ QA feedback └──────────┘
(max 2 rounds)
Convergence: qa.score >= 8 && qa.critical_count === 0
```
### Consulting Pattern (CP-8)
developer 可向 analyst 咨询设计决策:
```
developer → coordinator: "需要设计决策咨询"
coordinator → analyst: 创建 ANALYZE-consult 任务
analyst → coordinator: 设计建议
coordinator → developer: 转发建议
```
### Shared Memory
```json
{
"design_intelligence": {},
"design_token_registry": {
"colors": {}, "typography": {}, "spacing": {}, "shadows": {}
},
"component_inventory": [],
"style_decisions": [],
"qa_history": [],
"industry_context": {}
}
```
每个角色在 Phase 2 读取Phase 5 写入自己负责的字段。
## Session Directory
```
.workflow/.team/FE-{slug}-{YYYY-MM-DD}/
├── team-session.json # Session state
├── shared-memory.json # Cross-role accumulated knowledge
├── analysis/ # Analyst output
│ ├── design-intelligence.json
│ └── requirements.md
├── architecture/ # Architect output
│ ├── design-tokens.json
│ ├── component-specs/
│ │ └── {component-name}.md
│ └── project-structure.md
├── qa/ # QA output
│ └── audit-{NNN}.md
└── build/ # Developer output
├── token-files/
└── component-files/
```
## ui-ux-pro-max Integration
### Design Intelligence Engine
analyst 角色通过 Skill 调用 ui-ux-pro-max 获取行业设计智能:
```javascript
// 生成完整设计系统推荐
Skill(skill="ui-ux-pro-max", args="${industry} ${keywords} --design-system")
// 领域搜索UX 指南、排版、色彩等)
Skill(skill="ui-ux-pro-max", args="${query} --domain ${domain}")
// 技术栈指南
Skill(skill="ui-ux-pro-max", args="${query} --stack ${stack}")
// 持久化设计系统(跨会话复用)
Skill(skill="ui-ux-pro-max", args="${query} --design-system --persist -p ${projectName}")
```
### Installation
```
/plugin install ui-ux-pro-max@ui-ux-pro-max-skill
```
### Fallback Strategy
若 ui-ux-pro-max skill 未安装,降级为 LLM 通用设计知识。
### Supported Domains & Stacks
- **Domains**: product, style, typography, color, landing, chart, ux, web
- **Stacks**: html-tailwind, react, nextjs, vue, svelte, shadcn, swiftui, react-native, flutter
## Coordinator Spawn Template
When coordinator creates teammates:
```javascript
TeamCreate({ team_name: teamName })
// Analyst
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "analyst",
prompt: `你是 team "${teamName}" 的 ANALYST。
当你收到 ANALYZE-* 任务时,调用 Skill(skill="team-frontend", args="--role=analyst") 执行。
当前需求: ${taskDescription}
约束: ${constraints}
Session: ${sessionFolder}
## 角色准则(强制)
- 你只能处理 ANALYZE-* 前缀的任务
- 所有输出必须带 [analyst] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 ANALYZE-* 任务
2. Skill(skill="team-frontend", args="--role=analyst") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Architect
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "architect",
prompt: `你是 team "${teamName}" 的 ARCHITECT。
当你收到 ARCH-* 任务时,调用 Skill(skill="team-frontend", args="--role=architect") 执行。
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则(强制)
- 你只能处理 ARCH-* 前缀的任务
- 所有输出必须带 [architect] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 ARCH-* 任务
2. Skill(skill="team-frontend", args="--role=architect") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// Developer
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "developer",
prompt: `你是 team "${teamName}" 的 DEVELOPER。
当你收到 DEV-* 任务时,调用 Skill(skill="team-frontend", args="--role=developer") 执行。
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则(强制)
- 你只能处理 DEV-* 前缀的任务
- 所有输出必须带 [developer] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 DEV-* 任务
2. Skill(skill="team-frontend", args="--role=developer") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
// QA
Task({
subagent_type: "general-purpose",
team_name: teamName,
name: "qa",
prompt: `你是 team "${teamName}" 的 QA (质量保证)。
当你收到 QA-* 任务时,调用 Skill(skill="team-frontend", args="--role=qa") 执行。
当前需求: ${taskDescription}
Session: ${sessionFolder}
## 角色准则(强制)
- 你只能处理 QA-* 前缀的任务
- 所有输出必须带 [qa] 标识前缀
- 仅与 coordinator 通信
## 消息总线(必须)
每次 SendMessage 前,先调用 mcp__ccw-tools__team_msg 记录。
工作流程:
1. TaskList → 找到 QA-* 任务
2. Skill(skill="team-frontend", args="--role=qa") 执行
3. team_msg log + SendMessage 结果给 coordinator
4. TaskUpdate completed → 检查下一个任务`
})
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Unknown --role value | Error with available role list |
| Missing --role arg | Error with usage hint |
| Role file not found | Error with expected path (roles/{name}/role.md) |
| QA score < 6 超过 2 轮 GC | Coordinator 上报用户 |
| 双轨同步失败 | 回退到单轨顺序执行 |
| ui-ux-pro-max skill 未安装 | 降级为 LLM 通用设计知识,提示安装命令 |
| DEV 找不到设计文件 | 等待 Sync Point 或上报 |

View File

@@ -0,0 +1,150 @@
# Command: design-intelligence
> 通过 Skill 调用 ui-ux-pro-max 获取行业设计智能,生成 design-intelligence.json。
## When to Use
- Phase 3 of analyst role: Core design intelligence retrieval
- ui-ux-pro-max skill 已安装
## Strategy
### Delegation Mode
**Mode**: Skill invocation
**Skill**: `ui-ux-pro-max`
## Execution Steps
### Step 1: 调用 ui-ux-pro-max 生成设计系统
analyst 在 subagent 中通过 Skill 调用 ui-ux-pro-max获取完整设计系统推荐
```javascript
// 核心调用:生成完整设计系统
// ui-ux-pro-max 的 Step 2 会自动执行 search.py --design-system
Task({
subagent_type: "general-purpose",
run_in_background: false,
description: "Retrieve design intelligence via ui-ux-pro-max skill",
prompt: `调用 ui-ux-pro-max skill 获取设计系统推荐。
## 需求
- 产品类型/行业: ${industry}
- 关键词: ${keywords}
- 技术栈: ${detectedStack}
## 执行步骤
### 1. 生成设计系统(必须)
Skill(skill="ui-ux-pro-max", args="${industry} ${keywords} --design-system")
### 2. 补充 UX 指南
Skill(skill="ui-ux-pro-max", args="accessibility animation responsive --domain ux")
### 3. 获取技术栈指南
Skill(skill="ui-ux-pro-max", args="${keywords} --stack ${detectedStack}")
## 输出
将所有结果整合写入: ${sessionFolder}/analysis/design-intelligence-raw.md
包含:
- 设计系统推荐pattern, style, colors, typography, effects, anti-patterns
- UX 最佳实践
- 技术栈指南
- 行业反模式列表
`
})
```
### Step 2: 解析 Skill 输出
```javascript
// 读取 ui-ux-pro-max 的原始输出
let rawOutput = ''
try {
rawOutput = Read(`${sessionFolder}/analysis/design-intelligence-raw.md`)
} catch {}
// 解析为结构化 design-intelligence.json
const designIntelligence = {
_source: "ui-ux-pro-max-skill",
_generated_at: new Date().toISOString(),
industry: industry,
detected_stack: detectedStack,
design_system: parseDesignSystem(rawOutput),
ux_guidelines: parseUxGuidelines(rawOutput),
stack_guidelines: parseStackGuidelines(rawOutput),
recommendations: {
style: null,
color_palette: null,
typography: null,
anti_patterns: parseAntiPatterns(rawOutput),
must_have: industryConfig?.mustHave || []
}
}
Write(`${sessionFolder}/analysis/design-intelligence.json`, JSON.stringify(designIntelligence, null, 2))
```
### Step 3: Fallback
```javascript
// 若 ui-ux-pro-max skill 不可用(未安装),降级为 LLM 通用设计知识
// analyst 在 Phase 3 中直接基于 LLM 知识生成设计推荐
if (!skillAvailable) {
return {
_source: "llm-general-knowledge",
_fallback: true,
note: "ui-ux-pro-max skill not installed. Install via: /plugin install ui-ux-pro-max@ui-ux-pro-max-skill"
}
}
```
## Skill 调用参考
ui-ux-pro-max 支持的调用方式:
| 用途 | 调用 |
|------|------|
| 完整设计系统 | `Skill(skill="ui-ux-pro-max", args="<query> --design-system")` |
| 持久化设计系统 | `Skill(skill="ui-ux-pro-max", args="<query> --design-system --persist -p <name>")` |
| 领域搜索 | `Skill(skill="ui-ux-pro-max", args="<query> --domain <domain>")` |
| 技术栈指南 | `Skill(skill="ui-ux-pro-max", args="<query> --stack <stack>")` |
可用领域: product, style, typography, color, landing, chart, ux, web
可用技术栈: html-tailwind, react, nextjs, vue, svelte, shadcn, swiftui, react-native, flutter
## Output Format
```json
{
"_source": "ui-ux-pro-max-skill",
"design_system": {
"pattern": "...",
"style": "...",
"colors": { "primary": "...", "secondary": "...", "cta": "..." },
"typography": { "heading": "...", "body": "..." },
"effects": "...",
"anti_patterns": []
},
"ux_guidelines": [],
"stack_guidelines": {},
"recommendations": {
"style": null,
"color_palette": null,
"typography": null,
"anti_patterns": [],
"must_have": []
}
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| ui-ux-pro-max skill not installed | Fallback to LLM general knowledge, suggest install command |
| Skill execution error | Retry once, then fallback |
| Partial output | Use available data, fill gaps with defaults |
| Timeout | Use partial results, log warning |

View File

@@ -0,0 +1,361 @@
# Role: analyst
需求分析师。调用 ui-ux-pro-max 搜索引擎获取行业设计智能,分析需求、匹配行业推理规则、生成 design-intelligence.json 供下游角色消费。
## Role Identity
- **Name**: `analyst`
- **Task Prefix**: `ANALYZE-*`
- **Responsibility**: Read-only analysis + design intelligence retrieval
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[analyst]`
## Role Boundaries
### MUST
- 仅处理 `ANALYZE-*` 前缀的任务
- 所有输出必须带 `[analyst]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在需求分析和设计智能检索范围内工作
### MUST NOT
- ❌ 执行架构设计、代码实现、质量审查等其他角色职责
- ❌ 直接与其他 worker 角色通信
- ❌ 为其他角色创建任务
- ❌ 修改源代码文件
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `analyze_ready` | analyst → coordinator | Analysis complete | 设计智能已就绪,下游可消费 |
| `analyze_progress` | analyst → coordinator | Partial progress | 分析进度更新 |
| `error` | analyst → coordinator | Analysis failure | 分析失败或工具不可用 |
## Toolbox
### Available Tools
| Tool | Purpose |
|------|---------|
| Read, Glob, Grep | 读取项目文件、搜索现有代码模式 |
| Bash (search.py) | 调用 ui-ux-pro-max 搜索引擎 |
| WebSearch, WebFetch | 竞品参考、设计趋势搜索 |
| Task (cli-explore-agent) | 深度代码库探索 |
### Subagent Capabilities
| Agent Type | Purpose |
|------------|---------|
| `cli-explore-agent` | 探索现有代码库的设计模式和组件结构 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('ANALYZE-') &&
t.owner === 'analyst' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// Extract session folder from task description
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : null
// Extract industry context
const industryMatch = task.description.match(/Industry:\s*([^\n]+)/)
const industry = industryMatch ? industryMatch[1].trim() : 'SaaS/科技'
// Load shared memory
let sharedMemory = {}
try {
sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
} catch {}
// Load session info
let session = {}
try {
session = JSON.parse(Read(`${sessionFolder}/team-session.json`))
} catch {}
// Detect existing design system in project
const existingTokenFiles = Glob({ pattern: '**/*token*.*' })
const existingCssVars = Glob({ pattern: '**/*.css' })
// Detect tech stack
const packageJsonExists = Glob({ pattern: 'package.json' })
let detectedStack = 'html-tailwind'
if (packageJsonExists.length > 0) {
try {
const pkg = JSON.parse(Read('package.json'))
const deps = { ...pkg.dependencies, ...pkg.devDependencies }
if (deps['next']) detectedStack = 'nextjs'
else if (deps['react']) detectedStack = 'react'
else if (deps['vue']) detectedStack = 'vue'
else if (deps['svelte']) detectedStack = 'svelte'
if (deps['@shadcn/ui'] || deps['shadcn-ui']) detectedStack = 'shadcn'
} catch {}
}
```
### Phase 3: Core Analysis — Design Intelligence Retrieval
This is the key integration point with ui-ux-pro-max. 通过 Skill 调用获取设计智能。
详细执行策略见: [commands/design-intelligence.md](commands/design-intelligence.md)
#### Step 1: 通过 Skill 调用 ui-ux-pro-max
```javascript
const taskDesc = task.description.replace(/Session:.*\n?/g, '').replace(/Industry:.*\n?/g, '').trim()
const keywords = taskDesc.split(/\s+/).slice(0, 5).join(' ')
// 通过 subagent 调用 ui-ux-pro-max skill 获取完整设计智能
// ui-ux-pro-max 内部会自动执行 search.py --design-system
Task({
subagent_type: "general-purpose",
run_in_background: false,
description: "Retrieve design intelligence via ui-ux-pro-max skill",
prompt: `调用 ui-ux-pro-max skill 获取设计系统推荐。
## 需求
- 产品类型/行业: ${industry}
- 关键词: ${keywords}
- 技术栈: ${detectedStack}
## 执行步骤
### 1. 生成设计系统(必须)
Skill(skill="ui-ux-pro-max", args="${industry} ${keywords} --design-system")
### 2. 补充 UX 指南
Skill(skill="ui-ux-pro-max", args="accessibility animation responsive --domain ux")
### 3. 获取技术栈指南
Skill(skill="ui-ux-pro-max", args="${keywords} --stack ${detectedStack}")
## 输出
将所有结果整合写入: ${sessionFolder}/analysis/design-intelligence-raw.md
包含:
- 设计系统推荐pattern, style, colors, typography, effects, anti-patterns
- UX 最佳实践
- 技术栈指南
- 行业反模式列表
`
})
// 读取 skill 输出
let designSystemRaw = ''
try {
designSystemRaw = Read(`${sessionFolder}/analysis/design-intelligence-raw.md`)
} catch {
// Skill 输出不可用,将在 Step 3 使用 fallback
}
const uiproAvailable = designSystemRaw.length > 0
```
#### Step 2: Fallback — LLM 通用设计知识
```javascript
// 若 ui-ux-pro-max skill 不可用(未安装或执行失败),降级为 LLM 通用知识
if (!uiproAvailable) {
// analyst 直接基于 LLM 知识生成设计推荐
// 不需要外部工具,但质量低于 ui-ux-pro-max 的数据驱动推荐
designSystemRaw = null
}
```
#### Step 3: Analyze Existing Codebase
```javascript
// Explore existing design patterns in the project
let existingPatterns = {}
if (existingTokenFiles.length > 0 || existingCssVars.length > 0) {
Task({
subagent_type: "cli-explore-agent",
run_in_background: false,
description: "Explore existing design system",
prompt: `Analyze the existing design system in this project:
- Token files: ${existingTokenFiles.slice(0, 5).join(', ')}
- CSS files: ${existingCssVars.slice(0, 5).join(', ')}
Find: color palette, typography scale, spacing system, component patterns.
Output as JSON: { colors, typography, spacing, components, patterns }`
})
}
```
#### Step 4: Competitive Reference (optional)
```javascript
// Quick web search for design inspiration if needed
if (industry !== '其他') {
try {
const webResults = WebSearch({ query: `${industry} web design trends 2025 best practices` })
// Extract relevant insights
} catch {}
}
```
### Phase 4: Synthesis & Output
```javascript
// Compile design intelligence
// 若 Skill 调用成功,解析 raw output否则使用 LLM fallback
const designIntelligence = {
_source: uiproAvailable ? "ui-ux-pro-max-skill" : "llm-general-knowledge",
_generated_at: new Date().toISOString(),
industry: industry,
detected_stack: detectedStack,
// From ui-ux-pro-max skill (or LLM fallback)
design_system: uiproAvailable ? parseDesignSystem(designSystemRaw) : generateFallbackDesignSystem(industry, taskDesc),
ux_guidelines: uiproAvailable ? parseUxGuidelines(designSystemRaw) : [],
stack_guidelines: uiproAvailable ? parseStackGuidelines(designSystemRaw) : {},
// From codebase analysis
existing_patterns: existingPatterns,
existing_tokens: existingTokenFiles,
// Synthesized recommendations
recommendations: {
style: null, // Recommended UI style
color_palette: null, // Recommended colors
typography: null, // Recommended font pairing
anti_patterns: uiproAvailable ? parseAntiPatterns(designSystemRaw) : [],
must_have: session.industry_config?.mustHave || []
}
}
// Write design intelligence for downstream consumption
Write(`${sessionFolder}/analysis/design-intelligence.json`, JSON.stringify(designIntelligence, null, 2))
// Write human-readable requirements summary
Write(`${sessionFolder}/analysis/requirements.md`, `# Requirements Analysis
## Task
${taskDesc}
## Industry Context
- **Industry**: ${industry}
- **Detected Stack**: ${detectedStack}
- **Design Intelligence Source**: ${designIntelligence._source}
## Design System Recommendations
${designSystemRaw || '(Using LLM general knowledge — install ui-ux-pro-max for data-driven recommendations)'}
## Existing Patterns Found
${JSON.stringify(existingPatterns, null, 2)}
## Anti-Patterns to Avoid
${designIntelligence.recommendations.anti_patterns.map(p => \`- ❌ \${p}\`).join('\\n') || 'None specified'}
## Must-Have Requirements
${designIntelligence.recommendations.must_have.map(m => \`- ✅ \${m}\`).join('\\n') || 'Standard requirements'}
`)
// Update shared memory
sharedMemory.design_intelligence = designIntelligence
sharedMemory.industry_context = { industry, config: session.industry_config }
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
const resultStatus = 'complete'
const resultSummary = `Design intelligence generated (source: ${designIntelligence._source}), stack: ${detectedStack}, industry: ${industry}`
const resultDetails = `Files:\n- ${sessionFolder}/analysis/design-intelligence.json\n- ${sessionFolder}/analysis/requirements.md`
```
#### Fallback: LLM General Knowledge
```javascript
function generateFallbackDesignSystem(industry, taskDesc) {
// When ui-ux-pro-max skill is not installed, use LLM general knowledge
// Install: /plugin install ui-ux-pro-max@ui-ux-pro-max-skill
return {
_fallback: true,
note: "Generated from LLM general knowledge. Install ui-ux-pro-max skill for data-driven recommendations.",
colors: { primary: "#1976d2", secondary: "#dc004e", background: "#ffffff" },
typography: { heading: ["Inter", "system-ui"], body: ["Inter", "system-ui"] },
style: "modern-minimal"
}
}
```
### Phase 5: Report to Coordinator
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "analyst",
to: "coordinator",
type: "analyze_ready",
summary: `[analyst] ANALYZE complete: ${task.subject}`,
ref: `${sessionFolder}/analysis/design-intelligence.json`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [analyst] Analysis Results
**Task**: ${task.subject}
**Status**: ${resultStatus}
### Summary
${resultSummary}
### Design Intelligence
- **Source**: ${designIntelligence._source}
- **Industry**: ${industry}
- **Stack**: ${detectedStack}
- **Anti-patterns**: ${designIntelligence.recommendations.anti_patterns.length} identified
### Output Files
${resultDetails}`,
summary: `[analyst] ANALYZE complete`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task (e.g., ANALYZE-consult from CP-8)
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('ANALYZE-') &&
t.owner === 'analyst' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No ANALYZE-* tasks available | Idle, wait for coordinator |
| ui-ux-pro-max not found | Fallback to LLM general knowledge, log warning |
| search.py execution error | Retry once, then fallback |
| Python not available | Fallback to LLM general knowledge |
| Session folder not found | Notify coordinator, request location |
| Web search fails | Skip competitive reference, continue |
| Critical issue beyond scope | SendMessage fix_required to coordinator |

View File

@@ -0,0 +1,408 @@
# Role: architect
前端架构师。消费 design-intelligence.json定义设计令牌系统、组件架构、项目结构、技术选型。设计令牌值优先使用 ui-ux-pro-max 推荐值。
## Role Identity
- **Name**: `architect`
- **Task Prefix**: `ARCH-*`
- **Responsibility**: Code generation (architecture artifacts)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[architect]`
## Role Boundaries
### MUST
- 仅处理 `ARCH-*` 前缀的任务
- 所有输出必须带 `[architect]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在架构设计和令牌定义范围内工作
### MUST NOT
- ❌ 执行需求分析、代码实现、质量审查等其他角色职责
- ❌ 直接与其他 worker 角色通信
- ❌ 为其他角色创建任务
- ❌ 实现具体组件代码(仅定义规格)
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `arch_ready` | architect → coordinator | Architecture complete | 架构产出就绪,下游可消费 |
| `arch_revision` | architect → coordinator | Revision after QA feedback | 架构修订完成 |
| `arch_progress` | architect → coordinator | Partial progress | 架构进度更新 |
| `error` | architect → coordinator | Architecture failure | 架构设计失败 |
## Toolbox
### Available Tools
| Tool | Purpose |
|------|---------|
| Read, Write, Edit | 读写架构产物文件 |
| Glob, Grep | 搜索项目结构和模式 |
| Task (code-developer) | 复杂架构文件生成委派 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('ARCH-') &&
t.owner === 'architect' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// Extract session folder
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : null
// Extract scope (tokens / components / full)
const scopeMatch = task.description.match(/Scope:\s*([^\n]+)/)
const scope = scopeMatch ? scopeMatch[1].trim() : 'full'
// Load design intelligence from analyst
let designIntel = {}
try {
designIntel = JSON.parse(Read(`${sessionFolder}/analysis/design-intelligence.json`))
} catch {
// No design intelligence available — use defaults
}
// Load shared memory
let sharedMemory = {}
try {
sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
} catch {}
// Load existing project structure
const projectFiles = Glob({ pattern: 'src/**/*' })
const hasExistingProject = projectFiles.length > 0
```
### Phase 3: Architecture Design
#### Step 1: Design Token System (scope: tokens or full)
```javascript
if (scope === 'tokens' || scope === 'full') {
const recommended = designIntel.design_system || {}
const designTokens = {
"$schema": "https://design-tokens.github.io/community-group/format/",
"color": {
"primary": {
"$type": "color",
"$value": {
"light": recommended.colors?.primary || "#1976d2",
"dark": recommended.colors?.primary_dark || "#90caf9"
}
},
"secondary": {
"$type": "color",
"$value": {
"light": recommended.colors?.secondary || "#dc004e",
"dark": recommended.colors?.secondary_dark || "#f48fb1"
}
},
"background": {
"$type": "color",
"$value": { "light": recommended.colors?.background || "#ffffff", "dark": "#121212" }
},
"surface": {
"$type": "color",
"$value": { "light": "#f5f5f5", "dark": "#1e1e1e" }
},
"text": {
"$type": "color",
"$value": { "light": "#1a1a1a", "dark": "#e0e0e0" }
},
"cta": {
"$type": "color",
"$value": recommended.colors?.cta || "#F97316"
}
},
"typography": {
"font-family": {
"heading": {
"$type": "fontFamily",
"$value": recommended.typography?.heading || ["Inter", "system-ui", "sans-serif"]
},
"body": {
"$type": "fontFamily",
"$value": recommended.typography?.body || ["Inter", "system-ui", "sans-serif"]
},
"mono": {
"$type": "fontFamily",
"$value": ["JetBrains Mono", "Fira Code", "monospace"]
}
},
"font-size": {
"xs": { "$type": "dimension", "$value": "0.75rem" },
"sm": { "$type": "dimension", "$value": "0.875rem" },
"base": { "$type": "dimension", "$value": "1rem" },
"lg": { "$type": "dimension", "$value": "1.125rem" },
"xl": { "$type": "dimension", "$value": "1.25rem" },
"2xl": { "$type": "dimension", "$value": "1.5rem" },
"3xl": { "$type": "dimension", "$value": "2rem" }
}
},
"spacing": {
"xs": { "$type": "dimension", "$value": "0.25rem" },
"sm": { "$type": "dimension", "$value": "0.5rem" },
"md": { "$type": "dimension", "$value": "1rem" },
"lg": { "$type": "dimension", "$value": "1.5rem" },
"xl": { "$type": "dimension", "$value": "2rem" },
"2xl": { "$type": "dimension", "$value": "3rem" }
},
"border-radius": {
"sm": { "$type": "dimension", "$value": "0.25rem" },
"md": { "$type": "dimension", "$value": "0.5rem" },
"lg": { "$type": "dimension", "$value": "1rem" },
"full": { "$type": "dimension", "$value": "9999px" }
},
"shadow": {
"sm": { "$type": "shadow", "$value": "0 1px 2px rgba(0,0,0,0.05)" },
"md": { "$type": "shadow", "$value": "0 4px 6px rgba(0,0,0,0.1)" },
"lg": { "$type": "shadow", "$value": "0 10px 15px rgba(0,0,0,0.1)" }
},
"transition": {
"fast": { "$type": "duration", "$value": "150ms" },
"normal": { "$type": "duration", "$value": "200ms" },
"slow": { "$type": "duration", "$value": "300ms" }
}
}
Write(`${sessionFolder}/architecture/design-tokens.json`, JSON.stringify(designTokens, null, 2))
}
```
#### Step 2: Component Architecture (scope: components or full)
```javascript
if (scope === 'components' || scope === 'full') {
const taskDesc = task.description.replace(/Session:.*\n?/g, '').replace(/Scope:.*\n?/g, '').trim()
const antiPatterns = designIntel.recommendations?.anti_patterns || []
const styleHints = designIntel.design_system?.css_keywords || ''
// Analyze requirements and define component specs
// Each component spec includes: props, variants, accessibility, implementation hints
Bash(`mkdir -p "${sessionFolder}/architecture/component-specs"`)
// Generate component spec template with design intelligence hints
const componentSpecTemplate = `# Component: {name}
## Design Reference
- **Style**: ${designIntel.design_system?.style || 'modern-minimal'}
- **Stack**: ${designIntel.detected_stack || 'react'}
## Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
## Variants
| Variant | Description |
|---------|-------------|
## Accessibility
- Role:
- Keyboard:
- ARIA:
- Contrast: 4.5:1 minimum
## Implementation Hints
${styleHints ? `- CSS Keywords: ${styleHints}` : ''}
${antiPatterns.length > 0 ? `\n## Anti-Patterns to AVOID\n${antiPatterns.map(p => '- ❌ ' + p).join('\n')}` : ''}
`
// Write component specs based on task requirements
// (Actual component list derived from task description analysis)
}
```
#### Step 3: Project Structure
```javascript
if (scope === 'full' || !hasExistingProject) {
const stack = designIntel.detected_stack || 'react'
const projectStructure = {
stack: stack,
structure: getStackStructure(stack),
conventions: {
naming: "kebab-case for files, PascalCase for components",
imports: "absolute imports via @/ alias",
styling: stack === 'html-tailwind' ? 'Tailwind CSS' : 'CSS Modules + design tokens',
testing: "co-located test files (*.test.tsx)"
}
}
Write(`${sessionFolder}/architecture/project-structure.md`, `# Project Structure
## Stack: ${stack}
## Directory Layout
\`\`\`
${projectStructure.structure}
\`\`\`
## Conventions
${Object.entries(projectStructure.conventions).map(([k, v]) => `- **${k}**: ${v}`).join('\n')}
`)
}
function getStackStructure(stack) {
const structures = {
'react': `src/
├── components/ # Reusable UI components
│ ├── ui/ # Primitive components (Button, Input, etc.)
│ └── layout/ # Layout components (Header, Footer, etc.)
├── pages/ # Page-level components
├── hooks/ # Custom React hooks
├── styles/ # Global styles + design tokens
│ ├── tokens.css # CSS custom properties from design tokens
│ └── global.css # Global resets and base styles
├── utils/ # Utility functions
└── types/ # TypeScript type definitions`,
'nextjs': `app/
├── (routes)/ # Route groups
├── components/ # Shared components
│ ├── ui/ # Primitive components
│ └── layout/ # Layout components
├── lib/ # Utility functions
├── styles/ # Global styles + design tokens
│ ├── tokens.css
│ └── globals.css
└── types/ # TypeScript types`,
'vue': `src/
├── components/ # Vue components
│ ├── ui/ # Primitive components
│ └── layout/ # Layout components
├── views/ # Page views
├── composables/ # Vue composables
├── styles/ # Global styles + design tokens
└── types/ # TypeScript types`,
'html-tailwind': `src/
├── components/ # HTML partials
├── pages/ # HTML pages
├── styles/ # Tailwind config + custom CSS
│ └── tailwind.config.js
└── assets/ # Static assets`
}
return structures[stack] || structures['react']
}
```
### Phase 4: Self-Validation
```javascript
// Validate architecture artifacts
const validationResults = { issues: [] }
// Check design tokens JSON validity
try {
JSON.parse(Read(`${sessionFolder}/architecture/design-tokens.json`))
} catch (e) {
validationResults.issues.push({ severity: 'critical', message: 'design-tokens.json is invalid JSON' })
}
// Check color contrast (basic)
// Check that all required token categories exist
const requiredCategories = ['color', 'typography', 'spacing']
const tokens = JSON.parse(Read(`${sessionFolder}/architecture/design-tokens.json`))
for (const cat of requiredCategories) {
if (!tokens[cat]) {
validationResults.issues.push({ severity: 'high', message: `Missing token category: ${cat}` })
}
}
// Check anti-pattern compliance
const antiPatterns = designIntel.recommendations?.anti_patterns || []
// Verify token values don't violate industry anti-patterns
// Update shared memory with architecture output
sharedMemory.design_token_registry = tokens
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
const resultStatus = validationResults.issues.length === 0 ? 'complete' : 'complete_with_warnings'
const resultSummary = `Architecture artifacts generated for scope: ${scope}. ${validationResults.issues.length} issues found.`
const resultDetails = `Files:\n- ${sessionFolder}/architecture/design-tokens.json\n- ${sessionFolder}/architecture/project-structure.md\n- ${sessionFolder}/architecture/component-specs/`
```
### Phase 5: Report to Coordinator
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "architect",
to: "coordinator",
type: "arch_ready",
summary: `[architect] ARCH complete: ${task.subject}`,
ref: `${sessionFolder}/architecture/design-tokens.json`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [architect] Architecture Results
**Task**: ${task.subject}
**Status**: ${resultStatus}
**Scope**: ${scope}
### Summary
${resultSummary}
### Design Tokens
- Colors: ${Object.keys(tokens.color || {}).length} tokens
- Typography: ${Object.keys(tokens.typography || {}).length} categories
- Spacing: ${Object.keys(tokens.spacing || {}).length} scales
- Source: ${designIntel._source || 'defaults'}
### Output Files
${resultDetails}
${validationResults.issues.length > 0 ? `### Warnings\n${validationResults.issues.map(i => `- [${i.severity}] ${i.message}`).join('\n')}` : ''}`,
summary: `[architect] ARCH complete`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('ARCH-') &&
t.owner === 'architect' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No ARCH-* tasks available | Idle, wait for coordinator |
| design-intelligence.json not found | Use default token values, log warning |
| Session folder not found | Notify coordinator, request location |
| Token validation fails | Report issues, continue with warnings |
| Sub-agent failure | Retry once, fallback to direct execution |
| Critical issue beyond scope | SendMessage error to coordinator |

View File

@@ -0,0 +1,312 @@
# Role: coordinator
Frontend team coordinator. Orchestrates pipeline: requirement clarification → industry identification → team creation → task chain → dispatch → monitoring → reporting. Manages Generator-Critic loops between developer and qa, consulting pattern between developer and analyst.
## Role Identity
- **Name**: `coordinator`
- **Task Prefix**: N/A (coordinator creates tasks, doesn't receive them)
- **Responsibility**: Orchestration
- **Communication**: SendMessage to all teammates
- **Output Tag**: `[coordinator]`
## Role Boundaries
### MUST
- 所有输出SendMessage、team_msg、日志必须带 `[coordinator]` 标识
- 仅负责需求澄清、任务创建/分发、进度监控、结果汇报
- 通过 TaskCreate 创建任务并分配给 worker 角色
- 通过消息总线监控 worker 进度并路由消息
### MUST NOT
-**直接执行任何业务任务**(代码编写、分析、测试、审查等)
- ❌ 直接调用 code-developer、cli-explore-agent 等实现类 subagent
- ❌ 直接修改源代码或生成产物文件
- ❌ 绕过 worker 角色自行完成应委派的工作
- ❌ 在输出中省略 `[coordinator]` 标识
> **核心原则**: coordinator 是指挥者,不是执行者。所有实际工作必须通过 TaskCreate 委派给 worker 角色。
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `task_unblocked` | coordinator → any | Dependency resolved | Notify worker of available task |
| `sync_checkpoint` | coordinator → all | QA passed at sync point | Design artifacts stable for consumption |
| `fix_required` | coordinator → developer | QA found issues | Create DEV-fix task |
| `error` | coordinator → all | Critical system error | Escalation to user |
| `shutdown` | coordinator → all | Team being dissolved | Clean shutdown signal |
## Execution
### Phase 0: Session Resume Check
```javascript
const args = "$ARGUMENTS"
const isResume = /--resume|--continue/.test(args)
if (isResume) {
const sessionDirs = Glob({ pattern: '.workflow/.team/FE-*/team-session.json' })
const resumable = sessionDirs.map(f => {
try {
const session = JSON.parse(Read(f))
if (session.status === 'active' || session.status === 'paused') return session
} catch {}
return null
}).filter(Boolean)
if (resumable.length === 1) {
var resumedSession = resumable[0]
} else if (resumable.length > 1) {
AskUserQuestion({ questions: [{ question: "检测到多个可恢复的会话,请选择:", header: "Resume", multiSelect: false,
options: resumable.slice(0, 4).map(s => ({ label: s.session_id, description: `${s.topic} (${s.current_phase}, ${s.status})` }))
}]})
var resumedSession = resumable.find(s => s.session_id === userChoice)
}
if (resumedSession) {
const teamName = resumedSession.team_name
const sessionFolder = `.workflow/.team/${resumedSession.session_id}`
TeamCreate({ team_name: teamName })
// Spawn workers, create remaining tasks, jump to Phase 4
}
}
```
### Phase 1: Requirement Clarification
```javascript
const args = "$ARGUMENTS"
const teamNameMatch = args.match(/--team-name[=\s]+([\w-]+)/)
const teamName = teamNameMatch ? teamNameMatch[1] : `frontend-${Date.now().toString(36)}`
const taskDescription = args.replace(/--team-name[=\s]+[\w-]+/, '').replace(/--role[=\s]+\w+/, '').replace(/--resume|--continue/, '').trim()
```
Assess scope, industry, and select pipeline:
```javascript
AskUserQuestion({
questions: [
{
question: "前端开发范围:",
header: "Scope",
multiSelect: false,
options: [
{ label: "单页面", description: "设计并实现一个独立页面/组件" },
{ label: "多组件特性", description: "多组件 + 设计令牌 + 交互逻辑" },
{ label: "完整前端系统", description: "从零构建完整前端(令牌 + 组件库 + 页面)" }
]
},
{
question: "产品行业/类型:",
header: "Industry",
multiSelect: false,
options: [
{ label: "SaaS/科技", description: "SaaS、开发工具、AI 产品" },
{ label: "电商/零售", description: "电商、奢侈品、市场平台" },
{ label: "医疗/金融", description: "医疗、银行、保险(高合规要求)" },
{ label: "其他", description: "手动输入行业关键词" }
]
}
]
})
// Map scope to pipeline
const pipelineMap = {
'单页面': 'page',
'多组件特性': 'feature',
'完整前端系统': 'system'
}
const pipeline = pipelineMap[scopeChoice]
// Industry-based audit strictness
const industryConfig = {
'SaaS/科技': { strictness: 'standard', mustHave: [] },
'电商/零售': { strictness: 'standard', mustHave: ['responsive', 'performance'] },
'医疗/金融': { strictness: 'strict', mustHave: ['wcag-aaa', 'high-contrast', 'security-first'] },
'其他': { strictness: 'standard', mustHave: [] }
}
const industry = industryConfig[industryChoice]
```
Design constraints:
```javascript
AskUserQuestion({
questions: [{
question: "设计约束:",
header: "Constraint",
multiSelect: true,
options: [
{ label: "现有设计系统", description: "必须兼容现有设计令牌和组件" },
{ label: "WCAG AA", description: "必须满足 WCAG 2.1 AA 可访问性标准" },
{ label: "响应式", description: "必须支持 mobile/tablet/desktop" },
{ label: "暗色模式", description: "必须支持 light/dark 主题切换" }
]
}]
})
```
### Phase 2: Create Team + Session + Spawn Teammates
```javascript
// Create session directory
const slug = taskDescription.replace(/[^a-zA-Z0-9\u4e00-\u9fff]+/g, '-').slice(0, 30)
const date = new Date().toISOString().slice(0, 10)
const sessionId = `FE-${slug}-${date}`
const sessionFolder = `.workflow/.team/${sessionId}`
Bash(`mkdir -p "${sessionFolder}/analysis" "${sessionFolder}/architecture" "${sessionFolder}/qa" "${sessionFolder}/build"`)
// Initialize session
Write(`${sessionFolder}/team-session.json`, JSON.stringify({
session_id: sessionId,
team_name: teamName,
topic: taskDescription,
pipeline: pipeline,
industry: industryChoice,
industry_config: industry,
constraints: constraintChoices,
status: 'active',
current_phase: 'init',
created_at: new Date().toISOString()
}, null, 2))
// Initialize shared memory
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify({
design_intelligence: {},
design_token_registry: { colors: {}, typography: {}, spacing: {}, shadows: {} },
component_inventory: [],
style_decisions: [],
qa_history: [],
industry_context: { industry: industryChoice, config: industry }
}, null, 2))
// Create team and spawn workers
TeamCreate({ team_name: teamName })
// → Spawn analyst, architect, developer, qa (see SKILL.md Coordinator Spawn Template)
```
### Phase 3: Create Task Chain
Based on selected pipeline:
```javascript
if (pipeline === 'page') {
// CP-1 Linear: ANALYZE → ARCH → DEV → QA
TaskCreate({ subject: "ANALYZE-001: 需求分析与设计智能获取", description: `${taskDescription}\nSession: ${sessionFolder}\nIndustry: ${industryChoice}`, owner: "analyst" })
TaskCreate({ subject: "ARCH-001: 页面架构与设计令牌", description: `${taskDescription}\nSession: ${sessionFolder}`, owner: "architect", addBlockedBy: ["ANALYZE-001"] })
TaskCreate({ subject: "DEV-001: 页面实现", description: `${taskDescription}\nSession: ${sessionFolder}`, owner: "developer", addBlockedBy: ["ARCH-001"] })
TaskCreate({ subject: "QA-001: 代码审查与质量验证", description: `${taskDescription}\nSession: ${sessionFolder}`, owner: "qa", addBlockedBy: ["DEV-001"] })
}
if (pipeline === 'feature') {
// CP-1 + CP-2: ANALYZE → ARCH → QA(arch) → DEV → QA(code)
TaskCreate({ subject: "ANALYZE-001: 需求分析与设计智能获取", description: `${taskDescription}\nSession: ${sessionFolder}\nIndustry: ${industryChoice}`, owner: "analyst" })
TaskCreate({ subject: "ARCH-001: 设计令牌+组件架构", description: `${taskDescription}\nSession: ${sessionFolder}`, owner: "architect", addBlockedBy: ["ANALYZE-001"] })
TaskCreate({ subject: "QA-001: 架构审查", description: `审查 ARCH-001 产出\nSession: ${sessionFolder}\nType: architecture-review`, owner: "qa", addBlockedBy: ["ARCH-001"] })
TaskCreate({ subject: "DEV-001: 组件实现", description: `${taskDescription}\nSession: ${sessionFolder}`, owner: "developer", addBlockedBy: ["QA-001"] })
TaskCreate({ subject: "QA-002: 代码审查", description: `审查 DEV-001 产出\nSession: ${sessionFolder}\nType: code-review`, owner: "qa", addBlockedBy: ["DEV-001"] })
}
if (pipeline === 'system') {
// CP-1 + CP-2 + CP-9 Dual-Track
TaskCreate({ subject: "ANALYZE-001: 需求分析与设计智能获取", description: `${taskDescription}\nSession: ${sessionFolder}\nIndustry: ${industryChoice}`, owner: "analyst" })
TaskCreate({ subject: "ARCH-001: 设计令牌系统", description: `${taskDescription}\nSession: ${sessionFolder}\nScope: tokens`, owner: "architect", addBlockedBy: ["ANALYZE-001"] })
TaskCreate({ subject: "QA-001: 令牌审查", description: `审查 ARCH-001 令牌系统\nSession: ${sessionFolder}\nType: token-review`, owner: "qa", addBlockedBy: ["ARCH-001"] })
// Dual-track after QA-001
TaskCreate({ subject: "ARCH-002: 组件架构设计", description: `${taskDescription}\nSession: ${sessionFolder}\nScope: components`, owner: "architect", addBlockedBy: ["QA-001"] })
TaskCreate({ subject: "DEV-001: 令牌实现", description: `实现设计令牌\nSession: ${sessionFolder}\nScope: tokens`, owner: "developer", addBlockedBy: ["QA-001"] })
// Sync point 2
TaskCreate({ subject: "QA-002: 组件架构审查", description: `审查 ARCH-002 组件架构\nSession: ${sessionFolder}\nType: component-review`, owner: "qa", addBlockedBy: ["ARCH-002"] })
TaskCreate({ subject: "DEV-002: 组件实现", description: `${taskDescription}\nSession: ${sessionFolder}\nScope: components`, owner: "developer", addBlockedBy: ["QA-002", "DEV-001"] })
TaskCreate({ subject: "QA-003: 最终质量验证", description: `最终审查\nSession: ${sessionFolder}\nType: final`, owner: "qa", addBlockedBy: ["DEV-002"] })
}
```
### Phase 4: Coordination Loop
Receive teammate messages, dispatch based on content.
**Before each decision**: `team_msg list` to check recent messages.
**After each decision**: `team_msg log` to record.
| Received Message | Action |
|-----------------|--------|
| analyst: `analyze_ready` | team_msg log → TaskUpdate ANALYZE completed → unblock ARCH |
| architect: `arch_ready` | team_msg log → TaskUpdate ARCH completed → unblock QA/DEV |
| developer: `dev_complete` | team_msg log → TaskUpdate DEV completed → unblock QA |
| qa: `qa_passed` | team_msg log → TaskUpdate QA completed → unblock next stage |
| qa: `fix_required` | Create DEV-fix task → notify developer (CP-2 GC loop) |
| developer: consult request | Create ANALYZE-consult task → notify analyst (CP-8) |
| Worker: `error` | Assess severity → retry or escalate to user |
| All tasks completed | → Phase 5 |
#### GC Loop Control (CP-2)
```javascript
let gcRound = 0
const MAX_GC_ROUNDS = 2
// When QA sends fix_required
if (qaMessage.type === 'fix_required' && gcRound < MAX_GC_ROUNDS) {
gcRound++
// Create fix task for developer
TaskCreate({
subject: `DEV-fix-${gcRound}: 修复 QA 发现的问题`,
description: `${qaMessage.issues}\nSession: ${sessionFolder}\nGC Round: ${gcRound}`,
owner: "developer"
})
// Re-queue QA after fix
TaskCreate({
subject: `QA-recheck-${gcRound}: 复查修复`,
description: `复查 DEV-fix-${gcRound}\nSession: ${sessionFolder}`,
owner: "qa",
addBlockedBy: [`DEV-fix-${gcRound}`]
})
} else if (gcRound >= MAX_GC_ROUNDS) {
// Escalate to user
AskUserQuestion({ questions: [{ question: `QA 审查 ${MAX_GC_ROUNDS} 轮后仍有问题,如何处理?`, header: "GC Escalation", multiSelect: false,
options: [
{ label: "接受当前状态", description: "跳过剩余问题,继续下一阶段" },
{ label: "手动介入", description: "暂停流水线,手动修复" }
]
}]})
}
```
### Phase 5: Report + Persist
Summarize results. Update session status.
```javascript
// Update session
const session = JSON.parse(Read(`${sessionFolder}/team-session.json`))
session.status = 'completed'
session.completed_at = new Date().toISOString()
Write(`${sessionFolder}/team-session.json`, JSON.stringify(session, null, 2))
AskUserQuestion({
questions: [{
question: "当前需求已完成。下一步:",
header: "Next",
multiSelect: false,
options: [
{ label: "新需求", description: "提交新需求给当前团队" },
{ label: "关闭团队", description: "关闭所有 teammate 并清理" }
]
}]
})
// 新需求 → 回到 Phase 1
// 关闭 → shutdown → TeamDelete()
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| Teammate unresponsive | Send follow-up, 2x → respawn |
| QA rejected 3+ times | Escalate to user |
| Dual-track sync failure | Fallback to single-track sequential |
| ui-ux-pro-max unavailable | Continue with LLM general knowledge |
| DEV can't find design files | Wait for sync point or escalate |

View File

@@ -0,0 +1,348 @@
# Role: developer
前端开发者。消费架构产出,实现前端组件/页面代码。代码生成时引用 design-intelligence.json 的 Implementation Checklist 和技术栈指南,遵循 Anti-Patterns 约束。
## Role Identity
- **Name**: `developer`
- **Task Prefix**: `DEV-*`
- **Responsibility**: Code generation
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[developer]`
## Role Boundaries
### MUST
- 仅处理 `DEV-*` 前缀的任务
- 所有输出必须带 `[developer]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在前端代码实现范围内工作
### MUST NOT
- ❌ 执行需求分析、架构设计、质量审查等其他角色职责
- ❌ 直接与其他 worker 角色通信
- ❌ 为其他角色创建任务
- ❌ 修改设计令牌定义(仅消费)
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `dev_complete` | developer → coordinator | Implementation complete | 代码实现完成 |
| `dev_progress` | developer → coordinator | Partial progress | 实现进度更新 |
| `error` | developer → coordinator | Implementation failure | 实现失败 |
## Toolbox
### Available Tools
| Tool | Purpose |
|------|---------|
| Read, Write, Edit | 读写源代码文件 |
| Bash | 运行构建命令、安装依赖、格式化 |
| Glob, Grep | 搜索项目文件和代码模式 |
| Task (code-developer) | 复杂组件实现委派 |
### Subagent Capabilities
| Agent Type | Purpose |
|------------|---------|
| `code-developer` | 复杂组件/页面的代码实现 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('DEV-') &&
t.owner === 'developer' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// Extract session folder and scope
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : null
const scopeMatch = task.description.match(/Scope:\s*([^\n]+)/)
const scope = scopeMatch ? scopeMatch[1].trim() : 'full'
// Load design intelligence
let designIntel = {}
try {
designIntel = JSON.parse(Read(`${sessionFolder}/analysis/design-intelligence.json`))
} catch {}
// Load design tokens
let designTokens = {}
try {
designTokens = JSON.parse(Read(`${sessionFolder}/architecture/design-tokens.json`))
} catch {}
// Load project structure
let projectStructure = ''
try {
projectStructure = Read(`${sessionFolder}/architecture/project-structure.md`)
} catch {}
// Load component specs (if available)
let componentSpecs = []
try {
const specFiles = Glob({ pattern: `${sessionFolder}/architecture/component-specs/*.md` })
componentSpecs = specFiles.map(f => ({ name: f, content: Read(f) }))
} catch {}
// Load shared memory
let sharedMemory = {}
try {
sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
} catch {}
// Detect stack
const detectedStack = designIntel.detected_stack || 'react'
```
### Phase 3: Code Implementation
#### Step 1: Generate Design Token CSS
```javascript
if (scope === 'tokens' || scope === 'full') {
// Convert design-tokens.json to CSS custom properties
let cssVars = ':root {\n'
// Colors
if (designTokens.color) {
for (const [name, token] of Object.entries(designTokens.color)) {
const value = typeof token.$value === 'object' ? token.$value.light : token.$value
cssVars += ` --color-${name}: ${value};\n`
}
}
// Typography
if (designTokens.typography?.['font-family']) {
for (const [name, token] of Object.entries(designTokens.typography['font-family'])) {
const value = Array.isArray(token.$value) ? token.$value.join(', ') : token.$value
cssVars += ` --font-${name}: ${value};\n`
}
}
if (designTokens.typography?.['font-size']) {
for (const [name, token] of Object.entries(designTokens.typography['font-size'])) {
cssVars += ` --text-${name}: ${token.$value};\n`
}
}
// Spacing
if (designTokens.spacing) {
for (const [name, token] of Object.entries(designTokens.spacing)) {
cssVars += ` --space-${name}: ${token.$value};\n`
}
}
// Border radius
if (designTokens['border-radius']) {
for (const [name, token] of Object.entries(designTokens['border-radius'])) {
cssVars += ` --radius-${name}: ${token.$value};\n`
}
}
// Shadows
if (designTokens.shadow) {
for (const [name, token] of Object.entries(designTokens.shadow)) {
cssVars += ` --shadow-${name}: ${token.$value};\n`
}
}
// Transitions
if (designTokens.transition) {
for (const [name, token] of Object.entries(designTokens.transition)) {
cssVars += ` --duration-${name}: ${token.$value};\n`
}
}
cssVars += '}\n'
// Dark mode
if (designTokens.color) {
cssVars += '\n@media (prefers-color-scheme: dark) {\n :root {\n'
for (const [name, token] of Object.entries(designTokens.color)) {
if (typeof token.$value === 'object' && token.$value.dark) {
cssVars += ` --color-${name}: ${token.$value.dark};\n`
}
}
cssVars += ' }\n}\n'
}
// Write token CSS
Bash(`mkdir -p src/styles`)
Write('src/styles/tokens.css', cssVars)
}
```
#### Step 2: Implement Components
```javascript
if (scope === 'components' || scope === 'full') {
const taskDesc = task.description.replace(/Session:.*\n?/g, '').replace(/Scope:.*\n?/g, '').trim()
const antiPatterns = designIntel.recommendations?.anti_patterns || []
const stackGuidelines = designIntel.stack_guidelines || {}
const implementationChecklist = designIntel.design_system?.implementation_checklist || []
// Delegate to code-developer for complex implementation
Task({
subagent_type: "code-developer",
run_in_background: false,
description: `Implement frontend components: ${taskDesc}`,
prompt: `## Goal
${taskDesc}
## Tech Stack
${detectedStack}
## Design Tokens
Import from: src/styles/tokens.css
Use CSS custom properties (var(--color-primary), var(--space-md), etc.)
## Component Specs
${componentSpecs.map(s => s.content).join('\n\n---\n\n')}
## Stack-Specific Guidelines
${JSON.stringify(stackGuidelines, null, 2)}
## Implementation Checklist (MUST verify each item)
${implementationChecklist.map(item => `- [ ] ${item}`).join('\n') || '- [ ] Semantic HTML\n- [ ] Keyboard accessible\n- [ ] Responsive layout\n- [ ] Dark mode support'}
## Anti-Patterns to AVOID
${antiPatterns.map(p => `- ❌ ${p}`).join('\n') || 'None specified'}
## Coding Standards
- Use design token CSS variables, never hardcode colors/spacing
- All interactive elements must have cursor: pointer
- Transitions: 150-300ms (use var(--duration-normal))
- Text contrast: minimum 4.5:1 ratio
- Include focus-visible styles for keyboard navigation
- Support prefers-reduced-motion
- Responsive: mobile-first with md/lg breakpoints
- No emoji as functional icons
`
})
}
```
### Phase 4: Self-Validation
```javascript
// Pre-delivery self-check
const implementedFiles = Glob({ pattern: 'src/**/*.{tsx,jsx,vue,svelte,html,css}' })
const selfCheckResults = { passed: [], failed: [] }
for (const file of implementedFiles.slice(0, 20)) {
try {
const content = Read(file)
// Check: no hardcoded colors (hex outside tokens.css)
if (file !== 'src/styles/tokens.css' && /#[0-9a-fA-F]{3,8}/.test(content)) {
selfCheckResults.failed.push({ file, check: 'hardcoded-color', message: 'Found hardcoded color value' })
}
// Check: cursor-pointer on interactive elements
if (/button|<a |onClick|@click/.test(content) && !/cursor-pointer/.test(content)) {
selfCheckResults.failed.push({ file, check: 'cursor-pointer', message: 'Missing cursor-pointer on interactive element' })
}
// Check: focus styles
if (/button|input|select|textarea|<a /.test(content) && !/focus/.test(content)) {
selfCheckResults.failed.push({ file, check: 'focus-styles', message: 'Missing focus styles' })
}
// Check: responsive
if (/className|class=/.test(content) && !/md:|lg:|@media/.test(content)) {
selfCheckResults.failed.push({ file, check: 'responsive', message: 'No responsive breakpoints found' })
}
} catch {}
}
// Auto-fix simple issues if possible
for (const failure of selfCheckResults.failed) {
if (failure.check === 'cursor-pointer') {
// Attempt to add cursor-pointer to button/link styles
}
}
// Update shared memory
sharedMemory.component_inventory = implementedFiles.map(f => ({ path: f, status: 'implemented' }))
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
const resultStatus = selfCheckResults.failed.length === 0 ? 'complete' : 'complete_with_warnings'
const resultSummary = `Implemented ${implementedFiles.length} files. Self-check: ${selfCheckResults.failed.length} issues.`
const resultDetails = `Files:\n${implementedFiles.map(f => `- ${f}`).join('\n')}\n\n${selfCheckResults.failed.length > 0 ? `Self-check issues:\n${selfCheckResults.failed.map(f => `- [${f.check}] ${f.file}: ${f.message}`).join('\n')}` : 'All self-checks passed.'}`
```
### Phase 5: Report to Coordinator
```javascript
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "developer",
to: "coordinator",
type: "dev_complete",
summary: `[developer] DEV complete: ${task.subject}`
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [developer] Implementation Results
**Task**: ${task.subject}
**Status**: ${resultStatus}
**Scope**: ${scope}
### Summary
${resultSummary}
### Details
${resultDetails}`,
summary: `[developer] DEV complete`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('DEV-') &&
t.owner === 'developer' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No DEV-* tasks available | Idle, wait for coordinator |
| design-tokens.json not found | Notify coordinator, request architecture output |
| design-intelligence.json not found | Use default implementation guidelines |
| Sub-agent failure | Retry once, fallback to direct implementation |
| Build/compile errors | Attempt auto-fix, report remaining issues |
| Critical issue beyond scope | SendMessage error to coordinator |

View File

@@ -0,0 +1,116 @@
# Command: pre-delivery-checklist
> 最终交付前的 CSS 级别精准检查清单,融合 ui-ux-pro-max Pre-Delivery Checklist 和 ux-guidelines.csv 规则。
## When to Use
- Phase 3 of qa role, Dimension 5: Pre-Delivery
- Final review type (`reviewType === 'final'` or `reviewType === 'code-review'`)
## Strategy
### Delegation Mode
**Mode**: Direct (inline pattern matching)
## Checklist Items
### Accessibility
| # | Check | Pattern | Severity | Do | Don't |
|---|-------|---------|----------|-----|-------|
| 1 | Images have alt text | `<img` without `alt=` | CRITICAL | Always provide descriptive alt text | Leave alt empty without role="presentation" |
| 2 | Form inputs have labels | `<input` without `<label`/`aria-label` | HIGH | Associate every input with a label | Use placeholder as sole label |
| 3 | Focus states visible | Interactive elements without `focus` styles | HIGH | Add focus-visible outline | Remove default focus ring without replacement |
| 4 | Color contrast 4.5:1 | Light text on light background | HIGH | Ensure 4.5:1 minimum ratio | Use low-contrast decorative text for content |
| 5 | prefers-reduced-motion | Animations without media query | MEDIUM | Wrap in @media (prefers-reduced-motion: no-preference) | Force animations on all users |
| 6 | Heading hierarchy | Skipped heading levels (h1→h3) | MEDIUM | Use sequential heading levels | Skip levels for visual sizing |
### Interaction
| # | Check | Pattern | Severity | Do | Don't |
|---|-------|---------|----------|-----|-------|
| 7 | cursor-pointer on clickable | Buttons/links without cursor-pointer | MEDIUM | Add cursor: pointer to all clickable elements | Leave default cursor |
| 8 | Transitions 150-300ms | Duration outside range | LOW | Use 150-300ms for micro-interactions | Use >500ms or <100ms transitions |
| 9 | Loading states | Async ops without loading indicator | MEDIUM | Show skeleton/spinner during fetch | Leave blank screen while loading |
| 10 | Error states | Async ops without error handling | HIGH | Show user-friendly error message | Silently fail or show raw error |
### Design Compliance
| # | Check | Pattern | Severity | Do | Don't |
|---|-------|---------|----------|-----|-------|
| 11 | No hardcoded colors | Hex values outside tokens.css | HIGH | Use var(--color-*) tokens | Hardcode #hex values |
| 12 | No hardcoded spacing | px values for margin/padding | MEDIUM | Use var(--space-*) tokens | Hardcode pixel values |
| 13 | No emoji as icons | Unicode emoji in UI | HIGH | Use proper SVG/icon library | Use emoji for functional icons |
| 14 | Dark mode support | No prefers-color-scheme | MEDIUM | Support light/dark themes | Design for light mode only |
### Layout
| # | Check | Pattern | Severity | Do | Don't |
|---|-------|---------|----------|-----|-------|
| 15 | Responsive breakpoints | No md:/lg:/@media | MEDIUM | Mobile-first responsive design | Desktop-only layout |
| 16 | No horizontal scroll | Fixed widths > viewport | HIGH | Use relative/fluid widths | Set fixed pixel widths on containers |
## Execution
```javascript
function runPreDeliveryChecklist(fileContents) {
const results = { passed: 0, failed: 0, items: [] }
const checks = [
{ id: 1, check: "Images have alt text", test: (c) => /<img\s/.test(c) && !/<img\s[^>]*alt=/.test(c), severity: 'CRITICAL' },
{ id: 7, check: "cursor-pointer on clickable", test: (c) => /button|onClick/.test(c) && !/cursor-pointer/.test(c), severity: 'MEDIUM' },
{ id: 11, check: "No hardcoded colors", test: (c, f) => f !== 'src/styles/tokens.css' && /#[0-9a-fA-F]{6}/.test(c), severity: 'HIGH' },
{ id: 13, check: "No emoji as icons", test: (c) => /[\u{1F300}-\u{1F9FF}]/u.test(c), severity: 'HIGH' },
{ id: 14, check: "Dark mode support", test: (c) => !/prefers-color-scheme|dark:|\.dark/.test(c), severity: 'MEDIUM', global: true },
{ id: 15, check: "Responsive breakpoints", test: (c) => !/md:|lg:|@media.*min-width/.test(c), severity: 'MEDIUM', global: true }
]
// Per-file checks
for (const [file, content] of Object.entries(fileContents)) {
for (const check of checks.filter(c => !c.global)) {
if (check.test(content, file)) {
results.failed++
results.items.push({ ...check, file, status: 'FAIL' })
} else {
results.passed++
results.items.push({ ...check, file, status: 'PASS' })
}
}
}
// Global checks (across all content)
const allContent = Object.values(fileContents).join('\n')
for (const check of checks.filter(c => c.global)) {
if (check.test(allContent)) {
results.failed++
results.items.push({ ...check, file: 'global', status: 'FAIL' })
} else {
results.passed++
results.items.push({ ...check, file: 'global', status: 'PASS' })
}
}
return results
}
```
## Output Format
```
## Pre-Delivery Checklist Results
- Passed: X / Y
- Failed: Z
### Failed Items
- [CRITICAL] #1 Images have alt text — src/components/Hero.tsx
- [HIGH] #11 No hardcoded colors — src/styles/custom.css
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No files to check | Report empty checklist, score 10/10 |
| File read error | Skip file, note in report |
| Regex error | Skip check, note in report |

View File

@@ -0,0 +1,491 @@
# Role: qa
质量保证工程师。融合 ux-guidelines.csv 的 Do/Don't 规则、Pre-Delivery Checklist、行业反模式库执行 5 维度代码审查。从概念级审查升级为 CSS 级别精准审查。
## Role Identity
- **Name**: `qa`
- **Task Prefix**: `QA-*`
- **Responsibility**: Read-only analysis (code review + quality audit)
- **Communication**: SendMessage to coordinator only
- **Output Tag**: `[qa]`
## Role Boundaries
### MUST
- 仅处理 `QA-*` 前缀的任务
- 所有输出必须带 `[qa]` 标识
- 仅通过 SendMessage 与 coordinator 通信
- 严格在质量审查范围内工作
### MUST NOT
- ❌ 执行需求分析、架构设计、代码实现等其他角色职责
- ❌ 直接与其他 worker 角色通信
- ❌ 为其他角色创建任务
- ❌ 直接修改源代码(仅报告问题)
## Message Types
| Type | Direction | Trigger | Description |
|------|-----------|---------|-------------|
| `qa_passed` | qa → coordinator | All checks passed | 审查通过,可进入下一阶段 |
| `qa_result` | qa → coordinator | Review complete with findings | 审查完成,有发现需处理 |
| `fix_required` | qa → coordinator | Critical issues found | 发现严重问题,需修复 (triggers CP-2 GC loop) |
| `error` | qa → coordinator | Review failure | 审查过程失败 |
## Toolbox
### Available Tools
| Tool | Purpose |
|------|---------|
| Read, Glob, Grep | 读取代码文件、搜索模式 |
| Bash (read-only) | 运行 lint/type-check 等只读检查命令 |
## 5-Dimension Audit Framework
| Dimension | Weight | Source | Focus |
|-----------|--------|--------|-------|
| Code Quality | 0.20 | Standard code review | 代码结构、命名、可维护性 |
| Accessibility | 0.25 | ux-guidelines.csv accessibility rules | WCAG 合规、键盘导航、屏幕阅读器 |
| Design Compliance | 0.20 | design-intelligence.json anti-patterns | 行业反模式检查、设计令牌使用 |
| UX Best Practices | 0.20 | ux-guidelines.csv Do/Don't rules | 交互模式、响应式、动画 |
| Pre-Delivery | 0.15 | ui-ux-pro-max Pre-Delivery Checklist | 最终交付检查清单 |
## Execution (5-Phase)
### Phase 1: Task Discovery
```javascript
const tasks = TaskList()
const myTasks = tasks.filter(t =>
t.subject.startsWith('QA-') &&
t.owner === 'qa' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (myTasks.length === 0) return // idle
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })
```
### Phase 2: Context Loading
```javascript
// Extract session folder and review type
const sessionMatch = task.description.match(/Session:\s*([^\n]+)/)
const sessionFolder = sessionMatch ? sessionMatch[1].trim() : null
const typeMatch = task.description.match(/Type:\s*([^\n]+)/)
const reviewType = typeMatch ? typeMatch[1].trim() : 'code-review'
// Types: architecture-review, token-review, component-review, code-review, final
// Load design intelligence
let designIntel = {}
try {
designIntel = JSON.parse(Read(`${sessionFolder}/analysis/design-intelligence.json`))
} catch {}
// Load design tokens
let designTokens = {}
try {
designTokens = JSON.parse(Read(`${sessionFolder}/architecture/design-tokens.json`))
} catch {}
// Load shared memory for industry context
let sharedMemory = {}
try {
sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
} catch {}
const industryContext = sharedMemory.industry_context || {}
const antiPatterns = designIntel.recommendations?.anti_patterns || []
const mustHave = designIntel.recommendations?.must_have || []
// Determine audit strictness from industry
const strictness = industryContext.config?.strictness || 'standard'
// Collect files to review based on review type
let filesToReview = []
if (reviewType === 'architecture-review' || reviewType === 'token-review') {
filesToReview = Glob({ pattern: `${sessionFolder}/architecture/**/*` })
} else if (reviewType === 'component-review') {
filesToReview = Glob({ pattern: `${sessionFolder}/architecture/component-specs/**/*` })
} else {
// code-review or final: review implemented source files
filesToReview = Glob({ pattern: 'src/**/*.{tsx,jsx,vue,svelte,html,css}' })
}
// Read file contents
const fileContents = {}
for (const file of filesToReview.slice(0, 30)) {
try { fileContents[file] = Read(file) } catch {}
}
```
### Phase 3: 5-Dimension Audit
```javascript
const audit = {
score: 0,
dimensions: {},
issues: [],
passed: [],
critical_count: 0
}
// ═══════════════════════════════════════════
// Dimension 1: Code Quality (weight: 0.20)
// ═══════════════════════════════════════════
const codeQuality = { score: 10, issues: [] }
for (const [file, content] of Object.entries(fileContents)) {
// Check: consistent naming conventions
// Check: no unused imports/variables
// Check: reasonable file length (< 300 lines)
if (content.split('\n').length > 300) {
codeQuality.issues.push({ file, severity: 'MEDIUM', message: 'File exceeds 300 lines, consider splitting' })
codeQuality.score -= 1
}
// Check: no console.log in production code
if (/console\.(log|debug)/.test(content) && !/\.test\.|\.spec\./.test(file)) {
codeQuality.issues.push({ file, severity: 'LOW', message: 'console.log found in production code' })
codeQuality.score -= 0.5
}
// Check: proper error handling
if (/catch\s*\(\s*\)\s*\{[\s]*\}/.test(content)) {
codeQuality.issues.push({ file, severity: 'HIGH', message: 'Empty catch block found' })
codeQuality.score -= 2
}
}
audit.dimensions.code_quality = { weight: 0.20, score: Math.max(0, codeQuality.score), issues: codeQuality.issues }
// ═══════════════════════════════════════════
// Dimension 2: Accessibility (weight: 0.25)
// ═══════════════════════════════════════════
const accessibility = { score: 10, issues: [] }
for (const [file, content] of Object.entries(fileContents)) {
if (!/\.(tsx|jsx|vue|svelte|html)$/.test(file)) continue
// Check: images have alt text
if (/<img\s/.test(content) && !/<img\s[^>]*alt=/.test(content)) {
accessibility.issues.push({ file, severity: 'CRITICAL', message: 'Image missing alt attribute', do: 'Always provide alt text', dont: 'Leave alt empty for decorative images without role="presentation"' })
accessibility.score -= 3
}
// Check: form inputs have labels
if (/<input\s/.test(content) && !/<label/.test(content) && !/aria-label/.test(content)) {
accessibility.issues.push({ file, severity: 'HIGH', message: 'Form input missing associated label', do: 'Use <label> or aria-label', dont: 'Rely on placeholder as label' })
accessibility.score -= 2
}
// Check: buttons have accessible text
if (/<button\s/.test(content) && /<button\s[^>]*>\s*</.test(content) && !/aria-label/.test(content)) {
accessibility.issues.push({ file, severity: 'HIGH', message: 'Button may lack accessible text (icon-only?)', do: 'Add aria-label for icon-only buttons', dont: 'Use title attribute as sole accessible name' })
accessibility.score -= 2
}
// Check: heading hierarchy
if (/h[1-6]/.test(content)) {
const headings = content.match(/<h([1-6])/g)?.map(h => parseInt(h[2])) || []
for (let i = 1; i < headings.length; i++) {
if (headings[i] - headings[i-1] > 1) {
accessibility.issues.push({ file, severity: 'MEDIUM', message: `Heading level skipped: h${headings[i-1]} → h${headings[i]}` })
accessibility.score -= 1
}
}
}
// Check: color contrast (basic — flag hardcoded light colors on light bg)
// Check: focus-visible styles
if (/button|<a |input|select/.test(content) && !/focus-visible|focus:/.test(content)) {
accessibility.issues.push({ file, severity: 'HIGH', message: 'Interactive element missing focus styles', do: 'Add focus-visible outline', dont: 'Remove default focus outline without replacement' })
accessibility.score -= 2
}
// Check: ARIA roles used correctly
if (/role=/.test(content) && /role="(button|link)"/.test(content)) {
// Verify tabindex is present for non-native elements with role
if (!/tabindex/.test(content)) {
accessibility.issues.push({ file, severity: 'MEDIUM', message: 'Element with ARIA role may need tabindex' })
accessibility.score -= 1
}
}
}
// Strict mode: additional checks for medical/financial
if (strictness === 'strict') {
for (const [file, content] of Object.entries(fileContents)) {
// Check: prefers-reduced-motion
if (/animation|transition|@keyframes/.test(content) && !/prefers-reduced-motion/.test(content)) {
accessibility.issues.push({ file, severity: 'HIGH', message: 'Animation without prefers-reduced-motion respect', do: 'Wrap animations in @media (prefers-reduced-motion: no-preference)', dont: 'Force animations on all users' })
accessibility.score -= 2
}
}
}
audit.dimensions.accessibility = { weight: 0.25, score: Math.max(0, accessibility.score), issues: accessibility.issues }
// ═══════════════════════════════════════════
// Dimension 3: Design Compliance (weight: 0.20)
// ═══════════════════════════════════════════
const designCompliance = { score: 10, issues: [] }
for (const [file, content] of Object.entries(fileContents)) {
// Check: using design tokens (no hardcoded colors)
if (file !== 'src/styles/tokens.css' && /#[0-9a-fA-F]{3,8}/.test(content)) {
const hardcodedColors = content.match(/#[0-9a-fA-F]{3,8}/g) || []
designCompliance.issues.push({ file, severity: 'HIGH', message: `${hardcodedColors.length} hardcoded color(s) found — use design token variables`, do: 'Use var(--color-primary)', dont: 'Hardcode #1976d2' })
designCompliance.score -= 2
}
// Check: using spacing tokens
if (/margin|padding/.test(content) && /:\s*\d+px/.test(content) && !/var\(--space/.test(content)) {
designCompliance.issues.push({ file, severity: 'MEDIUM', message: 'Hardcoded spacing values — use spacing tokens', do: 'Use var(--space-md)', dont: 'Hardcode 16px' })
designCompliance.score -= 1
}
// Check: industry anti-patterns
for (const pattern of antiPatterns) {
// Each anti-pattern is a string description — check for common violations
if (typeof pattern === 'string') {
const patternLower = pattern.toLowerCase()
if (patternLower.includes('gradient') && /gradient/.test(content)) {
designCompliance.issues.push({ file, severity: 'CRITICAL', message: `Industry anti-pattern violation: ${pattern}` })
designCompliance.score -= 3
}
if (patternLower.includes('emoji') && /[\u{1F300}-\u{1F9FF}]/u.test(content)) {
designCompliance.issues.push({ file, severity: 'HIGH', message: `Industry anti-pattern violation: ${pattern}` })
designCompliance.score -= 2
}
}
}
}
audit.dimensions.design_compliance = { weight: 0.20, score: Math.max(0, designCompliance.score), issues: designCompliance.issues }
// ═══════════════════════════════════════════
// Dimension 4: UX Best Practices (weight: 0.20)
// ═══════════════════════════════════════════
const uxPractices = { score: 10, issues: [] }
for (const [file, content] of Object.entries(fileContents)) {
// Check: cursor-pointer on clickable elements
if (/button|<a |onClick|@click/.test(content) && !/cursor-pointer/.test(content) && /\.css$/.test(file)) {
uxPractices.issues.push({ file, severity: 'MEDIUM', message: 'Missing cursor: pointer on clickable element', do: 'Add cursor: pointer to all clickable elements', dont: 'Leave default cursor on buttons/links' })
uxPractices.score -= 1
}
// Check: transition duration in valid range (150-300ms)
const durations = content.match(/duration[:-]\s*(\d+)/g) || []
for (const d of durations) {
const ms = parseInt(d.match(/\d+/)[0])
if (ms > 0 && (ms < 100 || ms > 500)) {
uxPractices.issues.push({ file, severity: 'LOW', message: `Transition duration ${ms}ms outside recommended range (150-300ms)` })
uxPractices.score -= 0.5
}
}
// Check: responsive breakpoints
if (/className|class=/.test(content) && !/md:|lg:|@media/.test(content) && /\.(tsx|jsx|vue|html)$/.test(file)) {
uxPractices.issues.push({ file, severity: 'MEDIUM', message: 'No responsive breakpoints detected', do: 'Use mobile-first responsive design', dont: 'Design for desktop only' })
uxPractices.score -= 1
}
// Check: loading states for async operations
if (/fetch|axios|useSWR|useQuery/.test(content) && !/loading|isLoading|skeleton|spinner/.test(content)) {
uxPractices.issues.push({ file, severity: 'MEDIUM', message: 'Async operation without loading state', do: 'Show loading indicator during data fetching', dont: 'Leave blank screen while loading' })
uxPractices.score -= 1
}
// Check: error states
if (/fetch|axios|useSWR|useQuery/.test(content) && !/error|isError|catch/.test(content)) {
uxPractices.issues.push({ file, severity: 'HIGH', message: 'Async operation without error handling', do: 'Show user-friendly error message', dont: 'Silently fail or show raw error' })
uxPractices.score -= 2
}
}
audit.dimensions.ux_practices = { weight: 0.20, score: Math.max(0, uxPractices.score), issues: uxPractices.issues }
// ═══════════════════════════════════════════
// Dimension 5: Pre-Delivery Checklist (weight: 0.15)
// ═══════════════════════════════════════════
const preDelivery = { score: 10, issues: [] }
// Only run full pre-delivery on final review
if (reviewType === 'final' || reviewType === 'code-review') {
const allContent = Object.values(fileContents).join('\n')
const checklist = [
{ check: "No emojis as functional icons", test: () => /[\u{1F300}-\u{1F9FF}]/u.test(allContent), severity: 'HIGH' },
{ check: "cursor-pointer on clickable", test: () => /button|onClick/.test(allContent) && !/cursor-pointer/.test(allContent), severity: 'MEDIUM' },
{ check: "Transitions 150-300ms", test: () => { const m = allContent.match(/duration[:-]\s*(\d+)/g); return m?.some(d => { const v = parseInt(d.match(/\d+/)[0]); return v > 0 && (v < 100 || v > 500) }) }, severity: 'LOW' },
{ check: "Focus states visible", test: () => /button|input|<a /.test(allContent) && !/focus/.test(allContent), severity: 'HIGH' },
{ check: "prefers-reduced-motion", test: () => /animation|@keyframes/.test(allContent) && !/prefers-reduced-motion/.test(allContent), severity: 'MEDIUM' },
{ check: "Responsive breakpoints", test: () => !/md:|lg:|@media.*min-width/.test(allContent), severity: 'MEDIUM' },
{ check: "No hardcoded colors", test: () => { const nonToken = Object.entries(fileContents).filter(([f]) => f !== 'src/styles/tokens.css'); return nonToken.some(([,c]) => /#[0-9a-fA-F]{6}/.test(c)) }, severity: 'HIGH' },
{ check: "Dark mode support", test: () => !/prefers-color-scheme|dark:|\.dark/.test(allContent), severity: 'MEDIUM' }
]
for (const item of checklist) {
try {
if (item.test()) {
preDelivery.issues.push({ check: item.check, severity: item.severity, message: `Pre-delivery check failed: ${item.check}` })
preDelivery.score -= (item.severity === 'HIGH' ? 2 : item.severity === 'MEDIUM' ? 1 : 0.5)
}
} catch {}
}
}
audit.dimensions.pre_delivery = { weight: 0.15, score: Math.max(0, preDelivery.score), issues: preDelivery.issues }
```
### Phase 4: Score Calculation & Report
```javascript
// Calculate weighted score
audit.score = Object.values(audit.dimensions).reduce((sum, dim) => {
return sum + (dim.score * dim.weight)
}, 0)
// Collect all issues
audit.issues = Object.values(audit.dimensions).flatMap(dim => dim.issues)
audit.critical_count = audit.issues.filter(i => i.severity === 'CRITICAL').length
audit.passed = Object.entries(audit.dimensions)
.filter(([, dim]) => dim.issues.length === 0)
.map(([name]) => name)
// Determine verdict
let verdict = 'PASSED'
if (audit.score < 6 || audit.critical_count > 0) {
verdict = 'FIX_REQUIRED'
} else if (audit.score < 8) {
verdict = 'PASSED_WITH_WARNINGS'
}
// Write audit report
const auditIndex = Glob({ pattern: `${sessionFolder}/qa/audit-*.md` }).length + 1
const auditFile = `${sessionFolder}/qa/audit-${String(auditIndex).padStart(3, '0')}.md`
Write(auditFile, `# QA Audit Report #${auditIndex}
## Summary
- **Review Type**: ${reviewType}
- **Verdict**: ${verdict}
- **Score**: ${audit.score.toFixed(1)} / 10
- **Critical Issues**: ${audit.critical_count}
- **Total Issues**: ${audit.issues.length}
- **Strictness**: ${strictness}
## Dimension Scores
| Dimension | Weight | Score | Issues |
|-----------|--------|-------|--------|
| Code Quality | 0.20 | ${audit.dimensions.code_quality.score.toFixed(1)} | ${audit.dimensions.code_quality.issues.length} |
| Accessibility | 0.25 | ${audit.dimensions.accessibility.score.toFixed(1)} | ${audit.dimensions.accessibility.issues.length} |
| Design Compliance | 0.20 | ${audit.dimensions.design_compliance.score.toFixed(1)} | ${audit.dimensions.design_compliance.issues.length} |
| UX Best Practices | 0.20 | ${audit.dimensions.ux_practices.score.toFixed(1)} | ${audit.dimensions.ux_practices.issues.length} |
| Pre-Delivery | 0.15 | ${audit.dimensions.pre_delivery.score.toFixed(1)} | ${audit.dimensions.pre_delivery.issues.length} |
## Issues
${audit.issues.map(i => `### [${i.severity}] ${i.message}
- **File**: ${i.file || i.check || 'N/A'}
${i.do ? `- ✅ **Do**: ${i.do}` : ''}
${i.dont ? `- ❌ **Don't**: ${i.dont}` : ''}
`).join('\n')}
## Passed Dimensions
${audit.passed.map(p => `- ✅ ${p}`).join('\n') || 'None — all dimensions have issues'}
`)
// Update shared memory
sharedMemory.qa_history = sharedMemory.qa_history || []
sharedMemory.qa_history.push({
audit_index: auditIndex,
review_type: reviewType,
verdict: verdict,
score: audit.score,
critical_count: audit.critical_count,
total_issues: audit.issues.length,
timestamp: new Date().toISOString()
})
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))
const resultStatus = verdict
const resultSummary = `Score: ${audit.score.toFixed(1)}/10, Verdict: ${verdict}, ${audit.issues.length} issues (${audit.critical_count} critical)`
const resultDetails = `Report: ${auditFile}`
```
### Phase 5: Report to Coordinator
```javascript
const msgType = verdict === 'FIX_REQUIRED' ? 'fix_required' : verdict === 'PASSED' ? 'qa_passed' : 'qa_result'
mcp__ccw-tools__team_msg({
operation: "log",
team: teamName,
from: "qa",
to: "coordinator",
type: msgType,
summary: `[qa] QA ${verdict}: ${task.subject} (${audit.score.toFixed(1)}/10)`,
ref: auditFile
})
SendMessage({
type: "message",
recipient: "coordinator",
content: `## [qa] QA Results
**Task**: ${task.subject}
**Verdict**: ${verdict}
**Score**: ${audit.score.toFixed(1)} / 10
### Dimension Summary
${Object.entries(audit.dimensions).map(([name, dim]) =>
`- **${name}**: ${dim.score.toFixed(1)}/10 (${dim.issues.length} issues)`
).join('\n')}
### Critical Issues
${audit.issues.filter(i => i.severity === 'CRITICAL').map(i => `- ❌ ${i.message} (${i.file || i.check})`).join('\n') || 'None'}
### High Priority Issues
${audit.issues.filter(i => i.severity === 'HIGH').map(i => `- ⚠️ ${i.message} (${i.file || i.check})`).join('\n') || 'None'}
### Report
${resultDetails}`,
summary: `[qa] QA ${verdict} (${audit.score.toFixed(1)}/10)`
})
TaskUpdate({ taskId: task.id, status: 'completed' })
// Check for next task
const nextTasks = TaskList().filter(t =>
t.subject.startsWith('QA-') &&
t.owner === 'qa' &&
t.status === 'pending' &&
t.blockedBy.length === 0
)
if (nextTasks.length > 0) {
// Continue with next task → back to Phase 1
}
```
## Error Handling
| Scenario | Resolution |
|----------|------------|
| No QA-* tasks available | Idle, wait for coordinator |
| design-intelligence.json not found | Skip design compliance dimension, adjust weights |
| No files to review | Report empty review, notify coordinator |
| Session folder not found | Notify coordinator, request location |
| Critical issue beyond scope | SendMessage error to coordinator |

View File

@@ -0,0 +1,84 @@
{
"team_name": "frontend",
"skill_name": "team-frontend",
"team_display_name": "Frontend Development",
"description": "全栈前端开发团队,内置 ui-ux-pro-max 设计智能。具备需求分析、设计系统生成、前端实现、质量保证的完整能力。",
"pipeline_type": "adaptive",
"roles": [
{
"name": "coordinator",
"task_prefix": null,
"responsibility_type": "Orchestration",
"description": "需求澄清、行业识别、流水线编排、进度监控、GC循环控制",
"message_types": ["task_unblocked", "sync_checkpoint", "fix_required", "error", "shutdown"]
},
{
"name": "analyst",
"task_prefix": "ANALYZE",
"responsibility_type": "Read-only analysis",
"description": "需求分析、调用 ui-ux-pro-max 获取设计智能、行业推理规则匹配",
"message_types": ["analyze_ready", "analyze_progress", "error"]
},
{
"name": "architect",
"task_prefix": "ARCH",
"responsibility_type": "Code generation",
"description": "消费设计智能、定义设计令牌系统、组件架构、技术选型",
"message_types": ["arch_ready", "arch_revision", "arch_progress", "error"]
},
{
"name": "developer",
"task_prefix": "DEV",
"responsibility_type": "Code generation",
"description": "消费架构产出、实现前端组件/页面代码",
"message_types": ["dev_complete", "dev_progress", "error"]
},
{
"name": "qa",
"task_prefix": "QA",
"responsibility_type": "Read-only analysis",
"description": "5维度代码审查代码质量、可访问性、设计合规、UX最佳实践、Pre-Delivery验证",
"message_types": ["qa_passed", "qa_result", "fix_required", "error"]
}
],
"pipelines": {
"page": {
"description": "单页面开发:分析→架构→开发→质检",
"task_chain": ["ANALYZE-001", "ARCH-001", "DEV-001", "QA-001"],
"collaboration_patterns": ["CP-1", "CP-2"],
"complexity": "low"
},
"feature": {
"description": "多组件特性:分析→架构→质检→开发→质检",
"task_chain": ["ANALYZE-001", "ARCH-001", "QA-001", "DEV-001", "QA-002"],
"collaboration_patterns": ["CP-1", "CP-2", "CP-8"],
"complexity": "medium"
},
"system": {
"description": "完整前端系统:分析→架构→[开发令牌 ∥ 架构组件]→质检→开发组件→最终质检",
"task_chain": ["ANALYZE-001", "ARCH-001", "QA-001", "ARCH-002||DEV-001", "QA-002", "DEV-002", "QA-003"],
"sync_points": ["QA-001", "QA-002"],
"collaboration_patterns": ["CP-1", "CP-2", "CP-8", "CP-9"],
"complexity": "high"
}
},
"uipro_config": {
"search_paths": [
"G:/github_lib/ui-ux-pro-max-skill/src/ui-ux-pro-max",
"../ui-ux-pro-max-skill/src/ui-ux-pro-max",
"./ui-ux-pro-max"
],
"fallback": "LLM general design knowledge",
"data_domains": ["product", "style", "typography", "color", "landing", "chart", "ux", "web"],
"supported_stacks": ["html-tailwind", "react", "nextjs", "vue", "svelte", "shadcn"]
},
"shared_memory_schema": {
"design_intelligence": {},
"design_token_registry": {},
"component_inventory": [],
"style_decisions": [],
"qa_history": [],
"industry_context": {}
},
"generated_at": "2026-02-17T00:00:00+08:00"
}