finish-pr

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Finish PR

完成PR

Bring the pull request attached to the current branch to a genuinely ready state.
Requires Git 2.38+, GitHub CLI (
gh
) authenticated for the repository, and PowerShell 7 (
pwsh
) for bundled helpers.
将当前分支关联的pull request推进至真正就绪的状态。
需要Git 2.38+、针对仓库已认证的GitHub CLI (
gh
),以及用于捆绑工具的PowerShell 7 (
pwsh
)。

Definition of done

完成定义

Finish only when all of these are true for the current PR HEAD:
  • GitHub and a local merge probe show no merge conflicts.
  • No CI check is failing. Pending checks may still be running, but never describe the PR as fully ready while a required check is pending.
  • Every unresolved review thread is in one of these states:
    • its latest unaddressed feedback has been actioned and the agent has replied with the result; or
    • the latest relevant comment is the agent's response and no reviewer has replied afterwards, so the thread is awaiting review and needs no duplicate work.
  • No reply created by this run remains in a pending GitHub review.
  • No review thread's resolution state was changed by this run.
  • The exact current HEAD has a successful completed
    Gitar
    check, Gitar's dashboard Code Review verdict is
    Approved
    , and no later Gitar or other reviewer feedback is left unaddressed.
This completion rule uses Gitar Core only. Never require Gitar auto-approval, a GitHub approving review, merge blocking, auto-apply, or any other Pro signal. Treat
Approved with Suggestions
,
Changes Requested
,
Blocked
, and
Needs Review
as non-terminal feedback states even if the
Gitar
check itself succeeds.
An unresolved thread is not automatically unfinished. Reviewers own resolution state; the conversation order determines whether the agent currently owes action.
仅当当前PR HEAD满足以下所有条件时,才视为完成:
  • GitHub和本地合并探查均显示无合并冲突。
  • 无CI检查失败。待处理的检查仍可运行,但只要有必填检查处于待处理状态,就绝不能将PR描述为完全就绪。
  • 每个未解决的评审线程都处于以下状态之一:
    • 其最新未处理的反馈已得到处理,且Agent已回复处理结果;或
    • 最新相关评论是Agent的回复,且评审者尚未跟进,因此该线程正在等待评审,无需重复工作。
  • 本次运行创建的回复均未处于GitHub待处理评审状态。
  • 本次运行未更改任何评审线程的解决状态。
  • 当前精确HEAD已通过
    Gitar
    检查,Gitar仪表板的代码评审 verdict为
    Approved
    ,且无后续Gitar或其他评审者的反馈未处理。
本完成规则仅使用Gitar Core。绝不要求Gitar自动批准、GitHub批准评审、合并阻止、自动应用或任何其他Pro信号。即使
Gitar
检查本身成功,也需将
Approved with Suggestions
Changes Requested
Blocked
Needs Review
视为非终结反馈状态。
未解决的线程并不自动代表未完成。评审者拥有解决状态的控制权;对话顺序决定Agent当前是否需要采取行动。

Operating rules

操作规则

  • Use the conversation history as first-class task context. The skill is often invoked after implementation, so recover the user's intent, earlier decisions, tradeoffs, verification, known limitations, and reasons for the current design before judging PR feedback.
  • Read every applicable
    AGENTS.md
    plus repository-native requirements and design documents implicated by the PR. Discover these from the repository and PR; never assume a particular task directory, branch naming scheme, language, build system, or hosting provider.
  • Treat unresolved review threads as the authoritative inline-feedback list. Also inspect PR-level reviews and issue comments for standalone actionable feedback.
  • Preserve unrelated worktree changes. Commit only changes made during this run.
  • Resolve conflicts before failed checks, and failed checks before review feedback. Later evidence may require revisiting an earlier phase.
  • Prefer the smallest correct change. Add focused tests for behavioural or regression-prone fixes.
  • Use exactly one focused, unsquashed commit per action-required PR feedback unit whose disposition produces a change: one review thread or one standalone PR-level feedback item. Never combine multiple units into one commit, even when they are related. A justified disagreement requires a reply but no commit.
  • Never rebase, force-push, merge the pull request on GitHub, close, approve, or mark the PR ready for review unless the user explicitly requested that separate action. The conflict-resolution workflow may merge the latest base commit into the PR branch.
  • Never resolve or unresolve a review thread. Do not call
    resolveReviewThread
    ,
    unresolveReviewThread
    , or an equivalent.
  • Reply directly to review threads, one at a time. Never create replies concurrently.
  • Continue autonomously through new feedback from Gitar and every other source after pushes, within the convergence bounds below.
  • Never ask Gitar to apply or commit a fix. Do not use
    gitar fix
    , one-click apply, or
    gitar auto-apply:on
    . This agent owns every code change.
  • 将对话历史作为一等任务上下文。本技能通常在实现后调用,因此在判断PR反馈前,需还原用户意图、早期决策、权衡方案、验证结果、已知限制以及当前设计的理由。
  • 阅读所有适用的
    AGENTS.md
    以及PR涉及的仓库原生要求和设计文档。从仓库和PR中查找这些文档;绝不假设特定的任务目录、分支命名方案、语言、构建系统或托管提供商。
  • 将未解决的评审线程视为权威的内联反馈列表。同时检查PR级评审和问题评论,寻找独立的可操作反馈。
  • 保留无关的工作区变更。仅提交本次运行期间所做的变更。
  • 先解决冲突,再处理失败的检查,最后处理评审反馈。后续证据可能需要重新审视早期阶段。
  • 优先选择最小的正确变更。针对行为修复或易回归修复添加针对性测试。
  • 每个需要处理的PR反馈单元(其处理结果产生变更)对应一个独立的、未压缩的提交:一个评审线程或一个独立的PR级反馈项。即使相关,也绝不能将多个单元合并到一个提交中。合理的异议只需回复,无需提交。
  • 除非用户明确要求单独操作,否则绝不执行变基、强制推送、在GitHub上合并拉取请求、关闭、批准或标记PR为就绪评审状态。冲突解决工作流可将最新的基础提交合并到PR分支。
  • 绝不解决或重新打开评审线程。不要调用
    resolveReviewThread
    unresolveReviewThread
    或等效功能。
  • 直接回复评审线程,一次一个。绝不并发创建回复。
  • 推送后,自主处理来自Gitar和所有其他渠道的新反馈,遵循以下收敛边界。
  • 绝不要求Gitar应用或提交修复。不要使用
    gitar fix
    、一键应用或
    gitar auto-apply:on
    。所有代码变更均由本Agent负责。

