chore(repo): initialize team collaboration repository
CI / Python 3.12 (push) Waiting to run
CI / Python 3.9 (push) Waiting to run

This commit is contained in:
2026-07-27 20:40:12 +08:00
commit c91a64fddb
109 changed files with 21121 additions and 0 deletions
@@ -0,0 +1,43 @@
# 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 的默认执行后端。