{"id":"891e8e48-24f0-4b0f-b97d-b0dab9a4a484","shortId":"t2ARYB","kind":"skill","title":"forge-qa","tagline":"QA 验收与测试报告。纯验收模式：测试+报告，不修代码。\n两种调用模式：\n  Mode A（完整 QA）：test-spec 生成 → 10 维度 Playwright 断言引擎 → 智能分析。\n  Mode B（单 bug 修复回归）：配合 forge-bugfix 的 P6 调用，读取 docs/bugfix/reviews/BF-XX.md，\n    针对 Bug 修复验收报告里的人工验收指南跑自动化测试，把逐步截图、深度断言、\n    前后端环境身份校验回填到报告。QA 全过 → 单 bug 模式进 P6.5，批量模式进入\n    qa-pass","description":"> **文档落地路径**：遵循 forge-doc-policy 规范。完整白名单 + frontmatter schema 见\n> `~/claudecode_workspace/工具/forge-cookbook/skills/forge-doc-policy/doc-paths.md`。\n\n# /forge-qa：QA 验收与测试报告\n\n**纯验收模式：测试 + 报告，不修代码。** 发现的问题生成结构化 bug 记录；单 bug 回归时回填 Bug 修复验收报告。\n\n## 调用模式\n\nforge-qa 支持两种调用模式，**入口判断在前置脚本阶段**完成（见\"前置脚本\"节）。\n\n| 模式 | 触发条件 | 输入 | 输出 | 下游 |\n|---|---|---|---|---|\n| **Mode A：完整 QA** | 用户直接触发，或 forge-dev 调度 | PRD / DESIGN / git diff | QA.md 报告 + 结构化 bug 候选 + User Gate | forge-ship / forge-bugfix / forge-eng |\n| **Mode B：单 bug 修复验收报告** | forge-bugfix 的 P6 调用；入口带参数 `review_doc=docs/bugfix/reviews/BF-XX.md` | 单 bug Bug 修复验收报告 | 报告内 QA 证据区、环境身份校验、逐步截图回填 | forge-bugfix 的 P6.5 / 批次最终验收 / P5（回修）|\n\n**模式判断逻辑**（前置脚本执行）：\n\n**模式判断优先级**（从高到低）：\n\n1. **显式参数** — Skill 调用时 args 含 `mode=B` 和 `review_doc=<路径>` → 直接 Mode B\n2. **调用来源** — 触发消息里出现 \"forge-bugfix\"、\"review-checklist\"、`BF-\\d+-\\d+.md` 文件路径 → Mode B\n3. **默认** — Mode A\n\n```bash\n# AI 从 args 或触发消息中解析\n# 优先级 1: 显式 args\nif echo \"$ARGS\" | grep -q \"mode=B\"; then\n  MODE=\"B\"\n  REVIEW_DOC=$(echo \"$ARGS\" | grep -oE \"review_doc=[^ ]+\" | cut -d= -f2)\n  BUG_ID=$(echo \"$ARGS\" | grep -oE \"bug_id=[^ ]+\" | cut -d= -f2)\n  WORKTREE=$(echo \"$ARGS\" | grep -oE \"worktree=[^ ]+\" | cut -d= -f2)\n  COMMIT=$(echo \"$ARGS\" | grep -oE \"commit=[^ ]+\" | cut -d= -f2)\n  APP_URL=$(echo \"$ARGS\" | grep -oE \"app_url=[^ ]+\" | cut -d= -f2)\n  echo \"QA Mode: B（单 bug 修复验收报告）\"\n  echo \"  review_doc: $REVIEW_DOC\"\n  echo \"  bug_id: $BUG_ID\"\n  echo \"  worktree: $WORKTREE\"\n  echo \"  commit: $COMMIT\"\n  [ -n \"$APP_URL\" ] && echo \"  app_url: $APP_URL\"\n# 优先级 2: 启发式识别\nelif echo \"$USER_MESSAGE\" | grep -qE \"forge-bugfix|review-checklist|docs/bugfix/reviews/BF-[0-9]+-[0-9]+\\.md\"; then\n  MODE=\"B\"\n  # 从消息里捞 review_doc 路径\n  REVIEW_DOC=$(echo \"$USER_MESSAGE\" | grep -oE \"docs/bugfix/reviews/BF-[0-9]+-[0-9]+\\.md\" | head -1)\n  echo \"QA Mode: B（启发式判定）\"\n  echo \"  review_doc: $REVIEW_DOC\"\n  # AI 必须验证：报告存在 + 其他必需参数从报告或上下文推断\nelse\n  MODE=\"A\"\n  echo \"QA Mode: A（完整 QA）\"\nfi\n\n# Mode B 必需参数校验\nif [ \"$MODE\" = \"B\" ]; then\n  [ -f \"$REVIEW_DOC\" ] || { echo \"❌ Bug 修复验收报告不存在: $REVIEW_DOC\"; exit 1; }\n  [ -n \"$BUG_ID\" ] || BUG_ID=$(basename \"$REVIEW_DOC\" .md)\n  if [ -n \"$WORKTREE\" ] && [ -d \"$WORKTREE\" ] && [ -z \"$APP_URL\" ]; then\n    if [ -f \"$WORKTREE/package.json\" ] && (cd \"$WORKTREE\" && npm run 2>/dev/null | grep -q \"dev:status\"); then\n      echo \"⚠️ 当前项目提供 dev:status，但 Mode B 未传 app_url。若验收项涉及浏览器、curl 或截图，调用方必须先运行 npm run dev:status，并把 Frontend URL 作为 app_url 传入。\"\n    elif [ -x \"$WORKTREE/scripts/dev-stack.sh\" ]; then\n      echo \"⚠️ 当前项目提供 scripts/dev-stack.sh，但 Mode B 未传 app_url。若验收项涉及浏览器、curl 或截图，调用方必须先运行 dev-stack status，并把 Frontend URL 作为 app_url 传入。\"\n    fi\n  fi\nfi\n```\n\nMode B 详见\"## Mode B：单 bug 修复验收报告模式\"节（本文档末尾）。\n\nMode A 详见\"## 三层架构\"往下的完整流程。\n\n**Mode B 的 args 契约（forge-bugfix 必须传，forge-qa 必须接收）**：\n\n| 参数 | 必填 | 含义 |\n|---|---|---|\n| `mode=B` | ✅ | 强制信号，优先级最高 |\n| `review_doc=<路径>` | ✅ | Bug 修复验收报告（存在性校验失败直接 exit） |\n| `bug_id=BF-{MMDD}-{N}` | ✅ | 用于命名截图 / 日志 |\n| `worktree=<路径>` | ✅ | 在该 worktree 内运行测试 |\n| `commit=<hash>` | ✅ | 用于定位修复范围 |\n| `app_url=<URL>` | 条件 | 仅当 bug 类型涉及应用运行时；必须来自调用方的 `dev:status` / `dev-stack status` 输出 |\n\n## 三层架构\n\n```\n┌─────────────────────────────────────────────────┐\n│  Layer 1: 测试规格生成（文档 → test-spec.json）     │\n│  输入: PRD / DESIGN.md / git diff / 会话上下文       │\n├─────────────────────────────────────────────────┤\n│  Layer 2: 10 维度 Playwright 断言引擎               │\n│  控制台|数据驱动|网络|视觉|交互|响应式|可访问|SSE|URL|懒加载│\n├─────────────────────────────────────────────────┤\n│  Layer 3: 智能分析（失败归因 + 根因定位）            │\n│  console → 源码 → git diff 交叉引用                │\n└─────────────────────────────────────────────────┘\n```\n\n## 铁律\n\n1. **只测不修** — forge-qa 不修改任何业务代码。发现 bug 记录到报告，由 forge-eng 修复。\n2. **不生成 test-spec 就不执行测试** — 先从文档提取验收项，结构化后再执行。\n3. **每个测试必须有 pass/fail** — 不允许 `.catch(() => {})` 吞错误，不允许\"只截图不断言\"。\n4. **断言必须验证功能正确性，不能只验证元素存在** — `visible` 和 `count_gte` 是前置条件，不是验收断言。每个测试用例必须至少包含一个验证**数据值/文本内容/状态变化**的深层断言（`contains_text`、`has_attribute`、`css_value`、`matches_regex`、自定义 `evaluate`）。详见下方\"断言深度规则\"。\n5. **证据先于结论** — 每个测试结果必须有截图、输出、或日志作为证据。\n6. **控制台零容忍** — 任何 `pageerror` 或 `console.error` 自动 FAIL。\n7. **不得猜本地端口** — 有 `app_url` 就只测该 URL；没有 `app_url` 时，优先读取 `dev:status` / `dev-stack status`，不得自行发明 `localhost:3000`、`5173`、`8080` 等地址。\n8. **Codex 浏览器优先** — 在 Codex 中做本地前端页面/交互 QA 时，若 Browser Use 插件可用，优先使用 `browser-use:browser`。不得因为 Computer Use 工具可见就跳过 Browser Use；Computer Use 只作明确兜底。\n\n## 定位说明\n\n| forge-eng 负责 | forge-qa 负责 |\n|----------------|--------------|\n| 单元测试（TDD 红绿重构） | **端到端用户流程测试** |\n| 原子 commit 验证（exit code） | **跨模块集成测试** |\n| 任务级验证 | **7 维度断言（视觉+响应式+可访问性+网络+数据驱动）** |\n| — | **验收标准逐项核对** |\n| — | **User Gate（用户验收关卡）** |\n\n## 完整流程\n\n```\n第0步 上下文探测\n  ├── 0.1 Worktree 检测\n  ├── 0.2 文档链定位（PRD/DESIGN/ENGINEERING/FEEDBACK）\n  ├── 0.3 变更范围分析（git diff）\n  ├── 0.4 选择器审计（铁律：不盲猜选择器）\n  └── 0.5 测试级别确认\n  │\n第1步 建立健康基准\n  │\n  ├── 已有 QA.md → 第2步 理解现状\n  └── 无 QA.md   → 第2步(替代) 从零创建\n  │\n第2.5步 生成 test-spec（铁律：不生成就不执行）\n  │\n第3步 测试计划确认（用户审查 test-spec 摘要）\n  │\n第4步 更新 QA 文档\n  │\n第5步 10 维度测试执行\n  ├── Phase 1: 控制台[console] + 网络[network]\n  ├── Phase 2: 交互[functional] + 数据驱动[data-driven] + SSE[streaming] + URL状态[url-state] + 懒加载[async-content]\n  ├── Phase 3: 视觉[visual] + 响应式[responsive]\n  └── Phase 4: 可访问性[accessibility]\n  │\n第6步 智能分析 + Bug 报告\n  │\n第7步 User Gate（用户验收 — 不可跳过）\n  │\n  ├── accept → forge-ship\n  └── reject → FEEDBACK.md → forge-eng → forge-qa (回归) → User Gate\n```\n\n全程中文。关键测试策略需用户确认后再执行。\n\n## 报告产出后的出口\n\n```\nQA 验收完成。下一步：\n\n[全部通过 + 用户验收通过]\n→ /forge-ship 或 /forge-review\n\n[有 FAIL 或用户 reject]\n→ 生成修复清单 + FEEDBACK.md → /forge-eng 修复 → /forge-qa 回归\n```\n\n---\n\n## 前置脚本\n\n```bash\n_BRANCH=$(git branch --show-current 2>/dev/null || echo \"unknown\")\n_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)\necho \"当前分支: $_BRANCH\"\n\n# === Worktree 检测 ===\n_IN_WORKTREE=\"no\"\n_WORKTREE_ROOT=\"\"\ngit worktree list 2>/dev/null | while read line; do\n  echo \"  worktree: $line\"\ndone\n[ \"$(git rev-parse --git-common-dir 2>/dev/null)\" != \"$(git rev-parse --git-dir 2>/dev/null)\" ] && _IN_WORKTREE=\"yes\" && _WORKTREE_ROOT=\"$_ROOT\"\necho \"在 Worktree 中: $_IN_WORKTREE\"\n\n# === 测试引擎 1: gstack/browse ===\nB=\"\"\n[ -n \"$_ROOT\" ] && [ -x \"$_ROOT/.claude/skills/gstack/browse/dist/browse\" ] && B=\"$_ROOT/.claude/skills/gstack/browse/dist/browse\"\n[ -z \"$B\" ] && [ -x \"$HOME/.claude/skills/gstack/browse/dist/browse\" ] && B=\"$HOME/.claude/skills/gstack/browse/dist/browse\"\n[ -n \"$B\" ] && echo \"gstack/browse: $B\" || echo \"gstack/browse: 不可用\"\n\n# === 测试引擎 2: Playwright ===\nPW=\"\"\ncommand -v npx >/dev/null 2>&1 && npx playwright --version >/dev/null 2>&1 && PW=\"npx\"\n[ -z \"$PW\" ] && python3 -c \"from playwright.sync_api import sync_playwright\" 2>/dev/null && PW=\"python\"\n[ -n \"$PW\" ] && echo \"Playwright: 可用 ($PW)\" || echo \"Playwright: 不可用\"\n\n# === qa-runner.mjs 检测 ===\nQA_RUNNER=\"\"\n[ -f \"$HOME/.claude/skills/forge-qa/scripts/qa-runner.mjs\" ] && QA_RUNNER=\"$HOME/.claude/skills/forge-qa/scripts/qa-runner.mjs\"\n[ -n \"$QA_RUNNER\" ] && echo \"qa-runner: $QA_RUNNER\" || echo \"qa-runner: 不可用\"\n\n# === 框架检测 ===\n[ -f \"$_ROOT/package.json\" ] && grep -q '\"react\"' \"$_ROOT/package.json\" 2>/dev/null && echo \"框架: React\"\n[ -f \"$_ROOT/package.json\" ] && grep -q '\"vue\"' \"$_ROOT/package.json\" 2>/dev/null && echo \"框架: Vue\"\n[ -f \"$_ROOT/package.json\" ] && grep -q '\"next\"' \"$_ROOT/package.json\" 2>/dev/null && echo \"框架: Next.js\"\n[ -f \"$_ROOT/requirements.txt\" ] || [ -f \"$_ROOT/pyproject.toml\" ] && echo \"运行时: Python\"\n[ -f \"$_ROOT/package.json\" ] && echo \"运行时: Node.js\"\n\n# === 本地服务探测 ===\necho \"本地服务:\"\nif [ -n \"$APP_URL\" ]; then\n  echo \"  APP_URL=$APP_URL（由调用方传入）\"\nelif [ -f \"$_ROOT/package.json\" ] && (cd \"$_ROOT\" && npm run 2>/dev/null | grep -q \"dev:status\"); then\n  (cd \"$_ROOT\" && npm run dev:status)\n  echo \"  未传 APP_URL：如需浏览器验收，请使用 dev:status 输出中的 Frontend URL 重新调用 forge-qa。\"\nelif [ -x \"$_ROOT/scripts/dev-stack.sh\" ]; then\n  (cd \"$_ROOT\" && bash scripts/dev-stack.sh status)\n  echo \"  未传 APP_URL：如需浏览器验收，请使用 dev-stack status 输出中的 Frontend URL 重新调用 forge-qa。\"\nelse\n  for port in 3000 3456 4000 5173 8080 8081; do\n    curl -s -o /dev/null -w \"%{http_code}\" \"http://localhost:$port\" 2>/dev/null | grep -qE \"200|301|302|304\" && echo \"  http://localhost:$port ✓（旧项目兜底探测）\"\n  done\nfi\n\n# === 报告目录 ===\nREPORT_DIR=\"$_ROOT/.gstack/qa-reports\"\nmkdir -p \"$REPORT_DIR/screenshots\" 2>/dev/null\necho \"报告目录: $REPORT_DIR\"\n```\n\n---\n\n## AskUserQuestion 格式规范\n\n每次提问结构：\n1. **重新聚焦**：当前项目、分支、正在测试的功能\n2. **通俗解释**：高中生能懂的语言描述问题\n3. **给出建议**：推荐选项 + 完整度评分\n4. **列出选项**：`A) B) C)` + 工作量估算\n\n---\n\n## 第0步：上下文探测与环境准备\n\n### 0.1 Worktree 检测（铁律：在正确的分支上测试）\n\n按优先级检测工作环境：\n\n1. **forge-dev 调度传入**：如果 Agent prompt 中包含 `worktree_path`，直接 `cd` 进入\n2. **当前目录检测**：前置脚本已检测 `_IN_WORKTREE`，如果是则直接使用\n3. **扫描已有 worktree**：`git worktree list` 查找最近的 `eng/*` 分支\n4. **当前分支为 feature 分支**：如果当前在 `eng/*` 或非 `main` 分支，可以直接测试\n5. **询问用户**：如果当前在 main 且无 worktree，通过 AskUserQuestion 询问\n\n确认后输出：\n```\n🔧 测试环境：\n  Worktree: /path/to/.worktrees/feature-slug (或 \"当前目录\")\n  Branch:   eng/feature-slug-2026-03-28\n  Base:     main\n```\n\n### 0.2 文档链定位\n\n按搜索模式定位所有参考文档，forge-dev 传入的路径优先级最高：\n\n```bash\n# PRD\nfor f in docs/PRD.md PRD.md docs/*PRD*; do [ -f \"$f\" ] && echo \"PRD: $f\" && break; done\n\n# DESIGN\nfor f in DESIGN.md docs/DESIGN.md docs/DESIGN-BLUEPRINT.md; do [ -f \"$f\" ] && echo \"DESIGN: $f\" && break; done\n\n# ENGINEERING\nfor f in docs/ENGINEERING.md ENGINEERING.md; do [ -f \"$f\" ] && echo \"ENGINEERING: $f\" && break; done\n\n# FEEDBACK（历史用户反馈，回归测试用）\nfor f in FEEDBACK.md docs/FEEDBACK.md; do [ -f \"$f\" ] && echo \"FEEDBACK: $f\" && break; done\n\n# QA\nfor f in docs/QA.md QA.md; do [ -f \"$f\" ] && echo \"QA: $f\" && break; done\n\n# .features/status\nls .features/*/status.md 2>/dev/null | head -5\n```\n\n**文档版本校验**：读取文档后提取版本号，与 `.features/status.md` 中记录的 PRD 版本对比。不一致则警告。\n\n**降级模式**：如果找不到 PRD/DESIGN → 降级为\"无文档模式\"（只做 console + 响应式 + 可访问性基础测试）。\n\n### 0.3 变更范围分析\n\n```bash\n# 基准分支\nBASE=$(gh pr view --json baseRefName -q .baseRefName 2>/dev/null || echo \"main\")\n\n# 变更文件列表\ngit diff $BASE...HEAD --name-only 2>/dev/null\ngit diff $BASE...HEAD --stat 2>/dev/null\n\n# 变更摘要\ngit log $BASE..HEAD --oneline 2>/dev/null\n```\n\n变更文件 → 推断影响范围 → 决定测试重点（Diff-aware 模式）。\n\n### 0.4 选择器审计（铁律：不盲猜选择器）\n\n**在生成 test-spec 前，必须扫描代码确认可用选择器。** 不同项目的 DOM 结构完全不同，不能假设任何 `data-testid` 或 ARIA 属性存在。\n\n```bash\n# 扫描项目中可用的选择器锚点\necho \"=== data-testid ===\"\ngrep -r 'data-testid' src/ --include='*.tsx' --include='*.jsx' --include='*.vue' --include='*.html' -l 2>/dev/null | head -10\n\necho \"=== data-* 属性 ===\"\ngrep -roh 'data-[a-z_-]*=' src/ --include='*.tsx' --include='*.jsx' --include='*.vue' -h 2>/dev/null | sort -u | head -20\n\necho \"=== ARIA 属性 ===\"\ngrep -roh 'role=\"[^\"]*\"\\|aria-[a-z]*=' src/ --include='*.tsx' --include='*.jsx' --include='*.vue' -h 2>/dev/null | sort -u | head -20\n\necho \"=== 语义化 HTML ===\"\ngrep -roh '<\\(nav\\|main\\|aside\\|header\\|footer\\|section\\|article\\|dialog\\)[> ]' src/ --include='*.tsx' --include='*.jsx' --include='*.vue' -h 2>/dev/null | sort | uniq -c | sort -rn | head -10\n```\n\n**根据扫描结果决定选择器策略：**\n\n| 项目状态 | 选择器策略 | test-spec 中使用 |\n|---------|-----------|----------------|\n| 有丰富 `data-testid` | 直接使用 testid | `[data-testid='feed-section']` |\n| 有 `data-*` 属性但非 testid | 使用已有 data 属性 | `[data-platform='twitter']`, `[data-item-id]` |\n| 有 ARIA 属性 | 使用 role + aria | `[role='tab']`, `[aria-selected='true']` |\n| 有语义化 HTML | 使用语义标签 | `main`, `nav`, `dialog` |\n| 以上都没有 | **文本 + CSS 组合** | `button:has-text(\"搜索\")`, `.card-container > .card:nth-child(1)` |\n\n**选择器优先级（从稳定到脆弱）：**\n\n```\n1. getByRole('tab', { name: '推荐' })    ← 最稳定，语义化\n2. [data-testid='feed-section']           ← 专为测试设计\n3. [data-platform='twitter']              ← 业务语义属性\n4. [role='dialog']                        ← ARIA 属性\n5. button:has-text(\"搜索\")                ← 可见文本\n6. main > section:first-child             ← 结构选择器\n7. .bg-card.rounded-lg                    ← CSS class（最脆弱）\n```\n\n**如果项目零 data-testid：**\n- **不要在 test-spec 中编造 `data-testid`**——这会导致所有测试因选择器找不到而假性 FAIL\n- 使用上述优先级中实际存在的选择器\n- 在 QA 报告的\"改进建议\"中标注：建议 forge-eng 在关键交互元素上补充 `data-testid`\n\n**输出选择器映射表**（供 test-spec 生成时引用）：\n\n```\n🔍 选择器审计结果：\n  data-testid: 0 个（项目未使用 testid）\n  data-* 属性: data-platform, data-item-id, data-section\n  ARIA: role=\"dialog\" (1处), role=\"button\" (3处)\n  语义标签: main, nav, section, header\n\n  推荐策略：data-* 属性 + 文本选择器 + 语义标签组合\n\n  关键元素映射：\n  ├── 信息卡片: [data-platform] 或 .cursor-pointer:has(h3)\n  ├── 详情面板: [role=\"dialog\"] 或 [class*=\"detail\"]\n  ├── Tab 导航: button:has-text(\"推荐\") 等\n  └── 搜索框: input[type=\"search\"] 或 input[placeholder*=\"搜索\"]\n```\n\n### 0.5 测试级别与模式\n\n**测试级别**（如用户未指定，通过 AskUserQuestion 确认）：\n\n- A) **快速** — 只测 P0 核心流程（约5-10分钟）→ Phase 1+2\n- B) **标准** — 快速 + P1 视觉/响应式（约15-30分钟）→ Phase 1+2+3\n- C) **详尽** — 标准 + P2-P3 可访问性和边界（约30-60分钟）→ Phase 1+2+3+4\n\n**测试模式**（自动选择）：\n\n| 模式 | 触发条件 | 行为 |\n|------|---------|------|\n| **Diff-aware** | 在 feature 分支且有 base diff | 从 diff 推断影响范围，聚焦测试 |\n| **Full** | 指定了 URL 或用户要求 | 系统性遍历所有页面 |\n| **Regression** | 存在 FEEDBACK.md 或历史 QA 报告 | 优先测试历史反馈项 + 变更回归 |\n\n---\n\n## 第1步：建立健康基准\n\n**在测试前打分（0-100分）：**\n\n| 维度 | 权重 | 评估方式 |\n|------|------|---------|\n| 控制台错误 | 15% | JS 错误数量（0→100, 1-3→70, 4-10→40, 10+→10）|\n| 链接完整性 | 10% | 死链数量（每个 -15，最低 0）|\n| 核心功能 | 20% | 主要用户流程是否可用 |\n| 视觉呈现 | 10% | 页面布局、样式是否正确 |\n| 用户体验 | 15% | 交互流畅度、反馈及时性 |\n| 性能 | 10% | 首屏加载、LCP、CLS |\n| 内容 | 5% | 文案、数据展示是否正确 |\n| 无障碍 | 15% | 键盘导航、对比度、语义化 |\n\n使用 gstack/browse 或 Playwright 截取基准截图和控制台状态。\n\n---\n\n## 第2步：理解现状\n\n### 迭代模式（已有 QA.md）\n1. 读取 PRD 最新迭代摘要，提取验收标准\n2. 读取 ENGINEERING.md，提取 API 契约和测试矩阵\n3. 读取 DESIGN.md，提取视觉硬规则（字号、颜色、间距）\n4. 读取 FEEDBACK.md（如有），提取历史用户反馈 → 纳入回归基线\n5. 读取 QA.md + QA CHANGELOG，做热点分析\n6. 向用户总结当前状态\n\n### 从零创建模式（无 QA.md）\n1. 分析项目测试现状（检查 tests/、覆盖率、CI 配置）\n2. 与用户多轮确认（测试策略、范围、验收标准）\n3. 产出 QA.md 初稿（参考 [references/qa-template.md](references/qa-template.md)）\n\n---\n\n## 第2.5步：生成 test-spec（铁律：不生成就不执行）\n\n### 输入 → 输出映射\n\n| 输入源 | 提取内容 | 转化为 |\n|--------|---------|-------|\n| PRD 验收标准 | \"用户点击卡片，弹出详情面板\" | `functional` 断言 |\n| DESIGN.md 规则 | \"最小字号 12px\"、\"4px 间距网格\" | `visual` CSS 断言 |\n| ENGINEERING.md API | \"GET /api/feed → { items: [...] }\" | `network` 断言 |\n| git diff | \"修改了 DetailPanel.tsx\" | `regression` 聚焦断言 |\n| 会话上下文 | \"刚实现了频道切换功能\" | `functional` 断言 |\n| FEEDBACK.md | 历史用户反馈 | `regression` 回归断言 |\n\n### test-spec.json 结构\n\n**重要：选择器必须来自 Step 0.4 的审计结果，不能编造不存在的 `data-testid`。** 下面的示例用 `$SELECTOR_*` 占位符表示\"根据审计结果填充实际选择器\"。\n\n```json\n{\n  \"metadata\": {\n    \"source\": \"PRD.md v10.1 + DESIGN.md v2\",\n    \"branch\": \"eng/feature-slug-2026-03-28\",\n    \"generated_at\": \"2026-03-28T10:00:00Z\",\n    \"scope\": \"full | diff-aware | regression\",\n    \"app_url\": \"http://localhost:8080\",\n    \"selector_strategy\": \"data-* + text + semantic\"\n  },\n  \"selector_map\": {\n    \"_comment\": \"Step 0.4 审计产出，所有 case 引用此映射\",\n    \"feed_section\": \"main > section:first-child\",\n    \"info_card\": \".cursor-pointer:has(h3)\",\n    \"detail_panel\": \"[role='dialog']\",\n    \"tab_nav\": \"nav button\",\n    \"search_input\": \"input[placeholder*='搜索']\"\n  },\n  \"suites\": [\n    {\n      \"id\": \"feed-display\",\n      \"name\": \"信息流展示\",\n      \"source_ref\": \"PRD.md#v10.0-信息流\",\n      \"priority\": \"P0\",\n      \"cases\": [\n        {\n          \"id\": \"feed-001\",\n          \"description\": \"首页加载后展示信息卡片\",\n          \"dimension\": \"functional\",\n          \"steps\": [\n            { \"action\": \"navigate\", \"url\": \"/\" },\n            { \"action\": \"wait\", \"selector\": \"main > section:first-child\", \"timeout\": 8000 }\n          ],\n          \"assertions\": [\n            { \"type\": \"visible\", \"selector\": \"main > section:first-child\" },\n            { \"type\": \"count_gte\", \"selector\": \".cursor-pointer:has(h3)\", \"min\": 1 },\n            { \"type\": \"contains_text\", \"selector\": \"main\", \"texts\": [\"$EXPECTED_SECTION_TITLE\"] },\n            { \"type\": \"no_console_errors\" }\n          ]\n        },\n        {\n          \"id\": \"feed-002\",\n          \"description\": \"卡片点击→详情面板，验证内容完整性（数据驱动）\",\n          \"dimension\": \"data-driven\",\n          \"data_driven\": {\n            \"selector\": \".cursor-pointer:has(h3)\",\n            \"sample_size\": 15,\n            \"strategy\": \"stratified\"\n          },\n          \"steps\": [\n            { \"action\": \"click\", \"selector\": \"$item\" },\n            { \"action\": \"wait\", \"selector\": \"[role='dialog']\", \"timeout\": 5000 }\n          ],\n          \"assertions\": [\n            { \"type\": \"visible\", \"selector\": \"[role='dialog']\" },\n            { \"type\": \"evaluate\", \"description\": \"详情面板有标题且文本长度 > 0\",\n              \"script\": \"const panel = document.querySelector('[role=\\\"dialog\\\"]'); const title = panel?.querySelector('h2, h3'); if (!title || title.textContent.trim().length === 0) throw new Error('详情面板标题为空')\" },\n            { \"type\": \"evaluate\", \"description\": \"详情面板有实质内容（不只是骨架屏）\",\n              \"script\": \"const panel = document.querySelector('[role=\\\"dialog\\\"]'); const textLen = panel?.innerText?.trim().length || 0; if (textLen < 50) throw new Error(`面板内容过短: ${textLen} 字符`)\" },\n            { \"type\": \"no_console_errors\" }\n          ]\n        }\n      ]\n    }\n  ]\n}\n```\n\n**选择器规则**（参考 Step 0.4 审计 + Playwright 最佳实践）：\n- 只使用审计中确认存在的选择器，**绝不编造不存在的 `data-testid`**\n- 优先级：`role/aria` > `data-*` 属性 > 语义标签 > 可见文本 > CSS class 组合\n- 如果项目缺乏稳定选择器，在 QA 报告的\"改进建议\"中提出，交由 forge-eng 补充\n\n### 断言深度规则（铁律 4 的展开）\n\n**核心原则：\"it renders\" ≠ \"it works correctly\"。**\n\n每个 test case 的 assertions 数组必须包含至少一个**深层断言**。`visible` 和 `count_gte` 只能作为前置条件（确认元素在 DOM 中），不能作为验收断言。\n\n#### ❌ 反面示例（浅断言 — 只验证\"存在\"不验证\"正确\"）\n\n```json\n{\n  \"id\": \"starred-001\",\n  \"description\": \"收藏页展示收藏的卡片\",\n  \"assertions\": [\n    { \"type\": \"visible\", \"selector\": \"section.starred-view\" },\n    { \"type\": \"count_gte\", \"selector\": \".cursor-pointer:has(h3)\", \"min\": 1 }\n  ]\n}\n```\n问题：只验证了\"收藏页有卡片\"，没验证卡片**确实是收藏的**、内容**确实渲染了**。\n\n#### ✅ 正面示例（深层断言 — 验证数据正确性和功能完整性）\n\n```json\n{\n  \"id\": \"starred-001\",\n  \"description\": \"收藏页展示收藏的卡片\",\n  \"assertions\": [\n    { \"type\": \"visible\", \"selector\": \"section.starred-view\" },\n    { \"type\": \"count_gte\", \"selector\": \".cursor-pointer:has(h3)\", \"min\": 1 },\n    { \"type\": \"evaluate\", \"description\": \"每张卡片有标题且标题非空\",\n      \"script\": \"const cards = document.querySelectorAll('.cursor-pointer:has(h3)'); cards.forEach((c, i) => { const title = c.querySelector('h3'); if (!title || title.textContent.trim().length === 0) throw new Error(`第 ${i+1} 张卡片标题为空`) })\" },\n    { \"type\": \"evaluate\", \"description\": \"收藏页卡片数量与页面显示的统计数一致\",\n      \"script\": \"const displayed = document.querySelectorAll('.cursor-pointer:has(h3)').length; const header = document.querySelector('h2, [class*=\\\"header\\\"]')?.textContent || ''; const match = header.match(/(\\\\d+)/); if (match && displayed !== parseInt(match[1])) throw new Error(`显示 ${displayed} 张但标题显示 ${match[1]}`)\" }\n  ]\n}\n```\n\n#### 更多断言深度检查表（生成 test-spec 时逐条对照）\n\n| 测试场景 | 浅断言（❌ 不够） | 深层断言（✅ 必须） |\n|---------|-----------------|-------------------|\n| 详情/弹窗 | `panel.isVisible()` | `panel.innerText.length > 50` + 包含标题/关键区块 |\n| 列表/收藏 | `cards.count() > 0` | 每张卡片有标题且非空，数量与页头统计一致 |\n| Tab/频道切换 | `section.isVisible()` | 切换后内容区文本变化（不是切前的旧内容） |\n| SSE/流式生成 | `button.isVisible()` | 触发 → 中间态可观测 → 完成后结果持久化（reload 仍在） |\n| 搜索/过滤 | `results.isVisible()` | 结果包含关键词，数量合理，空结果有空状态提示 |\n| 模态框/对话框 | `dialog.isVisible()` | 有标题 + 正文文本长度 > 0 + Escape 可关闭 |\n| 表单提交 | `form.isVisible()` | 填充 → 提交 → 反馈出现（toast/跳转/数据变化） |\n| URL/深度链接 | `page.loaded()` | 直接访问带参数的 URL → 视图状态与参数一致 |\n| 懒加载内容 | `skeleton.gone()` | 等待加载完成 → 内容非空 → 数量/值与预期一致 |\n\n#### 自检规则\n\n生成 test-spec 后，**自动扫描**所有 case：\n- 如果某个 case 的 assertions 只有 `visible`/`count_gte`/`hidden` 类型 → **标记为 ⚠️ 浅断言**，必须补充深层断言\n- 如果某个 case 没有任何 `contains_text`/`evaluate`/`has_attribute`/`css_value`/`matches_regex` → **拒绝执行**，回到 test-spec 生成步骤补充\n\n### test-spec 不是手写的\n\ntest-spec 由 Claude 基于文档理解自动生成，但它是**结构化的、可审查的**。生成后必须输出摘要供用户确认。\n\n---\n\n## 第3步：生成验收计划并请用户确认\n\n**铁律：不是技术 test-spec 的摘要，而是用户可读的验收计划。** 用户需要先理解\"要验什么\"，才能判断测试是否充分。\n\n### 3.1 检查 Feature Spec\n\n读取 PRD 中的 Feature Spec 章节。如果存在：\n- 从 Feature Spec 的验收检查表提取所有验收项\n- 将 Given/When/Then 场景映射为 test-spec 用例\n- Feature Spec 的验收检查表是 QA 的**主要输入**，test-spec 的每个用例 SHALL 可追溯到 Feature Spec 中的某个场景\n\n如果 Feature Spec 不存在：\n- 通过 AskUserQuestion 警告：「PRD 中没有 Feature Spec，QA 将基于 PRD 功能描述生成测试，但验收标准可能不够精确。建议先运行 /forge-prd 补充 Feature Spec。」\n- 如果用户选择继续，降级为从 PRD 功能描述 + DESIGN.md 提取验收项\n\n### 3.2 生成验收计划文档\n\n基于 Feature Spec（或降级来源），生成一份**先全局后细节**的验收计划：\n\n```markdown\n## QA 验收计划：{功能名}\n\n### 全局验证（先看整体是否符合预期）\n\n#### 用户流程完整性（对标 Feature Spec 第一节）\n- [ ] 用户流程从 {入口} 到 {出口} 无断点\n- [ ] 异常路径均有对应的错误处理\n- [ ] 流程图中的每个步骤在实际页面中都可达\n\n#### 页面/系统结构合规性（对标 Feature Spec 第二节）\n- [ ] 整体布局与 Feature Spec 的结构图一致\n- [ ] 各区块职责与描述匹配\n- [ ] 组件列表完整，无遗漏无多余\n\n---\n\n### 逐项验证（再看具体细节）\n\n| # | 验收项 | 来源 | 测试方法 | 断言类型 |\n|---|--------|------|---------|---------|\n| 1 | {场景描述} | Feature Spec: {Requirement名}.正常 | {Playwright/gstack} | {contains_text/css_value/...} |\n| 2 | {场景描述} | Feature Spec: {Requirement名}.异常 | ... | ... |\n| ... | ... | ... | ... | ... |\n\n---\n\n### 视觉合规验证（对标 DESIGN.md + Feature Spec CSS 约束）\n\n| # | 组件 | CSS 属性 | 预期值 | 断言方式 |\n|---|------|---------|--------|---------|\n| V1 | {组件名} | font-size | {值} | css_value |\n| V2 | {组件名} | color | {值} | css_value |\n| V3 | {组件名} | padding | {值} | css_value |\n| ... | ... | ... | ... | ... |\n\n如果存在 Image 2 视觉稿、`.do-dev/visual-decision.md` 或 `.deliver/visual-decision.md`，在计划中单列「视觉意图参考」：说明会用真实浏览器截图对比信息层级、密度、主操作和空态/错态覆盖。Image 2 不作为 pass/fail 证据，pass/fail 只来自 Feature Spec、DESIGN.md、CSS 属性、行为断言和真实截图。\n\n---\n\n共 {N} 项验收（功能 {X} 项 + 视觉 {Y} 项 + 流程 {Z} 项），预计 {时间}。\n```\n\n### 3.3 用户确认\n\n通过 AskUserQuestion 展示验收计划摘要并等待确认：\n\n```\n📋 验收计划已生成（基于 Feature Spec + DESIGN.md）\n\n全局验证：\n  - 用户流程完整性：{步骤数} 步\n  - 页面结构合规性：{区块数} 区块，{组件数} 组件\n\n逐项验证：\n  - 功能场景：{X} 项（{功能点数} 个功能点 × 3 场景）\n  - 视觉合规：{Y} 项（CSS 属性断言）\n  - 流程完整：{Z} 项\n\nA) 确认执行\nB) 需要增减测试项（说明哪些）\nC) 需要看完整验收计划再决定\nD) Feature Spec 有误，需要先修正\n```\n\n**⚠️ 用户确认后才执行测试。**\n\n---\n\n## 第4步：更新 QA 文档\n\n1. 更新/创建 QA.md（参考 [references/qa-template.md](references/qa-template.md)）\n2. 更新 QA CHANGELOG\n3. 将 test-spec.json 保存到报告目录\n\n---\n\n## 第5步：7 维度测试执行\n\n**使用 qa-runner.mjs 框架。** 详细代码模板参考 [references/test-dimensions.md](references/test-dimensions.md)。\n\n### 测试脚本编写规范\n\n**必须使用 qa-runner.mjs 框架**，不从零写脚本：\n\n```javascript\nimport { TestCollector, attachMonitors, snap, snapElement, createPage, pickStratified, writeResults } from '$QA_RUNNER';\n\nconst collector = new TestCollector();\nconst { browser, page } = await createPage();\nattachMonitors(page, collector);\n\n// ... 测试逻辑（使用 collector.pass/fail/skip）...\n\ncollector.printSummary();\nwriteResults(collector);\nawait browser.close();\nprocess.exit(collector.summary().failed > 0 ? 1 : 0);\n```\n\n**`$QA_RUNNER` 替换为前置脚本检测到的路径。**\n\n### 执行分阶段（快速失败）\n\n```\nPhase 1 冒烟（所有级别都执行）\n  ├── 控制台零容忍 [console]：page.on('pageerror') + page.on('console error')\n  ├── 首页加载：导航 → 等待 → 断言核心元素可见\n  └── API/网络基础 [network]：检查 /api/* 状态码 < 400\n  → 如果 Phase 1 全 FAIL → 停止测试（环境问题），报告并退出\n\nPhase 2 核心功能（快速+标准+详尽）\n  ├── 交互完整性 [functional]：Tab 切换、按钮点击、模态框开关\n  ├── 数据驱动遍历 [data-driven]：采样 N 个元素，逐一验证\n  ├── SSE/流式生成 [streaming]：全链路（触发→中间态→完成→持久化），有 SSE 时启用\n  ├── URL 状态 [url-state]：正反向验证（操作→URL + URL→视图恢复），有路由状态时启用\n  └── 懒加载/异步 [async-content]：加载态→内容验证→分页/进度，有异步加载时启用\n  → 覆盖 P0 用例\n\nPhase 3 视觉+响应式（标准+详尽）\n  ├── 视觉规则断言 [visual]：CSS 属性验证（字号、颜色、间距）\n  └── 响应式断点 [responsive]：375/768/1440 三个视口\n  → 覆盖 P1 用例\n\nPhase 4 深度（仅详尽级别）\n  ├── 可访问性 [accessibility]：axe-core WCAG 2.0 AA\n  └── 边界条件：空数据、超长文本、网络异常\n  → 覆盖 P2-P3 用例\n```\n\n### 7 维度概述\n\n#### 维度 1: 控制台零容忍 [console]\n\n`attachMonitors()` 自动挂载。每个导航/交互后通过 `collector.checkConsoleErrors()` 检查。\n任何 `pageerror` = 自动 FAIL，包含错误文本和 stack trace。\n\n**能发现**：React 渲染崩溃、未捕获异常、404 资源\n**不能发现**：被 try-catch 包裹的静默错误\n\n#### 维度 2: 数据驱动遍历 [data-driven]\n\n不测 1 个元素，采样 N 个。使用 `pickStratified()` 分层采样（首尾 + 均匀分布）。\n每个元素独立 pass/fail，统计崩溃率并推算总体影响。\n\n**能发现**：27% 卡片因数据类型不一致崩溃（当前完全测不到的）\n**不能发现**：需要特定数据组合才触发的 bug\n\n#### 维度 3: 网络契约验证 [network]\n\n`attachMonitors()` 自动收集 `/api/*` 响应。断言：状态码 < 400 + 响应结构匹配。\n如果 ENGINEERING.md 定义了 API schema，验证响应 JSON 结构。\n\n**能发现**：API 404、响应结构变更、后端未启动\n**不能发现**：语义正确但数据错误的响应\n\n#### 维度 4: 视觉规则断言 [visual]\n\n从 DESIGN.md 提取硬规则 → CSS 断言。使用 `page.evaluate(el => getComputedStyle(el))`。\n检查项：字号 ≥ 12px、间距遵循 4px 网格、平台配色正确。\n如果有 Image 2 视觉稿，仅用作解释偏差的参考，不能替代 CSS 断言或真实截图。\n\n**能发现**：字号不达标、间距违规、颜色错误\n**不能发现**：\"看起来不对但 CSS 值合规\"的美学问题\n\n#### 维度 5: 交互完整性 [functional]\n\n每个可交互元素：操作 → 状态变化断言 → 可逆性验证。\nTab: `click → aria-selected === true → panel visible`\n模态框: `click → modal visible → Escape → modal gone`\n\n**能发现**：Tab 崩溃、按钮无响应、模态框不可关闭\n**不能发现**：交互流畅度、动画是否自然\n\n#### 维度 6: 响应式断点 [responsive]\n\n三个断点：mobile(375×812) / tablet(768×1024) / desktop(1440×900)。\n每个断点检查：无水平溢出 + 触控目标 ≥ 44px + 截图留证。\n\n#### 维度 7: 可访问性 [accessibility]\n\naxe-core WCAG 2.0 AA 扫描 + 键盘导航验证（Tab 遍历 + Enter 激活 + Escape 关闭）。\n\n#### 维度 8: SSE / 流式生成全链路 [streaming]\n\n**适用条件**：项目包含 SSE 端点、WebSocket、流式 AI 生成等实时特性。通过 Step 0.4 扫描 `EventSource`、`fetch.*stream`、`WebSocket` 判断是否启用。\n\n测试全生命周期，不只是\"按钮存在\"：\n\n```\n触发入口（按钮/表单）→ 中间态（loading/thinking/progress）→ 数据流（逐步到达）→ 完成态 → 持久化验证（reload 后数据仍在）\n```\n\n关键断言：\n- 触发后：中间态 UI 出现（spinner/进度条/thinking 动画），按钮变为不可操作\n- 流式期间：内容区逐步增长（`textContent.length` 单调递增）\n- 完成后：loading 消失，最终内容完整渲染\n- 取消/中断：如果有取消按钮，点击后回到 idle 态，无残留\n- **持久化**：刷新页面后，生成的内容仍然存在（最关键的深层断言）\n- 错误恢复：模拟网络中断（`page.route` 拦截 → abort），UI 显示错误态而非卡死\n\n#### 维度 9: URL 状态 / 深度链接 [url-state]\n\n**适用条件**：项目使用 hash 路由（`#view=xxx`）、query 参数（`?tab=xxx`）、或 SPA 路由（`/page/xxx`）管理视图状态。通过 Step 0.4 扫描 `useHash`、`useRouter`、`history.pushState`、`window.location.hash` 判断是否启用。\n\n测试双向一致性：\n\n```\n操作 → URL 变化        （正向：UI 操作驱动 URL 更新）\nURL → 视图恢复         （反向：直接访问 URL 恢复完整状态）\n```\n\n关键断言：\n- **正向**：点击 Tab/频道/卡片 → `page.url()` 包含对应参数\n- **反向**：直接 `page.goto(url_with_params)` → 视图状态正确恢复（Tab 选中、内容加载）\n- **深度链接**：带完整参数的 URL（如 `#l1=recommend&d=item-123`）→ 详情面板自动打开，内容正确\n- **浏览器前进/后退**：`page.goBack()` / `page.goForward()` → 视图正确切换\n- **边界**：无效参数的 URL（如 `#d=nonexistent-id`）→ 优雅降级，不白屏\n\n#### 维度 10: 懒加载 / 异步内容 [async-content]\n\n**适用条件**：项目包含分页加载、无限滚动、骨架屏、点击后异步获取详情等模式。几乎所有现代 SPA 都适用。\n\n测试加载全生命周期：\n\n```\n触发加载 → 加载态（skeleton/spinner）→ 内容到达 → 加载态消失 → 内容正确\n```\n\n关键断言：\n- **等待策略**：不用 `waitForTimeout` 硬等，使用 `waitForResponse` 或 `waitForSelector` 等具体条件\n- **骨架屏消失**：如果有 skeleton，等待 `.skeleton` 消失再断言内容\n- **内容非空**：加载完成后，内容区 `textContent.length > 0`（不只是 skeleton 被替换为空 div）\n- **分页/进度**：如果有进度提示（\"加载中 500/10740\"），验证进度文本格式正确，全部加载完成后进度消失\n- **滚动加载**：`page.mouse.wheel` 或 `scrollIntoView` 触发加载 → 新内容出现 → 总量增加\n- **加载失败**：`page.route` 拦截 API 返回 500 → 显示错误提示而非无限 loading\n\n**通用等待模式**（替代 `waitForTimeout`）：\n\n```javascript\n// ❌ 硬等（不可靠，慢）\nawait page.waitForTimeout(3000);\n\n// ✅ 等 API 响应（精确）\nawait page.waitForResponse(resp => resp.url().includes('/api/feed') && resp.status() === 200);\n\n// ✅ 等骨架屏消失（语义化）\nawait page.waitForSelector('.skeleton', { state: 'hidden', timeout: 10000 });\n\n// ✅ 等内容出现（直接）\nawait page.waitForSelector('main .cursor-pointer:has(h3)', { timeout: 10000 });\n\n// ✅ 等网络空闲（兜底）\nawait page.waitForLoadState('networkidle');\n```\n\n### Codex Browser Use 引擎（用户视角浏览器验收）\n\n在 Codex 环境中，如果 Browser Use 插件可用，前端页面、交互、视觉、控制台检查优先使用 `browser-use:browser`：\n\n- 使用 Codex in-app browser 打开调用方传入的 `APP_URL`\n- 通过 DOM snapshot 构造稳定 locator，不盲猜选择器\n- 每次点击、输入、切换、提交后采集最小必要状态：DOM snapshot 或截图\n- 关键状态节点截图保存到 QA 报告或 Bug 修复验收报告指定目录，并用 Markdown 内嵌\n- 读取 console logs，任何 error 进入 FAIL\n- 如果代码或 build 刚变更，测试本地页面前先 reload，再重新采集 DOM/screenshot\n\n使用规则：\n\n1. 执行浏览器动作前必须先加载并遵守 `browser-use:browser` skill。\n2. 初始化 Browser 时使用 `iab` backend 和 Node REPL 的 browser-client runtime。\n3. 不用 Computer Use 操作浏览器，除非 Browser Use 不可用、被中断或目标不是浏览器页面；兜底原因必须写入报告。\n4. Browser Use 负责用户视角证据，仍需配合断言。截图不能单独作为 PASS。\n5. 需要可重复批量回归时，Browser Use 证据可与 Playwright 脚本断言并行使用。\n\n### gstack/browse 引擎（快速探索和截图标注）\n\n当 gstack/browse 可用时，可作为 Playwright 的补充：\n\n```bash\n$B goto <URL>\n$B snapshot -i -a     # 标注所有可交互元素\n$B console --errors   # 控制台错误\n$B network            # 网络请求\n$B perf               # LCP、CLS 性能\n$B screenshot $REPORT_DIR/screenshots/overview.png\n$B responsive         # 三视口截图\n```\n\n**引擎协同**：\n- browser-use:browser：Codex in-app browser 用户视角操作、DOM 快照、截图证据\n- Playwright + qa-runner：结构化断言、数据驱动、网络拦截、可重复回归\n- gstack/browse：快速探索、截图标注、性能指标\n\n### 纯代码测试（无浏览器引擎时）\n\n- 逐文件读取实现代码，检查边界情况\n- 验证错误处理完整性\n- 检查 API 输入验证\n- 运行项目已有的测试框架（`npm test` / `pytest` 等）\n\n---\n\n## 第6步：智能分析 + Bug 报告\n\n### 分析流程\n\n对每个 FAIL 的测试用例：\n\n1. **错误分类**\n   - Console Error → 提取 stack trace → 定位源文件:行号\n   - 元素不存在 → 检查选择器 → 检查组件是否渲染\n   - 网络错误 → 检查后端日志 → 检查 API 路由\n   - 视觉偏差 → 检查 CSS 来源 → 对比 DESIGN.md 规则\n\n2. **交叉验证**\n   - 将 console error 中的文件路径 → 对应到 git diff 中的变更文件\n   - 在 diff 中 → 标记 `[本次引入]`\n   - 不在 diff 中 → 标记 `[已有问题]`\n\n3. **影响范围估算**\n   - data-driven 测试：5/20 崩溃 → 推算 25% 数据受影响\n   - 功能测试：特定 tab 崩溃 → 标记该 tab 下所有功能受影响\n\n### Bug 登记格式\n\n```markdown\n### BUG-001 [严重度] 标题\n\n**现象：** 用户看到了什么\n**影响：** 影响范围（如\"25% 的卡片无法打开详情\"）\n**证据：**\n  - Console: \"错误信息原文\"\n  - Stack: `文件:行号`\n  - 截图: qa_screenshots/XX_name.png\n**根因定位：**\n  - 文件: `src/components/DetailPanel.tsx:360`\n  - 原因: 一句话说明\n**本次引入：** 是/否（基于 git diff 交叉引用）\n**修复建议：** 简要描述修复思路\n```\n\n### 严重度分类\n\n| 严重度 | 定义 | 处理 |\n|--------|------|------|\n| 严重 | 核心功能崩溃/不可用 | 必须修复 |\n| 高 | 功能可用但结果错误 | 必须修复 |\n| 中 | 功能可用但体验差 | 建议修复 |\n| 低 | 外观/措辞/细节问题 | 可延后 |\n\n### 修复清单产出\n\n```markdown\n# 修复清单（forge-qa 生成）\n\n## 必须修复（严重 + 高）\n- [ ] BUG-001: {现象} — {文件:行号} — {修复方向}\n- [ ] BUG-002: ...\n\n## 建议修复（中）\n- [ ] BUG-003: ...\n\n## 可延后（低）\n- [ ] BUG-005: ...\n```\n\n### QA 自动闭环交付给 forge-bugfix\n\n当 forge-qa 处于功能开发后的自动闭环场景，发现属于本轮 Feature Spec 或本次 diff 引入的 bug 时，不能只写散文报告，必须为 forge-bugfix 准备结构化输入：\n\n```markdown\n### BF-CANDIDATE: {标题}\n\n**建议严重度**：P0 / P1 / P2\n**是否属于本轮范围**：是 / 否 / 待用户判断\n**关联 Feature Spec**：docs/PRD.md#...\n**用户可见现象**：...\n**复现步骤**：\n1. ...\n2. ...\n3. ...\n**前端地址**：...\n**后端/API 地址**：...\n**环境身份摘要**：Frontend PID/cwd, Backend PID/cwd, commit\n**截图证据**：\n![](./qa_screenshots/BUG-001-step-01.png)\n![](./qa_screenshots/BUG-001-step-02.png)\n**深度断言失败**：文本/状态/URL/CSS/网络/数据断言摘要\n**console/network 证据**：...\n**建议交给 forge-bugfix 的原因**：...\n```\n\n调度层或 forge-dev 可以把这些候选写入 `docs/bugfix/backlog.md`，创建对应 `docs/bugfix/reviews/BF-XX.md`，然后逐个调用 forge-bugfix。forge-qa 自己仍然只测不修。\n\n自动闭环分类规则：\n\n| 分类 | 处理 |\n|---|---|\n| 属于本轮 Feature Spec / 本次 diff 引入 | 自动登记 BF，进入 forge-bugfix |\n| 回归破坏核心流程 | 自动登记 BF，进入 forge-bugfix |\n| 新需求或设计取舍 | 登记为待用户判断，不自动修 |\n| 范围外低优先级问题 | 登记 backlog，不阻塞本轮 |\n| 环境身份无法确认 | BLOCKED_HUMAN，不进入 bugfix |\n\n---\n\n## 第7步：User Gate（用户验收关卡）\n\n**铁律：不可跳过。** QA 自动化测试无法覆盖设计意图偏差、功能遗漏等只有用户能判断的问题。\n\n### 输出与等待\n\nQA 报告生成后，输出以下内容并等待用户操作：\n\n```\n╔══════════════════════════════════════════╗\n║           QA 报告已生成                   ║\n╠══════════════════════════════════════════╣\n║  通过: 10  失败: 3  跳过: 1              ║\n║  健康评分: 72/100                        ║\n║  报告: .gstack/qa-reports/qa-report-*.md ║\n╠══════════════════════════════════════════╣\n║  请验收后选择：                            ║\n║  A) 验收通过 → 进入发布流程                ║\n║  B) 验收不通过 → 填写反馈，回 forge-eng     ║\n║  C) 我需要先自己体验一下                    ║\n╚══════════════════════════════════════════╝\n```\n\n### 用户操作\n\n**A) 验收通过（accept）**\n- 更新 `.features/status.md` qa 行为 `[✅ 已完成]`\n- 建议下一步：`/forge-review` 或 `/forge-ship`\n\n**B) 验收不通过（reject）**\n- 引导用户描述问题（可以直接在会话中描述）\n- Claude 自动提取为 FEEDBACK.md 格式\n- **⚠️ 触发举一反三机制（见下方）**\n- 合并 qa-report 中未修复的 BUG + 用户 FEEDBACK + 举一反三发现\n- 生成统一修复清单 → `/forge-eng`\n\n### 举一反三机制（用户反馈问题时 SHALL 执行）\n\n当用户报告任何问题时，SHALL 按以下步骤执行：\n\n1. **修复用户指出的问题**\n\n2. **搜索相似模式**：\n   - 使用 Grep 在代码库中搜索与该问题相同的模式（同类 CSS 属性、同类组件、同类逻辑）\n   - 示例：用户报告「某组件间距不对」→ Grep 搜索所有使用相同 margin/padding 值的组件\n\n3. **回查 Feature Spec**：\n   - 读取 PRD 中的 Feature Spec，检查其他行为场景是否可能存在同类问题\n   - 检查验收检查表中未测试的项是否包含类似约束\n\n4. **产出「类似风险清单」**：\n   ```markdown\n   ### 举一反三：类似风险清单\n   \n   用户反馈：{用户描述的问题}\n   根因：{问题的根本原因}\n   \n   发现 {N} 处类似风险：\n   1. {文件路径:行号} — {组件/模块名} 使用了相同的 {模式}，可能存在同样问题\n   2. {文件路径:行号} — Feature Spec 场景 {场景名} 的 THEN 要求 {约束}，当前实现为 {实际值}\n   3. ...\n   ```\n\n5. **请用户确认**：\n   ```\n   发现 {N} 处类似风险，要一并修复吗？\n   A) 全部修复\n   B) 选择性修复（指定哪些）\n   C) 只修复用户指出的问题，其余记录到 FEEDBACK.md\n   ```\n\n**SHALL NOT 仅修复用户明确指出的单点问题就声称完成。**\n\n**C) 用户自行体验**\n- 暂停，等待用户回来反馈\n- 用户可以随时在会话中描述问题\n\n### FEEDBACK.md 结构\n\n```markdown\n# User Feedback — {feature-name}\n\n## 元数据\n- 日期: YYYY-MM-DD\n- QA 报告参考: qa-report-YYYY-MM-DD.md\n- 分支: eng/feature-name-YYYY-MM-DD\n\n## 反馈项\n\n### UF-001 [Design Intent] 标题\n**期望：** 用户期望的行为\n**现状：** 实际看到的行为\n**参考：** DESIGN.md#section 或 PRD.md#version\n**截图：** feedback_screenshots/001.png（可选）\n\n### UF-002 [Missing] 标题\n**期望：** PRD 中描述的功能\n**现状：** 功能缺失或未实现\n**参考：** PRD.md#section\n```\n\n**反馈类型：**\n- `[Design Intent]` — 设计意图偏差（QA 测不到的，只有用户能判断）\n- `[Missing]` — 功能缺失（PRD 有但没实现）\n- `[Regression]` — 回归问题（之前好的现在坏了）\n- `[Polish]` — 打磨细节（能用但不够好）\n\n### FEEDBACK.md 的流转\n\n| 谁 | 怎么用 |\n|----|-------|\n| **forge-eng** | 读取 → 作为 fix list，和 qa-report BUG 一起修 |\n| **forge-qa（下一轮）** | 读取 → 纳入 test-spec 回归项，确保不再漏测 |\n| **forge-qa（长期）** | 历史 FEEDBACK 累积为项目回归测试基线 |\n| **用户** | 只写\"发现了什么 + 期望什么\"，不需要定位根因 |\n\n### 反馈闭环流程\n\n```\nQA 报告 → User Gate → reject\n                        │\n                        ↓\n                  FEEDBACK.md（用户反馈）\n                        │\n                        ↓\n                  合并修复清单 = qa-report BUG + FEEDBACK\n                        │\n                        ↓\n                  forge-eng（修复）\n                        │\n                        ↓\n                  forge-qa（回归）\n                    ├── test-spec 自动包含 FEEDBACK 项\n                    └── 只测变更 + FEEDBACK 涉及范围\n                        │\n                        ↓\n                  User Gate（再次验收）\n                        │\n                        └── ... 直到 accept\n```\n\n---\n\n## 第8步：健康评分与报告\n\n### 健康评分计算\n\n| 维度 | 权重 | 评分方式 |\n|------|------|---------|\n| 控制台错误 | 15% | 0 错误→100, 1-3→70, 4-10→40, 10+→10 |\n| 链接完整性 | 10% | 每个死链 -15，最低 0 |\n| 核心功能 | 20% | 每个严重 -25, 高 -15, 中 -8, 低 -3 |\n| 视觉呈现 | 10% | 同上 |\n| 用户体验 | 15% | 同上 |\n| 性能 | 10% | 同上 |\n| 内容 | 5% | 同上 |\n| 无障碍 | 15% | 同上 |\n\n### 报告结构（先全局后细节）\n\nQA 报告 SHALL 采用以下结构，让用户先看整体是否符合预期，再审阅细节：\n\n```markdown\n# QA 验收报告：{功能名}\n\n**日期**: YYYY-MM-DD  **分支**: {branch}  **PRD 版本**: vX.Y\n\n---\n\n## 一、全局评估（先看整体）\n\n### 用户流程完整性\n- 状态：PASS / FAIL\n- 说明：{流程是否通畅，哪些步骤有问题}\n- 证据：{流程截图或描述}\n\n### 页面/系统结构合规性\n- 状态：PASS / FAIL\n- 说明：{整体布局是否符合 Feature Spec 第二节的结构图}\n- 偏差项：{列出与 Feature Spec 不一致的区块/组件}\n\n### 整体健康评分：XX/100\n\n---\n\n## 二、逐项验收结果（再看细节）\n\n| # | 验收项 | 来源场景 | 结果 | 证据 |\n|---|--------|---------|------|------|\n| 1 | {描述} | {Feature Spec 场景} | ✅ PASS | {截图/日志} |\n| 2 | {描述} | {Feature Spec 场景} | ❌ FAIL | {错误详情} |\n| ... | ... | ... | ... | ... |\n\n通过率：{X}/{Y} ({Z}%)\n\n---\n\n## 三、视觉合规结果\n\n| # | 组件 | CSS 属性 | 预期值 | 实际值 | 结果 |\n|---|------|---------|--------|--------|------|\n| V1 | {名} | font-size | 14px | 14px | ✅ |\n| V2 | {名} | color | #1e293b | #333 | ❌ |\n| ... | ... | ... | ... | ... | ... |\n\n---\n\n## 四、发现的问题（按严重度排序）\n\n{BUG 登记，格式同第6步}\n\n---\n\n## 五、验收结论\n\n- 上线就绪：✅ / ⚠️ / ❌\n- 必须修复：{N} 项\n- 建议修复：{N} 项\n- 举一反三风险：{N} 项（如有用户反馈触发）\n```\n\n### 报告输出\n\n**输出到项目目录**：`$REPORT_DIR/qa-report-{YYYY-MM-DD}.md`\n\n```\n.gstack/qa-reports/\n├── qa-report-{YYYY-MM-DD}.md      # 结构化报告（先全局后细节）\n├── test-results.json               # 结构化结果（机器可读，qa-runner 产出）\n├── test-spec.json                  # 测试规格（用于回归）\n├── screenshots/                    # 截图证据\n└── baseline.json                   # 回归基准数据\n```\n\n### 终端报告\n\n```\n+============================================================+\n|                     QA 交付完成                              |\n+============================================================+\n| 项目：[项目名]      分支：[分支名]                            |\n| 测试级别：快速 / 标准 / 详尽                                   |\n| 测试引擎：qa-runner + gstack/browse                          |\n+------------------------------------------------------------+\n| 测试结果                                                     |\n|   总计: XX  通过: XX  失败: XX  跳过: XX                      |\n|   通过率: XX%  控制台错误: XX  网络错误: XX                    |\n+------------------------------------------------------------+\n| 健康评分：XX/100                                             |\n| 上线就绪：✅ 可以上线 / ⚠️ 需关注 / ❌ 不建议                  |\n+------------------------------------------------------------+\n| 等待用户验收（User Gate）...                                   |\n+============================================================+\n```\n\n---\n\n## Feature 状态管理\n\n### 启动时\n- 读取 `.features/{feature-id}/status.md`，确认 eng 行为 `[✅ 已完成]`\n- 将 qa 行更新为 `[🔄 进行中]`\n\n### 执行中\n- 更新 QA Items 表，每个测试项独立状态\n\n### 完成时\n- 通过：qa 行 `[✅ 已完成]`，note: `{passed}/{total} PASS, {score}/100`\n- 未通过：qa 行 `[❌ 失败]`，note: `{failed} FAIL, 需修复后重测`\n- 更新 `_registry.md` heartbeat\n\n---\n\n## 重要规则\n\n1. **像真实用户一样测试** — 点所有可点的，填所有表单，测试所有状态。\n2. **截图留证** — 每个测试步骤至少一张截图。用 `snapElement()` 紧凑裁剪，不用 fullPage。截图后用 Read 工具展示给用户。\n3. **不要只测 Happy Path** — 边界、空状态、超长输入、网络错误都要测。\n4. **控制台是第一现场** — 每次交互后检查控制台。视觉上没问题不代表没有 JS 错误。\n5. **数据驱动是核心** — 不只测一条数据。用 `pickStratified()` 采样多条。\n6. **前后端联动是重点** — 验证 API 调用是否正确、响应是否合理。\n7. **深度优于广度** — 5-10 个证据充分的 Bug > 20 个模糊描述。\n8. **自我调节** — 拿不准就停下来问。\n9. **绝不拒绝使用浏览器** — 后端变更也会影响应用行为，始终打开浏览器测试。\n10. **User Gate 不可跳过** — 自动化测不到设计意图偏差，必须等用户验收。\n\n---\n\n## 资源\n\n- **QA 文档模板**：[references/qa-template.md](references/qa-template.md)\n- **10 维度代码模板**：[references/test-dimensions.md](references/test-dimensions.md)\n- **通用测试引擎**：[scripts/qa-runner.mjs](scripts/qa-runner.mjs)\n\n---\n\n## Mode B：单 bug 修复验收报告模式\n\n> 🎯 配合 forge-bugfix 的 P6 调用。目标：针对**一个 bug 的 Bug 修复验收报告**跑自动化测试，把环境身份、逐步截图、深度断言回填到同一份报告里。\n\n### B.1 前提与入口\n\n- **触发方**：forge-bugfix 的 P6 节点\n- **传入参数**：`REVIEW_DOC`（Bug 修复验收报告路径，形如 `docs/bugfix/reviews/BF-0419-2.md`）\n- **跳过的节点**：不做 test-spec 生成（Layer 1）、不做 User Gate（那一步由 forge-bugfix 的 P6.5 做）\n- **继承的能力**：仍然用 10 维度断言引擎和三种测试引擎（gstack / Playwright / 纯代码）\n\n### B.2 读取 Bug 修复验收报告\n\n```bash\n# 必须存在\n[ -f \"$REVIEW_DOC\" ] || { echo \"❌ Bug 修复验收报告不存在: $REVIEW_DOC\"; exit 1; }\n\n# 读取报告全部内容\ncat \"$REVIEW_DOC\"\n```\n\nAI 解析出：\n- BUG_ID\n- 修复 commit hash（用于定位修复范围）\n- 涉及文件列表（用于缩小测试范围）\n- TDD / 回归用例区\n- 验收入口与环境身份校验区\n- 人工验收指南的每一行（检查点 / 操作步骤 / 预期效果）\n\n### B.3 为每个验证项选择测试引擎\n\n| 验证项性质 | 默认引擎 | 选择理由 |\n|---|---|---|\n| UI 交互 / 视觉 / 控制台 | browser-use:browser（Codex 可用时优先）或 Playwright | 需要真实浏览器和用户视角截图 |\n| API / 数据 / 业务逻辑 | curl / 代码单元测试 | 更快更直接 |\n| 响应式 / 可访问性 | Playwright | 专业断言库 |\n| 静态代码属性（文件存在 / import 正确） | Grep / Bash | 无需运行时 |\n\n### B.4 执行验证 + 回填\n\n对每条验证项：\n\n1. 按\"人工验收指南\"的\"怎么操作\"执行\n2. 每个有意义的状态节点截图：打开页面、操作前、操作后、加载态、结果态、错误态\n3. 按\"预期效果\"做深度断言\n4. 截图保存到 `docs/bugfix/reviews/assets/${BUG_ID}/`，并在 Markdown 中用 `![](...)` 内嵌\n5. 回填\"QA 测试过程与截图证据\"节和\"验收入口与环境身份校验\"节\n\n在 Codex 环境中，前端验证默认用 `browser-use:browser` 采集截图和 DOM 证据；需要更强可重复性时，再补 Playwright 脚本断言。若 Browser Use 不可用或被用户/插件中断，报告必须写明 fallback 原因。\n\n截图命名建议：\n\n```text\ndocs/bugfix/reviews/assets/${BUG_ID}/qa-1-01-open-page.png\ndocs/bugfix/reviews/assets/${BUG_ID}/qa-1-02-click-submit.png\ndocs/bugfix/reviews/assets/${BUG_ID}/qa-1-03-final-state.png\n```\n\n报告中必须写成：\n\n```markdown\n![](./assets/BF-0419-2/qa-1-01-open-page.png)\n```\n\n**断言原则**（和 Mode A 一致）：\n- 必须基于\"用户视角可见的内容变化\"\n- 不得单独用技术指标（HTTP 200 数量 / DOM 节点存在）\n- 每个测试至少包含一个内容、状态、URL、CSS、网络响应或数据变化断言\n- 必须核对前后端进程身份（优先看 `dev:status` / `dev-stack status`；兜底用 `ps aux | grep <服务>` + `lsof -p $PID | grep cwd`）\n- QA 使用的 Frontend/Backend 地址必须和报告中交给用户验收的地址一致\n\n### B.5 控制台零容忍（强制）\n\n任何 `pageerror` 或 `console.error` 自动标记为 FAIL，即使该验证项的主逻辑通过。\n\n### B.6 环境身份强校验\n\nforge-qa 必须在报告的\"验收入口与环境身份校验\"区写入：\n\n- Frontend URL、来源、PID、cwd、branch/commit（能获取时）\n- Backend/API URL、来源、PID、cwd、branch/commit（涉及后端时）\n- API health 或关键接口探活结果（涉及后端时）\n- QA 执行时间\n- 环境一致性结论：PASS / FAIL / EXPIRED\n\n硬性 FAIL 条件：\n\n- QA 实际访问的 URL 与报告交给用户验收的 URL 不一致\n- 能拿到 PID/cwd，但 cwd 不属于当前 worktree\n- 前端页面来自旧进程或主仓库，而不是当前 bug worktree\n- 涉及后端但 Backend/API 地址无法确认\n- 交给用户前再次检查发现地址或进程身份已变化\n\n### B.7 回填\"QA 测试过程与截图证据\"节\n\nforge-qa 必须填充报告里的\"## QA 测试过程与截图证据（forge-qa 填）\"：\n\n```markdown\n## QA 测试过程与截图证据（forge-qa 填）\n\n**模式**：Mode B（单 bug 修复回归）\n**执行时间**：2026-04-19 15:45\n\n**自动化测试范围**：\n- 跑了 Playwright 重放（3 步：打开登录 / 登录 / 查看头像）\n- 跑了 tests/auth.test.ts（2 个相关 case）\n- 控制台检查：0 error, 0 warning\n\n### 验证项 1：登录后头像刷新\n\n**结论**：PASS\n\n**操作轨迹与截图**\n\n1. 打开登录页\n\n   ![](./assets/BF-0419-2/qa-1-01-open-login.png)\n\n2. 提交登录\n\n   ![](./assets/BF-0419-2/qa-1-02-submit-login.png)\n\n3. 检查右上角头像\n\n   ![](./assets/BF-0419-2/qa-1-03-avatar-updated.png)\n\n**断言**\n- 头像元素可见：PASS\n- 头像 URL 已更新：PASS\n- console.error：0\n- network error：0\n\n**Bug 复现核对**：\n- 修复前：重现了 BF-0419-2 的原始症状（已对比 before 截图）\n- 修复后：原始症状消失（after 截图）\n```\n\n### B.8 QA 自动闭环状态信号和退出\n\n- **所有验证项 PASS 且环境一致性 PASS**：\n  ```\n  ✅ QA_PASS (BF-0419-2)\n  报告已回填：docs/bugfix/reviews/BF-0419-2.md\n  下一步：交还 forge-bugfix。单 bug 模式进入 P6.5；批量模式进入 qa-pass-pending-final-review。\n  ```\n\n- **至少一条 FAIL 或环境一致性 FAIL**：\n  ```\n  ❌ QA_FAIL (BF-0419-2)\n  失败项: 第 3 条（控制台 TypeError）\n  报告已回填 FAIL + 截图/日志证据。\n  下一步：交还 forge-bugfix，有界回 P5 继续修复。\n  ```\n\n- **需求/设计/环境身份无法判断**：\n  ```\n  ⚠️ BLOCKED_HUMAN (BF-0419-2)\n  原因: 保存后是否必须 toast 提示，Feature Spec 未定义。\n  报告已写入决策卡。\n  下一步：交还 forge-bugfix，询问用户。\n  ```\n\n### B.9 Mode B 不做的事\n\n明确禁止：\n- ❌ 不生成 `docs/QA.md`（那是 Mode A 的产物）\n- ❌ 不做 User Gate（那由 forge-bugfix 的 P6.5 做）\n- ❌ 不写 FEEDBACK.md（那是 Mode A 的 reject 闭环）\n- ❌ 不主动判断\"产品上是否接受\"（只按报告和 Feature Spec 断言，最终由用户/批次验收决定）\n- ❌ 不修改代码（和 Mode A 一样，只测不修）\n\n### B.10 Mode B 的铁律\n\n1. **只填 Bug 修复验收报告，不新建散乱 QA 文档**\n2. **每条验证项必须有 pass/fail**（和 Mode A 第 3 条铁律一致）\n3. **每个前端交互关键步骤必须有 Markdown 内嵌截图**\n4. **控制台零容忍**（一致）\n5. **不能越界修改用户验收列和最终结论**\n6. **应用 URL 必须由调用方或 dev-status 提供**，不得在 Mode B 中猜测本地端口。\n7. **环境身份校验失败就是 QA_FAIL**，不能用“页面能打开”替代。\n8. **发现疑似新需求、范围外问题或设计歧义时输出 BLOCKED_HUMAN**，不要替用户决定。\n9. **Codex 中优先使用 browser-use:browser 做本地浏览器验收**；Computer Use 不是浏览器首选兜底。","tags":["forge","skills","yike-gunshi","agent-skills","ai-development","claude-code","skill-md","skillsmp"],"capabilities":["skill","source-yike-gunshi","skill-forge-qa","topic-agent-skills","topic-ai-development","topic-claude-code","topic-forge","topic-skill-md","topic-skillsmp"],"categories":["forge-skills"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/yike-gunshi/forge-skills/forge-qa","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add yike-gunshi/forge-skills","source_repo":"https://github.com/yike-gunshi/forge-skills","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (40,317 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-05-18T19:07:34.209Z","embedding":null,"createdAt":"2026-04-24T07:03:38.743Z","updatedAt":"2026-05-18T19:07:34.209Z","lastSeenAt":"2026-05-18T19:07:34.209Z","tsv":"'+1':2428 '+2':1799,1811,1825 '+3':1812,1826 '+4':1827 '-001':2126,2345,2378,3789,3853,4180 '-002':2180,3859,4199 '-003':3863 '-005':3867 '-03':2053 '-04':5015 '-0419':5070,5090,5117,5143 '-1':342 '-10':1483,1560,1877,4318,4636 '-100':1862 '-123':3394 '-15':1885,4325,4333 '-19':5016 '-2':5071,5091,5118,5144 '-20':1506,1530 '-25':4331 '-28':2054 '-3':1874,4315,4337 '-5':1373 '-8':4335 '-9':317,319,337,339 '/100':4578 '/api':2951,3122,3916 '/api/feed':2008,3500 '/assets/bf-0419-2/qa-1-01-open-login.png':5046 '/assets/bf-0419-2/qa-1-01-open-page.png':4879 '/assets/bf-0419-2/qa-1-02-submit-login.png':5049 '/assets/bf-0419-2/qa-1-03-avatar-updated.png':5052 '/claudecode_workspace':65 '/dev/null':410,872,884,899,917,926,970,976,992,1035,1046,1057,1095,1162,1169,1191,1371,1404,1416,1423,1431,1481,1502,1526,1553 '/fail/skip':2915 '/forge-cookbook/skills/forge-doc-policy/doc-paths.md':67 '/forge-eng':859,4063 '/forge-prd':2660 '/forge-qa':68,861 '/forge-review':852,4039 '/forge-ship':850,4041 '/page/xxx':3342 '/path/to/.worktrees/feature-slug':1276 '/qa-1-01-open-page.png':4868 '/qa-1-02-click-submit.png':4872 '/qa-1-03-final-state.png':4876 '/qa_screenshots/bug-001-step-01.png':3925 '/qa_screenshots/bug-001-step-02.png':3926 '/status.md':1369,4553 '/thinking':3292 '/url/css':3930 '/visual-decision.md':2770 '0':316,318,336,338,1716,1861,1871,1887,2225,2242,2264,2422,2490,2517,2924,2926,3454,4311,4327,5034,5036,5061,5064 '0.1':735,1219 '0.2':738,1283 '0.3':741,1391 '0.4':745,1439,2031,2077,2281,3264,3346 '0.5':749,1782 '00':2056 '00z':2057 '1':164,205,383,544,581,785,940,972,978,1199,1225,1629,1632,1798,1810,1824,1873,1923,1958,2164,2364,2397,2460,2468,2716,2858,2925,2933,2956,3061,3096,3594,3723,3911,4010,4071,4114,4314,4412,4591,4712,4745,4806,5039,5044,5206 '10':19,556,782,1879,1880,1882,1892,1900,3413,4006,4320,4321,4323,4339,4345,4648,4659,4725 '100':1872,4313 '10000':3511,3523 '1024':3222 '10分钟':1796 '12px':1999,3159 '1440':3224 '14px':4444,4445 '15':1868,1896,1909,2200,4310,4342,4351,5017 '1e293':4449 '1处':1735 '2':179,301,409,555,595,791,871,883,898,916,925,964,971,977,991,1034,1045,1056,1094,1168,1190,1204,1239,1370,1403,1415,1422,1430,1480,1501,1525,1552,1639,1928,1965,2725,2765,2780,2865,2963,3090,3166,3601,3747,3912,4073,4122,4420,4596,4812,5030,5047,5213 '2.0':3047,3239 '20':1889,4329,4639 '200':1172,3502,4889 '2026':2052,5014 '25':3776,3797 '27':3110 '3':195,571,603,809,1207,1245,1647,1934,1970,2831,2869,3018,3117,3615,3767,3913,4008,4090,4135,4607,4820,5023,5050,5121,5220,5222 '3.1':2606 '3.2':2670 '3.3':2806 '3000':670,1152,3490 '301':1173 '302':1174 '304':1175 '30分钟':1808 '333':4451 '3456':1153 '360':3811 '375':3218 '375/768/1440':3032 '3处':1738 '4':611,815,1211,1254,1653,1876,1941,2312,3038,3144,3626,4101,4317,4615,4824,5226 '40':1878,4319 '400':2953,3126 '4000':1154 '404':3081,3138 '44px':3229 '45':5018 '4px':2000,3161 '5':637,1264,1658,1905,1947,3182,3633,4136,4348,4621,4635,4833,5229 '5/20':3773 '50':2267,2484 '500':3478 '500/10740':3463 '5000':2214 '5173':671,1155 '6':642,1665,1953,3213,4627,5231 '60分钟':1822 '7':650,721,1672,2874,3058,3232,4633,5243 '70':1875,4316 '72/100':4012 '768':3221 '8':674,3250,4641,5250 '8000':2144 '8080':672,1156,2067 '8081':1157 '812':3219 '9':3322,4644,5256 '900':3225 'a-z':1490,1514 'aa':3048,3240 'abort':3318 'accept':827,4032,4302 'access':817,3042,3234 'action':2132,2135,2204,2208 'agent':1231 'ai':200,353,3260,4750 'api':987,1932,2006,2947,3131,3137,3476,3492,3708,3738,4630,4785,4952 'app':258,264,293,296,298,399,424,438,452,466,528,653,658,1078,1082,1084,1109,1133,2064,3553,3556,3684 'arg':168,202,207,210,221,232,242,251,261,490 'aria':1457,1508,1513,1596,1600,1604,1656,1732,3192 'aria-select':1603,3191 'articl':1542 'asid':1538 'askuserquest':1196,1271,1787,2648,2809 'assert':2145,2215,2324,2348,2381,2552 'async':806,3007,3417 'async-cont':805,3006,3416 'attachmonitor':2890,2908,3064,3120 'attribut':628,2569 'aux':4908 'await':2906,2919,3488,3495,3505,3514,3526 'awar':1437,1835,2062 'axe':3044,3236 'axe-cor':3043,3235 'b':25,129,171,178,194,214,217,272,323,346,368,372,422,450,473,476,488,504,942,947,950,953,956,959,1214,1800,2843,3650,3652,3657,3661,3664,3669,3673,4020,4042,4144,4450,4667,5009,5161,5204,5241 'b.1':4689 'b.10':5202 'b.2':4730 'b.3':4767 'b.4':4802 'b.5':4920 'b.6':4930 'b.7':4985 'b.8':5080 'b.9':5159 'backend':3606,3921 'backend/api':4945,4982 'backlog':3983 'base':1281,1395,1410,1419,1427,1839 'baseline.json':4503 'basenam':389 'baserefnam':1400,1402 'bash':199,864,1128,1290,1393,1459,3649,4734,4800 'bf':188,516,3894,3966,3973,5069,5089,5116,5142 'bf-candid':3893 'bg-card.rounded':1673 'block':3986,5140,5253 'branch':865,867,887,1279,2048,4371 'branch/commit':4943,4950 'break':1305,1320,1334,1350,1364 'browser':684,689,691,696,2904,3530,3538,3546,3548,3554,3597,3599,3603,3612,3621,3627,3635,3678,3680,3685,4777,4779,4845,4847,4856,5260,5262 'browser-cli':3611 'browser-us':688,3545,3596,3677,4776,4844,5259 'browser.close':2920 'bug':27,39,47,76,79,81,115,131,144,145,229,235,274,282,284,378,385,387,478,510,514,532,588,820,3115,3574,3717,3785,3788,3852,3858,3862,3866,3884,4058,4242,4279,4455,4638,4669,4681,4683,4701,4732,4740,4752,4827,4866,4870,4874,4979,5011,5065,5100,5208 'bugfix':32,124,135,154,184,311,494,3872,3890,3938,3951,3970,3977,3989,4674,4694,4719,5098,5133,5157,5176 'build':3587 'button':1617,1659,1737,1768,2103 'button.isvisible':2500 'c':984,1215,1556,1813,2412,2846,4027,4147,4154 'c.queryselector':2416 'candid':3895 'card':1623,1625,2090,2404 'card-contain':1622 'cards.count':2489 'cards.foreach':2411 'case':2080,2123,2322,2548,2550,2563,5032 'cat':4747 'catch':607,3087 'cd':405,1090,1101,1126,1237 'changelog':1951,2868 'checklist':187,314 'child':1628,1670,2088,2142,2153 'ci':1963 'class':1676,1764,2297,2448 'claud':2588,4047 'click':2205,3190,3198 'client':3613 'cls':1903,3667 'code':718,1165 'codex':675,678,3529,3535,3550,3681,4780,4841,5257 'collector':2900,2910,2918 'collector.checkconsoleerrors':3068 'collector.pass':2914 'collector.pass/fail/skip':2913 'collector.printsummary':2916 'collector.summary':2922 'color':2753,4448 'command':967 'comment':2075 'commit':249,254,290,291,526,715,3923,4755 'common':914 'comput':693,698,3617,5264 'consol':575,787,1388,2176,2276,2937,2941,3063,3580,3658,3725,3750,3800 'console.error':647,4926,5060 'console/network':3933 'const':2227,2232,2253,2258,2403,2414,2435,2444,2451,2899,2903 'contain':625,1624,2166,2565,2723 'content':807,3008,3418 'core':3045,3237 'correct':2319 'count':616,2155,2329,2355,2388,2555 'createpag':2893,2907 'css':629,1615,1675,2003,2296,2570,2736,2739,2749,2755,2761,2789,2836,3025,3150,3170,3178,3742,4079,4434,4896 'curl':427,455,1159,4788 'current':870 'cursor':1756,2092,2159,2194,2359,2392,2407,2439,3518 'cursor-point':1755,2091,2158,2193,2358,2391,2406,2438,3517 'cut':226,237,246,255,266 'cwd':4915,4942,4949,4974 'd':189,190,227,238,247,256,267,396,2454,2848,3392,3406 'data':796,1454,1463,1468,1485,1489,1570,1575,1581,1585,1588,1592,1641,1649,1680,1688,1704,1714,1720,1723,1726,1730,1745,1752,2035,2070,2188,2190,2288,2292,2976,3093,3770 'data-driven':795,2187,2975,3092,3769 'data-item-id':1591,1725 'data-platform':1587,1648,1722,1751 'data-sect':1729 'data-testid':1453,1462,1467,1569,1574,1640,1679,1687,1703,1713,2034,2287 'dd':4172,4369,4478,4487 'deliver/visual-decision.md':2772 'descript':2127,2181,2223,2249,2346,2379,2400,2432 'design':109,1307,1318,4181,4211 'design.md':550,1311,1936,1996,2046,2668,2733,2788,2815,3148,3745,4189 'desktop':3223 'detail':1765,2096 'detailpanel.tsx':2015 'dev':106,413,418,432,459,535,538,662,665,1098,1105,1113,1138,1228,1288,2769,3943,4900,4903,5236 'dev-stack':458,537,664,1137,4902 'dev-status':5235 'dialog':1543,1612,1655,1734,1762,2099,2212,2220,2231,2257 'dialog.isvisible':2514 'diff':111,552,578,744,1409,1418,1436,1834,1840,1842,2013,2061,3755,3758,3763,3819,3882,3963 'diff-awar':1435,1833,2060 'dimens':2129,2186 'dir':915,924,1184,1195 'dir/qa-report-':4474 'dir/screenshots':1189 'dir/screenshots/overview.png':3672 'display':2113,2436,2457,2465 'div':3458 'do-dev':2767 'doc':58,141,174,219,225,278,280,326,329,350,352,376,381,391,508,1297,4700,4738,4743,4749 'docs/bugfix/backlog.md':3945 'docs/bugfix/reviews/assets':4826,4865,4869,4873 'docs/bugfix/reviews/bf-':315,335 'docs/bugfix/reviews/bf-0419-2.md':4704,5093 'docs/bugfix/reviews/bf-xx.md':37,142,3947 'docs/design-blueprint.md':1313 'docs/design.md':1312 'docs/engineering.md':1326 'docs/feedback.md':1343 'docs/prd.md':1295,3908 'docs/qa.md':1356,5165 'document.queryselector':2229,2255,2446 'document.queryselectorall':2405,2437 'dom':1450,2333,3559,3568,3687,4849,4891 'dom/screenshot':3592 'done':907,1180,1306,1321,1335,1351,1365 'driven':797,2189,2191,2977,3094,3771 'echo':209,220,231,241,250,260,269,276,281,286,289,295,304,330,343,348,360,377,416,445,873,885,904,933,957,960,997,1001,1016,1022,1036,1047,1058,1065,1070,1074,1081,1107,1131,1176,1192,1302,1317,1331,1347,1361,1405,1461,1484,1507,1531,4739 'el':3154,3156 'elif':303,441,1087,1122 'els':357,1148 'eng':127,593,704,835,1252,1259,1701,2308,4026,4233,4283,4555 'eng/feature-name-yyyy-mm-dd':4177 'eng/feature-slug-2026-03-28':1280,2049 'engin':1322,1332 'engineering.md':1327,1930,2005,3129 'enter':3245 'error':2177,2245,2270,2277,2425,2463,2942,3583,3659,3726,3751,5035,5063 'escap':2518,3201,3247 'evalu':634,2222,2248,2399,2431,2567 'eventsourc':3266 'exit':382,513,717,4744 'expect':2171 'expir':4961 'f':374,403,1008,1028,1039,1050,1061,1063,1068,1088,1293,1300,1301,1304,1309,1315,1316,1319,1324,1329,1330,1333,1340,1345,1346,1349,1354,1359,1360,1363,4736 'f2':228,239,248,257,268 'fail':649,854,1691,2923,2958,3073,3585,3721,4381,4391,4425,4584,4585,4928,4960,4963,5111,5113,5115,5126,5246 'fallback':4861 'featur':1256,1368,1837,2608,2613,2618,2628,2640,2644,2652,2662,2673,2687,2700,2704,2718,2727,2734,2786,2813,2849,3879,3906,3960,4092,4097,4125,4165,4394,4399,4414,4422,4545,4549,4551,5149,5191 'feature-id':4550 'feature-nam':4164 'features/status':1366 'features/status.md':1377,4034 'feed':1578,1644,2082,2112,2125,2179 'feed-display':2111 'feed-sect':1577,1643 'feedback':1336,1348,4060,4163,4195,4260,4280,4293,4296 'feedback.md':832,858,1342,1852,1943,2022,4049,4150,4159,4227,4273,5181 'fetch':3267 'fi':366,469,470,471,1181 'final':5108 'first':1669,2087,2141,2152 'first-child':1668,2086,2140,2151 'fix':4236 'font':2746,4442 'font-siz':2745,4441 'footer':1540 'forg':2,31,57,85,105,120,123,126,134,153,183,310,493,497,584,592,703,707,829,834,837,1120,1146,1227,1287,1700,2307,3846,3871,3875,3889,3937,3942,3950,3953,3969,3976,4025,4232,4245,4256,4282,4286,4673,4693,4718,4933,4991,4997,5004,5097,5132,5156,5175 'forge-bugfix':30,122,133,152,182,309,492,3870,3888,3936,3949,3968,3975,4672,4692,4717,5096,5131,5155,5174 'forge-dev':104,1226,1286,3941 'forge-doc-polici':56 'forge-eng':125,591,702,833,1699,2306,4024,4231,4281 'forge-qa':1,84,496,583,706,836,1119,1145,3845,3874,3952,4244,4255,4285,4932,4990,4996,5003 'forge-ship':119,828 'form.isvisible':2521 'frontend':435,463,1116,1142,3919,4938 'frontend/backend':4918 'frontmatt':62 'full':1845,2059 'fullpag':4603 'function':793,1994,2020,2130,2969,3184 'gate':118,730,824,841,3992,4271,4299,4544,4650,4715,5172 'generat':2050 'get':2007 'getbyrol':1633 'getcomputedstyl':3155 'gh':1396 'git':110,551,577,743,866,876,895,908,913,918,923,1248,1408,1417,1425,2012,3754,3818 'git-common-dir':912 'git-dir':922 'given/when/then':2622 'gone':3203 'goto':3651 'grep':211,222,233,243,252,262,307,333,411,1030,1041,1052,1096,1170,1465,1487,1510,1534,4076,4086,4799,4909,4914 'gstack':4727 'gstack/browse':941,958,961,1914,3640,3644,3698,4520 'gstack/qa-reports':4480 'gstack/qa-reports/qa-report-':4014 'gte':617,2156,2330,2356,2389,2556 'h':1500,1524,1551 'h2':2236,2447 'h3':1759,2095,2162,2197,2237,2362,2395,2410,2417,2442,3521 'happi':4609 'has-text':1618,1660,1769 'hash':3331,4756 'head':341,1372,1411,1420,1428,1482,1505,1529,1559 'header':1539,1743,2445,2449 'header.match':2453 'health':4953 'heartbeat':4589 'hidden':2557,3509 'history.pushstate':3350 'home/.claude/skills/forge-qa/scripts/qa-runner.mjs':1009,1012 'home/.claude/skills/gstack/browse/dist/browse':952,954 'html':1478,1533,1608 'http':1164,4888 'human':3987,5141,5254 'iab':3605 'id':230,236,283,285,386,388,515,1594,1728,2110,2124,2178,2343,2376,3409,4552,4753,4828,4867,4871,4875 'idl':3307 'imag':2764,2779,3165 'import':988,2888,4797 'in-app':3551,3682 'includ':1471,1473,1475,1477,1494,1496,1498,1518,1520,1522,1545,1547,1549,3499 'info':2089 'innertext':2261 'input':1775,1779,2105,2106 'intent':4182,4212 'item':1593,1727,2009,2207,3393,4565 'javascript':2887,3484 'js':1869,4619 'json':1399,2041,2342,2375,3134 'jsx':1474,1497,1521,1548 'l':1479 'l1':3390 'layer':543,554,570,4711 'lcp':1902,3666 'length':2241,2263,2421,2443 'lg':1674 'line':902,906 'list':897,1250,4237 'load':3300,3480 'loading/thinking/progress':3278 'localhost':669,1166,1177,2066 'locat':3562 'log':1426,3581 'ls':1367 'lsof':4911 'main':1261,1267,1282,1406,1537,1610,1666,1740,2084,2138,2149,2169,3516 'map':2074 'margin/padding':4088 'markdown':2679,3577,3787,3843,3892,4104,4161,4361,4830,4878,5000,5224 'match':631,2452,2456,2459,2467,2572 'md':191,320,340,392,4015,4479,4488 'messag':306,332 'metadata':2042 'min':2163,2363,2396 'miss':4200,4217 'mkdir':1186 'mm':4171,4368,4477,4486 'mmdd':517 'mobil':3217 'modal':3199,3202 'mode':11,24,98,128,170,177,193,197,213,216,271,322,345,358,362,367,371,421,449,472,475,482,487,503,4666,4882,5008,5160,5167,5183,5198,5203,5217,5240 'n':292,384,394,518,943,955,995,1013,1077,2793,2979,3099,4112,4139,4462,4465,4468 'name':1413,1635,2114,4166 'name-on':1412 'nav':1536,1611,1741,2101,2102 'navig':2133 'network':789,2010,2949,3119,3662,5062 'networkidl':3528 'new':2244,2269,2424,2462,2901 'next':1054 'next.js':1060 'node':3608 'node.js':1072 'nonexist':3408 'nonexistent-id':3407 'note':4573,4583 'npm':407,430,1092,1103,3711 'npx':969,973,980 'nth':1627 'nth-child':1626 'o':1161 'oe':223,234,244,253,263,334 'onelin':1429 'p':1187,4912 'p0':1792,2122,3015,3898 'p1':1803,3035,3899 'p2':1817,3055,3900 'p2-p3':1816,3054 'p3':1818,3056 'p5':158,5135 'p6':34,137,4676,4696 'p6.5':49,156,4721,5102,5178 'pad':2759 'page':2905,2909 'page.evaluate':3153 'page.goback':3399 'page.goforward':3400 'page.goto':3378 'page.loaded':2530 'page.mouse.wheel':3467 'page.on':2938,2940 'page.route':3316,3474 'page.url':3374 'page.waitforloadstate':3527 'page.waitforresponse':3496 'page.waitforselector':3506,3515 'page.waitfortimeout':3489 'pageerror':645,2939,3071,4924 'panel':2097,2228,2234,2254,2260,3195 'panel.innertext.length':2483 'panel.isvisible':2482 'param':3381 'pars':879,911,921 'parseint':2458 'pass':53,3632,4380,4390,4417,4574,4576,4959,5042,5055,5059,5084,5086,5088,5106 'pass/fail':605,2782,2784,3107,5215 'path':1235,4610 'pend':5107 'perf':3665 'phase':784,790,808,814,1797,1809,1823,2932,2955,2962,3017,3037 'pickstratifi':2894,3102,4625 'pid':4913,4941,4948 'pid/cwd':3920,3922,4972 'placehold':1780,2107 'platform':1589,1650,1724,1753 'playwright':21,558,965,974,990,998,1002,1916,2283,3638,3647,3690,4728,4783,4793,4853,5021 'playwright.sync':986 'playwright/gstack':2722 'pointer':1757,2093,2160,2195,2360,2393,2408,2440,3519 'polici':59 'polish':4224 'port':1150,1167,1178 'pr':1397 'prd':108,549,1291,1298,1303,1379,1925,1990,2611,2650,2656,2666,4095,4203,4219,4372 'prd.md':1296,2044,2118,4192,4208 'prd/design':1384 'prd/design/engineering/feedback':740 'prioriti':2121 'process.exit':2921 'prompt':1232 'ps':4907 'pw':966,979,982,993,996,1000 'pytest':3713 'python':994,1067 'python3':983 'q':212,412,1031,1042,1053,1097,1401 'qa':3,4,14,44,52,69,86,101,148,270,344,361,365,498,585,681,708,779,838,845,1006,1010,1014,1018,1020,1024,1121,1147,1352,1362,1694,1854,1950,2301,2631,2654,2680,2856,2867,2897,2927,3572,3692,3806,3847,3868,3876,3954,3996,4000,4003,4035,4055,4173,4214,4240,4246,4257,4268,4277,4287,4355,4362,4482,4495,4506,4518,4559,4564,4570,4580,4655,4835,4916,4934,4956,4965,4987,4992,4994,4998,5001,5005,5081,5087,5105,5114,5211,5245 'qa-pass':51 'qa-pass-pending-final-review':5104 'qa-report':4054,4239,4276,4481 'qa-report-yyyy-mm-dd.md':4175 'qa-runn':1017,1023,3691,4494,4517 'qa-runner.mjs':1004,2877,2884 'qa.md':112,754,758,1357,1922,1949,1957,1972,2861 'qe':308,1171 'queri':3335 'queryselector':2235 'r':1466 'react':1032,1038,3078 'read':901,4605 'recommend':3391 'ref':2117 'references/qa-template.md':1975,1976,2863,2864,4657,4658 'references/test-dimensions.md':2880,2881,4661,4662 'regex':632,2573 'registry.md':4588 'regress':1850,2016,2024,2063,4221 'reject':831,856,4044,4272,5186 'reload':2504,3283,3590 'render':2316 'repl':3609 'report':1183,1188,1194,3671,4056,4241,4278,4473,4483 'requirement名':2720,2729 'resp':3497 'resp.status':3501 'resp.url':3498 'respons':813,3031,3215,3674 'results.isvisible':2508 'rev':878,910,920 'rev-pars':877,909,919 'review':140,173,186,218,224,277,279,313,325,328,349,351,375,380,390,507,4699,4737,4742,4748,5109 'review-checklist':185,312 'rn':1558 'roh':1488,1511,1535 'role':1512,1599,1601,1654,1733,1736,1761,2098,2211,2219,2230,2256 'role/aria':2291 'root':875,894,931,932,944,1091,1102,1127 'root/.claude/skills/gstack/browse/dist/browse':946,948 'root/.gstack/qa-reports':1185 'root/package.json':1029,1033,1040,1044,1051,1055,1069,1089 'root/pyproject.toml':1064 'root/requirements.txt':1062 'root/scripts/dev-stack.sh':1124 'run':408,431,1093,1104 'runner':1007,1011,1015,1019,1021,1025,2898,2928,3693,4496,4519 'runtim':3614 'sampl':2198 'schema':63,3132 'scope':2058 'score':4577 'screenshot':3670,4501 'screenshots/001.png':4196 'screenshots/xx_name.png':3807 'script':2226,2252,2402,2434 'scripts/dev-stack.sh':447,1129 'scripts/qa-runner.mjs':4664,4665 'scrollintoview':3469 'search':1777,2104 'section':1541,1579,1645,1667,1731,1742,2083,2085,2139,2150,2172,4190,4209 'section.isvisible':2495 'section.starred':2352,2385 'select':1605,3193 'selector':2038,2068,2073,2137,2148,2157,2168,2192,2206,2210,2218,2351,2357,2384,2390 'semant':2072 'shall':2638,4066,4069,4151,4357 'ship':121,830 'show':869,881 'show-curr':868 'show-toplevel':880 'size':2199,2747,4443 'skeleton':3446,3448,3456,3507 'skeleton.gone':2535 'skeleton/spinner':3430 'skill':166,3600 'skill-forge-qa' 'snap':2891 'snapel':2892,4600 'snapshot':3560,3569,3653 'sort':1503,1527,1554,1557 'sourc':2043,2116 'source-yike-gunshi' 'spa':3340,3425 'spec':17,599,767,775,1446,1566,1685,1710,1982,2473,2544,2578,2582,2586,2600,2609,2614,2619,2626,2629,2636,2641,2645,2653,2663,2674,2688,2701,2705,2719,2728,2735,2787,2814,2850,3880,3907,3961,4093,4098,4126,4252,4291,4395,4400,4415,4423,4709,5150,5192 'spinner':3290 'src':1470,1493,1517,1544 'src/components/detailpanel.tsx':3810 'sse':567,798,2498,2982,2991,3251,3256 'stack':460,539,666,1139,3075,3728,3802,4904 'star':2344,2377 'stat':1421 'state':803,2997,3328,3508 'status':414,419,433,461,536,540,663,667,1099,1106,1114,1130,1140,4901,4905,5237 'step':2030,2076,2131,2203,2280,3263,3345 'strategi':2069,2201 'stratifi':2202 'stream':799,2984,3253,3268 'suit':2109 'sync':989 't10':2055 'tab':1602,1634,1766,2100,2493,2970,3189,3205,3243,3337,3371,3383,3780,3783 'tablet':3220 'tdd':711,4760 'test':16,598,766,774,1445,1565,1684,1709,1961,1981,2321,2472,2543,2577,2581,2585,2599,2625,2635,3712,4251,4290,4708 'test-results.json':4491 'test-spec':15,597,765,773,1444,1564,1683,1708,1980,2471,2542,2576,2580,2584,2598,2624,2634,4250,4289,4707 'test-spec.json':547,2026,2871,4498 'testcollector':2889,2902 'testid':1455,1464,1469,1571,1573,1576,1583,1642,1681,1689,1705,1715,1719,2036,2289 'tests/auth.test.ts':5029 'text':626,1620,1662,1771,2071,2167,2170,2566,4864 'text/css_value':2724 'textcont':2450 'textcontent.length':3297,3453 'textlen':2259,2266,2272 'throw':2243,2268,2423,2461 'timeout':2143,2213,3510,3522 'titl':2173,2233,2239,2415,2419 'title.textcontent.trim':2240,2420 'toast':2525,5147 'topic-agent-skills' 'topic-ai-development' 'topic-claude-code' 'topic-forge' 'topic-skill-md' 'topic-skillsmp' 'toplevel':882 'total':4575 'trace':3076,3729 'tri':3086 'trim':2262 'true':1606,3194 'try-catch':3085 'tsx':1472,1495,1519,1546 'twitter':1590,1651 'type':1776,2146,2154,2165,2174,2216,2221,2247,2274,2349,2354,2382,2387,2398,2430 'typeerror':5124 'u':1504,1528 'uf':4179,4198 'ui':3288,3319,3358,4772 'uniq':1555 'unknown':874 'url':259,265,294,297,299,400,425,436,439,453,464,467,529,568,654,656,659,802,1079,1083,1085,1110,1117,1134,1143,1847,2065,2134,2528,2532,2993,2996,3000,3001,3323,3327,3355,3360,3362,3366,3379,3388,3404,3557,4895,4939,4946,4967,4969,5057,5233 'url-stat':801,2995,3326 'url状态':800 'use':685,690,694,697,699,3531,3539,3547,3598,3618,3622,3628,3636,3679,4778,4846,4857,5261,5265 'usehash':3348 'user':117,305,331,729,823,840,3991,4162,4270,4298,4543,4649,4714,5171 'userout':3349 'v':968 'v1':2743,4439 'v10.0-':2119 'v10.1':2045 'v2':2047,2751,4446 'v3':2757 'valu':630,2571,2750,2756,2762 'version':975,4193 'view':1398,2353,2386,3333 'visibl':614,2147,2217,2327,2350,2383,2554,3196,3200 'visual':811,2002,3024,3146 'vue':1043,1049,1476,1499,1523,1550 'vx.y':4374 'w':1163 'wait':2136,2209 'waitforrespons':3440 'waitforselector':3442 'waitfortimeout':3437,3483 'warn':5037 'wcag':3046,3238 'websocket':3258,3269 'window.location.hash':3351 'work':2318 'worktre':240,245,287,288,395,397,406,521,524,736,888,891,893,896,905,928,930,935,938,1220,1234,1243,1247,1249,1269,1275,4976,4980 'worktree/package.json':404 'worktree/scripts/dev-stack.sh':443 'writeresult':2895,2917 'x':442,945,951,1123,2796,2827,4428 'xx':4523,4525,4527,4529,4531,4533,4535 'xx/100':4404,4537 'xxx':3334,3338 'y':2799,2834,4429 'yes':929 'yyyi':4170,4367,4476,4485 'yyyy-mm-dd':4169,4366,4475,4484 'z':398,949,981,1492,1516,2802,2839,4430 '一':4375 '一个':4680 '一句话说明':3813 '一样':5200 '一致':4884,5228 '一起修':4243 '三':4431 '三个断点':3216 '三个视口':3033 '三层架构':485,542 '三视口截图':3675 '上下文探测':734 '上下文探测与环境准备':1218 '上线就绪':4460,4538 '下一步':847,5094,5129,5153 '下一轮':4247 '下所有功能受影响':3784 '下游':97 '下面的示例用':2037 '不一致':4970 '不一致则警告':1381 '不一致的区块':4401 '不主动判断':5188 '不从零写脚本':2886 '不作为':2781 '不修代码':9,74 '不修改代码':5196 '不修改任何业务代码':586 '不做':4706,4713,5170 '不做的事':5162 '不允许':606,609 '不写':5180 '不只是':3272,3455 '不只是骨架屏':2251 '不只测一条数据':4623 '不可用':962,1003,1026,3623,3829 '不可用或被用户':4858 '不可跳过':826,3995,4651 '不可靠':3486 '不同项目的':1449 '不在':3762 '不够':2477 '不存在':2646 '不属于当前':4975 '不建议':4541 '不得单独用技术指标':4887 '不得因为':692 '不得在':5239 '不得猜本地端口':651 '不得自行发明':668 '不新建散乱':5210 '不是切前的旧内容':2497 '不是手写的':2583 '不是技术':2597 '不是浏览器首选兜底':5266 '不是验收断言':619 '不测':3095 '不生成':596,5164 '不生成就不执行':769,1984 '不用':3436,3616,4602 '不白屏':3411 '不盲猜选择器':748,1442,3563 '不能作为验收断言':2335 '不能假设任何':1452 '不能发现':3083,3113,3141,3176,3209 '不能只写散文报告':3886 '不能只验证元素存在':613 '不能替代':3169 '不能用':5247 '不能编造不存在的':2033 '不能越界修改用户验收列和最终结论':5230 '不自动修':3980 '不要只测':4608 '不要在':1682 '不要替用户决定':5255 '不进入':3988 '不阻塞本轮':3984 '不需要定位根因':4266 '不验证':2340 '与':1376 '与报告交给用户验收的':4968 '与用户多轮确认':1966 '专业断言库':4794 '专为测试设计':1646 '且无':1268 '且环境一致性':5085 '业务语义属性':1652 '业务逻辑':4787 '两种调用模式':10 '严重':3827,3850 '严重度':3790,3824 '严重度分类':3823 '个':1717,3100 '个元素':2980,3097 '个功能点':2830 '个模糊描述':4640 '个相关':5031 '个证据充分的':4637 '中':936,2334,3759,3764,3834,3861,4334 '中优先使用':5258 '中使用':1567 '中做本地前端页面':679 '中包含':1233 '中描述的功能':4204 '中提出':2304 '中断':3304 '中未修复的':4057 '中标注':1697 '中没有':2651 '中猜测本地端口':5242 '中用':4831 '中的':2612,4096 '中的变更文件':3756 '中的文件路径':3752 '中的某个场景':2642 '中编造':1686 '中记录的':1378 '中间态':2987,3277,3287 '中间态可观测':2502 '为每个验证项选择测试引擎':4768 '主操作和空态':2777 '主要用户流程是否可用':1890 '主要输入':2633 '举一反三':4105 '举一反三发现':4061 '举一反三机制':4064 '举一反三风险':4467 '之前好的现在坏了':4223 '二':4405 '五':4458 '交互':564,680,792,3542,4773 '交互后通过':3067 '交互完整性':2968,3183 '交互流畅度':1897,3210 '交付完成':4507 '交叉引用':579,3820 '交叉验证':3748 '交由':2305 '交给用户前再次检查发现地址或进程身份已变化':4984 '交还':5095,5130,5154 '产出':1971,4102,4497 '产品上是否接受':5189 '人工验收指南':4808 '人工验收指南的每一行':4763 '仅修复用户明确指出的单点问题就声称完成':4153 '仅当':531 '仅用作解释偏差的参考':3168 '仅详尽级别':3040 '仍在':2505 '仍然用':4724 '仍需配合断言':3630 '从':201,1841,2617,3147 '从消息里捞':324 '从稳定到脆弱':1631 '从零创建':761 '从零创建模式':1955 '从高到低':163 '代码单元测试':4789 '以上都没有':1613 '任何':644,3070,3582,4923 '任务级验证':720 '优先使用':687 '优先测试历史反馈项':1856 '优先看':4899 '优先级':204,300,2290 '优先级最高':506 '优先读取':661 '优雅降级':3410 '会话上下文':553,2018 '传入':440,468 '传入参数':4698 '传入的路径优先级最高':1289 '但':420,448,4973 '但它是':2590 '但验收标准可能不够精确':2658 '低':3837,3865,4336 '作为':437,465,4235 '使用':1598,1913,2876,2912,3101,3152,3439,3549,4075 '使用上述优先级中实际存在的选择器':1692 '使用了相同的':4119 '使用已有':1584 '使用的':4917 '使用规则':3593 '使用语义标签':1609 '供':1707 '保存到报告目录':2872 '保存后是否必须':5146 '信息卡片':1750 '信息流':2120 '信息流展示':2115 '修复':594,860,4284,4754 '修复前':5067 '修复后':5076 '修复回归':28,5012 '修复建议':3821 '修复方向':3857 '修复清单':3844 '修复清单产出':3842 '修复用户指出的问题':4072 '修复验收报告':82,132,146,275,511,4684,4733,5209 '修复验收报告不存在':379,4741 '修复验收报告指定目录':3575 '修复验收报告模式':479,4670 '修复验收报告路径':4702 '修复验收报告里的人工验收指南跑自动化测试':40 '修改了':2014 '候选':116 '值':2748,2754,2760 '值与预期一致':2539 '值合规':3179 '值的组件':4089 '偏差项':4397 '做':4722,5179 '做本地浏览器验收':5263 '做深度断言':4823 '做热点分析':1952 '停止测试':2959 '健康评分':4011,4536 '健康评分与报告':4304 '健康评分计算':4305 '像真实用户一样测试':4592 '元数据':4167 '元素不存在':3732 '先从文档提取验收项':601 '先全局后细节':2677,4354,4490 '先看整体':4377 '先看整体是否符合预期':2684 '兜底':3525 '兜底原因必须写入报告':3625 '兜底用':4906 '入口':2691 '入口判断在前置脚本阶段':88 '入口带参数':139 '全':2957 '全局评估':4376 '全局验证':2683,2816 '全程中文':842 '全过':45 '全部修复':4143 '全部加载完成后进度消失':3465 '全部通过':848 '全链路':2985 '共':2792 '关联':3905 '关键元素映射':1749 '关键区块':2486 '关键断言':3285,3368,3434 '关键测试策略需用户确认后再执行':843 '关键状态节点截图保存到':3571 '关闭':3248 '其他必需参数从报告或上下文推断':356 '其余记录到':4149 '内容':1904,2370,4347 '内容到达':3431 '内容加载':3385 '内容区':3452 '内容区逐步增长':3296 '内容正确':3396,3433 '内容非空':2537,3450 '内容验证':3010 '内嵌':3578,4832 '内嵌截图':5225 '内运行测试':525 '再审阅细节':4360 '再次验收':4300 '再看具体细节':2711 '再看细节':4407 '再补':4852 '再重新采集':3591 '冒烟':2934 '决定测试重点':1434 '准备结构化输入':3891 '几乎所有现代':3424 '出口':2693 '出现':3289 '分':1863 '分层采样':3103 '分支':1202,1253,1257,1262,4176,4370,4510 '分支且有':1838 '分支名':4511 '分析流程':3719 '分析项目测试现状':1959 '分类':3957 '分页':3011,3459 '切换':2971,3566 '切换后内容区文本变化':2496 '列出与':4398 '列出选项':1212 '列表':2487 '刚变更':3588 '刚实现了频道切换功能':2019 '创建':2860 '创建对应':3946 '初始化':3602 '初稿':1973 '判断是否启用':3270,3352 '到':2692 '刷新页面后':3311 '前':1447 '前后端环境身份校验回填到报告':43 '前后端联动是重点':4628 '前提与入口':4690 '前端地址':3914 '前端页面':3541 '前端页面来自旧进程或主仓库':4977 '前端验证默认用':4843 '前置脚本':91,863 '前置脚本已检测':1241 '前置脚本执行':161 '功能':2795 '功能可用但体验差':3835 '功能可用但结果错误':3832 '功能名':2682,4364 '功能场景':2826 '功能描述':2667 '功能描述生成测试':2657 '功能测试':3778 '功能点数':2829 '功能缺失':4218 '功能缺失或未实现':4206 '功能遗漏等只有用户能判断的问题':3998 '加载中':3462 '加载失败':3473 '加载完成后':3451 '加载态':3009,3429,4817 '加载态消失':3432 '动画':3293 '动画是否自然':3211 '包含对应参数':3375 '包含标题':2485 '包含错误文本和':3074 '包裹的静默错误':3088 '区写入':4937 '区块':2822 '区块数':2821 '单':26,46,78,130,143,273,477,4668,5010,5099 '单元测试':710 '单调递增':3298 '占位符表示':2039 '卡片':3373 '卡片因数据类型不一致崩溃':3111 '卡片点击':2182 '即使该验证项的主逻辑通过':4929 '历史':4259 '历史用户反馈':1337,2023 '原因':3812,4862,5145 '原始症状消失':5077 '原子':714 '参数':500,3336 '参考':1974,2279,2862,4188,4207 '反向':3364,3376 '反面示例':2336 '反馈出现':2524 '反馈及时性':1898 '反馈类型':4210 '反馈闭环流程':4267 '反馈项':4178 '发现':587,4111,4138 '发现了什么':4264 '发现属于本轮':3878 '发现疑似新需求':5251 '发现的问题':4453 '发现的问题生成结构化':75 '取消':3303 '变化':3356 '变更回归':1857 '变更摘要':1424 '变更文件':1432 '变更文件列表':1407 '变更范围分析':742,1392 '只作明确兜底':700 '只使用审计中确认存在的选择器':2285 '只修复用户指出的问题':4148 '只做':1387 '只写':4263 '只填':5207 '只截图不断言':610 '只按报告和':5190 '只有':2553 '只有用户能判断':4216 '只来自':2785 '只测':1791 '只测不修':582,5201 '只测变更':4295 '只能作为前置条件':2331 '只验证':2338 '只验证了':2366 '可以上线':4539 '可以把这些候选写入':3944 '可以直接在会话中描述':4046 '可以直接测试':1263 '可作为':3646 '可关闭':2519 '可审查的':2592 '可延后':3841,3864 '可用':999 '可用时':3645 '可用时优先':4781 '可能存在同样问题':4121 '可见文本':1664,2295 '可访问':566 '可访问性':725,816,3041,3233,4792 '可访问性和边界':1819 '可访问性基础测试':1390 '可追溯到':2639 '可逆性验证':3188 '可选':4197 '可重复回归':3697 '各区块职责与描述匹配':2707 '合并':4053 '合并修复清单':4275 '同上':4340,4343,4346,4349,4352 '同类':4078 '同类组件':4081 '同类逻辑':4082 '名':4440,4447 '后':2545 '后数据仍在':3284 '后端':3915 '后端变更也会影响应用行为':4646 '后端未启动':3140 '后退':3398 '向用户总结当前状态':1954 '吞错误':608 '否':3816,3903 '含':169 '含义':502 '启动时':4547 '启发式判定':347 '启发式识别':302 '和':172,615,2328,3607,4238,4881,5197,5216 '响应':3123,3493 '响应式':565,724,812,1389,1805,3020,4791 '响应式断点':3030,3214 '响应是否合理':4632 '响应结构匹配':3127 '响应结构变更':3139 '哪些步骤有问题':4384 '四':4452 '回':4023 '回修':159 '回到':2575 '回填':4804,4834,4986 '回归':839,862,4288 '回归基准数据':4504 '回归断言':2025 '回归时回填':80 '回归测试用':1338 '回归用例区':4761 '回归破坏核心流程':3971 '回归问题':4222 '回归项':4253 '回查':4091 '在':677,934,1693,1836,2300,3534,3757,4840 '在代码库中搜索与该问题相同的模式':4077 '在关键交互元素上补充':1702 '在正确的分支上测试':1223 '在测试前打分':1860 '在生成':1443 '在计划中单列':2773 '在该':523 '地址':3917 '地址必须和报告中交给用户验收的地址一致':4919 '地址无法确认':4983 '场景':2832,4127,4416,4424 '场景名':4128 '场景描述':2717,2726 '场景映射为':2623 '均匀分布':3105 '基于':2672,2812,3817 '基于文档理解自动生成':2589 '基准分支':1394 '填':4999,5006 '填充':2522 '填写反馈':4022 '填所有表单':4594 '处于功能开发后的自动闭环场景':3877 '处理':3826,3958 '处类似风险':4113,4140 '复现核对':5066 '复现步骤':3910 '外观':3838 '失败':4007,4526,4582 '失败归因':573 '失败项':5119 '头像':5056 '头像元素可见':5054 '契约':491 '契约和测试矩阵':1933 '如':3389,3405,3796 '如有':1944 '如有用户反馈触发':4470 '如果':1230,2643,2954,3128,3537 '如果代码或':3586 '如果存在':2616,2763 '如果当前在':1258,1266 '如果找不到':1383 '如果是则直接使用':1244 '如果有':3164,3445 '如果有取消按钮':3305 '如果有进度提示':3461 '如果某个':2549,2562 '如果用户选择继续':2664 '如果项目缺乏稳定选择器':2299 '如果项目零':1678 '如用户未指定':1785 '如需浏览器验收':1111,1135 '始终打开浏览器测试':4647 '字号':1938,3027,3158 '字号不达标':3173 '字符':2273 '存在':1851,2339 '存在性校验失败直接':512 '完成':89,2988 '完成后':3299 '完成后结果持久化':2503 '完成态':3281 '完成时':4568 '完整':13,100,364 '完整度评分':1210 '完整流程':732 '完整白名单':61 '定义':3825 '定义了':3130 '定位源文件':3730 '定位说明':701 '实际值':4134,4437 '实际看到的行为':4187 '实际访问的':4966 '审计':2282 '审计产出':2078 '密度':2776 '对应到':3753 '对标':2686,2699,2732 '对每个':3720 '对每条验证项':4805 '对比':3744 '对比度':1911 '对话框':2513 '导航':1767,2944 '将':2621,2870,3749,4558 '将基于':2655 '就不执行测试':600 '就只测该':655 '展示验收计划摘要并等待确认':2810 '属于本轮':3959 '属性':1486,1509,1586,1597,1657,1721,1746,2293,2740,2790,4080,4435 '属性但非':1582 '属性存在':1458 '属性断言':2837 '属性验证':3026 '崩溃':3206,3774,3781 '工作量估算':1216 '工具':66 '工具可见就跳过':695 '工具展示给用户':4606 '已完成':4037,4557,4572 '已对比':5073 '已更新':5058 '已有':753,1921 '已有问题':3766 '带完整参数的':3387 '平台配色正确':3163 '并在':4829 '并把':434,462 '并用':3576 '应用':5232 '建立健康基准':752,1859 '建议':1698 '建议下一步':4038 '建议严重度':3897 '建议交给':3935 '建议修复':3836,3860,4464 '建议先运行':2659 '异常':2730 '异常路径均有对应的错误处理':2695 '异步':3005 '异步内容':3415 '引入':3964 '引入的':3883 '引导用户描述问题':4045 '引擎':3532,3641 '引擎协同':3676 '引用此映射':2081 '张但标题显示':2466 '张卡片标题为空':2429 '弹出详情面板':1993 '弹窗':2481 '强制':4922 '强制信号':505 '当':3643,3873 '当前分支':886 '当前分支为':1255 '当前完全测不到的':3112 '当前实现为':4133 '当前目录':1278 '当前目录检测':1240 '当前项目':1201 '当前项目提供':417,446 '当用户报告任何问题时':4068 '形如':4703 '影响':3794 '影响范围':3795 '影响范围估算':3768 '往下的完整流程':486 '待用户判断':3904 '必填':501 '必需参数校验':369 '必须':2479 '必须为':3887 '必须传':495 '必须使用':2883 '必须修复':3830,3833,3849,4461 '必须在报告的':4935 '必须基于':4885 '必须填充报告里的':4993 '必须存在':4735 '必须扫描代码确认可用选择器':1448 '必须接收':499 '必须来自调用方的':534 '必须核对前后端进程身份':4898 '必须由调用方或':5234 '必须等用户验收':4653 '必须补充深层断言':2561 '必须验证':354 '快照':3688 '快速':1790,1802,2965,4513 '快速失败':2931 '快速探索':3699 '快速探索和截图标注':3642 '态':3308 '怎么操作':4810 '怎么用':4230 '性能':1899,3668,4344 '性能指标':3701 '总计':4522 '总量增加':3472 '恢复完整状态':3367 '慢':3487 '懒加载':569,804,3004,3414 '懒加载内容':2534 '我需要先自己体验一下':4028 '或':103,646,851,1277,1456,1754,1763,1778,1915,2771,3339,3441,3468,4040,4191,4782,4925 '或关键接口探活结果':4954 '或历史':1853 '或截图':428,456,3570 '或日志作为证据':641 '或本次':3881 '或环境一致性':5112 '或用户':855 '或用户要求':1848 '或触发消息中解析':203 '或降级来源':2675 '或非':1260 '截取基准截图和控制台状态':1917 '截图':3805,4194,4418,5075,5079,5127 '截图不能单独作为':3631 '截图保存到':4825 '截图后用':4604 '截图命名建议':4863 '截图标注':3700 '截图留证':3230,4597 '截图证据':3689,3924,4502 '所有':2079,2547 '所有级别都执行':2935 '所有验证项':5083 '才能判断测试是否充分':2605 '打开登录':5025 '打开登录页':5045 '打开调用方传入的':3555 '打开页面':4814 '打磨细节':4225 '执行':4067,4811 '执行中':4562 '执行分阶段':2930 '执行时间':4957,5013 '执行浏览器动作前必须先加载并遵守':3595 '执行验证':4803 '扫描':3241,3265,3347 '扫描已有':1246 '扫描项目中可用的选择器锚点':1460 '批次最终验收':157 '批次验收决定':5195 '批量模式进入':50,5103 '把环境身份':4686 '把逐步截图':41 '报告':8,73,113,821,1855,3718,4013,4269,4356 '报告中必须写成':4877 '报告产出后的出口':844 '报告内':147 '报告参考':4174 '报告存在':355 '报告已写入决策卡':5152 '报告已回填':5092,5125 '报告已生成':4004 '报告并退出':2961 '报告必须写明':4860 '报告或':3573 '报告生成后':4001 '报告的':1695,2302 '报告目录':1182,1193 '报告结构':4353 '报告输出':4471 '拒绝执行':2574 '拦截':3317,3475 '拿不准就停下来问':4643 '持久化':2989,3310 '持久化验证':3282 '指定了':1846 '指定哪些':4146 '按':4807,4821 '按严重度排序':4454 '按以下步骤执行':4070 '按优先级检测工作环境':1224 '按搜索模式定位所有参考文档':1285 '按钮':3275 '按钮变为不可操作':3294 '按钮存在':3273 '按钮无响应':3207 '按钮点击':2972 '控制台':560,786,4775,5123 '控制台是第一现场':4616 '控制台检查':5033 '控制台检查优先使用':3544 '控制台错误':1867,3660,4309,4532 '控制台零容忍':643,2936,3062,4921,5227 '推断影响范围':1433,1843 '推算':3775 '推荐':1636,1772 '推荐策略':1744 '推荐选项':1209 '措辞':3839 '描述':4413,4421 '提交':2523 '提交后采集最小必要状态':3567 '提交登录':5048 '提供':5238 '提取':1931,3727 '提取内容':1988 '提取历史用户反馈':1945 '提取硬规则':3149 '提取视觉硬规则':1937 '提取验收标准':1927 '提取验收项':2669 '提示':5148 '插件中断':4859 '插件可用':686,3540 '搜索':1621,1663,1781,2108,2506 '搜索所有使用相同':4087 '搜索框':1774 '搜索相似模式':4074 '摘要':776 '操作':2999,3186,3354 '操作前':4815 '操作后':4816 '操作步骤':4765 '操作浏览器':3619 '操作轨迹与截图':5043 '操作驱动':3359 '支持两种调用模式':87 '收藏':2488 '收藏页卡片数量与页面显示的统计数一致':2433 '收藏页展示收藏的卡片':2347,2380 '收藏页有卡片':2367 '改进建议':1696,2303 '数据':4786 '数据值':621 '数据受影响':3777 '数据变化':2527 '数据展示是否正确':1907 '数据断言摘要':3932 '数据流':3279 '数据驱动':561,727,794,2185,3695 '数据驱动是核心':4622 '数据驱动遍历':2974,3091 '数组必须包含至少一个':2325 '数量':2538,4890 '数量与页头统计一致':2492 '数量合理':2510 '整体健康评分':4403 '整体布局与':2703 '整体布局是否符合':4393 '文件':3803,3809,3855 '文件存在':4796 '文件路径':192,4115,4123 '文本':1614,3928 '文本内容':622 '文本选择器':1747 '文案':1906 '文档':546,780,2857,5212 '文档模板':4656 '文档版本校验':1374 '文档落地路径':54 '文档链定位':739,1284 '断言':1995,2004,2011,2021,3124,3151,5053,5193 '断言原则':4880 '断言引擎':22,559 '断言必须验证功能正确性':612 '断言或真实截图':3171 '断言方式':2742 '断言核心元素可见':2946 '断言深度规则':636,2310 '断言类型':2715 '新内容出现':3471 '新需求或设计取舍':3978 '无':757,1956 '无效参数的':3403 '无文档模式':1386 '无断点':2694 '无残留':3309 '无水平溢出':3227 '无浏览器引擎时':3703 '无遗漏无多余':2709 '无限滚动':3421 '无障碍':1908,4350 '无需运行时':4801 '日志':520,4419 '日志证据':5128 '日期':4168,4365 '旧项目兜底探测':1179 '时':660,682,3885 '时使用':3604 '时启用':2992 '时逐条对照':2474 '时间':2805 '明确禁止':5163 '是':3815,3902 '是前置条件':618 '是否属于本轮范围':3901 '显式':206 '显式参数':165 '显示':2464 '显示错误态而非卡死':3320 '显示错误提示而非无限':3479 '智能分析':23,572,819,3716 '暂停':4156 '更多断言深度检查表':2469 '更快更直接':4790 '更新':778,2855,2859,2866,3361,4033,4563,4587 '替代':760,3482,5249 '替换为前置脚本检测到的路径':2929 '最低':1886,4326 '最佳实践':2284 '最关键的深层断言':3313 '最小字号':1998 '最新迭代摘要':1926 '最稳定':1637 '最终内容完整渲染':3302 '最终由用户':5194 '最脆弱':1677 '有':652,853,1580,1595,2990 '有丰富':1568 '有但没实现':4220 '有异步加载时启用':3013 '有标题':2515 '有界回':5134 '有语义化':1607 '有误':2851 '有路由状态时启用':3003 '服务':4910 '期望':4184,4202 '期望什么':4265 '未传':423,451,1108,1132 '未定义':5151 '未捕获异常':3080 '未通过':4579 '本地服务':1075 '本地服务探测':1073 '本文档末尾':481 '本次':3962 '本次引入':3761,3814 '机器可读':4493 '权重':1865,4307 '条':5122 '条件':530,4964 '条铁律一致':5221 '来源':2713,3743,4940,4947 '来源场景':4409 '构造稳定':3561 '某组件间距不对':4085 '查找最近的':1251 '查看头像':5027 '标准':1801,1815,2966,3021,4514 '标注所有可交互元素':3656 '标记':3760,3765 '标记为':2559 '标记该':3782 '标题':3791,3896,4183,4201 '样式是否正确':1894 '核心功能':1888,2964,4328 '核心功能崩溃':3828 '核心原则':2314 '核心流程':1793 '根因':4109 '根因定位':574,3808 '根据审计结果填充实际选择器':2040 '根据扫描结果决定选择器策略':1561 '格式':4050 '格式同第6步':4457 '格式规范':1197 '框架':1037,1048,1059,2878,2885 '框架检测':1027 '检查':1960,2607,2950,3069,3707,3737,3741 '检查其他行为场景是否可能存在同类问题':4099 '检查右上角头像':5051 '检查后端日志':3736 '检查点':4764 '检查组件是否渲染':3734 '检查边界情况':3705 '检查选择器':3733 '检查项':3157 '检查验收检查表中未测试的项是否包含类似约束':4100 '检测':737,889,1005,1221 '模块名':4118 '模式':93,1438,1830,4120,5007 '模式判断优先级':162 '模式判断逻辑':160 '模式进':48 '模式进入':5101 '模态框':2512,3197 '模态框不可关闭':3208 '模态框开关':2973 '模拟网络中断':3315 '正反向验证':2998 '正向':3357,3369 '正在测试的功能':1203 '正常':2721 '正文文本长度':2516 '正确':2341,4798 '正面示例':2372 '步':763,1978,2819,5024 '步骤数':2818 '死链数量':1883 '每个':1884,2320 '每个严重':4330 '每个元素独立':3106 '每个前端交互关键步骤必须有':5223 '每个可交互元素':3185 '每个导航':3066 '每个断点检查':3226 '每个有意义的状态节点截图':4813 '每个死链':4324 '每个测试必须有':604 '每个测试步骤至少一张截图':4598 '每个测试用例必须至少包含一个验证':620 '每个测试结果必须有截图':639 '每个测试至少包含一个内容':4893 '每个测试项独立状态':4567 '每张卡片有标题且标题非空':2401 '每张卡片有标题且非空':2491 '每条验证项必须有':5214 '每次交互后检查控制台':4617 '每次提问结构':1198 '每次点击':3564 '没有':657 '没有任何':2564 '没验证卡片':2368 '流式':3259 '流式期间':3295 '流式生成':2499,2983 '流式生成全链路':3252 '流程':2801 '流程图中的每个步骤在实际页面中都可达':2696 '流程完整':2838 '流程截图或描述':4386 '流程是否通畅':4383 '浅断言':2337,2476,2560 '测不到的':4215 '测试':7,72,3772 '测试全生命周期':3271 '测试加载全生命周期':3427 '测试双向一致性':3353 '测试场景':2475 '测试引擎':939,963,4516 '测试所有状态':4595 '测试方法':2714 '测试本地页面前先':3589 '测试模式':1828 '测试环境':1274 '测试策略':1967 '测试级别':1784,4512 '测试级别与模式':1783 '测试级别确认':750 '测试结果':4521 '测试脚本编写规范':2882 '测试规格':4499 '测试规格生成':545 '测试计划确认':771 '测试过程与截图证据':4836,4988,4995,5002 '测试逻辑':2911 '浏览器优先':676 '浏览器前进':3397 '消失':3301 '消失再断言内容':3449 '涉及后端但':4981 '涉及后端时':4951,4955 '涉及文件列表':4758 '涉及范围':4297 '深层断言':2326,2373,2478 '深度':3039 '深度优于广度':4634 '深度断言':42 '深度断言回填到同一份报告里':4688 '深度断言失败':3927 '深度链接':2529,3325,3386 '渲染崩溃':3079 '源码':576 '滚动加载':3466 '激活':3246 '点击':3370 '点击后回到':3306 '点击后异步获取详情等模式':3423 '点所有可点的':4593 '然后逐个调用':3948 '版本':4373 '版本对比':1380 '特定':3779 '状态':2994,3324,3929,4379,4389,4894 '状态变化':623 '状态变化断言':3187 '状态码':2952,3125 '状态管理':4546 '环境一致性结论':4958 '环境中':3536,4842 '环境身份强校验':4931 '环境身份摘要':3918 '环境身份无法判断':5139 '环境身份无法确认':3985 '环境身份校验':150 '环境身份校验失败就是':5244 '环境问题':2960 '现状':4186,4205 '现象':3792,3854 '理解现状':756,1919 '生成':18,764,1979,2470,2541,3848,4710 '生成一份':2676 '生成修复清单':857 '生成后必须输出摘要供用户确认':2593 '生成时引用':1711 '生成步骤补充':2579 '生成的内容仍然存在':3312 '生成等实时特性':3261 '生成统一修复清单':4062 '生成验收计划并请用户确认':2595 '生成验收计划文档':2671 '用':4599,4624 '用于命名截图':519 '用于回归':4500 '用于定位修复范围':527,4757 '用于缩小测试范围':4759 '用例':2627,3016,3036,3057 '用户':4059,4262 '用户体验':1895,4341 '用户反馈':4107,4274 '用户反馈问题时':4065 '用户可以随时在会话中描述问题':4158 '用户可见现象':3909 '用户审查':772 '用户报告':4084 '用户描述的问题':4108 '用户操作':4029 '用户期望的行为':4185 '用户流程从':2690 '用户流程完整性':2685,2817,4378 '用户点击卡片':1992 '用户直接触发':102 '用户看到了什么':3793 '用户确认':2807 '用户确认后才执行测试':2853 '用户自行体验':4155 '用户视角可见的内容变化':4886 '用户视角操作':3686 '用户视角浏览器验收':3533 '用户需要先理解':2603 '用户验收':825 '用户验收关卡':731,3993 '用户验收通过':849 '由':590,2587 '由调用方传入':1086 '登录':5026 '登录后头像刷新':5040 '登记':3982,4456 '登记为待用户判断':3979 '登记格式':3786 '的':33,136,155,489,2323,2551,2632,3610,4129,4675,4682,4695,4720,4809,5177,5185 '的产物':5169 '的卡片无法打开详情':3798 '的原因':3939 '的原始症状':5072 '的审计结果':2032 '的展开':2313 '的摘要':2601 '的每个用例':2637 '的流转':4228 '的测试用例':3722 '的深层断言':624 '的结构图一致':2706 '的美学问题':3180 '的补充':3648 '的铁律':5205 '的验收检查表提取所有验收项':2620 '的验收检查表是':2630 '的验收计划':2678 '目标':4678 '直到':4301 '直接':176,1236,3377,3513 '直接使用':1572 '直接访问':3365 '直接访问带参数的':2531 '看起来不对但':3177 '硬性':4962 '硬等':3438,3485 '确保不再漏测':4254 '确实是收藏的':2369 '确实渲染了':2371 '确认':1788,4554 '确认元素在':2332 '确认后输出':1273 '确认执行':2842 '示例':4083 '空数据':3050 '空状态':4612 '空结果有空状态提示':2511 '章节':2615 '端到端用户流程测试':713 '端点':3257 '第':2426,5120,5219 '第0步':733,1217 '第1步':751,1858 '第2.5':762,1977 '第2步':755,759,1918 '第3步':770,2594 '第4步':777,2854 '第5步':781,2873 '第6步':818,3715 '第7步':822,3990 '第8步':4303 '第一节':2689 '第二节':2702 '第二节的结构图':4396 '等':1773,3491,3714 '等具体条件':3443 '等内容出现':3512 '等地址':673 '等待':2945,3447 '等待加载完成':2536 '等待用户回来反馈':4157 '等待用户验收':4542 '等待策略':3435 '等网络空闲':3524 '等骨架屏消失':3503 '简要描述修复思路':3822 '管理视图状态':3343 '类似风险清单':4103,4106 '类型':2558 '类型涉及应用运行时':533 '精确':3494 '系统性遍历所有页面':1849 '系统结构合规性':2698,4388 '紧凑裁剪':4601 '累积为项目回归测试基线':4261 '红绿重构':712 '约15':1807 '约15-30分钟':1806 '约30':1821 '约30-60分钟':1820 '约5':1795 '约5-10分钟':1794 '约束':2737,4132 '纯代码':4729 '纯代码测试':3702 '纯验收模式':6,71 '纳入':4249 '纳入回归基线':1946 '组件':2738,2824,4117,4402,4433 '组件列表完整':2708 '组件名':2744,2752,2758 '组件数':2823 '组合':1616,2298 '细节问题':3840 '终端报告':4505 '结构':2027,3135,4160 '结构化':114 '结构化后再执行':602 '结构化报告':4489 '结构化断言':3694 '结构化的':2591 '结构化结果':4492 '结构完全不同':1451 '结构选择器':1671 '结果':4410,4438 '结果包含关键词':2509 '结果态':4818 '结论':5041 '给出建议':1208 '绝不拒绝使用浏览器':4645 '绝不编造不存在的':2286 '统计崩溃率并推算总体影响':3108 '继承的能力':4723 '继续修复':5136 '维度':20,557,1864,3060,3089,3116,3143,3181,3212,3231,3249,3321,3412,4306 '维度代码模板':4660 '维度断言':722 '维度断言引擎和三种测试引擎':4726 '维度概述':3059 '维度测试执行':783,2875 '网格':3162 '网络':562,726,788,3931 '网络响应或数据变化断言':4897 '网络基础':2948 '网络契约验证':3118 '网络异常':3052 '网络拦截':3696 '网络请求':3663 '网络错误':3735,4534 '网络错误都要测':4614 '而不是当前':4978 '而是用户可读的验收计划':2602 '聚焦断言':2017 '聚焦测试':1844 '能发现':3077,3109,3136,3172,3204 '能拿到':4971 '能用但不够好':4226 '能获取时':4944 '脚本断言':4854 '脚本断言并行使用':3639 '自动':648,3072 '自动包含':4292 '自动化测不到设计意图偏差':4652 '自动化测试无法覆盖设计意图偏差':3997 '自动化测试范围':5019 '自动扫描':2546 '自动挂载':3065 '自动提取为':4048 '自动收集':3121 '自动标记为':4927 '自动登记':3965,3972 '自动选择':1829 '自动闭环交付给':3869 '自动闭环分类规则':3956 '自动闭环状态信号和退出':5082 '自定义':633 '自己仍然只测不修':3955 '自我调节':4642 '自检规则':2540 '至少一条':5110 '节':92,480,4839,4989 '节和':4837 '节点':4697 '节点存在':4892 '若':683,4855 '若验收项涉及浏览器':426,454 '范围':1968 '范围外低优先级问题':3981 '范围外问题或设计歧义时输出':5252 '行':4571,4581 '行为':1832,4036,4556 '行为断言和真实截图':2791 '行号':3731,3804,3856,4116,4124 '行更新为':4560 '补充':2309,2661 '表':4566 '表单':3276 '表单提交':2520 '被':3084 '被中断或目标不是浏览器页面':3624 '被替换为空':3457 '要一并修复吗':4141 '要求':4131 '要验什么':2604 '覆盖':3014,3034,3053 '覆盖率':1962 '见':64,90 '见下方':4052 '规则':1997,3746 '规范':60 '视图恢复':3002,3363 '视图正确切换':3401 '视图状态与参数一致':2533 '视图状态正确恢复':3382 '视觉':563,723,810,1804,2798,3019,3543,4774 '视觉上没问题不代表没有':4618 '视觉偏差':3740 '视觉合规':2833 '视觉合规结果':4432 '视觉合规验证':2731 '视觉呈现':1891,4338 '视觉意图参考':2774 '视觉稿':2766,3167 '视觉规则断言':3023,3145 '解析出':4751 '触发':2501,2986 '触发举一反三机制':4051 '触发入口':3274 '触发加载':3428,3470 '触发后':3286 '触发方':4691 '触发条件':94,1831 '触发消息里出现':181 '触控目标':3228 '警告':2649 '让用户先看整体是否符合预期':4359 '记录':77 '记录到报告':589 '设计':5138 '设计意图偏差':4213 '证据':2783,3799,3934,4385,4411,4850 '证据先于结论':638 '证据区':149 '证据可与':3637 '评估方式':1866 '评分方式':4308 '询问':1272 '询问用户':1265,5158 '详尽':1814,2967,3022,4515 '详情':2480 '详情面板':1760,2183 '详情面板有实质内容':2250 '详情面板有标题且文本长度':2224 '详情面板标题为空':2246 '详情面板自动打开':3395 '详细代码模板参考':2879 '详见':474,484 '详见下方':635 '语义化':1532,1638,1912,3504 '语义标签':1739,2294 '语义标签组合':1748 '语义正确但数据错误的响应':3142 '说明':4382,4392 '说明会用真实浏览器截图对比信息层级':2775 '说明哪些':2845 '请使用':1112,1136 '请用户确认':4137 '请验收后选择':4016 '读取':36,1924,1929,1935,1942,1948,2610,3579,4094,4234,4248,4548,4731 '读取报告全部内容':4746 '读取文档后提取版本号':1375 '谁':4229 '调度':107 '调度传入':1229 '调度层或':3940 '调用':35,138,4677 '调用方必须先运行':429,457 '调用时':167 '调用是否正确':4631 '调用来源':180 '调用模式':83 '负责':705,709 '负责用户视角证据':3629 '资源':3082,4654 '超长文本':3051 '超长输入':4613 '跑了':5020,5028 '跑自动化测试':4685 '跨模块集成测试':719 '路径':175,327,509,522 '路由':3332,3341,3739 '跳转':2526 '跳过':4009,4528 '跳过的节点':4705 '转化为':1989 '输入':95,548,1985,3565 '输入源':1987 '输入验证':3709 '输出':96,541,640 '输出与等待':3999 '输出中的':1115,1141 '输出以下内容并等待用户操作':4002 '输出到项目目录':4472 '输出映射':1986 '输出选择器映射表':1706 '边界':3402,4611 '边界条件':3049 '过滤':2507 '运行时':1066,1071 '运行项目已有的测试框架':3710 '返回':3477 '这会导致所有测试因选择器找不到而假性':1690 '进入':1238,3584,3967,3974 '进入发布流程':4019 '进度':3012,3460 '进度条':3291 '进行中':4561 '迭代模式':1920 '适用条件':3254,3329,3419 '选中':3384 '选择器优先级':1630 '选择器审计':746,1440 '选择器审计结果':1712 '选择器必须来自':2029 '选择器策略':1563 '选择器规则':2278 '选择性修复':4145 '选择理由':4771 '逐一验证':2981 '逐文件读取实现代码':3704 '逐步到达':3280 '逐步截图':4687 '逐步截图回填':151 '逐项验收结果':4406 '逐项验证':2710,2825 '通俗解释':1205 '通用测试引擎':4663 '通用等待模式':3481 '通过':1270,1786,2647,2808,3262,3344,3558,4005,4524,4569 '通过率':4427,4530 '遍历':3244 '遵循':55 '那一步由':4716 '那是':5166,5182 '那由':5173 '都适用':3426 '配合':29,4671 '配置':1964 '采样':2978,3098 '采样多条':4626 '采用以下结构':4358 '采集截图和':4848 '重放':5022 '重新聚焦':1200 '重新调用':1118,1144 '重现了':5068 '重要':2028 '重要规则':4590 '针对':38,4679 '铁律':580,747,768,1222,1441,1983,2311,2596,3994 '链接完整性':1881,4322 '错态覆盖':2778 '错误':4312,4620 '错误信息原文':3801 '错误分类':3724 '错误态':4819 '错误恢复':3314 '错误数量':1870 '错误详情':4426 '键盘导航':1910 '键盘导航验证':3242 '长期':4258 '闭环':5187 '问题':2365 '问题的根本原因':4110 '间距':1940,3029 '间距网格':2001 '间距违规':3174 '间距遵循':3160 '降级为':1385 '降级为从':2665 '降级模式':1382 '除非':3620 '需修复后重测':4586 '需关注':4540 '需求':5137 '需要先修正':2852 '需要可重复批量回归时':3634 '需要增减测试项':2844 '需要更强可重复性时':4851 '需要特定数据组合才触发的':3114 '需要看完整验收计划再决定':2847 '需要真实浏览器和用户视角截图':4784 '静态代码属性':4795 '面板内容过短':2271 '页面':2697,4387 '页面布局':1893 '页面结构合规性':2820 '页面能打开':5248 '项':2797,2800,2803,2828,2835,2840,4294,4463,4466,4469 '项目':4508 '项目使用':3330 '项目包含':3255 '项目包含分页加载':3420 '项目名':4509 '项目未使用':1718 '项目状态':1562 '项验收':2794 '预期值':2741,4436 '预期效果':4766,4822 '预计':2804 '频道':3372 '频道切换':2494 '颜色':1939,3028 '颜色错误':3175 '首尾':3104 '首屏加载':1901 '首页加载':2943 '首页加载后展示信息卡片':2128 '验收不通过':4021,4043 '验收与测试报告':5,70 '验收入口与环境身份校验':4838,4936 '验收入口与环境身份校验区':4762 '验收完成':846 '验收报告':4363 '验收标准':1969,1991 '验收标准逐项核对':728 '验收结论':4459 '验收计划':2681 '验收计划已生成':2811 '验收通过':4018,4031 '验收项':2712,4408 '验证':716,4629 '验证内容完整性':2184 '验证响应':3133 '验证数据正确性和功能完整性':2374 '验证进度文本格式正确':3464 '验证错误处理完整性':3706 '验证项':5038 '验证项性质':4769 '骨架屏':3422 '骨架屏消失':3444 '高':3831,3851,4332 '高中生能懂的语言描述问题':1206 '默认':196 '默认引擎':4770","prices":[{"id":"79771b68-9975-4bfa-84c4-3541d3821141","listingId":"891e8e48-24f0-4b0f-b97d-b0dab9a4a484","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"yike-gunshi","category":"forge-skills","install_from":"skills.sh"},"createdAt":"2026-04-24T07:03:38.743Z"}],"sources":[{"listingId":"891e8e48-24f0-4b0f-b97d-b0dab9a4a484","source":"github","sourceId":"yike-gunshi/forge-skills/forge-qa","sourceUrl":"https://github.com/yike-gunshi/forge-skills/tree/main/skills/forge-qa","isPrimary":false,"firstSeenAt":"2026-04-24T07:03:38.743Z","lastSeenAt":"2026-05-18T19:07:34.209Z"}],"details":{"listingId":"891e8e48-24f0-4b0f-b97d-b0dab9a4a484","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"yike-gunshi","slug":"forge-qa","github":{"repo":"yike-gunshi/forge-skills","stars":11,"topics":["agent-skills","ai-development","claude-code","forge","skill-md","skillsmp"],"license":"mit","html_url":"https://github.com/yike-gunshi/forge-skills","pushed_at":"2026-04-28T05:11:10Z","description":"Forge — 文档驱动的 AI 辅助开发框架 | Document-driven AI development framework with 14 Skills covering brainstorm → PRD → design → engineering → QA → review → ship → retrospective","skill_md_sha":"acad0a6fe360703824e95c2829acc1e1d052f197","skill_md_path":"skills/forge-qa/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/yike-gunshi/forge-skills/tree/main/skills/forge-qa"},"layout":"multi","source":"github","category":"forge-skills","frontmatter":{"name":"forge-qa","description":"QA 验收与测试报告。纯验收模式：测试+报告，不修代码。\n两种调用模式：\n  Mode A（完整 QA）：test-spec 生成 → 10 维度 Playwright 断言引擎 → 智能分析。\n  Mode B（单 bug 修复回归）：配合 forge-bugfix 的 P6 调用，读取 docs/bugfix/reviews/BF-XX.md，\n    针对 Bug 修复验收报告里的人工验收指南跑自动化测试，把逐步截图、深度断言、\n    前后端环境身份校验回填到报告。QA 全过 → 单 bug 模式进 P6.5，批量模式进入\n    qa-pass-pending-final-review；QA 有挂 → 通知 forge-bugfix 有界回 P5。\n核心原则：断言引擎模式，每个测试必须有 pass/fail，不允许 catch 吞错误；\n浏览器验收必须使用调用方传入或 dev-status 输出的 app_url，不猜 localhost 端口。\n在 Codex 环境中，如果 Browser Use 插件可用，前端页面/交互验收优先使用\nbrowser-use:browser 的 Codex in-app browser 采集用户视角截图和 DOM 证据；\nComputer Use 只作为 browser-use 不可用或非浏览器桌面应用场景的兜底。\n在功能开发后的 QA 自动闭环中，forge-qa 发现 bug 时必须产出结构化 bug 信息，\n供 forge-bugfix 创建 BF 报告并独立 worktree/TDD 修复。\n支持多种测试引擎：browser-use:browser、Playwright、gstack/browse、纯代码。\n触发方式：\n  Mode A：用户说\"测试\"、\"QA\"、\"forge-qa\"、forge-dev 调度器调用\n  Mode B：forge-bugfix 的 P6 调用（传入 review_doc 路径）"},"skills_sh_url":"https://skills.sh/yike-gunshi/forge-skills/forge-qa"},"updatedAt":"2026-05-18T19:07:34.209Z"}}