reply-and-review-discipline
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseReply and Review Discipline
回复与评审规范
Someone else's thread: the reader skims it and does not know the code, and whatever is written there publishes under the user's name. Plain words first, the reader's own log lines with arrow notes, questions only when the report does not answer them, and on a PR one pending review the user publishes.
These rules apply to any session writing on a thread it does not own: an issue reply, or a review of someone else's PR. The user's own PR or issue is the skill's moment. Its Readability rules and its redaction rule apply here unchanged; they are stated there, once.
/pr-and-issue-discipline/unslop他人的讨论串:读者只会快速浏览,并不了解代码,而写入其中的一切都会以用户的名义发布。先用通俗语言,引用读者自己的日志行并附上箭头注释;只有报告未回答问题时才提问;在 PR 上则只保留一个待发布评审,由用户发布。
这些规则适用于任何在不属于自己的讨论串中撰写的会话:issue 回复,或对他人 PR 的评审。用户自己的 PR 或 issue 属于 skill 的适用范围。其 Readability 规则和 redaction 规则在此原样适用;只需在该 skill 中说明一次。
/pr-and-issue-discipline如果安装了 ,则让它最后处理每条回复和暂存评论:内容会以用户的名义发布,因此不能出现任何 AI 痕迹。
/unslopWhen to Apply
何时应用
- Replying to an issue reporter or outside contributor
- Reviewing someone else's PR under the user's account
- 回复 issue 报告者或外部贡献者
- 以用户账号评审他人的 PR
Replies to Issue Reporters: Plain First
给 issue 报告者的回复:先讲通俗内容
An issue reply to an outside contributor is read by someone skimming a thread who does not know the code. Write a plain-language part that stands alone. Add a technical part, collapsed so it costs nothing to skip, only when it carries information the plain part cannot: when everything fits in plain words, the plain part is the whole reply.
A finding comment staged on someone else's PR follows the Each comment rules below and borrows only this section's voice; the staged summary has its own shape there.
The report decides the opening: read the reporter's log before writing a word. A question is asked only when the report does not already answer it, so the two shapes open differently: cause visible, diagnosis and steps; cause unknown, questions. Defaulting to questions is the failure the specimens were written against.
text
cause visible in the log cause not in the log
------------------------------------ ------------------------------------给外部贡献者的 issue 回复,是写给一个快速浏览讨论串、却不了解代码的人。必须先写一段能够独立成立的通俗语言内容。只有在技术部分能提供通俗部分无法提供的信息时,才添加技术部分,并将其折叠起来;如果所有内容都能用通俗语言表达,通俗部分就是全部回复。
暂存在他人 PR 上的发现评论应遵循下方“每条评论”的规则,但只沿用本节的语气;暂存总结的结构则采用该节自身的形式。
报告内容决定开头方式:动笔前先读报告者的日志。只有报告本身没有回答问题时才提问,因此两种形式的开头不同:原因明确时,先给诊断和步骤;原因不明时,先提问。一律先提问,正是这些示例旨在避免的失败模式。
text
cause visible in the log cause not in the log
------------------------------------ ------------------------------------What the report shows ## Questions (3 at most; say which helps most)
What the report shows ## Questions (3 at most; say which helps most)
their log lines, with arrow notes ## What the report shows
their log lines, with arrow notes ## What the report shows
What to do their log lines, with arrow notes
What to do their log lines, with arrow notes
- ... 2. ... 3. ... a guess, labeled a guess, last one fallback line: what to paste next <details> Technical details </details> (only when it adds something)
Full specimens of both shapes, and the two-language layout: `references/issue-replies.md`.
- **Cause visible: `## What the report shows`, then a numbered `## What to do`.** The reader's own log lines with arrow notes carry the diagnosis, and each numbered step carries its exact click path or command when one exists. One fallback line closes part one, saying what to paste if the steps do not fix it, and no `## Questions` heading appears.
- **Cause unknown: `## Questions` first.** A `## Questions` heading exists only when the diagnosis genuinely depends on the answers. Ask them as questions: a numbered list, three at most, and say which one would help most.
- Give the exact click path or command when one exists.
- "What would help" rather than "what we need": the reporter is doing you a favor. The reader may stop after the list.
- **Part one is plain language, and never says so** (the Readability rules own the heading rule).
- Say what the reader did and what they see: "the server you removed" rather than "the tombstoned server entry". When a mechanism has no plain name, show its effect instead of naming it.
- Quote the reader's own log line with an arrow note rather than paraphrasing it.
- **Part two is the technical reading, collapsed, and only when it adds something.** The same collapsible as a PR body's part two in the `/pr-and-issue-discipline` skill, its summary line in the half's language (`Technical details`, `Détails techniques`).
- Inside a `<details>` block: the mechanism names, the log lines mapped to code paths, docs links, and what a future maintainer would want when re-reading the thread. Nothing in part one depends on it.
- A reply that says everything in plain words has no part two. The visible-cause specimen has none; the mid-request one's exists because the buffer size and timeout explain why the log stops where it does.
- **A guess goes last in part one and is labeled a guess.** It saves a round trip without steering the reader before they answer.
- **The reporter's language first, then English.** When the reporter writes in another language, or their pasted text reveals one (a localized error message, a UI label), the reply carries both: the full reply in the reporter's language, then the full reply in English.
- Each half is complete on its own, with its own details block when the reply has one. Neither half is a summary of the other.
- The two halves sit in one comment, a rule between them; layout in `references/issue-replies.md`.
- **The repository's convention sets headings and tone, never how the reply reads.** A maintainers' "prose over templates" rule drops the headings and softens the voice; the reply still carries the same content in the same order and stays skimmable, judged per reply, never a wall of text.
- The Readability rules and the redaction rule apply unchanged, to both halves of a two-language reply.- ... 2. ... 3. ... a guess, labeled a guess, last one fallback line: what to paste next <details> Technical details </details> (only when it adds something)
两种形式的完整示例及双语布局见 `references/issue-replies.md`。
- **原因明确:先写 `## What the report shows`,再写带编号的 `## What to do`。** 读者自己的日志行配合箭头注释来呈现诊断;每个编号步骤在存在准确路径或命令时,都要写出具体的点击路径或命令。第一部分以一行兜底说明结束,指出如果这些步骤无法解决问题,应粘贴什么内容;此时不出现 `## Questions` 标题。
- **原因不明:先写 `## Questions`。** 只有在诊断确实依赖答案时才存在 `## Questions` 标题。以问题的形式提出:使用编号列表,最多三个,并说明哪一个帮助最大。
- 如存在准确的点击路径或命令,就写出来。
- 使用“什么会有帮助”,而不是“我们需要什么”:报告者是在帮你。读者可能看完问题列表就停止回复。
- **第一部分使用通俗语言,而且不要明说这一点**(标题规则由 Readability 规则决定)。
- 说明读者做了什么、看到了什么:例如“你移除的服务器”,而不是“已墓碑化的服务器条目”。当某个机制没有通俗名称时,应展示其影响,而不是直接说出机制名称。
- 引用读者自己的日志行并附上箭头注释,而不要转述日志。
- **第二部分是折叠的技术解读,且仅在能增加信息时出现。** 折叠块采用与 `/pr-and-issue-discipline` skill 的 PR 正文第二部分相同的结构,摘要行使用其所在半部分的语言(`Technical details`, `Détails techniques`)。
- 在 `<details>` 块内:写明机制名称、将日志行映射到代码路径、文档链接,以及未来维护者重读该讨论串时需要的信息。第一部分不依赖其中任何内容。
- 如果回复中的所有内容都能用通俗语言表达,就不要第二部分。日志中原因明确的示例没有第二部分;请求进行到中途的示例有第二部分,因为缓冲区大小和超时时间解释了日志为何停在那里。
- **猜测放在第一部分最后,并明确标为猜测。** 这样可以省去一轮来回沟通,又不会在读者回答之前误导读者。
- **先使用报告者的语言,再使用英语。** 当报告者使用另一种语言,或其粘贴内容暴露出某种语言(本地化错误消息、UI 标签)时,回复要同时包含两种语言:先给出完整的报告者语言版本,再给出完整的英语版本。
- 每一半都要能够独立成立;如果回复包含折叠块,每一半都要有自己的折叠块。任一半都不能只是另一半的摘要。
- 两半放在同一条评论中,中间加一条分隔线;布局见 `references/issue-replies.md`。
- **仓库惯例决定标题和语气,但绝不决定回复的呈现方式。** 维护者的“散文优先于模板”规则会去掉标题并让语气更柔和;回复仍须按相同顺序包含相同内容,并保持便于扫读。每条回复都应单独判断,绝不能堆成一堵文字墙。
- Readability 规则和 redaction 规则原样适用于双语回复的两半。Reviewing Someone Else's PR: One Pending Review
评审他人的 PR:只保留一个待发布评审
The agent reviews under the user's account, so publishing is the user's act: they publish the staged review themselves, or they tell the agent to post a verdict they have decided. Every comment goes into ONE pending review for the user to edit and publish. Never a standalone comment on someone else's PR: it publishes at once, under the user's name, unedited.
Pick the lenses before reading, once per PR. Who owns the repository sets the recommendation, not who wrote the PR:
- The user's repository, or one in an organization they own: the full set of these skills' standards, as on their own PR, where the skill folds every installed
/rubber-duck-reviewsection in without asking. Recommend the whole set.## Review Criteria - A repository they do not own: that repository's conventions come first, and which of these standards a colleague's PR is held to is the user's call. Recommend the correctness lenses and offer the rest.
-
Collect the candidates: every installed skill declaring asection, found the way the
## Review Criteriaskill's companion-skills step finds them; that skill itself, for a read-only cross-model pass over the PR's diff; and/rubber-duck-reviewwhen the PR touches working text (a page, a comment, a description)./working-text -
Read the memories first: the memories available to the session (the index, where the memory system keeps one, and this project's memories). A standing correction about this repository, a rule the user gave the last time a PR like this was reviewed, a library the user prefers over hand-rolling: each one adds a lens, drops one, or sharpens the recommendation.
-
Ask once, the recommendation first, with the reason for each lens inside the dialog itself, since text outside a dialog is lost:text
Lenses for PR #123 on octocat/fetcher, a repository you do not own (adds a retry loop in src/fetch.ts and a page docs/retries.md). Apply which? [x] /rubber-duck-review on the PR diff (Recommended) a second model, read-only, before staging [x] /never-twice criteria (Recommended) the retry loop repeats a fix from PR #98 [ ] /code-standards criteria their repository, their standards; memory: prefer a library over hand-rolling, if you hold this PR to it [ ] /working-text docs/retries.md is a new page [ ] /no-invalid-states no lifecycle flags or repeated guards in the diff [ ] /verify-with-controls the body claims no zero, alarm, or success reading -
Carry the answer for the PR, through every revision of the pending review. Apass on this PR expands only the
/rubber-duck-reviewsections the user chose here, not every installed one: that skill's every-section rule is for the user's own change, and this choice scopes it. Then read the PR's linked document and the code, and only then write.## Review Criteria
Stage: one JSON body, the head commit inside it, no field. belongs in the file: with , a field goes to the URL query string.
eventcommit_id--input-fThe file is written with the harness's file-writing tool, the head SHA already in it: comment bodies carry backticks a shell heredoc would run, and some sandboxes refuse heredocs, a , or a variable chained into the command. One plain command per step, the removal its own last command, like the skill's PR-body fallback.
trap/pr-and-issue-disciplineA finding that spans several lines is anchored on its whole range with and ; and name the diff side the lines are on, for lines in the new file, for a removed range. A single-line anchor only when one line is the whole finding.
start_linelinestart_sidesideRIGHTLEFTbash
gh pr view <n> --repo <owner>/<repo> --json headRefOid -q .headRefOid # 1. the head SHA, for commit_id below
mktemp -d /tmp/pr-review-XXXXXX # 2. prints e.g. /tmp/pr-review-Kq3mZp; copy the printed path by handAgent 在用户账号下进行评审,因此发布属于用户的行为:用户可以自行发布暂存评审,也可以指示 Agent 发布其已决定的结论。所有评论都放入一个待发布评审中,供用户编辑并发布。绝不要在他人 PR 上单独发表评论:这种评论会立即以用户名义发布,且无法编辑。
阅读前先选定评审视角,每个 PR 只做一次。由谁编写 PR 不决定推荐项,仓库所有者才决定推荐项:
- 用户自己的仓库,或用户所属组织拥有的仓库: 像评审自己的 PR 一样,采用这些 skill 的完整标准集合;其中 skill 会自动纳入每个已安装 skill 中的
/rubber-duck-review章节,无需询问。推荐整套标准。## Review Criteria - 用户不拥有的仓库: 首先遵循该仓库的惯例,而同事的 PR 应适用哪些标准由用户决定。推荐正确性相关的评审视角,并提供其余视角供选择。
-
收集候选项: 查找所有声明章节的已安装 skill,查找方式与
## Review Criteriaskill 的 companion-skills 步骤相同;还要加入该 skill 本身,用于对 PR 的 diff 执行只读的跨模型检查;若 PR 涉及 working text(页面、评论、描述),还要加入/rubber-duck-review。/working-text -
先阅读 memories: 阅读会话可用的 memories(index,也就是 memory system 保存索引的位置,以及本项目的 memories)。关于该仓库的一项长期纠正、上次评审类似 PR 时用户给出的规则、用户更偏好使用而非手工实现的库:每一项都可能新增、取消或细化一个评审视角。
-
只询问一次,先给出推荐项,并在对话框内部说明每个评审视角的理由,因为对话框之外的文字会丢失:text
undefined
Lenses for PR #123 on octocat/fetcher, a repository you do not own (adds a retry loop in src/fetch.ts and a page docs/retries.md). Apply which?
[x] /rubber-duck-review on the PR diff (Recommended) a second model, read-only, before staging
[x] /never-twice criteria (Recommended) the retry loop repeats a fix from PR #98
[ ] /code-standards criteria their repository, their standards; memory: prefer a library
over hand-rolling, if you hold this PR to it
[ ] /working-text docs/retries.md is a new page
[ ] /no-invalid-states no lifecycle flags or repeated guards in the diff
[ ] /verify-with-controls the body claims no zero, alarm, or success reading
4. **在待发布评审的每次修订中沿用针对该 PR 的选择。** 对该 PR 执行 `/rubber-duck-review` 时,只扩展用户在此选择的 `## Review Criteria` 章节,而不是所有已安装章节:该 skill 的“全部章节”规则仅用于用户自己的改动,而此处选择限定了范围。然后阅读 PR 链接的文档和代码,之后再撰写。
**暂存:** 使用一个 JSON 请求体,并在其中包含 head commit;不要设置 `event` 字段。`commit_id` 应放在文件中:使用 `--input` 时,`-f` 字段会被放到 URL 查询字符串中。
使用 harness 的文件写入工具写文件,并预先写入 head SHA:评论正文含有反引号,使用 shell heredoc 会执行这些内容;而某些沙箱会拒绝 heredoc、trap,或拒绝将变量串接进命令。每一步只使用一条普通命令,删除操作作为最后一条独立命令,方式与 `/pr-and-issue-discipline` skill 的 PR 正文兜底方案相同。
对于横跨多行的发现,使用 `start_line` 和 `line` 将其锚定到完整范围;`start_side` 和 `side` 指明这些行位于 diff 的哪一侧,`RIGHT` 表示新文件中的行,`LEFT` 表示已删除的范围。只有当整个发现就是一行时,才使用单行锚点。
```bash
gh pr view <n> --repo <owner>/<repo> --json headRefOid -q .headRefOid # 1. the head SHA, for commit_id below
mktemp -d /tmp/pr-review-XXXXXX # 2. prints e.g. /tmp/pr-review-Kq3mZp; copy the printed path by hand3. write /tmp/pr-review-Kq3mZp/review.json with the harness's file-writing tool:
3. write /tmp/pr-review-Kq3mZp/review.json with the harness's file-writing tool:
{
{
"commit_id": "<head SHA>",
"commit_id": "<head SHA>",
"comments": [
"comments": [
{"path": "src/metrics.ts", "line": 42, "side": "RIGHT", "body": "Review summary (copy into the summary box)\n\n[comment, not approve yet]\n\nWorks: ...\nBlocks: ..."},
{"path": "src/metrics.ts", "line": 42, "side": "RIGHT", "body": "Review summary (copy into the summary box)\n\n[comment, not approve yet]\n\nWorks: ...\nBlocks: ..."},
{"path": "src/metrics.ts", "start_line": 84, "start_side": "RIGHT", "line": 88, "side": "RIGHT", "body": "[blocking] The two headline metrics disagree on answers that cannot be parsed. Count them the same way in both."}
{"path": "src/metrics.ts", "start_line": 84, "start_side": "RIGHT", "line": 88, "side": "RIGHT", "body": "[blocking] The two headline metrics disagree on answers that cannot be parsed. Count them the same way in both."}
]
]
}
}
gh api -X POST repos/<owner>/<repo>/pulls/<n>/reviews --input /tmp/pr-review-Kq3mZp/review.json --jq .id # 4. no "event": stays pending
rm -rf /tmp/pr-review-Kq3mZp # 5. its own command, whatever gh returned
**Revise:** GitHub keeps one pending review per author per PR, so a second POST fails. Read the pending review's comments as they are now, since the user may have edited them in the web UI, and rebuild the full set from that text. Then delete it, confirm none remains, recreate, and tell the user the id changed:
```bashgh api -X POST repos/<owner>/<repo>/pulls/<n>/reviews --input /tmp/pr-review-Kq3mZp/review.json --jq .id # 4. no "event": stays pending
rm -rf /tmp/pr-review-Kq3mZp # 5. its own command, whatever gh returned
**修订:** GitHub 会为每个 PR 的每位作者保留一个待发布评审,因此第二次 POST 会失败。先读取待发布评审当前的评论,因为用户可能已在 Web UI 中编辑它们;然后根据这些文本重建完整评论集。随后删除该评审,确认没有残留,再重新创建,并告知用户 id 已变化:
```bash--paginate: a PR with many reviews spreads them over pages, and the pending one is the newest
--paginate: a PR with many reviews spreads them over pages, and the pending one is the newest
gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews --jq '.[] | select(.state == "PENDING") | .id' # the id to delete
gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews/<id>/comments --jq '.[] | {path, start_line, start_side, line, side, body}' # the current text, web edits included, with each anchor's range; rebuild from this (position alone would collapse a ranged comment to one line)
gh api -X DELETE repos/<owner>/<repo>/pulls/<n>/reviews/<id>
gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews --jq '.[] | select(.state == "PENDING") | .id' | wc -l # must print 0 before the new POST
**The verdict lives on the PR, never in a document.**
- **The summary is a staged inline comment** on the first changed line, headed `Review summary (copy into the summary box)`, then a bracketed recommendation (`[LGTM]`, `[comment, not approve yet]`, `[request changes]`), then `Works:` and `Blocks:` lines only. A nit that would need a third line is not staged at all. The web dialog drops an API-set review body, so the user pastes this one into the summary box.
- **A verdict the user has decided and told the agent to post** goes out directly, with `event` (`APPROVE`, `REQUEST_CHANGES`, or `COMMENT`) and `body`, instead of staged. That instruction is the publication; without it, everything stays pending.
- **The report to the user is one chat line** with the recommendation: no findings document, no copy-paste file, no dashboard row.
**Each comment:**
- **One or two sentences, plain English, as short as possible.** Open with a bracketed hint for the publisher (`[blocking]`, `[small ask]`, `[question]`), then the exact change asked for. No background, no restating what the code does. Accepted: "[blocking] The linked comment has only headline and per-type tables, not the 100-task paired table the body promises. Please post it or link to it."
- **Plain human voice:** the Replies section's words (plain language, no internal names), not its two-part layout or language pairing. Rejected: "PARSING_ERROR maps to COULD_NOT_EXTRACT_ANSWER, which is trainable, so the rollout arrives as a CompletedRollout with reward 0". At most one code identifier per comment, one comparison, no chained numbers. Technical detail only when the author cannot act without it.
- **A re-review stages comments only for what is still open or partly open.** An item the author addressed gets no comment of its own; the summary may list the resolved ones in one line.
- **Only what changes behavior, reliability, or the truth of a stated fact.** Test-coverage, YAGNI, and tidying nits are not staged unless the user asks for them: most publishers drop them, so staging them only costs an editing pass.
- **A Windows-only issue** (newline translation, path separators) **is a finding only when the repository supports Windows**: its CI matrix, docs, or issues say so. A case-insensitive filesystem is a macOS default too, so that one stays a finding.
- The redaction rule applies: a staged comment publishes under the user's name.gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews --jq '.[] | select(.state == "PENDING") | .id' # the id to delete
gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews/<id>/comments --jq '.[] | {path, start_line, start_side, line, side, body}' # the current text, web edits included, with each anchor's range; rebuild from this (position alone would collapse a ranged comment to one line)
gh api -X DELETE repos/<owner>/<repo>/pulls/<n>/reviews/<id>
gh api --paginate repos/<owner>/<repo>/pulls/<n>/reviews --jq '.[] | select(.state == "PENDING") | .id' | wc -l # must print 0 before the new POST
**结论必须留在 PR 上,绝不能放在文档中。**
- **总结是一个暂存的行内评论**,放在首个变更行上,标题为 `Review summary (copy into the summary box)`,然后是方括号中的推荐结论(`[LGTM]`, `[comment, not approve yet]`, `[request changes]`),最后只写 `Works:` 和 `Blocks:` 两行。如果某个小建议需要第三行,则完全不暂存。Web 对话框会丢弃通过 API 设置的评审正文,因此用户需要将这一条粘贴到总结框中。
- **如果用户已决定某个结论并指示 Agent 发布,** 则直接发布该结论,使用 `event`(`APPROVE`、`REQUEST_CHANGES` 或 `COMMENT`)和 `body`,而不是暂存。该指令即构成发布;没有它,一切都会保持待发布状态。
- **向用户汇报只用一条聊天消息,** 并包含推荐结论:不要提供发现项文档、复制粘贴文件或仪表盘行。
**每条评论:**
- **一两句,尽可能简短,使用通俗英语。** 先以面向发布者的方括号提示开头(`[blocking]`、`[small ask]`、`[question]`),然后写出要求做出的准确修改。不要背景说明,也不要重述代码的功能。可接受:“`[blocking]` 链接的评论只有汇总表和按类型分类的表,没有正文承诺的 100 个任务配对表。请发布该表或提供链接。”
- **采用自然的人类口吻:** 使用“回复”部分的措辞(通俗语言,不使用内部名称),不要采用该部分的两段式布局或语言配对。不可接受:“PARSING_ERROR 映射到 COULD_NOT_EXTRACT_ANSWER,而后者可训练,因此 rollout 会以 reward 0 的 CompletedRollout 到达。”每条评论最多包含一个代码标识符、一次比较,不要串联多个数字。只有作者不看到技术细节就无法采取行动时,才提供技术细节。
- **复审时,只为仍未解决或部分解决的发现项暂存评论。** 作者已处理的项目不单独评论;总结中可用一行列出已解决项。
- **只暂存会影响行为、可靠性或既定事实真实性的内容。** 除非用户明确要求,否则不要暂存测试覆盖率、YAGNI 和整理类小建议:多数发布者会忽略它们,因此暂存只会徒增编辑工作。
- **仅在 Windows 上出现的问题**(换行转换、路径分隔符)**只有仓库支持 Windows 时才算发现项:** 其 CI matrix、文档或 issue 应能证明这一点。不区分大小写的文件系统在 macOS 上也是默认行为,因此该问题仍算发现项。
- redaction 规则同样适用:暂存评论会以用户名义发布。