ThinkRail 代码审查完整教程:3 步把行级评论钉进 Diff,给 AI Agent 一份带行号的修复工单
【免费下载链接】thinkrailVibe code with pi in a lightweight, real IDE that customises itself around the way you work — The Vibe You Need项目地址: https://gitcode.com/GitHub_Trending/th/thinkrail
ThinkRail 是一款围绕 pi 编码代理构建的 Agentic IDE,它的代码审查功能让你把评论直接钉在 Diff 的具体行上,再一键打包成带行号、代码片段和上下文的工单,交给 AI Agent 逐条修复。本教程从一轮完整审查的走查讲起,把操作路径、上下文包内容和锚点漂移处理机制一次说清。
一轮审查走查:从选区到发出
先不看机制,把一整轮操作走一遍,你就知道每个状态长什么样了。
在 Diff 上留评论:3 个动作
- 双击文件打开 Diff,选中要说的行。在 Changes 面板里双击文件名进入 Diff 视图,用鼠标(或方向键)框选任意几行。
- 点选区旁浮出的评论图标。会弹出一个内联输入框(composer),里面标着选区行号,比如
Line 2。这时你有两个出口:Save draft存成草稿稍后统一处理,或者Send now立刻发出,并顺带创建这个文件的审查会话。 - 看着它钉在 Diff 上。存为草稿的评论会渲染成一张
review-thread-card线程卡片,卡片上标着 draft 状态和发送按钮;与此同时,编辑器对应标签页会挂上一个紫色 Review 角标和待发送计数,相当于在提醒你"这个文件还有话没说出去"。
评论的挂载点不止 Diff 一种:普通文件里的 inline 评论、整文件的 file 评论、乃至整组改动(whole change set)级别的备注都支持。
base 侧:另一套独立的锚点空间
Diff 的左右两侧其实是两套互不干扰的锚点空间。你可以专门针对左侧"改动前(base 侧)被删除或替换掉的代码"留言——这在"为什么要删这段"的讨论里特别有用。这类评论在发给 Agent 时会明确标注side="base",行号和片段引用的是变更前的文件版本,Agent 拿到后会先自己对照当前文件定位,而不是照着旧行号乱改。
All changes 视图:逐块过一遍
切到分支级 Diff(All changes)视图,审查节奏会变成"逐块确认":每个 hunk 下面挂着Keep / Revert / Ask agent about this hunk三个按钮,Keep 以 hunk 内容本身为键,后面行号再怎么漂移也不影响它。底部是一条进度条加Next unreviewed按钮(快捷键J,到末尾会绕回开头),配合V标记已读,大改动就能一块一块啃完。
点下发送之后:Agent 实际收到了什么
很多人以为"发审查"就是把你的文字原样丢进聊天框。实际不是。Host 端在发送前会先把这个文件的所有评论渲染成一份结构化上下文包,逻辑在 上下文包渲染模块。每条评论在包里都带着:
- 稳定的 comment id、文件路径、行号范围、锚点状态(anchored / moved / outdated);
- 你选中的那段代码片段原文(fragment);
- 片段前后各 10 行的上下文(context),让 Agent 不用盲猜周边;
- 一段明确的行为指令:逐条处理;直接用你平时的编辑工具改文件;每处理完一条就调用
resolve_comment工具并附一行"做了什么"的说明;遇到 outdated 的评论先对照当前文件核实;看不懂或不同意,就在对话里反驳,不要硬改、也不要销账。
注意指令里那句"反驳"——Agent 被明确允许说"我不同意",而不是必须执行。
发送后的收尾分两种走向:
- 正常:Agent 用真实编辑工具改完文件,调一次
resolve_comment,Review 面板里对应评论立刻从 In progress 沉到 Resolved。这个工具做了会话绑定:只有真正收到过这条评论的那个聊天会话能销账它,所以规划流程里的审查 Agent 没法自己提一条 finding 又自己秒销。 - 翻车前滚:如果 Agent 还没开始干活就失败了(比如模型密钥过期),发送会在"回合被接受"这个窗口判定为拒绝,评论自动回滚成草稿,该文件为此新建的会话也会被解绑。你可以直接重发,不会留下"发出去但 AI 根本没收到"的悬空状态。
每个文件的第一次发送会自动开一个专属审查会话,之后这个文件的所有新评论都续进同一个会话,讨论是连续的;发送时也可以显式指定当前打开的聊天作为落点。
重锚机制:行号会漂移,评论不会
审查往往横跨好几个 Agent 回合,文件在背后不停变化。ThinkRail 的对策是:每次读取快照和每次发送前都跑一遍重锚(re-anchoring),纯函数实现见 重锚算法。锚点只有三种状态:
- anchored—— 文件的 sha-256 内容哈希没变,评论原地不动;
- moved—— 文件变了,但评论创建时截取的文本引用(textQuote,带前缀/后缀消歧)在全文中恰好命中一处,静默改钉到新行号,不打扰你;
- outdated—— 找不到、命中多处、或文件已删除。此时评论保留写下那一刻的代码快照并打上 outdated 标记,发送时指令会告诉 Agent"先核实当前文件"。
设计取向很清晰:能对上就悄悄跟上,对不上就诚实承认,绝不假装还在原位。而 base 侧评论不参与重锚——它被钉死在创建时固化的 commit 上,你之后随便提交多少次,被删除的代码也不会"复活错位"。
Review 面板的状态账本
右侧边栏的 Review 面板把所有评论按文件分组,每个文件下分三段:
| 分段 | 内容 | 能做什么 |
|---|---|---|
| Drafts | 未发送的草稿 | 编辑、删除、单条发送、整文件发送 |
| In progress | 已发送、Agent 处理中 | 打开关联会话、看 Agent 状态 |
| Resolved | 已销账 | 回看讨论 |
发送按钮有两档粒度(见 发送按钮组件):文件级的Send review (N)只发这一个文件的 N 条草稿;面板顶部的Send all (N)一次性清空全部草稿。
有几条规则值得记住:
- 草稿能删,发出去的就删不了。这是刻意的:Agent 会话里已经引用了这条评论的 id,删了就是悬空引用。不认同某条已发评论?用回复的方式表达,而不是抹掉它。
- Done 是文件级收尾。一个文件的评论全部解决后可以点 Done 标记完结;但在这个文件上再留一条新评论,标记会自动解除、文件重新回到待处理列表。
- Clear 开启下一轮。它会把已发送/已解决的记录归档(存到
reviews/archive/),丢弃剩余草稿,所有连着的客户端同步清空——一轮审查干净收场。
长审查实战清单
- ⌨️
J跳下一个未审查文件,V标记当前文件已读,Alt+↑/↓ 在文件间上下移动; - 边读边攒草稿,攒成一批再Send all,Agent 一次拿到完整问题清单,修起来不反复;
- 想评论被删除的代码,就选 base 侧,Agent 会自动按"改动前版本"理解;
- 审查状态持久化在
~/.thinkrail,重启 IDE 后评论、会话都在,各自独立恢复; - 50 个文件以上的大改动,界面会自动建议你切到One file模式逐文件过,避开长虚拟列表的卡顿;
- 人 + 机协作:规划流程中的审查 Agent走同一条
addComment通道提交发现,面板上带 "Filed by ThinkRail's reviewer agent" 机器人角标,你逐条确认或回复即可; - 想舒服地久坐审查:Settings → Layout 里内置了Review 预设布局(1 左 + 2 右栏组),一键切换后聊天、Diff、Changes/Review 各就各位。
从"许愿"到"工单"
把代码审查从聊天里的一笔带过,变成选行 → 留言 → 锚定 → 打包 → 派单 → 销账的闭环:每条意见精确到行号、带着片段和上下文进 Agent,处理完有明确的销账动作,位置漂移有自愈机制。审查从此不再是一句"把这块改一下",而是一份可追踪、可重发、对不上了会自己承认的工单。
想更细地看行为细节,端到端测试用例 几乎可以当第二本教程读;整个审查层的状态机设计在 reviews 模块 SPEC 里写得很完整,前端评论交互可看 useReviewCommenting。
【免费下载链接】thinkrailVibe code with pi in a lightweight, real IDE that customises itself around the way you work — The Vibe You Need项目地址: https://gitcode.com/GitHub_Trending/th/thinkrail
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考