Skip to content

nudge推荐侧与compress执行侧字符计数不一致,tool-heavy range被推荐后遭min检查拒绝(#355分析发现) #359

Description

@ranxianglei

来源: #355 (#355) 分析长会话缝隙残留时发现

现象

nudge 推荐列表列出的 range,agent 按推荐调用 compress 时被执行侧 min 检查拒绝:

  • 实测(长会话范围压缩产生'缝隙残留'孤儿消息,建议孤儿回收/碎片整理机制 #355 作者会话,v1.14.26):range 含 m00001(用户文本)+ m00002(webfetch 失败 tool)+ m00003(gh issue view JSON 输出 tool)+ m00004(文本总结),tool part 占大头;nudge 侧通过 750-token floor,执行侧报 Range too small (2760 chars, min 3000)。作者全程 nudge-driven、未调用 acp_status——即 nudge 推荐本身不可信。
  • 同族历史:issue chore: bump version to 1.6.0 #37(ses_7fb5cbc8:显示 10.8K compressible → 管线解析 3066 chars → 拒绝 → 模型重试 ×10)。filterRecommendedRanges 的 doc comment(lib/messages/inject/utils.ts:933-935)记载了该事故与 ÷4 floor 对齐的初衷。

根因

两侧使用不同的字符计数函数:

位置 text part tool part
推荐侧 buildCompressibleRanges(lib/messages/inject/utils.ts:813-825) text.length / 4 JSON.stringify(整个 part).length / 4 —— 含 name/callID/state.status/metadata 字段 + JSON 包装开销
执行侧 countMessageCharacters(lib/token-utils.ts:224-237) text.length extractToolContent(lib/token-utils.ts:163-182)= input + output/error 内容长度

纯文本消息两侧一致;tool 消息推荐侧系统性高估约 10–40%(深度嵌套 JSON 输出、error 态 part 更高——error 正文两侧都计,多出的是 JSON 包装开销 ∝ 嵌套深度 + part 元字段)。floor = minCompressRange÷4(resolveEffectiveFloor,utils.ts:947-952),故 tool-heavy 的 sub-floor range 在推荐侧过门、执行侧被拒。

影响

  1. agent 做注定失败的压缩尝试(chore: bump version to 1.6.0 #37 型重试循环,浪费轮次/token);
  2. 失败后残留组继续卡死在压缩边界缝隙里——与 长会话范围压缩产生'缝隙残留'孤儿消息,建议孤儿回收/碎片整理机制 #355 孤儿问题叠加放大;
  3. nudge 是多数 agent 的第一引导面(不调 acp_status),此缺陷直接损害压缩引导可靠性。

修复建议

推荐侧统一改用 countMessageCharacters ÷ 4(纯字符串长度,零 tokenizer 成本),使推荐门槛 ≡ 执行侧接受谓词。补回归测试钉住两侧差额,fixtures:纯文本 / 正常完成 tool / error 态含堆栈 / 深度嵌套 JSON 输出。

参考:acp-kernel 已解决同族问题——CompressibleRange.chars 字段(src/types.ts:193-210,注释明确记载 tokens≠chars/4 时两侧失配的失效模式)+ mergeRangesToThreshold 用真实 chars 批处理(src/recommend.ts:307-339)+ 回归测试 tests/effective-gate-chars.test.ts。其架构(扁平 msg.text)使两侧天然一致;opencode-acp 需显式共享同一计数函数。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions