关于 meticulous-review
meticulous-review 是一项引导 Agent 检查 Meticulous 测试运行的技能,涵盖核对预期视觉变化、分类差异和记录决定。它面向审查界面变更的开发者,并将审查与后续修复分开。
主要功能
- 01检查运行的审查状态和差异
- 02比较截图与 DOM 变化
- 03检查时间线以分析异常差异
- 04批准、拒绝、忽略或评论差异
- 05审查后整理待修复项目
适用场景
- 01审查拉取请求中的视觉变化
- 02区分回归问题与回放噪声
- 03记录截图差异的审查决定
- 04为后续修复整理被拒绝的变更
MCP 相关
该工作流支持使用 Meticulous CLI 或 MCP 命令,包括获取测试运行差异、截图、DOM 差异和时间线,并记录审查决定。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ alwaysmeticulous/ skills --skill meticulous-review安装后在 Claude Code 中输入/meticulous-review确认已加载。
详细介绍
要完成一次 Meticulous 测试运行,请按照以下工作流逐步操作,并使用所述的 CLI 或 MCP 命令。你无需事先知道该运行是否仍需审核,或是否已有人审核:步骤 1 会读取其审核状态,并据此决定后续操作。
开始前,运行
meticulous-cli-update技能,确保 Meticulous CLI 和技能均为最新版本;如果本次对话中此前已经运行过,则跳过。
审核时,请将自己视为审核者,而非实现者——即使你在本次对话中较早时编写过此改动。根据每项差异本身进行分类;修复是之后单独进行的环节(步骤 12),不要与审核交替进行。如果你正在实现功能,并希望通过 Meticulous 反复迭代,直到效果符合预期,请参阅用于具有预期视觉变化的功能开发的 meticulous-iterative-dev 技能;如果界面不得发生变化,请参阅 meticulous-zero-diff-task 技能。
步骤 0 -- 确定预期效果
查看任何差异之前,先弄清楚此 PR 预期产生什么视觉变化:
- 如果你已充分了解上下文(在同一对话中实现了该改动,或用户刚刚描述了任务),请使用这些信息。
- 否则——获取 PR 描述(例如,对于 GitHub,使用
gh pr view <number> --json title,body;对于 GitLab,使用glab mr view <id> --output json --jq '{title,description}';对于 Bitbucket,如果 Teamwork Graph CLI 可用,则使用twg bitbucket pull-requests get <id>——如果已安装,请遵循其twg-engineering-work技能;如果提示输入 Bitbucket 令牌,则运行一次twg setup bitbucket;否则使用GET /2.0/repositories/{workspace}/{repo_slug}/pullrequests/{id}?fields=title,description),并简要提取其中列出的预期视觉变化,以项目符号列出。 - 如果描述中没有提及任何视觉变化,请明确注明——之后的每项差异都需要额外仔细检查,因为没有记录表明它可能是已知且已接受的后果。
步骤 1 -- 获取回放差异摘要及其审核状态
从本地检出目录运行命令,以当前提交的 git HEAD 为依据解析测试运行——先确保 HEAD 与 CI 运行时对应的远程 HEAD 一致(例如,运行 git pull),否则你可能会审核过期或不存在的运行:
# CLI (infers the run from local git HEAD)
meticulous agent test-run-diffs --includeReviews
# MCP (git context is never inferred — resolve the testRunId from a commit first)
get_test_run_for_commit(commitSha="<sha>")
get_test_run_diffs(testRunId="<id>", includeReviews=true)
返回包含 replayDiffId/screenshotName 行的 TSV——这些行是按优先级排序的真实视觉差异代表性子集;请从上到下逐一检查。--includeReviews 会为每行添加 decision 和 openComments。如需明确指定运行,而不是根据 HEAD 解析,请传入 --testRunId <id>、--commitSha <sha> 或 --prNumber <n>(在 MCP 中,get_test_run_diffs(prNumber=<n>) 会跳过 get_test_run_for_commit 步骤)。默认情况下,CLI 会阻塞,直到运行结束(传入 --dontWaitForTestRunToComplete 则会报告正在进行的运行并立即退出);MCP 不会阻塞,因此请持续轮询,直到 status 为 complete/failed。
审核状态决定每行需要执行的操作:
unreviewed,没有未解决评论——审核该项:步骤 2–6。rejected,或有未解决评论——已有其他人查看过该项,因此不要重新审核;步骤 7 会处理该项。accepted或ignored,没有未解决评论——已有结论;无需处理。
如果没有任何行需要审核,直接进入步骤 7。否则,在判定 PR 没有问题之前,必须将每个尚未审核的行与步骤 0 中的预期进行核对,或将其标记出来(参见“判定指南”)。
步骤 2 -- 获取截图
对每张代表性截图:
# CLI (downloads images to ~/.meticulous/agent-images/ and prints local paths)
meticulous agent image-files --replayDiffId <replayDiffId> --screenshotName <screenshotName>
# MCP (no download-to-disk tool — returns signed URLs instead; fetch them to view the images)
get_image_urls(replayDiffId="<replayDiffId>", screenshotName="<screenshotName>")
打开(或获取)before、after 和 diffImage 以检查改动——diffImage 通常最有参考价值,它会准确突出显示发生变化的像素。即使 DOM 差异看起来很清楚,也务必检查图像。
第 3 步——检查 DOM 差异(了解结构细节)
# CLI
meticulous agent dom-diff --replayDiffId <replayDiffId> --screenshotName <screenshotName>
# MCP
get_dom_diff(replayDiffId="<replayDiffId>", screenshotName="<screenshotName>")
可选:--context <N|full>(CLI)用于控制每个差异块周围包含多少行上下文(默认为 3)。
输出为统一差异(+/-,已去除缩进),每个独立变更对应一个以 [diff N] 开头的区块——例如(仅供说明,并非真实输出):
[diff 0]
<div class="item">
- <span class="label">old label</span>
+ <span class="label" data-flag="true">new label</span>
</div>
[diff 1]
<ul class="list">
+ <li>new item</li>
</ul>
第 4 步——获取回放时间线(可选,用于诊断意外差异)
如果差异出乎意料,且无法从图像/DOM 明显看出原因:
# CLI
meticulous agent timeline-diff --replayDiffId <replayDiffId>
# MCP
get_timeline_diff(replayDiffId="<replayDiffId>")
TSV 列:diff( 表示相同,- 表示已移除,+ 表示已添加,! 表示已更改)、timeMs、event(user/screenshot/network/console/等)、description。留意失败的网络请求、意外重定向或时间异常,这些情况可能解释视觉变化。
第 5 步——决策指南
对于每张有代表性的屏幕截图,将差异图像和 DOM 差异与第 0 步的预期进行比较:
- 符合预期——与第 0 步的某项预期变更相符(或者结合完整实现上下文来看,显然是期望的结果)。确认差异确实呈现了_该_变更,且没有其他内容——差异类型可能符合预期,但同一张截图中仍可能夹带额外的无关回归。无需标记;如果有
approve-diff,则批准(第 6 步)。 - 非预期——第 0 步未涵盖此变更。利用时间线排除请求失败、重定向或其他异常,然后进行标记:
- 潜在回归(实际的副作用,或其他明显错误)→ 拒绝。
- 与正在审查的变更无关(见下文)→ 忽略。
无论如何,都应标记,而不是悄悄跳过——仍需让人工审核者看到。
哪些情况算无关。 仅忽略变更不可能导致的差异:
- 渲染噪声:亚像素或抗锯齿差异,通常不会伴随 DOM 变化;
- 动画、加载旋转图标、轮播或视频恰好停留在不同帧;
- 字体或图像延迟加载,或网络响应顺序不同;
- 环境噪声:服务器渲染的时间戳或数据、构建版本或 SHA、第三方内容。
忽略之前,请确认变更无法影响相关区域(PR 差异中没有任何内容会触及该屏幕或组件),并确认时间线没有显示它可以解释的偏差。回放路径不同——例如点击落在其他位置,或只有一侧打开了菜单——只有在变更不可能导致这种情况时才算无关;引擎自身的偶发故障标签不能作为定论。绝不要忽略:
- 无法解释的差异;
- 变更可能导致的差异,即使没有危害——如果是有意的,就批准;否则,添加评论并保持未决定状态;
- 新代码不再适用的已记录网络响应(例如“Missing field”错误)——这是变更造成的;
- 夹带在其他无关截图中的回归——应拒绝。
不确定时,保持差异未决定状态,并使用 create-diff-comment 说明原因。
报告可能的引擎错误。 如果忽略的差异来自非确定性回放,而 Meticulous 本应使其具有确定性,请添加 --reportFlake——可能涉及渲染、动画、计时器、日期、随机性、网络排序,或回放路径不同。Meticulous 随后会将其作为可能的回放引擎错误进行调查。每次运行中,每种偶发问题只报告一次,而不是在每个出现该问题的差异上都报告:当某个原因在许多差异中反复造成相同的偶发问题(例如时钟或动画在每个屏幕上都不相同),请忽略每个此类差异,但只在其中一个差异上添加 --reportFlake。如果确实是应用提供的内容不同(服务器渲染的时间戳、构建版本、第三方内容),则不要添加该参数:这些问题应由应用所有者修复,例如使用 meticulous-ignore 类隐藏相关元素。
先审查,之后再修复。 审查期间不要修改代码:先完成所有差异的分类和标记,再于第 12 步处理需要修复的问题。
第 6 步——标记或批准差异
# CLI
meticulous agent reject-diff --replayDiffId=<id> --screenshotName=<name> --reason="<why>" --x=<0..1> --y=<0..1>
meticulous agent approve-diff --replayDiffId=<id> --screenshotName=<name>
meticulous agent ignore-diff --replayDiffId=<id> --screenshotName=<name> --reason="<why>" --x=<0..1> --y=<0..1> [--reportFlake]
meticulous agent create-diff-comment --replayDiffId=<id> --screenshotName=<name> --text="<note>" --x=<0..1> --y=<0..1>
# MCP
reject_diff(replayDiffId="<id>", screenshotName="<name>", reason="<why>", x=<0..1>, y=<0..1>)
approve_diff(replayDiffId="<id>", screenshotName="<name>")
ignore_diff(replayDiffId="<id>", screenshotName="<name>", reason="<why>", x=<0..1>, y=<0..1>, reportFlake=<true|false>)
create_diff_comment(replayDiffId="<id>", screenshotName="<name>", text="<note>", x=<0..1>, y=<0..1>)
对于判定为非预期的每一项差异,都要调用 reject-diff 或 ignore-diff,并在最终报告中列出。--reason 是上文分类时给出的简要说明;--x/--y 是根据差异图像估算的更改区域大致归一化坐标。对于任何想留档但不作判断的内容,create-diff-comment 是中立选项。
是否提供 approve-diff? 只有启用了 Enable approve/ignore diff actions 设置的项目才提供。通过 MCP 时,只有启用该设置才会提供 approve_diff;CLI 无法提前判断,因此请在第一个预期差异上调用它——如果返回以 "Agents may not approve diffs on project …" 开头的 403 错误,就说明该功能已关闭,之后跳过所有有关批准的内容。
对于判定为预期的每一项差异,都要调用 approve-diff。与 reject 和 ignore 不同,它不需要理由。
两者并不对称: reject-diff 会写入真正具有阻止效力的决定,效果与人工拒绝相同。如果提供 approve-diff,approve-diff 和 ignore-diff 也会写入真正的决定并清除差异。否则,ignore-diff 不会作出任何决定——它只会添加评论,因此差异仍为 unreviewed,检查也仍处于待处理状态——所以不要在最终报告中过度宣称它解决了问题。
第 7 步——检查本次运行中的其余差异
第 1–6 步只涵盖了具有代表性的子集。即使第 1 步发现该子集中没有需要审核的内容,也要执行此步骤。
收集修复目标。 列出本次运行中所有已拒绝或有未解决评论的差异:
# CLI
meticulous agent test-run-diffs --onlyRejected --onlyWithComments --includeReviews
# MCP
get_test_run_diffs(testRunId="<id>", onlyRejected=true, onlyWithComments=true, includeReviews=true)
--only* 标志是累加的(差异可以已拒绝、有未解决评论,或两者兼有),且绝不会仅限于具有代表性的子集。被拒绝的差异,或要求修改的评论(diff-comments / get_diff_comments 会显示评论串),都会成为第 12 步的修复目标——包括你自己拒绝的差异。仅用于说明忽略或批准原因的评论(例如此技能本身留下的 ignore-diff 和 approve-diff 评论;在不支持 Agent 忽略的项目中,被忽略的差异仍为 unreviewed),或者你在不确定的差异上留下的备注,都不属于修复目标。
决定其余差异(仅限提供 approve-diff 的情况)。 只有每一项差异都已作出决定,检查才会通过。如果第 6 步发现 approve-diff 不可用,就跳过此部分:没有它,这里无法清除检查。否则,列出仍未决定的差异:
# CLI
meticulous agent test-run-diffs --includeAllDiffs --onlyUnreviewed --includeReviews
# MCP
get_test_run_diffs(testRunId="<id>", includeAllDiffs=true, onlyUnreviewed=true, includeReviews=true)
对于没有未解决评论的每一行,按照第 2–6 步进行处理,就像处理第一批差异一样;有未解决评论的行已在上文涵盖。如果你还没有调用过 approve-diff,那么在第一个被判定为预期的行上调用时,就能像第 6 步那样确认它是否可用——如果不可用,就到此为止。请保留 --includeAllDiffs:否则,只要具有代表性的子集中仍有任何差异尚未决定,--onlyUnreviewed 就会一直仅限于该子集。
步骤 8 -- 查看非视觉检查(仅当运行包含此类检查时)
除了截图差异外,运行还可能包含非视觉检查:内置检查,例如 accessibility、network-requests 和 react-component-renders,以及项目自己的 CI 报告的自定义检查。大多数项目没有此类检查,因此首先确认这次运行是否包含检查:
# CLI (same run selector as Step 1)
meticulous agent test-run-check --availableIds
# MCP
get_test_run_check_available_ids(testRunId="<id>")
如果项目尚未配置检查,导致命令被拒绝,那么就没有检查需要查看:跳到步骤 9。空列表也可能表示尚未报告结果,因此请按照命令提示重试,然后再得出没有检查的结论。
对列出的每项检查,获取其报告:
# CLI
meticulous agent test-run-check --checkId=<checkId> [--checkType=custom]
# MCP
get_test_run_check(testRunId="<id>", checkId="<checkId>", checkType="builtin|custom")
只有失败的检查需要作出决定:也就是其发现需要确认的检查。通过的检查或仅发出警告的检查都不需要处理。报告会说明发现的问题。对于内置检查,meticulous agent test-runs --prNumber=<n> --includeCheckIssueCounts 也会统计每次运行的失败数(checkFailureCount)。下面的审核命令会拒绝不需要确认的检查,因此命令被拒绝也就说明该检查无需处理。
根据步骤 0 中的预期,按照步骤 5 对差异的分类方式,对每项失败检查进行分类并采取相应操作:
- 符合预期:是此次更改有意造成的后果,例如 PR 特意新增的请求。批准。
- 可能是回归问题 → 拒绝。
- 与正在审核的更改无关 → 按照与差异相同的规则忽略:只有当此更改不可能以任何合理方式导致该发现时才忽略,例如问题出在 PR 未涉及的代码或页面中。绝不要忽略无法解释的发现。
# CLI (--prNumber=<n> can stand in for --testRunId)
meticulous agent reject-check --testRunId=<id> --checkId=<checkId> [--checkType=custom] --reason="<why>"
meticulous agent approve-check --testRunId=<id> --checkId=<checkId> [--checkType=custom] --reason="<why>"
meticulous agent ignore-check --testRunId=<id> --checkId=<checkId> [--checkType=custom] --reason="<why>"
# MCP
reject_check(testRunId="<id>", checkId="<checkId>", checkType="builtin|custom", reason="<why>")
approve_check(testRunId="<id>", checkId="<checkId>", checkType="builtin|custom", reason="<why>")
ignore_check(testRunId="<id>", checkId="<checkId>", checkType="builtin|custom", reason="<why>")
这与步骤 6 的做法相同,但有以下区别:
- 用户看不到原因。 原因会作为决定的说明保存,Agent 可通过
check-comments读取,但 Meticulous 应用不会显示。仍要始终填写原因,即使approve-check中原因是可选的;还要在最终报告中重述,因为人们会在那里看到原因。 approve-check和ignore-check需要启用 Enable approve/ignore check actions,这是与差异检查设置分开的项目设置。未启用时,这两项操作都会被拒绝;与ignore-diff不同,没有仅发表评论的后备选项。通过 MCP 时,只有启用该设置才会提供这两项操作。如果操作被拒绝,就让检查保持未决,并在最终报告中指出需要人工决定。reject-check始终可用。- 检查没有中立评论。不确定时,让检查保持未决,并在最终报告中解释原因。
步骤 9 -- 汇总 Agent swarm 结果(仅当提交包含此类结果时)
部分项目还会运行 Agent swarm,这是 Meticulous 托管的 Agent,它会在浏览器中测试拉取请求的构建,并报告若干测试用例,每个用例的状态为 pass、fail、blocked 或 skipped。无需批准、拒绝或忽略这些结果:除包含修复提示的用例外,其他结果仅供参考。查找同一提交对应的运行:
# CLI (same run selector as Step 1; waits up to 10 minutes for a run still in progress)
meticulous agent agent-swarm-run
# MCP (a run still in progress returns { status: 'processing' }: poll every 10s, for at most 10 minutes)
get_agent_swarm_run(commitSha="<sha>")
如果该提交没有 Agent swarm 运行,或只有仅规划的运行,则跳到步骤 10。如果运行在 10 分钟后仍在进行中、未能完成(其 errorMessage 会说明原因),或被判定为无法测试(notTestable),只需在最终报告中注明。
否则,查看所有用例(title、status、outcomeSummary),了解测试了哪些内容以及哪些内容未测试。需要关注的是包含修复提示的用例:经过独立检查器确认的问题,并附有现成的修复提示。只有 fail 用例可能包含修复提示,因此请获取每个此类用例,并检查其输出是否包含 fixPrompt:
# CLI
meticulous agent agent-swarm-run-case --swarmRunId=<id> --caseIndex=<n> --json
# MCP
get_agent_swarm_run_case(swarmRunId="<id>", caseIndex=<n>)
用例是否包含修复提示比提示内容更重要:请在报告中指出它——这是步骤 12 的修复目标。
第 10 步——最终报告
涵盖所有重要的视觉变更,以及第 8 步中的任何失败检查和第 9 步中的 Agent swarm 摘要。
- 预期变更——每项简要说明,一两行即可:变更内容、对应第 0 步中的哪项预期,以及你是否批准了该变更。
- 标记的差异(如有)——这是审核的重点,请在此处提供最多细节:
replayDiffId/screenshotName(链接:https://app.meticulous.ai/test-runs/<testRunId>/replay-diff/<replayDiffId>?screenshot=<screenshotName>)、你是拒绝还是忽略了它、标记时给出的原因(第 6 步)、变更的具体表现,以及你对成因的最佳判断。 - 失败检查(如有)——逐项列出检查 ID 和类型、检查发现的问题、你是批准、拒绝、忽略了它,还是尚未决定,以及完整的理由,因为应用不会显示这些理由。
- Agent swarm(如果此提交有对应运行)——简要说明结果(例如“4 个用例:3 个通过,1 个受阻”)及大致覆盖内容,或说明运行未完成或无法测试的原因,并附上链接:
https://app.meticulous.ai/test-runs/<testRunId>?tab=agent-swarm。列出每个失败用例及其outcomeSummary,并指出哪些用例带有修复提示,可由meticulous-fix技能处理。 - 已审核项(如果第 7 步发现任何内容)——列出其他人已拒绝或评论过的差异、每条评论的要求,以及你接下来是否会修复(第 12 步),还是留给 PR 作者处理。
只有每项差异和失败检查都已匹配或标记,PR 才算合格。如果有任何标记项,PR 就尚未合格:除了列出标记项,还要向用户明确指出这一点。如果可以使用 approve-diff,还要列出任何尚未决定的差异:它会使检查保持待处理状态。任何尚未决定的失败检查也同样需要列出。
第 11 步——向 Meticulous 提交反馈
始终执行此操作以结束审核——这是审核本身的一部分,并非需要用户提出要求才做。 提交一条简短反馈:Meticulous 是否发现了实际问题、是否有令人困惑之处,以及哪些改进能让审核更轻松。正面反馈同样有价值——反馈并非只用于报告阻碍。
# CLI
meticulous agent submit-feedback --message="<one or two sentences>" --outcome=<helped|neutral|hindered> --testRunId=<id> --skill=meticulous-review
# MCP
submit_feedback(message="<one or two sentences>", outcome="<helped|neutral|hindered>", testRunId="<id>", skill="meticulous-review")
第 12 步——交接需要修复的内容
汇总修复目标:第 7 步中的差异(包括你拒绝的差异)、第 8 步中你拒绝的检查,以及第 9 步中带有修复提示的 Agent swarm 用例。如果没有这些内容,则任务完成。
- 如果你正在处理此 PR 的代码——你实现了该变更,或用户要求你让 PR 通过检查——现在就为他们遵循
meticulous-fix技能。它会读取评论、修复代码、回复每个讨论串、推送变更,并在下一次运行中确认。 - 如果你只是在审核其他人的 PR,不要更改他们的代码:最终报告(第 10 步)已经为 PR 作者列出了修复目标,因此你的工作到此结束。
- 如果运行针对的是本地构建,而非已推送的提交(例如
meticulous-test技能将你带到此处),请在最终报告后停止:meticulous-fix会提交、推送并等待 CI,而这并非该工作流的迭代方式。