## 状态机违规（High）

### 触发信号

在以下代码特征出现时启动此检测：
- 状态字段直接赋值（`obj.status = ...`、`obj.state = ...`）
- 状态枚举定义（`enum Status`、`const STATUS = {...}`）
- 包含 approve/reject/complete/cancel/start 等状态变更语义的函数名

### 判定流程

1. **构建状态变更图**：`find_references` 追踪状态字段的所有赋值位置，记录每次变更的来源状态和目标状态，构建实际状态转换图
2. **检查状态转换方法**：对直接赋值 `obj.status = X` 的位置，`Read` 确认：
   - 是否通过专用方法（`transition()`、`complete()`、`cancel()`）而非直接赋值
   - 直接赋值处是否缺失了前置条件验证
3. **验证前置条件**：`Read` 检查状态转换方法内部是否有条件校验：
   - 当前状态是否在允许的来源状态列表中
   - 是否校验了业务前置条件（如余额充足、库存足够）
4. **检查关联动作**：`Read` 确认状态转换是否触发了必要副作用：
   - 库存释放、通知发送、审计日志、计数器更新
5. **检查终态保护**：`Read` 确认终态（completed/cancelled/closed/archived）是否有写入保护，防止对已终结状态的修改

### 证据构造

确认缺陷后，输出需包含：
- 状态转换图（实际代码中的所有状态变更路径）
- 违规跳转（哪些非法跳转缺少拦截，含文件:行号）
- 遗漏的关联动作（状态变更后未触发的副作用）
- 业务影响（非法跳转可导致的后果：跳过审核、重复发货、库存泄露）

### 排除

- 初始化赋值（构造函数中的初始状态设置）
- 枚举/常量定义（非运行时赋值）
- 测试代码中的直接状态设置
