关于 doubt-driven-development
面向主会话编排者的技能,用于在非平凡决策和产出定稿前进行新上下文的对抗式审查。它通过提取最小审查材料、分类审查发现和限制循环次数,帮助及早发现问题。
主要功能
- 01明确决策主张及其重要性
- 02分离待审材料与约束
- 03调用新上下文审查者找出问题
- 04逐项核对并分类审查发现
- 05设置有界审查循环与停止条件
- 06交互会话中提供跨模型复核选项
适用场景
- 01审查架构决策或非平凡代码
- 02核实依赖隐含上下文的正确性主张
- 03评估生产发布、数据迁移或公共 API 变更
- 04在定稿前检查可能存在的边界情况
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ addyosmani/ agent-skills --skill doubt-driven-development安装后在 Claude Code 中输入/doubt-driven-development确认已加载。
详细介绍
疑疑驱动开发
概述
有把握的答案不一定正确。长时间的会话会不断积累上下文,悄然将假设变成“事实”,却无人察觉。疑疑驱动开发是一种纪律:在任何重要产出定稿之前,先引入一位拥有全新上下文的审查者,并让其倾向于证伪,而不是批准。
这不是 /review。/review 是对已完成成果作出判定。这是一种进行中的工作方式:在纠正方向仍然代价低廉时,对重要决策进行质询。
何时使用
当至少满足以下一项时,某项决策就是重要决策:
- 引入或修改分支逻辑
- 跨越模块或服务边界
- 声称了类型系统或编译器无法验证的属性(线程安全、幂等性、顺序、不变量)
- 正确性依赖于未来读者无法看到的上下文
- 影响范围不可逆(生产环境部署、数据迁移、公共 API 变更)
在以下情况下应用此技能:
- 即将基于不确定信息作出架构决策
- 即将提交重要代码
- 即将声称某个不明显的事实(“这样是安全的”“这样可扩展”“这样符合规范”)
- 在你不完全理解的代码中工作
不应使用的情况:
- 机械操作(重命名、格式化、移动文件)
- 遵循明确无歧义的用户指示
- 阅读或总结现有代码
- 正确性显而易见的单行修改
- 纯工具操作(运行测试、列出文件)
- 用户明确要求优先考虑速度而非验证
如果你对每一次按键都心存疑虑,就什么也交付不了。此技能仅适用于上述定义的重要决策。
加载限制
此技能专为主会话编排器设计,因为步骤 3(DOUBT,详见下文)可以启动一位拥有全新上下文的审查者。
- 不要将此技能添加到 persona 的
skills:frontmatter 中。 遵循步骤 3 的 persona 会启动另一个 persona——这违反了../../references/orchestration-patterns.md中明确禁止的编排反模式(“personas do not invoke other personas”)。 - 如果你发现自己正在子 Agent 上下文中应用此技能(Claude Code 会阻止嵌套启动子 Agent):首选做法是告知用户,疑疑驱动审查无法嵌套运行,并让主会话处理。仅在万不得已时,才使用降级的自我质询备用方案——将 ARTIFACT + CONTRACT 作为新的自我提示词重写,与先前推理在思维上严格隔离,然后执行步骤 1–5。这不属于全新上下文审查(你仍然带着自己的上下文),因此必须标明结果已降级;只要用户可联系,就应优先升级处理。
流程
应用此技能时,复制以下清单:
Doubt cycle:
- [ ] Step 1: CLAIM — wrote the claim + why-it-matters
- [ ] Step 2: EXTRACT — isolated artifact + contract, stripped reasoning
- [ ] Step 3: DOUBT — invoked fresh-context reviewer with adversarial prompt
- [ ] Step 4: RECONCILE — classified every finding against the artifact text
- [ ] Step 5: STOP — met stop condition (trivial findings, 3 cycles, or user override)
步骤 1:CLAIM — 明确要审查的内容
用两三行说清楚决策:
CLAIM: "The new caching layer is thread-safe under the
read-heavy workload described in the spec."
WHY THIS MATTERS: a race here corrupts user data and is
hard to detect in QA.
如果无法简洁地写出主张,那你只有一种感觉,而不是一个决策。先明确表达,再进行审查。
步骤 2:EXTRACT — 提取最小可审查单元
拥有全新上下文的审查者需要的是产出物和契约,而不是过程。
- 代码:差异或函数,而不是整个文件
- 决策:用 3–5 句话说明提案及其必须满足的约束
- 断言:主张及其声称支持该主张的证据(与步骤 1 的 CLAIM 块分开;该块是编排器正在接受审查的假设)
删去你的推理过程。如果你直接给出结论,得到的就只会是对结论的确认。审查单元必须足够精简,让审查者一遍阅读就能记住;如果这是一个 500 行的 PR,请先拆分。
第 3 步:DOUBT——调用全新上下文的审查者
审查者的提示词必须具有对抗性。措辞决定答案。
Adversarial review. Find what is wrong with this artifact.
Assume the author is overconfident. Look for:
- Unstated assumptions
- Edge cases not handled
- Hidden coupling or shared state
- Ways the contract could be violated
- Existing conventions this might break
- Failure modes under unexpected input
Do NOT validate. Do NOT summarize. Find issues, or state
explicitly that you cannot find any after thorough examination.
ARTIFACT: <paste artifact>
CONTRACT: <paste contract>
只传递 ARTIFACT 和 CONTRACT。不要传递 CLAIM。 把你的结论交给审查者会使其倾向于赞同。审查者必须独立判断该制品是否满足契约。
在 Claude Code 中,agents/ 里的角色审查者默认使用隔离上下文,因此可用于此处——请参阅 agents/,了解人员名单和各领域的匹配情况。
上述对抗性提示词优先于角色设定的默认回复格式。 code-reviewer 之类的角色设定旨在给出兼顾优缺点的平衡评判;而基于质疑的审查需要只输出问题。调用时请原样粘贴对抗性提示词,以覆盖角色设定的默认格式。如果无法干净地覆盖某个角色设定的回复格式,请改用带有对抗性提示词的通用子 Agent。
跨模型升级
单模型审查者与原作者有着相同的盲点——换一个更冷静、架构不同的模型就能发现这些问题。对于非简单决策,疑虑驱动审查本来就是可选的,因此在此范围内提供跨模型审查是这项技能的价值所在,而不是可选的麻烦。
交互式会话:始终提供此选项。绝不默默跳过。
步骤 1:询问用户
在上文步骤 3 的单模型审查完成后、RECONCILE 之前,暂停并询问:
“单模型审查已完成。要征求跨模型第二意见吗?选项:Gemini CLI、Codex CLI、手动进行外部审查(由你粘贴到其他地方),或跳过。”
每次交互式疑虑审查周期都必须提出此问题——即使产物看起来风险很低也不例外。是否值得付出成本由用户决定,而不是 Agent。Agent 的职责是让用户知道有此选项。
步骤 2:如果用户选择 CLI——先验证,再调用
- 检查工具是否位于 PATH 中(
which gemini、which codex)。 - 在传入完整提示词之前,先测试工具是否可用(
gemini --version或等效命令)——过时或损坏的二进制文件可能通过which检查,却无法处理实际输入。 - 与用户确认确切的调用方式,包括所需标志、身份验证和环境变量(例如 API 密钥)。不同实现各不相同;绝不要想当然。
- 只传入 ARTIFACT + CONTRACT + 对抗性提示词。不传入会话上下文或 CLAIM。
- 注意 shell 转义。如果产物包含引号、
$(...)或反引号,优先使用标准输入(echo … | gemini)或 heredoc,而不是内联的-p "…"。如有疑问,运行前请用户确认调用方式。 - 将输出带入步骤 4(RECONCILE)。
**绝不要将产物插入带引号的 shell 参数中。**代码、Markdown 和审查提示词经常包含反引号、$(...) 和引号字符,这些内容可能截断提示词或执行其中嵌入的 shell 命令。请将完整提示词写入文件,并通过标准输入传递。
示例形式(请根据已安装工具确认标志——不同实现和版本的语法各不相同):
# Write the adversarial prompt + ARTIFACT + CONTRACT to a temp file first.
# Then pipe via stdin so shell metacharacters in the artifact stay inert.
# Codex (read-only sandbox keeps the CLI from writing to your workspace):
codex exec --sandbox read-only -C <repo-path> - < /tmp/doubt-prompt.md
# Gemini ('--approval-mode plan' is read-only; '-p ""' triggers non-interactive
# mode and the prompt is read from stdin):
gemini --approval-mode plan -p "" < /tmp/doubt-prompt.md
只读沙箱是关键所在:疑虑审查产物本身可能包含指令(有意或无意的提示词注入),否则跨模型 CLI 可能会对你的工作区执行这些指令。
步骤 3:如果 CLI 不可用或调用失败
明确说明失败情况。提供以下选项:手动运行、尝试其他工具,或跳过。不要默默退回单模型审查——用户应该知道跨模型审查并未进行。
步骤 4:如果用户跳过
在输出中确认已跳过(“仅根据单模型审查结果继续”),然后继续 RECONCILE。跳过没问题;默默跳过则不行。
非交互式上下文(CI、/loop、自主循环、定时运行):
- 跳过跨模型审查,并且必须在输出中说明已跳过:“已跳过跨模型审查:非交互式上下文。”
- 绝不要在未经用户明确授权的情况下调用外部 CLI——这是关键的安全属性。
跨模型审查会增加成本、延迟和工具的不稳定性。Agent 每个周期都会向用户提供选择;用户决定该产物是否值得进行跨模型审查。
步骤 4:RECONCILE — 纳入审查结果
审查者的输出是数据,不是判决。你仍然是协调者。 针对每条发现,重新对照产物文本进行核查后再分类——不加判断地照单全收,与置之不理是同一种失误。
按以下优先顺序对每条发现进行分类(匹配到的第一类即为结果):
- 误读契约 — 审查者指出某个问题,明确是因为你提供的契约不够清晰或不完整。先修正契约,在下一轮重新分类。
- 有效且可操作 — 确实存在需要修改产物的问题。修改后重新循环。
- 有效但属于权衡 — 问题确实存在,但修复成本高于接受问题的成本。明确记录这种权衡,让用户了解情况。
- 噪声 — 审查者指出的问题,在它不了解的上下文中其实是正确的。记录下来,继续处理,并自问:把该上下文补充到契约中,能否避免误报?
新加入的审查者可能因缺少上下文而出错。不要只因为它是“新来的”就让步。
步骤 5:停止 — 有界循环,而非递归
在以下情况下停止:
- 下一轮只返回细枝末节或已考虑过的发现,或
- 已完成 3 轮(升级给用户处理,不要独自再磨第四轮),或
- 用户明确表示“可以发布”
如果经过 3 轮后,审查者仍指出实质性问题,产物可能尚未准备就绪。向用户说明这一点——3 轮问题仍未解决,说明了产物的情况,而不是继续循环的理由。
如果 3 轮“显然不够”,因为产物太大:说明产物过大——返回步骤 2 并拆分。不要放宽轮数上限。
常见借口
| 借口 | 实际情况 |
|---|---|
| “我有把握,跳过质疑步骤吧” | 面对新问题时,自信程度与正确性关联不大。越是确信无疑,盲点越容易藏在其中。 |
| “启动审查者太费钱” | 在生产环境中调试错误提交,代价更高。检查有上限;Bug 没有。 |
| “审查者只会挑刺” | 只有在范围不明确时才会如此。将提示词限定为“根据契约会导致失败的问题”。 |
“我会在最后用 /review 进行质疑” | /review 是最终关卡。通过质疑尽早发现错误方向,纠偏成本更低。等到 PR 阶段就太晚了。 |
| “每一步都质疑的话,我永远也无法发布” | 这项技能适用于重要决策,而不是每次敲击按键。请重读“何时不使用”。 |
| “两个观点总比一个好” | 如果第二个观点缺少更多上下文并产生噪声,就不是这样。要核对,而非让步。 |
| “审查者不同意,说明我错了” | 审查者缺少你的上下文——意见不一致是信息,不是判决。重新阅读产物、分类,然后再做决定。 |
| “跨模型总是更好” | 跨模型审查能发现单个模型自身不易察觉的盲点,但也会增加成本,并带来工具不稳定性。每个交互式质疑周期都应提供此选项——由用户决定产物是否值得这样做。Agent 的职责是提供选择,而不是设限。 |
| “用户曾经同意过一次,所以我可以继续调用 CLI” | 每次调用都需要单独授权。不同调用之间,产物、提示词和标志都会变化——每次运行前,都要与用户再次确认确切的命令。 |
危险信号
- 为单行重命名或格式调整启动一个全新上下文的审查者
- 不重新阅读制品文本,就把审查者的输出视为权威结论
- 循环超过 3 轮仍不升级给用户
- 用“这样好吗?”来提示审查者,而不是“找出问题”
- 在时间紧迫时,对高风险决策跳过疑虑核查
- 对未更改的制品重新启动全新上下文审查(你会得到相同的发现;这是在拖延)
- 疑虑作秀(可检查的信号):在 2 轮或更多轮次中,审查者提出了实质性发现,但没有任何发现被归类为可执行事项。你是在确认,而不是存疑。停止并升级处理。
- 只有提交之后才产生疑虑——那属于
/review,不是由疑虑驱动的开发 - 未与用户确认某个外部 CLI 工具确实存在、已配置且接受完全相同的语法,就硬编码调用该工具
- 在交互式疑虑循环中默默跳过跨模型审查。 即使不建议跨模型审查,也必须明确提出。可以跳过,但不能默默跳过。
- 外部 CLI 报错或缺失时默默回退——应指出故障,并让用户决定如何处理
- 从提供给审查者的输入中删除契约
- 将 CLAIM 提供给审查者(这会造成偏向认同的倾向)
与其他技能的配合
code-review-and-quality//review:两者互为补充。/review是事后的 PR 评审结论;由疑虑驱动的开发则针对进行中的每项决策。两者都要使用。source-driven-development:SDD 会根据官方文档核实 有关框架的事实。由疑虑驱动的开发则核实 你对制品的推理。SDD 检查 API 是否存在;由疑虑驱动的开发检查你是否在契约约束下正确使用了它。test-driven-development:TDD 的 RED 步骤是将疑虑具体化——失败的测试就是一次反证尝试。适用 TDD 时,这个失败的测试 本身就是 对行为主张的疑虑步骤,详见“与其他技能的配合”。debugging-and-error-recovery:如果审查者发现了真实的故障模式,就切换到调试技能来定位并修复。- 仓库编排规则(
../../references/orchestration-patterns.md):此技能由主会话进行编排。由某个人格调用另一个人格是反模式 B——参见上文“加载约束”。
验证
应用由疑虑驱动的开发后:
- 每项非平凡决策(定义见上文)在坚持该决策前,都已明确表述为 CLAIM
- 每个非平凡制品至少经过一次全新上下文审查(根据“与其他技能的配合”,TDD RED 步骤产生的失败测试可满足行为主张的这一要求)
- 审查者收到的是 ARTIFACT + CONTRACT,而不是 CLAIM,也不是你的推理
- 给审查者的提示具有对抗性(“找出问题”),而不是用于确认(“这样好吗”)
- 根据制品文本对发现进行了分类(而非照单全收),并遵循以下优先顺序:误读契约 / 可执行事项 / 权衡 / 噪声
- 达到停止条件(发现的问题无关紧要、循环 3 轮,或用户覆盖)
- 在交互模式下,无论制品风险如何,都已明确向用户提出跨模型审查,并在输出中确认其回复
- 在非交互模式下,已跳过跨模型审查,并说明了跳过的情况
- 任何外部 CLI 调用之前,都已检查 PATH、测试可执行文件是否正常、向用户确认语法,并取得明确的运行授权