PostHog 前端 QA 证据输出与报告规范:从截图采集到 PR 评论的完整管线
2026/9/10 18:34:37 网站建设 项目流程

PostHog 前端 QA 证据输出与报告规范:从截图采集到 PR 评论的完整管线

【免费下载链接】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技能的核心收尾阶段——evidence-and-output.md 展开,系统讲解前端浏览器 QA 跑完之后的三件事:如何安全地上传证据(hogli pr:upload-image/hogli pr:upload-video)、如何产出机器可解析的findings.jsonQA-VERDICT产物、以及如何渲染出符合模板的 PR 评论与本地报告,并最终通过审批门推送修复提交。读完你将掌握一条可复制的证据治理流程:采集 → 审查 → 上传 → 渲染 → 审批推送,并理解其背后的源码实现与安全护栏。

一、整体定位:QA 循环的最终阶段

qa-frontend是 PostHog 仓库内置的前端/浏览器 QA 技能(入口见 SKILL.md),运行在两种模式下:

  • PR 模式:针对某个 PR(URL/编号/分支)执行浏览器 QA,可上传证据、在审批后发布一条 PR 评论并推送修复。
  • 本地模式:针对当前分支与未提交改动执行 QA,只写本地报告,绝不上传、评论或推送。

本文档(evidence-and-output.md)是该技能在 "QA loop 完成、结论尘埃落定之后" 才加载的参考文件,负责证据上传、机器产物(findings.json+QA-VERDICT)、报告渲染与推送审批四个环节。它与其他参考文件构成完整闭环:

  • safety-rules.md:硬性审批门与推送策略,本指南中的"审批"均来自它的定义;
  • pr-comment-template.md:PR 评论与本地报告的统一模板;
  • browser-mcp-patterns.md:浏览器执行、控制台排查与证据采集的具体模式;
  • cleanup.md:报告写完后对 checkout、浏览器会话、栈与生成文件的清理。

二、证据上传:hogli pr:upload-imagepr:upload-video

2.1 基本规则

上传是PR 模式专属行为,且可选。任何文件离开开发者机器之前,必须先获得用户的显式批准;本地模式永远不上传证据。上传使用仓库自带的hogli pr:upload-image命令,它把文件推送到公开的PostHog/pr-assets仓库,并为每个文件打印一行alt形式的 Markdown,可直接粘贴进 PR 评论。

2.2 命令与参数

# 上传图片(png/jpg/jpeg/gif/webp,最大 10 MB,含动画演示卷轴 frontend-qa.webp) hogli pr:upload-image --yes \ ".qa-frontend/runs/<run-id>/frontend-qa.webp" \ ".qa-frontend/runs/<run-id>/<screenshot>.annotated.png" # 上传演示视频(mp4/webm,同样 10 MB 上限与 --yes 审批门) hogli pr:upload-video --yes --label "demo video" \ ".qa-frontend/runs/<run-id>/frontend-qa.mp4"

源码级细节(upload_image.py)明确了参数与限制:

  • 允许的图片扩展名pngjpgjpeggifwebp不含 svg——因为raw.githubusercontent.com会以text/plain提供 SVG,GitHub 无法内联渲染;
  • 10 MB 上限:与 GitHub 对图片/GIF 附件的内置上限一致;
  • --alt指定图片的 Markdown alt 文本,--pr可显式指定关联的 PR 编号(默认取当前分支的 open PR);
  • --yes(隐藏参数)是审批门的落点:第一次不带--yes运行只会打印公开性与永久性的警告并停止,什么都不上传--yes代表"用户已批准这一组确切的文件",绝不能在对话中出现该批准之前传入。

视频命令(upload_video.py)只接受mp4webm,用--label指定链接文本,打印的是普通label链接行。由于 GitHub 对 raw 托管的视频不渲染播放器,该链接是"点击下载"式的:若想要行内播放器,仍需开发者手动把文件拖进评论编辑器。

2.3 存储实现:为什么 URL 是 SHA 固定且永久的

