goal 续行缺少"无进展"与"等待中"判断:0.1.6-alpha.2 仍复现 #7198
Replies: 3 comments
|
Both scheduler rules you're asking for are reachable today from outside What I verified in the 0.1.6-alpha.2 sources, so the mapping is exact rather than inferred:
One correction that matters. Suggestion #1 says "block 或提示用户". Those are two different harness operations, and the choice is not cosmetic:
Your #4664 evidence (the invented "~15/20/25 min in") and #1831's 160 near-identical rounds are stalls in a live loop, not a verdict that the goal is unreachable. That is precisely what Claude Code's "stops the loop, prints a warning, and returns control to you with the goal still set" describes — pause plus a durable notice, not block. Three implementation facts I would want if I were writing this, none of which are in the report:
On "did this round do anything", you don't need driver internals either. Where that leaves the thread: suggestions 1 and 2 are a policy question, and the policy is mountable today; the remaining core question is whether the driver should own it by default. Both can be true, and the second can be decided on the first one's evidence — which is cheaper than landing it sight-unseen. Adjacent note, since it is the same loop seen from the other end: I packaged the spend dimension as |
|
As promised above, the two rules are packaged: - insert:
- id: goal-progress-guard
name: '@argszero/cordis-plugin-goal-progress-guard'
config:
deferWhileJobsPending: true # default: pause while jobs run, resume when they settle
maxBarrenRounds: 3 # stop after N consecutive rounds with no tool call
dryRun: false # true logs the deferral or stop it would writeSuggestion #2, as implemented. At every quiescent edge, if the agent still owns an unsettled job ( The jobs service is injected with Suggestion #1, as implemented. The ordering caveat from my earlier comment is now load-bearing in the code, not just an observation: the plugin registers its Boundaries, stated up front:
Verification. 30 tests: the pure policy functions exhaustively (the streak arithmetic, both gates, the resume decision) plus the guard driven through a real cordis Where this leaves your report. The suggestion-1/2 policy is deployable today, per-deployment, with no core change; the open core question is whether the driver should own it by default. Both can be true, and the second can now be decided on this one's evidence rather than sight-unseen — which I think is the cheaper order. Your third point (an independent evaluator) stays orthogonal, as you argued. One note for anyone reading this thread from the spend side: the sibling |
|
Thanks @argszero — the mapping is clear and I can follow it against the 0.1.6-alpha.2 sources. Two things I take from this:
I confirmed the packaged plugin exists ( |
Uh oh!
There was an error while loading. Please reload this page.
背景
本问题在 #1831 与 #4664 已有讨论。本帖补充三项前两帖没有的内容:0.1.6-alpha.2 的复现状态、源码级根因定位,以及另外两个框架在同一问题上的公开做法与原文——其中一家的做法表明,缓解空转并不需要引入独立模型。
环境
0.1.6-alpha.2(dsh --version实测)0.1.6-alpha.2:@deepseek-ai/dsh-goal、@deepseek-ai/dsh-goal-round-driver、@deepseek-ai/dsh-tool-goalprofiles/web/cordis.patch.yml中无 goal 条目,defaultMaxGoalRounds未被覆盖)现象
goal 处于 active 且续行已启用时,agent 无法停留在 idle 等待一件事完成:
<goal_round>,无法被动等待roundsStarted逐轮递增,上限 256,每轮重发完整会话历史与目标块源码定位
1.
idle是无条件的续行触发点dsh-goal-round-driver/lib/index.js:213-229:该分支只处理「目标已被暂停/取消」。
requestDrive之后进入drive(),其中与 goal 状态相关的唯一停止条件是轮数上限(:125-131):驱动器内不存在「本回合是否产生了实际推进」或「agent 是否在等某件已经发起的事」的判断。
idle只表示「当前没有回合在跑」,一个刚按工具文档建议结束回合、等待后台通知的 agent,与一个真正做完了的 agent,在这个信号上完全一致。2. 驱动器没有 jobs 视野
dsh-goal-round-driver/package.json的peerDependencies为dsh-goal、dsh-llm、dsh-session、cordis、dsh-invariants、dsh-agent,源码中不出现 jobs。而JobsService提供同步的list(caller?: Agent): JobSnapshot[],按 agent 归属返回作业快照。3. 全部 block 代码只有三个
round-limit(:127)、queue-failed(:160)、prompt-rejected(:318)。没有对应「无进展」的稳定代码。4. 空转未被计入异常
driver README 说明它会在轮次因 max tokens 结束、持久化写入失败、agent 被取消、插件卸载时自行停止。这些都是异常路径,「模型连续多轮没有实际推进」不在其中。
与包自述的关系
dsh-goal/README.zh.md与dsh-goal-round-driver/README.zh.md的「已知限制」都写明「没有独立评估器」,开发备注把「评估器支持的完成与阻塞认证」列为开放方向。本帖想指出的是:防住空转与"独立评估器"是两件可分离的事。
其他框架的公开做法
Claude Code
/goal官方文档:https://code.claude.com/docs/en/goal
Not yet met/Met/Impossible;原文为completion is decided by a fresh model rather than the one doing the workIf Claude keeps answering the evaluator without making progress (no tool use for several turns in a row), Claude Code stops the loop, prints a warning, and returns control to you with the goal still set.If a subagent or a background shell command is still running when a turn ends, Claude Code skips the evaluation for that turn.Codex Goal
官方 cookbook:https://developers.openai.com/cookbook/examples/codex/using_goals_in_codex
the evidence decides whether it is done)If a continuation turn makes no tool call, the next automatic continuation is suppressed so Codex does not spin.Codex does not continue while another turn is active, while user input is queued, or while other thread work is pending.关键对照:Codex 表明,显著缓解空转不需要额外模型——一条「本续行回合无工具调用则抑制下一次」的调度规则即可,成本接近零。
建议
按成本从低到高:
drive()中加入无进展抑制:记录最近一个已准入 round 是否产生过工具调用,连续 N 轮(可配置,默认 1–2)无工具调用则不再排入下一轮,并以稳定代码(如no-progress)block 或提示用户。此条不引入新依赖,不产生模型调用。ctx.inject(['jobs'], …),官方llm-pi-ai即此模式)在 idle 检查点查询ctx.jobs.list(agent),仍有未结算作业时推迟续行。组合中没有 jobs 服务时行为与现状一致,不产生硬依赖。同一判断后续可扩展到等待审批、等待子代理。一个值得单独记录的副作用
被强制发言而无话可说时,模型会编造时间感。#4664 记录到 agent 在没有任何新信息的情况下自称
~15/20/25 min in。这些句子进入会话历史后会被后续回合当作事实读取。这比roundsStarted递增本身更值得注意。本报告由用户在实际使用中遇到问题后,基于本地安装的
0.1.6-alpha.2源码核查与上述官方文档整理。All reactions