contributions-implement

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Implement a contribution in a fork

在 fork 中实现贡献

One contribution per run. The run's Multica issue names the target repository (owner/repo) and the change to make. There are two shapes. In the initial run, the deliverables are a pushed branch in the user's fork and a Multica comment carrying a pasteable PR body that follows the upstream PR template; no PR is opened anywhere — the user opens the upstream PR after validating the branch. In a review iteration (the PR is already open and maintainers left review comments), the deliverable is a push to the same fork branch plus a pasteable PR comment per PR on the Multica issue — and the PR discussion itself stays with the humans.
每次运行只处理一项贡献。本次运行的 Multica issue 会指定目标仓库(owner/repo)和需要进行的变更。流程分为两种形态。在 首次运行 中,交付物是用户 fork 中的 已 push branch,以及一条 Multica comment,其中包含遵循上游 PR 模板、可直接粘贴的 PR 正文;任何位置都不会创建 PR——用户在验证 branch 后自行创建上游 PR。在 review 迭代 中(PR 已开启且 maintainer 留下了 review comments),交付物是向 同一 fork branch push,以及在 Multica issue 中为每个 PR 发布一条 可粘贴的 PR comment——PR 讨论本身仍由人工处理。

Scope

范围

  • In: verify the fork; read the upstream conventions; tests first; implement; run the upstream CI checks locally; commit with the correct sign-off; push the fork branch; write the PR body; in review iterations, address the explicit review comments on the same branch and write the pasteable PR comment; post the deliverable comment.
  • Out (hard): creating the fork, opening a PR against the fork, opening a PR against upstream, merging anything, force-pushing, replying to or resolving PR review threads, editing the PR body, or deciding what an unresolved discussion means.
  • **范围内:**验证 fork;阅读上游规范;优先编写测试;实现变更;在本地运行上游 CI 检查;使用正确的 sign-off 提交;push fork branch;编写 PR 正文;在 review 迭代中,于同一 branch 上处理明确的 review comments,并编写可粘贴的 PR comment;发布交付物 comment。
  • **范围外(硬性限制):**创建 fork、针对 fork 创建 PR、针对 upstream 创建 PR、合并任何内容、force-push、回复或 resolve PR review threads、编辑 PR 正文,或自行判断未解决的 discussion 意味着什么。

Hard gate: the fork must already exist

硬性门槛:fork 必须已经存在

The fork is created by the user, never by you. Before any other work, verify a fork of the upstream repo exists under the user's account (e.g.
gh api repos/<user>/<repo>
returning
fork: true
, or the fork metadata via the GitHub MCP tools). If it does not exist, stop immediately and ask the user to fork the repo — do not fork it yourself and do not start other work before the fork is there. A fork you create silently is not the same deliverable: the user chose to own the fork relationship.
fork 始终由 用户 创建,绝不能由你创建。在开始任何其他工作前,验证上游仓库的 fork 是否存在于用户账户下(例如,
gh api repos/<user>/<repo>
返回
fork: true
,或通过 GitHub MCP tools 获取 fork metadata)。如果不存在,立即停止并请用户创建 fork——不要自行创建 fork,也不要在 fork 存在前开始其他工作。你在后台静默创建的 fork 并不等同于要求的交付物:用户有意选择拥有这层 fork 关系。

Procedure