pr:upload-image/pr:upload-video共用一个存储层 pr_assets.py。其核心设计:

  • 对象键YYYY/MM/<uuid4>.<ext>(UTC 时间),随机命名避免冲突,按日期分目录便于浏览与清理(make_key);
  • 单次签名提交:所有文件打包进一次提交,通过 GitHubGraphQLcreateCommitOnBranchmutation提交,而非 REST contents API——因为该仓库要求签名提交,GraphQL 路径由 GitHub 用自己的密钥签名;REST 路径以调用者身份未签名提交,会被 ruleset 拒绝(见模块 docstring);
  • URL 固定:返回的 URL 形如https://raw.githubusercontent.com/PostHog/pr-assets/<oid>/<path>钉死在提交 SHA 上,因此即使文件之后被移动或删除,URL 依然持续服务——这正是一旦上传便无法收回的根本原因;
  • 并发容错:mutation 携带expectedHeadOid,若并发提交先落地则报STALE_DATA,代码会重读分支头重试,最多 5 次(_MAX_ATTEMPTS);
  • 安全校验validate):拒绝符号链接(防止screenshot.png指向.env之类的敏感文件被上传)、拒绝不支持的扩展名、拒绝超限文件;
  • 认证:从GH_TOKEN/GITHUB_TOKENgh auth token获取 token,只需要对 PostHog 组织仓库有写权限(开发者日常的gh登录即可),无需额外密钥。token 缺失或权限不足时给出明确报错(见_denied_message,提示gh auth refresh -s repo或配置带reposcope 的 PAT)。

2.4 上传前必须做的证据审查

上传是公开且永久的披露行为,命令每次运行都会打印警告(PUBLIC_WARNING常量)。因此在请求上传批准之前,必须:

  1. 像发布那样检查最终证据:每张图必须让读者不重放浏览器会话就能理解其对应的 PASS/FAIL/SKIP/NEEDS INTENT 行。如果图片只显示页头、hero、空壳或设置状态,而真正的证明在折叠线以下或小到不可读,则不要上传;应重新截图、通过浏览器定位滚动裁剪,或先做更清晰的标注静态图。
  2. 只挑人可读的证据frontend-qa.webp(仅在生成且确认可读时)、1–3 张与结论或 PASS 叙事匹配的关键标注截图。不传.md快照、console.log或每张编号截图。
  3. 不泄露敏感信息:只上传不含密钥、私有客户数据或无关本地上下文的已审查证据。
  4. 对刻意造的数据补充说明:当截图使用了技术上有效但不易自解释的测试数据(边界邮箱语法、编码 URL、时区边界、合成计费状态)时,在报告的证据或覆盖行附近加一句解释。

2.5 在可信目录运行上传命令

PR 模式下工作树持有的是 PR 的代码,./bin/hogli会执行 PR 的代码,因此上传命令必须从可信的树运行,绝不能从 PR checkout 运行。正确做法是:先恢复原分支(上传和评论本来就在 QA 循环之后发生),或从另一个处于自己分支的独立 checkout 调用 hogli。

2.6 上传失败的处理

如果命令失败(无 token、无组织访问权限、网络问题):不要自写上传器,也不要在 PR 评论中暴露本地文件系统路径;记录evidence captured locally; upload failed or was skipped(证据已本地采集;上传失败或已跳过)并继续。绝不让上传失败阻塞整个运行。本地报告仍可引用本地相对路径。

PR 评论中要逐字使用命令打印的 Markdown 行,不要重建或编辑 URL(见 pr-comment-template.md 的 Evidence URLs 一节:URL 是 SHA 固定的raw.githubusercontent.com/PostHog/pr-assets地址,禁止重构、缩短或修改;上传失败时回退到本地路径并追加(upload failed))。

三、必需产物:findings.jsonQA-VERDICT

每次运行在渲染任何面向用户的内容之前,必须写出两个产物:

  1. .qa-frontend/runs/<run-id>/findings.json——结构化的 findings 数组,PR 评论和本地报告都是这个文件的渲染结果;
  2. stdout 第一行输出QA-VERDICT: <verdict>——让外层编排器无需解析 Markdown 就能 grep 状态。

verdict 词与模板(pr-comment-template.md)中的完全一致:PASSFIXEDFAILNEEDS-INTENTREPORT-ONLY。fork PR 与仅评论的运行使用REPORT-ONLY并携带reason=token。示例:

QA-VERDICT: PASS QA-VERDICT: FIXED findings=1 fixes=1 QA-VERDICT: FAIL findings=3 fixes=0 coverage_gaps=2 QA-VERDICT: NEEDS-INTENT ambiguities=1 QA-VERDICT: REPORT-ONLY findings=1 reason=fork

findings.json的 schema:

