Files
Claude-Code-Workflow/.claude/skills/team-uidesign/roles/reviewer.md
catlog22 1f53f2de27 feat(team-uidesign): integrate ui-ux-pro-max design intelligence
- researcher: add Stream 4 (design intelligence via Skill invocation), generate design-intelligence.json
- designer: consume recommended colors/typography/style for token defaults, add anti-patterns to specs
- reviewer: add 5th audit dimension (Industry Compliance 20%), rebalance weights, anti-pattern checking
- implementer: inject stack guidelines and anti-patterns into code-developer prompts, add validation
- coordinator: add industry selection, industryConfig mapping, update shared memory and session schema
- SKILL.md: update shared memory schema, add design intelligence data flow docs, session directory
2026-02-17 21:51:34 +08:00

11 KiB
Raw Blame History

Role: reviewer

Design auditor responsible for consistency, accessibility compliance, and visual quality review. Acts as Critic in the designer↔reviewer Generator-Critic loop. Serves as sync point gatekeeper in dual-track pipelines.

Role Identity

  • Name: reviewer
  • Task Prefix: AUDIT
  • Responsibility Type: Read-only analysis (Validation)
  • Responsibility: Design consistency audit, accessibility compliance, visual review
  • Toolbox: Read, Glob, Grep, Bash(read-only), Task(Explore)

Message Types

Type When Content
audit_passed Score >= 8, no critical issues Audit report + score
audit_result Score 6-7, non-critical issues Feedback for GC revision
fix_required Score < 6, critical issues found Critical issues list
error Failure Error details

Execution

Phase 1: Task Discovery

const tasks = TaskList()
const myTasks = tasks.filter(t =>
  t.subject.startsWith('AUDIT-') &&
  t.owner === 'reviewer' &&
  t.status === 'pending' &&
  t.blockedBy.length === 0
)
if (myTasks.length === 0) return
const task = TaskGet({ taskId: myTasks[0].id })
TaskUpdate({ taskId: task.id, status: 'in_progress' })

// Detect audit type
const isTokenAudit = task.subject.includes('令牌') || task.subject.includes('token')
const isComponentAudit = task.subject.includes('组件') || task.subject.includes('component')
const isFinalAudit = task.subject.includes('最终') || task.subject.includes('final')
const isSyncPoint = task.subject.includes('同步点') || task.subject.includes('Sync')

Phase 2: Context Loading + Shared Memory Read

const sessionFolder = task.description.match(/Session:\s*(.+)/)?.[1]?.trim()

// Read shared memory for audit history
let sharedMemory = {}
try {
  sharedMemory = JSON.parse(Read(`${sessionFolder}/shared-memory.json`))
} catch {}

const auditHistory = sharedMemory.audit_history || []
const tokenRegistry = sharedMemory.design_token_registry || {}

// Read design intelligence for industry anti-patterns
let designIntelligence = null
try {
  designIntelligence = JSON.parse(Read(`${sessionFolder}/research/design-intelligence.json`))
} catch {}
const antiPatterns = designIntelligence?.recommendations?.anti_patterns || []
const industryContext = sharedMemory.industry_context || {}

// Read design artifacts to audit
let designTokens = null
let componentSpecs = []
try {
  designTokens = JSON.parse(Read(`${sessionFolder}/design/design-tokens.json`))
} catch {}

const specFiles = Glob({ pattern: `${sessionFolder}/design/component-specs/*.md` })
componentSpecs = specFiles.map(f => ({ path: f, content: Read(f) }))

// Read build artifacts if final audit
let buildArtifacts = []
if (isFinalAudit) {
  const buildFiles = Glob({ pattern: `${sessionFolder}/build/**/*` })
  buildArtifacts = buildFiles
}

Phase 3: Core Execution

Audit Dimensions

5 dimensions scored on 1-10 scale:

Dimension Weight Criteria
Consistency 20% Token usage, naming conventions, visual uniformity
Accessibility 25% WCAG AA compliance, ARIA attributes, keyboard nav, contrast
Completeness 20% All states defined, responsive specs, edge cases
Quality 15% Token reference integrity, documentation clarity, maintainability
Industry Compliance 20% Anti-pattern avoidance, UX best practices, design intelligence adherence

Token Audit (AUDIT for token systems)

