babysit-pr
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBabysit a PR
跟进PR
Goal: carry a pull request (GitHub) or merge request (GitLab) from "just opened" to "nothing left
unanswered," without the human having to sit and refresh the page. "PR" below means either.
Review bots are diff-anchored samplers. Every push mints a fresh round, and a fix in one place can
light up commentary somewhere adjacent. Left alone, a PR accumulates half-answered threads that
nobody resolves, and the real bug in round three gets buried under nitpicks from rounds one and two.
Your job is to be the person who reads every finding, decides what is actually true, fixes what
blocks, and closes every loop in writing.
You know how to drive (GitHub), (GitLab), and git. What follows is only the judgment this
loop needs and the few API calls that are easy to get wrong. The harvest script picks the forge from
the cwd's git origin; everything it returns has the same shape on both, with a block
naming what that forge cannot tell you.
ghglabcapabilities目标:将GitHub的拉取请求(pull request)或GitLab的合并请求(merge request)从“刚提交”状态推进到“所有问题已处理完毕”状态,无需人工手动刷新页面。下文的“PR”指代上述两种请求。
评审机器人是基于差异采样的工具。每次推送代码都会触发一轮新的评审,一处修复可能会引发相邻代码的新评审意见。如果放任不管,PR会积累大量未彻底解决的讨论线程,第三轮出现的真实bug会被前两轮的细枝末节问题掩盖。你的任务是通读所有评审结果,判断哪些问题真实存在,修复阻碍合并的问题,并以书面形式彻底解决所有问题。
你需要掌握(GitHub命令行工具)、(GitLab命令行工具)和git的使用方法。下文仅介绍该流程所需的判断逻辑以及容易出错的几个API调用。采集脚本会从当前工作目录的git远程仓库地址判断代码托管平台;无论平台是GitHub还是GitLab,脚本返回的数据结构一致,其中包含字段,用于说明该平台无法提供的信息。
ghglabcapabilitiesThe three rules that matter most
最重要的三条规则
Verify before you believe. A bot's severity badge is a guess made without running anything. Treat
every finding, including the P1s, as a claim to check against the code. Bots are frequently right
(that is why this loop is worth running), and they are also confidently wrong often enough that
shipping their suggestions unexamined will introduce bugs. Read the actual code path before you
agree or disagree.
Every thread gets an answer. A finding you fixed, rejected, or deferred is only closed once you have
said so in that thread and resolved it. Silence reads as "ignored" to the next human who opens the
PR, and it is how a real bug gets lost.
Publish before you answer. A "fixed" reply is only true once the remote branch carries the fix.
Never post a confirmed reply, or resolve its thread, while the fix exists only locally. Rejections
need no push. Reply with evidence and resolve immediately.
先验证再采信。机器人标注的严重程度只是未运行代码的猜测结果。将所有评审结果(包括P1级问题)都视为需要对照代码验证的断言。机器人的判断通常是正确的(这也是该流程有价值的原因),但也经常会自信地给出错误结论,如果未经检查就采纳其建议,会引入bug。在同意或反对评审意见前,请先阅读实际的代码路径。
每个线程都要有回复。无论是已修复、已拒绝还是已推迟处理的评审意见,只有当你在对应线程中说明情况并标记为已解决后,才算真正处理完毕。沉默会让后续查看PR的人认为“该问题被忽略了”,这也是真实bug被遗漏的原因。
先推送代码再回复。只有当修复代码已推送到远程分支时,“已修复”的回复才成立。绝不要在修复仅存在于本地时就发布确认回复或标记线程为已解决。拒绝评审意见无需推送代码,只需附上证据并立即回复,然后标记线程为已解决。
Harvest the round
采集评审结果
Findings arrive on two different surfaces, and a round that reads only one silently misses half of
them. This is the single most common way a babysit loop goes wrong:
- Inline review threads. This is where debate-review and Codex post their findings (Codex attaches
P1/P2-badged inline comments to an otherwise boilerplate review body; an empty-looking body proves
nothing). Each thread carries a (to resolve) and a
thread_id(to reply inside the thread). On GitHub these are GraphQL review threads; on GitLab they are discussions.reply_to - Top-level review bodies. This is where Greptile summarizes, Codex sometimes posts a numbered list, and debate-review posts its round summary. These have no thread to resolve; answer them with one PR comment per round. On GitHub they are review objects; on GitLab they are plain notes.
The bundled script returns both in one call, already correlated ( is the folder that
holds this SKILL.md):
<skill-dir>bash
"<skill-dir>/scripts/threads.sh" <N> > /tmp/pr-<N>-round-<k>.jsonNever trust a filtered count without its unfiltered twin. Before applying any jq filter to the
harvest, print the raw totals () and
compare. A filter that eliminates 100% of items is presumed broken until the field names are
verified against the actual schema (). jq selects on a misspelled field
fail silently-empty, and a "clean round" built on one is how a P1 gets a merge-gate mention posted
over it. That has happened. GitHub tooling fails by returning less data, not by erroring; pair this with the
pagination rule.
jq '{threads: (.threads|length), reviews: (.reviews|length)}'jq '.threads[0] | keys'Never describe an object you did not fetch. If a query for a specific id returns empty, that is a
stop signal. Say "I can't see it" and fetch it another way (), never narrate
its presumed content. Related trap: every inline thread reply arrives wrapped in a zero-byte
review object, so a watcher's "new review" event may be just a reply wrapper, not a new
round. threads.sh's does not include these wrappers, so a review id from an event that is
missing from the harvest means "wrapper", not "gone".
gh api .../reviews/<id>COMMENTED.reviewsDiff it against the previous round's file to see what is genuinely new. on a thread
means the line moved underneath it. The finding may already be fixed, so check it against current
code before spending the round on it. A bump on a thread you already handled means a
bot followed up inside it.
outdated: truecomment_countHas this reviewer seen the current push? Only trust a field that names a sha. On GitHub each review
carries ; compare it to . For debate-review on either forge, the round body's
is the sha it reviewed. On GitLab other reviewers' notes carry no sha (); a note's timestamp being later than your push does not prove it reviewed
that push, so say "coverage unknown" rather than guessing.
commit_idheaddebate_headcapabilities. review_commit_id: falseTwo kinds of author count as a reviewer. First, a bot: in the harvest. On GitHub
that comes from the API's own author type and is reliable ( and
are the usual ones; don't hardcode a whitelist). On GitLab the API only sometimes
says, so can be ; treat as unknown, look at the thread, and say in your
report that you could not confirm it. Second, any thread whose first comment carries a
marker. debate-review posts from the user's own account, so the author
is the PR author (), but the thread is a reviewer thread. The harvest
flags these as with , , and parsed
from the marker; its round body shows up in with (the sha it reviewed) and
/ . Treat them like any other bot thread. Anything else from the PR
author, and any human's comment without that marker, is never in scope for autonomous fixing.
Surface it to the user instead.
author_bot: truechatgpt-codex-connectorgreptile-appsauthor_botnullnull<!-- debate-review:... -->author_is_pr_author: truedebate_review: truedebate_iddebate_statusdebate_severity.reviewsdebate_headdebate_agreeddebate_contestedBots post 5 to 10 minutes after a push, longer on a big diff. Don't poll tightly; background the wait
and review the diff yourself meanwhile. A round is "in" once every reviewer you expect has either
posted against the current head SHA or been marked unavailable after its own wait budget. An
unavailable reviewer never blocks harvesting or acting on the ones that did post. Disclose the gap
instead of reporting the PR clean.
评审结果会出现在两个不同位置,如果只读取其中一处,会漏掉一半的内容。这是跟进流程最常见的错误:
- 内嵌评审线程:debate-review和Codex会在此发布评审结果(Codex会将带有P1/P2标记的内嵌评论附加到一个空的评审主体中;看起来为空的评审主体并不代表没有评审结果)。每个线程都包含(用于标记解决)和
thread_id(用于在线程内回复)。在GitHub上,这些是GraphQL评审线程;在GitLab上,它们是讨论线程。reply_to - 顶层评审主体:Greptile的总结、Codex有时发布的编号列表以及debate-review的评审总结都会出现在这里。这些内容没有对应的线程需要解决,每轮评审只需发布一条PR评论即可回复。在GitHub上,这些是评审对象;在GitLab上,它们是普通笔记。
配套脚本可一次性返回两种类型的内容,并已完成关联(是存放本SKILL.md的文件夹):
<skill-dir>bash
"<skill-dir>/scripts/threads.sh" <N> > /tmp/pr-<N>-round-<k>.json绝不要只信任过滤后的计数而忽略未过滤的原始数据。在对采集结果应用任何jq过滤器之前,请先打印原始总数()并进行对比。如果某个过滤器过滤掉了100%的条目,默认视为该过滤器存在问题,直到验证字段名称与实际 schema 一致()。jq对拼写错误的字段进行选择时会静默返回空值,基于此得到的“无问题评审”会导致P1级问题被遗漏并最终合并到生产环境。这种情况确实发生过。GitHub工具会返回更少的数据而非报错;请结合分页规则使用。
jq '{threads: (.threads|length), reviews: (.reviews|length)}'jq '.threads[0] | keys'绝不要描述未获取到的对象。如果针对特定ID的查询返回空值,这是停止信号。请说明“我无法查看该内容”并尝试其他方式获取(),绝不要猜测并描述其内容。相关陷阱:每个内嵌线程回复都会被一个空的评审对象包裹,因此监控器的“新评审”事件可能只是一个回复包裹,而非新一轮评审。threads.sh的字段不包含这些包裹对象,因此如果事件中的评审ID未出现在采集结果中,说明是“包裹对象”而非“评审已消失”。
gh api .../reviews/<id>COMMENTED.reviews将当前采集结果与上一轮的文件进行对比,查看哪些是真正的新内容。线程的表示对应的代码行已被移动。该评审意见可能已被修复,因此在处理前请对照当前代码进行检查。如果你已处理过的线程的增加,说明机器人在该线程中发布了后续意见。
outdated: truecomment_count评审者是否查看了当前推送的代码?只信任包含sha值的字段。在GitHub上,每个评审都包含;请将其与进行对比。对于任一平台上的debate-review,评审主体中的是其评审的sha值。在GitLab上,其他评审者的笔记不包含sha值();笔记的时间戳晚于你的推送并不代表它评审了该推送,因此请说明“覆盖范围未知”而非猜测。
commit_idheaddebate_headcapabilities.review_commit_id: false两类作者可视为评审者:第一类是机器人:采集结果中的。在GitHub上,该字段来自API自身的作者类型,是可靠的(常见的有和;不要硬编码白名单)。在GitLab上,API仅有时会返回该字段,因此可能为;请将视为未知,查看线程内容并在报告中说明无法确认其是否为机器人。第二类是第一条评论带有标记的线程。debate-review使用用户自身账号发布内容,因此作者是PR作者(),但该线程属于评审线程。采集结果会将这些线程标记为,并从标记中解析出、和;其评审主体会出现在中,包含(评审的sha值)以及 / 。请将其视为普通机器人线程处理。PR作者发布的其他内容,以及没有该标记的人类评论,均不属于自动修复的范围,应将其告知用户。
author_bot: truechatgpt-codex-connectorgreptile-appsauthor_botnullnull<!-- debate-review:... -->author_is_pr_author: truedebate_review: truedebate_iddebate_statusdebate_severity.reviewsdebate_headdebate_agreeddebate_contested机器人会在推送代码后5到10分钟发布评审结果,大差异的代码可能需要更长时间。不要频繁轮询;在等待期间可自行查看代码差异。当所有预期的评审者要么针对当前head SHA发布了评审结果,要么在等待超时后被标记为不可用时,本轮评审才算“完成”。不可用的评审者不会阻碍对已发布评审结果的采集和处理,只需披露该缺口即可,不要报告PR无问题。
Classify by real impact, not by badge
根据实际影响而非标记分类
After verifying a finding, sort it by consequence rather than by the label the bot attached.
Blocking, meaning it would ship a defect or stop the merge:
- a real bug, wrong behavior, or broken edge case in the changed code
- security, authorization, data-integrity, or data-loss exposure
- a violation of the change's own stated contract, acceptance criteria, or spec
- a migration or schema hazard
- a failing or newly-flaky check
Non-blocking, meaning real but ships nothing broken: naming, structure, docs, test nitpicks, micro
performance, "consider extracting this", style preference.
When a finding is genuinely ambiguous, hold it as blocking until you have read enough code to demote
it. The asymmetry is deliberate. An over-cautious fix costs minutes, a missed P1 costs a production
bug.
A debate-review thread with means two models looked and disagreed. The
main reviewer held the finding against a refutation, and the italic last line of the comment says
what the challenge was. That is a claim with a known counter-argument, not a weaker claim. Verify it
the same way, and say in your reply which side the code supports and why.
debate_status: contested验证评审意见后,请根据后果而非机器人附加的标签进行分类。
阻塞性问题:会导致代码缺陷或阻止合并的问题:
- 修改后的代码中存在真实bug、错误行为或未处理的边缘情况
- 安全、授权、数据完整性或数据丢失风险
- 违反变更自身声明的契约、验收标准或规范
- 迁移或架构风险
- 测试失败或新出现的不稳定测试
非阻塞性问题:真实存在但不会导致代码缺陷的问题:命名、结构、文档、测试细节、微性能优化、“考虑提取该代码”、风格偏好。
当评审意见存在歧义时,在阅读足够代码确认其为非阻塞性问题前,应将其视为阻塞性问题。这种不对称性是有意设计的:过度谨慎的修复仅需花费数分钟,而遗漏P1级问题会导致生产环境出现bug。
debate_status: contestedFix the blockers, autonomously
自动修复阻塞性问题
Don't stop to ask about blockers. Verify, fix, push, keep watching, report what you did.
- Reproduce first where you can. A probe that fails before the fix and passes after is what separates a real fix from a plausible edit. This matters most on findings you initially disagreed with. Those are the ones where being wrong is expensive.
- One push per round, not one per finding. Every push mints a new bot round, so per-finding pushes multiply the rounds you have to sit through.
- Run the repo's own gate before pushing. A fix that breaks the suite costs a whole extra round.
- If a matching guard skill is installed (clean-code-guard, test-guard, wp-guard, woo-guard from guard-skills), run it on your fix before pushing. The guards catch the failure modes a quick fix under review pressure tends to produce.
- When you disagree, prove it. Rejecting a finding is legitimate and common, but the reply has to carry the evidence: the code path, the guard that already handles it, or the test that pins the behavior. "This is fine" is not a rejection.
不要就阻塞性问题询问用户。验证问题、修复、推送、持续监控,并报告你的操作。
- 尽可能先复现问题。修复前探针失败、修复后探针成功,这是区分真实修复与看似合理修改的关键。这一点在你最初反对的评审意见上尤为重要,因为在这些问题上出错的代价很高。
- 每轮推送一次代码,而非每个问题推送一次。每次推送都会触发一轮新的机器人评审,因此针对每个问题推送会大幅增加需要处理的评审轮次。
- 推送前运行仓库自带的验证流程。导致测试套件失败的修复会额外增加一轮评审。
- 如果已安装匹配的防护技能(来自guard-skills的clean-code-guard、test-guard、wp-guard、woo-guard),请在推送前对修复代码运行该防护技能。防护技能会捕捉在评审压力下快速修复容易出现的问题。
- 当你反对评审意见时,请提供证据。拒绝评审意见是合理且常见的,但回复必须包含证据:代码路径、已处理该情况的防护逻辑或固定该行为的测试。“这没问题”不算有效的拒绝理由。
Publish, then reply, then resolve
推送代码、回复、解决线程
Work the round in one pass, not per finding: verify everything, reproduce confirmed blockers where
practical, fix them all, run the gate, then commit and push once and confirm the remote SHA. Only
then close the loops:
- Confirmed: reply naming the fix commit, then resolve.
- Rejected: reply with concrete evidence, then resolve. No push needed; these can close anytime.
- Deferred: create the agreed issue, reply with its link, then resolve.
Non-blocker fixes the user approves ride the next consolidated push, never a dedicated push of their
own. There is no re-review-exempt push: every push, including a final docs-only or nit-only one, must
be covered by a clean round from the merge-gate reviewer before merge (see "Before merge"). If
publication or verification fails, leave the thread open and report the blocker.
Answer inside the thread the finding came from. A fresh top-level comment leaves the original thread
open and forces the reader to correlate by hand. Use the harvest's to reply and
to resolve. On GitHub those are two different identifiers (REST comment id, GraphQL thread id); on
GitLab both are the discussion id.
reply_tothread_idGitHub:
bash
gh api --method POST "repos/<owner>/<repo>/pulls/<N>/comments/<reply_to>/replies" \
-f body="$(cat /tmp/reply.md)"
gh api graphql -f query='mutation($t:ID!){
resolveReviewThread(input:{threadId:$t}){ thread{ isResolved } } }' -F t="<thread_id>"GitLab ( is the URL-encoded , your instance):
<project>group/path--hostnamebash
glab api --hostname <host> --method POST "projects/<project>/merge_requests/<N>/discussions/<reply_to>/notes" \
--raw-field "body=$(cat /tmp/reply.md)"
glab api --hostname <host> --method PUT "projects/<project>/merge_requests/<N>/discussions/<thread_id>" \
-F resolved=trueThe GitLab reply and resolve calls are taken from the GitLab API docs and have not yet been exercised
against a live instance from this skill. The first time you use them, check the response, and if
either fails, stop and report rather than retrying variations.
Attribution. Open every reply by naming the model writing it and the person it writes for, so a
reader never has to guess whether a human weighed in. Sign your own model name; this skill is
model-neutral. The person is whoever owns the account the reply posts from. Get the name once per
session, on GitHub or on GitLab, and reuse it:
gh api user -q '.name // .login'glab api user --hostname <host> | jq -r '.name // .username'I am <model-slug> writing on behalf of <user>.
Then the verdict, then the evidence, briefly:
I am <model-slug> writing on behalf of <user>.
Confirmed and fixed in `a1b2c3d`. You were right that `occurrence_time` was never
compared against `evidence.event_time`, so a mapping could bind proof from a
different occurrence. Reproduced with a failing test first
(`test_binds_proof_to_mapped_occurrence`), then fixed the composition check.I am <model-slug> writing on behalf of <user>.
Declining this one. The nil case you describe is already unreachable. `resolve()`
returns early at `handlers.py:88` whenever the session is unset, which is the only
path that reaches this line. Leaving the behavior as-is.Resolve only what is actually closed: fixed and pushed, rejected with evidence, or deferred with an
issue filed. Never resolve a thread whose question you have not answered. Resolution claims the loop
is closed, and a false claim is worse than an open thread.
请一次性处理完本轮所有问题,而非逐个处理:验证所有问题,尽可能复现已确认的阻塞性问题,修复所有阻塞性问题,运行验证流程,然后提交并推送一次代码,确认远程分支的SHA。之后再处理所有线程:
- 已确认修复:回复中说明修复的提交ID,然后标记线程为已解决。
- 已拒绝:回复中提供具体证据,然后标记线程为已解决。无需推送代码;这些线程可随时关闭。
- 已推迟:创建约定的Issue,回复中附上Issue链接,然后标记线程为已解决。
用户批准的非阻塞性修复会随下一次合并推送一起提交,绝不要单独推送仅包含非阻塞性修复的代码。不存在无需重新评审的推送:每次推送(包括仅修改文档或细节的最终推送)在合并前都必须经过合并门评审者的无问题评审(见“合并前”部分)。如果发布或验证失败,请保持线程开放并报告阻塞性问题。
请在评审意见所在的线程内回复。新发布的顶层评论会让原始线程保持开放,迫使读者手动关联内容。请使用采集结果中的进行回复,使用标记线程为已解决。在GitHub上,这是两个不同的标识符(REST评论ID、GraphQL线程ID);在GitLab上,两者均为讨论ID。
reply_tothread_idGitHub:
bash
gh api --method POST "repos/<owner>/<repo>/pulls/<N>/comments/<reply_to>/replies" \
-f body="$(cat /tmp/reply.md)"
gh api graphql -f query='mutation($t:ID!){
resolveReviewThread(input:{threadId:$t}){ thread{ isResolved } } }' -F t="<thread_id>"GitLab(是URL编码的,是你的实例地址):
<project>group/path--hostnamebash
glab api --hostname <host> --method POST "projects/<project>/merge_requests/<N>/discussions/<reply_to>/notes" \
--raw-field "body=$(cat /tmp/reply.md)"
glab api --hostname <host> --method PUT "projects/<project>/merge_requests/<N>/discussions/<thread_id>" \
-F resolved=trueGitLab的回复和解决调用来自GitLab API文档,尚未通过本技能在真实实例中测试。首次使用时,请检查响应;如果任一调用失败,请停止操作并报告,不要尝试修改参数重试。
署名。每条回复开头请注明撰写回复的模型名称及其代表的用户,以便读者无需猜测是否有人类参与。请签署你自己的模型名称;本技能与模型无关。用户是回复所使用账号的所有者。每次会话只需获取一次名称:在GitHub上使用,在GitLab上使用,然后重复使用:
gh api user -q '.name // .login'glab api user --hostname <host> | jq -r '.name // .username'我是<model-slug>,代表<user>撰写此回复。
然后是结论,再附上简要证据:
我是<model-slug>,代表<user>撰写此回复。
已确认问题并在提交`a1b2c3d`中修复。你指出的`occurrence_time`从未与`evidence.event_time`进行比较,导致映射可能绑定来自不同事件的证据。我先编写了失败测试用例(`test_binds_proof_to_mapped_occurrence`)复现问题,然后修复了组合检查逻辑。我是<model-slug>,代表<user>撰写此回复。
我拒绝此评审意见。你描述的空值情况实际上是无法触发的。当会话未设置时,`resolve()`会在`handlers.py:88`提前返回,这是唯一能到达此行的路径。因此保留现有行为不变。仅解决真正已处理完毕的线程:已修复并推送代码、已提供证据拒绝、或已创建Issue推迟处理。绝不要标记未回答问题的线程为已解决。标记解决意味着闭环,虚假的闭环比开放线程更糟糕。
Non-blockers: one batched ask per round
非阻塞性问题:每轮批量询问一次
Don't interrupt per finding, and don't silently decide. Once per round, after the blockers are
handled, bring the non-blocking findings as one list with a recommendation each (fix now, open an
issue, or reject) and let the user choose:
Round 2 on PR #123. 1 blocker fixed and pushed (). Three non-blocking findings left:a1b2c3d
- debate-review: extract the duplicated fixture in
. Recommend issue, touches files outside this changetest_foo.py- Codex:
comparison could useCounterdirectly. Recommend fix now, one line==- Greptile: docstring missing on the new helper. Recommend fix now, trivial Fix 2 and 3 in the next push, issue for 1?
Whatever they decide, close each thread the same way as any other finding. Anything deferred gets a
real issue with enough context to act on months later: a link back to the thread, the file, and why
it was deferred. Not just a title.
不要逐个处理非阻塞性问题,也不要自行决定处理方式。每轮评审处理完阻塞性问题后,将非阻塞性问题整理为一个列表,每个问题附带建议(立即修复、创建Issue或拒绝),让用户选择:
PR #123的第二轮评审。1个阻塞性问题已修复并推送(提交)。剩余3个非阻塞性问题:a1b2c3d
- debate-review:提取
中重复的fixture。建议创建Issue,因为修改涉及本次变更之外的文件test_foo.py- Codex:
比较可直接使用Counter。建议立即修复,仅需修改一行代码==- Greptile:新辅助函数缺少文档字符串。建议立即修复,操作简单 是否在下次推送中修复问题2和3,并为问题1创建Issue?
无论用户做出何种决定,请以处理其他评审意见的方式关闭每个线程。所有推迟处理的问题都要创建包含足够上下文的Issue,以便数月后仍可处理:包含线程链接、文件路径以及推迟处理的原因,而不仅仅是标题。
Re-trigger within a fixed budget
在固定预算内重新触发评审
One invocation gets the initial harvest plus at most two consolidated repair pushes and two
re-review cycles unless the user explicitly asks to continue. After each push you start the next
round yourself. How depends on the reviewer, because they are triggered in three different ways:
-
debate-review is a local script, not a bot, and it works on both forges. You run it, it does the whole review while you wait, and it exits once the review is posted. Nothing to mention, nothing to poll:bash
node "<debate-review skill-dir>/scripts/review-pr.mjs" <pr-url>(is wherever that skill is installed,<debate-review skill-dir>on a standard install.) Run it in the background, keep working, and harvest the moment the command exits. It prints the review URL; exit code 3 means this head was already reviewed. It reviews exactly one head sha per run, so a run after a push always produces a fresh round. A run takes 10 to 20 minutes.~/.agents/skills/debate-review -
Codex is a GitHub app (there is no GitLab equivalent). Mentionin a PR comment, then wait. It answers 8 to 15 minutes later, against whatever head was current when it ran. Check
@codex reviewon its review before believing it covers your push.commit_id -
Greptile and similar bots re-review every push on their own. Don't summon them; handle their findings when they show up.
For a bot you are waiting on, wait at most 10 minutes past its usual window. If it is silent or
rate-limited, mark that reviewer unavailable; do not wait out a cooldown. The one exception is the
merge-gate reviewer at the merge gate, which has no timeout (see "Before merge"). Even a final
test-only, documentation-only, or nit-only push gets a round. The merge gate below is meaningless if
the last push went unreviewed.
Run the repository's required gate once per consolidated repair push; never rerun an already-passing
gate for the same SHA. If the user says "stop", "enough", or "push whatever you have", cancel active
polls and long gates, run the smallest relevant check that can finish promptly, publish the safe
work, disclose any incomplete gate, and do not trigger another review round.
Rounds should shrink. If round three is as large as round one, something systematic is wrong. Say
so rather than grinding. Findings that recur in the same shape usually mean the fix addressed a
symptom instead of the cause, which is worth surfacing.
At the budget boundary, stop and hand off the exact remaining findings, unresolved threads, last
reviewed SHA, and unavailable reviewers. Never describe an unreviewed head as clean.
一次调用包含初始采集结果,以及最多两次合并修复推送和两次重新评审周期,除非用户明确要求继续。每次推送后,请自行启动下一轮评审。具体方式取决于评审者,因为触发方式有三种:
-
debate-review是本地脚本而非机器人,可在两个平台上使用。你运行该脚本,它会在你等待期间完成整个评审,评审发布后退出。无需额外操作或轮询:bash
node "<debate-review skill-dir>/scripts/review-pr.mjs" <pr-url>(是该技能的安装目录,标准安装路径为<debate-review skill-dir>)。请在后台运行该脚本,继续处理其他工作,脚本退出后立即采集评审结果。它会打印评审URL;退出码3表示该head已被评审过。每次运行仅评审一个head sha,因此推送后运行会产生一轮新的评审。运行时间为10到20分钟。~/.agents/skills/debate-review -
Codex是GitHub应用(无GitLab等效工具)。在PR评论中提及,然后等待。它会在8到15分钟后回复,针对运行时的当前head。请检查其评审的
@codex review,确认它覆盖了你的推送。commit_id -
Greptile及类似机器人会自动重新评审每次推送。不要主动召唤它们;当它们发布评审结果时再进行处理。
对于等待中的机器人,请在其通常响应窗口后最多等待10分钟。如果它无响应或被限流,请标记该评审者为不可用;不要等待冷却时间。唯一的例外是合并门处的合并门评审者,没有超时限制(见“合并前”部分)。即使是仅修改测试、文档或细节的最终推送,也需要一轮评审。如果最后一次推送未经过评审,合并门就失去了意义。
每次合并修复推送后运行一次仓库的必填验证流程;不要对同一SHA重复运行已通过的验证流程。如果用户说“停止”、“足够了”或“推送当前所有内容”,请取消正在进行的轮询和长时间验证流程,运行能快速完成的最小相关检查,发布安全的工作成果,披露未完成的验证流程,不要触发新一轮评审。
评审轮次应逐渐减少。如果第三轮评审的问题数量与第一轮相当,说明存在系统性问题。请告知用户而非继续处理。重复出现的相同问题通常意味着修复仅解决了症状而非根源,这一点值得向用户说明。
到达预算上限时,请停止操作并移交剩余的具体问题、未解决的线程、最后评审的SHA以及不可用的评审者。绝不要将未经过评审的head描述为无问题。
Before merge
合并前
The merge gate is an explicit clean round from the repo's primary reviewer on the exact merge
candidate, the final head sha. Which reviewer that is depends on the repo.
Where Codex is installed, mention after the final push and wait for its reply. A
clean round is Codex saying so in plain words ("no findings", "good job") against the final head. No
reply yet is not a pass. Codex answers 8 to 15 minutes after a push, and merging inside that window
is how a real finding lands minutes after the merge.
@codex reviewWhere debate-review is the reviewer (on GitLab it is usually the only one), run it on the final head.
A clean round is all three of: its round body present in with equal to the
final head sha, and both zero, and no unresolved reviewer threads.
If the body is missing (a run can fail after posting inline comments), the gate has not been met;
re-run it, don't infer.
.reviewsdebate_headdebate_agreeddebate_contestedEither way, a finding is a new round, not a merge. Silence well past the usual window is something
to report to the user, not approval.
Re-harvest and re-read the PR's most recent comments before proposing a merge. A watcher settled
into a quiet interval can miss a late round, and a comment posted after your last check is exactly
the one that gets merged over.
Then ask the user whether to merge. Never merge on your own initiative. Report: rounds run,
blockers fixed with their SHAs, findings rejected and why, issues filed, unresolved threads
remaining (ideally zero), and CI state. The merge decision is theirs; everything leading to it was
yours.
合并门是指仓库主评审者针对确切的合并候选版本(最终head sha)给出的明确无问题评审。主评审者是谁取决于仓库配置。
如果安装了Codex,请在最终推送后提及并等待回复。无问题评审是指Codex针对最终head明确说明“无问题”或“做得好”。未回复不代表通过。Codex会在推送后8到15分钟回复,在此窗口期内合并会导致真实问题在合并后几分钟内出现。
@codex review如果主评审者是debate-review(在GitLab上通常是唯一的评审者),请针对最终head运行该脚本。无问题评审需满足三个条件:其评审主体出现在中,且等于最终head sha;和均为0;无未解决的评审线程。如果评审主体缺失(运行脚本可能在发布内嵌评论后失败),则未通过合并门;请重新运行脚本,不要推断结果。
.reviewsdebate_headdebate_agreeddebate_contested无论哪种情况,只要存在评审意见,就需要新一轮评审,而非直接合并。超出通常响应窗口后的沉默应告知用户,而非视为批准。
建议合并前,请重新采集并阅读PR的最新评论。处于静默期的监控器可能会错过后期评审,而你最后一次检查后发布的评论正是可能被合并遗漏的内容。
然后询问用户是否合并。绝不要自行决定合并。请报告:已运行的评审轮次、已修复的阻塞性问题及其SHA、已拒绝的评审意见及原因、已创建的Issue、剩余的未解决线程(理想情况下为0)以及CI状态。合并决策由用户做出;之前的所有工作由你完成。
When to stop and speak up
何时停止并告知用户
Some situations are not yours to grind through:
- A bot finding that is right but demands a change well beyond this PR's scope.
- Two bots contradicting each other on the same line, when code, tests, and the stated contract cannot settle it.
- The same finding recurring after a retry. The first recurrence gets a re-verified root cause and one more attempt inside the repair budget; a second means your model of the bug is wrong.
- A human reviewer's comment, always.
- CI failing for infrastructure reasons rather than code.
- The two-repair-cycle budget is exhausted.
- The user asks to stop, push the current work, or end the babysit loop.
某些情况不应继续处理:
- 机器人的评审意见正确,但需要进行超出本次PR范围的修改。
- 两个机器人针对同一行代码给出矛盾意见,而代码、测试和声明的契约无法解决该矛盾。
- 同一问题在重试后再次出现。第一次重复出现时,请重新验证根源并在修复预算内再尝试一次;第二次重复出现说明你对bug的模型理解有误。
- 人类评审者的评论,无论内容如何。
- CI因基础设施原因而非代码原因失败。
- 两次修复周期的预算已用尽。
- 用户要求停止、推送当前工作或结束PR跟进流程。