1. Establish state and intent

1. 建立状态与意图

  1. Locate the repository root and read applicable instructions.
  2. Inspect:
    powershell
    git status --short
    git rev-parse --abbrev-ref HEAD
    git rev-parse HEAD
    gh --version
    gh auth status
    gh pr view --json number,title,url,body,author,headRefName,headRefOid,headRepository,headRepositoryOwner,isCrossRepository,baseRefName,baseRefOid,mergeable,mergeStateStatus,reviews,comments
  3. Record the starting SHA and every existing changed path, separating staged, unstaged, and untracked changes. Never include pre-existing changes in this run's commits. A feedback or CI fix must not touch a path that had any pre-existing staged, unstaged, or untracked change. Stop and ask the user before editing that path; partial staging plus
    git commit --only
    does not preserve same-file hunk isolation.
  4. If the current branch has no PR, inspect
    gh pr status
    . Switch or check out a PR only when the mapping is unambiguous and local changes are safe; otherwise ask the user.
  5. Reconstruct the intended change from, in priority order:
    • explicit user instructions and this conversation;
    • applicable repository instructions;
    • PR title, body, commits, and diff;
    • linked issue/spec/design documents;
    • surrounding code, tests, and conventions.
  6. Inspect the complete PR diff before evaluating conflicts, CI, or feedback.
  7. Identify the Gitar integration from exact case-insensitive
    Gitar
    check runs whose GitHub App slug is Gitar-marked, plus the Gitar-authored dashboard Code Review comment. Treat the exact-HEAD check as the processing/completion boundary and the dashboard's Code Review verdict as the review result. Never infer completion from reactions or require a GitHub approval review.
  8. Resolve the authenticated GitHub viewer login. Treat comments from that login, or another agent login established unambiguously by the conversation/PR history, as agent responses.
  9. Resolve the base and head repositories independently from PR metadata:
    • derive the base repository from the PR URL;
    • use
      headRepository.nameWithOwner
      for the head repository;
    • prefer existing configured remotes that match those exact repositories;
    • otherwise use GitHub-provided clone URLs and configure Git to use the authenticated
      gh
      credential helper;
    • retain the exact
      headRefName
      .
    powershell
    $pr = gh pr view --json number,url,headRefName,headRefOid,headRepository,headRepositoryOwner |
      ConvertFrom-Json
    $prNumber = [int]$pr.number
    $prUri = [uri]$pr.url
    $pathSegments = $prUri.AbsolutePath.Trim("/").Split("/")
    $githubHostname = $prUri.Authority
    $baseRepositoryName = "$($pathSegments[0])/$($pathSegments[1])"
    $baseRepository = "$githubHostname/$baseRepositoryName"
    $baseMetadata = gh api --hostname $githubHostname "repos/$baseRepositoryName" |
      ConvertFrom-Json
    $headMetadata = gh api --hostname $githubHostname "repos/$($pr.headRepository.nameWithOwner)" |
      ConvertFrom-Json
    gh auth setup-git --hostname $githubHostname
    $baseFetchUrl = [string]$baseMetadata.clone_url
    $headPushUrl = [string]$headMetadata.clone_url
    GitHub's
    clone_url
    preserves the server authority, including non-default ports, while
    gh auth setup-git
    makes HTTPS Git operations use the authenticated CLI identity. A verified matching SSH/configured remote may be used instead. Stop if authentication, repository identity, or the head repository is unavailable or ambiguous. Never assume
    origin
    points to either side of a fork-based PR.
  10. Align the checkout with the exact PR head before making any changes:
powershell
git fetch $headPushUrl $pr.headRefName
$remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
$lastObservedPrHeadSha = $remoteHeadSha
$localHeadSha = (git rev-parse HEAD).Trim()
git merge-base --is-ancestor $remoteHeadSha $localHeadSha
$localContainsRemoteHead = $LASTEXITCODE -eq 0

if ($localContainsRemoteHead -and $localHeadSha -ne $remoteHeadSha) {
  $initialLocalAheadCommits = git log --oneline "$remoteHeadSha..$localHeadSha"
  # Validate and record every commit against the recovered user intent and full PR diff.
  # Stop for confirmation if any commit is unrelated, unfinished, or ambiguous.
}

