D2启动前确认
日期: 2026-09-14
前置条件: D1观察通过(90次运行,100%成功)
任务1:确认方式B3行为
方式B3定义
B3: 临时禁用原cron → 只跑影子cron → 验证包装功能 → 测试后恢复
执行流程:
1. 备份原cron状态
2. 临时禁用原cron(hermes cron pause)
3. 注册影子cron(run_with_alert包装)
4. 等待1-2次运行周期
5. 验证影子cron告警功能
6. 恢复原cron(hermes cron resume)
7. 禁用影子cron
8. 清理测试数据
与原方式B对比
| 对比项 |
方式B(影子并行) |
方式B3(临时替换) |
| 原cron状态 |
保持运行 |
临时暂停 |
| 风险等级 |
低(双系统并行) |
中(有窗口期) |
| 验证效果 |
比对输出一致性 |
直接测试告警功能 |
| 回滚难度 |
低(删除影子cron) |
低(恢复原cron) |
| 适用场景 |
输出比对验证 |
告警路径验证 |
推荐:方式B3 + 影子并行混合
阶段1(08:30-09:30): 影子并行测试
- 原cron保持运行
- 影子cron并行运行
- 比对两次运行输出
阶段2(15:30-16:30): B3临时替换测试
- 暂停原cron
- 只跑影子cron
- 验证告警功能
- 恢复原cron
任务2:确认alert_channel_health监控范围
当前监控范围
⚠️ 只监控5个agent-mode任务(硬编码TASK_CRON_IDS):
1. position_688306 (P0) - 均普智能持仓跟踪
2. ops_system_health (P1) - 系统环境自检
3. ops_backup_daily (P1) - hermes每日备份
4. risk_sentiment_radar (P1) - A股风险情绪雷达
5. eval_pias_daily (P1) - PIAS评估
总计: 5个任务(占104个任务的4.8%)
问题确认
❌ test_alert_path_001不会被检测到
- 不在TASK_CRON_IDS列表中
- alert_channel_health不会轮询该任务
⚠️ 受控测试方案需调整
- 不能直接测试test_alert_path_001
- 需要改用已监控任务或扩展监控范围
任务3:调整受控测试告警路径方案
方案选择
| 方案 |
操作 |
优点 |
缺点 |
| A |
临时加入TASK_CRON_IDS |
真实测试 |
改代码有风险 |
| B ⭐ |
用已监控任务名测试 |
不改代码 |
可能误报真实任务 |
| C |
扩展监控范围为所有任务 |
全面监控 |
改动大 |
推荐方案:B(用已监控任务名测试)
# 测试策略:临时修改已监控任务的last_run_at,模拟故障
# 测试1: 告警路径测试
# 用ops_system_health(P1任务)
# 修改其last_run_at为3小时前,模拟超时
# 验证alert_channel_health检测到并告警
# 测试2: 静默期测试
# 连续触发2次失败
# 验证第1次静默,第2次告警
# 测试3: 恢复测试
# 修改last_run_at为正常时间
# 验证恢复通知发送
具体测试步骤
# 测试1: 告警路径
import sqlite3
from datetime import datetime, timedelta
conn = sqlite3.connect('D:/Hermes/data/state/alert_state.db')
# 修改ops_system_health的last_run_at为3小时前
conn.execute("""
UPDATE task_runs
SET start_time = ?, status = 'failed', exit_code = 1
WHERE task_id = 'ops_system_health'
AND start_time = (SELECT MAX(start_time) FROM task_runs WHERE task_id = 'ops_system_health')
""", ((datetime.now() - timedelta(hours=3)).isoformat(),))
conn.commit()
conn.close()
# 等待alert_channel_health运行(最多15分钟)
# 验证alerts表有新记录
# 验证TG消息已发送
任务4:D2执行清单
时间窗口
明天(9月15日):
08:30-09:30 受控测试(阶段1:影子并行)
15:30-16:30 run_with_alert集成(阶段2:B3临时替换)
20:00-20:30 回归验证
执行清单
阶段1:影子并行测试(08:30-09:30)
| 步骤 |
操作 |
预期结果 |
验收标准 |
| 1.1 |
备份原cron状态 |
jobs.json备份 |
文件存在 |
| 1.2 |
注册影子cron(eval_morning影子) |
影子任务ID生成 |
cron list可见 |
| 1.3 |
等待原cron运行(08:00已过,等待下次) |
原任务完成 |
last_run_at更新 |
| 1.4 |
等待影子cron运行 |
影子任务完成 |
task_runs记录生成 |
| 1.5 |
比对两次输出 |
输出一致 |
偏差率<5% |
| 1.6 |
记录比对结果 |
比对报告生成 |
文件保存 |
阶段2:B3临时替换测试(15:30-16:30)
| 步骤 |
操作 |
预期结果 |
验收标准 |
| 2.1 |
暂停原cron(eval_morning) |
原任务禁用 |
cron list显示disabled |
| 2.2 |
手动触发影子cron |
影子任务执行 |
exit_code=0 |
| 2.3 |
验证alert_state.db写入 |
task_runs记录 |
记录生成 |
| 2.4 |
验证告警功能(插入失败记录) |
alerts表有新记录 |
记录生成 |
| 2.5 |
恢复原cron |
原任务启用 |
cron list显示enabled |
| 2.6 |
禁用影子cron |
影子任务删除 |
cron list不可见 |
| 2.7 |
清理测试数据 |
DB清理完成 |
测试记录删除 |
阶段3:回归验证(20:00-20:30)
| 步骤 |
操作 |
预期结果 |
验收标准 |
| 3.1 |
检查原cron状态 |
正常运行中 |
last_run_at正常 |
| 3.2 |
检查alert_channel_health |
无异常告警 |
channel_health=ok |
| 3.3 |
检查alert_state.db |
无测试残留 |
测试记录已清理 |
| 3.4 |
检查TG消息 |
无噪音消息 |
消息正常 |
| 3.5 |
生成回归报告 |
报告保存 |
文件存在 |
验收标准
D2通过条件:
✓ 阶段1: 影子并行比对一致
✓ 阶段2: B3测试通过,原cron恢复正常
✓ 阶段3: 回归验证无异常
✓ 无TG告警噪音
✓ 测试数据已清理
✓ 原cron状态未改变
回滚方案
# 一键回滚(如遇问题)
hermes cron resume <原任务id> # 恢复原cron
hermes cron remove <影子任务id> # 删除影子cron
python -c "import sqlite3; c=sqlite3.connect('D:/Hermes/data/state/alert_state.db'); c.execute(\"DELETE FROM task_runs WHERE task_id LIKE 'test_%'\"); c.commit()" # 清理测试数据
请确认方案后,回复"进入D2"启动明天执行。