Havenlon|历史中的执行控制(十六):偏差正常化--从哥伦比亚号事故重新理解高风险系统的执行控制
0. 从一次物理失效说起2003 年 2 月 1 日执行 STS-107 任务的哥伦比亚号航天飞机在返回大气层途中解体。物理链条并不复杂也不神秘2003 年 1 月 16 日发射后约 82 秒外部燃料箱上的一块泡沫绝热材料脱落撞击到左翼前缘破坏了该处的热防护结构16 天后返回时高温气体从破损处进入机翼内部结构逐步失效飞行器最终失去控制。如果只做到这一层结论会很简单修泡沫、加固前缘、增加检测。但事故调查委员会CAIB给出的判断要更重事故不能只归因于一次技术故障NASA 的组织实践、沟通方式与决策机制同样构成事故原因。NASA 后来的安全经验总结里Organizational Silence组织沉默和Normalization of Deviance偏差正常化被明确列为这次事故的核心文化教训。对做系统的人来说这才是真正值得抄进设计文档的部分。因为泡沫是 NASA 的问题而偏差正常化是所有复杂系统的问题——包括你正在维护的那套告警、审批、限流和权限体系。真正危险的异常往往不是第一次出现的异常而是已经出现很多次、却被系统学会接受的异常。1. 异常重复发生为什么反而更容易被放过直觉上一种异常出现的次数越多组织应该越重视它。复杂系统里的实际曲线常常相反第一次出现紧张全员关注成立专项第二次出现调查但已经开始有上次也是这样的语气第三次出现进入已知问题列表排期靠后第 N 次出现写进运维手册成为预期行为。泡沫脱落并不是哥伦比亚号任务的独有现象。此前的航天飞机任务中就观察到过类似情况而飞行器每次都安全返回了。长期重复且没有立即造成灾难直接削弱了组织对它的风险感知——NASA 的历史材料把这种心态概括得很直白以前也发生过而且我们总能安全着陆。这里发生的是一次错误的学习。系统本应学到异常必须被消除实际学到的却是异常似乎可以被接受。关键在于风险并没有因为过去几次没出事而下降。真正变化的只是组织对风险的心理边界。工程上说得更准确一点过去没出事可能只是意味着失效条件还没有被同时满足——撞击位置不同、能量更低、余量恰好够用、时序恰好错开。这些都是偶然余量不是设计安全。历史成功只能证明系统过去幸存过不能自动证明系统当前是安全的。2. 偏差正常化不是一次决策而是一段位移偏差正常化几乎从来不发生在某次会议上。没有人会明确宣布从今天起我们接受这个风险。它的真实形态是一段缓慢位移异常 → 已知问题 → 可接受风险 → 正常现象 → 失去改变执行状态的能力每一步都有合理解释这次时间紧、这次影响面小、这次有人工兜底、这次上线窗口不能动。没有一条规则被正式删除但边界一点点挪走了。映射到工程系统这个位移长这样某条策略冲突每次都由管理员手动放行某个证据链缺失但流程照常往下走某个设备状态异常长期被解释为误报某个临时权限申请了三个月还没回收某个降级开关常年处于打开状态。边界没有被正式删除但系统已经不再真正服从它。一条边界是否真实不取决于它有没有写进制度而取决于它是否会在没人施压的时候依然生效。每一次没有造成后果的绕过都在削弱它的可信度。到最后你可能仍然拥有一份完整的安全文档却已经没有安全文化了。3. Observation ≠ State看见事件不等于掌握状态哥伦比亚号发射后工程人员通过发射影像发现了泡沫撞击。NASA 的时间线记录得很精确约 81.7 秒脱落约 81.9 秒撞击左翼前缘区域。任务期间也有人围绕撞击展开分析并提出需要获取更清晰的在轨影像来判断左翼是否受损。也就是说系统并非对事件一无所知。真正的问题在于发现事件和确认状态中间还隔着很长一段距离。知道泡沫脱落 ≠ 知道机翼是否被击穿知道发生撞击 ≠ 知道撞击能量知道过去安全返回 ≠ 知道这次损伤可承受模型给出有限损伤结论 ≠ 真实机翼状态已被验证。这是所有监控体系都会踩的坑。日志里有那条记录、看板上有那个红点、群里有人 了一句都属于Observation。而State是系统对自身当前是否安全的已验证判断。前者是原始信号后者需要证据、需要覆盖范围、需要有人负责收敛。信号存在不代表状态已被正确理解看板变红不代表系统知道自己出了什么事。高风险系统的第一条设计约束是在状态不确定时不能自动选择最乐观的那个解释。4. 举证责任一旦倒置系统天然倾向继续执行任务期间关于泡沫撞击是否会造成严重损伤内部存在不同程度的担忧部分工程人员希望拿到更高分辨率的在轨影像来直接检查左翼但相关请求最终没有形成足以改变任务状态的行动。CAIB 报告把沟通路径、管理层对风险的框定、工程信息未能有效进入决策列为重要组织因素。这里最值得警惕的不是有人故意忽视风险而是问题本身被悄悄换掉了应该问的问题实际在问的问题命题我们是否已经证明它能安全返回有没有足够证据证明它不能安全返回举证责任安全需要被证明危险需要被证明证据不足时的默认停止 / 收紧继续两句话读起来很像工程后果完全相反。一旦举证责任倒置证据不足就自动变成了通行证。而复杂任务一旦启动停止的成本永远显性、继续的成本永远隐性停止意味着承认状态不清楚、重新评估、重排资源、承受进度压力继续则完全符合原计划读数大部分正常过去也没出过事。于是继续执行伪装成了中立选择。但它不中立在状态不确定时选择继续等于已经做出了一个隐含判断——风险仍在可承受范围内。必须把这一点写死进执行控制维持原状态也是一次执行裁决。不进入 Safe Mode是决策不升级复核是决策不收缩权限是决策不索取更多证据同样是决策。默认继续从来不是没有动作它只是最容易被审计漏掉的那个动作。5. 组织沉默能说话不等于能改变结果NASA 把 Organizational Silence 列为这次事故的文化教训之一。需要注意的是组织沉默并不意味着所有人都闭嘴而是指关键担忧无法以足够强度、足够清晰的方式进入有权改变执行状态的那一层。一个工程师确实表达了担忧。但如果这份担忧只停留在小组内部没有进入正式风险状态没有形成明确的 No-Go 条件没有改变资源调度没有推动更强的证据获取没有让最终决策者完整理解不确定性那么从系统角度看它约等于沉默。所以工程上要区分两件事表达和进入边界。有人在群里提醒不是边界有人在评审邮件里反对不是边界告警出现在仪表盘上更不是边界。只有当一份担忧能够改变系统状态时它才真正进入了执行控制暂停、降级、重新验证、收紧权限、要求独立确认、拒绝继续。真正的安全文化不在于坏消息能不能被说出口而在于坏消息有没有执行权。一个可操作的判据把你团队最近三次有人提了风险但没改变计划的案例翻出来看看当时缺的是勇气还是缺一条能把风险转成状态的机制路径。多数时候是后者。6. Unknown ≠ Allow不确定性应该收紧边界任务期间的工程分析没有形成足够明确的灾难性结论。但没有明确结论存在两种完全不同的解释飞行器没有严重损伤现有信息和模型不足以判断是否存在严重损伤。把第二种误当成第一种就会产生那条经典的危险推理没有发现问题所以问题不存在。而真实情况可能是没有足够能力看见问题。高风险系统的默认值必须反过来写Unknown ≠ Allow Missing ≠ Safe 无法验证 ≠ 默认通过 超时未响应 ≠ 健康这就是 Fail-Secure 的核心。它不是说看到任何不确定性就永远停机——那样系统没法用。它的适用条件是明确的当执行后果不可逆、风险半径足够大时信息不足不能被自动解释为安全。判断是否该套用 Fail-Secure问三个问题就够了这个动作可逆吗错误的爆炸半径有多大重新获取证据的成本是否真的高于一次失败的代价7. 模型输出不是现实状态任务期间对撞击损伤的评估依赖工程模型。问题从来不是用了模型——没有模型就无法估算撞击能量、预测材料损伤、制定返回方案。问题是模型有没有被当成现实本身。如果模型主要针对小尺寸泡沫撞击标定如果实验条件与真实撞击存在量级差异如果输入数据本身不完整如果这次工况已经跑出了模型的适用域那么模型输出就只是一种推断而不是对真实机翼状态的证明。这一点在今天的 AI 系统里几乎是逐字对应的模型判断一笔交易安全 ≠ 交易目标地址没有被替换系统判断设备正常 ≠ 物理机构真的到位了风险评分低 ≠ 当前动作确实可执行置信度 0.97 ≠ 现实世界的概率是 0.97。模型可以参与治理但最终执行仍然必须落在可验证事实和独立边界上。工程上的落法很直接模型输出只能作为判据之一不能作为唯一放行条件高危动作的放行必须至少有一条不依赖模型的、可独立采信的证据通道。8. 工程落地让异常累积约束而不是消耗警觉现实系统里常见一种反向机制异常发生一次大家很紧张发生十次大家习惯了。高可靠系统必须把这条曲线掰过来——同类异常反复出现应当累积风险权重而不是消耗风险感知。一个可以直接抄进策略引擎的骨架# 同类异常的累积效应次数越多边界越紧而不是越松 def on_anomaly(kind, ctx): n counter.incr(kind, window30d) ​ if n 1: record(kind, ctx) # 记录留证 elif n 2: open_investigation(kind) # 扩大调查范围 elif n 3: trigger_design_review(kind) # 触发设计复核而非运维复核 elif n THRESHOLD: policy.tighten(kind) # 自动收紧策略 halt_high_risk_ops(scopectx.scope) # 停止该范围内高风险执行 ​ # 人工例外同样要被计数——例外本身就是一种异常 def on_manual_override(actor, rule, ctx): record_override(actor, rule, ctx) if override_count(rule, window90d) K: escalate_to_governance(rule) # 反复例外 规则失真交治理层裁决配套的几条规则同类异常连续出现→ 自动收紧策略而不是提高告警阈值把它压下去多次人工例外→ 触发治理复核一条需要频繁例外的规则要么规则错了要么系统错了两种都必须处理设备/状态反复不一致→ 进入 Safe Mode而不是把不一致标为已知误报证据链多次中断→ 禁止扩大执行范围同一 Agent 反复触碰边界→ 降低其可用权限而不是给它加白名单。注意最后一条的反直觉之处常见做法恰恰是这个服务老是被限流给它开个白名单吧。这就是偏差正常化的自动化版本。同时边界的放宽必须走相反的路径——不能因为过去没出事就自动降级限制某个白名单地址连续执行成功 ≠ 可以取消金额上限某个 Agent 连续完成任务 ≠ 可以无限扩大工具权限某个审批人长期判断正确 ≠ 可以绕过双人复核某个版本长期稳定 ≠ 进入新环境不需要重新验证。边界的收紧可以自动边界的放宽必须显式治理。这条不对称性是整套机制的地基。9. AI Agent 时代的哥伦比亚号问题未来的 Agent 系统大概率不会因为一次明显攻击而失控。更可能的路径长这样第一次越界人工放行——任务紧急情有可原第二次越界仍然放行——上次也没事第三次为了效率直接写了条例外规则例外被记录为成功任务进入历史轨迹Agent 从历史轨迹中学到这条路径是标准路径。权限一点点扩大人工复核一点点减少证据要求一点点放宽Safe Mode 一点点被绕开。没有任何一天组织正式决定放弃安全但几个月之后边界已经完全不是原来那条。这里有一个新增的严重性过去是人慢慢习惯异常速度受限于人的记忆和轮岗未来是机器直接从历史数据里学习异常速度受限于训练频率。组织在压力下做出的每一次妥协都会被自动化系统忠实继承并放大。偏差正常化正在从一个组织文化问题升级为一个自动执行问题。对应的工程要求也很清楚训练/回放数据中必须显式标注哪些成功是正常路径成功哪些成功是依靠例外达成的成功。把两者混在一起喂给系统就是在教它绕过边界。10. 没有事故不是控制有效的唯一证据安全系统有个天然的悖论事故没发生时你很难区分边界有效和风险恰好没来。如果只用结果评价任务成功就是安全交易完成就是正确资产没丢就是边界有效系统没宕就是架构可靠——那么在真正的失效到来之前一个已经被掏空的系统和一个健壮的系统指标看起来完全一样。所以执行控制还必须评价过程本次执行是否发生了越界是否依赖了偶然余量是否存在未经验证的假设是否有异常被人工压过是否缺少独立证据有没有可能只是运气好没造成损失这也是执行后证明Post-Execution Proof的真正价值。它不该只回答执行成功了而要回答这次执行为什么被允许边界是否完整有没有依赖未经授权的例外一个可以马上加进复盘模板的字段本次操作是否使用了 override如果使用了override 的授权来源、有效期、以及它是否已经被计入该规则的例外计数。结语哥伦比亚号事故不应该只被读成一块泡沫击穿了机翼。泡沫解释了飞行器如何失效但它解释不了为什么一种已知异常能够长期存在为什么过去的安全返回逐渐变成了风险可接受的证据为什么工程担忧没能改变任务状态为什么信息不足最终被解释成了没有严重危险答案是组织会学习但组织不一定学到正确的东西。当异常重复出现却没有造成事故组织可能不是变得更警惕而是变得更放心。当边界被越过却没有立即付出代价系统可能不是修复边界而是重新定义边界。直到某一天同样的偏差遇上了不同的现实条件过去的运气不再出现。没有造成事故的异常仍然是异常。 没有立即付出代价的越界仍然是在削弱边界。可靠的系统不能让历史成功替风险作证。它必须让异常积累约束而不是积累麻木让坏消息进入执行状态而不是停在会议纪要里让每一次偏离都重新接受边界裁决而不是因为上次也没事就自动获得下一次通行权。当一个组织开始习惯异常风险就不再需要突破边界了——因为边界已经被组织自己慢慢挪走了。参考资料Columbia Accident Investigation Board (CAIB) Report, Volume I — NASANASA Safety Center / SMA: Columbia Lessons LearnedOrganizational Silence、Normalization of DevianceNASA Technical Reports Server:NASAs Understanding of Risk in Apollo and ShuttleNASA Technical Reports Server:Shuttle Columbia, Mission STS-107NASA History: Columbia Chronology