if (-not $localContainsRemoteHead) {
  git merge-base --is-ancestor $localHeadSha $remoteHeadSha
  $canFastForward = $LASTEXITCODE -eq 0 -and -not (git status --porcelain)
  if (-not $canFastForward) {
    throw "Local HEAD is stale or diverged from the PR head; stop before mutation."
  }

  git merge --ff-only $remoteHeadSha
}
Continue only when local
HEAD
matches the fetched PR head, is safely fast-forwarded to it, or every initially local-ahead commit was explicitly validated as intended PR work from conversation and repository evidence. Record those commits as pre-existing push scope; stop for confirmation on any uncertainty. Never silently publish local-ahead commits. 11. Create one unique state directory outside the repository and retain it for the full run:
powershell
$runStateDirectory = Join-Path ([IO.Path]::GetTempPath()) (
  "finish-pr-{0}-{1}" -f $prNumber, [guid]::NewGuid().ToString("N")
)
New-Item -ItemType Directory -Path $runStateDirectory | Out-Null
Store every baseline, snapshot, and watcher-state file for this run inside this directory so concurrent runs cannot overwrite one another.
  1. 定位仓库根目录并阅读适用说明。
  2. 检查:
    powershell
    git status --short
    git rev-parse --abbrev-ref HEAD
    git rev-parse HEAD
    gh --version
    gh auth status
    gh pr view --json number,title,url,body,author,headRefName,headRefOid,headRepository,headRepositoryOwner,isCrossRepository,baseRefName,baseRefOid,mergeable,mergeStateStatus,reviews,comments
  3. 记录起始SHA以及所有已变更路径,区分暂存、未暂存和未跟踪变更。绝不将预先存在的变更包含在本次运行的提交中。 反馈或CI修复不得触及任何存在预先暂存、未暂存或未跟踪变更的路径。编辑该路径前需停止并询问用户;部分暂存加
    git commit --only
    无法保证同一文件内的代码块隔离。
  4. 如果当前分支无PR,检查
    gh pr status
    。仅当映射明确且本地变更安全时,才切换或检出PR;否则询问用户。
  5. 按以下优先级重构预期变更:
    • 明确的用户指令和本次对话;
    • 适用的仓库指令;
    • PR标题、正文、提交和差异;
    • 关联的问题/规范/设计文档;
    • 周边代码、测试和约定。
  6. 在评估冲突、CI或反馈前,检查完整的PR差异。
  7. 从GitHub应用slug标记为Gitar的精确大小写不敏感
    Gitar
    检查运行,以及Gitar撰写的仪表板代码评审评论中识别Gitar集成。将精确HEAD检查视为处理/完成边界,将仪表板的代码评审verdict视为评审结果。绝不从反应推断完成状态,也不要求GitHub批准评审。
  8. 解析已认证的GitHub查看者登录信息。将该登录账号的评论,或由对话/PR历史明确确定的其他Agent登录账号的评论视为Agent回复。
  9. 独立于PR元数据解析基础仓库和头仓库:
    • 从PR URL推导基础仓库;
    • 使用
      headRepository.nameWithOwner
      作为头仓库;
    • 优先选择与这些精确仓库匹配的现有配置远程;
    • 否则使用GitHub提供的克隆URL,并配置Git使用已认证的
      gh
      凭证助手;
    • 保留精确的
      headRefName
    powershell
    $pr = gh pr view --json number,url,headRefName,headRefOid,headRepository,headRepositoryOwner |
      ConvertFrom-Json
    $prNumber = [int]$pr.number
    $prUri = [uri]$pr.url
    $pathSegments = $prUri.AbsolutePath.Trim("/").Split("/")
    $githubHostname = $prUri.Authority
    $baseRepositoryName = "$($pathSegments[0])/$($pathSegments[1])"
    $baseRepository = "$githubHostname/$baseRepositoryName"
    $baseMetadata = gh api --hostname $githubHostname "repos/$baseRepositoryName" |
      ConvertFrom-Json
    $headMetadata = gh api --hostname $githubHostname "repos/$($pr.headRepository.nameWithOwner)" |
      ConvertFrom-Json
    gh auth setup-git --hostname $githubHostname
    $baseFetchUrl = [string]$baseMetadata.clone_url
    $headPushUrl = [string]$headMetadata.clone_url
    GitHub的
    clone_url
    保留服务器权限(包括非默认端口),而
    gh auth setup-git
    使HTTPS Git操作使用已认证的CLI身份。也可使用已验证匹配的SSH/配置远程。如果认证、仓库身份或头仓库不可用或不明确,则停止操作。绝不假设
    origin
    指向基于派生的PR的任何一方。
  10. 在进行任何变更前,将检出内容与精确的PR头对齐:
    powershell
    git fetch $headPushUrl $pr.headRefName
    $remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
    $lastObservedPrHeadSha = $remoteHeadSha
    $localHeadSha = (git rev-parse HEAD).Trim()
    git merge-base --is-ancestor $remoteHeadSha $localHeadSha
    $localContainsRemoteHead = $LASTEXITCODE -eq 0
    
    if ($localContainsRemoteHead -and $localHeadSha -ne $remoteHeadSha) {
      $initialLocalAheadCommits = git log --oneline "$remoteHeadSha..$localHeadSha"
      # 根据还原的用户意图和完整PR差异验证并记录每个提交。
      # 如果任何提交无关、未完成或不明确,则停止并确认。
    }
    
    if (-not $localContainsRemoteHead) {
      git merge-base --is-ancestor $localHeadSha $remoteHeadSha
      $canFastForward = $LASTEXITCODE -eq 0 -and -not (git status --porcelain)
      if (-not $canFastForward) {
        throw "Local HEAD is stale or diverged from the PR head; stop before mutation."
      }
    
      git merge --ff-only $remoteHeadSha
    }
    仅当本地
    HEAD
    与获取的PR头匹配、可安全快进至该头,或所有初始本地超前提交均通过对话和仓库证据明确验证为预期PR工作时,才继续操作。将这些提交记录为预先存在的推送范围;如有任何不确定性,停止并确认。绝不静默发布本地超前提交。
  11. 在仓库外创建一个唯一的状态目录,并在整个运行期间保留:
    powershell
    $runStateDirectory = Join-Path ([IO.Path]::GetTempPath()) (
      "finish-pr-{0}-{1}" -f $prNumber, [guid]::NewGuid().ToString("N")
    )
    New-Item -ItemType Directory -Path $runStateDirectory | Out-Null
    将本次运行的所有基线、快照和监视器状态文件存储在此目录中,以便并发运行不会相互覆盖。

2. Resolve merge conflicts

2. 解决合并冲突

Run this before CI or feedback:
  1. Refresh PR/base metadata and perform a non-mutating local probe:
    powershell
    $pr = gh pr view $prNumber --repo $baseRepository --json number,url,baseRefName,baseRefOid,headRefName,headRefOid,headRepository,headRepositoryOwner,mergeable,mergeStateStatus |
      ConvertFrom-Json
    git fetch $baseFetchUrl $pr.baseRefName
    $baseCommit = (git rev-parse FETCH_HEAD).Trim()
    git merge-tree --write-tree --messages HEAD $baseCommit
  2. Investigate locally when GitHub reports
    CONFLICTING
    ,
    DIRTY
    , or
    UNKNOWN
    , or when the probe reports conflicts.
  3. If conflicts exist, check the initial worktree baseline before merging. A normal merge requires a clean index: if any pre-existing staged change remains, stop before mutation and tell the user to commit or stash it, or request explicit permission to isolate and restore the index. Do not use
    --autostash
    on user work without that permission.
    If the index is clean and unrelated local changes are safe, merge the latest base into the PR branch:
    powershell
    git merge --no-ff $baseCommit
  4. Resolve each conflict using the recovered task intent, repository requirements, adjacent code, and tests. Do not mechanically prefer either side.
  5. Run focused verification, stage only the resolution, and commit it. Record the conflict summary, commit SHA, and checks run.
  6. If the merge is clean, keep any Git-created merge commit but do not create an extra empty commit.
