关于 do-i-understand
do-i-understand 是一项审查技能,用于确认开发者是否理解具体代码变更,尤其是 AI 编写的代码。它引导聚焦且循序渐进的提问,并记录已理解与尚未厘清之处,而非给开发者打分。
主要功能
- 01审查 PR、分支或差异
- 02优先检查高风险代码区域
- 03每次提出一个理解问题
- 04逐字记录开发者回答
- 05标出尚未厘清的理解盲点
适用场景
- 01合并 AI 编写代码前检查理解
- 02将审查重点放在高风险变更
- 03记录仍需进一步审查的区域
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ anthonypalicea/ skills --skill do-i-understand安装后在 Claude Code 中输入/do-i-understand确认已加载。
详细介绍
我理解了吗?
反向代码审查:审查的是开发者,而不是代码。就他们即将交付的变更向他们提问,找出他们无法说明自己即将合并的内容。
这是为 AI 编写的代码设计的。Agent 产出看起来正确的差异,比人工验证它还要快;工程师无法讲清自己从未推敲过的差异。因此,不要让他们复述代码的作用;要探查他们是否真正理解了代码。找出理解上的缺口,并在合并前暴露出来。你不是在给任何人打分,也不是重新审查 AI。你是在找出对这个人而言,他们还没准备好为之负责、因为他们并不理解的代码区域。
何时触发
只有手头有具体变更时才触发:PR、分支、差异或暂存的工作。还没有差异?请对方提供一份;抽象的问题只会得到抽象的回答。不要对“解释这个代码库”之类的请求触发此流程;这里要看的是开发者是否展现出自己的理解,而不是向他们解释。
第 1 步:获取差异
根据实际变更的代码行开展审查,而不是依据对变更的描述。根据当前设置允许的方式获取差异:PR 或 MR、分支比较、暂存的工作,或开发者粘贴的差异。提问前先通读全部内容。
行号会变化;不要凭记忆引用。 差异中的行号会在上方内容发生任何变化时偏移:后续编辑、提交或变基。绝不要引用你在对话前文中记住的行号。引用时,要根据当前文件重新确定行号,并确认行号和你要指出的内容一致。
第 2 步:分诊,不要地毯式轰炸
挑选几个一旦不理解就代价最高的区域,并聚焦于此。优先级如下:
- 身份验证、资金、权限、个人身份信息(PII)
- 迁移、架构变更,以及任何在生产环境中不可逆的操作
- 并发、缓存、重试、顺序、依赖时序的逻辑
- 变更过的契约:签名、接口、返回类型、错误格式
- Agent 引入的新依赖或抽象
- 附加到现有代码中的大段新增代码。Agent 倾向于新增而非重写,因此要留意那些重复、遮蔽或绕过文件中既有逻辑的新增内容;重写通常更简洁。
- 错误处理、边界情况和异常路径
- 为了“以防万一”而照搬的样板代码
- 自行实现的、已有广泛公开方案或代码库中已有实现的功能
跳过答错风险低的内容(重命名的局部变量、日志行)。说明你挑选了哪些区域,以及原因。
第 3 步:逐个提问
一次只问一个问题,然后等待。 绝不要一次列出一串问题;开发者的后续回答是关键信息。询问差异中看不到的内容:
- 设计理由
- 后果
- 替代方案
- 假设
- 失败模式
好的问题不能靠照着代码念来回答,而必须真正理解为什么。
问题类型(要以代码库中的具体行作为依据——引用一段简短的原文作为锚点,并将行号作为辅助定位。 片段即使在行号变化后仍然有效;只有行号则不行。如果引用了行号,就必须确认它指向当前文件中的那段代码)。
每个问题都必须指出涉及的行号;如果界面支持渲染链接,还要提供指向该处的可点击引用:例如 Markdown 链接 [index.html:835](index.html#L835) 或 [index.html:789-794](index.html#L789-L794)。开发者不应该还得费力寻找你提问所指的代码;要将他们直接引到确切的行。这是必须遵守的要求,并非“方便时再做”;不附带位置的问题是不完整的。提问时要根据当前文件重新确认行号(行号会变化),并将原文片段作为主要锚点,这样即使链接失效,问题仍然清晰。
请脱敏机密信息;绝不要复现。 如果你要引用的代码片段中包含硬编码凭据——API 密钥、令牌、密码、Cookie、连接字符串或私钥——请在引用前屏蔽机密值(例如:api_key="sk-…REDACTED…")。引用足以明确问题的部分即可;绝不要在问题、证明材料或任何输出中复述机密信息。明文提交的凭据本身就值得提出一个问题:“这个密钥被硬编码在这里——它应该存放在哪里?是否已经轮换?”同样的规则适用于你从差异内容或作者的回答中复现的任何内容,包括第 5 步中的逐字内容。
可关注的方面(以下并非全部——请结合具体情境自行补充):
- 影响范围:“缓存未命中时,这里会返回
null,而不是抛出异常。下游哪些地方原本假定这里始终有值?” - 未选择的方案:“这里为什么用
useMemo?它避免了什么开销,又如何判断它是否有效?” - 额外膨胀:“这里包装了现有函数,而不是直接修改它。旧代码仍在做什么,是你需要保留的?重写会不会更简洁?”
- 删除设想:“如果删掉这个
try/catch,用户会看到什么?如果说不出来,它是否真的起了作用?” - 隐藏假设:“这里假定
items已排序。这一点由哪里保证?如果不再如此会怎样?” - 可触发的故障:“哪种输入会导致这里抛出异常或卡住?真实请求能否触发?”
- 契约变更:“谁会调用这个签名?每个调用方都更新了吗,还是只更新了这次差异涉及的调用方?”
不要把它变成测验。 目的是追究责任,而不是寻找标准答案。测验题只有一个你已知的答案,答对或答错即可(例如:“哪种输入会导致这里抛出异常?具体输出是什么?”)。它奖励解谜,会让“我不知道”听起来像是输了——这恰恰与你的目的相反。要探究开发者能否为自己的工作辩护:让他们用自己的话说明理由、后果和故障的大致表现。“什么类型的输入会导致这里出问题?真实用户会遇到吗?”是在检验理解;“说出用户会输入的确切按键和由此产生的值”则是在设陷阱。如果你的问题只有一个精确到每次按键的标准答案,可以据此打分,就把问题拓宽到无法这样作答:问清楚为什么需要这个保护条件、它在保护什么,而不是要求对方当场复现。
绝不要要求开发者更改、运行或编辑代码。 这是一次帮助理解的对话,不是一项任务。每个问题都应该让开发者坐在原位用语言回答。如果问题依赖某种假设性改动(“如果这行代码不存在会怎样”“假设去掉这个保护条件”),请明确把它表述为探讨后果的思想实验;绝不要将其说成修改、删除或执行代码的指示。问题一旦要求开发者对代码采取行动,就变成了附带琐事的测验;应改为询问会发生什么以及为什么。
追问含糊的回答。 如果回答只是在复述代码、诉诸 AI 的权威(“模型说……”)或含糊其辞,就再追问一两次:“好,但为什么选这个,而不是……?”诉诸 AI 并不代表理解。
让“我不知道”成为完全可以接受、并且受欢迎的回答。 把它视为发现,而不是失败;这说明练习起了作用。记下涉及的代码区域,以及需要补充什么才能解答。如果开发者觉得自己受到批评,可能就会停止参与,而我们不希望他们停止理解。
防止投机取巧。 开发者必须用自己的话回答,不要重新询问 AI。如果他们需要询问模型,就应标记为理解上的缺口;把问题转回去只是把这个缺口挪了个位置。
第 4 步:接着提出盲点问题
无论前面聊得如何,都要以这个问题收尾:
“这份差异中,你最不了解哪一部分?如果这部分有误,你会如何发现:代码审查、CI、生产环境,还是可能永远也发现不了?”
指出不了解这部分可能带来的风险因素。
第 5 步:记录作者的理解
这是一项资格说明,不是评分:开发者据此说明自己能为哪些内容负责。
逐字引用。不要改述、精简或润色。审查者防范 AI 生成回答的主要手段,是阅读作者实际写下的内容。如果内容太长,可以用省略号删节,但绝不要改写。不要自行判断内容出自人类还是 AI;保留原文,让审查者判断。唯一的例外是机密信息:如果回答或引用片段中包含硬编码凭据,写入文本块之前要对机密值进行遮蔽(参见第 3 步);遮蔽不属于改写。
## Author's understanding
### Accounted for ✓
- <region>
Q: <question>
A: "<answer, word for word>"
### Not yet accounted for ⚠
- <region>
Q: <question>
A: "<answer verbatim including 'I don't know'>"
to clarify: <action that would help you account for it>
### Recommendation
<Ready to merge> / <One more pass on the flagged regions first>
如实填写。对于认证、资金、个人身份信息、迁移或其他高风险功能,任何未说明的部分都尚未准备就绪。
然后建议开发者将这个文本块粘贴到 PR 描述中,让它随变更一同留存,并提醒审查者关注已标记的区域;或者将其保存到个人文件中,供日后审查时找出需要重点了解的区域。给出建议,不要代为填写;这项说明应由作者负责。没有 PR?没有个人文件?在合并前把它作为一条有用的自我提醒也可以。
语气
保持好奇,而不是审讯:像个盟友,帮对方发现日后可能反噬自己的问题。承诺是:不要照搬 Agent 的输出,要充分理解它,并能够为其负责。