AgentEvalTool/docs/adr/0011-intelligent-eval-terminal-state-discipline.md
sinohqb eb4944a8bd feat(intelligent-eval): terminal-state discipline watchdogs (ADR-0011)
常见故障自愈有上限,超限收敛终态且可见:任务 attempts 上限、会话过期、
planning 双闸、executing 超窗兜底、触发失败计数判死、孤儿 agent 双管、
fire-and-forget 触发;open_session 预算硬闸门、settle 按终态区分、报告
scores 归一化;cron 池遗留面全删。
2026-08-20 14:34:17 +08:00

44 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-0011: 智能评估容错收敛——终态纪律与失败可见性
**状态**: 已接受
**日期**: 2026-08-19
**决策者**: 架构团队
**相关**: ADR-0009触发式执行、ADR-0010独立 session、ADR-0007已被取代、CONTEXT.md智能评估会话、触发式执行
## Context
v1.1.1 将触发式执行在 t480 跑通后,对智能评估模块做容错盘点,发现一批"无声卡死"类缺口:评估级无 watchdogworker 不关闭会话 → 报告永远 409 → 评估永久卡 executing、任务与 planner 触发无限重试、子进程触发失败只写日志不落库、600s 超时杀不掉容器内 agent 形成孤儿、会话数无平台侧上限、串行 await 触发使 60s 扫描周期漂移、已删除前端页面的 Cron 池 API 面仍挂载。
根本问题不是单点 bug而是缺少一条容错纪律故障发生后系统该自愈到什么程度、什么时候必须放弃并让人知道。
## Decision
确立**终态纪律**常见故障自愈有上限超限或结构性失败收敛到终态completed/failed/cancelled且用户可见绝不无声卡死。具体机制
1. **planning 双闸**planner 触发满 5 次或进入 planning 满 30 分钟仍未提交粗计划(触发失败计入次数),置 `failed` 并落原因 + 决策日志。
2. **会话过期**running 会话 60 分钟无新轮次由平台置 `expired`(启用既有 EXPIRED 枚举);`submit_report` 校验从"全部 completed"放宽为"全部终态"expired 会话在报告中标注为不完整证据——不把超时会话伪装成 completed证据链保持诚实。
3. **executing 兜底**:最后一个会话到达终态后 10 分钟平台自动触发 analyst上限 3 次;仍无报告或 executing 总时长超 `time_window_hours + 2h`,置 `failed`
4. **任务重试上限**:任务表加 `attempts`stale requeue 上限 3 次,超限置 `failed`
5. **触发失败可见**:子进程缺失/超时/非零退出记入决策日志(`cron_id=platform`)并计入对应闸;同一评估连续 3 次触发失败直接判 `failed`(结构性故障不等自然到期)。
6. **孤儿 agent 双管**:触发命令容器内包 `timeout` 灭杀 agent 进程;平台侧 per-eval 触发冷却 10 分钟,兜住重启丢句柄留下的残余孤儿。
7. **预算硬闸门**`open_session` 校验会话数 < 粗计划审批的虚拟用户数超出 409用户审批粗计划 = 审批预算,平台执行审批过的数字。
8. **扫描节奏恢复**触发改 fire-and-forgetasyncio task结果在回调中持久化扫描循环恢复准确 60s保住时段分布
9. **Cron 池遗留面全删**摘除 `/api/openclaw/cron-pool` router 挂载删除 openclaw_cron_pool / alerts / fault_tolerance / cron_pool 模块AlertManager 无后台 tickduration 告警永远不会触发是假装在工作的死代码)。
10. **settle 语义诚实化**评估 cancelled/failed 时遗留任务置 `failed`completed 时才置 completed任务队列监控统计口径随之诚实
11. **报告边界归一化**`submit_report` scores 归一到单一规范结构落库前端与 markdown 渲染删除双兼容分支
### Considered Options已拒绝
- **全自动自愈**任何故障都自行恢复对单实例内部工具是过度工程"明确失败"本身是重要信号
- **任务/触发不设上限靠评估级超时兜底**确定性失败的任会在兜底期内被重试约 24 触发约 24 个子进程烧资源并刷垃圾数据
- **超时会话强置 completed**会让报告消费者人和 AI无法分辨完整证据与不完整证据污染证据链
- **预算软约束自然语言指令**对会幻觉的 agent 不是约束预算失控完全无声
## Consequences
- 新增 schema 变更`IntelligentEvalTaskQueueDB.attempts`Alembic 迁移 + 全新库 parity 测试)。
- `EXPIRED` 会话状态从死代码变为真实终态CONTEXT.md 已同步报告校验口径变化需要前后端一起改
- 冷却期把触发频率从" 60s"降为"每评估每 10 分钟"时段推进节奏相应放缓 stale requeue 10 分钟对齐
- 部署拓扑假设不变单进程单实例SQLite + StaticPool多实例部署需另行复审触发/扫描的分布式互斥
- 不变更OpenClaw 三角色职责划分时间窗口语义报告业务 schema仅归一化 scores 结构)。