在处理CI或反馈前执行此步骤:
  1. 刷新PR/基础元数据并执行非变异本地探查:
    powershell
    $pr = gh pr view $prNumber --repo $baseRepository --json number,url,baseRefName,baseRefOid,headRefName,headRefOid,headRepository,headRepositoryOwner,mergeable,mergeStateStatus |
      ConvertFrom-Json
    git fetch $baseFetchUrl $pr.baseRefName
    $baseCommit = (git rev-parse FETCH_HEAD).Trim()
    git merge-tree --write-tree --messages HEAD $baseCommit
  2. 当GitHub报告
    CONFLICTING
    DIRTY
    UNKNOWN
    ,或探查报告冲突时,在本地调查。
  3. 如果存在冲突,在合并前检查初始工作区基线。正常合并需要干净的索引:如果任何预先存在的暂存变更仍存在,则在变异前停止,并告知用户提交或暂存该变更,或请求明确权限以隔离和恢复索引。未经许可,不得对用户工作使用
    --autostash
    如果索引干净且无关本地变更安全,则将最新基础合并到PR分支:
    powershell
    git merge --no-ff $baseCommit
  4. 使用还原的任务意图、仓库要求、相邻代码和测试解决每个冲突。不要机械地偏好任何一方。
  5. 运行针对性验证,仅暂存解决方案,并提交。记录冲突摘要、提交SHA和运行的检查。
  6. 如果合并干净,保留Git创建的合并提交,但不要创建额外的空提交。

3. Fix failed CI

3. 修复失败的CI

  1. Inspect all checks:
    powershell
    gh pr checks $prNumber --repo $baseRepository --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    gh pr checks $prNumber --repo $baseRepository --required --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    Use the second query to distinguish required checks from optional checks. Treat “no required checks reported” as an empty required set, not a failure.
  2. For each failure, retrieve the actual logs before editing:
    powershell
    gh run list --repo $baseRepository --branch $pr.headRefName --commit $pr.headRefOid --json databaseId,name,workflowName,status,conclusion,url,headSha,event,createdAt -L 50
    gh run view <run-id> --repo $baseRepository --json name,status,conclusion,jobs,url
    gh run view <run-id> --repo $baseRepository --log-failed
  3. For non-Actions checks, inspect the provider link or available check details.
  4. Fix the root cause, not merely the symptom. Work from the clearest upstream failure outward because one failure may cascade into others.
  5. Run the closest local equivalent, inspect the initial worktree baseline, and stage only that fix. Commit with an exact pathspec so pre-existing staged changes remain outside the CI commit:
    powershell
    git commit --only -m "fix(ci): address <failed check>" -- <exact-ci-fix-paths>
    If a CI fix path had pre-existing staged, unstaged, or untracked changes, stop before editing it. Record the check, cause, SHA, and verification.
  6. If a failure is external, flaky, permission-related, or not repository-fixable, capture evidence. Retry only when safe and supported; do not change code to appease an unrelated failure.
  1. 检查所有检查:
    powershell
    gh pr checks $prNumber --repo $baseRepository --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    gh pr checks $prNumber --repo $baseRepository --required --json bucket,completedAt,description,event,link,name,startedAt,state,workflow
    使用第二个查询区分必填检查和可选检查。将“无必填检查报告”视为空必填集,而非失败。
  2. 对于每个失败,在编辑前检索实际日志:
    powershell
    gh run list --repo $baseRepository --branch $pr.headRefName --commit $pr.headRefOid --json databaseId,name,workflowName,status,conclusion,url,headSha,event,createdAt -L 50
    gh run view <run-id> --repo $baseRepository --json name,status,conclusion,jobs,url
    gh run view <run-id> --repo $baseRepository --log-failed
  3. 对于非Actions检查,检查提供商链接或可用的检查详情。
  4. 修复根本原因,而非仅修复症状。从最清晰的上游故障向外处理,因为一个故障可能引发其他故障。
  5. 运行最接近的本地等效检查,检查初始工作区基线,并仅暂存该修复。使用精确路径规范提交,以便预先存在的暂存变更保留在CI提交之外:
    powershell
    git commit --only -m "fix(ci): address <failed check>" -- <exact-ci-fix-paths>
    如果CI修复路径存在预先暂存、未暂存或未跟踪变更,则在编辑前停止。记录检查、原因、SHA和验证结果。
  6. 如果故障是外部的、不稳定的、权限相关的或无法通过仓库修复的,则捕获证据。仅在安全且支持的情况下重试;不要更改代码以适应无关故障。

4. Fetch and classify feedback

4. 获取并分类反馈

Resolve the loaded skill's directory, then use its bundled helpers by absolute path; do not assume the skill lives inside the target repository.
Capture every thread's read-only resolution baseline outside the repository:
powershell
$threadBaseline = Join-Path $runStateDirectory "thread-resolution.json"
$threadSnapshot = Join-Path $runStateDirectory "unresolved-threads.json"
pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname -All |
  Set-Content -Encoding utf8 $threadBaseline

pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname |
  Set-Content -Encoding utf8 $threadSnapshot
For each unresolved thread, read all paginated comments in chronological order and classify it:
  • Awaiting reviewer: the latest relevant comment is an agent response in a submitted review (
    pullRequestReview.state != PENDING
    with non-null
    submittedAt
    ) and nobody has replied later. Do nothing. Do not post a reminder, repeat the fix, or duplicate the response.
  • Action required: there is reviewer feedback after the agent's latest submitted response, the agent has never responded, or its latest response exists only in a pending review.
  • Superseded/non-actionable: the later conversation explicitly withdraws, answers, or supersedes the point. Reply only if the thread still needs an agent acknowledgement; avoid duplicating an existing agent response.
