阅读材料: 应用部分 12. 生产 SDD 反模式:应用周期诊断图

模块「应用部分 12. 生产 SDD 反模式:应用周期诊断图」中第 1 / 5 节课
您正在未登录状态下查看课程。 请登录,以保存进度并参加测试。

应用篇 12. 生产 SDD 反模式:应用周期的诊断地图

状态:建议。 本篇汇集了恰恰出现在应用周期中的反模式:决斗、文件仲裁、Spec CI、分层预算、anti-Goodhart 指标以及自动修复。它们延续了第一卷第 20 篇的路线:制品存在,检查存在,代理运行迅速,但对系统的控制正在逐渐丧失。

本篇作为应用卷的诊断地图。如果生产回路变得嘈杂、矛盾,或以牺牲用户为代价保护自身速度,请从这里开始。

阅读前

  • 来自第一卷的支撑:第 20 篇展示了 SDD 的基本反模式。
  • 本地学习案例:来自第 8–11 章的任何已创建制品。
  • 用于 capstone/ 的痕迹:所选 high_memory_usage 包的 blocker / owner / next_check 三行。
  • 首读的主要术语:诊断阻塞项。各个反模式的名称仅供参考,无需连续阅读。
  • 可推迟的事:将每个反模式转化为自动 CI 策略。

目标

本章的目标不是记住一份名称清单,而是对已收集的生产 SDD 包进行一次简短的审计。本章结束后,你应该拥有三行诊断:什么阻塞了准入,谁负责修复,以及何时再次检查。

首读时,请将本章作为检查清单,而非所有可能故障的字典。下面的目录用于识别已发现的问题;可以用 blocker / owner / next_check 三行收尾。

第一卷反模式的升级

本章目录中的一部分反模式并非新出现的,而是第一卷第 20 篇中所述内容的生产版本。差别在于规模:在学习周期中,基础反模式会浪费一天的工作;在应用周期中,它会打开线上服务的一整类事件。

本章的反模式来自第一卷的升级
章程流于形式"无人打开的章程"(第一卷,第 20 篇)
制品中无 diff 的有毒规范"代码之后的规范"——打解释的补丁而非修改制品
红色 CI 后的 validation.md 漂移"错误后的事实弱化"(第一卷,第 20 篇)

| 无复审期限的影子规范 | "QWEN.md 沦为垃圾场"——没有 ttl 和作者的备忘 | | 无证据标记的痕迹 | "口头事实"——缺少 evidence_ref |

如果你已经学习了第一卷第 20 篇,这些条目可以有选择地阅读——这里只添加生产上下文。本章其余的 12 个反模式仅出现在应用周期中(决斗、仲裁、预算、anti-Goodhart、自动修复),在第一卷中不作讨论。

最小学习场景

学习案例

在最终考核前,需要检查一个生产 SDD 回路的噪声。从第 8–11 章中任选一个包:judgment.mdvalidation.mdbudget_network.yaml 或 readiness 表。目标是找出不少于三个反模式,或明确证明它们不存在。

准备

  • 下方的诊断检查清单。
  • book2/examples/templates/retrospective.md——简短记录输出的表单。
  • 一个已经通过可运行示例或手动学习场景的制品。

步骤

  1. 选择一个制品,不要扩大检查范围。期望:审计耗时 15–30 分钟,而非变成对整个项目的审查。
  1. 回答检查清单中的 12 个问题。*期望:每个答案为 yesnonot_applicable,并附简短的文件链接。*
  2. 对每个 no,指出反模式、所有者和修复期限。
  3. 在所选章节中至少找到一个 [project script],并检查它是否被标记为可运行类比或"自行实现"接口。
  4. 将结论记录到 antipattern-audit.md 或回顾中:什么阻塞了生产准入,什么可以作为改进保留。

检验事实

存在一个三项清单:blockerownernext_check。如果否定回答只被转化为笼统建议,则诊断地图未能完成其职能。

它如何进入 capstone/

blocker / owner / next_check 三行移入 capstone/antipattern-audit.md。不要在没有单独记录的情况下在同一文件中修复这些问题:对考核而言,重要的是看到诊断和下一次检查,而不是一份没有历史的漂亮总结。

最小片段:

