PostHog 前端 QA 实战:浏览器 MCP 模式与证据化验证指南
2026/9/10 22:01:29 网站建设 项目流程

PostHog 前端 QA 实战:浏览器 MCP 模式与证据化验证指南

【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog

本篇技术指南以 PostHog 仓库内qa-frontend技能集的 浏览器 MCP 模式参考文档 为主体,系统讲解如何用浏览器 MCP(Browser MCP)工具链对 PostHog 前端执行可复现、证据驱动的 QA 循环。你将掌握:浏览器 MCP 的接入与作用域选型、七步浏览器流程骨架、锁定配置文件与会话清理的排障纪律、以截图与控制台/网络信号为准的"证据优先"验证法、暗/亮主题切换、测试数据播种、Feature Flag 覆盖,以及从标注截图、WebP 演示胶卷到录制视频的完整证据产出流水线。文章结合仓库中 qa-frontend 技能 及其脚本源码,给出可直接照搬的命令、代码片段与可验证的文件依据。

一、浏览器 MCP:把浏览器当作 QA 的"眼睛"

qa-frontend技能集把浏览器 MCP/工具化能力定义为前端 QA 的唯一浏览器透镜,核心原则是:优先做用户可见的断言(user-visible assertions),而不是实现层面的断言。也就是说,验证一个改动是否生效,应该看页面上用户能感知到的文字、Toast、表格行、模态框状态、URL 变化,而不是去检查内部 state 或 DOM 结构细节。

在 browser-mcp-patterns.md 中,Playwright MCP 被明确定为仓库内的"已知可用"参考实现(known-good concrete example);Chrome DevTools MCP 或其他浏览器 MCP 同样适用,前提是它暴露了同一组基础原语:

  • navigate:导航到目标 URL
  • interact:与页面交互
  • evaluate:在页面上下文中执行 JavaScript
  • screenshot:捕获截图
  • console / network 信号检查:读取控制台与网络信号

这一要求的源码级佐证在 SKILL.md 的allowed-tools字段中:技能明确允许mcp__playwright__*mcp__chrome-devtools__*mcp__phrocs__*三个命名空间的 MCP 工具,其中mcp__phrocs__*用于本地开发进程状态检查(下文"控制台与网络信号分级"会用到)。

MCP 可用性检查与会话前置