Within action-required threads, identify each distinct feedback item. Judge it against the user's intent, conversation history, repository rules, linked requirements, PR scope, current code, conventions, and tests. The thread is the commit boundary: group all work required by one thread into that thread's single commit, but never include another thread's work.
Classify actionable PR-level review bodies and issue comments with the same rules. Each standalone feedback item is its own commit boundary; never combine it with a review thread or another standalone item. Track it by feedback ID and permalink because it has no review-thread ID.
  • Agree when it identifies a real bug, missed requirement, broken invariant, missing test, misleading behaviour, or scoped maintainability problem.
  • Disagree when it conflicts with requirements, established intent, repository invariants, or would produce a worse/out-of-scope design.
  • When uncertain, make a small scoped correctness fix if evidence supports it. Otherwise explain the uncertainty and why no change was made.
Do not skip outdated unresolved threads; determine whether their feedback still applies to current code.
解析已加载技能的目录,然后通过绝对路径使用其捆绑工具;不要假设技能位于目标仓库内。
在仓库外捕获每个线程的只读解决基线:
powershell
$threadBaseline = Join-Path $runStateDirectory "thread-resolution.json"
$threadSnapshot = Join-Path $runStateDirectory "unresolved-threads.json"
pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname -All |
  Set-Content -Encoding utf8 $threadBaseline

pwsh <skill-directory>/scripts/get-unresolved-pr-threads.ps1 -PrNumber $prNumber -Repository $baseRepository -Hostname $githubHostname |
  Set-Content -Encoding utf8 $threadSnapshot
对于每个未解决的线程,按时间顺序读取所有分页评论并分类:
  • 等待评审者回复:最新相关评论是已提交评审中的Agent回复(
    pullRequestReview.state != PENDING
    submittedAt
    非空),且无人后续回复。无需操作。不要发布提醒、重复修复或重复回复。
  • 需要处理:评审者在Agent最新提交回复后提供了反馈,Agent从未回复,或其最新回复仅存在于待处理评审中。
  • 已取代/不可操作:后续对话明确撤回、回答或取代了该观点。仅当线程仍需Agent确认时才回复;避免重复现有Agent回复。
在需要处理的线程中,识别每个不同的反馈项。根据用户意图、对话历史、仓库规则、关联要求、PR范围、当前代码、约定和测试判断。线程是提交边界:将一个线程所需的所有工作归入该线程的单个提交,但绝不包含另一个线程的工作。
使用相同规则分类可操作的PR级评审正文和问题评论。每个独立反馈项都是自己的提交边界;绝不将其与评审线程或其他独立项合并。通过反馈ID和永久链接跟踪,因为它没有评审线程ID。
  • 当反馈识别出真实bug、遗漏的需求、破坏的不变量、缺失的测试、误导性行为或范围内的可维护性问题时,表示同意。
  • 当反馈与需求、既定意图、仓库不变量冲突,或会产生更差/超出范围的设计时,表示不同意。
  • 不确定时,如果证据支持,进行小范围的正确性修复。否则解释不确定性以及未做变更的原因。
不要跳过过时的未解决线程;确定其反馈是否仍适用于当前代码。

5. Fix and reply

5. 修复并回复

For each action-required review thread or standalone feedback item:
  1. Make the smallest complete fix for every actionable item in that thread, with focused tests.
  2. Run the narrowest meaningful verification.
  3. Inspect and stage only files for that item:
    powershell
    git status --short
    git diff
    git add <paths>
    git diff --cached
    Keep unrelated staged changes in other paths staged. Stop before editing any fix path that had a pre-existing staged, unstaged, or untracked change; never rely on partial staging followed by
    git commit --only
    for same-file isolation.
  4. If the disposition produces a change, create exactly one commit for the feedback unit before moving to the next unit:
    powershell
    git commit --only -m "fix(pr): address <thread summary>" -- <exact-thread-fix-paths>
    Do not amend, squash, or combine feedback commits. If an earlier unit's change completely satisfies a later agreed unit and no distinct file change remains, create an explicit traceability commit with
    --allow-empty
    for that later unit rather than merging their commit history. Do not create a commit for a justified disagreement.
  5. For review-thread feedback, reply directly to the thread after evaluating it and creating any relevant commit, subject to the Gitar deferral below:
    powershell
    $body = @"
    Agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    pwsh <skill-directory>/scripts/reply-to-review-thread.ps1 -ThreadId "<thread-id>" -Hostname $githubHostname -Body $body
    For standalone feedback, post a PR-level reply that links the exact feedback permalink:
    powershell
    $body = @"
    Regarding [this feedback](<feedback-permalink>): agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    gh pr comment $prNumber --repo $baseRepository --body $body
    Use the same PR-level path for a standalone justified disagreement, retaining the feedback permalink and the disagreement wording below.
    For a justified disagreement:
    text
    I don't think this change is correct for this PR.
    
    Reason: <specific reason grounded in requirements, conversation, or code>.
    
    No code change made.
    If any Gitar-authored feedback disposition created a commit that has not been pushed yet, defer its thread or PR-level reply until immediately after the batch push. Gitar cannot verify a local-only SHA; replying before it can see the commit may cause a misleading follow-up. Prefix a PR-level Gitar reply with
    Gitar,
    so the dashboard feedback is processed; never ask it to apply the fix. A Gitar disagreement has no commit dependency and may be replied to immediately. Keep all replies serial.
  6. Record the one-to-one feedback-unit ID → commit SHA mapping for changed dispositions, plus every disposition, verification, and returned comment ID. Use the thread ID for review threads and the feedback ID for standalone items. Record
    no commit — disagreement
    for justified disagreements.