| blocker | owner | next_check |
|---|---|---|
| readiness 缺少 `evidence_ref` | platform | 用 fixture 链接重做 dry-run |

| `[project script]` 没有可运行类比 | devex | 替换为 `examples/real-api` 或实现脚本 |
| 未指定 `manual_review_floor` | sre | 在 auto-mode 之前添加 guard 指标 |

可审查的痕迹

如果审计涉及学习包或 capstone/,请保留 antipattern-audit.md。不要在没有单独记录的情况下在同一变更中修复发现的问题:先看到诊断,然后才是修复。

关键思想

下面的每个反模式按相同的三字段模式分析:症状——在制品和日志中观察到的情况,为何有害——如何改变团队或代理的行为,如何修复——使症状可被自动捕获的最小步骤。

目录可以按任意顺序阅读:每个条目独立,仍遵循相同的三字段。这些条目并非互斥——它们是经常一起出现的不同噪声类别。如果在一个生产包中发现了三个或更多反模式,请将它们视为一个相互关联的问题网络,其共同根源在于丢失的风险契约。

示例与应用

章程流于形式

> 第一卷反模式的升级。 基础版本是第一卷第 20 篇中的"无人打开的章程"。在应用周期中,同一错误不会导致糟糕的代码,而是导致执行了危险的操作。

症状:仓库中存在带有 immutable_principlesmutable_rulesconstitution.md,但危险操作前的网关并未启动。在 judgment.md 中有对 forbid_unscoped_delete 规则的引用,在团队日志(logs/auto-remediation.jsonl)中没有一次调用 scripts/constitution/check.py。过去 30 天内,网关的触发次数为零。

为何有害:规则形式上存在,但在压力时刻并不约束代理。经历几次事件后,团队开始将章程视为装饰。在下一次事件的复盘会上会出现这样一句典型的话:"规则本来是有的,只是没人检查"——这是章程作为注释而非契约运作的信号。

如何修复:

  • 在执行 playbook 之前将 constitution.md 接入网关检查(参见第 3 篇);
  • 任何危险操作都需通过 scripts/constitution/check.py 或 CI 中的等价物;
  • judgment.md 中记录章程版本和 decision_hash 的引用;
  • 如果规则未被自动检查,则将其从 immutable_principles 移入 playbook,并明确标记为"指令,非网关";
  • 检查过去 30 天内是否至少有一条日志显示网关触发并阻止了某个操作。一个季度内零触发,要么是章程未接入,要么是它在描述不存在的风险。

ttl: ∞ 的可变规则

症状:mutable_rules 中存在没有 ttl 的规则,或 ttl 设为数年。rollback_condition 缺失,或被表述为"由团队决定"。

为何有害:规则无限期存活,并逐渐变成不变式的隐藏部分。一年后,参与者已不记得它为何出现,并害怕修改它。该规则的修正被类比地应用于原本未曾设想的情况。

如何修复:

  • 以天为单位设置 ttl,而非年;首次复审为 30–90 天(参见 INSTRUCTOR.md 中的参考答案);
  • rollback_condition 表述为可验证的谓词:repeat_incidents_same_node>=2silent_p0_ratio>0.05safety_veto=true
  • ttl 到期后,暂停该规则的适用,直至通过公投明确续期;
  • 删除在其整个生命周期内从未触发过的规则。

制品中无 diff 的有毒规范

> 第一卷反模式的升级。 基础版本是第一卷第 20 篇中的"代码之后的规范":解释在变,而制品未变。在反向任务(恢复规范)中,同样的错误表现为:补丁治标不治本。

症状:团队在有毒规范上训练规范恢复能力(参见第 2 篇),但补丁只修改了解释文本或注释。requirements.mdplan.mdvalidation.md 保持原样。

为何有害:练习不再教授定位根本原因。一周后,同一类有毒规范再次通过——补丁并未封堵根本原因。

如何修复:

  • 在课程的完成标准中要求至少在一个制品(requirements.mdplan.mdvalidation.mdconstitution.md)中产生 diff——而不仅仅在解释中;
  • 修复后进行完整的反向回放 Specify → Plan → Tasks → Implement
  • 如果补丁只修改了解释文本,则要求重做;
  • 将受控缺陷规范的类别登记到 precedents.md,以便后续类似缺陷可被自动捕获。

以谨慎为借口的 ask_storm

症状:代理在循环中不断提出澄清性问题而不转向解决方案。判定串:cycle_count > 0 && ask_storm >= 4 && escalation_path_resolved=falseask_storm——无新数据时重复澄清的计数器)。

为何有害:问题看似谨慎,但实际上是规范内部矛盾的信号。人类每次临时回答都添加了一个新的措辞,但该措辞未在任何地方固化,并在下一次 /clear 时消失。

如何修复:

  • 在连续三次澄清后停止会话,并检查 requirements.md 是否存在矛盾;
  • 将规范视为有毒的(第 2 篇)进行剖析——单一缺陷,查找根本原因;
  • 将回答固化在 requirements.mdclarifications.md 中,而非聊天里;
  • 不要将代理的提问变成持续对话:每次澄清要么关闭一个规范条目,要么回到规范修订。

无明确原因的 stage_regress

症状:implement 阶段返回到 planplan 阶段返回到 specify,但没有原因记录。第二天没人记得为何重写了计划。(stage_regress——无明确原因地回退到 SDD 循环的上一阶段。)

为何有害:SDD 循环变成漂移。每一次回退都会丢失前一步的上下文,一周后项目会有三份半成品的计划草案,没有一份在 validation.md 中被事实闭环。

如何修复:

  • 明确地记录阶段之间的转换:可审查的变更记录、genealogy.md 中的记录、原因;
  • 禁止在不更新 validation.md 中至少一个事实的情况下回退到上一阶段;
  • 使用项目技能,在 git status 时显示当前阶段及尚未闭环的事实;
  • 如果回退频率高于每天一次,这表明规范太少,而非流程在制造噪声。

阶段间的 phase_context_loss

症状:specify 确定了决策,plan 未能继承,implement 始于一份从未经过 validation.md 的草稿。(phase_context_loss——阶段之间上下文的丢失。)

为何有害:每一步都基于自己的世界图景运作。经过两三次转换后,它们分歧过大,制品互相矛盾,任何检查都能平凡通过——因为它检查的并非真正需要检查的内容。

如何修复:

  • 阶段之间只传递文件链接(@specs/...),而非聊天中的转述;
  • 引入项目技能 check_phase_handoff,检查计划是否引用了现行的 requirements.md,而实现是否引用了现行的计划;
  • /clear 后,开始新阶段时先阅读 QWEN.md、最新的 requirements.md 和当前的 plan.md
  • 如果一个阶段无法说明它实现了上一阶段的哪个条目,则在修改代码前应回到上一阶段。

验证者沦为普通的代码审查

症状:验证者写出诸如"风格不太好"、"最好重命名"、"我们讨论一下"之类的评论。没有具体的反例、规则引用或 JSON Schema 违规。

为何有害:决斗失去了程序性。验证者不再是正式回路,而只是另一种意见。实现者以自由文本回应,争论转移到聊天中,无法复现。

如何修复:

  • 禁止验证者在没有具体制品的情况下作出任何判断:带最小化条件的反例、hook 日志、JSON Schema、Given/When/Then;
  • 裁定结果应可在本地复现:另一个人基于相同的 cases/metrics/ 应得到相同的 judgment.md
  • 如果验证者未找到反例,则记录 verdict=APPROVE 并继续推进,而非以笼统措辞继续讨论;
  • 将风格性意见移至单独的审查通道,不要与决斗混在一起。

仅由多数票决定的文件仲裁

症状:governance_protocol 被描述为"3 人中 2 票赞成",没有 Safety 的 veto 和平局裁决机制。票数相同时,系统会卡住或根据召集日期作决定。

为何有害:Safety 角色失去意义。决定由验证者和实现者投票作出,他们都在优化速度;关键风险被当作"可接受"通过。

如何修复:

  • 为 Safety 角色引入 safety_veto: critical_risk
  • 设置 tie_breaker: safety_first_then_latest_matching_precedent
  • 由 Spec CI 网关检查 governance_protocol:缺少 tie-breaker 和 veto 将阻塞 merge;
  • 每一次因 Safety veto 而产生的偏离都应记录在 precedents.md 中,并附上对不可变规则的引用,以便类似争议更快闭环。

虚假的 [project script]

症状:在规范、检查清单或教学章节中使用了形如 python3 scripts/spec_ci/check_scope.py 的命令,但仓库中并不存在该脚本。无人运行过它,"检查通过"是隐含的,而非观察到的。

为何有害:产生一种虚假的安全感。CI 看起来很严格,但检查并未实际执行。几周后,团队会忘记哪些脚本是真实的,哪些只是接口。

如何修复:

  • 在每个 [project script] 块旁明确说明 examples/ 中是否存在可运行的类比,或这是"自行实现"的接口;
  • 在 Spec CI 中设置单独的步骤,检查 validation.md 中提到的命令是否真实存在(test -x path/to/script);
  • 教学章节中仅对能够通过本地 python3 scripts/... 的命令标记 [runnable]
  • 如果脚本需要但尚不存在,应创建一个具有明确实现日期的工单,而非留作"以后再说"。

没有配对反向指标的裸 KPI

症状:在 validation.md 中存在目标指标(MTTR<=5mcoverage>=80%auto_close_rate>=0.9),但没有配对的控制指标(guard 指标)。当 KPI 达成时,CI 网关通过。

为何有害:典型的古德哈特效应。代理或团队学会不惜代价达成指标:将复杂事件当作简单事件关闭、将 P0 标记为 P2、绕过人工审查。指标上升,实际质量下降。

如何修复:

  • 为每个目标指标配对一个 anti-Goodhart 指标(参见第 10 篇):与 MTTR 配对的是 silent_p0_ratiomanual_review_floor;与 coverage 配对的是 mutation_kill_rate
  • 仅当配对指标同时达成时,网关才放行;
  • 任何阈值的变更都是风险事件,而非 YAML 的修饰性修改;应附带依据加以记录;
  • 定期对历史事件进行重放:新版本不得在已分析案例的判定上出现退步。

红色 CI 后的 validation.md 漂移

症状:CI 失败后,拉取请求的作者修改了 validation.md 中的阈值或删除了某个事实,而非修改代码。变更说明为"完善了验证"。

为何有害:流程开始保护实现,而非用户契约。这与第一卷第 20 篇中"错误后的事实弱化"是同一错误,只是规模更大:一次拉取请求就将 silent_p0 阈值从默认值 0.05(AgentClinic 基线,参见附录 D.4)放宽到 0.10,移位了整类风险。

如何修复:

  • 任何放宽检查的 validation.md 修改都应作为风险契约的变更单独审查;
  • 在变更说明中记录原因:事件标识符、事后复盘链接、预期效果;
  • 禁止在未记录到 precedents.md 的情况下删除必备事实;
  • 如果一个季度内阈值变更超过两次,这是目标与检查脱节的信号。

没有预算的层级切换

症状:当 local-coder 失效时,所有流量自动转至 frontier-reviewerbudget_keeper(预算守护者)未配置或不阻止超额。

为何有害:昂贵的层级在数分钟内消耗掉一整天的配额,当真正的 P0/P1 出现时,已无力应对。故障转移(failover)反而成为二次事件的根源。

如何修复:

  • 将切换描述为有优先级的,而非全量的(参见第 9 篇);
  • 仅将 severity in [P0, P1]age > N 的任务送入 frontier-reviewer
  • 其余任务进入降级队列,超时后转入手动通道;
  • 紧急模式根据 token_health 触发,并将系统切换到受保护模式,直至 local-coder 恢复。

无复审期限的影子规范

> 第一卷反模式的升级。 基础版本是第一卷第 20 篇中的"QWEN.md 沦为垃圾场"。在学习周期中,问题是上下文不断膨胀;在应用周期中,问题是无作者的启发式获得了契约的效力。

症状:QWEN.md 包含一个样本提示(few-shot)或启发式,不知怎么就被加进来了。作者不记得是谁、什么时候添加的。条目没有 ttl、证据或评估链接。

为何有害:启发式在没有复审程序的情况下获得了契约的效力。它无法被质疑(没人记得作者),也无法被精确验证(没有来源)。半年后,规则被类比地应用于原本未曾设想的情况。

