阅读材料: 应用部分 6. 阴影规范的选择

模块「应用部分 6. 阴影规范的选择」中第 1 / 5 节课
您正在未登录状态下查看课程。 请登录,以保存进度并参加测试。

应用部分 6. 影子规范的筛选

状态:前沿。 这种做法——将非形式化的启发式提取到独立层中,并限制其少量示例槽位预算——已被采用。但评分公式和接受阈值需要针对具体项目进行校准。"不替换主规范"这一理念是一项建议。

对于教学性学习而言,运行 examples/shadow-auction/ 并观察为何一条启发式被收入 QWEN.md,而另一条则进入隔离区,已经足够。在 50+ 起事故上进行权重校准则属于完整的生产轨道。

我们引入几个关键概念。影子规范(shadow specs)——来自运维实践的可验证启发式。它们在分诊阶段有帮助,但不是系统的强制要求。少样本示例(few-shot)——提示中的简短示例,向智能体展示在类似案例上期望的响应格式。评分日志(scorebook)——影子规范的经济性日志:原始数据(seed)、评分公式、阈值、预算(budget)、候选版本以及决策协议。

当我们在一卷第 6 部分 第一卷第 6 部分 中整理 mission.md 时,参与者还留有一些未达到要求层级的愿望。以下是典型例子:

  • "夜间回答更简短",
  • "不要用 emergency 一词惊吓患者",
  • "复发性症状出现时立即请求病史"。

本章回答了当时搁置的问题——在生产环境中如何处理这些愿望。它们流向何处,如何证明自身价值,何时可以移除。最终进入 QWEN.md 的少样本示例,与一卷第 19 部分 第一卷第 19 部分 中的智能体记忆是同一种东西,但具有明确的生存时间(ttl)和接受竞标。

阅读前

  • 来自一卷的支撑:第 6 部分说明愿望不等于要求;第 19 部分将记忆与规范分离。
  • 本地教学案例:竞标 shadow.p0.voice_handoff 对抗关于仪表盘颜色的嘈杂启发式。
  • 留给 capstone/ 的痕迹:简短的 Shadow notes 块,针对 high_memory_usage 包含一条被接受和一条被拒绝的候选。
  • 第一遍的核心术语:影子规范和评分日志(scorebook)。竞标、少样本示例、隔离——供参考。
  • 需推迟的事项:从 50+ 起事故中收集候选,校准权重以及 QWEN.md 的自动更新。

目标

在本章中,您将把事故管理中的非形式化观察转化为具有可衡量价值的可验证影子规范层。这里的"竞标"一词指的是在受限的上下文预算下进行排序筛选,而非独立的产品或强制性的外部服务。哪些观察会进入此处:

  • 沟通语气,
  • 直觉性的前提,
  • 环境信号,
  • 资深工程师的"魔法"决策。

目标不是替换形式化规范。目标是将有用的启发式与运维传说(folklore)区分开来。最终您将能够:

  • 启动影子规范竞标(即在受限上下文预算下进行启发式的评分和筛选);
  • 基于历史事故为每个细微之处赋予预测价值;
  • QWEN.md 中仅保留那些真正提升 Qwen Code 质量的少样本示例。

最小教学场景

教学案例

需要决定启发式 shadow.p0.voice_handoff 是否进入 QWEN.md,而关于仪表盘红色的嘈杂启发式是否进入隔离区。目标是看到非形式化观察会经过评分和预算两道关卡,而非凭借权威成为要求。

准备

  • book2/examples/shadow-auction/candidates/candidates.yaml
  • book2/examples/shadow-auction/data/incidents.jsonl
  • 脚本 score.pydecide.pywrite_qwen_block.py

