关于 codeant-resolve-pr-comments
Resolve CodeAnt PR Comments 是用于查找和处理 PR 中未解决 CodeAnt 行内建议的 Agent 技能。它通过已配置的源代码管理服务工作,编辑前需获批,验证修复后才解决讨论串,并避免发送 CodeAnt 遥测数据。
主要功能
- 01支持 GitHub、GitLab、Bitbucket 和 Azure DevOps
- 02获取并筛选未解决的行内建议
- 03验证并分类问题
- 04编辑前征求批准
- 05验证修复后解决讨论串
适用场景
- 01查找 PR 中未解决的 CodeAnt 建议
- 02先审阅问题,再执行获批的修改
- 03验证修复并解决对应讨论串
- 04通过已配置的服务访问处理 PR 评论
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ codeant-ai/ skills --skill codeant-resolve-pr-comments安装后在 Claude Code 中输入/codeant-resolve-pr-comments确认已加载。
详细介绍
解决 CodeAnt PR 评论
使用源代码管理提供商作为 PR 元数据、审查评论和线程状态的唯一可信来源。绝不安装、更新、调用或回退到 codeant-cli。绝不发送 CodeAnt 遥测数据。
工作流
- 运行预检。
- 仅选择一个提供商适配器,并获取所有结果页。
- 仅保留未解决的 CodeAnt 行内线程。
- 验证并分类每条发现。
- 提出计划,并在编辑前获得批准。
- 应用已批准的修复并运行相关验证。
- 仅解决已应用修复并通过验证的线程。
- 报告结果,并提出提交和推送。
- 完成所有 PR 工作后,执行一次请求的技能更新检查。
1. 预检
检查仓库,不作任何修改:
git status --short
git branch --show-current
git remote -v
保留所有现有更改。根据远程主机检测提供商:
github.com或 GitHub Enterprise:GitHub。gitlab.com或自托管 GitLab:GitLab。bitbucket.org:Bitbucket Cloud。- 其他 Bitbucket Server/Data Center 主机:Bitbucket Data Center。
dev.azure.com、ssh.dev.azure.com或*.visualstudio.com:Azure DevOps。
如果无法明确判断,请询问 PR 托管在哪个提供商上。如果用户提供了 PR/MR URL 或编号,请使用它。否则,查找源分支与当前分支完全一致的开放 PR。如果当前位于默认分支,则必须提供 PR 编号或 URL。如果不存在匹配项,或存在多个完全匹配项,请停止并请用户指定 PR。
使用已配置的提供商身份验证。预检期间不要探测多种身份验证方法;遵循所选提供商适配器的身份验证优先级。不要安装 CLI、泄露令牌、打印包含凭据的请求头,或在生成的文件中放入机密。如果缺少身份验证,请说明所需的提供商登录方式或令牌,并停止。
筛选 CodeAnt 建议
获取 PR 审查评论后,仅保留由 CodeAnt 生成且尚未解决的行内建议。符合以下任一条件时,将行内评论视为由 CodeAnt 生成:
- 作者登录名、用户名、昵称或显示名称(不区分大小写)与
codeant-ai、codeant-ai[bot]、codeant-bot或CodeAnt AI完全一致。 - 评论正文包含以
https://app.codeant.ai/fix-in-ide或https://app.codeant.ai/feedback开头的 CodeAnt 操作 URL。
使用正文特征,因为 GitLab 和 Azure DevOps 可能会将 CodeAnt 评论归属到已连接的人类账号。正文特征匹配时,不要要求评论作者是机器人,也不要单独进行身份发现或确认步骤。仅凭 CodeAnt 一词不要将评论归类为 CodeAnt 评论;必须匹配确切的服务账号名称或 CodeAnt 操作 URL。
跳过常规 PR 评论、摘要、质量门报告、系统消息、已删除的评论、草稿,以及并非行内发现起始内容的回复。如果没有符合条件的建议,请报告该 PR 没有未解决的 CodeAnt 行内建议,然后停止。否则直接继续验证。
2. 提供商适配器
仅选择匹配的适配器。将每个可执行项规范化为:
thread_id, comment_id, author_id, body, path, line, url,
resolved, outdated_or_stale, provider
保留提供商原生 ID 的原样,因为解决评论时需要这些 ID。
GitHub
要求已通过身份验证的 gh。确定 PR 和仓库:
gh auth status
gh pr view <number-or-url> --json number,title,url,state,headRefName,baseRefName
gh repo view --json nameWithOwner --jq .nameWithOwner
如果没有提供 PR 编号,请在当前分支上尝试运行 gh pr view。必要时,列出完全匹配的分支:
gh pr list --head "<branch>" --state open \
--json number,title,url,state,headRefName,baseRefName
使用 GitHub GraphQL 获取并分页审查线程。使用 --paginate --slurp;分页变量必须命名为 $endCursor:
gh api graphql --paginate --slurp \
-f owner='<owner>' \
-f name='<repository>' \
-F number=<pr-number> \
-f query='query($owner: String!, $name: String!, $number: Int!, $endCursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
number title url
reviewThreads(first: 100, after: $endCursor) {
nodes {
id isResolved isOutdated
comments(first: 100) {
nodes {
databaseId
author { login }
body path line originalLine createdAt url
}
}
}
pageInfo { hasNextPage endCursor }
}
}
}
}'
对于暂时性 HTTP 429、502、503 或 504 响应,最多重试此只读获取操作三次;如果存在 Retry-After,则遵循其指示。不要对身份验证、授权、架构或验证错误进行重试。
在所有返回的页面中,仅保留符合以下条件的线程:
isResolved为false。- 根评论符合 CodeAnt 作者或正文筛选规则。
- 根评论的
path非空;使用line,仅在定位历史上下文时回退到originalLine。
在过期验证中保留 isOutdated。成功修复线程后,使用其 GraphQL 线程节点 ID(而非数字评论 ID)解决线程:
gh api graphql \
-f threadId='<thread-node-id>' \
-f query='mutation($threadId: ID!) {
resolveReviewThread(input: {threadId: $threadId}) {
thread { id isResolved }
}
}'
要求响应确认 isResolved: true。
GitLab
要求已通过身份验证的 glab。GitLab 合并请求 IID 是项目级别的;不要将其与全局数据库 ID 混淆。
glab auth status
glab mr view <iid-or-url> --output json
glab repo view --output json
如果没有提供 IID,请查找 source_branch 与当前分支完全匹配的唯一一个开放 MR:
glab mr list --source-branch "<branch>" --state opened --output json
使用 glab repo view 返回的数字项目 ID,避免路径编码错误。获取所有讨论页面:
glab api --paginate \
"projects/<project-id>/merge_requests/<mr-iid>/discussions?per_page=100"
仅保留符合以下条件的讨论:
individual_note为false。- 根备注符合 CodeAnt 作者或正文筛选规则。GitLab 可能会将关联的人类用户显示为作者,因此应接受正文中包含匹配的 CodeAnt 操作 URL 的备注。
- CodeAnt 根备注的
resolvable: true且resolved: false。 - 备注具有包含
new_path或old_path的差异position;优先使用new_line,否则使用old_line作为上下文。
将讨论的 id 作为 thread_id,将根备注的 id 作为 comment_id。成功修复讨论后,解决该讨论:
glab api --method PUT \
"projects/<project-id>/merge_requests/<mr-iid>/discussions/<discussion-id>" \
-f resolved=true
要求返回的讨论显示相关的可解决备注已解决。
Bitbucket Cloud
使用 Bitbucket Cloud REST API 2.0,并通过现有 OAuth、访问令牌或 API 令牌进行身份验证。从远程地址或 PR URL 中解析 <workspace>/<repo-slug>。绝不要输出凭据。
如果没有提供 PR 编号,请列出开放的 PR,并选择 source.branch.name 完全匹配的唯一一个 PR。对查询值进行 URL 编码:
GET https://api.bitbucket.org/2.0/repositories/<workspace>/<repo-slug>/pullrequests
?state=OPEN&pagelen=100
获取所有评论页面,并持续跟进响应中的 next URL,直到其不存在:
GET https://api.bitbucket.org/2.0/repositories/<workspace>/<repo-slug>/pullrequests/<pr-id>/comments
?pagelen=100
仅保留符合以下条件的评论:
deleted不为true,且pending不为true。- 是根评论,而非回复。
- 存在
inline.path;新文件行使用inline.to,旧文件行使用inline.from。 resolution为 null 或不存在。- 使用
user.nickname、user.display_name或content.raw,并按照 CodeAnt 作者或正文筛选规则匹配评论。
保留根评论的 id。成功修复线程后,解决该线程:
POST https://api.bitbucket.org/2.0/repositories/<workspace>/<repo-slug>/pullrequests/<pr-id>/comments/<comment-id>/resolve
Accept: application/json
要求 HTTP 200 响应,并且返回解决对象。绝不要以删除评论来代替解决评论。
Bitbucket Data Center
使用主机的 /rest/api/latest API,并通过现有的 bearer、个人访问令牌或会话进行身份验证。从远程 URL 或 PR URL 中解析 <base-url>、<project-key> 和 <repo-slug>。
如果未提供 PR ID,则对处于打开状态的 PR 进行分页,并选择其中唯一一个 fromRef.displayId 与当前分支完全匹配的项:
GET <base-url>/rest/api/latest/projects/<project-key>/repos/<repo-slug>/pull-requests
?state=OPEN&limit=100&start=<offset>
持续读取 nextPageStart,直到 isLastPage 为 true。以相同方式获取所有评论页:
GET <base-url>/rest/api/latest/projects/<project-key>/repos/<repo-slug>/pull-requests/<pr-id>/comments
?limit=100&start=<offset>
保留符合 CodeAnt 作者或正文筛选规则的根评论(使用 author.name、author.slug、author.displayName 或 text),并且其 anchor.path 必须存在、pending 不得为 true、state 必须为 OPEN,且 threadResolved 必须为 false。使用 anchor.line 和完整的锚定路径。
要解决已成功修复的评论线程,先重新获取评论以取得其当前 version,然后使用乐观并发控制更新:
PUT <base-url>/rest/api/latest/projects/<project-key>/repos/<repo-slug>/pull-requests/<pr-id>/comments/<comment-id>
Content-Type: application/json
{
"id": <comment-id>,
"version": <current-version>,
"text": <unchanged-current-text>,
"state": "OPEN",
"severity": <unchanged-current-severity>,
"threadResolved": true
}
保留当前文本、状态、严重性和必需属性。如果收到 HTTP 409,仅当该评论线程仍是同一个未解决的评论时,才重新获取并重试。要求响应显示 threadResolved: true。
Azure DevOps (ADO)
使用 Azure DevOps REST API 7.1。从远程 URL 或 PR URL 中解析组织、项目和仓库。优先使用不可变的仓库 ID 和身份 ID。
首次请求前,按以下优先级进行身份验证:
- 检查
AZURE_DEVOPS_PAT是否非空,且不得打印或以其他方式泄露其值。 - 如果存在,则在本地对其进行规范化后再进行身份验证:
- 默认将原始值视为 PAT。
- 仅当其符合标准 Base64 规范语法(允许省略结尾填充)、严格解码成功,且解码后重新编码的值在填充规范化后与原值相同时,才将其视为 Base64 编码。
- 仅当解码后的值是可识别的 Azure DevOps PAT 时才使用该值:可以是旧版 52 字符格式,或在文档规定位置带有固定
AZDO签名的当前 84 字符格式。如果解码后是<username>:<PAT>格式的 HTTP Basic 负载,且第一个冒号后的部分符合其中一种 PAT 格式,也应接受;仅将 PAT 部分用作密码。 - 否则,保留原始值不变。不得通过试探性 API 请求来判断该值是否经过编码。 立即将所得 PAT 用作 HTTP Basic 身份验证的密码。跳过 Azure CLI、Azure DevOps CLI、凭据管理器及其他身份验证发现。仅在内存中解码和构造授权值;绝不打印 PAT 或包含凭据的请求头,也不得将其写入文件。
- 如果经过 PAT 身份验证的请求返回 HTTP 401 或 403,应报告 PAT 无效、已过期、无权访问或权限范围不足,然后停止。不得静默回退到其他身份,因为这可能掩盖 PAT 配置错误,并以非预期用户身份访问资源。
- 仅当
AZURE_DEVOPS_PAT不存在时,才使用已配置的 OAuth 或 Microsoft Entra 令牌。不得启动交互式登录。如果没有现成的非交互式凭据,请指出缺少身份验证凭据并停止。
如果未提供 PR ID,请对完整源引用进行 URL 编码,并选择唯一一个完全匹配且处于活动状态的项:
GET https://dev.azure.com/<organization>/<project>/_apis/git/repositories/<repository-id>/pullrequests
?searchCriteria.status=active
&searchCriteria.sourceRefName=refs/heads/<branch>
&$top=100
&api-version=7.1
获取 PR 线程:
GET https://dev.azure.com/<organization>/<project>/_apis/git/repositories/<repository-id>/pullRequests/<pr-id>/threads
?api-version=7.1
仅在满足以下条件时保留线程:
status为active或pending。threadContext.filePath存在;使用rightFileStart.line,否则使用leftFileStart.line。- 根评论不是系统评论或已删除评论,且其
commentType为text。 - 根评论符合 CodeAnt 作者或正文筛选规则,使用
author.uniqueName、author.displayName或content。Azure DevOps 可能会将关联的人类用户显示为作者。
保留数字类型的线程 id 和根评论 id。要标记已成功修复的线程,请将其标记为已修复:
PATCH https://dev.azure.com/<organization>/<project>/_apis/git/repositories/<repository-id>/pullRequests/<pr-id>/threads/<thread-id>
Content-Type: application/json
{"status":"fixed"}
使用 api-version=7.1,并要求返回的线程显示 status: fixed。对于已应用的修复,不得使用 closed、wontFix 或 byDesign。
3. 验证每项发现
按文件对发现进行分组。对每项发现:
- 阅读完整评论,以及被引用行上下至少 30 行内容。
- 检查相关定义、调用方、测试和仓库指南,以理解所述行为。
- 确认缺陷、预期行为、复现路径以及任何围栏代码建议。
- 如果提供方将位置标记为已过时、文件已不存在,或当前代码已不再符合所述问题,则标记为
STALE,除非该缺陷在被引用代码中仍明确存在。 - 将 Architect Review 和 Logical Review 评论视为可处理项。阅读完整的
Prompt for AI Agent部分;如果未提供建议,则起草一个局部修复方案。 - 验证语法、范围、导入、类型、错误处理、公共接口、边缘情况、并发性,以及与调用方的兼容性。
- 优先采用最小且正确的修复。不要为了代码风格重构相邻代码。
必须且只能指定以下一种判定:
ACCEPT:缺陷确实存在,且局部修复安全,不会改变公共契约或削弱处理能力。LIKELY ACCEPT:修复方案合理,但行为变更可能影响调用方,或需要有针对性的验证。DO NOT ACCEPT:提议不安全、缺乏依据、依赖不可用的 API,或需要超出可安全提供的局部补丁范围的设计工作。STALE:被引用的代码或缺陷已不存在。
不要仅因 Architect Review 或 Logical Review 未提供现成补丁就拒绝其评论。
4. 编辑前先提交计划
报告提供方、PR 编号、标题、链接以及未解决的 CodeAnt 行内线程数。按判定对所有发现进行分组。每项都包含:
- 文件和行号。
- 一句话概述问题。
- 验证依据。
- 适用时,说明计划中的修改前后变化。
- 对于
LIKELY ACCEPT,列出需要验证的确切调用方、测试或行为。
说明 ACCEPT 修复已就绪,并询问是否纳入点名的 LIKELY ACCEPT 修复。未经批准不得编辑。绝不应用 DO NOT ACCEPT 或 STALE 发现的修复。
5. 应用并验证
获得批准后:
- 重新检查
git status --short,并保留已有的编辑。 - 仅对评论中提及的文件应用已确认的修复,但狭义必需的测试或导入除外。
- 检查差异,确认没有意外更改或修复之间的相互影响。
- 运行范围最窄且相关的格式化工具、静态检查和测试;如果共享行为发生变化,则扩大验证范围。
- 仅修复由这些编辑导致的失败。如果某项修复无法验证,且可安全单独撤销,则仅撤销该修复,将其线程留待处理,并报告情况。
6. 解决线程并报告
解决线程属于外部变更。只有在用户批准对应修复且本地验证通过后,才能逐个解决线程。即使个别解决操作失败,也要继续处理其他线程。
绝不解决 DO NOT ACCEPT、STALE、跳过、部分修复或未经验证的发现。如果提供方响应含糊,则在线程解决后重新获取线程状态。
最终报告:
- 已应用并验证的修复,包括文件、行号、判定和测试结果。
- 未应用的发现,包括判定和原因。
- 已解决的提供方线程 ID,以及任何解决失败。
- 最终的
git status --short,以及此工作流更改的文件。
询问是否需要提交并推送选定文件。未经明确批准,不得提交或推送。
7. 检查技能更新
仅在所有 PR 工作完成且最终报告已准备好之后、发送报告之前,尽力执行此检查。此检查绝不能延迟、更改或使 PR 工作流失效。
解析当前已加载的 codeant-resolve-pr-comments/SKILL.md 的路径,不要扫描无关目录。如果无法确定其路径或文件不可写,则静默跳过此检查。否则,仅发送一次未经身份验证的 GitHub API 请求,并将原始响应保存到临时文件:
curl --fail --silent --show-error \
--connect-timeout 2 --max-time 5 \
-H 'Accept: application/vnd.github.raw+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
'https://api.github.com/repos/CodeAnt-AI/skills/contents/skills/codeant-resolve-pr-comments/SKILL.md?ref=main' \
-o '<temporary-file>'
不要发送第二次请求,不要通过 releases、commits、tags 或包管理器继续查找,也不要重试失败的请求。使用响应前,必须确认 HTTP 请求成功,并验证它是合理的技能文件:文件必须以 YAML frontmatter 开头,声明的名称必须恰好为 name: codeant-resolve-pr-comments,包含 # Resolve CodeAnt PR Comments,并且恰好包含一个 `` 标记。
在本地比较远程标记与当前文件的标记。如果远程版本等于或低于当前版本,删除临时文件,并且仅在最终报告中添加 Skill update: already current。如果远程版本较高,则以原子方式仅替换当前技能文件,保留其现有权限,删除临时文件,并在最终报告中添加 Skill update: updated; the new instructions apply next session。绝不要覆盖较新的本地版本。如果验证、比较或替换失败,则尽可能删除临时文件,并添加一条简洁、不会阻塞流程的说明;不要重试。
防护规则
- 在声称列表完整之前,获取所有分页。
- 将提供方原生线程状态视为权威信息。
- 逐条验证建议;绝不要盲目批量应用。
- 保留无关的用户更改,避免修改无关文件。
- 指出相互冲突的评论,不要擅自选择。
- 绝不泄露访问令牌、PAT、Cookie 或详细的身份验证输出。
- 任何步骤都不得安装、调用或依赖
codeant-cli。