Merge pull request 'sync: 合并上游增量更新 - 添加核对清单、增量同步选择、格式修正' (#47) from sync/d8d-skills-20260416-075956 into master

Reviewed-on: http://gitea.d8d.fun/d8dfun/bmad-method-template/pulls/47
This commit is contained in:
2026-04-16 08:13:58 +00:00
6 changed files with 89 additions and 49 deletions

View File

@@ -517,10 +517,10 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
- 修复失败 → 标记 journey-step-fail → 继续下一步骤
- 步骤 4修复阶段仅处理功能断言 FAIL不处理视觉验证 FAIL
f. 如涉及数据变化 → browser_evaluate 或 curl 验证数据(✅ 允许 curl 补充)
6. ⛔ **旅程步骤原型/Pencil 视觉对比验证**(⛔ 强制 — 针对操作时产生的动态状态)
6. ⛔ **旅程步骤原型/Pencil 视觉对比验证**(⛔ 强制 — 针对操作时产生的动态状态):
目的: 捕获并验证操作时才会出现的视觉状态hover、选中、弹窗、展开、加载中、错误提示等这些状态在静态原型对比中无法覆盖
触发条件(满足任一即执行):
- 当前步骤操作后出现了弹窗/Modal/对话框
- 下拉菜单/Select/日期选择器展开
@@ -531,14 +531,14 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
- 页面切换/跳转后的首屏渲染完成
- 出现了错误提示/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
@@ -546,33 +546,33 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
- 搜索关键词: "{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
@@ -605,13 +605,13 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
auto_fix_type: "AUTO-FIX" # 修复类型
auto_fix_result: "PASS" # 修复结果
```
差异处理规则:
- 🔴 严重差异(布局错误、关键组件缺失、文字错误)→ 立即触发 AUTO-FIX
- 🟡 中等差异(颜色、间距偏差)→ 记录到 pipeline-report.md建议修复
- 🟢 轻微差异(微小像素偏移)→ 记录但不阻断旅程
- ✅ 无差异 → 标记状态正常
f. 自动修复与重测(如触发):
- AUTO-FIX 触发后:
1. 定位相关源码文件(根据差异类型确定)
@@ -620,13 +620,13 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
4. 重新对比: ui_diff_check
5. 修复成功 → 标记 auto_fix_result: "PASS"
6. 修复失败 → 标记 auto_fix_result: "FAIL",记录原因
6. ⛔ **源码 SVG data URI 扫描**(视觉验证关卡内 — 每次 snapshot 后强制执行):
g. ⛔ **约束一致性检查**(每个用户步骤首次执行时 — R7 执行时强制检测):
触发条件(操作被拦截 + 声明方说"可选":
- 操作后 Toast 出现且含"请上传/请填写/请选择/不能为空/不能为空"
- 且满足以下任一:
a. 旅程定义中该步骤描述含"可跳过/可选/选填/optional/skip/跳过/使用占位图"
a. 旅程定义中该步骤描述含"可跳过/可选/选填/optional/skip/跳过"
b. browser_snapshot 页面文本含"(选填)/(可选)"标记
满足 → Constraint Mismatch (FAIL #16):
- ❌ 不得静默补填继续
@@ -684,7 +684,7 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
| 6⃣ | 流水线状态 | `_bmad-output/implementation-artifacts/pipeline-state.yaml`、`_bmad-output/implementation-artifacts/pipeline-report.md` | `ci(pipeline): update journey verification status` |
- 提交前 `git diff --stat` 确认变更范围
- 排除 `.env`、`node_modules/`、`.next/`、`dist/`
- 排除 `.env`、`node_modules/`、`.next/`、`dist`
- 所有分类提交完成后: `git push origin main`
- 推送失败 → 记录到 error_log不中断
```

View File

@@ -59,10 +59,9 @@ Phase PVD-1: 逐页对比循环
├── C. 结构校验(.pen节点树+ AI 视觉对比
├── D. 差异分级 + 强制执行计数
└── E. PAGE GATE-CHECK 门禁检查
Phase PVD-2: 汇总报告
├── 生成 visual-diff-pencil-report.md
└── 输出差异统计和修复建议
├── 🟢 通过 → G. 记录 → NEXT PAGE
└── 🔴/🟡 未通过 → F. AUTO-FIX → 重截 → 重比 → 重新 GATE-CHECK
G. 记录结果到 pipeline-state.yaml
```
---
@@ -204,8 +203,8 @@ PVD-1 PER-PAGE LOOP:
C. 结构校验 + AI 视觉对比
D. 差异分级
E. PAGE GATE-CHECK ⛔
├── 🟢 通过 → G. 记录 → NEXT PAGE
└── 🔴/🟡 未通过 → F. AUTO-FIX → 重截 → 重比 → 重新 GATE-CHECK
├── 🟢 通过 → G. 记录 → NEXT PAGE
└── 🔴/🟡 未通过 → F. AUTO-FIX → 重截 → 重比 → 重新 GATE-CHECK
G. 记录结果到 pipeline-state.yaml
```
@@ -299,31 +298,27 @@ PVD-1 PER-PAGE LOOP:
结果包含所有层级topBar, topBar.topLeft, topBar.topRight, tabSection, tabSection.tabLeft, barCard1, barCard1.ratingBadge, barCard1.activitySnippet 等等(深度嵌套没问题,全部提取)。
示例: topBar.topLeft / tabSection.tabLeft / availableCard / amountInput / ...
3. **检查全局配置关联**: 如果设计帧包含 name=bottomNav/BottomNav 且是 ref 组件
- 读取 app/mini-program/src/pages.json → 获取当前 tabBar 配置
- 对比设计中 bottomNav.children.length vs 实际 tabBar.list.length
- 对比每个 item 文字描述是否匹配(如果可匹配)
- 数量不匹配 → critical_count += 1底部导航结构错误是严重差异
- 读取 app/mini-program/src/pages.json → 获取当前 tabBar 配置
- 对比设计中 bottomNav.children.length vs 实际 tabBar.list.length
- 对比每个 item 文字描述是否匹配(如果可匹配)
- 数量不匹配 → critical_count += 1底部导航结构错误是严重差异
4. 读取实际页面源码app/mini-program/src/pages/{page}/index.vue双向检查每个必需组件:
- **必需组件检查**: 按路径节点整个区块缺失 → 直接判定为 🔴 严重差异 → critical_count += 1
**强制规则**: 无论层级多深,**只要设计节点有 name 就必须存在**,缺失必须计数
- **文字样式一致性检查**: **任意设计节点 type=text 且有 name** → 检查 fill 颜色 + fontSize + fontWeight 与实际CSS不符 → 🟡 中等差异 → moderate_count += 1
- **布局对齐检查**: 设计节点声明 `justifyContent: space_between` → 检查实际CSS是否正确设置 `display: flex; justify-content: space-between;` → 如果右侧元素未靠右对齐 → 🟡 中等差异 → moderate_count += 1
4. 读取实际页面源码app/mini-program/src/pages/{page}/index.vue双向检查每个必需组件:
- **必需组件检查**: 按路径节点整个区块缺失 → 直接判定为 🔴 严重差异 → critical_count += 1
- **文字样式一致性检查**: **任意设计节点 type=text 且有 name** → 检查 fill 颜色 + fontSize + fontWeight 与实际CSS不符 → 🟡 中等差异 → moderate_count += 1
- **布局对齐检查**: 设计节点声明 `justifyContent: space_between` → 检查实际CSS是否正确设置 `display: flex; justify-content: space-between;` → 如果右侧元素未靠右对齐 → 🟡 中等差异 → moderate_count += 1
5. 结构校验通过后,使用 Read 工具分别查看设计截图和实际截图AI 综合分析视觉差异:
- **必需组件检查**: 节点整个区块缺失 → 直接判定为 🔴 严重差异 → critical_count += 1
- **多余组件检查**: 实际页面存在设计稿中没有的顶层区块 → 🟡 中等差异 → moderate_count += 1
- **组件类型一致性检查**: 设计是 `icon_font` 但实现用纯文本字符 → 🟡 中等差异 → moderate_count += 1
- **必需组件检查**: 节点整个区块缺失 → 直接判定为 🔴 严重差异 → critical_count += 1
- **多余组件检查**: 实际页面存在设计稿中没有的顶层区块 → 🟡 中等差异 → moderate_count += 1
- **组件类型一致性检查**: 设计是 `icon_font` 但实现用纯文本字符 → 🟡 中等差异 → moderate_count += 1
6. 结构校验通过后,使用 Read 工具分别查看设计截图和实际截图AI 综合分析视觉差异:
- 布局结构(网格/弹性/定位、对齐方式)
- 组件排列(导航栏、卡片、按钮、图标)
- 颜色Neon Pulse 规范:#000000 背景、#ffb3b5 粉色、#e8b3ff 紫色、#00dce5 青色)
- 间距(内边距、外边距、元素间距)
- 字体(大小、粗细、颜色、对齐方式)
- 图标(是否存在、形状是否正确、是否 emoji 替代)
- 设计规范(是否违反 Neon Pulse 原则:如存在不必要的 1px 边框)
- 布局结构(网格/弹性/定位、对齐方式)
- 组件排列(导航栏、卡片、按钮、图标)
- 颜色Neon Pulse 规范:#000000 背景、#ffb3b5 粉色、#e8b3ff 紫色、#00dce5 青色)
- 间距(内边距、外边距、元素间距)
- 字体(大小、粗细、颜色、对齐方式)
- 图标(是否存在、形状是否正确、是否 emoji 替代)
- 设计规范(是否违反 Neon Pulse 原则:如存在不必要的 1px 边框)
```
**优势**:
@@ -338,14 +333,14 @@ PVD-1 PER-PAGE LOOP:
设计稿 (.pen) 中标记 `reusable: true` 的组件为**全局可复用组件**,必须抽取为 Vue 全局组件在 `app/mini-program/src/components/` 目录,所有页面使用 import 导入,禁止在每个页面重复手写完整实现。
**检查规则**
**检查规则**:
1. 先通过 Pencil MCP `batch_get` 扫描 `.pen` 中所有标记 `reusable: true` 的节点 → 获取全局可复用组件列表
2. 对每个需要使用该组件的页面:
- 如果页面**完整手写实现了可复用组件代码**(未 import 使用全局组件)→ 🟡 中等差异 `moderate_count += 1`
- 如果使用了全局组件但样式(背景色/尺寸)不符合设计规范 → 🟡 中等差异 `moderate_count += 1`
- 正确使用了全局组件且样式符合规范 → 不计数
**当前已识别可复用组件**
**当前已识别可复用组件**:
- `NavigationBarPrimary` (一级页面通用导航栏) → 要求:背景 `#000000` 不透明
- `NavigationBarWithBack` (二级页面带返回导航栏) → 要求:背景 `#000000cc` 半透明 + `backdrop-filter: blur(20px)`

View File

@@ -55,11 +55,29 @@ description: BMAD 项目增量需求规划 - 自动识别需要更新哪些BMAD
- 哪些代码文件需要修改/新建?
### 3. 生成计划阶段
**生成计划前必须检查以下产物是否都已纳入变更清单(核对清单):**
```
[ ] 1. _bmad-output/planning-artifacts/ - PRD/Epics/UX 顶层文档更新
[ ] 2. _bmad-output/implementation-artifacts/ - 单个故事文档(新建/更新)
[ ] 3. _bmad-output/implementation-artifacts/journey-coverage-report.md - FR覆盖报告更新
[ ] 4. ui.pen - 设计文件更新如果涉及UI变更
[ ] 5. prototype/ - 静态原型 HTML 页面更新 + mobile-index.html 索引更新
[ ] 6. 数据库 schema - 修改(如果涉及数据模型变更)
[ ] 7. 后端 API - 新建/修改端点
[ ] 8. 前端页面 - 新建/修改页面组件
[ ] 9. 配置文件 - 路由等配置修改
```
只有全部勾选确认后,才能输出最终计划。
生成计划内容要求:
- 严格遵循现有格式写出每一步更新内容
- 对文档更新,给出**具体插入位置**和**完整内容片段**
- 对代码更新,给出**文件路径**和**代码结构**
- 输出完整的文件变更清单
- 给出验证测试步骤
- 输出完整的文件变更清单(表格形式)
- 给出验证测试步骤(分点)
### 4. 写入计划文件
- 写入计划到 `/home/d8d-claude/.claude/plans/{random-slug}.md`

View File

@@ -110,7 +110,11 @@ A: 建议:
- 转换后进行人工微调
### Q: 可以只转换部分页面吗?
A: 可以!使用 `--pages` 参数指定页面名称,例如:`--pages home,profile`
A: 可以!有两种方式:
- 命令行直接指定:`--pages home,profile`(逗号分隔)
- 交互式选择:不指定 `--pages` 参数时如果扫描到多个页面AI 会列出所有页面让你勾选选择
特别适合增量同步:原型部分页面更新后,只转换更新过的页面。
### Q: 转换结果在哪里查看?
A: .pen文件会保存到你指定的路径或默认位置同时会生成详细的转换报告。

View File

@@ -36,7 +36,30 @@ AI自动执行以下操作
- 目录:扫描目录下所有 `.html` 文件
- 构建页面清单,包含文件名和路径
### 1.4 初始化 .pen 文件
### 1.4 根据参数过滤或交互式选择页面(增量同步支持)
执行页面选择逻辑:
#### 情况 1: 用户提供了 `--pages` 参数
1. 将逗号分隔的页面列表解析为目标页面名称数组
2. 对已扫描的页面进行过滤:
- 提取每个HTML文件的文件名不含扩展名 `.html`
- 只保留文件名匹配目标列表中任意一项的页面
- 不匹配的页面从清单中移除
3. 记录过滤结果,继续执行
#### 情况 2: 用户未提供 `--pages` 参数,但扫描到**多个页面**
1. 提取所有扫描到的页面文件名(不含扩展名)
2. 使用 `AskUserQuestion` 工具创建多选界面,列出所有找到的页面让用户选择
3. 用户选择后,只保留选中的页面到清单中
4. 继续执行
这种交互式选择非常适合**增量同步场景**:原型部分页面更新后,只需勾选更新过的页面重新转换,提高效率。
#### 情况 3: 用户未提供 `--pages` 参数,但只有一个页面
1. 保留该页面,直接继续执行
### 1.5 初始化 .pen 文件
- 如果目标 .pen 文件已存在,打开它
- 如果不存在,创建新的 .pen 文件

View File

@@ -52,7 +52,6 @@ progress_file: '{planning_artifacts}/.pipeline-progress.md'
| 2-规划 | 2.2 | `bmad-validate-prd` | 验证报告(内嵌) | PRD |
| 2-规划 | 2.3 | `bmad-create-ux-design` | `*ux*.md` | PRD |
| 2-规划 | 2.4 | (流水线内置) | `.pen` 设计文件同步 | PRD, UX, 已有 .pen |
| **design-sync (built-in)** | 检查 UX 文档是否新增页面 → 创建页面 → **截图验证 + 自动优化循环** → 更新设计上下文 |
| 3-解决方案 | 3.1 | `bmad-create-architecture` | `*arch*.md` | PRD, UX |
| 3-解决方案 | 3.2 | `bmad-create-epics-and-stories` | `*epic*.md` | PRD, 架构 |
| 3-解决方案 | 3.3 | `bmad-check-implementation-readiness` | 就绪报告 | 全部 |
@@ -249,6 +248,7 @@ phases:
| create-prd | 页面导航流程 + 功能区域 + 组件概览 |
| validate-prd | 不注入验证已有PRD |
| create-ux-design | 完整设计系统:变量、组件、页面布局 |
| **design-sync (built-in)** | 检查 UX 文档是否新增页面 → 创建页面 → **截图验证 + 自动优化循环** → 更新设计上下文 |
| create-architecture | 组件层级 + 数据流模式 |
| create-epics | 页面级功能分解 |
| check-readiness | (不注入,验证已有产物) |