The reply helper uses GitHub's single-comment reply endpoint so it never submits or modifies a shared pending review. It then verifies
state != PENDING
plus a non-null
submittedAt
. A helper failure is blocking; a returned comment URL alone is not proof of submission.
After all replies:
  1. Re-fetch all threads with
    -All
    , plus PR-level reviews and issue comments.
  2. Verify every reply created in this run belongs to a submitted review.
  3. Verify the authenticated user has no pending review on the PR, including reviews created before this run.
  4. For every thread ID present in the baseline, compare its
    isResolved
    value with the current value. Baseline resolution states must be unchanged; report external changes and never mutate them back. New thread IDs are expected during review convergence: classify them as additional feedback rather than treating their existence as a resolution mutation.
  5. If new action-required review threads or standalone feedback items appeared during the batch, action each in its own commit and repeat the audit. Push only once the currently visible feedback set has been fully actioned or is awaiting reviewer response. Gitar threads with a deferred local-commit reply count as actioned for this pre-push audit, but the reply remains mandatory immediately after push.
对于每个需要处理的评审线程或独立反馈项:
  1. 对该线程中的每个可操作项进行最小的完整修复,并添加针对性测试。
  2. 运行最窄范围的有意义验证。
  3. 检查并仅暂存该项目的文件:
    powershell
    git status --short
    git diff
    git add <paths>
    git diff --cached
    保留其他路径中无关的暂存变更。如果修复路径存在预先暂存、未暂存或未跟踪变更,则在编辑前停止;绝不依赖部分暂存后执行
    git commit --only
    来实现同一文件内的隔离。
  4. 如果处理结果产生变更,则为该反馈单元创建恰好一个提交,再处理下一个单元:
    powershell
    git commit --only -m "fix(pr): address <thread summary>" -- <exact-thread-fix-paths>
    不要修正、压缩或合并反馈提交。如果早期单元的变更完全满足后续同意的单元且无明显文件变更,则为后续单元创建一个带
    --allow-empty
    的显式可追溯提交,而非合并它们的提交历史。合理的异议无需创建提交。
  5. 对于评审线程反馈,在评估并创建任何相关提交后直接回复线程,遵循以下Gitar延迟规则:
    powershell
    $body = @"
    Agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    pwsh <skill-directory>/scripts/reply-to-review-thread.ps1 -ThreadId "<thread-id>" -Hostname $githubHostname -Body $body
    对于独立反馈,发布PR级回复并链接精确的反馈永久链接:
    powershell
    $body = @"
    Regarding [this feedback](<feedback-permalink>): agreed. I fixed this in commit <sha> by <specific change>.
    
    Verification: <command and result>.
    "@
    gh pr comment $prNumber --repo $baseRepository --body $body
    对于合理的异议,使用相同的PR级路径,保留反馈永久链接和以下异议措辞。
    合理异议的回复模板:
    text
    I don't think this change is correct for this PR.
    
    Reason: <specific reason grounded in requirements, conversation, or code>.
    
    No code change made.
    如果任何Gitar撰写的反馈处理结果创建了尚未推送的提交,则延迟其线程或PR级回复,直到批量推送完成后立即发布。Gitar无法验证本地SHA;在它能看到提交前回复可能导致误导性的后续操作。PR级Gitar回复需以
    Gitar,
    为前缀,以便仪表板反馈得到处理;绝不要求它应用修复。Gitar异议无提交依赖,可立即回复。所有回复需保持串行。
  6. 记录变更处理的反馈单元ID→提交SHA的一对一映射,以及每个处理结果、验证和返回的评论ID。评审线程使用线程ID,独立项使用反馈ID。合理异议记录为
    no commit — disagreement
回复工具使用GitHub的单条评论回复端点,因此绝不会提交或修改共享的待处理评审。然后验证
state != PENDING
submittedAt
非空。工具调用失败是阻塞性的;仅返回评论URL不足以证明提交成功。
所有回复完成后:
  1. 使用
    -All
    重新获取所有线程,以及PR级评审和问题评论。
  2. 验证本次运行创建的所有回复均属于已提交评审。
  3. 验证已认证用户在PR上无待处理评审,包括本次运行前创建的评审。
  4. 对于基线中存在的每个线程ID,比较其
    isResolved
    值与当前值。基线解决状态必须保持不变;报告外部变更,绝不将其改回。评审收敛期间出现新线程ID是预期的:将其归类为额外反馈,而非将其存在视为解决状态变更。
  5. 如果批量处理期间出现新的需要处理的评审线程或独立反馈项,则为每个项创建独立提交并重复审核。仅当当前可见反馈集已完全处理或正在等待评审者回复时才推送。带有延迟本地提交回复的Gitar线程在预推送审核中视为已处理,但回复仍需在推送后立即发布。

6. Push and converge with Gitar

