Plan 状态枚举与迁移
wesgine 使用 PlanStatus 枚举替代双 bool(Completed + Interrupted),消除非法状态组合。
状态枚举
| 状态 | 含义 |
|---|---|
planning | 初始态,计划正在构建 |
active | 计划已创建,步骤执行中 |
completed | 模型声明完成 |
terminated | 异常终止 |
迁移函数
ApplyCompletion
模型调用 plan(action=complete) 时触发:
planning → completed ✓
active → completed ✓
terminated → completed ✗ (非法)
completed → completed ✓ (幂等)
完成时收口剩余 open 步骤为 done。
ApplyTermination
Run 异常终止时触发:
planning → terminated ✓
active → terminated ✓
completed → terminated ✗ (非法,完成的计划不能被终止)
terminated → terminated ✓ (幂等)
携带 TerminationReason:
| Reason | 触发条件 |
|---|---|
run_interrupted | Run 被中断(用户/budget/cycle) |
nudge_exhausted | Plan-pending nudge 3 次耗尽 |
validation_failed | 验证失败 |
终态判定
IsTerminal() 返回 true:
completedterminated
终态的 Plan:
- 不注入系统提示词
- 不触发 nudge
- 不 pin 到上下文
终结收口点
三处收口,全部改调迁移函数:
| 位置 | 动作 |
|---|---|
control.go nudge 耗尽 | ApplyTermination(nudge_exhausted) |
loop.go runEnd | ApplyTermination(run_interrupted) |
builtin/plan.go planComplete | ApplyCompletion() |
持久化
Plan 状态通过 frontmatter 持久化到 artifact:
---
status: active
termination_reason: ""
termination_detail: ""
---
# Plan: 重构数据库
## Steps
...
旧格式兼容
PlanStatusFromArtifact 是全函数:
- 域外值(含旧
interrupted)一律读回planning - 按 DEV-1 旧产物读回
planning是预期行为 - 权威源是 TaskStore,产物重写即恢复
水合语义
Store 保留 terminated(resume-then-complete 合法):
terminated→completed是合法 resume 迁移completed→terminated非法(迁移表拒绝)
仅 completed 排除再进入。
事件映射
| 迁移 | 事件 |
|---|---|
→ completed | EventPlanComplete |
→ terminated | EventPlanInterrupted |
| nudge 耗尽 | EventPlanNudge(提醒非错误) |
事件名与载荷未变,前端零改动。
步骤状态
| 步骤状态 | 含义 |
|---|---|
pending | 等待执行 |
in_progress | 执行中 |
done | 已完成 |
skipped | 已跳过 |
完成收口
ApplyCompletion 时将所有 open(pending + in_progress)步骤收口为 done。
实质化(INV-PE-15)
步骤标记 done 需要"工作发生过":
- session ledger 记录
PlanStep.Substantiated ∪ PlanWorkThisTurn - 引擎在 execute 阶段给所有 open 步骤盖章
- 记账可以是下一轮
相关文档
- Plan 系统 →
plan-system.md - Plan 实质化 →
plan-substantiation.md - Run 生命周期 →
run-lifecycle.md - Nudge 机制 →
run-nudge.md