# Changelog: 2026-05-30 — Heartbeat 422 修复 + Agent 弃用升级

## 变更摘要
1. 修复未注册/旧版 Agent 发送无 server_id 心跳导致 422 日志噪音问题
2. 将 web/agent/agent.py 的已弃用 `on_event("startup")` 迁移到 `lifespan`
3. Agent 心跳添加指数退避 + discarded 状态自动停止
4. main.py 临时 RequestValidationError handler 升级为正式版本
5. 卸载脚本增强对旧版 MultiSync Agent 的清理（crontab/legacy 路径）
6. 确认 servers.html 批量操作按钮正常工作（disabled 为正确行为）

## 动机
- 47.121.118.30 旧版 Agent 持续发无 server_id 心跳，导致 422 日志刷屏
- 旧 Agent 收到 422 后不断重试，形成噪音循环
- FastAPI on_event("startup") 已弃用，需迁移到 lifespan
- Agent 心跳失败无退避，网络抖动时加重服务器负担
- 卸载脚本未覆盖旧版 MultiSync Agent（非 systemd、非标准路径）

## 涉及文件
- `server/api/schemas.py` — AgentHeartbeat.server_id 改为 Optional[int]
- `server/api/agent.py` — heartbeat handler 处理 server_id=None（返回 200 + discarded）
- `server/main.py` — 移除临时 Debug 注释，正式化 RequestValidationError handler
- `web/agent/agent.py` — on_event → lifespan + 指数退避 + discarded 停止
- `web/agent/uninstall.sh` — 增加 legacy Agent 进程杀除 + crontab 清理 + 旧路径删除

## 是否需迁移/重启
- 需要重启 Nexus 后端（agent.py + schemas.py 变更）
- 需要重新部署 Agent 脚本到子服务器（下次安装/升级时自动更新）

## 验证方式
- `python -c "import server.main"` 通过
- `ruff check server/api/agent.py server/api/schemas.py server/main.py` 通过
- `ast.parse(agent.py)` 通过
- 47.121.118.30 旧 Agent 发心跳 → 返回 200 discarded → 日志 warning 一次，不再循环
- 新 Agent 心跳失败 → 指数退避（60s → 120s → 240s → 300s cap）
- 新 Agent 收到 discarded → 停止心跳循环 + error 日志
