Merge pull request 'sync: 旅程验证新增语义审查关卡 + 前置视觉分析 + Base 镜像构建模式' (#71) from sync/d8d-skills-20260513-020720 into master

Reviewed-on: http://gitea.d8d.fun/d8dfun/bmad-method-template/pulls/71
This commit is contained in:
2026-05-13 02:10:24 +00:00
8 changed files with 708 additions and 31 deletions

View File

@@ -217,7 +217,9 @@ curl 只用于补充数据验证(如确认数据库状态),**永远不能
- [ ] 截图**必须**保存到 `tests/e2e/screenshots/` 目录,不能保存到当前工作目录
- [ ] **每个截图文件必须是真正的 PNG 图片**`file <path>` 检测输出必须包含 "PNG image data"
- [ ] **强制:每截一张图立刻检查**`playwright-cli -s={S} screenshot` 完成后**立刻**执行 `file` 检测格式,失败立刻重截
- [ ] 每个用户步骤完成`playwright-cli -s={S} screenshot` + `file` 格式验证 + `analyze_image`视觉验证关卡
- [ ] **每个用户步骤执行前**`playwright-cli -s={S} screenshot` (*-pre.png) + `analyze_image`前置视觉分析
- [ ] 每个用户步骤完成 → `playwright-cli -s={S} screenshot` (*-post.png) + `file` 格式验证 + `analyze_image`(含前后对比)→ 后置视觉验证关卡
- [ ] 前置截图路径唯一(*-pre.png 与 *-post.png 不冲突,且同 journey 内各步骤的 *-pre.png 不重复)
- [ ] 旅程最终完成 → `playwright-cli -s={S} screenshot` 最终截图 + `playwright-cli -s={S} network` 资源检查
- [ ] 违反任意一条 → 中断补全,不能继续
@@ -245,14 +247,41 @@ curl 只用于补充数据验证(如确认数据库状态),**永远不能
- ⛔ **起始页视觉验证**: playwright-cli -s={S} screenshot → filename: "tests/e2e/screenshots/journey-epic-{N}-{M}-step0.png", type: "png" + analyze_image
- 循环每个用户步骤(步骤编号 S = 1, 2, 3...:
a. playwright-cli -s={S} snapshot → 找到目标元素
a.5 ⛔ **前置视觉分析 — 操作决策支持**(⛔ 强制 — 新增独立步骤):
目的: 在操作前通过视觉能力理解页面当前可视状态,辅助 AI 做出更准确的操作决策。
弥补 DOM snapshot 无法传递的信息(布局、位置、视觉状态、非文本元素)。
1. playwright-cli -s={S} screenshot → filename: "tests/e2e/screenshots/journey-epic-{N}-{M}-step{S}-pre.png", type: "png"
2. file 格式验证 → 输出必须包含 "PNG image data"
3. analyze_image → 使用前置视觉分析提示词(见 ../../rules/visual-verification.md §前置视觉分析模块):
"分析此页面截图以支持操作决策:
1) 页面识别:这是什么页面/视图?页面标题/头部显示什么?
2) 可视交互元素列出所有可见的可交互元素按钮文字、输入框标签、Tab名称、链接文字、下拉选择、复选框
3) 页面状态:正常/加载中/空状态/错误状态/是否有Toast/是否有Modal弹窗
4) 当前用户进度:基于可见内容,用户处在什么位置?
5) 建议下一步操作:基于旅程定义的目标,下一步应该操作哪个元素?"
4. 结合 (a) DOM snapshot 信息 + (a.5) 视觉分析结果 → 确认要操作的交互元素
5. 视觉与 DOM 矛盾时DOM 找到但视觉看不到 → 元素可能 hidden/off-screen:
→ playwright-cli -s={S} eval 检查元素可见性计算样式
→ 不可见 → 走标准诊断流程(../../rules/auto-fix/diagnostics.md FAIL #5
6. 记录前置分析结果到 step_results新增 pre_action_screenshot 字段)
b. playwright-cli -s={S} click / playwright-cli -s={S} fill / playwright-cli -s={S} run-code → 执行操作(⛔ 禁止用 curl 替代)
操作决策结合 (a) DOM + (a.5) 视觉双重信息,提高操作精准度。
c. sleep 5 → 等待响应/跳转
d. playwright-cli -s={S} snapshot → 验证操作结果(⛔ 禁止用 curl GET 替代)
e. ⛔ **视觉验证关卡**(⛔ 强制 — Read fully and follow: ../../rules/visual-verification.md
e. ⛔ **后置视觉验证关卡**(⛔ 强制 — Read fully and follow: ../../rules/visual-verification.md
此关卡为独立步骤,不是子步骤。每个用户步骤完成后必须通过此关卡才能继续。
1. playwright-cli -s={S} screenshot → filename: "tests/e2e/screenshots/journey-epic-{N}-{M}-step{S}.png", type: "png"
2. analyze_image → 使用 visual-verification.md 中的标准提示词
3. 结果记录到 pipeline-state.yaml 的 verification_detail含 analyze_image_executed: true
1. playwright-cli -s={S} screenshot → filename: "tests/e2e/screenshots/journey-epic-{N}-{M}-step{S}-post.png", type: "png"
2. analyze_image → 使用增强版提示词(含前后对比 — 见 ../../rules/visual-verification.md §前置视觉分析模块):
"将此截图与操作前的截图 (journey-epic-{N}-{M}-step{S}-pre.png) 进行对比:
1) 变化检测:操作前后有什么变化?(弹窗开/关、页面跳转、Toast出现、表单更新、按钮状态变化
2) 预期效果验证操作是否产生了预期变化PASS/FAIL/PARTIAL
3) 意外变化:是否有不应出现的副作用?
4) 设计合规性检查保留原有检查图标完整性、布局质量、英文枚举、SVG data URI、异常状态"
3. 结果记录到 pipeline-state.yaml 的 verification_detail含 analyze_image_executed: true + pre_action_screenshot 关联)
4. 视觉验证 FAIL → 按分流规则处理(见 ../../rules/auto-fix/engine.md + ../../rules/iron-laws.md 检测即阻断表)
5. ⛔ **步骤级跟踪**(每个用户步骤完成后强制执行):
a. 更新 verification-checklist.yaml 对应 step 的 status
@@ -261,12 +290,18 @@ curl 只用于补充数据验证(如确认数据库状态),**永远不能
- step_id: "j{N}-{M}-s{S}"
action: "{操作描述}"
status: "pass|fail|fixed|skipped"
screenshot_path: "tests/e2e/screenshots/journey-epic{N}-{M}-step{S}.png"
pre_action_screenshot: "tests/e2e/screenshots/journey-epic{N}-{M}-step{S}-pre.png"
pre_action_visual_analysis: { ... } # 前置视觉分析结果
screenshot_path: "tests/e2e/screenshots/journey-epic{N}-{M}-step{S}-post.png"
analyze_image_result: { ... }
issues_detected: [ ... ] # 检测到的问题
auto_fixes: [ ... ] # 自动修复记录
step_gate: "pass|fail|blocked"
gate_checks:
- check: "pre_action_screenshot_exists"
result: "pass|fail"
- check: "pre_action_visual_analysis_executed"
result: "pass|fail"
- check: "screenshot_consistency"
result: "pass|fail"
- check: "analyze_image_executed"
@@ -280,20 +315,25 @@ curl 只用于补充数据验证(如确认数据库状态),**永远不能
executed_at: "{ISO timestamp}"
note: "{备注}"
```
c. 步骤级 GATE 检查(6 项,任一 FAIL → 阻断):
├── G1: screenshot_consistency — screenshot_path 文件存在
├── G2: analyze_image_executed — analyze_image_result 非空
c. 步骤级 GATE 检查(9 项,任一 FAIL → 阻断):
├── G0: pre_action_visual_analysis_executed — 前置视觉分析step a.5)已执行
│ ⛔ **强制: 每个用户步骤操作前必须执行前置视觉分析screenshot + analyze_image**
├── G1: screenshot_consistency — screenshot_path 文件存在(*-post.png
├── G2: analyze_image_executed — analyze_image_result 非空(后置视觉验证)
├── G3: checklist_synced — verification-checklist.yaml step status 已更新
├── G4: state_persisted — pipeline-state.yaml step_results 已追加
├── G5: all_issues_resolved — 所有 issues_detected 有对应 resolved auto_fix
├── G6: file_format_validation — `file screenshot.png` 输出检测为 "PNG image data"
│ ⛔ **强制规则:每截一张图立检查** → `playwright-cli -s={S} screenshot` 完成后**立刻**执行 `file` 命令检测格式
│ ⛔ **强制规则:每截一张图立检查** → `playwright-cli -s={S} screenshot` 完成后**立刻**执行 `file` 命令检测格式
│ - 检测失败 → **立即重新截图**,不得累积到最后批量修复
│ - 检测通过 → 才允许继续下一步骤
│ - 目的:防止出现"扩展名 .png 但内容是 YAML 文本"的错误
│ - ⛔ 前置截图 (*-pre.png) 和后置截图 (*-post.png) 都需执行 file 格式验证
├── G7: screenshot_path_unique — 当前步骤的 screenshot_path 不与同旅程其他步骤重复
│ 检查方式: grep verification-checklist.yaml 同 journey 下所有 step 的 screenshot_path
│ 发现重复 → ❌ FAIL → 自动修正为唯一路径 → 重新截图 → 重新校验 G1-G7
│ 发现重复 → ❌ FAIL → 自动修正为唯一路径 → 重新截图 → 重新校验
├── G8: pre_post_screenshot_pair — *-pre.png 和 *-post.png 成对存在
│ ⛔ 每个步骤必须有前置和后置两张截图,缺一不可
4.5. ⛔ **源码 SVG data URI 扫描**(视觉验证关卡内 — 每次 snapshot 后强制执行):
- Bash: `grep -rn "data:image/svg+xml" mini-program/src/`(扫描小程序源码目录)
- 发现匹配 → svg_data_uri_check.found = FOUND → 记录文件列表

View File

@@ -38,7 +38,9 @@ Story 验证全部通过 ≠ 用户能正常使用系统。旅程模式弥补这
**Read fully and follow: ./journey-validation.md**
编排并执行每条用户旅程的自动化验证:
- 执行前校验(真实性规则 + [C] 覆盖缺口门控 + 组件交叉校验
- ⛔ 旅程定义语义审查PRD + Epic/Story + 原型 + 跨文档一致性
- 执行前校验(真实性规则 R1-R9
- [C] 覆盖缺口门控 + 组件交叉校验
- 每条旅程独立 agent 执行(按 `./journey-execution.md` 执行模板)
- 汇总结果 → 生成验证报告 → 更新 pipeline-state.yaml

View File

@@ -30,7 +30,56 @@
- 违规 → 自动修复旅程文件 → 重新校验max 3x
- 环境适配:读取 pipeline-context.md 确定当前环境,按 R3 适配
1.6 [C] 覆盖缺口门控(⛔ 强制 — 检查即阻断
1.6 旅程定义语义审查(⛔ 强制 — 新增质量关卡
**Read fully and follow: ../../rules/journey-semantic-review.md**
审查旅程定义的语义正确性,对照源文档判断旅程定义是否有错误。
a. PRD 场景对齐检查(维度 A:
- Read _bmad-output/planning-artifacts/prd.md → 提取用户场景
- 建立场景-旅程映射 → 检查流程顺序/缺失场景/孤儿旅程/角色一致
b. Epic/Story 定义对齐检查(维度 B — 最重要,旅程直接从此生成):
- Read _bmad-output/planning-artifacts/epics-full.md → 提取 Story 表格
- Read _bmad-output/implementation-artifacts/sprint-status.yaml → 提取 Story 状态
- Read _bmad-output/implementation-artifacts/{epic}-{story}-*.md → 提取 AC + Validation Tasks
- 逐条旅程 vs 其覆盖的 Story 交叉比对:
· Story 范围是否与 Epic 定义一致?
· 旅程功能描述是否与 Story 规格一致?
· 旅程 AC 是否覆盖 Story AC
· 是否引用了 sprint-status 中未实现的 Story
· API 端点是否与 Story 规格一致?
c. 原型/设计页面对齐检查(维度 C:
- 文本级: grep 旅程引用的 UI 元素文字 vs prototype/**/*.html
- 视觉级(有视觉能力的模型): 打开原型页面 → screenshot → analyze_image
d. 跨文档四方对齐检查(维度 D:
- PRD → Epic/Story → 原型 → 旅程,四方语义对齐
- 汇总维度 A/B/C 结果 → 生成四方差异矩阵
门控:
├── 全部 PASS → ✅ 继续步骤 1.7
├── 仅有 WARN → ⚠️ 输出报告,自动修正后继续
├── MAJOR → 🔧 自动补全旅程步骤max 3x仍失败则 BLOCKED
└── CRITICAL / BLOCKED → ❌ BLOCKED
- 输出审查报告到 _bmad-output/implementation-artifacts/journey-semantic-review-report.md
- 阻断进入验证执行
- 要求旅程定义重新生成或人工修正
审查结果写入 pipeline-state.yaml:
```yaml
semantic_review:
executed: true
dimensions:
A_prd_alignment: PASS/WARN/FAIL/N/A
B_epic_story_alignment: PASS/WARN/MAJOR/CRITICAL/N/A
C_prototype_alignment: PASS/WARN/FAIL/N/A
D_cross_doc_alignment: PASS/BLOCKED/N/A
overall_gate: PASS/WARN/BLOCKED
report_path: "_bmad-output/implementation-artifacts/journey-semantic-review-report.md"
```
1.7 [C] 覆盖缺口门控(⛔ 强制 — 检查即阻断)
a. grep 所有 epic-N-journeys.md 中的 [C] 标记(差异标注但未覆盖)
b. [C] 计数 > 0 → ❌ FAIL:
- 列出所有未覆盖的交互元素(文件名 + 步骤位置 + [C] 内容)
@@ -40,7 +89,7 @@
c. [C] 计数 = 0 → ✅ PASS → 继续
⛔ 旅程文件中不允许遗留 [C] 标记。[C] 是临时标注,必须在验证前解决。
1.7 组件交互元素交叉校验(⛔ 强制 — 源码 vs 旅程步骤对比)
1.8 组件交互元素交叉校验(⛔ 强制 — 源码 vs 旅程步骤对比)
a. 从旅程定义提取所有「技术验证步骤」涉及的交互元素click/type/upload/navigate
b. 读取对应页面/组件源码,提取所有用户交互元素:
- 按钮: onClick / handleClick / button 元素
@@ -51,7 +100,7 @@
d. 发现未覆盖的交互元素 → 自动补充旅程步骤max 3x
e. 门控: 100% 覆盖才能进入验证执行
1.8 生成步骤级验证清单(⛔ 强制 — 写入 verification-checklist.yaml
1.9 生成步骤级验证清单(⛔ 强制 — 写入 verification-checklist.yaml
- 解析每个旅程的「技术验证步骤」→ 为每个步骤生成 step 条目
- 提取验收标准 → 生成 acceptance_criteria 条目
- 写入/追加到 verification-checklist.yaml 的 journeys 部分:
@@ -74,7 +123,7 @@
```
- 如 verification-checklist.yaml 已存在 → 跳过已 pass 的步骤,从 pending 步骤恢复
1.8.1 截图路径唯一性与覆盖率校验(⛔ 强制 — checklist 生成后必须执行):
1.9.1 截图路径唯一性与覆盖率校验(⛔ 强制 — checklist 生成后必须执行):
a. 提取当前 journey 下所有步骤的 screenshot_path:
- 过滤 screenshot_required: true 的步骤
- 收集所有 screenshot_path 值
@@ -92,7 +141,7 @@
2. 询问: 验证全部 Epic 还是指定 Epic?(确定验证范围)
1.9 创建旅程任务清单(⛔ 强制 — 根据范围筛选,每条旅程一个 Task
1.10 创建旅程任务清单(⛔ 强制 — 根据范围筛选,每条旅程一个 Task
- 为每条待验证旅程**创建独立的 Task 任务**,使用 `TaskCreate` 工具:
- 每个任务记录Epic 编号、旅程名称、旅程文件路径、前置条件
- 便于独立追踪每条旅程的验证进度
@@ -113,7 +162,7 @@
严格按照 journey-execution.md 执行模板执行完整验证流程。
```
1.10 启动逐个任务验证(每条旅程独立 agent
1.11 启动逐个任务验证(每条旅程独立 agent
- 对**每个任务**启动一个**独立的 agent**,按照 `./journey-execution.md` 执行模板执行验证
- 独立 agent 执行模型(⛔ 严格 R6 自包含 — 每个 teammate 完全独立):
- 每个 teammate 拿到一条完全自包含的旅程

View File

@@ -178,3 +178,5 @@ REVIEW attempt < 3?
> 完整的 AUTO-FIX/IMPLEMENT/DATA-FIX 分类标准见 ../rules/auto-fix/classification.md修复流程见 ../rules/auto-fix/workflows.md
> **Playwright CLI → Agent 工具**: 在支持 Agent 工具的环境中,`playwright-cli` 命令可映射为 `browser_session`/`browser_action` 工具调用(参考 `next-playwright-cli` 技能),避免 Bash 直接执行 playwright-cli。

View File

@@ -0,0 +1,396 @@
# 旅程定义语义审查规则
> **Read fully and follow** when referenced by `../modes/journey/journey-validation.md` 步骤 1.6.
>
> 本文件定义旅程定义的语义正确性审查方法论。与 `journey-authenticity-rules.md` 互补:
> - `journey-authenticity-rules.md` 检查旅程"全不全、真不真"(格式、覆盖、真实性)
> - 本文件检查旅程"对不对"(语义是否与 PRD/Epic/Story/原型一致)
---
## 审查总流程
```
对每条旅程:
├── 维度 A: PRD 场景对齐
├── 维度 B: Epic/Story 定义对齐(最重要 — 旅程直接从此生成)
├── 维度 C: 原型/设计页面对齐
└── 维度 D: 跨文档四方对齐汇总
汇总 → 门控判定 → PASS / WARN / MAJOR / BLOCKED
```
---
## 维度 APRD 场景对齐检查
### A.1 读取 PRD
```
Read _bmad-output/planning-artifacts/prd.md
→ 提取所有用户场景/用户故事描述段落
→ 每个场景标注: 场景ID如有、场景标题、涉及角色、核心操作流程
```
### A.2 建立场景-旅程映射
对每条旅程,标注其对应哪个 PRD 场景:
| 旅程 | PRD 场景 | 匹配类型 |
|------|---------|---------|
| Epic N Journey M: {标题} | PRD §X.Y: {场景名} | 精确匹配 / 部分匹配 / 无匹配 |
匹配规则:
- 精确匹配:旅程的用户视角步骤描述与 PRD 场景描述高度一致
- 部分匹配:旅程覆盖了 PRD 场景的部分功能但缺失了某些环节
- 无匹配:旅程无对应 PRD 场景(孤儿旅程)
### A.3 检查项
| 检查项 | 方法 | 判定 |
|--------|------|------|
| 流程顺序一致 | 逐步骤比对 PRD 描述的操作顺序 vs 旅程的用户步骤顺序 | 不一致 → FAIL |
| PRD 缺失场景 | 标注 PRD 中有但无任何旅程覆盖的场景 | 缺失 → WARN |
| 孤儿旅程 | 旅程无对应 PRD 场景 | 孤儿 → WARN |
| 角色一致 | 旅程中的用户身份与 PRD 中该场景的 actor 一致 | 不一致 → FAIL |
| 场景覆盖完整性 | 每个 PRD 场景至少被 1 条旅程覆盖 | < 100% WARN |
### A.4 降级
- PRD 文件不存在 跳过维度 A在审查报告中标注 "PRD N/A"
---
## 维度 BEpic/Story 定义对齐检查(⛔ 最重要)
旅程是从 Epic Story 文档生成的此维度是最关键的语义正确性把关
### B.1 读取源文档
```
1. Read _bmad-output/planning-artifacts/epics-full.md
→ 提取所有 Epic 章节,每个 Epic 下的 Story 表格:
| ID | 用户故事 | 验收标准 |
2. Read _bmad-output/implementation-artifacts/sprint-status.yaml
→ 提取每个 Story 的状态done / in-progress / to-do
3. 对当前审查的 EpicRead 对应的 Story 规格文件:
_bmad-output/implementation-artifacts/{epic}-{story}-*.md
→ 提取:
- Acceptance Criteria 列表
- Validation Tasks (V1/V2/V3)
- Source References (API/Service/Page 路径)
- Proto Reference (原型文件路径)
```
### B.2 建立 Epic-Story-Journey 映射
```
对每条旅程:
1. 读取旅程文件头部声明:
"> 对应需求FRxxx-FRyyy | Stories: S{N}.{a}-S{N}.{b}"
2. 从 epics-full.md 提取该 Epic 下声明范围内的所有 Story
3. 从 sprint-status.yaml 检查每个 Story 的状态
4. 从 Story 规格文件读取详细功能描述
```
### B.3 检查项
#### B.3.1 旅程覆盖的 Story 范围检查CRITICAL
```
方法:
1. 提取旅程文件声明的 "Stories: S{N}.{a}-S{N}.{b}"
2. 从 epics-full.md 提取该 Epic 实际包含的所有 Story ID
3. 比对:
- 旅程声明的 Story 都在 Epic 定义中存在? → 不存在 = CRITICAL引用不存在的 Story
- Epic 中的 Story 是否都在旅程中得到覆盖? → 未覆盖 = MAJOR
- sprint-status 中 done 状态的 Story 是否全部被覆盖? → 遗漏 = CRITICAL
```
#### B.3.2 旅程功能描述 vs Story 规格一致性CRITICAL
```
对旅程覆盖的每个 Story:
1. 读取对应 Story 规格文件的 "## Story" 部分
2. 提取 As a / I want / so that 描述
3. 检查旅程步骤中是否反映了该 Story 的核心功能
4. 不一致判定:
- Story 说"用户上传视频"但旅程中是"用户选择已有视频" → FAIL
- Story 说"通过手机号验证码登录"但旅程中跳过验证码步骤 → FAIL
```
#### B.3.3 旅程验收标准 vs Story 验收标准覆盖CRITICAL
```
对旅程覆盖的每个 Story:
1. 从 Story 规格文件提取 "## Acceptance Criteria" 所有条目
2. 从旅程文件提取 "### 验收标准" 所有条目
3. 逐条交叉比对:
判定矩阵:
| Story AC | 旅程有对应 AC | 完全匹配 | 部分匹配 | 无匹配 |
| Story AC 1: {内容} | ✅/❌ | ✅/⚠️/❌ | ✅/⚠️/❌ | ✅/⚠️/❌ |
4. 门控:
- 所有 Story AC 完全匹配 → PASS
- ≥ 80% Story AC 有对应(完全或部分)→ WARN输出差异清单
- < 80% Story AC 有对应 → FAIL
- 旅程 AC 中有但 Story AC 中无对应 → WARN可能是旅程自动补充的合理 AC
```
#### B.3.4 Story 功能细节缺失检测MAJOR
```
对旅程覆盖的每个 Story:
1. 从 Story 规格文件提取关键功能词:
- "## Validation Tasks" 中涉及的操作动词(上传/下载/筛选/排序/导出/分页/搜索/删除/编辑/创建)
- "## Source References" 中列出的页面/API 路径
2. 在旅程的"技术验证步骤"中 grep 这些关键功能词
3. Story 中有但旅程中无对应步骤的功能:
→ 记录为缺失功能细节MAJOR
→ 自动补充旅程步骤max 3x
```
#### B.3.5 引用未实现 Story 检测BLOCKED
```
方法:
1. 读取 sprint-status.yaml获取所有 status: done 的 Story 列表
2. 读取旅程文件,提取所有引用/描述的 Story 功能
3. 交叉比对:
- 旅程引用了 status: to-do 的 Story → BLOCKED
- 原因: 旅程不能验证未实现的功能
- 修复: 从旅程中移除该 Story 相关步骤,或标注为 "⛔ 待实现 — 暂不验证"
```
#### B.3.6 技术验证 API 端点一致性MAJOR
```
方法:
1. 提取旅程"技术验证步骤"中的所有 API 调用POST/GET/PUT/DELETE /api/...
2. 提取 Story 规格 "## Source References" 中的 API 路径
3. 提取 Story 规格 "## Validation Tasks → V1: API Route Validation" 中的 API 端点
4. 比对:
- 旅程中的 API 调用是否与 Story 规格中定义的 API 一致?
- 不一致 → MAJOR可能引用了错误或不存在的端点
```
#### B.3.7 Story 边界条件覆盖检测MINOR
```
方法:
1. 从 Story 规格的 Validation Tasks 提取异常场景:
- V1 中 400/404/500 等错误状态验证
- V2 中的表单校验失败场景
2. 检查旅程验收标准是否包含这些异常场景
3. 缺失 → MINOR旅程不要求覆盖所有异常场景但建议标注
```
### B.4 降级
- epics-full.md 不存在 Story 规格文件和 sprint-status.yaml 重建 Story 清单
- Story 规格文件不存在 维度 B 只做 B.3.1 + B.3.5基于 epics-full.md + sprint-status
- sprint-status.yaml 不存在 B.3.5 跳过记录 WARN " Story 状态信息"
---
## 维度 C原型/设计页面对齐检查
### C.1 读取原型
```
1. 确定原型目录:
- ls prototype/ → 确认存在
- ls prototype/pages/ → 确认页面文件存在
2. 对旅程中涉及的每个页面:
- 从旅程的 '跨越页面' 或步骤 URL 提取页面名称
- 在 prototype/ 下搜索匹配的原型文件
```
### C.2 文本级 UI 元素检查
```
对旅程每个步骤:
1. 提取步骤中引用的 UI 交互元素:
- 按钮文字: "点击 {文字}" → 提取文字
- Tab 名称: "点 {名称} Tab" → 提取名称
- 输入框标签: "在 {标签} 输入" → 提取标签
- 链接文字: "点击 {文字} 链接" → 提取文字
2. 在原型 HTML 文件中 grep 这些文字:
grep -F "{UI 元素文字}" prototype/pages/**/*.html
3. 未找到 → WARN原型中不存在该 UI 元素,可能旅程定义有误)
```
### C.3 视觉级 UI 元素检查(有视觉能力的模型)
```
⛔ 条件:当前模型支持 analyze_image视觉能力
对旅程涉及的每个关键页面:
1. 如果 Pencil MCP 可用 + .pen 设计文件存在:
- mcp__pencil__batch_get → 搜索匹配的帧
- mcp__pencil__export_nodes → 导出设计截图
- analyze_image → 对比旅程描述 vs 设计帧
2. 如果 HTML 原型存在:
- 启动原型服务: cd prototype && npx serve . -p 8765
- playwright-cli -s=semantic goto http://localhost:8765/pages/{group}/{page}.html
- playwright-cli -s=semantic screenshot
- analyze_image → 验证旅程引用的 UI 元素是否在原型中存在
- kill 原型服务
3. 无任何原型 → WARN "无可视化原型,跳过视觉校验"
```
### C.4 降级
- 无原型目录 跳过维度 C
- Pencil MCP 且无 HTML 原型 只做文本级 grep 检查C.2
- 仅有 HTML 原型 做文本级 (C.2) + 视觉级 (C.3.2)
- Pencil MCP + .pen 优先 C.3.1
---
## 维度 D跨文档四方对齐检查
### D.1 四方对齐逻辑
```
对每条旅程:
1. 确定其覆盖的 Story ID 列表 ← 维度 B
2. 确定其覆盖的 PRD 场景 ← 维度 A
3. 确定其涉及的原型页面 ← 维度 C
4. 检查四方描述的功能行为是否一致:
PRD 场景描述 ≈ Epic/Story 描述 ≈ 原型页面设计 ≈ 旅程步骤定义
```
### D.2 不一致类型
| 类型 | 描述 | 示例 |
|------|------|------|
| PRDStory 矛盾 | PRD 场景描述与 Epic Story 分解不一致 | PRD "一键发布"Story 分解为 3 步操作 |
| StoryJourney 矛盾 | Story 规格与旅程步骤不一致 | Story AC 要求"重定向到 /editor"旅程断言"/admin" |
| PRDPrototype 矛盾 | PRD 场景与原型设计不一致 | PRD 描述表单有 5 个字段原型只有 3 |
| JourneyPrototype 矛盾 | 旅程步骤与原型页面不一致 | 旅程说"点击提交按钮"原型中按钮文字是"保存" |
### D.3 检测方法
```
汇总维度 A、B、C 的检查结果:
1. 提取所有 FAIL 和 WARN 条目
2. 按"不一致类型"分类
3. 确定根本不一致的文档对(是哪两方的描述矛盾?)
4. 生成四方差异矩阵
```
### D.4 输出格式
```yaml
cross_doc_alignment:
epic_N:
journey_M:
story_coverage: ["S{N}.{a}", "S{N}.{b}"]
prd_scenario: "§X.Y: {场景名}"
prototype_pages: ["{page1}.html", "{page2}.html"]
alignment_issues:
- type: "Story↔Journey"
severity: "CRITICAL"
story_id: "S1.1"
description: "旅程 AC 缺少 Story 1.1 的 AC#3JWT Token Cookie 属性验证)"
- type: "Journey↔Prototype"
severity: "MAJOR"
prototype_file: "prototype/pages/editor/login.html"
description: "旅程引用'手机号输入框'但原型中 input type='email'"
```
### D.5 降级
- 任一维度缺失 该维度不参与对齐检查
- 仅有维度 B 只输出 StoryJourney 一致性
- 所有维度都有数据 完整四方对齐
---
## 门控规则
### 判定标准
| 审查结果 | 定义 | 处理 |
|----------|------|------|
| PASS | 所有维度所有检查项通过 | 继续下一步骤 |
| WARN | 缺失场景/孤儿旅程/边界条件未覆盖/原型元素未找到文本级 | 输出审查报告自动修正后继续不阻断 |
| MAJOR | Story 功能细节缺失/API 端点不一致 | 自动补全旅程步骤max 3x仍失败则升级为 BLOCKED |
| CRITICAL | 旅程覆盖的 Story 不存在/流程与 Story 描述矛盾/引用未实现 Story | BLOCKED输出详细差异报告 |
| BLOCKED | 维度 D 四方对齐 FAIL | BLOCKED阻断验证执行需人工判断后修正 |
### 门控汇总
```
汇总维度 A/B/C/D 的判定:
├── 全部 PASS → ✅ 继续步骤 1.7
├── 仅有 WARN → ⚠️ 输出报告 + 自动修正 + 继续
├── 有 MAJOR → 🔧 自动补全旅程步骤max 3x
│ ├── 修复成功 → ✅ 继续
│ └── 修复失败 → ❌ BLOCKED
├── 有 CRITICAL → ❌ BLOCKED
└── 维度 D 四方对齐 FAIL → ❌ BLOCKED
```
### BLOCKED 后处理
```
输出详细审查报告到:
_bmad-output/implementation-artifacts/journey-semantic-review-report.md
报告内容:
1. 审查执行时间 + 涉及旅程清单
2. 每个维度的检查结果摘要
3. 每条 FAIL/MAJOR 的详细信息(含文件路径 + 行号 + 差异内容)
4. 四方差异矩阵(如适用)
5. 建议修复方向(是修 PRD、修 Story、修原型、还是修旅程定义
BLOCKED 后必须:
- 停止进入验证执行
- 输出报告路径供人工审查
- 根据报告修正源文档后重新运行审查
```
---
## 审查结果记录
审查结果写入 `pipeline-state.yaml`
```yaml
semantic_review:
executed: true
executed_at: "{ISO timestamp}"
journeys_reviewed: N
dimensions:
A_prd_alignment: PASS/WARN/FAIL/N/A
B_epic_story_alignment: PASS/WARN/MAJOR/CRITICAL/N/A
C_prototype_alignment: PASS/WARN/FAIL/N/A
D_cross_doc_alignment: PASS/BLOCKED/N/A
overall_gate: PASS/WARN/BLOCKED
issues:
- dimension: "B"
severity: "CRITICAL"
journey: "Epic 1 Journey 1"
description: "..."
story_ref: "S1.3"
recommendation: "..."
report_path: "_bmad-output/implementation-artifacts/journey-semantic-review-report.md"
```
---
## 工具使用优先级
| 场景 | 首选工具 | 回退工具 |
|------|---------|---------|
| 读取 PRD/Epics/Story | `Read` | |
| 文本搜索 UI 元素 | `grep` prototype/ | |
| 视觉比对设计帧 | `mcp__pencil__batch_get` + `analyze_image` | `playwright-cli screenshot` + `analyze_image` |
| 检查 Story 状态 | `Read` sprint-status.yaml | |
| 统计覆盖度 | `Bash` (grep -c / wc -l) | 手动计数 |

View File

@@ -3,7 +3,7 @@
> **⛔ 所有模式共享**旅程验证模式、回归验证模式、E2E 测试、Phase 4 测试均引用此文件。
>
> **被引用位置**
> - `../modes/journey/journey-execution.md` 执行模板步骤 2e
> - `../modes/journey/journey-execution.md` 执行模板步骤 2a.5(前置视觉分析) + 步骤 2e后置视觉验证
> - `validation-mode.md` Story 验证流程
> - `e2e-testing.md` 步骤 8
> - `phase-04-test.md` 测试流程
@@ -25,15 +25,21 @@
视觉验证是**独立关卡**,不是循环内的子步骤。每个用户步骤/验证步骤完成后,必须经过视觉验证关卡才能继续。
```
每个步骤的执行流程:
每个步骤的执行流程(旅程验证模式):
a. playwright-cli -s={S} snapshot → 找到目标元素
a.5 ⛔ 前置视觉分析关卡(独立,不可跳过):
1. playwright-cli -s={S} screenshot → *-pre.png前置截图
2. analyze_image → 前置视觉分析提示词
3. 结合 DOM + 视觉 → 确认操作目标
b. playwright-cli -s={S} click / playwright-cli -s={S} fill → 执行操作
c. sleep N → 等待响应
d. playwright-cli -s={S} snapshot → 验证操作结果
⛔ 视觉验证关卡(独立,不可跳过):
1. playwright-cli -s={S} screenshot → 保存截图
2. analyze_image → AI 视觉分析(使用下方标准提示词)
后置视觉验证关卡(独立,不可跳过):
1. playwright-cli -s={S} screenshot → *-post.png后置截图
2. analyze_image → AI 视觉分析(含前后对比 — 使用增强版提示词)
3. 分析结果记录到 verification_detail
4. 发现问题 → 按分流规则处理
5. 关卡未通过 → 不得进入下一个用户步骤
@@ -55,20 +61,122 @@
```
执行后自检清单(⛔ 强制):
1. ✅ playwright-cli -s={S} screenshot 保存了截图文件(路径含步骤编号
2. ✅ analyze_image 对截图执行了视觉分析(结果已记录)
3. ✅ verification_detail.design_check 存在且值为 PASS 或 FAIL不能为 null
4. ✅ verification_detail.icons_check.emoji_as_icons 已检查
5. ✅ 发现 FAIL 后执行了分类判定和修复流程
1. ✅ playwright-cli -s={S} screenshot 保存了前置截图(*-pre.png和后置截图*-post.png
2. ✅ analyze_image 对前置截图执行了操作决策分析(结果已记录)
3. ✅ analyze_image 对后置截图执行了前后对比视觉验证(结果已记录
4. ✅ verification_detail.design_check 存在且值为 PASS 或 FAIL不能为 null
5. ✅ verification_detail.icons_check.emoji_as_icons 已检查
6. ✅ 发现 FAIL 后执行了分类判定和修复流程
任一为"否" → Story 不得标记为 verified/done。
```
---
## analyze_image 标准提示词
## 前置视觉分析模块Pre-Action Visual Analysis
每个截图的 AI 视觉分析使用以下提示词:
> **被引用位置**`../modes/journey/journey-execution.md` 执行模板步骤 2a.5
>
> 前置视觉分析在执行操作前,通过视觉能力理解页面当前可视状态,辅助 AI 做出更准确的操作决策。
> 弥补 DOM snapshot 无法传递的信息(布局、位置、视觉状态、非文本元素)。
### 目的
DOM snapshot 提供的是元素结构树,但无法回答:
- 这个按钮在页面上**长什么样子**、在**哪个位置**
- 页面上是否有**弹窗/Modal**遮挡了我想操作的元素?
- 页面当前处于**什么状态**(加载中/空状态/错误状态)?
- Tab 当前选中的是哪一个(视觉高亮 vs DOM 属性可能不同步)?
前置视觉分析通过 `screenshot` + `analyze_image` 在执行操作前获取这些信息,让 AI 的决策依据从"纯文本 DOM"升级为"视觉+DOM"。
### 执行流程
```
每个用户操作前:
1. playwright-cli -s={S} snapshot → DOM 结构分析
2. playwright-cli -s={S} screenshot → *-pre.png前置截图
3. file 格式验证 → 确保为 PNG
4. analyze_image → 使用前置分析提示词
5. 结合 DOM + 视觉结果 → 确认操作目标
6. 视觉与 DOM 矛盾 → 诊断处理
```
### 前置截图命名规则
- 格式: `tests/e2e/screenshots/journey-epic-{N}-{M}-step{S}-pre.png`
- 后置截图: `tests/e2e/screenshots/journey-epic-{N}-{M}-step{S}-post.png`
- 最终截图: `tests/e2e/screenshots/journey-epic-{N}-{M}-final.png`(保持不变)
- 起始页截图: `tests/e2e/screenshots/journey-epic-{N}-{M}-step0.png`(保持不变,起始页无操作前状态)
### 前置视觉分析提示词
```
分析此页面截图以支持操作决策:
1. **页面识别**:这是什么页面/视图?页面标题/头部显示什么文字?
2. **可视交互元素**:逐个列出所有可见的可交互元素及其标签文字:
- 按钮: 列出每个按钮的文字标签
- 输入框: 列出每个输入框的 placeholder/label 文字
- Tab/导航项: 列出每个 Tab 的文字,标注哪个处于选中状态
- 链接: 列出所有可点击的链接文字
- 下拉选择器/复选框/开关: 列出标签和当前状态
- 弹窗/Modal/对话框: 如果有,列出标题和按钮文字
3. **页面状态**:
- 正常渲染 / 加载中Skeleton/Spinner/ 空状态(无数据提示)/ 错误状态
- 是否有 Toast/Snackbar/Notification 显示(含文字内容)
- 是否有 Modal/Dialog/BottomSheet 打开
- 是否有表单校验错误提示(含文字内容)
4. **当前用户进度**:基于可见内容,用户处在操作的哪个阶段?
5. **建议下一步操作**基于旅程定义的目标下一步应该操作哪个元素给出2-3个候选优先最可能的
输出结构化结果,标注每个可交互元素的区域位置和标签文字。
```
### 后置视觉验证提示词(增强版 — 含前后对比)
```
将此截图 (journey-epic-{N}-{M}-step{S}-post.png) 与操作前的截图 (journey-epic-{N}-{M}-step{S}-pre.png) 进行对比:
1. **变化检测**:操作前后有什么可见变化?
- 是否有弹窗/Modal 打开或关闭?
- 页面是否跳转到不同视图?
- 是否有 Toast/Notification 出现(含文字内容)?
- 表单字段值是否有更新?
- 列表/表格数据是否有变化(行数增减、内容变化)?
- 按钮状态是否有变化(禁用↔启用、文字变化)?
- Tab/导航选中状态是否变化?
2. **预期效果验证**
- PASS: 操作产生了与旅程步骤预期一致的变化
- FAIL: 操作后无任何可见变化(操作可能未生效)
- PARTIAL: 部分变化但不完整(如有弹窗但内容为空)
3. **意外变化检测**:是否有不应出现的副作用(如页面整体刷新、其他区域异常变化)?
4. **设计合规性检查**(保留原有检查):
- 图标/图片完整性TabBar 图标、无 emoji 替代图标、无 broken image
- 英文枚举检测
- 布局质量(无溢出、无重叠、间距正常、无变形、对齐正确)
- SVG data URI 充当图标/装饰元素
- 双重导航栏
- 下拉刷新一致性
输出变化检测结果 + 设计合规检查结果。标注 PASS/FAIL/PARTIAL 及具体原因。
```
### 前后截图对应规则
- 每条旅程的每个步骤有且仅有一对 *-pre.png 和 *-post.png
- 前置截图通过 step_id 与后置截图关联(`j{N}-{M}-s{S}`
- 前置截图在后置视觉验证中作为 reference 传入
- 前后截图路径唯一性:同 journey 内所有 *-pre.png 和 *-post.png 路径不可重复
---
## analyze_image 标准提示词(后置验证 — 原有,保留兼容)
每个截图的 AI 视觉分析使用以下提示词。**注意:旅程验证模式下优先使用「后置视觉验证提示词(增强版)」,回归验证/E2E 测试等单截图场景使用此标准提示词。**
```
详细分析此移动端/桌面端页面截图,检查以下维度:

View File

@@ -0,0 +1,79 @@
# Base 镜像构建模式
**适用场景**:修改了 `Dockerfile.base` 后,需要重新构建 base 镜像。
Base 镜像包含系统级依赖apt 包、全局 npm 工具等),很少重建。主应用镜像(`Dockerfile`)在每次发新版时自动引用最新的 base 镜像。
---
## 执行流程
| 步骤 | 操作 | 说明 |
|------|------|------|
| 1 | 确认 Dockerfile.base 已修改 | `git diff HEAD~1 Dockerfile.base` |
| 2 | 确认已推送到 main 分支 | `git log --oneline -3` |
| 3 | 触发 workflow_dispatch | `python3 scripts/ci.py build-base` |
| 4 | 监控构建状态 | `python3 scripts/ci.py status` |
| 5 | 构建完成后发新版 | `bash scripts/release_tag.sh <version>` |
---
## 详细步骤
### 步骤 1: 确认修改
```bash
git diff HEAD~1 Dockerfile.base
```
### 步骤 2: 确认推送
```bash
git log --oneline -3
```
确保最新的 commit 已在 remote。
### 步骤 3: 触发构建
```bash
python3 scripts/ci.py build-base
```
指定分支(默认 main
```bash
python3 scripts/ci.py build-base main
```
### 步骤 4: 监控构建
```bash
# 查看最近构建状态
python3 scripts/ci.py status
# 查看构建日志run_id 从 status 命令获取)
python3 scripts/ci.py log <run_id>
```
### 步骤 5: 发新版
Base 镜像构建成功后,发新版让主应用使用新 base 镜像:
```bash
bash scripts/release_tag.sh <version>
```
---
## 构建内容
`build-base` 触发 `.gitea/workflows/build-base.yaml`,构建 `Dockerfile.base` 并推送到:
| Registry | 镜像路径 |
|----------|---------|
| 北京 ACR | `registry.cn-beijing.aliyuncs.com/d8dcloud/d8d-next-base:latest` |
| 香港 ACR | `registry-vpc.cn-hongkong.aliyuncs.com/d8dcloud/d8d-next-base:latest` |
---
→ 返回 [workflow.md](../workflow.md)

View File

@@ -57,6 +57,7 @@
| 🚀 **发新版模式** | `modes/release-version-mode.md` | 快速发新版:创建 tag → 触发 CI → 监控构建 |
| 🏗️ **标准部署模式** | `modes/deployment-mode.md` | 完整端到端部署:基础设施 → CI → ECI 部署 |
| 💾 **数据同步模式** | `modes/data-sync-mode.md` | 备份/恢复/迁移AI 动态执行 |
| 🖼️ **Base 镜像构建** | `modes/build-base-mode.md` | 构建新的 base 镜像Dockerfile.base很少触发 |
| 🔄 **Registry 维护模式** | `modes/registry-only.md` | 仅部署/重启私有 Registry |
## 阶段导航