{ "id": "<sha1(target+step)[:12]>", "kind": "finding|coverage_gap|needs_intent", "severity": "high|medium|low", "confidence": "high|medium", "target": "/route", "step": "user-visible step", "expected": "expected outcome", "actual": "actual outcome", "evidence": ["<uploaded url or local path>"], "status": "new|fix-applied|suggested-patch|skipped|needs-intent", "fix_commit": "<sha or null>", "question": "intent question for needs_intent entries" }

字段语义要点:

  • idsha1(target+step)截取前 12 位生成,保证相同目标与步骤的 finding 可稳定去重;
  • coverage_gap条目记录 QA 循环无法执行的路由或文件,它们必须作为 PR 评论测试计划表中的可见行出现,而不是页脚备注;
  • needs_intent条目记录观察到、但无法确立预期结果的行为:本地模式在条件允许时应先问用户再定稿;PR 模式应把这类条目显式渲染出来,而不是把运行称作干净的 PASS。

QA 循环中确认的 finding 是上述 schema 的严格子集(渲染时会补上idkindconfidencestatusfix_commit),被清洗过的控制台摘录留在运行笔记中,只引用在报告正文,放进findings.json

四、渲染:PR 评论与本地报告

4.1 渲染前的强制动作

  • 重读模板:在撰写评论或本地报告之前,重新阅读 pr-comment-template.md,不要凭记忆即兴发挥。
  • 持续记录运行笔记:整个运行过程中,把创建或依赖的每项设置追加到.qa-frontend/runs/<run-id>/run-notes.md(与所有其他产物同一目录):栈选择、工作区与登录、org/计划状态、创建或播种的数据、flag/主题覆盖、降级进程。报告必需的 Setup 章节就是从这些笔记渲染的——它是读者决定是否信任每个 PASS 的依据。
  • 发布前完整性检查:渲染后的报告必须满足——第一行是## PostHog QA Frontend Report,第二行是匹配模板的 verdict 行,最后一行是<sub>PostHog QA Frontend Report</sub>。缺少任何一项就重新读模板再渲染。

4.2 PR 模式评论规则

PR 模式在显式批准后为每次完成的运行发布一条 PR 评论,按结果分型:

  • 干净运行:PASS verdict + 覆盖表;
  • 有把握的修复:已推送的修复摘要 + findings 与证据;
  • 低置信度或 fork PR:带复现步骤与建议补丁的 findings;
  • 预期行为不明确:NEEDS-INTENT verdict + 可见的 intent 行;
  • 前端目标有缺口:显式的 coverage-gap 行。

任何推送之前,先用只读的gh api可达性检查验证评论路径,不要创建临时桩评论。若评论连通性失败,跳过推送、把最终评论 Markdown 打印到 stdout 然后停止。

4.3 本地模式报告规则

本地模式把渲染报告写到 stdout 和.qa-frontend/runs/<run-id>/report.md,使用同一模板,但:

  • 省略上传步骤;
  • 证据只以本地路径引用,作为相对于报告文件的可点击 Markdown 链接(参见模板中的 local-report links 规则,如before可在编辑器预览中内联渲染,demo reel可点击打开);
  • 不调用gh apigh pr comment或任何推送。

五、推送审批门:修复提交如何落地

PR 模式、同仓库 PR、且至少有一个高置信度修复提交时才适用:

  1. 自动推送:如果$ARGUMENTS中设置了AUTO_PUSH_FIXES,直接进入推送步骤。自动推送同时也意味着对"修复摘要 PR 评论"的批准——没有披露修复的评论,就绝不推送修复;评论发不出去就不推送。
  2. 人工确认:否则,在修复循环完成且复验通过后,停下来在对话中询问用户:"Apply fix commit(s) <sha-list> to the PR branch? (y/n)"。等待明确的 "yes" / "y" / "push" 或类似确认。"no" / "n" / 沉默 = 不推送。此时输出带本地提交 SHA 的评论草稿,并注明用户可以手动推送。
  3. 普通非强制推送
PR_HEAD_REF=$(gh pr view "$PR_REF" --json headRefName --jq '.headRefName') test -n "$PR_HEAD_REF" GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath GIT_CONFIG_VALUE_0=/dev/null \ git push origin "$PR_HEAD_REF"

