diff --git a/.claude/skills/d8d-dev/modes/journey/journey-execution.md b/.claude/skills/d8d-dev/modes/journey/journey-execution.md index cb40249..ef8e543 100644 --- a/.claude/skills/d8d-dev/modes/journey/journey-execution.md +++ b/.claude/skills/d8d-dev/modes/journey/journey-execution.md @@ -217,7 +217,9 @@ curl 只用于补充数据验证(如确认数据库状态),**永远不能 - [ ] 截图**必须**保存到 `tests/e2e/screenshots/` 目录,不能保存到当前工作目录 - [ ] **每个截图文件必须是真正的 PNG 图片** → `file ` 检测输出必须包含 "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 → 记录文件列表 diff --git a/.claude/skills/d8d-dev/modes/journey/journey-index.md b/.claude/skills/d8d-dev/modes/journey/journey-index.md index e00be4a..f6e604c 100644 --- a/.claude/skills/d8d-dev/modes/journey/journey-index.md +++ b/.claude/skills/d8d-dev/modes/journey/journey-index.md @@ -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 diff --git a/.claude/skills/d8d-dev/modes/journey/journey-validation.md b/.claude/skills/d8d-dev/modes/journey/journey-validation.md index 49a7d55..928d18f 100644 --- a/.claude/skills/d8d-dev/modes/journey/journey-validation.md +++ b/.claude/skills/d8d-dev/modes/journey/journey-validation.md @@ -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 拿到一条完全自包含的旅程 diff --git a/.claude/skills/d8d-dev/phases/phase-04-test.md b/.claude/skills/d8d-dev/phases/phase-04-test.md index f190185..5cf07a0 100644 --- a/.claude/skills/d8d-dev/phases/phase-04-test.md +++ b/.claude/skills/d8d-dev/phases/phase-04-test.md @@ -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。 + diff --git a/.claude/skills/d8d-dev/rules/journey-semantic-review.md b/.claude/skills/d8d-dev/rules/journey-semantic-review.md new file mode 100644 index 0000000..33089f3 --- /dev/null +++ b/.claude/skills/d8d-dev/rules/journey-semantic-review.md @@ -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 +``` + +--- + +## 维度 A:PRD 场景对齐检查 + +### 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" + +--- + +## 维度 B:Epic/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. 对当前审查的 Epic,Read 对应的 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 不一致类型 + +| 类型 | 描述 | 示例 | +|------|------|------| +| PRD↔Story 矛盾 | PRD 场景描述与 Epic Story 分解不一致 | PRD 说"一键发布",Story 分解为 3 步操作 | +| Story↔Journey 矛盾 | Story 规格与旅程步骤不一致 | Story AC 要求"重定向到 /editor",旅程断言"/admin" | +| PRD↔Prototype 矛盾 | PRD 场景与原型设计不一致 | PRD 描述表单有 5 个字段,原型只有 3 个 | +| Journey↔Prototype 矛盾 | 旅程步骤与原型页面不一致 | 旅程说"点击提交按钮",原型中按钮文字是"保存" | + +### 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#3(JWT Token Cookie 属性验证)" + - type: "Journey↔Prototype" + severity: "MAJOR" + prototype_file: "prototype/pages/editor/login.html" + description: "旅程引用'手机号输入框'但原型中 input type='email'" +``` + +### D.5 降级 + +- 任一维度缺失 → 该维度不参与对齐检查 +- 仅有维度 B → 只输出 Story↔Journey 一致性 +- 所有维度都有数据 → 完整四方对齐 + +--- + +## 门控规则 + +### 判定标准 + +| 审查结果 | 定义 | 处理 | +|----------|------|------| +| 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) | 手动计数 | diff --git a/.claude/skills/d8d-dev/rules/visual-verification.md b/.claude/skills/d8d-dev/rules/visual-verification.md index fdb3e12..36b4f4b 100644 --- a/.claude/skills/d8d-dev/rules/visual-verification.md +++ b/.claude/skills/d8d-dev/rules/visual-verification.md @@ -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 测试等单截图场景使用此标准提示词。** ``` 详细分析此移动端/桌面端页面截图,检查以下维度: diff --git a/.claude/skills/d8d-release/modes/build-base-mode.md b/.claude/skills/d8d-release/modes/build-base-mode.md new file mode 100644 index 0000000..7cb904d --- /dev/null +++ b/.claude/skills/d8d-release/modes/build-base-mode.md @@ -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 ` | + +--- + +## 详细步骤 + +### 步骤 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 +``` + +### 步骤 5: 发新版 + +Base 镜像构建成功后,发新版让主应用使用新 base 镜像: + +```bash +bash scripts/release_tag.sh +``` + +--- + +## 构建内容 + +`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) diff --git a/.claude/skills/d8d-release/workflow.md b/.claude/skills/d8d-release/workflow.md index 9bdea3c..0a737f0 100644 --- a/.claude/skills/d8d-release/workflow.md +++ b/.claude/skills/d8d-release/workflow.md @@ -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 | ## 阶段导航