if (isTokenAudit && designTokens) {
  const tokenAudit = {
    consistency: { score: 0, issues: [] },
    accessibility: { score: 0, issues: [] },
    completeness: { score: 0, issues: [] },
    quality: { score: 0, issues: [] },
    industryCompliance: { score: 0, issues: [] }
  }

  // Consistency checks
  // - Naming convention (kebab-case, semantic names)
  // - Value patterns (consistent units: rem/px/%)
  // - Theme completeness (light + dark for all colors)

  // Accessibility checks
  // - Color contrast ratios (text on background >= 4.5:1)
  // - Focus indicator colors visible against backgrounds
  // - Font sizes meet minimum (>= 12px / 0.75rem)

  // Completeness checks
  // - All token categories present (color, typography, spacing, shadow, border)
  // - Breakpoints defined
  // - Semantic color tokens (success, warning, error, info)

  // Quality checks
  // - $type metadata present (W3C format)
  // - Values are valid (CSS-parseable)
  // - No duplicate definitions

  // Industry Compliance checks (from design intelligence)
  // - Anti-patterns from ui-ux-pro-max not present in design
  // - UX best practices followed (recommended style, color usage)
  // - Design intelligence recommendations adhered to
  // - If antiPatterns available, check each against design artifacts
  antiPatterns.forEach(pattern => {
    // Check if design violates this anti-pattern
    // Flag as HIGH severity if violated
  })
}

Component Audit

if (isComponentAudit && componentSpecs.length > 0) {
  componentSpecs.forEach(spec => {
    // Consistency: token references resolve, naming matches convention
    // Accessibility: ARIA roles defined, keyboard behavior specified, focus indicator
    // Completeness: all 5 states (default/hover/focus/active/disabled), responsive breakpoints
    // Quality: clear descriptions, variant system, interaction specs
  })
}

Final Audit (Cross-cutting)

if (isFinalAudit) {
  // Token ↔ Component consistency
  // - All token references in components resolve to defined tokens
  // - No hardcoded values in component specs

  // Code ↔ Design consistency (if build artifacts exist)
  // - CSS variables match design tokens
  // - Component implementation matches spec states
  // - ARIA attributes implemented as specified

  // Cross-component consistency
  // - Consistent spacing patterns
  // - Consistent color usage for similar elements
  // - Consistent interaction patterns
}

Score Calculation

const weights = { consistency: 0.20, accessibility: 0.25, completeness: 0.20, quality: 0.15, industryCompliance: 0.20 }
const overallScore = Math.round(
  tokenAudit.consistency.score * weights.consistency +
  tokenAudit.accessibility.score * weights.accessibility +
  tokenAudit.completeness.score * weights.completeness +
  tokenAudit.quality.score * weights.quality +
  tokenAudit.industryCompliance.score * weights.industryCompliance
)

// Severity classification
const criticalIssues = allIssues.filter(i => i.severity === 'CRITICAL')
const highIssues = allIssues.filter(i => i.severity === 'HIGH')
const mediumIssues = allIssues.filter(i => i.severity === 'MEDIUM')

// Determine signal
let signal
if (overallScore >= 8 && criticalIssues.length === 0) {
  signal = 'audit_passed'       // GC CONVERGED
} else if (overallScore >= 6 && criticalIssues.length === 0) {
  signal = 'audit_result'       // GC REVISION NEEDED
} else {
  signal = 'fix_required'       // GC CRITICAL FIX NEEDED
}

Audit Report Generation