技能要求在动手前先确认会话里是否真的有浏览器 MCP 工具:

  • 如果当前会话没有任何浏览器 MCP 工具,先停下来询问用户,而不是擅自配置。标准话术是:"我没有在会话中看到浏览器 MCP 工具。你希望我为这个 Agent 环境配置一个,还是你自己配置?如果由我配置,范围是仅限本仓库/工作区、用户级,还是你的客户端支持的其他范围?"
  • 作用域选型原则:优先选择"最窄的、不提交进仓库的"作用域(如客户端本地 scope 或用户级 scope)。绝不静默修改已入库的仓库级 MCP 配置(如.mcp.json,也不要用项目/仓库级提交作用域、更不要为了跑一次 QA 就把 MCP 配置提交进版本库。
  • 配置完成后,主动告知用户:重新运行qa-frontend之前,可能需要重连或重启 Agent 会话。

各客户端的具体示例在文档中被明确标注为"参考性指导,而非通用指令":

客户端本地作用域示例说明
Claude Codeclaude mcp add --scope local playwright -- npx -y @playwright/mcp@0.0.75本地 scope,不提交
Chrome DevTools MCP服务通常命名为chrome-devtools,在保留服务名的客户端中映射为mcp__chrome-devtools__*工具命名空间沿用客户端或仓库已有的浏览器 MCP 配置
Cursor 及其他客户端使用该客户端的本地或用户级 MCP 设置不用仓库提交式配置
Codex优先使用已暴露的浏览器工具;否则询问用户如何在 Codex 环境中配置浏览器自动化

二、浏览器流程骨架:七步标准 QA 循环

文档给出了一个可复用的浏览器执行骨架,以下工具名以 Playwright MCP 为例;使用 Chrome DevTools MCP 或其他实现时,换成该服务等价的 navigate、snapshot/DOM、evaluate、screenshot、console、network 工具即可:

  1. 导航:跳转到目标 URL,例如mcp__playwright__browser_navigate
  2. 读取响应:导航动作的返回通常自带一次自动快照(automatic snapshot),先读完它再决定下一步。
  3. 按需深查 DOM:当页面状态不清晰时,调用 snapshot/DOM 检查工具,例如mcp__playwright__browser_snapshot
  4. 交互:优先按 role、文本或无障碍快照引用(accessible snapshot reference)定位控件,优先可见控件而非 CSS 选择器——这呼应了"用户可见断言优先"的核心原则。
  5. 逐步断言:每次有意义的动作之后,立即对 UI 状态做断言:文本变化、Toast、表格行、模态框状态、URL 变化等任何可见结果。
  6. 截图留证:截图统一落入.qa-frontend/runs/<run-id>/目录(run 目录的命名规则见 SKILL.md 的 Run identity 小节:本地模式为local-<时间戳>,PR 模式为pr<编号>-<时间戳>)。
  7. 收集信号:读取页面 error 级控制台消息与网络失败记录。

这套骨架与 SKILL.md 中定义的 Frontend QA Loop 一一对应:navigate → snapshot → exercise the changed behavior → capture screenshot evidence → collect console errors → inspect relevant network failures。

锁定浏览器配置文件:基础设施阻塞,不是 QA 结果

如果浏览器 MCP/工具报告"浏览器配置文件已被占用"(browser profile already in use),应将其视为基础设施阻塞而非 QA 结论。处理流程:

  1. 优先切换到能启动全新隔离配置文件的 MCP/浏览器选项。
  2. 若是一个陈旧的本地浏览器进程占用了配置文件,在杀死进程或清除配置文件锁之前先询问用户
  3. 恢复后,重新打开目标路由,从头重做受影响的动作。
  4. 若锁无法解除,记录一条带有确切浏览器报错信息的 coverage gap(覆盖缺口),且不得声称该路由已被测试

红线:未经明确批准,不得删除浏览器配置文件数据,也不得关闭用户可见的浏览器窗口。

浏览器会话清理

每次 QA 结束时,如果浏览器 MCP/工具暴露了 close-page、close-context、close-browser 或 end-session 类动作,就关闭浏览器自动化会话,防止陈旧的 Chromium 会话长期占住配置文件锁、干扰后续 QA。

同样地,不要关闭用户可见的浏览器窗口。如果上一个 Agent 遗留的无头 Chromium 进程阻塞了运行,而 MCP 又没有关闭动作,先询问再杀,并且只瞄准 Agent 启动的浏览器进程。文档给出了识别 Agent 启动会话的命令行标记(command-line markers),用于在检查进程时向用户精确说明要终止什么:

  • ms-playwright
  • mcp-chrome-
  • remote-debugging-pipe
  • playwright-mcp

而用户可见的浏览器通常走正常浏览器配置文件,不属于这些标记。

三、Snapshot 与"证据优先"截图纪律

Snapshot 的克制使用

默认从一次默认快照开始,仅在以下情况才加深或滚动:

  • 目标元素很可能在首屏折叠线(below the fold)以下;
  • 折叠面板隐藏了被改动的功能;
  • 默认快照只有 loading 或空壳(shell)内容。

纪律要点:在检查过合理的滚动或标签页状态之前,不得声明某元素不存在——元素"缺席"必须是在已穷尽合理视图状态之后才能下的结论。

Proof-First 截图:每张图都要"自证"

Proof-First(证据优先)是本文档最核心的截图原则:每一张截图都必须能可见地证明它所支撑的那条覆盖行(coverage row)。拍摄之前,先确定能让该用例通过或失败的具体元素——精确的文本、控件、表格行、图表、Toast、表单状态——然后:

  1. 等待这个证明元素出现;
  2. 必要时滚动到可视区;
  3. 截图时带上足够的上下文,让审查者能看懂路由与状态。

对长页面、落地页(landing pages)、定价页、文档页等"hero 引导式"布局,假设首屏只是设置上下文而不是证明:只截 hero 区域不能作为页面下方 gate、表单、警告或 CTA 状态的有效证据。应滚动到被改动的区域再截,或使用整页截图——前提是整页截图仍可读、证明区域容易找到。

每次截完候选图后,在标注或上传前先检查保存的文件。若证明被裁掉、被 banner 或字幕遮挡、太小无法辨认,或画面大部分是导航栏、调试边框、无关页面设置,就重截。如果截图需要一个图注来解释术语,就在报告里补一句简短说明,而不是只靠图本身。

四、Console 与网络信号:分级与甄别

建立基线再对比

页面初次加载后先收集一份基线控制台快照(baseline console snapshot),目标动作执行后再对比。只有满足以下条件的新错误才算相关:出现在目标交互之后,或明确属于被锻炼到的端点

已知的、动作前就存在的第三方噪音,如果它不影响被改动的流程,可以忽略。

区分本地栈噪音与 PR 引入的错误

在对任何控制台输出打分之前,先通过 phrocs MCP 检查进程相关的开发状态(这是 SKILL.mdallowed-toolsmcp__phrocs__*的典型用途):

  • mcp__phrocs__get_process_status(process="backend")
  • mcp__phrocs__get_process_status(process="frontend")
  • 错误所指的进程,例如capturefeature-flagstemporal-workermcp

注意:不要依赖启动期间的"全进程状态"(all-process status)——进程级调用可能已经可用,而全进程状态仍不稳定。

只有当下游进程停止/崩溃能解释这些错误时,才按以下常见模式降权处理:

常见错误可解释的本地进程状态
capturecapture-aicapture-replay端点出现 502这些进程为stoppedcrashed
invocations / hog flow 路径出现 500posthog-node(CDP)或temporal-worker进程宕机
/decide、remote-config、feature-flag 端点出现Failed to load resource: 404feature-flagsflags-consumer已停止
开发环境第三方脚本导致的 CORS 或字体 CDN 失败

判定范围(in-scope vs out-of-scope)

  • 范围内(值得标记):错误触碰了 PR 实际改动的代码路径,无论它何时触发——包括初始挂载时、任何用户交互之前。首渲染就抛异常的场景、加载时就请求了错误端点的场景,是真实 bug 而非既有噪音。受影响界面在加载时报错,与点击/提交后的报错享有同等审查权重。
  • 范围外(值得降权):错误能被上表列出的本地进程停止状态解释,或来自与 diff 无关的第三方脚本。

关键纪律:降权时必须把分级结论显式写进 run notes 和 PR 评论(例如"所有控制台错误均追溯到此机器上 capture 进程已停止;本 PR 未引入新错误")。静默吞掉控制台输出会侵蚀报告的可信度。

页面上下文辅助(Page Context Helpers)

  • 只有为了设置或检查可见流程所需的前端状态时,才在浏览器页面上下文里使用已认证的fetch。Cookie 与 CSRF 状态来自浏览器会话。不要把它变成一套独立的后端测试计划。
  • 仅在无认证健康检查(如_health)时使用 shellcurl

五、可复现性:一次强制重试

任何"发现"成立之前,必须重试一次

  1. 只重置该步骤所需的本地页面状态;
  2. 重跑同一动作序列;
  3. 捕获全新证据;
  4. 确认同样的"期望 vs 实际"错配。

如果第一次失败、重试通过,且重试成本很低,再跑一次。此时不要把它报告为已确认发现,但也不要隐瞒:给它独立的 coverage 行,结果标注为INTERMITTENT,把第一次失败的证据保留在 run 目录里,并在 run notes 中描述观察到的现象。文档给出的理由很直接:"一个读起来像干净 PASS 的真实竞态(race),比一行诚实的 INTERMITTENT 更侵蚀信任。"

六、主题切换(Theme Toggle):暗/亮变体的可靠开关

要锻炼一个场景的暗/亮变体,正确做法是从页面上下文 PATCH 已认证用户的theme_mode并重新加载——这是应用内主题切换器走的同一条路径,也是唯一可靠的杠杆:

// via the browser MCP evaluate tool, in the authenticated page context ;async () => { const csrf = document.cookie.match(/csrftoken=([^;]+)/)?.[1] const r = await fetch('/api/users/@me/', { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': csrf }, body: JSON.stringify({ theme_mode: 'dark' }), // or 'light' / 'system' }) return { status: r.status, theme_mode: (await r.json()).theme_mode } }

然后导航到目标路由(导航会重载 kea state)。<html>上带有服务端渲染的data-boot-theme属性(检查document.documentElement.dataset.bootTheme可看启动状态),但运行时切换不会更新它——验证切换是否生效,应读取计算后的背景色:kea state 直接驱动 CSS 变量,且 PostHog不会在运行时设置darkclass 或data-theme/data-color-mode属性。

;() => getComputedStyle(document.body).backgroundColor // dark: ~rgb(19, 19, 22); light: ~rgb(243, 244, 240)

明确不要尝试这些路径(文档逐一给出了理由):

  • document.documentElement.classList.add('dark')——themeLogic不读它;
  • data-theme/data-color-mode属性 —— 不被查询;
  • window.getKeaContext()—— 生产构建不暴露;
  • 单独使用emulateMedia({colorScheme:'dark'})—— 仅当用户theme_mode === 'system'时才生效,而种子用户默认是null/'light'

运行结束时恢复原始theme_mode(通常是'light',让开发环境保持原样。

七、播种测试数据(Seeding Test Data)

如果一个 PR 添加的是"显示 X 的计数 / 按 Y 过滤 / 当 Z 时高亮行"之类的行为,它往往依赖全新本地栈中不存在的数据形态。空态(empty states)渲染没问题,但 diff 内的行为永远不会被触发。在声明覆盖之前,先播种锻炼该改动所需的最小数据,否则这次运行是 coverage gap,而不是 PASS。

两个后端存储

  • Postgres:应用模型(surveys、dashboards、cohorts、data warehouse sources、feature flags、organizations 等)。通过 shell 驱动 Django ORM,保持模型不变量(model invariants)完好:

    flox activate -- bash -c "uv run python manage.py shell <<'PY' from posthog.models import Team team = Team.objects.first() # create the minimum rows needed to exercise the diff PY"
  • ClickHouse:事件、人员属性、会话录制、LLM spans 等。优先使用 posthog/test/ 与 posthog/clickhouse/ 下现有的工厂工具;只有当没有工厂覆盖所需形态时,才退回到裸INSERT INTO ... VALUES (...)

播种纪律

  • 播种最小集合,不要批量灌入类生产规模的数据;
  • 给播种行打上可识别的标记(名称前缀、固定描述等),便于日后识别与恢复;
  • 播种后重新加载受影响的场景,断言 UI 现在反映了你设置的数据形态;
  • run-notes.md和 PR 评论的"What was tested"行里注明播种步骤,让审查者知道创建了哪些前置条件;
  • 默认不删除播种行(留给调试),只有用户明确要求时才清理。

八、Feature Flag 覆盖:不碰后端,页面上下文直接 override

如果 PR 行为被某个种子用户项目尚未启用的 Feature Flag 门控,新 UI 会一直隐藏,QA 循环永远锻炼不到它。此时可以从已认证的浏览器页面上下文直接覆盖该 flag,无需后端改动:

// Enable a boolean flag posthog.featureFlags.overrideFeatureFlags({ flags: { 'my-flag-key': true } }) // Set a multivariate flag to a specific variant posthog.featureFlags.overrideFeatureFlags({ flags: { 'my-flag-key': 'variant-name' } }) // Clear all overrides posthog.featureFlags.overrideFeatureFlags(false)

操作流程:通过浏览器 MCP 的 evaluate 工具在已认证页面上下文发出上述调用 → 导航到目标路由(导航会重载 flag 驱动的渲染)→ 用 snapshot 确认门控 UI 已出现。QA 循环结束时调用overrideFeatureFlags(false)清除覆盖,保持开发环境原样,并在run-notes.md与 PR 评论中注明 override 步骤,让审查者知道测试是在非默认 flag 状态下运行的。

九、证据命名、标注与演示胶卷

证据命名:稳定可读

所有证据统一放在.qa-frontend/runs/<run-id>/下,保持未提交(uncommitted)状态,命名要稳定、可读:

.qa-frontend/runs/<run-id>/001-login.png .qa-frontend/runs/<run-id>/011-save-click-failure.png .qa-frontend/runs/<run-id>/011-save-click-failure.annotated.png .qa-frontend/runs/<run-id>/frontend-qa.webp .qa-frontend/runs/<run-id>/console-errors.json

截图优先使用 PostHog 工作区现有的浏览器工具:活动浏览器 MCP/工具,或仓库已有的@playwright/test依赖。不要package.json里添加截图、图片或视频类依赖包。

标注证据:让每帧自解释

原始截图要求审查者脑补发生了什么,所以关键帧必须标注:截图下方加图注条(说明这一步做了什么)、PASS/FAIL/INFO 芯片,发现(finding)还要在关键元素周围加高亮框。仓库自带的 annotate-evidence.py 用仓库已有的 Pillow 依赖同时完成标注与动画两种工作,用uv run python从可信检出(例如技能目录所在仓库)运行,绝不在 PR 检出里运行——uv run会解析那个工作树的依赖。不要用ffmpeg或为证据处理安装任何东西。

该脚本源码确认了三个子命令:annotate(图注条 + PASS/FAIL/INFO 芯片 + 高亮框)、animate(拼装动画 WebP,可带 GIF 兜底)、video(把录制 WebM 转码为 H.264 MP4,需要本机 ffmpeg)。标注样式直接采用 PostHog 产品色板(frontend/src/styles/base.scss 中的品牌红#f54e00高亮、--success/--danger芯片、品牌黑条 + 奶油色文字),与 cursor-overlay.js 中的颜色保持同步(两处源码都有"keep in sync"注释)。

要标注关键区域,先通过浏览器 MCP evaluate 工具抓取元素的 CSS 像素 rect,连同视口宽度(供 HiDPI 缩放):

;() => { const el = document.querySelector('<selector for the element that matters>') const r = el.getBoundingClientRect() return { x: r.x, y: r.y, w: r.width, h: r.height, viewportWidth: window.innerWidth } }

然后标注该帧。保留原始 PNG,标注副本写在其旁边:

uv run python "<skill_dir>/scripts/annotate-evidence.py" annotate \ --input "$RUN_DIR/011-save-click-failure.png" \ --caption "Clicked Save - no toast, no network call" \ --step 3 --status fail \ --highlight 840,220,320,88 --viewport-width 1280

要点:--highlight可重复且可选,整帧都是故事时可省略。由于浏览器是通过元素引用驱动的,截图里永远不会出现光标——当一帧展示交互时,加--click X,Y(被点击元素的中心点)绘制带点击环的光标,读者才能看到动作发生在哪里。--click用于交互,--highlight用于结果区域,同一元素同时加两者是冗余的。图注陈述"发生了什么、意味着什么",而不是内部代号。

Demo Reel:2~5 帧慢速动画 WebP

浏览器或视觉目标捕获两张以上截图后,把 2~5 个已标注关键帧拼成慢速动画 WebP。WebP 在远小于 GIF 的体积下保留完整 24 位色彩,且 GitHub 在 PR 评论中内联渲染动画 WebP:

uv run python "<skill_dir>/scripts/annotate-evidence.py" animate \ --frame "$RUN_DIR/003-state-a.annotated.png:1500" \ --frame "$RUN_DIR/011-save-click-failure.annotated.png:2500" \ --frame "$RUN_DIR/014-state-c.annotated.png:1500" \ --output "$RUN_DIR/frontend-qa.webp"

只收录审查者跟读流程所必需的帧——在有意义时刻之间跳过死时间正是拼接胶卷的意义。每个状态变化都需要成因在画面里:在出现/变化了某物的帧之前,前一帧必须在引起该变化的控件上带--click标记。凭空出现、看不到点击的副本读起来是困惑而非证据——重试帧也适用此规则,重试本身也是独立的因果对。发现(finding)帧给更多放映时间。

脚本实现细节(源自 annotate-evidence.py):宽度上限 1200px,混合高度帧用底部锚定补齐而非拉伸(保证每帧图注条位置一致),默认每帧 1800ms,输出时打印文件大小。3~5 帧 1200px UI 截图的胶卷可稳稳落在 200 KB 以下。只有当确实需要 GIF 兜底时才加--gif <path>,同样帧数的 GIF 体积会大数倍。

上传或嵌入胶卷之前,用 Read 工具或直接打开检查它。如果文字不可读、序列不如静帧清晰,就把标注 PNG 作为证据。

十、录制演示通道(Recorded Demo Pass):默认视频输出

WebP 胶卷像 GIF 一样自动播放,无法暂停或拖动进度。真正的视频只有在展示"人眼所见"时才值得:平滑的页面过渡 + 可见光标移动到每个控件。元素驱动的自动化不渲染任何光标——截图和会话录制里都没有——所以 QA 循环的原始录制又跳又难跟。不要用拼接静帧的方式做视频,那只是一个可暂停的胶卷。

默认做法:QA 循环稳定后,跑一遍演示通道(demo pass)——重新执行关键流程一次,开启录制并注入可见光标。仅当设置了NO_VIDEO、浏览器工具无法录视频、或缺少ffmpeg时才跳过——绝不静默跳过:在 run notes 和报告 Setup 节中说明跳过原因。

六步演示通道

  1. 开始录制:优先用浏览器工具的原生录制(agent-browser 可用时用agent-browser record start "$RUN_DIR/demo.webm";或用 Playwright MCP 视频捕获PLAYWRIGHT_MCP_SAVE_VIDEO=1280x720,它暴露带 chapter markers 的browser_start_video/browser_stop_video)。两者都不可用时,先询问再重新配置,然后跳过视频模式而不是即兴发挥。

  2. 等待页面恢复可用:开始录制通常会重建浏览器上下文、重载页面;冷开发服务器上这次重载可能很慢。轮询标记元素而不是固定 sleep。首次动作之前录到的都是要修剪的片头。

  3. 注入光标叠加层:用浏览器工具的 evaluate/eval 把仓库脚本 cursor-overlay.js 注入页面。它绘制跟随真实鼠标事件的光标、点击时产生涟漪、显示图注条,并暴露window.__qaCursor。叠加层纯视觉(pointer-events: none),且每次导航后都必须重新注入

  4. 整段流程写成一次连续批处理:步骤之间的停顿全都会上镜。每步:设图注 → 滑行(glide)→ 涟漪(ripple)→ 点击 → 短暂定格。图注讲述与标注静帧相同的故事(步骤号、发生了什么、pass/fail):

    window.__qaCursor.caption('Step 2 · Clicking Duplicate on Question 1', 'info') const r = el.getBoundingClientRect() await window.__qaCursor.glide(r.x + r.width / 2, r.y + r.height / 2, 650) window.__qaCursor.ripple(r.x + r.width / 2, r.y + r.height / 2) el.click()

    如果会话中真实输入事件不可靠(agent-browser daemon 的已知怪癖),程序化el.click()加显式ripple()在影片上看起来一模一样。注意:图注条覆盖页面底边,而 PostHog 的 Toast 和部分操作按钮锚定在底部——当某步的证明是底部锚定元素时,用window.__qaCursor.caption(null)在该节拍清掉图注,之后再恢复,确保录制从不遮挡它要展示的结果。这些能力在 cursor-overlay.js 源码中均有对应实现(caption/glide/ripple/moveTomousemove/mousedown监听器)。

  5. 停止录制、修剪片头并转码

    uv run python "<skill_dir>/scripts/annotate-evidence.py" video \ --input "$RUN_DIR/demo.webm" \ --output "$RUN_DIR/frontend-qa.mp4" \ --trim-start <lead-in seconds>

    --trim-start使用 ffmpeg 输出定位(output seeking),从头解码、帧级精确裁剪。绝不要自己用输入定位(-ss/-sseof放在-i之前)修剪 WebM:录屏 WebM 关键帧非常稀疏,输入定位会大幅偏离请求点,静默平移整个时间窗。脚本源码中video子命令正是把-ss放在-i之后的输出定位实现,并附加scale + yuv420plibx264 veryfast crf 26-movflags +faststart等参数。

  6. 发布前验证视频:Agent 看不了视频,所以渲染一张帧联系表(contact sheet)来检查:

    ffmpeg -y -i "$RUN_DIR/frontend-qa.mp4" \ -vf "fps=1,scale=420:-1,tile=5x2" -frames:v 1 /tmp/qa-video-sheet.png # fps=1 with tile=5x2 covers 10 seconds; for longer clips raise the tile # (tile=5x4 for 20 s) or lower fps - the sheet must reach the final frame

    联系表必须显示:前几秒就有图注条、每一步的图注按顺序出现、帧间有运动(没有大段相同空闲帧)、最后持有最终 finding 状态。不满足就修正裁剪再查;不要分享未验证的视频

视频输出与分享约束

  • 转码需要本机ffmpeg;缺失则保留 WebM 并在 run notes 中说明。15 秒 1280px 演示视频大约 300 KB;MP4 控制在 ~10 MB 以内,保证能直接拖进 GitHub 评论。
  • 不要尝试在 Agent 发布的评论里自动内嵌视频:GitHub 只为通过网页编辑器手工上传的文件渲染播放器,raw 托管的 MP4 链接按下载处理、不可播放。MP4 从本地报告链接出去;PR 模式下可经hogli pr:upload-video进入已批准的上传集(评论里是下载链接),开发者仍可把文件拖进评论编辑器获得内联播放器。
  • 叠加层只用不透明品牌色,明暗主题下可读性一致。

十一、证据上传与输出纪律(配套参考)

证据产出的最终归属与上传纪律由配套参考 evidence-and-output.md 定义,与本文档的浏览器模式紧密咬合:

  • 上传仅限 PR 模式且必须显式批准:用仓库自带上传器hogli pr:upload-image(png/jpg/gif/webp,10 MB 上限),上传到公开的PostHog/pr-assets仓库并打印alt行。上传是公开且永久的(URL 经 SHA 固定,删除后仍持续服务,不可撤回),所以上传前必须向用户展示确切文件清单并取得批准。第一个不带--yes的运行只打印警告、故意不传;--yes即"用户已批准这组文件"的确认,未经批准绝不传入。
  • 只挑人眼可见的证据frontend-qa.webp(若生成且检查可读)+ 1~3 张与 findings 或 PASS 叙事匹配的标注关键截图;不上传.md快照、console.log或每一张编号截图。MP4 走hogli pr:upload-video --yes --label "demo video"
  • 运行产物:每次运行必须写findings.json(结构化 findings 数组,PR 评论与本地报告都是它的渲染结果)并在 stdout 首行输出QA-VERDICT: <verdict>(取值PASS/FIXED/FAIL/NEEDS-INTENT/REPORT-ONLY),供外层编排器 grep。coverage_gap条目必须作为测试计划表中的可见行呈现,而不是页脚备注。
  • run-notes 贯穿始终:栈选择、工作区与登录、org/plan 状态、创建/播种的数据、flag/主题覆盖、降级的进程等所有设置,都随发生追加到.qa-frontend/runs/<run-id>/run-notes.md,报告必需的 Setup 节正是从这些笔记渲染而来。
  • 安全边界:safety-rules.md 强调.qa-frontend/下的证据绝不 stage 或 commit(老 PR 分支上该目录未被 gitignore,git add -A会把本地栈截图卷进 fix 提交);控制台摘录发布前必须擦除Bearer <token>?token=sk-*、长 base64 值、cookie/会话 ID/CSRF token;不上传包含邮件、工作区名、仪表盘内容或渲染 token 的截图。

十二、总结:从"跑一遍"到"可审查的证据链"

浏览器 MCP 模式把 PostHog 前端 QA 从随意的"点一点、截个图"升级为一条可复现、可审计的证据链

  1. 流程标准化:七步浏览器骨架(navigate → snapshot → interact → assert → screenshot → console/network)让每次 QA 覆盖同样的关键动作;
  2. 证据可自证:Proof-First 截图 + 图注条/PASS-FAIL 芯片/高亮框标注 + WebP 胶卷,让审查者无需重放会话即可读懂运行;
  3. 噪音可甄别:通过 phrocs 进程状态把"本地栈崩溃导致的错误"与"PR 真正引入的错误"区分开,降权结论必须显式写入报告;
  4. 状态可控:theme_mode PATCH、最小数据播种、Feature Flag override 三个"前置条件"杠杆,确保 diff 内行为在种子环境下真正被触发;
  5. 安全有边界:浏览器 MCP 作用域最窄化、不提交 MCP 配置、配置文件锁需询问、上传需批准——QA 全程不触碰用户可见浏览器与已入库配置。

这些模式的完整实现与配套脚本(标注/动画/转码工具 annotate-evidence.py、光标叠加层 cursor-overlay.js、技能总纲 SKILL.md)都保留在当前仓库中,可作为其他项目搭建"证据驱动前端 QA"体系的直接参考。

【免费下载链接】posthog:hedgehog: PostHog is the leading platform for building self-driving products. Our developer tools – AI observability, analytics, session replay, flags, experiments, error tracking, logs, and more – capture all the context agents need to diagnose problems, uncover opportunities, and ship fixes. Steer it all from Slack, web, desktop, or the MCP.项目地址: https://gitcode.com/GitHub_Trending/po/posthog

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询