6. 推送并与Gitar收敛

  1. Confirm the worktree contains no uncommitted changes created by this run. Do not push individual thread commits as they are created; batch-push all unsquashed thread commits only after the feedback audit is clear for the time being.
  2. Review commits after the starting SHA and every validated commit that was already local-ahead at invocation, then fetch the exact PR head before pushing:
    powershell
    git log --oneline <starting-sha>..HEAD
    git fetch $headPushUrl $pr.headRefName
    $remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
    $localHeadSha = (git rev-parse HEAD).Trim()
    $currentPrHeadSha = (gh pr view $prNumber --repo $baseRepository --json headRefOid --jq .headRefOid).Trim()
    $pushRequired = $localHeadSha -ne $remoteHeadSha
    git status --short --branch
    Stop if
    $remoteHeadSha
    and
    $currentPrHeadSha
    differ, or if either differs from
    $lastObservedPrHeadSha
    . Never overwrite
    $lastObservedPrHeadSha
    with an unexpected remote value. Use
    $pushRequired
    , not the starting-SHA commit range, to decide whether the PR head needs a push; the range is reporting context only.
  3. If
    $pushRequired
    , increment
    $reviewRound
    and capture a review baseline immediately before pushing:
    powershell
    $reviewRound++
    $reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -CaptureBaseline `
      -StatePath $reviewState `
      -PrNumber $prNumber `
      -Repository $baseRepository `
      -Hostname $githubHostname
  4. Push without force and record the exact HEAD:
    powershell
    $reviewRequestedAt = [DateTimeOffset]::UtcNow
    git push $headPushUrl "HEAD:refs/heads/$($pr.headRefName)"
    $expectedHeadSha = git rev-parse HEAD
    $lastObservedPrHeadSha = $expectedHeadSha
    Immediately after the push, post each deferred Gitar thread or PR-level reply serially with its now-visible commit SHA and verification result. Verify thread replies are submitted, then refresh feedback once before waiting for Gitar.
  5. After pushing, allow approximately 60 seconds for the exact-HEAD
    Gitar
    check to appear:
    powershell
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -Wait `
      -StatePath $reviewState `
      -ExpectedHeadSha $expectedHeadSha `
      -ReviewRequestedAt $reviewRequestedAt `
      -ReviewStartGraceSeconds 60 `
      -TimeoutMinutes 25 `
      -PollSeconds 10
    If this returns
    review_not_started
    , and only then, request review once for that pushed HEAD:
    powershell
    gh pr comment $prNumber --repo $baseRepository --body "gitar review"
    Do not post the fallback comment when an exact-HEAD Gitar check appeared during the grace period, even if it is still queued or processing.
  6. If the grace-period watcher returned
    review_not_started
    , resume the bundled watcher against the same baseline:
    powershell
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
       -Wait `
       -StatePath $reviewState `
       -ExpectedHeadSha $expectedHeadSha `
       -ReviewRequestedAt $reviewRequestedAt `
       -TimeoutMinutes 25 `
      -PollSeconds 20
    Run it as a long-lived tool call. While it runs, use only the environment's wait mechanism and remain silent unless the user interrupts. The watcher keeps repeated polling out of model context.
  7. Handle its terminal result:
    • feedback
      : fetch all feedback for context, but action only IDs in
      newFeedback
      . This may include inline threads, PR-level feedback from any reviewer, or Gitar's dashboard when its verdict is
      Approved with Suggestions
      ,
      Changes Requested
      ,
      Blocked
      , or
      Needs Review
      . If a new comment extends an old unresolved thread, read the full thread and handle only feedback after the last agent response.
    • approved
      : the exact-HEAD Gitar check completed successfully and the fresh dashboard verdict is
      Approved
      . Re-fetch checks, dashboard, PR-level feedback, and threads once; finish only if the full definition of done still holds.
    • gitar_failed
      : inspect the Gitar check and dashboard details. Treat provider/integration failure as a blocker unless repository evidence gives a scoped fix; never describe the PR as reviewed successfully.
    • review_not_started
      : post the single fallback
      gitar review
      comment, then resume step 6.
    • timeout
      : report that Gitar did not reach a terminal state; do not claim readiness.
    • head_changed
      : fetch and inspect the new state. Stop when another actor's push makes continued mutation unsafe.
    • pr_closed
      : stop and report the PR state.
  8. For new feedback, repeat fix → verify → commit → serial reply → audit → baseline → push → automatic-review grace period → wait.
If no push is needed, never post
gitar review
: the fallback is only permitted after this run pushes a new HEAD. Capture the current state and wait read-only. A completed successful
Gitar
check on the exact current HEAD plus an
Approved
dashboard verdict is sufficient; no Pro approval signal is required. Otherwise wait for an already-running automatic review and stop on timeout without posting a trigger.
powershell
$expectedHeadSha = (git rev-parse HEAD).Trim()
$reviewRound++
$reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -CaptureBaseline `
  -StatePath $reviewState `
  -PrNumber $prNumber `
  -Repository $baseRepository `
  -Hostname $githubHostname
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -Wait `
  -StatePath $reviewState `
  -ExpectedHeadSha $expectedHeadSha `
  -ReviewRequestedAt ([DateTimeOffset]::MinValue) `
  -TimeoutMinutes 25 `
  -PollSeconds 20