步骤

  1. cd book2/examples/shadow-auction预期:您位于可运行示例的目录中。
  2. python3 scripts/score.py --candidates candidates/candidates.yaml --incidents data/incidents.jsonl --weights 0.5,0.3,0.2,0.4 --out out/scorebook.json预期:已生成包含评分组件的评分日志。
  3. python3 scripts/decide.py --scorebook out/scorebook.json --budget-tokens 2000 --keep-threshold 0.70 --reject-threshold 0.40 --out-auction out/auction.json --out-quarantine out/quarantine.json。*预期:部分候选获得 winner 状态,部分进入隔离区(quarantine)。*
  1. python3 scripts/write_qwen_block.py --auction out/auction.json --target-anchor "QWEN.md#incident-triage-shadow" --today 2026-05-17 --out out/qwen_block.md。*预期:QWEN.md 的块仅包含胜出者和决策来源链接;在教学日期下它与 outputs/qwen_block.example.md 一致。*
  2. 比较 out/auction.jsonout/quarantine.json预期:落选候选并未消失,而是获得了拒绝原因。

验证事实

胜出者并未成为强制要求。它被格式化为带有 source_ref、score 和复审期限的版本化少样本示例。低于阈值的候选位于隔离区,并附有原因。

它如何进入 capstone/

将简短的 Shadow notes 章节移入 capstone/README.md:包含一个胜出者和一个被拒绝的候选、id、score、保留/拒绝原因及复审期限。请勿将胜出者添加到 requirements.md:在评分包中它仍然是影子提示,而非已批准的要求。

最小片段:

shadow_notes:
  keep:
    id: shadow.p0.voice_handoff.v1
    score: 0.727
    ttl: "14d"
    reason: "early signal for manual handoff"
  reject:

id: shadow.alert.red_color_urgency
    reason: "false escalation risk"

可评审的痕迹

教学包中不需要 out/。对于评分而言,在 QWEN.mdcapstone/README.md 中保留带竞标准则链接的简短摘录已经足够。

核心思想

通过将观察转换为影子规范格式来启动规范化:上下文 → 特征 → 可观察效应。字段如下:

  • 上下文 定义适用范围。例如,"具有级联到 appointments-api 风险的 P0 事故"。
  • 特征 固定可观察的细节。例如,"值班人员用简短命令式消息书写并跳过标准模板"。
  • 效应 描述可验证的后果。例如,"5–10 分钟后出现手动绕过(bypass)或紧急回滚(rollback)"。

这种格式并不会使细微之处成为完全形式化的合约。但它将其转化为一个可与事故历史进行比较的槽位。附加的 evidencescoperisksource_ref 字段是必要的,以便 Qwen Code 不会从自由文本中猜测启发式的含义。

在您的项目中,候选的收集由一对脚本 harvest.py + normalize.py 完成:前者从访谈、复盘和事故中提取摘录到 .specify/memory/shadow-candidates.raw.ndjson,后者按模板 上下文 → 特征 → 效应 将其展开为 .specify/memory/shadow-candidates.yaml。教材中没有此阶段的可运行类比;它取决于您的来源存放位置。评分和竞标本身的可运行类比位于 examples/shadow-auction/README.md

在规范化之后,每个候选槽位都按三组指标在历史事故上评分:

  • 对 MTTR 的影响,
  • 误升级比例,
  • 提前预警级联的能力。

评分沿三个轴构建。

MTTR 衡量启发式是否帮助更快地采取正确行动。但仅靠此指标是危险的。一条规则可能加速个别案例,同时在分诊阶段制造噪声。

误升级捕捉误触发的代价。尤其是当影子规范在没有充分依据的情况下将 P2 提升为 P1 时。

关于级联的早期预警衡量该特征是否出现在标准告警之前。而不是在形式化系统已经记录到问题之后。

将最终评分记为可复现的公式,而不是"看起来有用"这种专家判断。例如,对于教学回路,使用 score = 0.5*mttr_gain + 0.3*early_signal + 0.2*coverage - 0.4*false_escalation。其中 coverage 限制了过于狭窄的规则,而 false_escalation 对嘈杂的启发式进行惩罚。

