sync: d8d-dev 增加 Pencil MCP 直接对比模式 + 旅程验证动态状态对比
- 新增 visual-diff-mode-pencil.md:Pencil MCP 直接从 .pen 文件导出设计截图对比 - 更新 visual-diff-mode.md:支持双模式选择(Pencil MCP / HTML 原型) - 更新 workflow.md:新增原型对比子模式表格 + --pencil/--html 参数支持 - 更新 journey-mode.md:视觉验证关卡增加原型/Pencil 动态状态对比验证 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -378,7 +378,111 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
|
||||
- 修复后重测:重新 browser_take_screenshot + analyze_image 确认问题已修复
|
||||
- 修复失败 → 标记 journey-step-fail → 继续下一步骤
|
||||
- 步骤 4(修复阶段)仅处理功能断言 FAIL,不处理视觉验证 FAIL
|
||||
f. 如涉及数据变化 → browser_evaluate 或 curl 验证数据(✅ 允许 curl 补充)
|
||||
|
||||
6. ⛔ **旅程步骤原型/Pencil 视觉对比验证**(⛔ 强制 — 针对操作时产生的动态状态)
|
||||
目的: 捕获并验证操作时才会出现的视觉状态(hover、选中、弹窗、展开、加载中、错误提示等),这些状态在静态原型对比中无法覆盖
|
||||
|
||||
触发条件(满足任一即执行):
|
||||
- 当前步骤操作后出现了弹窗/Modal/对话框
|
||||
- 下拉菜单/Select/日期选择器展开
|
||||
- 按钮/卡片/列表项处于 Hover/Active 状态
|
||||
- 表单字段获得 Focus/有验证错误提示
|
||||
- 页面显示 Loading/Skeleton/进度条
|
||||
- 列表项被选中/高亮/勾选
|
||||
- 页面切换/跳转后的首屏渲染完成
|
||||
- 出现了错误提示/Toast/Notification
|
||||
- 折叠面板展开/收起状态变化
|
||||
|
||||
执行流程:
|
||||
a. 等待状态稳定(动画/过渡完成):
|
||||
- browser_wait_for → time=1-2s(等待动画完成)
|
||||
|
||||
b. 捕获实际状态截图:
|
||||
- browser_take_screenshot → 保存为 journey-epic{N}-{M}-step{S}-state.png
|
||||
|
||||
c. 搜索匹配的设计帧(双模式支持):
|
||||
**Pencil MCP 模式(优先)**:
|
||||
- 读取 pipeline-context.md 获取设计文件路径(如 VividSpark1.2.pen)
|
||||
- mcp__pencil__batch_get → 搜索与当前状态匹配的帧
|
||||
- 搜索关键词: "{Page}-{State}" 如 "Dashboard-Modal", "Login-Error", "Upload-Loading"
|
||||
- 或按 frame 类型和名称模式匹配
|
||||
- 如找到匹配帧 → mcp__pencil__export_nodes 导出设计截图
|
||||
|
||||
**HTML 原型模式(回退)**:
|
||||
- 检查 prototype/pages/{group}/{page}-{state}.html 是否存在
|
||||
- 如存在 → 启动原型服务 → Playwright 截图
|
||||
|
||||
设计帧未找到处理:
|
||||
- 标记 prototype_found: false
|
||||
- 记录 actual_screenshot 路径
|
||||
- 不阻断旅程,但记录到 pipeline-report.md 建议补充设计帧
|
||||
|
||||
d. 执行视觉对比(如找到设计帧):
|
||||
- ui_diff_check:
|
||||
- expected_image_source: 设计帧截图(或原型截图)
|
||||
- actual_image_source: 当前状态截图 (journey-epic{N}-{M}-step{S}-state.png)
|
||||
- prompt: "对比设计原型和实际实现。这是用户操作后出现的动态交互状态(如弹窗、hover、选中、加载中、错误提示等)。
|
||||
|
||||
重点关注:
|
||||
1) 组件布局和结构是否一致(弹窗位置、按钮排列等)
|
||||
2) 颜色/样式是否匹配(背景色、边框、阴影等)
|
||||
3) 文字内容是否正确(标题、提示信息、按钮文字等)
|
||||
4) 交互状态是否准确(hover 效果、选中状态、focus 样式等)
|
||||
5) 图标和装饰元素是否一致
|
||||
|
||||
注意:忽略动态数据(如用户名、时间戳等),只关注 UI 结构和样式。
|
||||
|
||||
按严重程度列出所有视觉差异:"
|
||||
|
||||
e. 差异分级与处理:
|
||||
记录到 pipeline-state.yaml:
|
||||
```yaml
|
||||
journey_state_visual_diff:
|
||||
epic_6:
|
||||
journey_1:
|
||||
step_3:
|
||||
state_type: "modal_open" # 状态类型: modal_open/hover/select_focus/loading/error/etc
|
||||
prototype_found: true # 是否找到对应设计帧
|
||||
prototype_source: "VividSpark1.2.pen:frame-456" # 设计来源
|
||||
prototype_frame_id: "frame-456"
|
||||
diff_check_executed: true
|
||||
severity: "moderate" # critical/moderate/minor/none
|
||||
differences:
|
||||
- type: "color"
|
||||
severity: "minor"
|
||||
description: "弹窗背景色不一致:设计 #1A1A1A,实际 #222222"
|
||||
location: "弹窗背景"
|
||||
- type: "spacing"
|
||||
severity: "moderate"
|
||||
description: "按钮间距偏差 8px,设计 16px,实际 24px"
|
||||
location: "底部按钮组"
|
||||
- type: "text"
|
||||
severity: "critical"
|
||||
description: "按钮文字错误:设计'确认',实际'提交'"
|
||||
location: "主按钮"
|
||||
screenshot_expected: "tests/e2e/screenshots/journey-epic6-1-step3-design.png" # 设计帧截图
|
||||
screenshot_actual: "tests/e2e/screenshots/journey-epic6-1-step3-state.png" # 实际状态截图
|
||||
auto_fix_triggered: true # 是否触发自动修复
|
||||
auto_fix_type: "AUTO-FIX" # 修复类型
|
||||
auto_fix_result: "PASS" # 修复结果
|
||||
```
|
||||
|
||||
差异处理规则:
|
||||
- 🔴 严重差异(布局错误、关键组件缺失、文字错误)→ 立即触发 AUTO-FIX
|
||||
- 🟡 中等差异(颜色、间距偏差)→ 记录到 pipeline-report.md,建议修复
|
||||
- 🟢 轻微差异(微小像素偏移)→ 记录但不阻断旅程
|
||||
- ✅ 无差异 → 标记状态正常
|
||||
|
||||
f. 自动修复与重测(如触发):
|
||||
- AUTO-FIX 触发后:
|
||||
1. 定位相关源码文件(根据差异类型确定)
|
||||
2. 执行修复(如调整 CSS、修改组件样式等)
|
||||
3. 重新截图: browser_take_screenshot
|
||||
4. 重新对比: ui_diff_check
|
||||
5. 修复成功 → 标记 auto_fix_result: "PASS"
|
||||
6. 修复失败 → 标记 auto_fix_result: "FAIL",记录原因
|
||||
|
||||
6. ⛔ **源码 SVG data URI 扫描**(视觉验证关卡内 — 每次 snapshot 后强制执行):
|
||||
g. ⛔ **约束一致性检查**(每个用户步骤首次执行时 — R7 执行时强制检测):
|
||||
触发条件(操作被拦截 + 声明方说"可选"):
|
||||
- 操作后 Toast 出现且含"请上传/请填写/请选择/不能为空/不能为空"
|
||||
|
||||
234
.claude/skills/d8d-dev/visual-diff-mode-pencil.md
Normal file
234
.claude/skills/d8d-dev/visual-diff-mode-pencil.md
Normal file
@@ -0,0 +1,234 @@
|
||||
# 原型对比验证模式 - Pencil MCP 直接对比版
|
||||
|
||||
> **定位**:使用 Pencil MCP 工具直接从 `.pen` 设计文件提取截图,与实际页面实现做逐页视觉对比。
|
||||
>
|
||||
> **与 HTML 原型版对比**:
|
||||
> | 维度 | Pencil MCP 直接版 | HTML 原型版 |
|
||||
> |------|------------------|-------------|
|
||||
> | 来源 | `.pen` 设计源文件 | `prototype/pages/*.html` |
|
||||
> | 保真度 | 100% 设计稿像素级 | 可能有 HTML/CSS 转换损耗 |
|
||||
> | 依赖 | Pencil MCP Server | Node.js + Express |
|
||||
> | 启动 | 无需额外服务 | 需启动 `prototype/server.js` |
|
||||
|
||||
---
|
||||
|
||||
## 前置条件
|
||||
|
||||
```
|
||||
检查清单(任一不满足 → 报错并终止):
|
||||
├── .pen 设计文件存在(如 VividSpark1.2.pen)
|
||||
├── Pencil MCP Server 可用(`pencil` 工具集)
|
||||
├── pipeline-context.md 存在(含实际应用 URL 和凭据)
|
||||
├── pm2 服务运行中(实际应用可访问)
|
||||
└── 至少有一个 Epic 的 Story 已 verified
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心流程
|
||||
|
||||
```
|
||||
Phase PVD-0: 准备
|
||||
├── 读取 .pen 文件 → 使用 Pencil MCP 发现设计页面
|
||||
├── 读取 pipeline-context.md → 获取实际应用 URL
|
||||
├── 构建页面映射表(设计帧 ↔ 实际路由)
|
||||
└── 创建截图输出目录
|
||||
|
||||
Phase PVD-1: 逐页对比循环
|
||||
对每个映射页面:
|
||||
├── A. Pencil MCP 导出设计帧截图
|
||||
├── B. Playwright 截取实际页面
|
||||
├── C. UI 差异对比(ui_diff_check)
|
||||
└── D. 差异分级 + 记录
|
||||
|
||||
Phase PVD-2: 汇总报告
|
||||
├── 生成 visual-diff-pencil-report.md
|
||||
└── 输出差异统计和修复建议
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase PVD-0: 准备
|
||||
|
||||
### 0.1 使用 Pencil MCP 发现设计页面
|
||||
|
||||
```
|
||||
工具: mcp__pencil__batch_get
|
||||
参数:
|
||||
- filePath: "VividSpark1.2.pen"
|
||||
- patterns: [{"type": "frame"}] # 查找所有帧/页面
|
||||
- searchDepth: 2
|
||||
```
|
||||
|
||||
从返回结果中提取所有设计帧:
|
||||
- 帧名称(如 "Login", "Dashboard")
|
||||
- 帧 ID(如 "node-123", "frame-456")
|
||||
- 帧尺寸(width, height)
|
||||
|
||||
分类为 frontend 和 admin 组:
|
||||
- 帧名称含 "admin"、"Admin" → admin 组
|
||||
- 其他 → frontend 组
|
||||
|
||||
### 0.2 读取实际应用信息
|
||||
|
||||
同 HTML 原型版,读取 `_bmad-output/implementation-artifacts/pipeline-context.md` 获取:
|
||||
- 实际应用 URL(API_URL, ADMIN_URL)
|
||||
- 认证凭据
|
||||
- 已实现的路由
|
||||
|
||||
### 0.3 构建页面映射表
|
||||
|
||||
**自动映射规则**:
|
||||
|
||||
```
|
||||
对每个设计帧(从 Pencil MCP 获取):
|
||||
1. 提取帧名称(如 "Login", "Dashboard")
|
||||
2. 在实际路由中查找匹配:
|
||||
- 帧名=Login → /login 或 /admin/login
|
||||
- 帧名=Dashboard → / 或 /dashboard
|
||||
- 帧名=Register → /register
|
||||
- 其他 → /{帧名小写} 或 /admin/{帧名小写}
|
||||
3. 验证实际路由可访问(curl 检查非 404)
|
||||
4. 不可访问的页面标记为 skipped
|
||||
```
|
||||
|
||||
**映射输出格式**(记录到 pipeline-state.yaml):
|
||||
|
||||
```yaml
|
||||
visual_diff_pencil_mapping:
|
||||
- design_frame: "Login"
|
||||
design_frame_id: "node-123"
|
||||
actual_route: "/login"
|
||||
group: "frontend"
|
||||
status: "active" # active / skipped / error
|
||||
|
||||
- design_frame: "Dashboard"
|
||||
design_frame_id: "node-456"
|
||||
actual_route: "/"
|
||||
group: "frontend"
|
||||
status: "active"
|
||||
```
|
||||
|
||||
### 0.4 创建截图输出目录
|
||||
|
||||
```bash
|
||||
mkdir -p tests/e2e/screenshots/visual-diff-pencil
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase PVD-1: 逐页对比循环
|
||||
|
||||
对映射表中每个 `status: active` 的页面执行以下流程。
|
||||
|
||||
### 1.A Pencil MCP 导出设计帧截图
|
||||
|
||||
```
|
||||
工具: mcp__pencil__export_nodes
|
||||
参数:
|
||||
- filePath: "VividSpark1.2.pen"
|
||||
- nodeIds: ["{design_frame_id}"] # 从映射表获取
|
||||
- outputDir: "tests/e2e/screenshots/visual-diff-pencil"
|
||||
- format: "png"
|
||||
- scale: 2 # 2x 高清
|
||||
```
|
||||
|
||||
导出后的文件路径:
|
||||
- `tests/e2e/screenshots/visual-diff-pencil/{design_frame_id}.png`
|
||||
|
||||
重命名为可读名称:
|
||||
- `tests/e2e/screenshots/visual-diff-pencil/{name}-design.png`
|
||||
|
||||
### 1.B 截取实际页面截图
|
||||
|
||||
同 HTML 原型版,使用 Playwright:
|
||||
|
||||
```
|
||||
1. browser_navigate → {实际 URL}{route}
|
||||
2. browser_resize → 1440x900(与设计帧尺寸匹配)
|
||||
3. 处理认证(如需要)
|
||||
4. browser_wait_for → time=3
|
||||
5. browser_take_screenshot(fullPage=false)
|
||||
→ tests/e2e/screenshots/visual-diff-pencil/{name}-actual.png
|
||||
```
|
||||
|
||||
### 1.C UI 差异对比
|
||||
|
||||
```
|
||||
工具: ui_diff_check
|
||||
参数:
|
||||
- expected_image_source: "tests/e2e/screenshots/visual-diff-pencil/{name}-design.png"
|
||||
- actual_image_source: "tests/e2e/screenshots/visual-diff-pencil/{name}-actual.png"
|
||||
- prompt: "对比这两张截图:第一张是 Pencil 设计稿,第二张是实际实现。列出所有视觉差异,包括布局结构、组件排列、颜色、间距、字体、图标等。按严重程度排序。"
|
||||
```
|
||||
|
||||
### 1.D 差异分级
|
||||
|
||||
同 HTML 原型版:
|
||||
|
||||
| 级别 | 标准 | 示例 |
|
||||
|------|------|------|
|
||||
| 🔴 严重 | 布局结构不同、关键组件缺失 | 原型有两列布局实际一列 |
|
||||
| 🟡 中等 | 颜色/间距偏差、图标不一致 | 卡片圆角不一致 |
|
||||
| 🟢 轻微 | 微小像素差异 | 1-2px 偏移 |
|
||||
|
||||
---
|
||||
|
||||
## Phase PVD-2: 汇总报告
|
||||
|
||||
### 2.1 生成报告
|
||||
|
||||
生成 `tests/e2e/screenshots/visual-diff-pencil/visual-diff-pencil-report.md`:
|
||||
|
||||
```markdown
|
||||
# Visual Diff Report (Pencil MCP Direct)
|
||||
|
||||
生成时间: {timestamp}
|
||||
对比页面数: {total_pages}
|
||||
数据来源: VividSpark1.2.pen (Pencil MCP 直接导出)
|
||||
|
||||
## Summary
|
||||
|
||||
| 级别 | 数量 |
|
||||
|------|------|
|
||||
| 🔴 严重 | {critical_count} |
|
||||
| 🟡 中等 | {moderate_count} |
|
||||
| 🟢 轻微 | {minor_count} |
|
||||
| ✅ 匹配 | {match_count} |
|
||||
|
||||
## 详细对比结果
|
||||
|
||||
### 🔴 {page_name}
|
||||
- 设计截图: `visual-diff-pencil/{name}-design.png`
|
||||
- 实际截图: `visual-diff-pencil/{name}-actual.png`
|
||||
- 差异描述...
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
### 2.2 更新 pipeline-state.yaml
|
||||
|
||||
```yaml
|
||||
visual_diff_pencil:
|
||||
status: completed
|
||||
total_pages: 11
|
||||
compared_pages: 11
|
||||
critical_count: 0
|
||||
moderate_count: 3
|
||||
minor_count: 5
|
||||
match_count: 3
|
||||
report_path: "tests/e2e/screenshots/visual-diff-pencil/visual-diff-pencil-report.md"
|
||||
timestamp: "2026-04-08T12:00:00Z"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录:与 HTML 原型版对比速查
|
||||
|
||||
| 步骤 | Pencil MCP 直接版 | HTML 原型版 |
|
||||
|------|------------------|-------------|
|
||||
| 原型来源 | `.pen` 文件 | `prototype/pages/*.html` |
|
||||
| 截图工具 | `mcp__pencil__export_nodes` | Playwright 访问 `localhost:8080` |
|
||||
| 保真度 | 100% 设计稿 | 可能有转换损耗 |
|
||||
| 启动依赖 | 无 | 需启动 `prototype/server.js` |
|
||||
| 推荐场景 | 有 `.pen` 文件时首选 | 无 `.pen` 或需 HTML 交互时 |
|
||||
@@ -1,6 +1,14 @@
|
||||
# 原型对比验证模式(Visual Diff Mode)
|
||||
|
||||
> **定位**:在回归验证和旅程验证之后,将实际页面实现与原型 HTML 页面做逐页视觉对比,发现布局偏差、组件遗漏、交互方式差异等视觉问题。
|
||||
> **定位**:在回归验证和旅程验证之后,将实际页面实现与原型做逐页视觉对比,发现布局偏差、组件遗漏、交互方式差异等视觉问题。
|
||||
>
|
||||
> **两种对比方式**(任选其一):
|
||||
> | 方式 | 来源 | 适用场景 |
|
||||
> |------|------|---------|
|
||||
> | **Pencil MCP 直接版**(推荐) | `.pen` 设计源文件 | 有 `.pen` 文件时首选,100% 设计稿保真度 |
|
||||
> | **HTML 原型版** | `prototype/pages/*.html` | 无 `.pen` 文件或需要 HTML 交互时 |
|
||||
>
|
||||
> Pencil MCP 直接版文档:**[visual-diff-mode-pencil.md](./visual-diff-mode-pencil.md)**
|
||||
>
|
||||
> **与其他模式的关系**:
|
||||
> - 回归验证模式 → 检查功能点存在且正确(类比单元测试)
|
||||
|
||||
@@ -87,7 +87,14 @@
|
||||
| **单 Epic 模式** | 执行指定 Epic 的所有 Story | 按模块开发 |
|
||||
| **回归验证模式** | 不做实现,逐 Story 验证功能点存在且正确 | 代码已实现需回归验证(类比:单元测试) |
|
||||
| **旅程验证模式** | 专用用户旅程定义+验证(跨页面完整流程) | 跨 Story/Epic 的用户体验验证(类比:E2E 测试) |
|
||||
| **原型对比验证模式** | 截取原型和实际页面截图,使用 ui_diff_check + analyze_image 对比差异 | Epic 完成后的视觉还原度检查(类比:视觉回归测试) |
|
||||
| **原型对比验证模式** | 截取原型和实际页面截图,使用 ui_diff_check 对比差异 | Epic 完成后的视觉还原度检查(类比:视觉回归测试) |
|
||||
|
||||
### 原型对比验证子模式
|
||||
|
||||
| 子模式 | 原型来源 | 推荐场景 |
|
||||
|--------|---------|---------|
|
||||
| **Pencil MCP 直接版**(优先) | `.pen` 设计文件(如 VividSpark1.2.pen) | 有 .pen 文件时首选,100% 设计稿保真度 |
|
||||
| **HTML 原型版** | `prototype/pages/*.html` | 无 .pen 文件或需要 HTML 交互时 |
|
||||
|
||||
## 模式选择与流转
|
||||
|
||||
@@ -183,9 +190,18 @@ Read fully and follow: ./journey-mode.md
|
||||
### 原型对比验证模式
|
||||
|
||||
```
|
||||
Read fully and follow: ./visual-diff-mode.md
|
||||
自动检测并选择:
|
||||
├── 存在 .pen 设计文件(如 VividSpark1.2.pen)
|
||||
│ └── Read fully and follow: ./visual-diff-mode-pencil.md # Pencil MCP 直接版
|
||||
│
|
||||
└── 不存在 .pen 文件,但存在 prototype/pages/*.html
|
||||
└── Read fully and follow: ./visual-diff-mode.md # HTML 原型版
|
||||
```
|
||||
|
||||
**手动指定子模式**:
|
||||
- `/d8d-dev visual-diff --pencil` → 强制使用 Pencil MCP 直接版
|
||||
- `/d8d-dev visual-diff --html` → 强制使用 HTML 原型版
|
||||
|
||||
### 仅测试模式 / 仅审查模式
|
||||
|
||||
直接读取对应 Story 的 phase-04-test.md 或 phase-05-review.md 中的相关部分。
|
||||
|
||||
Reference in New Issue
Block a user