fix: nudge 推荐侧与 compress 执行侧统一字符计数(#359) - #360
Conversation
…359) buildCompressibleRanges sized non-text parts with JSON.stringify(whole part)/4, systematically overstating tool-heavy ranges (~10-40%) vs the pipeline's countMessageCharacters. Sub-floor ranges passed the recommendation floor but were rejected by the min-size check (Range too small), inviting guaranteed- failed retry loops (#37 ses_7fb5cbc8; #355 incident v1.14.26: 2760 chars vs min 3000). Both branches now use Math.round(countMessageCharacters(msg) / 4); per-part loops retained for classification only. Residual divergence is per-message rounding (<=0.5 tokens/msg), asserted as a band in the regression suite. Tests: tests/recommend-exec-counter-alignment.test.ts (7 new; verified to fail 5/7 against pre-fix code per AGENTS.md 5.7.3). Full suite 1069/1069.
📦 Built Plugin ArtifactBranch: Option A — Install from npm PR tag (recommended)opencode plugin opencode-acp@pr-360 --globalEach push to this PR publishes a new version under the Option B — Install from GitHubopencode plugin "github:ranxianglei/opencode-acp#2026-09-03_recommend-exec-counter-alignment" --globalOption C — Download artifact
tar xzf opencode-acp-pr360.tgz
cp -r package/dist ~/.cache/opencode/packages/opencode-acp@latest/node_modules/opencode-acp/dist
This comment is automatically updated on each push. |
- wrap merged token-utils import to satisfy printWidth (no new prettier violations) - add compacted-tool-output fixture pinning the placeholder path (review M3) - document incident-fixture triple constraint + safe edit window (review M2) - reword exec-side comment to its actual scope (review N2)
[bot] 🏷 PR #360 审核进行中 — 初审结论与证据如下,第二路代码审核完成后补最终 verdict。 1. 重复判定:非重复 ✅
2. Triage 三步结论① 复现/查证 — 根因代码级证实。 我逐行读了两侧:
3. 本地独立验证(pr-360 @ f3b13e6)
4. 双 agent 审核(§5.3 + §5.6)Reviewer 1(测试审核):APPROVE-WITH-NITS 🟢
Reviewer 2(代码审核):运行中 —— 重点核查 reasoning/file/pending-tool/compacted 边界、 5. 其他发现(NIT)
当前状态:除第二路审核外全部通过,倾向 approve(human merge)。 终审结论稍后补充。 |
[bot] 🏷 终审:APPROVE ✅(双 agent 均 APPROVE-WITH-NITS,零 blocker / 零 major;CI 全绿)。以下为第二路代码审核结论 + 汇总。 Reviewer 2(代码审核)要点
汇总 nit 清单(均不阻塞,可合并后跟进)
最终判定
PR 可合并:#360 —— 按 AGENTS.md §5.1.1.2,merge 为 human-only 操作,请 owner 自行点击 Merge。nit #1/#2 若希望合并前处理,我可以补一个 follow-up commit(说一声即可)。 |
|
const tokens = Math.round(countMessageCharacters(msg) / 4) 这是写死的吗 |
[bot] 🏷 是写死的字面量,但不是本 PR 引入的 —— 它是全项目既有的 chars→tokens 启发式约定,本 PR 只统一了「字符怎么数」,没动「除以几」: 1.
2. 为什么不用真 tokenizer 3. 已知的精度取舍(既有,非本 PR) 4. 如果想收敛这个魔数,三个选项(都不属于本 PR 范围,可另开 issue):
需要的话我可以起一个 (a) 的小 follow-up issue/PR。 |
Issue
#359(来源 #355 长会话缝隙分析;与 #37 同族)
根因(已代码级证实)
buildCompressibleRanges(lib/messages/inject/utils.ts):非 text part 用JSON.stringify(整个 part).length / 4—— 含type/tool/callID/state.status包装字段 + JSON 转义开销(内容里每个\n、"多花 1 char)→ tool 消息系统性高估约 10–40%lib/compress/range.ts:180-201:soft filter 后求和countMessageCharacters(lib/token-utils.ts:224-237)= text 长度 + input + output/error 正文长度Range too small)→ 注定失败的重试循环(chore: bump version to 1.6.0 #37 ses_7fb5cbc8 ×10;长会话范围压缩产生'缝隙残留'孤儿消息,建议孤儿回收/碎片整理机制 #355 v1.14.26 实测 2760 chars vs min 3000,作者全程 nudge-driven)修复
buildCompressibleRanges两个分支(compressible + protected)统一改用Math.round(countMessageCharacters(msg) / 4)—— 零 tokenizer 成本,推荐门槛 ≡ 执行侧接受谓词。残留差异仅 per-message 四舍五入 ±0.5 tokens/msg(≤2 chars/msg),比修复前偏差小 2–3 个数量级,测试中以 rounding band 钉住。per-part 循环仅保留分类职责(isTool/toolPct/hasMeaningfulPart/protected tool 名收集);分组、soft-filter 镜像、zone sizing、所有 display-only counter 均未动(devlog REQ non-goals)。测试
新增
tests/recommend-exec-counter-alignment.test.ts(7 例):issue 点名的 4 类 fixture(纯文本 / 正常完成 tool / error 态含堆栈 / 深嵌套 JSON 输出)+ #355 事故形态 gate 等价性复现(exec 2866 < 3000;pre-fix 膨胀估计 780 ≥ floor 750 → 修复后 DROPPED;反事实 legacy 估计 KEPT——两侧都钉住)+ protected 分支同 counter 验证。.prettierrc归一化 diff 验证本 PR 零新增 drift,故不顺手重排整个文件)Devlog
devlog/2026-09-03_recommend-exec-counter-alignment/{REQ.md,WORKLOG.md}