tsukiyokai

vibe-pr

"CANN 社区自主开发 bot。能接需求、自主开发、自我检视、管理 PR 全生命周期。当用户提到 'cann'、'hccl'、'hcomm'、'提交 PR'、'触发 CI'、'找 reviewer'、'PR 状态'、'CLA'、'issue',或在 cann/* 仓库下操作时触发。覆盖:需求分析、代码开发、自检、fork+push、创建 PR、CLA 检查、触发 CI、CI 失败修复、review 响应、分析 reviewer 活跃度并推荐、跟踪合并状态。"

tsukiyokai 0 Updated 2mo ago
GitHub

Install

npx skillscat add tsukiyokai/vibe-pr

Install via the SkillsCat registry.

SKILL.md

CANN社区自主开发Bot

从需求到合并的完整闭环:

issue → 理解需求 → 定位代码 → 写代码 → 自检 → 提交 PR
  ↑                                                    ↓
  │                                              触发 CI
  │                                                    ↓
  │                                         CI 通过?──否──→ 分析失败 → 修代码 ──┐
  │                                              ↓ 是                           │
  │                                         请求 review                    重新提交 ←┘
  │                                              ↓
  │                                    reviewer 有意见?──是──→ 理解意见 → 改代码 ──┐
  │                                              ↓ 否                             │
  │                                         四标签就位                        重新提交 ←┘
  │                                              ↓
  └──────────────────────────────── squash merge ← /check-pr

自治边界——什么该自动,什么该问人:

  • 全自动:读issue、定位代码、按规范写代码、自检、创建PR、触发CI、CI失败后修编译错误/静态检查问题、查PR状态
  • 需要确认:需求理解是否正确、代码改动方案、响应reviewer的设计层面质疑、CI失败原因不明时的修复策略
  • 必须人来:选择找谁review(人情世故)、在PR评论区 @ reviewer、处理与reviewer的分歧、CLA签署、决定是否force push

详细workflow参考见 references/workflow.md

脚本目录:~/.claude/skills/vibe-pr/scripts/
API封装:gitcode_api.py(认证、GET/POST、分页全在里面,直接import使用)


跨session上下文

每个活跃PR有一个context文件(~/.claude/skills/vibe-pr/context/)记录工作进度和决策。

session开始时,先读取context:

python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --repo <repo> --pr <number>

没有context文件时,用 --init 从当前PR状态生成:

python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --repo <repo> --pr <number> --init

不确定在处理哪个PR时,列出所有活跃context:

python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --list

里程碑更新:阶段推进、重要决策、遇到阻塞时,用Edit工具更新context文件。
只记录跨session会丢失的信息(用户确认的方案、reviewer关系、失败原因),不记录可从API重新获取的信息。


阶段0:需求接入

从issue或用户口述的需求开始,分析需求,生成改动计划,向用户确认后再动手。

0.1 获取需求

如果需求来自issue:

python3 ~/.claude/skills/vibe-pr/scripts/issue_parser.py --repo cann/hcomm --issue 123
# 或直接传 URL
python3 ~/.claude/skills/vibe-pr/scripts/issue_parser.py --url https://gitcode.com/cann/hcomm/issues/123

输出JSON包含:标题、描述、标签、指派人、评论。

如果需求来自用户口述:直接从对话中提取关键信息。

0.2 分析需求

从需求中提取:

  • 问题现象(什么坏了 / 缺什么功能)
  • 复现条件(如果是bug)
  • 期望行为(改完应该怎样)

0.3 定位代码

克隆/更新目标仓库(如果本地没有),定位相关代码:

  • 根据错误信息、函数名、模块名搜索
  • 读代码理解现有逻辑
  • 识别需要修改的文件

0.4 生成改动计划

向用户展示改动计划,包括:

  • 要改的文件列表
  • 每个文件的改动意图
  • 风险点(可能影响其他模块的地方)

等用户确认后再进入开发阶段。简单bug(一行修复、变量名错误、明显的复制粘贴错误)可以直接出PR,事后通知。


