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