该公式中的权重是起始校准,而非法律。正权重的总和被选为单位(0.5+0.3+0.2),以使最终 score 落在区间 [-0.4; 1] 内,并可读作"有用信号的比例"。在该单位内部,比例 0.5 / 0.3 / 0.2 反映了 AgentClinic-production 的教学优先级:减少 MTTR 是主要可衡量效果,早期信号仅在与 MTTR 的缩减挂钩时才有价值,而覆盖范围只是对过于狭窄规则的保险。误升级的惩罚系数(0.4)被选择为:一次误升级消耗了一次理想 MTTR 缩减约 80% 的有益效果(0.4 / 0.5 = 0.8):一个启发式若在一次理想 MTTR 缩减(mttr_gain=1)的同时产生一次误升级(false_escalation=1),几乎失去全部最终 score(0.5 - 0.4 = 0.1),不会进入最终交付。如何进一步校准:

  • 如果您团队的错误代价更高——将惩罚提高到 0.6–0.8
  • 如果早期预警更重要——以 mttr_gain 为代价增加 early_signal

校准后,在 50+ 起历史事故上运行该公式。将胜出者与团队当前的决策方式进行对比。如果差异过大,则权重是根据别人的风险状况校准的。

使用足够多的历史案例,以免罕见的级联从评分中消失。对于严肃的决策,使用 50+ 起事故:这是下限,低于此值时,罕见的级联类别(频率约为 1/25 起事故)在样本中至少出现两次,early_signal 才能与随机巧合区分开。较少的集合仅用于冒烟(smoke)检查。

"数据漂移"在此上下文中意味着什么。漂移(drift)——事故源中时间轴和标识符的失同步。如果源中的时间轴未对齐,Qwen Code 可能将事后观察误判为早期信号。因此在评分之前执行三个操作:去重、时间戳标准化以及事件与单一事故标识符的绑定。

在您的项目中,评分格式化为 python3 scripts/shadow_specs/score.py --candidates .specify/memory/shadow-candidates.yaml --incidents .data/incidents_hist_50plus.jsonl --weights "0.5,0.3,0.2,0.4" --out .specify/memory/shadow-scorebook.json。教学数据上的可运行类比位于 examples/shadow-auction/README.md

竞标将评分转化为受限上下文预算的可控分配。

不良做法:

> 启发式"值班的 ASAP 出现在 Slack 中——将严重性提升至 P1"被直接作为强制要求添加进 requirements.md

问题:未经验证的观察成为没有证据的合约。并在聊天中任何"ASAP"出现时产生虚假的 P1。

良好做法:

> 同一启发式被格式化为影子规范 shadow.slack.asap_urgency,得分为 0.55,状态为 review:其值高于拒绝阈值 reject_threshold=0.40,但低于接受阈值 keep_threshold=0.70,因此候选进入人工复审,而非进入形式化规范。

过程是如何运作的。Qwen Code 按 value_score 对候选进行排序。然后消耗预设的 budget——例如 8 个少样本示例槽位或 2,000 个 token。结果分为三类:

  • keep——胜出者,进入 QWEN.md
  • review——有争议的,进入人工复审;
  • quarantine——被淘汰的,进入隔离区。

胜出者仅在超过上限阈值时自动包含。有争议的进入人工复审。被淘汰的不会停留在灰色地带。此方案保护 QWEN.md 免于膨胀。即使是貌似合理的细微之处,如果其预测价值低于提示中的位次成本,也会失败。

在您的项目中,竞标决策格式化为 python3 scripts/shadow_specs/decide.py --scorebook .specify/memory/shadow-scorebook.json --budget-tokens 2000 --keep-threshold 0.70 --reject-threshold 0.40 --out-auction .specify/memory/shadow-auction.json --out-quarantine .specify/memory/shadow-quarantine.json。在教学数据上,相同步骤在 examples/shadow-auction/README.md 中执行。

将胜出者转化为 QWEN.md 中的版本化少样本示例块,而不是简单地将它们追加到文件末尾。为每个块指定:

  • id
  • version
  • source_ref
  • score
  • valid_from
  • next_review(或 ttl——对像"14d"这样的短期复审可使用简写),
  • 简短的应用示例。

为什么需要这些字段。后续团队需要理解这条细微之处存在的原因。

