feat(plan): 计划完成门 — 拦截未完成 plan 的提前 end_turn - #18
Closed
1-ztc wants to merge 6 commits into
Closed
Conversation
Replace the process-wide singleton in plan-tools.ts with a sessionKey-routed store. Multi-session embedded hosts no longer cross-read each other's active plan. store maintains sessionKey->activePlanId; controller business logic unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
…d steps evaluatePlanCompletionGate checks plan step completeness (not just whether plan tools were called this turn like evaluatePlanEvalCompletionGate). Wired into the CLI completion-gate chain and the MossAgent completionGate wrapper. Escape hatch via plan_step skip with reason; fail-open on any fault. Co-Authored-By: Claude <noreply@anthropic.com>
Add MOSS_PLAN_GATE (default on) so the plan completion gate can be disabled (MOSS_PLAN_GATE=off) to take an A/B baseline against the same task set. Mirrors criticEnabled() in plan-critic.ts but defaults the opposite way (critic is experimental off, gate is shipped on). Verified end-to-end: default ON rejects premature end_turn with correction; OFF is a true no-op (no correction). 9 unit cases + integration test pass; typecheck clean. Co-Authored-By: Claude <noreply@anthropic.com>
Drives a real MossAgent loop end-to-end with a mock LLM provider: turn1 create -> turn2 approve+start -> turn3 plain end_turn (premature, 0/2 steps) -> gate rejects + injects correction -> turn4 skip step1 -> turn5 skip step2 -> turn6 end_turn passes. Closes the final-review M4 gap (spec-promised integration test was missing). Verified the gate only fires on end_turn with no pending tool_use, and that skipStep is sequential. Co-Authored-By: Claude <noreply@anthropic.com>
Same slack-off mock (5-step plan, completes 1, then premature end_turn): MOSS_PLAN_GATE=off -> premature end_turn passes, no correction. Default on -> rejected + correction injected. Verifies mechanism direction with a mock provider — NOT real-world gain (a mock is not a model that decides whether to slack off). Real gain needs a real model + controlled task set + N>=3. Co-Authored-By: Claude <noreply@anthropic.com>
…imits) Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
做了什么
给 moss 主循环加计划完成门:模型
end_turn时若该 session 有 approved/executing 状态的 plan 且 steps 未全做完(completed+skipped)→ 否决完成、注入 correction 逼模型继续,逃生口是plan_step skip带理由。堵长任务最典型失败——"有 plan 没做完就声称 done"。起点是「moss 主循环是否需要独立 Planner 规划校验层」——分析后确定性收益在「完成时强制 plan 执行完整」,不在「执行前校验质量」。本分支只做前者;critic 实验在独立分支
feature/plan-completion-gate,不带入。改动(5 commit)
40d3a36) — 把plan-tools.ts进程级单例换成按sessionKey路由的 store(plan-controller-store.ts)。多 session 嵌入式 host 不再串读对方 active plan。完成门的前提。PlanExecuteController业务逻辑不动。99507a8) —evaluatePlanCompletionGate(request, deps),接进 CLIcreateCliCompletionGate链(排evaluatePlanEvalCompletionGate后)+ MossAgentcompletionGate包装(无 structured-pending 分支)。fail-open 5 路径;类型干净(required→optional 子类型,无适配)。48de1f0) — default on。=off可关做 A/B baseline。端到端验证:ON 拦+注入 correction,OFF 彻底 no-op。0a2e0b2) — 真起 MossAgent loop:create→approve+start→提前 end_turn→被否决→skip 两步→放行。5947bc0) — 同一偷懒 mock:off 放行无 correction、on 拦住注入 correction。证明机制方向(非真实收益)。测试
6 个相关 spec 全过(plan-controller-store / plan-completion-gate 9 case / -integ / -ab / plan-tools-nudge / interaction-mode-exit)。build + typecheck 干净。
已知限制(诚实)
MOSS_PLAN_GATEflag 留作后续真 A/B。throw Completion rejected崩 run(平台既有 exhaustion 行为,非 force-complete,文档已对齐)。ctx.sessionKey空时走 shared 兜底,setActivePlanId不记,gate 查不到 → fail-open 放行。CLI 总有 sessionKey,影响主要在无 sessionKey 的嵌入 host。🤖 Generated with Claude Code