# ADR-0005:模拟器是一等公民,不是测试脚手架 - 日期:2026-07-27 - 状态:已接受 ## 背景 第一波没有真实硬件(没有可牺牲的 DUT、没有带外控制器、没有温箱)。 常规做法是先写代码、等硬件到位再联调。 ## 决定 把**模拟 DUT + 模拟带外控制器 + 故障注入器**做成产品代码的一部分 (`services/host-agent/flashops_agent/simulator/`),与真实适配器共用同一套接口, 而不是塞进 `tests/` 当替身。 模拟器支持注入的故障至少覆盖报告 Phase 1a 要求验证的三类: 杀 Agent、蓝屏/panic、拔网线;外加掉盘与数据完整性失败。 ## 理由 1. **它是长期资产,不是临时替身。** 有了真硬件之后,模拟器仍然是唯一能 在 CI 里跑"100 循环 + 注入 20 次故障"的东西。真设备跑一轮要几小时, CI 里不可能天天跑。 2. **恢复逻辑的测试覆盖只能靠它。** 五级恢复阶梯里的 L4/L5(ATX 长按、AC 断电) 在真机上每测一次都有风险且很慢。这条路径恰恰是产品价值所在,必须能高频回归。 3. **它是谈判道具的底座。** 报告把 Phase 1a 的产出定义为"一台会自救的演示台—— 同时是合伙人与客户谈判的最强道具"。在拿到硬件之前,模拟器版本已经能把 完整故事演一遍:注入蓝屏 → 看着它自己救回来 → 断点续跑 → 出证据包。 4. **它划清了接口。** 能被模拟器替换掉的地方,就是硬件接入的边界。 写模拟器的过程本身就在逼迫接口设计正确。 ## 代价 - 模拟器与真实实现可能漂移(模拟器里能过、真机上过不了)。 缓解:`tests/test_adapter_contract.py` 对模拟与真实适配器跑**同一套契约测试**; 真实适配器接入后,契约测试是第一道闸。 - 有"在模拟器上跑通了就以为完事了"的风险。缓解:README 的能力表里, 模拟实现一律标 ⚠️ 或"模拟",不标 ✅ 真实。 ## 什么时候推翻 不推翻。真实硬件接入后模拟器保留,作为 CI 的默认执行后端。