安全语义(同时见 safety-rules.md 的 Push Policy):

  • 绝不 force-push。推送命名的是本地 PR 分支而非HEAD,因此无论当前 checkout 的是哪个分支都正确;
  • 修复提交叠加在 checkout 出的 PR head 之上,所以如果非快进被拒绝,说明运行期间远端移动了:不要重试、不要 fetch-and-force,直接发布报告说明存在本地修复提交但因 PR 分支已变化而未推送;
  • 推送与修复提交相关的 git 操作都导出GIT_CONFIG_COUNT=1 GIT_CONFIG_KEY_0=core.hooksPath GIT_CONFIG_VALUE_0=/dev/null,因为本仓库的.husky/hooks 是 PR 控制的代码,裸执行会运行攻击者可控制的 hook(详见 SKILL.md 的 Checkout 一节)。

5.1 证据卫生:为什么修复提交只能按路径暂存

证据文件统一放在.qa-frontend/runs/<run-id>/下且保持未提交状态。永远不要 stage 或 commit.qa-frontend/下的任何内容:在技能合并之前创建的 PR 分支上该目录未被 gitignore,若使用git add -Agit add .git commit -a批量暂存,会把本地栈截图混入修复提交并在推送时公开,绕过证据上传审批门。因此必须只按精确路径暂存修复文件,并在每次提交前检查git diff --cached --name-only

六、从采集到产出的完整链路(源码视角)

把本指南与兄弟参考文件串起来,得到完整的证据生命周期:

  1. 采集(browser-mcp-patterns.md):用浏览器 MCP(Playwright MCP 是仓库内的已知范例)导航、快照、交互、断言 UI 状态、截图、收集控制台/网络信号;每个候选问题必须通过一次复现重试才能成为 finding,否则记为INTERMITTENT覆盖行并保留首次失败的证据;
  2. 标注与卷轴:用 annotate-evidence.py(uv run python,复用仓库已有 Pillow 依赖,不安装新包、不用 ffmpeg)为关键帧加 caption bar 与 PASS/FAIL/INFO 芯片、为 finding 加高亮框,并把 2–5 帧合成为慢速动画 WebPfrontend-qa.webp(宽度上限 1200px,3–5 帧的 1200px 截图卷轴通常远小于 200 KB);
  3. 录制演示视频:默认在 QA 循环结束后用浏览器工具原生录制 + cursor-overlay.js 注入可见光标重跑关键流程,再转码为 H.264 MP4(--trim-start用 ffmpeg 输出定位保证帧级精确,且只用uv run python ... video子命令转码;发布前用fps=1,tile=5x2的接触表(contact sheet)验证每步 caption 顺序与最终 finding 状态);
  4. 结构化产物findings.json(本指南第三节 schema)+ 第一行QA-VERDICT: ...
  5. 渲染与发布:按 pr-comment-template.md 渲染,PR 模式在审批后经hogli pr:upload-image上传并发布单条评论(含 banner、verdict 行、覆盖表、Setup、可选 Effort saved、findings、Needs intent、建议补丁、Before/After 并排对比,目标约 10k 字符、55k 字符时截断 per-finding 复现细节),本地模式只写 stdout 与report.md
  6. 推送与清理:走第五节审批门推送;随后按 cleanup.md 恢复原分支、关闭浏览器会话、恢复主题与 feature-flag 覆盖、必要时移除hogli.yaml中自动生成的 phrocs 配置、清理 gitignore 缺失分支上的运行目录(移出仓库到$TMPDIR/qa-frontend-runs/)。

6.1 评论发布前的清洗(Scrubbing)

无论走哪条发布路径,发布前都要清洗控制台摘录中的:bearer token、query-string token、cookie、CSRF 值、疑似密钥、凭据标签附近的长编码值。绝不包含 GitHub token 或 raw 上传响应体;若复制hogli pr:upload-image的输出,只取 stdout 中的alt行。来自被测应用的 UI 字符串(问题标题、标签、错误文本)会插值进代码围栏,必须剥离反引号与控制字符并截断超长内容,防止恶意或倒霉的字符串闭合围栏向评论注入 Markdown。本地栈截图仅在小且安全时嵌入;输出中不要使用 em dash(—),一律用普通连字符(-)或改写句子。

七、结语

qa-frontend的证据与输出规范把"浏览器 QA 跑完"这个模糊的中间态,收敛成三条硬性产出——findings.jsonQA-VERDICT与符合模板的报告——并用"公开且永久"的上传语义、逐字引用的 SHA 固定 URL、先审批后--yes的确认门、以及"无披露评论不推送"的联动约束,把证据治理从口头约定变成了可审计的流程。对于任何要复刻类似浏览器 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),仅供参考

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

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

立即咨询