显式删除低价值候选。将它们送入 quarantine,附带原因、复审日期和计算链接。不要让它们毫无痕迹地从历史中消失。这对于质疑决策很重要:如果一个月后告警策略或故障切换(failover)架构发生变化,可以将先前被拒绝的影子规范重新送回竞标,而无需重新收集原始数据。

- id: shadow.p0.voice_handoff.v1
  status: keep
  score: 0.727
  source_ref:
    - postmortem: "appointments-api-2026-02-11"
    - incident: "INC-1842"
  valid_from: "2026-05-17"
  next_review: "2026-08-17"
  few_shot_target: "QWEN.md#incident-triage-shadow"

0.727 的具体来源:这是 examples/shadow-auction/scripts/score.pydata/incidents.jsonl 的 20 起历史事故上使用默认权重 0.5/0.3/0.2 − 0.4 得出的值。与基准的对比——examples/shadow-auction/outputs/scorebook.example.json

评分日志是影子规范的经济性日志。它将原始数据(seed)、评分公式、阈值、预算(budget)、候选版本和决策协议一起存储。

没有评分日志,竞标很快就会变成权威之争。资深工程师可能强行推销自己偏爱的启发式,而 Qwen Code 会收到相互矛盾的少样本示例。此处引入另一个概念。反古德哈特(Anti-Goodhart)——防止以牺牲意义为代价优化指标。可复现的日志提供三种能力:在权重变化后重新计算结果,检查哪些事故影响了胜出,将真正的改进与古德哈特陷阱区分开。

在 SDD 回路中,将此文件与项目的记忆和宪法性约束放在一起。在 Spec Kit 中,对于此类永久规则,方便使用 .specify/memory/constitution.md 作为防范漂移的保护层 (GitHub Spec Kit)。

完整轨道:阈值校准

竞标公式的权重、keep/reject 阈值以及权重复审信号被提取到 附录 D,D.2 节。在第一遍中不需要该节:在默认权重下,一个被接受和一个被拒绝的候选已经足够。

示例与应用

示例:在 appointments-api 的自动分诊项目中,候选 shadow.p0.voice_handoff 描述了这种情况。在 P0 事故中,值班人员不会在聊天中写长消息,而是立即在值班(on-call)和服务负责人之间发起语音交接(handoff)。

data/incidents.jsonl 的 20 起历史事故上,该特征给出的分数为 0.727:MTTR 显著增长(0.7541),早期信号可信(1.0),覆盖范围窄(0.25),误升级为零。在五个案例中,它缩短了第二班次参与的时间。该候选几乎未产生误升级,因为它仅在已确认的 P0 加上事务级联风险时适用。

该候选成为胜出者。但在 QWEN.md 中,它以狭窄的适用条件进入。Qwen Code 不应将语音通道推荐给普通 P2,因为异步文字记录比快速通话更重要。此处的实际价值不在于"打电话"这一行为本身,而在于早期识别那种延迟交接的代价高于损失部分文字上下文的情境。

另一个候选 shadow.alert.red_color_urgency 输掉了竞标。虽然它看起来直观可信。同一个可运行竞标给出其分数为 -0.3081:MTTR 增长微弱,误升级比例显著,将评分拖入负值。红色常在仪表盘中用于视觉强调,但与后果半径、SLO 预算消耗速度或实际升级级别不符。

这样的影子规范产生三重负面效果:

  • 增加了虚假 P1 的比例,
  • 使分诊阶段过载,
  • 降低了自动推荐的信任度。

将其送入隔离区,附带原因 high_false_escalation、复审日期和返回条件。首先团队更改告警的可视化策略。然后通过评分日志重新运行该候选。

罕见的物理信号可以胜出,如果漏检的代价远高于检查的代价。例如,shadow.dc.burn_smell_power_risk 仅适用于数据中心现场(onsite)观察到的事故。其 coverage 较低,但 early_signal 较高:焦糊气味或过热有时在电源监控显示降级之前出现。

这样的候选不能转化为通用规则。否则它会变成无物理访问权限的云事故的有毒噪声。正确的包含形式是带三个限定符的罕见少样本示例:严格的上下文、关于风险的明确注释以及要求通过现场操作员通道确认信号。

