对抗性审查
在有人按计划行动之前,找出提案会失败的原因。生成有优先级、可操作的问题和一个唯一的结论。绝不实现任何内容。永不循环超过轮次上限。
0. 设置
- 选择模式: 当调用方明确要求(例如“对抗性审查,报告模式”),或在没有人类回答的子代理、工作节点或无头运行中时,使用
report模式。迹象包括:任务作为委托提示词到达、没有提问工具、或调用方要求输出文件或字数受限的摘要。其他所有情况使用interactive模式。 - 找到审查对象: 它可以是一个文件路径、一个差异范围、一个粘贴的计划,或是“本对话中刚刚产生的内容”。如果有多个候选对象匹配,在输出的第一行明确指出所选对象。如果没有给出任何对象,且当前对话中也没有明显的近期候选对象:在交互模式下,询问用户指的是哪个对象,并提供本对话中最近产生的输出、用户指定的文件或差异,或用户描述的方法作为选项。在报告模式下,停止并提示没有给出审查对象。
- 设定关键性: 原型、内部工具、生产环境,或涉及资金/安全的路径。交互模式:如果不明确且会影响审查力度,则询问一次。报告模式:假定为生产环境并说明。关键性决定了类别扫描的深度,但不会改变严重性等级。
- 检查账本: 确定账本路径(参见第 11 节)。如果该审查对象已有账本,读取
references/ledger-format.md。- 如果最新一轮中任何 ID 的最新行状态为
pending,则表示上次的审查中断了。续接:跳过第 1 至第 5 节,读取已存储的记录,并从第一个pending的问题开始继续第 8 节。不要重新运行透镜或重新排序。在报告模式下,改为将它们列在“未决决策(OPEN DECISIONS)”下。 - 否则这是后续轮次。遵循第 11 节。
- 如果最新一轮中任何 ID 的最新行状态为
1. 首先提出最佳论点
在任何问题提出之前,用两到三句话说明该提案的合理之处:它解决的问题以及它遵循的约束。如果写不出来,说明提案尚未被理解。先多读读。
2. 生成候选问题
当到达某个透镜时,加载该透镜的参考文件。最后运行 L12。
| # | 透镜 | 用途 | 参考 |
|---|---|---|---|
| L1 | 事后失败:已上线并导致故障;逆向追溯 | 始终使用 | references/lens-questions.md |
| L2 | 逆向目标:列出哪些行为与失败完全一致;检查当前存在哪些 | 始终使用 | references/lens-questions.md |
| L3 | 隐藏假设:逐一命名;询问如果它不成立会发生什么 | 始终使用 | references/lens-questions.md |
| L4 | 常见遗漏领域的类别扫描 | 始终使用 | references/category-checklist.md |
| L5 | 典型 AI 故障的 AI 输出扫描 | 始终使用,当审查对象由 AI 生成时 | references/ai-output-checklist.md |
| L6 | 锁定描述:使模糊的词语可验证 | 按类型 | references/lens-questions-extended.md |
| L7 | 询问证据:是测量的、阅读的还是假设的 | 按类型 | references/lens-questions-extended.md |
| L8 | 其他角色视角:值班人员、安全人员、新员工、重度用户、攻击者 | 按类型 | references/lens-questions-extended.md |
| L9 | 向前推演两到三步 | 始终使用 | references/lens-questions-extended.md |
| L10 | 质疑框架:正确的问题?更小的改动? | 始终使用 | references/lens-questions-extended.md |
| L11 | 分别审查:事实、风险、备选方案、审查质量 | 按类型 | references/lens-questions-extended.md |
| L12 | 从最严重的失败到其根本设计原因的因果链 | 按类型 | references/lens-questions-extended.md |
按审查对象类型使用的“按类型”透镜:
| 审查对象类型 | 额外使用的透镜 |
|---|---|
| 小差异或 Bug 修复 | 无 |
| 功能差异或多步骤计划 | L6, L7, L12 |
| 设计、RFC 或选项间的决策 | L6, L7, L8, L11, L12 |
| 其他技能或代理的输出 | 使用该技能产生的内容的类型对应的行 |
阅读问题所依赖的实际代码、配置或计划行。基于对代码的猜测构建的问题不是证据。
3. 过滤
对每个候选问题应用以下全部四项测试。任何一项测试失败的候选问题则丢弃。
- 后果: 如果没人对此采取行动,实际会发生什么?“没什么大不了”意味着丢弃。
- 反论: 写出它不是真正问题的最有力理由(代码已处理、不在此次变更范围内、或不会造成损害)。如果该理由成立,则丢弃。如果问题仍然成立,则保留反论并说明其为什么失败。
- 可操作: 必须有具体的操作步骤。没有操作意味着丢弃。
- 非重复: 丢弃本对话中其他审查步骤、调用方的简报或账本中已经报告过的任何内容。
4. 评定严重性
等级是固定的。模式、关键性、轮次和时间压力不会改变它。
- 严重: 描述一个具体的故障事件:触发条件、如何失败以及损害波及的范围。触发条件必须在提案的现有文本中可触及。如果无法命名一个可触及的触发条件,则该问题最多为高。 参见
references/severity-downgrade-example.md。 - 高: 一个命名的、合理的情景,在该情景下会造成危害。
- 中: 值得修复。无需故障事件。
将每个问题标记为阻塞性(必须在工作继续前修复)或观察项(跟踪它,不要为了它而暂停工作)。
5. 预算
- 完整报告每个严重和每个高问题。
- 完整报告前三个中问题。将其他中问题列在一行:计数,然后每个的简短标签。永远不要无声地丢弃一个中问题。
- 如果严重加高问题的数量超过五个,停止详细审查。 结论为重新思考,并推荐将提案拆分为更小的部分。仅列出严重和高问题的标题。
6. 问题记录
每个报告的问题都包含所有这些字段:
### H1: <一行标题>
- 严重性: 高 | 故障事件: <触发条件> -> <如何失败> -> <影响范围>
- 透镜: L3 隐藏假设
- 反论: <针对该问题的最有力理由>. 失败原因: <原因>.
- 证据: <文件:行号 | 计划步骤 | 引用的决策>
- 如果忽略: <会发生什么>
- 操作: <具体的变更>
- 状态: 阻塞性 | 观察项
ID 使用严重性字母和数字:C1, H1, M1。ID 在任何轮次中永不改变。中等级记录可写为 故障事件: 不适用。
7. 结论
每次审查结束只给出一个结论:
- 继续: 没有阻塞性问题。可附带备注。
- 修正: 方法可行;先修复列出的阻塞性问题。
- 重新思考: 存在根本性缺陷,或第 5 节中的预算已超。
在结论下方,添加已知风险标题。列出最新账本行状态为 risk-accepted 的每个问题(来自任何轮次),包括其 ID、标题和轮次。如果没有,则写“已知风险:无”。它们永远不会阻塞。
8. 交互模式
- 展示最佳论点(第 1 节)。
- 在第一个问题之前,写入问题记录和每个待讨论问题的
pending状态账本行(参见账本参考)。 - 每次提出一个问题,最严重的优先。用户选择接受、拒绝、修改、接受风险或推迟。
- 如果存在结构化提问工具(Claude Code 中的
AskUserQuestion,OpenCode 中的question),则使用它,每个问题一个问题,并将整个记录放在问题文本中以便显示。如果工具限制了选项,提供接受、拒绝、接受风险和推迟,并将修改作为自由文本处理。 - 修改:接受用户的变更,然后视该问题已以其新形式被接受。拒绝:该问题不适用。接受风险:问题真实存在,用户接受其后果,现在无人修复;不阻塞。推迟:观察项,稍后修复。
- 在每个回答之后立即追加账本行, 在下一个问题之前。不要等到结论。
- 如果存在结构化提问工具(Claude Code 中的
- 当每个问题都有了一个解决方案时,在第二轮及之后运行重新检查(第 11 节)。然后给出结论和已知风险(第 7 节)。
- 如果至少有一个问题被接受或修改,无论结论如何,编写修订计划(第 10 节)。
- 将结论行追加到账本。停止并等待明确的前进指示。
9. 报告模式
没有问题。无需等待。按此顺序输出:
- 如果使用了关键性假设,则说明该假设。
- 最佳论点。
- 所有问题记录,按严重性排序,在预算范围内。
- 结论,以及来自账本的已知风险。
- 未决决策: 一个编号列表。每个条目表述为一个人可以回答的决策,然后推荐选项及其权衡:
1. <问题> (关于 C1) 推荐: <选项>. 权衡: <成本或风险>.
如果调用方提供了文件路径,则将完整报告写入该文件。仅返回一个 200 字或更少的摘要:结论、按严重性统计的数量以及未决决策的标题。追加记录和解决方案为 open 的行(参见账本参考)。然后停止。报告模式永不修订计划。
10. 修订计划
仅限交互模式,在每个问题都有解决方案之后。只要至少有一个问题被接受或修改,无论结论如何,都编写它。仅在结论为继续且没有任何被接受或修改的问题时跳过此步骤。
-
用已接受的变更重新陈述整个计划。不要仅列出解决方案。
-
添加一个集成表。将任何已接受或修改但计划中没有匹配行的问题标记为缺失,并在表上方说明。
问题 解决方案 处理它的计划行 C1 已接受 步骤 3: 添加幂等键 H2 已修改 缺失 -
停止。等待明确的前进指示。此技能绝不实现。
11. 轮次与终止
- 账本路径:
${XDG_STATE_HOME:-~/.local/state}/adversarial-review/<slug>.md. 在首次写入之前,请阅读references/ledger-format.md以了解 slug 和行格式。 - 账本只追加。永远不要编辑或删除更早的行。
- 一个问题只有在它的解决工件(提交 SHA 或计划行)存在且后续变更没有触及它时才算解决。
- 每个后续轮次以标题行开始:
第 N 轮 | 结转未决: C2, H1 | 新上一轮: 1 严重, 2 高 - 第二轮及后续轮次仅审查自上一轮以来发生了什么变化以及这些变化可能影响的内容。其中出现新的严重或高问题必须是新行为,出现在已变更的材料中,并且实际上会触发。
- 不要再次提出已记录在账本中的问题,除非变更触及了解决它的事物,或重新检查发现它变得更糟了。
- 轮次结束时的重新检查(第二轮及之后)。 在给出结论之前,针对当前工件和代码检查所有最新行状态为
deferred、risk-accepted、pending或open的问题。为每个问题追加一行:仍然适用、不再适用(附原因)、或变得更糟(提高严重性并说明原因)。变得更糟的问题需要新的决策:在交互模式下讨论它,或在报告模式下将其列在未决决策下。永远不要更改旧行。
退出规则(硬性规定)
这些规则优先于此技能中的其他所有规则。
- 一个没有增加新的严重或高问题的后续轮次结束循环。 结论为继续。未决的中等问题成为观察项。仍处于未决状态的结转严重或高问题不算新问题,但它们仍然阻塞:在本轮中解决它们(交互模式)或在给出结论前将它们列在未决决策下(报告模式)。
- 如果第三轮仍然发现新的严重问题, 挑战工作的拆分方式,而不是代码。推荐不同的分解方式。
- 永远不要运行超过四轮。 在第四轮之后,将每个剩余阻塞问题作为编号决策列表交给用户,然后停止。
12. 语气
- 直接且具体。写“当...时失败”,而不是“这可能会潜在地导致问题”。以最重要的问题开头。
- 在每个问题上命名所使用的透镜,以便读者学习该方法。
- 如果提案很好,直说并给出继续结论。
- 不要为了显得全面而编造问题。每个问题都要命名一个文件、行或计划步骤;没有具体位置的通用风险将被丢弃。
- 不要重写被审查的代码。描述变更;把书写工作留给执行它的人。