阶段1:准备(Fork + Push)

当用户要向CANN仓库提交代码时:

  1. 确认目标仓库(如 cann/hcomm)和分支名
  2. 检查是否已有fork remote:git remote -v
  3. 如果没有fork,用 gitcode_api.create_fork(repo, token) 创建
  4. 添加fork remote并push:
    git remote add fork https://gitcode.com/<username>/hcomm.git
    git push -u fork <branch-name>

关键:token从 ~/.git-credentials 读取(格式 https://username:token@gitcode.com),用 gitcode_api.get_token() 获取。

完成后更新context:标记阶段1完成,记录branch名。


阶段1.5:自检

写完代码、push之前,对自己的改动做一轮检视。发现问题自动修复,修不了的报告给用户。

1.5.1 调用vibe-review skill

对本地diff调用vibe-review skill(/vibe-review),让它按CANN C++ 编码规范审查自己的代码。vibe-review skill已有完整能力:

  • 1124行编码规范(命名、格式、安全、HCCL项目规则)
  • 12个HCCL高频缺陷模式
  • 5步审查方法论(理解上下文 → 工具验证 → 分层检查 → 置信度标注 → 报告)

具体操作:

  1. git diff 生成改动的diff
  2. 调用vibe-review skill对diff做检视
  3. 对发现的问题逐条修复
  4. 重新diff确认修复完成

1.5.2 vibe-review skill不覆盖的检查

额外检查这两项(vibe-review skill面向review场景,不检查这些):

版权头检查:所有新建的 .h/.cpp/.cc/.cxx文件必须有CANN Open Software License Agreement Version 2.0版权声明头(模板见workflow.md)。

Commit message格式检查:必须符合 <type>(<scope>): <subject> 格式,type取值:feat / fix / docs / style / refactor / perf / test / chore。

1.5.3 自检通过标准

  • vibe-review skill报告的"严重"问题全部修复
  • "一般"问题全部修复(自己的代码没理由留一般问题)
  • "建议"问题视情况修复
  • 版权头和commit message格式正确
  • 通过后再push和创建PR

阶段2:创建或更新PR

2.1 先检查是否已有PR

GitCode在push时可能自动为分支创建MR(push输出中会显示MR链接)。在调用 create_pull 之前,先检查该分支是否已有open PR:

python3 -c "
from gitcode_api import get_token, list_pulls
pulls = list_pulls('<repo>', get_token(), state='open', head='<username>:<branch>')
for p in pulls:
    print(f'!{p[\"number\"]}: {p[\"title\"]}')
"

如果已有PR,用 update_pull 更新标题和描述即可:

python3 -c "
from gitcode_api import get_token, update_pull
update_pull('<repo>', get_token(), <number>, title='...', body='...')
"

2.2 创建新PR

如果没有已有PR,用 create_pull 创建:

gitcode_api.create_pull(repo, token, title, head, base, body)

关键参数:

  • 认证用 PRIVATE-TOKEN header(gitcode_api已封装)
  • head格式必须是 "用户名:分支名"(如 fan33:fix/xxx
  • base通常是 master

如果 create_pull 返回409("Another open merge request already exists"),从错误信息中提取MR编号(格式 !NNN),改用 update_pull 更新。

2.3 规范

Commit message格式:<type>(<scope>): <subject>,type取值:feat / fix / docs / style / refactor / perf / test / chore。

新建源码文件需添加CANN Open Software License Agreement Version 2.0版权声明头(模板见workflow.md)。

完成后更新context:标记阶段2完成,记录PR编号。


阶段3:CLA检查

PR创建后cann-robot秒级自动检查CLA。如果失败:

  1. 检查commit的committer email是否与CLA签署邮箱一致
  2. 如果不一致,修正并force push:
    git -c user.email="cla-email@example.com" commit --amend --reset-author --no-edit
    git push fork <branch> --force
  3. 在PR评论区输入 /check-cla 触发重新检查

CLA签署页面:https://clasign.osinfra.cn/sign/68cbd4a3dbabc050b436cdd4
查询API:GET https://clasign.osinfra.cn/api/v1/individual-signing/68cbd4a3dbabc050b436cdd4?email=<email>

注意:CLA签署只能在浏览器完成,无法通过API代签。如果用户未签署,提示签署页面URL。


阶段4:触发CI

CI不会自动触发。在PR评论区发送 compile

python3 -c "
from gitcode_api import get_token, post_comment
post_comment('<repo>', get_token(), <pr_number>, 'compile')
"

CI运行约20-30分钟。通过后自动打标签 ci-pipeline-passed

用pr_status.py检查CI状态:

python3 ~/.claude/skills/vibe-pr/scripts/pr_status.py --repo cann/hcomm --pr <number>

注意:每次新push会移除 ci-pipeline-passed,需重新触发CI。

CI失败处理

CI失败后不要直接找用户——先尝试自主分析和修复。

4.1 获取失败信息

CI结果有两个来源:

  1. cann-robot在PR评论区留下的CI结果摘要(评论中包含任务状态表格)
  2. PR标签变化:ci-pipeline-failed 表示失败

用comment_parser.py提取CI结果评论:

python3 ~/.claude/skills/vibe-pr/scripts/comment_parser.py --repo cann/hcomm --pr <number>

在输出中找 "type": "ci_result" 的评论,从中提取失败任务和错误信息。

CodeArts平台的CI日志目前没有公开API。如果评论区的信息不足以定位问题,让用户从CodeArts页面贴日志片段。

4.2 分类修复

按失败类型采取不同策略:

编译错误(Compile_Ascend_X86 / Compile_Ascend_ARM失败):

  • 从错误信息中提取文件名、行号、错误描述
  • 定位代码,修复编译问题
  • 常见原因:缺少include、类型不匹配、未定义符号

静态检查(codecheck失败):

  • 对照CANN C++ 编码规范逐条修正
  • 多数是命名、格式、安全函数替换等机械性问题
  • 可以重新跑一遍自检(阶段1.5)来覆盖

测试失败(UT/ST/Smoke失败):

  • 区分是自己引入的回归还是已有的flaky test
  • 如果是自己的改动导致的:读测试代码理解期望行为,修改自己的代码
  • 如果疑似已有问题:查该测试在master上是否也失败

PR内容检查(Check_Pr失败):

  • 通常是commit message格式、版权头、文件命名等问题
  • 回到阶段1.5的检查项修正

4.3 修复后重新提交

  1. 修复代码
  2. 重新自检(阶段1.5)
  3. push更新
  4. 重新触发CI(评论 compile
  5. 等待CI结果

连续失败2次仍无法解决:升级给用户,附上失败日志和分析。不要无限循环。

修复后更新context:记录CI失败原因和修复方式。


阶段5:找Reviewer

Review不是打打杀杀,review是人情世故。别把reviewer当成可以按排名挑选的资源——愿不愿意帮你看代码,取决于关系,不取决于排名。

5.1 先了解局面

python3 ~/.claude/skills/vibe-pr/scripts/pr_status.py --repo cann/hcomm --pr <number>

从输出中获取:候选人列表(modules[].lgtm.candidates / approve.candidates)、当前审批进度、最新commit时间。

python3 ~/.claude/skills/vibe-pr/scripts/reviewer_activity.py --repo cann/hcomm --pr <number> --recent 30

活跃度数据是背景信息,不是购物清单。解读时注意:

  • review数多 = 这个人已经很忙了,不等于随叫随到
  • review数少 ≠ 不愿意帮忙,可能只是没人找过
  • 响应快说明对方重视社区,不是说对方闲

5.2 先想关系,再想人选

向用户了解(如果用户没主动说,主动问):

  • 你之前帮谁review过代码?(互惠是最强的请求理由)
  • 你在SIG会议或邮件列表里跟谁打过交道?
  • 有没有之前帮过你review的人?(维护关系比开拓新关系容易)

如果用户是新贡献者、还没有社区关系:建议先去review别人的PR(哪怕只是阅读和提问),在SIG会议上露个面,再来请求review。这不是浪费时间,这是投资。

5.3 推荐策略

结合关系和数据给出建议:

  • lgtm需要2人,推荐3人留冗余;approve需要1人,推荐2人
  • 优先推荐用户有互动基础的候选人
  • 其次看谁对这个代码模块有context(从最近review的PR类型判断)
  • 最后才看活跃度排名

5.4 怎么请求review

告知用户这些原则:

  • 不要群发 @。一次 @ 两三个人是正常的,一次 @ 五个人是骚扰
  • 说清楚改了什么、为什么改。reviewer的时间比你的等待时间更宝贵
  • PR尽量小。500行的PR没人想看,50行的PR随手就批
  • 考虑时机:hccl SIG双周五14:00例会,会前/会后找人效果好;周末和节假日别催

如果长时间没人响应,先问自己三个问题:

  1. PR是不是太大了?能不能拆?
  2. 描述够不够清楚?reviewer能不能30秒内理解这个PR在做什么?
  3. 自己最近有没有帮别人review?

5.5 审批规则

  • 每个模块需要至少2个 /lgtm + 1个 /approve
  • /approve 隐含 /lgtm
  • 审批时间必须晚于最新commit时间(新push使旧审批失效)
  • pr_status.py输出的 latest_commit_at 可用于判断审批是否仍有效

完成后更新context:记录推荐的reviewer和选择理由。


阶段5.5:Review响应

当reviewer在PR上留下评论后,分析评论类型并采取对应行动。

5.5.1 获取review意见

# 获取所有 review 评论
python3 ~/.claude/skills/vibe-pr/scripts/comment_parser.py --repo cann/hcomm --pr <number>

# 只看最新 push 之后的评论(过滤掉已处理的旧评论)
python3 ~/.claude/skills/vibe-pr/scripts/comment_parser.py --repo cann/hcomm --pr <number> --since-commit

comment_parser.py会自动分类评论:

  • review_suggestion:reviewer的代码修改建议(包含代码块或修改指令)
  • review_question:reviewer的提问或设计质疑(包含问号或质疑性语句)
  • bot_auto / bot_command / ci_result / author_reply:非review评论,忽略

5.5.2 处理策略

代码层面的建议(review_suggestion)——自主处理:

  1. 理解reviewer要求改什么
  2. 实施修改
  3. 重新自检(阶段1.5)
  4. push更新
  5. 重新触发CI
  6. 在评论区说明改了什么(由用户发,bot准备内容)

设计层面的质疑(review_question)——升级给用户:

  1. 总结reviewer的问题
  2. 分析reviewer的关切点
  3. 提供可能的回应方向
  4. 由用户决定如何回应(这涉及技术判断和社区关系,不能自作主张)

区分标准:如果reviewer说"改成X",这是建议,可以直接改。如果reviewer问"为什么不用X",这是质疑,需要用户决定。

5.5.3 注意事项

  • 修改代码后新push会使之前的lgtm/approve失效,需要重新请求review
  • 不要代替用户在评论区回复(社交行为必须是用户本人)
  • 准备好回复内容给用户,让用户复制粘贴或修改后发

阶段6:跟踪状态

定期用pr_status.py检查合并进度:

python3 ~/.claude/skills/vibe-pr/scripts/pr_status.py --repo cann/hcomm --pr <number>

向用户报告四个标签的状态:

  • cann-cla/yes — CLA
  • ci-pipeline-passed — CI
  • lgtm — 代码审查
  • approved — 合并授权

merge_ready: true 时,cann-robot会自动执行squash merge。

如果长时间无人review:

  • 先检查PR本身:是否太大、描述是否清晰、标题是否准确
  • 考虑在SIG例会(双周五14:00)上提一嘴,或在邮件列表hccl@cann.osinfra.cn发一封简短说明
  • 礼貌地单独 @ 一两个人跟进,不要群发催促
  • 如果自己最近没帮别人review过,先去做一两个,再回来等

阶段7:自动监控

用pr_monitor.py持续监控PR评论,自动修复review建议。把阶段5.5(Review响应)从手动变成自动轮询。

7.1 启动监控

# 默认:处理所有 review 评论,每 5 分钟轮询
python3 ~/.claude/skills/vibe-pr/scripts/pr_monitor.py \
  --repo cann/hcomm --pr 584

# 只处理人类 reviewer 评论
python3 ~/.claude/skills/vibe-pr/scripts/pr_monitor.py \
  --repo cann/hcomm --pr 584 --human-only

# 单次执行(调试用)
python3 ~/.claude/skills/vibe-pr/scripts/pr_monitor.py \
  --repo cann/hcomm --pr 584 --once

注意:需要在仓库目录下运行,或通过 --work-dir 指定仓库路径。

7.2 工作流程

  1. 调comment_parser.py --since-commit拉取最新push后的评论
  2. review_suggestion → 构造prompt → claude -p 修复 → commit → push → 触发CI
  3. review_question → 打印通知,不自动修改(需要人决策)
  4. 用state文件去重,避免重复处理同一条评论

7.3 安全机制

  • 单PR最多5轮自动修复(--max-rounds 可调)
  • 启动时检查工作目录无未提交改动
  • Ctrl+C干净退出,state自动保存
  • state文件持久化在 ~/.claude/skills/vibe-pr/state/

7.4 参数

参数 默认值 说明
--repo 必填 仓库名
--pr 必填 PR编号
--interval 300 轮询间隔(秒)
--max-rounds 5 最大修复轮次
--human-only false 只处理人类评论
--bot-accounts 额外bot账号(逗号分隔)
--work-dir . 仓库目录
--once false 只执行一次

脚本调用速查

场景 命令
验证token python3 ~/.claude/skills/vibe-pr/scripts/gitcode_api.py
获取issue详情 python3 ~/.claude/skills/vibe-pr/scripts/issue_parser.py --repo <repo> --issue <n>
获取issue(URL) python3 ~/.claude/skills/vibe-pr/scripts/issue_parser.py --url <issue_url>
查PR状态 python3 ~/.claude/skills/vibe-pr/scripts/pr_status.py --repo <repo> --pr <n>
更新PR标题/描述 gitcode_api.update_pull(repo, token, number, title='...', body='...')
解析PR评论 python3 ~/.claude/skills/vibe-pr/scripts/comment_parser.py --repo <repo> --pr <n>
解析最新push后评论 python3 ~/.claude/skills/vibe-pr/scripts/comment_parser.py --repo <repo> --pr <n> --since-commit
分析reviewer python3 ~/.claude/skills/vibe-pr/scripts/reviewer_activity.py --repo <repo> --pr <n> --recent 30
手动指定候选人 python3 ~/.claude/skills/vibe-pr/scripts/reviewer_activity.py --repo <repo> --candidates "a,b,c" --recent 30
启动PR监控 python3 ~/.claude/skills/vibe-pr/scripts/pr_monitor.py --repo <repo> --pr <n>
单次监控(调试) python3 ~/.claude/skills/vibe-pr/scripts/pr_monitor.py --repo <repo> --pr <n> --once
读取PR上下文 python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --repo <repo> --pr <n>
初始化PR上下文 python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --repo <repo> --pr <n> --init
列出活跃PR python3 ~/.claude/skills/vibe-pr/scripts/task_context.py --list

合并排障

当PR满足四个标签却未合并时,检查:

症状 解决方法
squash冲突 用户需rebase目标分支后重新push
并发合并冲突 等1分钟后评论 /check-pr 重试
PR标题含 [WIP] 删掉 [WIP] 前缀
未解决的评审意见 先resolve所有CodeReview讨论
CI重试按钮无效 重新评论 /compile 完全重跑(重试按钮只重跑失败任务)

Bot命令速查

命令 功能
/compile 触发CI
/lgtm / /lgtm cancel 审查通过 / 撤销
/approve / /approve cancel 同意合并 / 撤销
/check-cla 重新检查CLA
/check-pr 检查标签并触发合并
/assign @user 分配Issue
/close 关闭Issue