The watcher verifies that Gitar's check belongs to the exact expected SHA. After a push, it also requires the dashboard comment to have changed after the baseline and in the same processing window before accepting its verdict, because Gitar edits one persistent dashboard comment in place. Never use the fallback comment without a preceding push from this run.
Bound convergence to five pushed review rounds or two hours overall. Stop earlier for a clean Gitar result, timeout, closure, unexpected head movement, or a genuine blocker.
  1. 确认工作区不包含本次运行创建的未提交变更。不要在创建时推送单个线程提交;仅在反馈审核暂时通过后,批量推送所有未压缩的线程提交。
  2. 查看起始SHA之后的提交以及调用时已本地超前的所有已验证提交,然后在推送前获取精确的PR头:
    powershell
    git log --oneline <starting-sha>..HEAD
    git fetch $headPushUrl $pr.headRefName
    $remoteHeadSha = (git rev-parse FETCH_HEAD).Trim()
    $localHeadSha = (git rev-parse HEAD).Trim()
    $currentPrHeadSha = (gh pr view $prNumber --repo $baseRepository --json headRefOid --jq .headRefOid).Trim()
    $pushRequired = $localHeadSha -ne $remoteHeadSha
    git status --short --branch
    如果
    $remoteHeadSha
    $currentPrHeadSha
    不同,或其中任何一个与
    $lastObservedPrHeadSha
    不同,则停止操作。绝不使用意外的远程值覆盖
    $lastObservedPrHeadSha
    。使用
    $pushRequired
    而非起始SHA提交范围来决定是否需要推送PR头;范围仅用于报告上下文。
  3. 如果
    $pushRequired
    ,递增
    $reviewRound
    并在推送前立即捕获评审基线:
    powershell
    $reviewRound++
    $reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -CaptureBaseline `
      -StatePath $reviewState `
      -PrNumber $prNumber `
      -Repository $baseRepository `
      -Hostname $githubHostname
  4. 无强制推送并记录精确HEAD:
    powershell
    $reviewRequestedAt = [DateTimeOffset]::UtcNow
    git push $headPushUrl "HEAD:refs/heads/$($pr.headRefName)"
    $expectedHeadSha = git rev-parse HEAD
    $lastObservedPrHeadSha = $expectedHeadSha
    推送后立即串行发布每个延迟的Gitar线程或PR级回复,附带现在可见的提交SHA和验证结果。验证线程回复已提交,然后在等待Gitar前刷新一次反馈。
  5. 推送后,等待约60秒让精确HEAD的
    Gitar
    检查出现:
    powershell
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
      -Wait `
      -StatePath $reviewState `
      -ExpectedHeadSha $expectedHeadSha `
      -ReviewRequestedAt $reviewRequestedAt `
      -ReviewStartGraceSeconds 60 `
      -TimeoutMinutes 25 `
      -PollSeconds 10
    仅当返回
    review_not_started
    时,才为该推送的HEAD请求一次评审:
    powershell
    gh pr comment $prNumber --repo $baseRepository --body "gitar review"
    如果宽限期内出现精确HEAD的Gitar检查(即使仍在排队或处理中),也不要发布回退评论。
  6. 如果宽限期监视器返回
    review_not_started
    ,针对同一基线恢复捆绑监视器:
    powershell
    pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
       -Wait `
       -StatePath $reviewState `
       -ExpectedHeadSha $expectedHeadSha `
       -ReviewRequestedAt $reviewRequestedAt `
       -TimeoutMinutes 25 `
      -PollSeconds 20
    将其作为长期工具调用运行。运行期间,仅使用环境的等待机制,保持静默,除非用户中断。监视器将重复轮询排除在模型上下文之外。
  7. 处理其终端结果:
    • feedback
      :获取所有反馈上下文,但仅处理
      newFeedback
      中的ID。这可能包括内联线程、任何评审者的PR级反馈,或当verdict为
      Approved with Suggestions
      Changes Requested
      Blocked
      Needs Review
      时的Gitar仪表板。如果新评论扩展了旧的未解决线程,读取完整线程并仅处理最后一次Agent回复后的反馈。
    • approved
      :精确HEAD的Gitar检查已成功完成,且最新仪表板verdict为
      Approved
      。重新获取检查、仪表板、PR级反馈和线程;仅当完成定义的所有条件仍满足时才结束。
    • gitar_failed
      :检查Gitar检查和仪表板详情。除非仓库证据提供了范围明确的修复,否则将提供商/集成故障视为阻塞;绝不描述PR已成功评审。
    • review_not_started
      :发布单个回退
      gitar review
      评论,然后回到步骤6。
    • timeout
      :报告Gitar未达到终端状态;不要声称已就绪。
    • head_changed
      :获取并检查新状态。当其他参与者的推送使继续变异不安全时停止。
    • pr_closed
      :停止并报告PR状态。
  8. 对于新反馈,重复修复→验证→提交→串行回复→审核→基线→推送→自动评审宽限期→等待的流程。
如果无需推送,绝不发布
gitar review
:只有在本次运行推送新HEAD后才允许使用回退。捕获当前状态并只读等待。精确当前HEAD上已完成的成功
Gitar
检查加上
Approved
仪表板verdict即足够;无需Pro批准信号。否则等待已在运行的自动评审,超时后停止,不发布触发信号。
powershell
$expectedHeadSha = (git rev-parse HEAD).Trim()
$reviewRound++
$reviewState = Join-Path $runStateDirectory ("review-round-{0}.json" -f $reviewRound)
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -CaptureBaseline `
  -StatePath $reviewState `
  -PrNumber $prNumber `
  -Repository $baseRepository `
  -Hostname $githubHostname
pwsh <skill-directory>/scripts/wait-for-pr-review.ps1 `
  -Wait `
  -StatePath $reviewState `
  -ExpectedHeadSha $expectedHeadSha `
  -ReviewRequestedAt ([DateTimeOffset]::MinValue) `
  -TimeoutMinutes 25 `
  -PollSeconds 20
监视器验证Gitar的检查属于精确的预期SHA。推送后,它还要求仪表板评论在基线之后且同一处理窗口内发生变化,才接受其verdict,因为Gitar会就地编辑一个持久的仪表板评论。绝不在本次运行未推送的情况下使用回退评论。
将收敛限制为5次推送评审轮次或总计2小时。如果获得干净的Gitar结果、超时、关闭、意外HEAD变动或真正的阻塞,提前停止。

Final audit and response

最终审核与回复

Re-fetch rather than relying on cached state:
  • PR head, mergeability, and base;
  • latest base commit and a fresh local
    git merge-tree --write-tree --messages HEAD <base-commit>
    conflict probe;
  • all checks;
  • required checks queried separately with
    gh pr checks --required
    ;
  • the exact-HEAD Gitar check and Gitar dashboard Code Review verdict;
  • PR-level reviews/comments;
  • all review threads and reply submission states;
  • local/remote branch state and worktree.
Report concisely:
  • PR number and URL;
  • conflict and CI outcome, with commits;
  • thread counts: actioned, awaiting reviewer, and disagreed;
  • fixes, focused verification, and commit SHAs;
  • push result and Gitar review rounds;
  • terminal Gitar Core status for current HEAD: successful completed check plus
    Approved
    dashboard verdict;
  • pending review replies:
    0
    ;
  • review-thread resolution mutations:
    0
    , with baseline audit result;
  • any blocker or required check still pending.
重新获取状态而非依赖缓存:
  • PR头、可合并性和基础;
  • 最新基础提交和新的本地
    git merge-tree --write-tree --messages HEAD <base-commit>
    冲突探查;
  • 所有检查;
  • 使用
    gh pr checks --required
    单独查询的必填检查;
  • 精确HEAD的Gitar检查和Gitar仪表板代码评审verdict;
  • PR级评审/评论;
  • 所有评审线程和回复提交状态;
  • 本地/远程分支状态和工作区。
简洁报告:
  • PR编号和URL;
  • 冲突和CI结果,附带提交;
  • 线程数量:已处理、等待评审者回复和异议;
  • 修复、针对性验证和提交SHA;
  • 推送结果和Gitar评审轮次;
  • 当前HEAD的终端Gitar Core状态:成功完成检查加上
    Approved
    仪表板verdict;
  • 待处理评审回复:
    0
  • 评审线程解决状态变更:
    0
    ,附带基线审核结果;
  • 任何阻塞或仍待处理的必填检查。