flowchart TD
A[第 6 章. 影子规范的筛选]
A --> B[访谈 / 复盘 / 事故历史]

B --> C[提取影子候选]
C --> D[规范化 上下文 / 特征 / 效应]
D --> E[在 50+ 案例上通过 Qwen Code 进行回溯测试]
E --> F["score = 0.5*mttr_gain + 0.3*early_signal + 0.2*coverage - 0.4*false_escalation"]
F --> G[竞标决策 keep/quarantine/review]
G --> H[keep]
G --> I[quarantine]
G --> J[review]
H --> K[QWEN.md]
I --> L[带复审日期的隔离区]
J --> L

小结

影子规范竞标使非形式化的细微之处变得可控。每个候选都获得 上下文 → 特征 → 可观察效应 结构,在历史事故上接受评分,为受限预算竞争——要么成为 QWEN.md 中版本化的少样本示例,要么带着可验证的原因进入隔离区。

该过程的主要纪律是不在没有评分日志的情况下相信精彩的故事。原始数据、公式、阈值和决策协议必须允许在基础设施变化时复现结果并对其提出质疑。下一章将此逻辑引入规范网关(Specification CI),在那里规范将成为可执行工件。

工件与就绪标准

工件就绪条件

| 从 book2/examples/shadow-auction 启动的本地竞标 | smoke 通过;在相同权重和数据下结果可复现 | | 一位胜出者 | 具有 source_ref、score 和复审期限;胜出者不扩展形式化 SDD 合约,也不伪装成要求 | | 一位被拒绝的候选 | 在隔离区中具有明确原因(例如 high_false_escalation) | | QWEN.md 的简短块或 capstone/README.md 中的 Shadow notes 章节 | 少样本示例具有狭窄的适用条件 |

完整轨道以 上下文 → 特征 → 效应 格式添加 .specify/memory/shadow-candidates.yaml、包含公式和权重的 .specify/memory/shadow-scorebook.json、包含 winner/disputed/rejected 决策的 .specify/memory/shadow-auction.json,以及版本化的少样本示例块或隔离区记录。如果每条影子规范都有 source_refscoperisknext_review,评分可复现计算(无人工重算),且候选在权重、预算或事故类别变化时得到复审,则视为就绪。

实践

  1. 在教学数据上运行竞标:cd book2/examples/shadow-auction && python3 scripts/score.py --candidates candidates/candidates.yaml --incidents data/incidents.jsonl --weights 0.5,0.3,0.2,0.4 --out out/scorebook.json。*预期:diff -u outputs/scorebook.example.json out/scorebook.json 输出 0 行;评分中至少有一个候选 score >= 0.70,至少有一个 score < 0.40。*
  2. 在相同的 scorebook.json 上运行 python3 scripts/decide.py --scorebook out/scorebook.json --budget-tokens 2000 --keep-threshold 0.70 --reject-threshold 0.40 --out-auction out/auction.json --out-quarantine out/quarantine.json。*预期:out/auction.jsonout/quarantine.jsonoutputs/ 中的基准一致;out/quarantine.json 中至少有一条记录具有明确的 reasonreturn_condition。*
  3. 将误升级惩罚权重从 0.4 改为 0.8,重新计算 scorebook.json 并在 capstone/README.md 中记录偏移。*预期:在 capstone/README.md 中记入一行"在将误升级惩罚加倍后,候选 <id>keep 转入 quarantine";同一行中指明在新权重下哪个公式组件成为主导。*

检验问题

  1. 影子规范与完整要求有何区别,为什么不能替换它?
  2. 为什么 QWEN.md 中的少样本示例必须具有复审期限?
  3. 如何判断启发式已成为运维传说?
  4. 值班人员要求在 QWEN.md 中添加规则"如果 Slack 中使用 ASAP 一词——提升 severity"。您如何在不直接拒绝的情况下,将其纳入影子规范竞标流程?
我的笔记
0 / 10000

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

课程菜单

课程

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