循环检测(CycleDetector)

wesgine 的 CycleDetector 是唯一的引擎内终止来源——检测可证明的死循环,不是"跑太久了"。


终止哲学

引擎不因 counter 阈值(轮次/token/时间)主动终止正常运行的任务(INV-TERM-01)。

CycleDetector 检测的是:


工具分类

分类说明streak 行为
exploration只读工具(read/grep/search)高阈值,参数变化 halving
action写入工具(edit/write/exec)中阈值,参数变化 halving
planPlan 工具探索预算 + 进度减半

分类优先级(四级 fallback)

  1. 硬编码 map(~20 个内置工具)
  2. ExtraCategories(消费方声明)
  3. ToolMeta 自动推断(ReadOnly=true → exploration)
  4. 默认:categoryAction

阈值配置

CycleDetectConfig{
    ExplorationWarnThreshold:    50,
    ExplorationTermThreshold:    100,
    ActionWarnThreshold:         25,
    ActionTermThreshold:         50,
    IdenticalCallWarnThreshold:  4,
    IdenticalCallTermThreshold:  7,
    ToolOverrides: map[string][2]int{
        "exec":       {30, 60},
        "exec:readonly": {50, 100},
        "edit":       {30, 60},
        "write":      {30, 60},
        "apply_patch": {30, 60},
        "plan":       {15, 30},
    },
}

两阶段终止协议

阶段触发行为
自愈首次 CycleTerm注入 system 纠正消息 + 重置 counter
HITL第二次 CycleTerm问用户"怎么办",超时 60s 自动终止

Progress-Aware 工具

当工具参数变化时 streak 计数 /= 2(halving)。

这区分了:


ErrorStreak 伪进展检测

ErrorStreakDetector 检测连续错误——表面上有进展(调用不同工具/不同参数),但每次都失败。


扩展机制

CycleDetectConfig{
    ExtraCategories: map[string]wesgine.ToolCategoryHint{
        "my_readonly_tool": wesgine.CategoryExploration,
    },
    ExtraProgressAware: []string{"my_mutation_tool"},
}

与 Plan 的关系


反模式

禁止正确做法
用 counter 阈值终止正常 RunCycleDetector 是唯一终止源
Plan 归为 action 类exploration 类
相同参数连续调用不检测IdenticalCallTerm 检测
无限自愈重试两阶段:自愈一次,HITL 一次