应用部分 12. 生产环境 SDD 反模式:应用周期诊断卡
状态:建议。 本部分收集在应用周期中出现的反模式:对质、文件仲裁、Spec CI、层级预算、反古德哈特指标和自动修复。它们延续了第一卷第20部分的思路:有工件、有检查、智能体运行很快,但对系统的控制逐渐流失。
本部分作为应用卷的诊断卡。如果生产环境变得嘈杂、矛盾或以牺牲用户为代价维护自身速度,请从这里开始。
阅读前
- 第一卷的铺垫:第20部分展示基础 SDD 反模式。
- 本地学习案例:第8-11章中已创建的任何工件。
capstone/的跟踪记录:为选定的high_memory_usage包填写三行blocker / owner / next_check。- 第一遍的主要术语:诊断阻塞项。单个反模式的名称仅供参考,无需按顺序阅读。
- 可推迟的事项:将每个反模式转化为自动 CI 策略。
目标
本章的目标不是背下名称列表,而是对已有的生产环境 SDD 包进行简短审计。阅读后,你应该有三条诊断记录:什么阻碍了准入、谁负责修复、何时再次检查。
第一遍请将本章作为检查清单阅读,而非所有可能故障的词典。下面的目录用于识别发现的问题;用三行 blocker / owner / next_check 即可结束本章。
第一卷反模式的升级
本目录中的部分反模式并非全新,而是第一卷第20部分所描述反模式的生产环境变体。区别在于规模:在学习周期中,基础反模式消耗一天工作量;在应用周期中,它会在实时服务上引发一类事件。
| 本章反模式 | 第一卷升级来源 |
|---|---|
| 宪法作为装饰 | 「无人打开的宪法」(卷1,第20部分) |
| 无工件差异的毒性规范 | 「代码后的规范」——用解释补丁代替工件修正 |
| 红色 CI 后 validation.md 漂移 | 「错误后弱化事实」(卷1,第20部分) |
| 无审查期限的影子规范 | 「QWEN.md 作为垃圾场」——无 ttl 和作者的备忘录 | | 无证据标记的跟踪记录 | 「口头事实」——缺少 evidence_ref |
如果你已完成第一卷第20部分,这些记录可以有选择地阅读——此处仅添加生产环境上下文。本章其余12个反模式仅在应用周期(对质、仲裁、预算、反古德哈特、自动修复)中出现,第一卷未涉及。
最小学习场景
学习案例
在期末考试前,需要检查一个生产环境 SDD 回路是否嘈杂。从第8-11章中选择任意包:judgment.md、validation.md、budget_network.yaml 或就绪性表。目标是找到至少三个反模式,或明确证明不存在。
准备
- 下面的诊断检查清单。
book2/examples/templates/retrospective.md——用于简短记录结论的表格。- 一个已经通过可运行示例或手动学习场景的工件。
步骤
- 选择一个工件,不要扩大检查范围。预期:审计耗时15-30分钟,而非变成整个项目的评审。
- 回答检查清单的12个问题。*预期:每个答案为
yes、no或not_applicable,并附简短文件引用。* - 对每个
no指出反模式、负责人和修复期限。 - 在选定章节中找到至少一个
[project script],检查它是否标记为可运行示例或「自行实现」接口。 - 将结论记录到
antipattern-audit.md或回顾中:什么阻碍生产准入,什么可作为改进保留。
控制事实
有一个三项目列表:blocker、owner、next_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 | 在自动模式前添加防护指标 |
可评审的跟踪记录
如果审计涉及学习包或 capstone/,请保留 antipattern-audit.md。不要在同一变更中修复发现的问题而不单独记录:首先必须可见诊断,然后才是治疗。
核心思想
下面每个反模式按三个字段的同一结构解析:症状——在工件和日志中观察到什么,为何有害——这如何改变团队或智能体的行为,如何修复——到症状可被自动捕获状态的最小步骤。
目录可按任意顺序阅读:每条记录独立,保持相同的三个字段。记录之间不是互斥的——它们是不同类别的噪音,经常同时出现。如果在一个生产包中发现三个及以上反模式,请将它们视为共同根源在于风险合同丢失的连锁问题网络来阅读。
示例与应用
宪法作为装饰
> 第一卷反模式升级。 基础版本——「无人打开的宪法」来自第一卷第20部分。在应用周期中,同样的错误不会导致糟糕的代码,而是导致执行了危险操作。
症状:仓库中有带 immutable_principles 和 mutable_rules 的 constitution.md,但危险操作前的网关未启动。judgment.md 中有规则 forbid_unscoped_delete 的引用,但团队日志(logs/auto-remediation.jsonl)中没有一次调用 scripts/constitution/check.py 的记录。最近30天——网关触发次数为零。
为何有害:规则形式上存在,但在压力时刻不限制智能体。经过几次事件后,团队开始将宪法视为装饰。在下次事件复盘时会出现标志性说法:「规则是有的,只是没人检查」——这是信号,表明宪法作为注释而非合同运作。
如何修复:
- 在执行剧本前将
constitution.md连接到网关检查(参见第3部分); - 任何危险操作都通过
scripts/constitution/check.py或 CI 中的等效检查;
- 在
judgment.md中固定宪法版本和decision_hash的引用; - 如果规则未自动检查,将其从
immutable_principles移至剧本,并明确标记为「指令,非网关」; - 检查最近30天是否至少有一条网关触发并阻止操作的日志。季度零触发——要么宪法未连接,要么描述了不存在的风险。
带 ttl: ∞ 的可变规则
症状:mutable_rules 中有无 ttl 的规则,或 ttl 直接设为多年。rollback_condition 缺失或表述为「由团队决定」。
为何有害:规则无限期存在,随时间变成隐藏的不变量部分。一年后参与者不记得它为何出现,不敢触碰。修正案被类比应用于未设想的情况。
如何修复:
- 以天而非年设置
ttl;首次复查为30-90天(参见INSTRUCTOR.md中的标准答案); - 将
rollback_condition表述为可验证的谓词:repeat_incidents_same_node>=2、silent_p0_ratio>0.05、safety_veto=true;
ttl到期后阻止规则应用,直至通过公投明确延期;- 删除在生命周期内从未触发过的规则。
无工件差异的毒性规范
> 第一卷反模式升级。 基础版本——「代码后的规范」来自第一卷第20部分:解释改变,工件不变。此处同一错误在反向任务(规范恢复)中显现——补丁治疗的是注释而非根本原因。
症状:团队在毒性规范上训练规范恢复(参见第2部分),但补丁只改变解释文本或注释。requirements.md、plan.md、validation.md 保持不变。
为何有害:练习不再教授原因定位。一周后同一类毒性规范再次通过——补丁未关闭根本原因。
如何修复:
- 在课程的完成标准中要求至少一个工件(
requirements.md、plan.md、validation.md、constitution.md)有差异——不仅仅是解释; - 修正后进行完整的反向运行
Specify → Plan → Tasks → Implement;
- 如果补丁仅改变解释文本,打回重做;
- 在
precedents.md中注册受控缺陷规范类别,以便下次类似缺陷自动捕获。
伪装成谨慎的 ask_storm
症状:智能体在循环中提出澄清问题而不进入解决。控制字符串:cycle_count > 0 && ask_storm >= 4 && escalation_path_resolved=false(ask_storm——无新信息的重复澄清计数器)。
为何有害:问题看似谨慎,但实为规范内部矛盾的信号。每个人的现场回答添加无处固定的新表述,下次 /clear 后消失。
如何修复:
- 连续第三次澄清后停止会话,检查
requirements.md的矛盾; - 将规范作为毒性规范解析(第2部分)——一个缺陷,寻找根本原因;
- 回答不固定在聊天中,而是固定在
requirements.md或clarifications.md; - 不要将智能体的问题变成持续对话:每个澄清要么关闭规范项,要么返回修正规范。
无明确原因的 stage_regress
症状:implement 阶段返回 plan,plan 返回 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 否决权和决胜机制。平局时系统挂起或按召集日期决定。
为何有害:Safety 角色失去意义。决策由优化速度的验证者和实现者投票通过;关键风险被接受为「可接受」。
如何修复:
- 为 Safety 角色引入
safety_veto: critical_risk; - 设置
tie_breaker: safety_first_then_latest_matching_precedent; - 用 Spec CI 网关检查
governance_protocol:缺少决胜机制和否决权阻止合并;
- Safety 的每次否决驳回固定在
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<=5m、coverage>=80%、auto_close_rate>=0.9),但无配对控制指标(防护指标)。KPI 满足时 CI 网关通过。
为何有害:经典古德哈特。智能体或团队学会不惜一切代价满足指标:将复杂事件标记为简单、将 P0 标记为 P2、绕过人工评审。指标上升,实际质量下降。
如何修复:
- 每个目标指标配对反古德哈特指标(参见第10部分):
MTTR配silent_p0_ratio和manual_review_floor;coverage配mutation_kill_rate; - 仅当配对同时满足时网关通过;
- 任何阈值变更都是风险事件,而非 YAML 的 cosmetic 修正;需记录理由;
- 定期对历史事件进行重放:新版本不应恶化已分析案例的判决。
红色 CI 后 validation.md 漂移
症状:CI 失败后,PR 作者改变 validation.md 中的阈值或删除事实,而非修正代码。变更描述为「澄清验证」。
为何有害:流程开始保护实现而非用户合同。这与第一卷第20部分的「错误后弱化事实」是同一错误,但在应用规模:一次 PR 中将 silent_p0 阈值从默认值0.05(AgentClinic 基线,参见附录 D.4)提高到0.10,会推移整个风险类别。
如何修复:
- 任何弱化检查的
validation.md修正单独作为风险合同变更评审; - 变更描述中固定原因:事件标识符、复盘链接、预期效果;
- 禁止无
precedents.md记录的强制事实删除; - 如果最近季度阈值变更超过两次——这是目标和检查各自为政的信号。
无预算的层级切换
症状:local-coder 故障时全部流量自动转入 frontier-reviewer。budget_keeper(预算守护者)未配置或不阻止超额。
为何有害:昂贵层级在数分钟内消耗日配额,失去在真实 P0/P1 到来时的服务能力。故障切换变成次生事件来源。
如何修复:
- 将切换描述为分级而非全量(参见第9部分);
- 仅向
frontier-reviewer发送severity in [P0, P1]且age > N的任务; - 其余进入降级队列,超时后进入人工通道;
- 紧急模式由
token_health触发,在local-coder恢复前转入保护模式。
无审查期限的影子规范
> 第一卷反模式升级。 基础版本——「QWEN.md 作为垃圾场」来自第一卷第20部分。在学习周期问题是增长的上下文;在应用周期是无作者启发式获得合同效力。
症状:QWEN.md 包含 somehow「自然而然」进入的少样本示例或启发式。作者不记得谁何时添加。记录无 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.md 或宪法 change_log 存在,但最后记录日期为三个月前。 meanwhile 五条规则已变更。
为何有害:出处不再作为证据链运作。半年后无法恢复「智能体为何有权执行此操作」,事件后争论沦为泛泛讨论。
如何修复:
change_log记录是每次宪法修正的强制部分,无记录网关不通过合并;parent_version强制要求;跳过版本是单独评审的理由;decision_hash自动计算自决策内容,使静默替换无法通过;- 每月——简短审计:
change_log与实际文件修正的核对。差异记录为流程事件。
无证据标记的跟踪记录
> 第一卷反模式升级。 基础版本——「口头事实」来自第一卷第20部分。在学习周期无需跟踪,因为功能很小。在应用周期无 evidence_ref 无法恢复操作依据。
症状:智能体保存操作日志,但记录无原始工件引用:应用了哪个规范版本、哪些宪法规则、哪个 prompt。事件后无法恢复决策上下文。
为何有害:audit_trace_coverage(审计跟踪覆盖率)形式上接近100%,但跟踪无用。这与无人运行但存在的 validation.md 是同一错误,只是在审计层面。
如何修复:
- 每条跟踪记录强制要求
spec_version、constitution_version、prompt_hash、decision_source、evidence_ref; - Spec CI 检查字段完整性,任一为空则阻止合并;
evidence_ref是工件内的路径和标识符(logs/node-2026-05-12.parquet#row_4123),非目录通用链接;- 任何
evidence_ref=null的记录视为审计无效。
诊断检查清单
如果应用 SDD 回路变得嘈杂或停止捕捉回归,请回答:
constitution.md是否在执行前作为网关触发,而非仅作为事后评审?mutable_rules中是否有无ttl或ttl超过90天的规则?- 毒性规范失败后是否至少变更一个工件(
requirements.md、plan.md、validation.md)? - 验证者是否使用反例、hook 日志或 JSON Schema——还是仅自由文本?
governance_protocol中是否有 Safety 否决权和确定性决胜机制?- 仓库中可运行命令是否与
[project script]接口分开标记? - 每个目标指标是否有配对反古德哈特指标?
- CI 失败时修复代码还是弱化
validation.md? - 层级切换是否有预算上限和紧急模式?
QWEN.md每条记录是否有作者、证据和ttl?manual_review_floor是否独立于 KPI 值保留?- 每条跟踪记录是否填写
evidence_ref?
如果三个及以上问题回答为否定——不要添加新的自动化层:文件仲裁、层级路由、新的紧急模式规则。先消除噪音,关闭当前回路的漏洞。
总结
应用周期的反模式单独来看并非灾难性。危险在于积累:经过几个发布周期,团队在「绿色 CI」后面看不到风险合同。诊断卡是修复的第一步。每个否定回答转化为项目技能、Spec CI 网关或带可验证 rollback_condition 的宪法规则。每次重大事件后回到本章:同一工件三个月后显示的是另外三个阻塞项。
第一卷相关部分
- 第一卷第20部分——基础 SDD 反模式:代码后的规范、巨型
requirements.md、仪式性/clear、QWEN.md作为垃圾场。 - 第一卷第18部分——同时构成安全威胁的反模式。
- 第2部分——毒性规范作为对抗本章大多数反模式的训练工具。
- 第10部分——反古德哈特作为裸 KPI 的防护。
工件与就绪标准
| 工件 | 就绪标准 |
|---|---|
antipattern-audit.md(或回顾) | 三字段填写:blocker、owner、next_check;每个发现的反模式有负责人和下次可检查步骤 |
| 12个检查清单问题的回答 | 针对一个选定工件完成;每个否定回答有计划 |
| 阻塞项与改进项的分离 | 审计不在同一变更中修复问题而不单独记录诊断 |
完整跟踪将更新的诊断检查清单加入 [appendix-c-checklists.md](appendix-c-checklists.md),每个遇到的反模式记入 precedents.md,重复出现的补充到 QWEN.md,并至少对其中一个进行 Spec CI 检查。当 Spec CI 中至少有一个自动捕获反模式的检查(例如无 ttl 的 mutable_rules),且重复出现的反模式仅在有证据和复查期限时进入 precedents.md 或 QWEN.md,视为就绪。
实践
- 打开团队当前
constitution.md,检查mutable_rules的ttl和rollback_condition。找到至少一条需要更新或送入隔离的规则。*预期:antipattern-audit.md中出现具体规则的一行blocker / owner / next_check;ttl 期限以天计,非年。* - 取最近修改
validation.md的 PR。确定变更的是阈值还是事实内容。如果是阈值,检查变更描述中是否有复盘链接或事件标识符。预期:PR 固定两种结果之一——要么是有事件引用的风险合同变更理由,要么是「红色 CI 后 validation.md 漂移」反模式,有负责人和回退期限。 - 遍历选定章节中的
[project script]块列表,核对哪些命令真实,哪些是接口。补充章节 README 标记。*预期:每个[project script]明确标注「examples/...有可运行示例」或「自行实现」;无未标记块。*
控制问题
- 为什么
ttl: ∞的可变规则比完全无表述的规则更危险? ask_storm与善意澄清有何区别,如何区分?- 哪三个字段使跟踪记录适合审计,为什么无它们的
audit_trace_coverage=100%是古德哈特指标? - 评审 PR 时你看到作者将
silent_p0阈值从0.05改为0.10并附评「临时,至稳定」。你会如何处理此 PR,此类变更合并前需满足哪三个条件?