如何修复:

  • QWEN.md 中的任何启发式都应附上最小化的元数据头:作者、日期、证据、ttl、拍卖链接(参见第 6 篇);
  • ttl 到期后,要么更新,要么送入隔离区并记录原因;
  • 在过去 50 起事件中未起作用的样本提示视为删除候选;
  • 影子规范不替代已批准的需求——它仅在歧义情况下引导 prompt。

没有最低人工检查的自动修复

症状:代理根据指标自动关闭事件。manual_review_floor 未设置或为零。

为何有害:即使指标看起来很干净,代理也会逐渐将人挤出回路。当出现模型未见过的某类事件时,没有备用机制来察觉偏差。几周后,安静的故障会积累起来,因为无人捕获。

如何修复:

  • 明确设置 manual_review_floor:例如,"无论指标如何,至少 15% 的事件需经过人工";
  • 轮换应随机选取,而非按"把最复杂的留给人"的原则——否则人工审查看不到基线水平;
  • 人工审查的结果进入下一轮验证器运行的重放数据集;
  • 任何 manual_review_floor 的降低都作为风险契约的变更处理,而非作为优化处理。

25/25 的就绪度作为目标而非描述

症状:团队将就绪度模型的所有 25 个条目都拉到绿色,因为"必须发布"。其中部分条目是预先标绿的,没有真实的证据标记。

为何有害:就绪度作为早期信号失去了意义。下一次发布时又是"25/25",但事件又回来了。该量表变成了一种仪式。

如何修复:

  • 通过 evidence_ref 检查就绪度,而非通过文本声明;
  • 23/25 配以真实证据即准予准入;25/25 但其中两项无证据则不予准入;
  • 在条目未达成时,明确记录风险和回滚条件,而非"涂成绿色";
  • 定期以反向方式运行就绪度:哪些条目触发并捕获了真实问题,哪些条目在一个季度内从未触发——后者是复审候选。

缺乏更新的谱系

症状:章程的 genealogy.mdchange_log 存在,但最后一条记录的日期是三个月前。其间规则已经变更了五次。

为何有害:出处不再作为证据链运作。半年后将无法还原"代理为何有权执行该操作",事件后的争论就会退化为泛泛而谈。

如何修复:

  • change_log 中的记录是章程每次修订的强制部分,没有它,网关不通过 merge;
  • parent_version 必填;版本号缺失将触发单独审查;
  • decision_hash 由决策内容自动计算,以防静默替换;
  • 每月进行一次简短审计:将 change_log 与文件的实际修改比对。不一致被记录为流程事件。

无证据标记的痕迹

> 第一卷反模式的升级。 基础版本是第一卷第 20 篇中的"口头事实"。在学习周期中,因为特性很小,所以不需要痕迹。在应用周期中,没有 evidence_ref 就无法还原某个动作是基于什么依据执行的。

症状:代理保存了动作日志,但记录中没有对源制品的引用:未指明使用的是哪一版规范、章程的哪些规则、哪一份 prompt。事件后无法还原决策的上下文。

为何有害:audit_trace_coverage(审计轨迹覆盖率)形式上接近 100%,但痕迹毫无用处。这与"无人运行 validation.md"是同一种错误,只是发生在审计层面。