执行步骤

  1. Read the upstream conventions before writing any code.
    • Agent-facing docs at the root —
      CONTRIBUTING.md
      ,
      AGENTS.md
      ,
      CLAUDE.md
      (whichever exist) — plus the issue and PR templates (
      .github/PULL_REQUEST_TEMPLATE*
      ) and any contribution or AI-PR policy in the tracker.
    • Commit conventions (Conventional Commits or otherwise), DCO vs CLA, and the CI expectations: which commands the upstream workflows run, and which tool versions are pinned (Makefile
      make lint
      targets,
      .golangci.yml
      , workflow
      go-version
      , etc.).
    • The code style of the exact files you will touch: naming, error handling, test framework, and existing helpers to reuse rather than reinvent. If upstream forbids fully AI-generated PRs, or requires a CLA the user has not signed, record it and stop — do not push on.
  2. Prepare the branch. Clone or fetch the fork. Base the new branch on the upstream default branch (fetch upstream explicitly; do not assume the fork's head is current). Name it
    feature-<short-name>
    or
    fix-<short-name>
    — never a generic agent-generated branch name.
  3. Tests first, equivalence first. Before changing behavior, add tests for the paths the change touches — especially branches that have no coverage today. Run them against the unmodified code: they must pass unmodified. A test that only passes after the change proves the new structure works; a test that passed before proves the behavior is the same, which is what a reviewer needs to trust a refactor.
  4. Implement the change. One logical change, minimal diff — no unrelated refactors, renames, deletions, or formatting tweaks. Match the repo's conventions from step 1 exactly.
  5. Run the upstream CI/CD checks locally, before pushing. The fork will not run upstream CI/CD, so nothing else will. Reproduce what the upstream workflows run: the build, the package's test suite (with race/sanitizer flags where the repo uses them), and the repo's lint target with the pinned tool versions (a lint pass on a newer linter is not the same evidence). Reproduce what the upstream workflows run, no more: flags they do not use (an added
    -race
    , a sanitizer) are slower evidence, not better, and a repo-wide build is unnecessary when the package's test run already compiles the touched package and its dependencies. Run each checkpoint once, as a single chained shell command (baseline pass on the unmodified code; final pass after the change) — re-run only the specific check that failed. Read the actual terminal output and confirm it is green; do not assume success from a quiet exit.
  6. Commit with the correct sign-off. Respect the upstream sign-off convention: for DCO repos, sign with the user's identity so the commit carries
    Signed-off-by: Name <email>
    (
    git commit -s
    ). Never change the git identity for the task, and never commit secrets. Commits must never carry a
    Co-Authored-By
    trailer — not one crediting the agent, the platform, or any tool: those identities have no CLA, and upstream CI that checks the CLA fails on them. The agent platform can append such a trailer automatically when the commit is made, so verify the message after committing (
    git log -1 --format=%B
    ), and if a
    Co-authored-by:
    line is present, rewrite it out of the last commit before pushing:
    sh
    git update-ref HEAD "$(git commit-tree "HEAD^{tree}" -p HEAD^ -m "$(git log -1 --format=%B | grep -v '^Co-authored-by:')")"
    Do not
    git commit --amend
    for this: amend re-runs the commit hooks and the trailer comes back;
    commit-tree
    bypasses them.
  7. Re-read the diff, then push. Review the generated diff for scope creep, then push the branch to the fork's origin. Do not open a PR against the fork — a fork PR shows up in the upstream's PR timeline and pollutes it with updates the maintainers will never review. The pushed branch alone is the deliverable.
  8. Write the PR body from the upstream PR template. Use the target repo's own template exactly: its sections, headings, and checkboxes, in the template's order. Do not import sections from another repo's template — the body's structure is whatever the target repo defines. Fill in what it does, the motivation (linked to the upstream issue if one exists), and the exact testing commands with their results (in the template's testing section if it has one). Then append the AI disclosure note at the end, after the template's sections.
    The note is a must-have, not optional: the PR body must acknowledge that the change was drafted with AI assistance and that a human reviewed it before the PR was submitted. Both halves are required — the AI disclosure and the human review. Example wording (from kubernetes-sigs/external-dns PR #6846 — adapt to the repo's tone if needed):
    Note: this change was drafted with AI assistance and reviewed locally before submission.
    Never drop the note, and never claim a human review that did not happen.
  9. Post the deliverable comment on the Multica issue (
    multica issue comment add <issue-id> --content-file <path>
    ). It must carry:
    • The branch name and the fork URL with a link to the branch diff.
    • The verification summary: the exact commands run (tests, lint, CI-equivalent checks) and their results.
    • The PR title and body in a fenced markdown block, pasteable as-is for the upstream PR. The user will copy the block's content straight into the upstream PR form, so the PR title is the first line inside the fence, followed by a blank line and the body in the format defined by the target repo's own PR template — its sections, headings, and checkboxes verbatim, in the template's order — with the exact testing commands and their results (in the template's testing section if it has one), and the AI disclosure note appended at the end after the template's sections. The fence is the one constant across repos; the body's structure is never assumed, only read from the target repo's template. Never render the PR body as live markdown in the comment — rendered headings, bold titles, and checkbox widgets cannot be copied back into the template, which defeats the purpose of the deliverable. It must appear verbatim inside a
      ```markdown
      fence. For several PRs in one comment, label each section (e.g.
      ### 1. <title>
      ) with its branch and commit, and put one fenced block per PR. Shape of the deliverable:
      markdown
      ### 1. `refactor(scope): <title>`
      
      ```markdown
      refactor(scope): <title>
      
      <the target repo's PR template sections, verbatim and in order>
      
      <testing commands and their results, if the template has no section for them>
      
      Note: this change was drafted with AI assistance and reviewed locally before submission.
      ```
    • A closing line: no PR was opened anywhere — the branch sits in the fork, and opening the upstream PR is the user's call.
  10. Close out. Set the issue status per the platform workflow once the deliverable is posted.
  1. 编写任何代码前,先阅读上游规范。
    • 根目录中面向 Agent 的文档——
      CONTRIBUTING.md
      、
      AGENTS.md
      、
      CLAUDE.md
      (以实际存在的文件为准)——以及 issue 和 PR 模板(
      .github/PULL_REQUEST_TEMPLATE*
      ),还有 tracker 中任何 contribution 或 AI-PR policy。
    • Commit 约定(Conventional Commits 或其他方式)、DCO 与 CLA 的适用情况,以及 CI 期望:上游 workflows 会运行哪些 commands、哪些 tool versions 已固定(Makefile 的
      make lint
      targets、
      .golangci.yml
      、workflow 的
      go-version
      等)。
    • 即将修改的具体文件所遵循的 code style:命名、错误处理、test framework,以及应复用而非重新实现的现有 helpers。 如果 upstream 禁止完全由 AI 生成的 PR,或要求用户签署尚未签署的 CLA,应记录这一点并停止——不要继续 push。
  2. 准备 branch。 Clone 或 fetch fork。基于 upstream default branch 创建新 branch(显式 fetch upstream;不要假定 fork 的 head 是最新的)。命名为
    feature-<short-name>
    或
    fix-<short-name>
    ——绝不要使用泛化的 Agent 生成 branch 名。
  3. 测试优先,等价性优先。 在更改行为前,为变更涉及的路径添加测试——尤其是当前没有 coverage 的分支。将这些测试运行在 未修改的代码 上:它们必须在未修改时通过。只有变更后才通过的测试证明新结构可以工作;变更前就已通过的测试证明行为保持一致,而这正是 reviewer 信任重构所需要的信息。
  4. 实现变更。 一项逻辑变更,最小 diff——不做无关的 refactor、rename、delete 或 formatting tweak。严格匹配步骤 1 中的仓库规范。
  5. push 前,在本地运行上游 CI/CD 检查。 fork 不会运行 upstream CI/CD,因此除此之外没有其他环境会运行。复现 upstream workflows 所执行的内容:build、package 的 test suite(如果仓库使用 race/sanitizer flags,则一并带上),以及使用 固定 tool versions 的仓库 lint target(使用更新版 linter 得到的通过结果并不是同等证据)。只复现 upstream workflows 实际运行的内容,不多做一些:它们未使用的 flags(额外加
    -race
    或 sanitizer)只会让证据更慢,并不会更好;而当 package 的 test run 已经编译了被修改的 package 及其 dependencies 时,无须进行 repo-wide build。将每个 checkpoint 运行一次,采用一条 chained shell command(先在未修改代码上执行 baseline pass,变更后再执行 final pass)——只在某项具体检查失败时重跑该项。读取真实的 terminal output 并确认其为绿色;不要因为没有输出就假定成功。
  6. 使用正确的 sign-off 提交。 遵循上游 sign-off 约定:对于 DCO 仓库,使用用户 identity 签署,使 commit 带有
    Signed-off-by: Name <email>
    (
    git commit -s
    )。执行任务时绝不更改 git identity,也绝不提交 secrets。Commits 绝不能带
    Co-Authored-By
    trailer——无论是署名给 Agent、平台还是工具:这些 identity 没有签署 CLA,而检查 CLA 的 upstream CI 会因此失败。Agent 平台可能会在创建 commit 时自动追加此类 trailer,因此提交后要验证 message(
    git log -1 --format=%B
    );如果存在
    Co-authored-by:
    行,请在 push 前将最后一条 commit 中的该行重写掉:
    sh
    git update-ref HEAD "$(git commit-tree "HEAD^{tree}" -p HEAD^ -m "$(git log -1 --format=%B | grep -v '^Co-authored-by:')")"
    不要使用
    git commit --amend
    :amend 会重新运行 commit hooks,trailer 会再次出现;
    commit-tree
    会绕过这些 hooks。
  7. 重新阅读 diff,然后 push。 检查生成的 diff 是否出现范围蔓延,然后将 branch push 到 fork 的 origin。不要针对 fork 创建 PR——fork PR 会出现在 upstream 的 PR timeline 中,并为其维护者永远不会审核的更新污染记录。已 push 的 branch 本身就是交付物。
  8. 根据上游 PR 模板编写 PR 正文。 严格使用 目标仓库自己的模板:保留其 sections、headings 和 checkboxes,并按模板顺序排列。不要引入其他仓库模板中的 sections——正文结构完全由目标仓库定义。填写变更内容、动机(如果存在则关联 upstream issue),以及准确的 testing commands 及其结果(如果模板有 testing section,就放在其中)。然后在模板 sections 之后、末尾追加 AI disclosure note。
    该 note 是 必需项,并非可选项:PR 正文必须说明此变更由 AI 辅助起草,并且在 PR 提交前经过人工审阅。两部分缺一不可——AI disclosure 和 human review。示例措辞(来自 kubernetes-sigs/external-dns PR #6846——如有需要,可根据仓库语气调整):
    注意:此变更由 AI 辅助起草,并在提交前经过本地审阅。
    绝不能省略该 note,也绝不能声称发生过实际上没有的人工审阅。
  9. 在 Multica issue 上发布交付物 comment(
    multica issue comment add <issue-id> --content-file <path>
    )。它必须包含:
    • branch 名称和 fork URL,并附上 branch diff 的链接。
    • verification summary:实际运行的准确 commands(tests、lint、CI-equivalent checks)及其结果。
    • 位于 fenced markdown block 中的 PR title 和 body,可直接粘贴到 upstream PR。用户会将 block 中的内容原样复制到 upstream PR 表单,因此 PR title 必须是 fence 内的第一行,随后是一个空行,再按照 目标仓库自己的 PR 模板 格式提供正文——逐字保留其 sections、headings 和 checkboxes,并按模板顺序排列——同时包含准确的 testing commands 及其结果(如果模板有 testing section,就放在其中),并在模板 sections 之后追加 AI disclosure note。Fence 是各仓库之间唯一不变的部分;正文结构不可假定,只能从目标仓库的模板中读取。绝不要在 comment 中将 PR body 呈现为 live markdown——渲染后的 headings、加粗标题和 checkbox widgets 无法复制回模板,这会违背交付物的目的。它必须逐字出现在一个 ```markdown fence 内。若一条 comment 中包含多个 PR,请为每个 section 添加标签(例如
      ### 1. <title>
      ),并附上其 branch 和 commit,每个 PR 使用一个 fenced block。交付物格式如下:
    markdown
    ### 1. `refactor(scope): <title>`
    
    ```markdown
    refactor(scope): <title>
    
    <the target repo's PR template sections, verbatim and in order>
    
    <testing commands and their results, if the template has no section for them>
    
    Note: this change was drafted with AI assistance and reviewed locally before submission.
    ```
    • 结束语:未在任何位置创建 PR——branch 位于 fork 中,是否创建 upstream PR 由用户决定。
  10. 收尾。 交付物发布后,按照 platform workflow 设置 issue 状态。

Review iterations (the PR is already open)

Review 迭代(PR 已开启)

When the issue or a comment asks to address maintainer review comments on a PR the user has already opened, the branch and the PR exist — the work is a fix iteration, not a new contribution:
  1. Read the review threads verbatim (GitHub MCP
    pull_request_read
    with
    get_review_comments
    , paginated). Work from the exact comment text and suggested code, never a paraphrase or a summary of an earlier turn.
  2. Split the threads into explicit requests and discussions. An explicit request is an instruction or a concrete suggestion block — implement it exactly. A discussion — a question, a "Maybe …?" proposal, a trade-off remark, a "fine as is" note — is not yours to answer: flag it in the deliverable comment for the human, and implement nothing for it unless the human has already decided in a comment.
  3. Never assume what a discussion resolves to. If a thread is ambiguous, leave the code alone and surface the question. The human reads the thread and decides; the resolution — not your guess — is what a later iteration implements.
  4. Verify and push to the same fork branch. Same evidence bar as the initial run (build, tests, lint with the pinned tooling, inspected output). Pushing updates the open PR in place; never open a new branch or a new PR for review fixes. Commits follow the step-6 sign-off rule — user identity,
    Signed-off-by
    , and no
    Co-Authored-By
    trailers.
  5. Post a pasteable PR comment for every PR that received new changes. Every iteration that pushes new commits gets one — even if it touches only a subset of the PRs, in which case only those get a block. Same format rules as the pasteable PR body: a fenced
    ```markdown
    block per PR, pasteable verbatim into the PR conversation, never rendered live. It thanks the reviewer, names the new commit, and answers each explicit review comment in order with what was done. Flagged discussion items are listed in the Multica comment, not in the pasteable block, unless the human wants to put a question to the reviewer.
  6. Leave the PR to the humans. You do not reply to, resolve, or edit review threads, and you do not edit the PR body or description — if a comment demands a PR-body change and you cannot make it, hand the exact needed edit to the human in the deliverable comment. The human pastes the PR comment, follows the discussion, resolves the threads, and merges.
当 issue 或 comment 要求处理用户已经开启的 PR 上 maintainer 留下的 review comments 时,branch 和 PR 均已存在——这是一次修复迭代,而不是一项新贡献:
  1. 逐字阅读 review threads(GitHub MCP
    pull_request_read
    ,带
    get_review_comments
    ,分页获取)。依据确切的 comment 文本和建议代码工作,绝不能使用转述或前一轮对话的摘要。
  2. 将 threads 分为明确请求和 discussions。 明确请求是指令或具体的建议代码块——应准确实现。discussion——问题、“也许……?”式提案、权衡说明或“保持原样即可”之类的备注——不属于你回答的范畴:在交付物 comment 中标出供人工处理;除非人工已在 comment 中作出决定,否则不要为其实现任何内容。
  3. 绝不假定 discussion 的 resolution。 如果某个 thread 含义不明确,保持代码不变并提出问题。由人工阅读 thread 并作出决定;后续迭代应实现的是 resolution,而不是你的猜测。
  4. 验证并 push 到同一 fork branch。 证据标准与首次运行相同(build、tests、使用固定 tooling 的 lint,并检查 output)。Push 会就地更新已开启的 PR;绝不要为 review fixes 新建 branch 或新 PR。Commits 遵循步骤 6 的 sign-off 规则——用户 identity、
    Signed-off-by
    ,且不带
    Co-Authored-By
    trailers。
  5. 为每个收到新变更的 PR 发布可粘贴的 PR comment。 每次 push 新 commits 的迭代都要发布一条——即使只涉及部分 PR,也仅为这些 PR 提供 block。格式规则与可粘贴 PR 正文相同:每个 PR 使用一个 fenced
    ```markdown
    block,可逐字粘贴到 PR conversation 中,绝不能以 live markdown 呈现。它应感谢 reviewer、注明新 commit,并按顺序回答每条明确的 review comment。被标出的 discussion 项列在 Multica comment 中,而不是可粘贴 block 中,除非人工希望向 reviewer 提问。
  6. 把 PR 留给人工处理。 不回复、resolve 或 edit review threads,也不 edit PR 正文或 description——如果某条 comment 要求修改 PR 正文而你无法完成,应在交付物 comment 中把所需的确切 edit 交给人工。人工粘贴 PR comment、跟进 discussion、resolve threads 并 merge。

Conventions this run followed (beyond the steps above)

本次运行遵循的约定(上述步骤之外)

  • Toolchain pinned to the repo. Verify the language toolchain the repo requires (e.g. the
    go.mod
    /
    GOTOOLCHAIN
    requirement, the linter version pinned by the Makefile or CI) before running anything — a green build on the wrong toolchain is false evidence.
  • Narrow reads, bounded context. Read the narrowest slice needed — one path, one line range, one diff — and summarize learnings before fetching more. Never dump whole files or unpaginated logs into the conversation.
  • Fewer, batched calls. In long runs the conversation is re-sent on every tool call, so the call count — not the commands — dominates cost. Combine independent steps into one chained shell command, read a range once instead of re-reading it, and never re-fetch what is already in context.
  • Parse-only tools for ranking and re-measuring metrics. When the task is to rank code by a metric (e.g. cyclomatic complexity) or to re-measure it after a refactor, use a parse-only analyzer that needs no build (Go:
    gocyclo -over N ./pkg/
    ); reserve the repo's pinned linter for the final package-level CI evidence, not for ranking or re-measurement.
  • Whole-function edits, not cascades. Read the full line range of a function once, then replace the whole function in a single edit. Cascading many small edits is where whitespace mismatches and indentation damage come from.
  • Pipes hide failures. Never pipe a verification command into
    grep
    or
    head
    when its success is the evidence: a failing tool still prints lines a filter can drop, and the exit status is lost — an empty "scan" may be a failed command, not a clean result.
  • Lightweight clones. When managing the clone yourself, use a blobless or shallow clone (
    git clone --filter=blob:none
    , or
    --depth
    when full history is not needed) — history stays available on demand and the initial transfer is far smaller.
  • One branch per logical change. If the work spans several independent changes, do one per branch and report them separately, so the user can open, sequence, or discard them independently.
  • Verification is evidence, not ritual. Every command's real output must be inspected (tests passing, lint "0 issues", build silence), and the summary must quote what was run and what it reported — a "tests pass" claim without the command and the observed result is not a verification.
  • Stop at the deliverable. The moment the branch is pushed and the comment is posted, the work is done. Wait for the human to validate and open the upstream PR; do not chase CI, reviews, or merges on your own. In review iterations the same holds for the discussion: the threads, the PR body, the resolutions, and the merge are the human's — your push and the pasteable PR comment are the entire deliverable of the iteration.
  • Toolchain 固定到仓库。 运行任何内容前,验证仓库要求的 language toolchain(例如
    go.mod
    /
    GOTOOLCHAIN
    要求、Makefile 或 CI 固定的 linter version)——在错误 toolchain 上得到的绿色 build 只是虚假证据。
  • 读取范围要窄,context 要有界。 只读取所需的最小范围——一个 path、一个 line range、一个 diff——并在获取更多内容前总结已了解的信息。绝不把完整文件或未分页的 logs 倾倒进 conversation。
  • 减少调用,批量执行。 在长时间运行中,每次 tool call 都会重新发送 conversation,因此主导成本的是 call 数量,而不是 commands。将独立步骤合并为一条 chained shell command;一个 range 只读取一次,而不是反复读取;绝不重新获取已经存在于 context 中的内容。
  • 使用 parse-only tools 对 metrics 排名或重新测量。 当任务需要按某个 metric(例如 cyclomatic complexity)对代码排名,或在 refactor 后重新测量时,使用无需 build 的 parse-only analyzer(Go:
    gocyclo -over N ./pkg/
    );将仓库固定的 linter 留给最终的 package 级 CI 证据,而不是用于排名或重新测量。
  • 整函数编辑,而非级联式小改动。 一次读取函数的完整 line range,然后在一次编辑中替换整个函数。大量连续的小改动容易造成 whitespace 不匹配和 indentation 损坏。
  • Pipe 会隐藏失败。 当某条 verification command 的成功本身就是证据时,绝不要将其 pipe 到
    grep
    或
    head
    :失败的工具仍可能输出被 filter 丢弃的行,同时 exit status 也会丢失——一次空白的“scan”可能意味着命令失败,而非结果干净。
  • 轻量 clone。 自己管理 clone 时,使用 blobless 或 shallow clone(
    git clone --filter=blob:none
    ,或在不需要完整历史时使用
    --depth
    );history 仍可按需获取,而初始传输量小得多。
  • 每项逻辑变更使用一个 branch。 如果工作涉及多项独立变更,每项使用一个 branch 并分别报告,以便用户独立 open、排序或 discard。
  • Verification 是证据,不是仪式。 必须检查每条 command 的真实 output(tests passing、lint 报告“0 issues”、build silence),并且 summary 必须引用实际运行的内容及其报告结果——仅声称“tests pass”而不给出 command 和观察到的结果,不构成 verification。
  • 在交付物处停止。 一旦 branch 已 push 且 comment 已发布,工作即告完成。等待人工验证并开启 upstream PR;绝不自行追踪 CI、reviews 或 merges。在 review 迭代中,对 discussion 也遵循同样的原则:threads、PR 正文、resolutions 和 merge 都属于人工;你的 push 和可粘贴 PR comment 就是本次迭代的全部交付物。