AI 写代码之后,Code Review 会议怎么开
背景:又一个"整理"的活
写完 /weekly-report12 之后发现同一套思路还能再用一次:代码 review 会前,也得把这段时间的提交整理成一份能讲的东西。会上被问"这里为什么这么改",自己都未必答得上来,毕竟现在很多代码本身是 AI 写的,没细看过的代码讲不出个所以然。
这次多了两个新问题:一是同一个需求(Jira 卡)的提交经常散在好几次 commit 里,逐条讲更没有整体感;二是既然连作者本人都未必讲得清楚"为什么这么改",报告干脆不勉强讲原因,正文只讲"改了什么、现在什么状态"。diff 直接嵌进报告里默认折叠,点开就是完整对比视图,想深究的人自己展开看,不用再跳到 IDE 或 GitHub 去对照。
于是有了 /code-review-prep。3
效果演示
/code-review-prep 2026-07-15
扫描指定日期到今天所有仓库的提交,按 Jira 需求分组生成一份 HTML 报告:需求标题、汇总表格、逐需求的业务向叙事,每段叙事下面挂着对应的 diff(默认折叠,点击展开,用 diff2html 渲染成正经的对比视图,不用跳去 GitHub)。同一个需求如果跨了好几个仓库,叙事按仓库分段;没挂 Jira 编号的提交单独归进"其他改动",不跟别的需求混在一起。
报告只在本地生成,不 commit:这是会前材料,不是工作日志。
实现思路:两个真正有意思的点
其余部分(读配置、扫 git log、查 Jira 上下文、用 diff2html 渲染 HTML)跟 weekly-report 那篇讲的"脚本管确定性逻辑,AI 管生成性逻辑"是一回事,不重复讲。这里挑两个新东西。
1. 把同一需求的多个 commit 合并成一份 diff
一个需求经常不是一次提交搞定的:先加个字段,发现漏了处理某个 case,再补一个 commit。如果报告里按 commit 一条条列 diff,同事看到的是"补丁的补丁",看不出这个需求最终落地成什么样。
merge-story-diff.js 的做法是:在临时 worktree 里把这些 commit 按时间顺序 cherry-pick 到一起,最后跟 base 做一次 diff,得到的就是这个需求的"净改动":
js
const worktreeDir = fs.mkdtempSync(path.join(os.tmpdir(), 'code-review-prep-'));
run(`git -C "${repo}" worktree add --detach "${worktreeDir}" ${base}`);
for (const hash of sorted) {
run(`${GIT_IDENTITY_ENV} git -C "${worktreeDir}" cherry-pick --keep-redundant-commits ${hash}`);
}
const diff = run(`git -C "${worktreeDir}" diff ${base} HEAD`);
几个细节:
- worktree 而非直接操作当前工作目录:cherry-pick 会改动文件、写 HEAD,绝不能碰用户手头正在改的代码,全程在临时 worktree 里发生,用完即删。
- 提交时间排序用
git log --all过滤而非按%at排序 :commit time 只有秒级精度,两个 commit 前后脚提交时可能撞时间戳,排序会把父子顺序搞反;git log默认遍历顺序天然保证父提交排在子提交后面,过滤出目标 hash 集合更可靠。 - cherry-pick 冲突时自动回退:合并失败就清理现场,退回按 commit 原样拼接 diff,报告标题自动注明"合并失败,以下为按 commit 拼接的版本",不阻断整体流程。
- 用环境变量而不是
git config设置占位身份 :linked worktree 和主仓库共享大部分本地配置(只有 HEAD/index 是 worktree 私有的),在这里写git config要么读到仓库里不相关的设置,要么在 worktree 删除后把占位身份永久漏进真实仓库配置。
2. 给 AI 划死"能写什么、不能写什么"的写作规范
报告的叙事部分是 AI 生成的,如果不加约束,很容易写成一堆函数名、字段名堆出来的"翻译腔总结"。展开 diff 就能看到的东西,没必要在正文里重复。SKILL.md 里专门定了几条硬规矩:
- 叙事里不出现函数名、变量名、文件路径:想看代码细节的人自己展开 diff,正文只讲"这个需求做了什么、现在是什么状态"。
- 只讲结论,不讲原因:不解释"为什么会这样、为什么这么改",无论是代码层面的技术根因还是业务层面的决策依据,都留给看 diff 的人自己推导。但"文案还需内容团队确认"这类事实性待办要保留,只是不展开为什么有这个待办。
- 专有名词不硬翻译 :diff 里的变量名、i18n key 能看出团队日常怎么称呼一个功能(比如某个字段叫
checkout),正文就直接用这个词,不要另造一个"结算"式的中文翻译,反而增加同事的识别成本。
这几条规矩的共同点是:把"AI 生成"限制在"复述员工都听得懂的业务语言"这个范围内,技术细节和推导过程一律让位给下面可展开的真实 diff。
总结
同一套"脚本管确定性,AI 管生成性"的骨架,换一批脚本就能覆盖第二个整理场景。这次真正花心思的地方是想清楚哪些环节该外包给脚本、AI 该被限制在多窄的范围内生成内容。
References
1 https://github.com/zhaokang555/kang-skills#weekly-report-1
2 https://www.cnblogs.com/forzhaokang/p/19847939
3 https://github.com/zhaokang555/kang-skills#code-review-prep-1