如何修复:

  • 每条痕迹记录都必须包含 spec_versionconstitution_versionprompt_hashdecision_sourceevidence_ref
  • Spec CI 检查字段的完整性,如有任何字段为空则阻塞 merge;
  • evidence_ref 是制品内的路径和标识符(如 logs/node-2026-05-12.parquet#row_4123),而非对目录的一般性引用;
  • 任何 evidence_ref=null 的记录在审计中视为无效。

诊断检查清单

如果应用 SDD 回路变得嘈杂或无法捕获回归,请回答:

  1. constitution.md 是否在执行前作为网关触发,而不仅仅在事后作为审查?
  2. mutable_rules 中是否存在没有 ttlttl 超过 90 天的规则?
  3. 在有毒规范失败后,是否至少有一个制品(requirements.mdplan.mdvalidation.md)被修改?
  4. 验证者是否使用反例、hook 日志或 JSON Schema——还是仅使用自由文本?
  5. governance_protocol 中是否有 Safety 的 veto 和确定性的 tie-breaker?
  6. 仓库中可运行的命令是否与 [project script] 接口分开标记?
  7. 每个目标指标是否都配有 anti-Goodhart 指标?
  8. CI 失败时,是在修复代码还是在放宽 validation.md
  9. 层级切换是否有预算上限和紧急模式?
  10. QWEN.md 中的每条记录是否都有作者、证据和 ttl
  11. manual_review_floor 是否独立于 KPI 的值而被保留?
  12. 每条痕迹记录中的 evidence_ref 是否都已填写?

如果有三个或以上的问题回答为否,请勿新增自动化层:文件仲裁、层级路由、新的紧急模式规则。首先消除噪声并修补当前回路中的漏洞。

总结

应用周期的反模式单独看并非灾难。危险的是它们的累积:经过几次发布后,团队在"绿色 CI"背后看不到风险契约。诊断地图是修复的第一步。每个否定回答都会转化为项目技能、Spec CI 网关,或带有可验证 rollback_condition 的章程规则。在每次重大事件后,请回到本章:同一制品在三个月后会显示出另外三个阻塞项。

第一卷的相关篇章

  • 第一卷第 20 篇——SDD 基本反模式:代码之后的规范、巨型 requirements.md、仪式化的 /clearQWEN.md 沦为垃圾场。
  • 第一卷第 18 篇——同时也是安全威胁的反模式。
  • 第 2 篇——将有毒规范作为对抗本章大多数反模式的训练工具。
  • 第 10 篇——将 anti-Goodhart 作为对裸 KPI 的防护。

制品与就绪标准

制品就绪条件
antipattern-audit.md(或回顾)三个字段已填写:blockerownernext_check;每个发现的反模式都有所有者和下一步可验证动作
检查清单 12 个问题的答案已针对所选的一个制品完成;每个否定回答都对应一个计划
阻塞项与改进项的分离审计不会在没有单独诊断记录的情况下,在同一变更中修复问题

完整轨道将更新的诊断检查清单加入 [appendix-c-checklists.md](appendix-c-checklists.md),将每个遇到过的反模式记录到 precedents.md,对反复出现的反模式补充到 QWEN.md,并至少对其中一个进行 Spec CI 检查。判定其就绪的条件是:Spec CI 中至少存在一项能自动捕获反模式的检查(例如无 ttlmutable_rules),而反复出现的反模式仅在附带证据和复审期限时才会被记入 precedents.mdQWEN.md

实践

  1. 打开团队当前的 constitution.md,检查 mutable_rules 中是否存在 ttlrollback_condition。至少找出一条需要更新或送入隔离区的规则。*期望:antipattern-audit.md 中出现针对该具体规则的 blocker / owner / next_check 一行;ttl 以天为单位,而非年。*
  2. 取最近一个修改 validation.md 的拉取请求。判断修改的是阈值还是事实内容。如果是阈值,检查变更说明中是否包含事后复盘链接或事件标识符。*期望:该拉取请求被记录为两种结果之一——要么是附带事件链接的、有依据的风险契约变更,要么是"红色 CI 后 validation.md 漂移"反模式,并附有所有者和回滚期限。*
  3. 在所选章节中遍历 [project script] 块列表,并核对哪些命令是真实的、哪些只是接口。在该章的 README 中补充相应标记。*期望:每个 [project script] 都明确标注"examples/... 中存在可运行类比"或"自行实现";没有未标记的块。*

检验问题

  1. 为什么带 ttl: ∞ 的可变规则比根本没有表述的规则更危险?
  2. ask_storm 与善意的澄清问题有何区别,如何辨别二者?
  3. 哪三个字段使痕迹记录可用于审计,为什么在缺少它们的情况下 audit_trace_coverage=100% 是一种古德哈特指标?
  4. 在审查拉取请求时,你看到作者将 silent_p0 阈值从 0.05 改为 0.10,并添加了"临时性调整,待稳定"的注释。你将如何处理该拉取请求?在合并此类变更前,必须满足哪三个条件?
我的笔记
0 / 10000

笔记保存在当前浏览器中。在其他设备上将不会显示。

课程菜单

课程

在 Qwen Code CLI 开发中使用 SDD。应用课程
进度 0 / 95