diff --git a/docs/design/08-classify-outcome-optimization.md b/docs/design/08-classify-outcome-optimization.md index 876286c..6086879 100644 --- a/docs/design/08-classify-outcome-optimization.md +++ b/docs/design/08-classify-outcome-optimization.md @@ -1,13 +1,14 @@ # #08 Classify Outcome 优化 + Registry 清理 -> 版本:v1.1 | 日期:2026-06-02 | 作者:庞统 | 状态:待实施(已部分实施,本轮补完剩余项) +> 版本:v2.0 | 日期:2026-06-02 | 作者:庞统 | 状态:✅ 已实施,司马懿评审通过 > -> v1.0→v1.1 变更:Phase -1 TCP probe 方案废弃(已转为独立 Gateway Watchdog v2); -> cooldown 参数统一简化(A14/A15/A8/A10 均改为 60s);A7 compact retry 暂缓; -> stderr_preview 暂缓;标注已实施项。 -> 已实施项(经司马懿 3 轮评审 approved):A3/A3b fallback 分级、api_error retry 上限、 -> crash/error cooldown 300s、fallback_retry_count 独立计数。 -> 本轮实施:A14/A15/A16/A17 拆分 + A8/A9/A10 改 retry + cooldown 统一 60s。 +> v2.0 最终状态: +> - Phase -1 TCP probe → 废弃,替代为独立 Gateway Watchdog v2(已部署) +> - Classify Outcome v3.1 → 全部实施(v1.0: A3/A3b/api_error/cooldown; v1.1: A14-A17/A8/A10/cooldown统一60s) +> - Registry 清理 → 不做物理删除,逻辑删除+归档,后续单独实施 +> - 并发控制一致性 → TODO,留 #02 Main Session 统一处理 +> - stderr_preview / exit_signal → 暂缓 +> - A7 compact_failed retry → 暂缓 ## 1. 背景与动机 @@ -98,9 +99,9 @@ TCP 握手只能检测进程端口是否监听,无法检测 Gateway **业务 | A5 | status=ok(其他组合) | completed | — | 结束 | | A6 | status=error + stderr 含 auth 关键字 | auth_failed | ❌ | 标 failed + 原因写黑板 | | A7 | status=error + stderr 含 compact 关键字 | compact_interrupted | ✅ | retry + cooldown 60s(等 compact 完成) | -| A8 | status=error + stderr 含 network 关键字 | gateway_unreachable | ✅ | retry + cooldown 30s | +| A8 | status=error + stderr 含 network 关键字 | gateway_unreachable | ✅ | retry + cooldown 60s | | A9 | status=error + stderr 含 rate_limit 关键字 | api_error | ✅ | retry + cooldown 60s | -| A10 | status=error + stderr 含 lock 关键字 | lock_conflict | ✅ | retry + cooldown 10s | +| A10 | status=error + stderr 含 lock 关键字 | lock_conflict | ✅ | retry + cooldown 60s | | A11 | status=error(其他) | agent_error | ❌ | 标 failed + 原因写黑板 | #### 第二层:无 JSON 输出(status = None, stdout 空) @@ -137,19 +138,19 @@ TCP 握手只能检测进程端口是否监听,无法检测 Gateway **业务 - 重试不会改变结果,需要人工介入 - 标 failed + `{"reason": "auth_failed", "stderr_preview": "..."}` -#### A7: compact_interrupted(可恢复,新逻辑) +#### A7: compact_interrupted(暂缓未实施) - compact 是 Gateway 的上下文压缩过程 -- compact 结束后 session 状态恢复,可以续杯 -- retry + cooldown 60s(给 compact 足够时间完成) -- 续杯时 spawn_full_agent 会重新检查 session state(Phase 2),如果 compact 还在进行会 AgentBusyError → 等 ticker +- compact 结束后 session 状态恢复,理论上可以续杯 +- **当前代码 A7 compact_failed 仍为不可恢复(should_retry=False)**,暂不改动 +- 等 A7 实施时一并处理 #### A8/A9/A10: 暂时性错误(可恢复,改为 retry) - 原逻辑:release counter + 推回 pending → 等 ticker 重新分配 - 新逻辑:counter 已在手里,直接 retry 更快 - 各自设 cooldown 避免高频轮询: - - A8 network: 30s + - A8 network: 60s - A9 rate_limit: 60s - - A10 lock: 10s + - A10 lock: 60s #### A11: agent_error(不可恢复) - status=error 但 stderr 不匹配任何已知关键字 @@ -209,11 +210,22 @@ if cls.get("cooldown_seconds"): stderr_preview 和 exit_signal 写 metadata 的方案暂缓,本轮不实施。 已有 metadata 记录 fallback_count、api_retry_count、retry_count 等计数器。 -## 4. Registry 清理 — 暂缓,不在本轮实施 +## 4. Registry 清理 — 最终决策:逻辑删除 + 归档,不做物理删除 -> 当前 delete_project 为逻辑删除(status→deleted),无物理删除。discover_projects 无孤儿清理。 -> 司马懿评审建议物理删除加恢复机制或 admin auth。 -> 本轮聚焦 classify outcome,Registry 清理后续单独实施。 +### 决策记录 + +- **delete_project 保持逻辑删除**(status→deleted,data 目录和 blackboard.db 保留) +- **不做物理删除**:项目数据有长期价值,保留可恢复 +- **归档方案**(TODO):定期将 deleted 项目的 data 移至 NAS 归档目录,从活跃存储清理 +- **批量管理 API**:暂不实施,当前项目数量少(15 个 active),手动管理可接受 +- **discover_projects 孤儿清理**:暂不实施,当前无孤儿问题 + +### 性能评估 + +逻辑删除不物理删对性能无影响: +- registry.db 多几十条 deleted 记录,SQLite 微秒级 +- ticker 只处理 active 项目,deleted 的不被遍历 +- API 查询已过滤 deleted 状态 ## 5. 并发控制一致性检查 @@ -241,17 +253,23 @@ stderr_preview 和 exit_signal 写 metadata 的方案暂缓,本轮不实施。 ## 6. 影响范围 +### 已实施 + | 文件 | 改动 | 风险 | |------|------|------| -| `src/daemon/spawner.py` | `_classify_outcome` 重写 + `_handle_exit` 增加 retry 分支 | 中 — 核心逻辑 | -| `src/daemon/spawner.py` | `_record_attempt` metadata 增强 | 低 — 只增加字段 | -| `src/daemon/spawner.py` | `_do_retry` cooldown 逻辑 | 低 — 在现有 retry 前加 sleep | -| `src/blackboard/registry.py` | delete_project 增强 + discover_projects 孤儿清理 | 低 — 边缘逻辑 | -| `src/api/admin_routes.py` | 新增批量清理 API | 低 — 新文件 | -| `src/api/project_routes.py` | delete_project 调用 registry 清理 | 低 | -| `config/default.yaml` | 无改动 | — | -| `docs/design/spawner-monitor-design.md` | A0 章节更新 | 无 | -| `tests/test_spawner.py` | 新增 A14-A17 + A3b + A7 retry 测试 | 无 | +| `src/daemon/spawner.py` | `_classify_outcome` A0→A14-A17 拆分 + A8/A10 改可恢复 | 中 — 核心逻辑 | +| `src/daemon/spawner.py` | `_handle_exit` should_retry 分支加 cooldown + A3b cooldown 30→60 + else 分支加 compact_interrupted | 中 | +| `scripts/gateway-watchdog.sh` | 独立 Gateway Watchdog v2(替代 Phase -1 TCP probe) | 低 — 新文件 | + +### 未实施(暂缓) + +| 文件 | 原计划改动 | 状态 | +|------|------|------| +| `src/daemon/spawner.py` | A7 compact_failed 改可恢复 | 暂缓 | +| `src/daemon/spawner.py` | stderr_preview / exit_signal 写 metadata | 暂缓 | +| `src/blackboard/registry.py` | delete_project 增强 + discover 孤儿清理 | 不做(逻辑删除+归档) | +| `src/api/admin_routes.py` | 批量清理 API | 不做 | +| `tests/test_spawner.py` | 单元测试 | 暂缓 | ## 7. 测试计划