auto-sync: 2026-06-03 00:42:29
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
# #06 PM2 Crash 恢复设计
|
||||
|
||||
> 版本: v1.1
|
||||
> 日期: 2026-06-01
|
||||
> 版本: v1.2
|
||||
> 日期: 2026-06-03
|
||||
> 作者: 庞统(副军师)
|
||||
> 状态: 二次评审中
|
||||
> 状态: 待评审(v1.2)
|
||||
> 前置: spawner-monitor-design.md §5 A0(Agent crash 恢复)
|
||||
> 变更: v1.1 纳入司马懿评审意见(Blocking #1 reviewing 状态 + Blocking #3 虚拟项目 + 建议 #2 审计事件)
|
||||
> 变更: v1.2 两个关键改进:(1) working→pending 保留 current_agent 让同一 agent 接手;(2) reviewing 精确恢复到前置状态而非硬推 done
|
||||
|
||||
---
|
||||
|
||||
@@ -127,15 +127,19 @@ PM2 启动 moziplus v2
|
||||
|
||||
```
|
||||
working + last_attempt.completed?
|
||||
├─ No → pending
|
||||
├─ No → pending(保留 current_agent)
|
||||
└─ Yes + has_output?
|
||||
├─ No → pending
|
||||
├─ No → pending(保留 current_agent)
|
||||
└─ Yes + has_handoff?
|
||||
├─ No → pending(可能标了 working 就 timeout 退出了,产出残留)
|
||||
├─ No → pending(保留 current_agent)
|
||||
└─ Yes → review(agent 已完成工作并交接)
|
||||
```
|
||||
|
||||
**注意**:`pending` 推回后 assignee 被清空,ticker 自然重新 broadcast 或 dispatch。如果原来有 assignee,agent 会看到之前的 outputs 和 comments(黑板数据不丢失),可以选择继续或重新认领。
|
||||
**保留 current_agent 原则**:推回 pending 时不清空 `current_agent`,让同一 agent 重新接手。原因:
|
||||
1. 该 agent 之前有对话上下文(现已丢失),但黑板上的 outputs/comments 是它写的,它最了解上下文
|
||||
2. Dispatcher 路由时如果 current_agent 仍在,直接复用,省去重新路由
|
||||
3. Agent 被 bootstrap 注入完整任务上下文(含之前的产出),自行决定继续还是重来
|
||||
4. 这是冗余操作,但保证状态一致
|
||||
|
||||
#### review 状态
|
||||
|
||||
@@ -168,13 +172,20 @@ working + last_attempt.completed?
|
||||
|
||||
**含义**:parent task 进入庞统 round review 的中间状态(`done/failed → reviewing`)。
|
||||
|
||||
**恢复逻辑**:推回 `working`,让 ticker 重新触发 `_check_round_complete`。
|
||||
**恢复逻辑**:查 events 表找到转入 reviewing 之前的状态(done 或 failed),精确推回该状态。
|
||||
|
||||
**原因**:reviewing 状态依赖 `_spawn_pangtong_review` 的回调 `_handle_review_conclusion` 来推进。PM2 crash 后回调丢失,`_handle_review_conclusion` 永不触发,parent 永久卡死。推回 working 后,下个 tick 的 `_check_round_complete` 检查 sub task 全部终态 + parent 状态非 done/failed → 跳过。但 `_check_round_complete` 只在 `parent_status in (done, failed)` 时触发,所以需要推回 working 后手动触发一次,或者直接推回 done(让 `_check_round_complete` 自然重新触发 review spawn)。
|
||||
**决策树**:
|
||||
|
||||
**最终策略**:推回 `done`(恢复到 reviewing 之前的状态),`_check_round_complete` 会自然重新触发庞统 review。
|
||||
```
|
||||
reviewing → 查 events 表最后一条 task_status_changed 到 reviewing 的记录
|
||||
├─ 找到前置状态 done → 推回 done
|
||||
├─ 找到前置状态 failed → 推回 failed
|
||||
└─ 找不到 → 兜底推 done(done/failed→reviewing 是唯一合法路径,大概率是 done)
|
||||
```
|
||||
|
||||
> 注:reviewing 状态是从 done/failed 转入的(`_set_parent_reviewing`),所以推回 done 是合法的(reviewing → done 在 VALID_TRANSITIONS 中)。但更安全的做法是查 events 表看 reviewing 之前是什么状态。简化起见直接推 done。
|
||||
**原因**:reviewing 状态依赖 `_spawn_pangtong_review` 的回调 `_handle_review_conclusion` 来推进。PM2 crash 后回调丢失,`_handle_review_conclusion` 永不触发,parent 永久卡死。推回 done/failed 后,`_check_round_complete` 会在下个 tick 自然重新触发庞统 review spawn。
|
||||
|
||||
**精确恢复优于硬推 done**:因为 parent 可能是从 failed 转入 reviewing 的(子任务失败触发 round review),推回 done 语义错误。查 events 表是确定性操作,成本可忽略(单条 SQL)。
|
||||
|
||||
#### escalated / waiting_human / paused 状态
|
||||
|
||||
|
||||
Reference in New Issue
Block a user