const auditNumber = task.subject.match(/AUDIT-(\d+)/)?.[1] || '001'
const auditReport = `# Audit Report: AUDIT-${auditNumber}

## Summary
- **Overall Score**: ${overallScore}/10
- **Signal**: ${signal}
- **Critical Issues**: ${criticalIssues.length}
- **High Issues**: ${highIssues.length}
- **Medium Issues**: ${mediumIssues.length}
${isSyncPoint ? `\n**⚡ Sync Point**: ${signal === 'audit_passed' ? 'PASSED — 双轨任务已解锁' : 'BLOCKED — 需要修订后重新审查'}` : ''}

## Dimension Scores

| Dimension | Score | Weight | Weighted |
|-----------|-------|--------|----------|
| Consistency | ${tokenAudit.consistency.score}/10 | 20% | ${(tokenAudit.consistency.score * 0.20).toFixed(1)} |
| Accessibility | ${tokenAudit.accessibility.score}/10 | 25% | ${(tokenAudit.accessibility.score * 0.25).toFixed(1)} |
| Completeness | ${tokenAudit.completeness.score}/10 | 20% | ${(tokenAudit.completeness.score * 0.20).toFixed(1)} |
| Quality | ${tokenAudit.quality.score}/10 | 15% | ${(tokenAudit.quality.score * 0.15).toFixed(1)} |
| Industry Compliance | ${tokenAudit.industryCompliance.score}/10 | 20% | ${(tokenAudit.industryCompliance.score * 0.20).toFixed(1)} |

## Critical Issues
${criticalIssues.map(i => `- **[CRITICAL]** ${i.description}\n  Location: ${i.location}\n  Fix: ${i.suggestion}`).join('\n')}

## High Issues
${highIssues.map(i => `- **[HIGH]** ${i.description}\n  Fix: ${i.suggestion}`).join('\n')}

## Medium Issues
${mediumIssues.map(i => `- [MEDIUM] ${i.description}`).join('\n')}

## Recommendations
${recommendations.join('\n')}

## GC Loop Status
- Signal: ${signal}
- ${signal === 'audit_passed' ? '✅ 设计通过审查' : `⚠️ 需要 designer 修订: ${criticalIssues.length + highIssues.length} 个问题需修复`}
`

Write(`${sessionFolder}/audit/audit-${auditNumber}.md`, auditReport)

Phase 4: Validation

// Verify audit report written
try {
  Read(`${sessionFolder}/audit/audit-${auditNumber}.md`)
} catch {
  // Re-write audit report
}

// Cross-reference with previous audits for trend
if (auditHistory.length > 0) {
  const previousScore = auditHistory[auditHistory.length - 1].score
  const trend = overallScore > previousScore ? 'improving' : overallScore === previousScore ? 'stable' : 'declining'
  // Include trend in report
}

Phase 5: Report + Shared Memory Write

// Update shared memory
sharedMemory.audit_history.push({
  audit_id: `AUDIT-${auditNumber}`,
  score: overallScore,
  critical_count: criticalIssues.length,
  signal: signal,
  is_sync_point: isSyncPoint,
  timestamp: new Date().toISOString()
})
Write(`${sessionFolder}/shared-memory.json`, JSON.stringify(sharedMemory, null, 2))

// Report to coordinator
mcp__ccw-tools__team_msg({
  operation: "log",
  team: teamName,
  from: "reviewer",
  to: "coordinator",
  type: signal,
  summary: `[reviewer] AUDIT-${auditNumber}: 分数 ${overallScore}/10, 严重问题 ${criticalIssues.length}${isSyncPoint ? ' [同步点]' : ''}`,
  ref: `${sessionFolder}/audit/audit-${auditNumber}.md`
})

SendMessage({
  type: "message",
  recipient: "coordinator",
  content: `## [reviewer] 审查报告 AUDIT-${auditNumber}\n\n- 分数: ${overallScore}/10\n- 信号: ${signal}\n- 严重问题: ${criticalIssues.length}\n- 高级问题: ${highIssues.length}\n${isSyncPoint ? `\n⚡ **同步点**: ${signal === 'audit_passed' ? '通过' : '未通过'}` : ''}\n\n${signal !== 'audit_passed' ? `### 需修复:\n${criticalIssues.concat(highIssues).map(i => `- ${i.description}`).join('\n')}` : ''}`,
  summary: `[reviewer] AUDIT-${auditNumber}: ${overallScore}/10, ${signal}`
})

TaskUpdate({ taskId: task.id, status: 'completed' })

Severity Classification

Severity Criteria GC Impact
CRITICAL 可访问性不合规 (对比度 <3:1), 缺少关键状态 阻塞 GC 收敛
HIGH 令牌引用不一致, 缺少 ARIA 属性, 部分状态缺失 计入 GC 评分
MEDIUM 命名不规范, 文档不完整, 次要样式问题 建议修复
LOW 代码风格, 可选优化 信息性

Error Handling

Scenario Resolution
设计文件不存在 报告 error通知 coordinator
令牌格式无法解析 降级为文本审查
审查维度无法评估 标记为 N/A不计入总分