You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
误导性消息来自下游:swap 之后该 range 分类为 "ok" 进入 applyCompression 的 gate;当批次里所有 range 都无效(countedRanges=0)时,gateMessage 三元式落到最后一个分支,产出 Total compressible content too small (0 chars across 0 range(s)...)——一个凭空捏造的内容结论,与真实的 per-range 错误并列出现。这就是模型收到「内容不够」的直接来源。
startId="m01101" resolves after endId="m01100" — the refs appear reversed: swap startId and endId. Normalized range m01100..m01101 contains 1734 chars.
当批次里 零个 range 被计入(全部分类失败,如全反向)时,gate 跳过 Total compressible content too small (0 chars across 0 range(s)) 这个凭空结论,只返回 per-range 错误。混合批次行为不变:合法小 range 仍报 "too small",反向 range 的错误并列出现(有测试覆盖)。consumed/unknown 两个既有分支未动。
Activity
ranxianglei commentedon Sep 16, 2026
[bot] 🏷 已按 Triage 流程审核完毕(复现/查证 → 层次定位 → 方案评估),确认成立,修复进行中。
查证结果
src/boundaries.ts:114-116,resolveBoundaries内if (startIndex > endIndex) { [startIndex, endIndex] = [endIndex, startIndex]; }。已对照已发布的 npm 0.0.74 dist(index.js:494-495)逐字核实,一致。index.js:1853实际是adjustBoundariesForReasoningPairs(src/reasoning-pairs.ts:35)——那是防御性守卫(if (startIndex > endIndex) return { startIndex, endIndex };),原样返回、不做任何交换,不是静默纠正。applyCompression的 gate;当批次里所有 range 都无效(countedRanges=0)时,gateMessage 三元式落到最后一个分支,产出Total compressible content too small (0 chars across 0 range(s)...)——一个凭空捏造的内容结论,与真实的 per-range 错误并列出现。这就是模型收到「内容不够」的直接来源。层次判断
静默 swap 是根因(参数错误被伪装成合法 range),gate 消息只是放大器。只改 gate 不解决 swap 吞掉参数错误的问题;只去掉 swap、不改 gate,模型仍会看到误导性的 "too small"。两处都要动:
resolveBoundaries检测到startIndex > endIndex时抛新的BoundaryReversedError,不再交换。消息一次给两个事实:方向写反了 + 规范化后区间的真实字符数(模型下一轮即可改对引用顺序)。countedRanges === 0(没有任何 range 被计入)时不再输出 "too small" 结论,只返回 per-range 错误。行为变化说明(有意为之)
之前大的反向区间(规范化跨度超过 minCompressRange)会被静默交换后成功压缩;修复后一律返回反向错误——参数错误必须显性化,不能被内核吸收。若有任何 host 侧代码主动构造反向引用需同步修正(已知唯一生产方是 LLM 自己,见 #847)。
实现中,PR 开好即更新本 issue。
ranxianglei commentedon Sep 16, 2026
[bot] 🏷 修复完成,PR 已开:**https://github.com/ranxianglei/acp-kernel/pull/314**(分支
2026-09-16_reversed-boundary-error,commite7550a2,基于 origin/master5d54c31)。Closes #310。实现(按 triage 方案落地,4 文件 +195/−14)
1.
src/boundaries.ts— 去掉静默交换,抛显式错误新增导出的
BoundaryReversedError(code = "BOUNDARY_REVERSED",携带原始 refs + 规范化字符数),resolveBoundaries检测到startIndex > endIndex时抛出,消息一次给两个事实:规范化字符数按 gate 同款口径统计(区间内非 summary 消息的
text.length之和)。host 侧可像BoundaryNotFoundError一样精确 catch。2.
src/compress.ts— gate 不再捏造 "too small"当批次里 零个 range 被计入(全部分类失败,如全反向)时,gate 跳过
Total compressible content too small (0 chars across 0 range(s))这个凭空结论,只返回 per-range 错误。混合批次行为不变:合法小 range 仍报 "too small",反向 range 的错误并列出现(有测试覆盖)。consumed/unknown 两个既有分支未动。测试
删掉了把 bug 当特性固化的旧测试
applyCompression auto-swaps reversed boundaries,换成 4 个:resolveBoundaries单测:错误类型/code/refs/规范化字符数/消息形状Pre-flight
npm run typecheck— cleannpm test— 792/792 passnpm run build— success;并核实构建产物 dist 中错误类已就位、swap 模式([startIndex, endIndex] = [endIndex, startIndex])已不存在行为变化(有意为之,已在 PR 描述展开)
src/recommend.ts:169-175注释),唯一生产方是 LLM 自己。rebuildCompressionState重放历史 LLM compress 调用:历史上写反的调用在 fork 恢复时不再产出 block——安全降级(那些消息保持可见/可压缩),而不是替模型圆一个它没真正请求过的顺序。中文摘要:静默交换改为抛
BoundaryReversedError(方向错 + 规范化真实大小一条消息说清),gate 在全批次无效时不再捏造 "too small";typecheck/792 测试/build 全绿,PR #314 待合并。ranxianglei commentedon Sep 16, 2026
这个是不是不应该错误,静默交换并不损失什么
ranxianglei commentedon Sep 16, 2026
方向调整(owner 在 billion-context#847 裁定):静默交换保留,不引入 BoundaryReversedError。
理由:反向引用对没有歧义——恰好只有一种合理解读(该区间),意图明确、零数据风险;硬报错会把本可原地恢复的情况变成强制重发(多耗一轮,且正是 #847 要消灭的重试循环模式)。真正的缺陷不在交换本身,而在下游消息对交换零交代:模型不知道自己提交的输入被改写过,于是继续在「内容不够」的错误前提上推理。
调整后的方案:
note: refs were given reversed (mXXXXX→mYYYYY), normalized to mYYYYY..mXXXXX(无 API 变更);notes?: string[](加法式、向后兼容),同样内容,供 proxy mode host 与 plugin mode 扩展各自渲染进 tool result。billion-context host 侧(billion-context#849)已按「提示而非报错」实现,与本方向一致。
ranxianglei commentedon Sep 16, 2026
[bot] 🏷 已按裁定重做:保留静默交换,用透明化替代报错。PR #314 分支已更新(commit
7e30477),PR 描述同步改写。逐条落实
src/boundaries.ts的 swap 原样保留,不引入BoundaryReversedError(上一版已删净,dist 验证无残留)gateMessage末尾追加note: refs were given reversed (mXXXXX→mYYYYY), normalized to mYYYYY..mXXXXX,无 API 变更。一次告诉模型两件事:尺寸不足 + 引用被改写ApplyCompressionResult.result新增可选notes?: string[](加法式;host 渲染进 tool result 即覆盖 proxy/plugin 两种模式)range foo..bar: Invalid boundary ref(s): ...),不再出现too small (0 chars across 0 range(s))这类误导性判词实现时的几个边界决定(均已写进测试)
...(notes.length > 0 ? { notes } : {}))——对现有消费者零可见变化。too small (N chars ...)),单范围场景下 N 就是该范围规范化后的大小,重复会冗余。一个诚实的备注
#847 里的 m01101/m01100 是相邻引用——规范化后区间完全相同,反转在那里只是外观问题,"too small" 判词本身是对的。真正的循环燃料是「sub-min 跨度 + 零交代」的组合:模型不知道输入被改写过,就在错误前提上反复挣扎。本修复保证 plugin mode 下模型每轮都能看到改写事实;host 侧提示(billion-context#849)仍是打断重试循环的主力,kernel 这条是补上 plugin mode 的盲区。
验证
npm run typecheck干净;npm test793/793(重写 4 个旧测试、新增 1 个 all-invalid guard);npm run build干净BOUNDARY_REVERSED无残留PR: https://github.com/ranxianglei/acp-kernel/pull/314(等你合并)
中文摘要:按 billion-context#847 裁定把「硬报错」方案改为「保留交换+透明化」——反向引用不再报错,而是通过 gate 消息追加说明和新增可选
result.notes告知模型其输入被规范化过,同时修掉了全失败批次被捏造成 "too small" 的误导判词;typecheck/793 测试/build 全绿,可以合并。ranxianglei commentedon Sep 17, 2026
继续